Skip to content

Commit 6ac2818

Browse files
broglep-workcarlescufi
authored andcommitted
net: lwm2m: fix observation path list ordering
under certain conditions the current implementation did not maintain the desired sort order. Signed-off-by: Pascal Brogle <[email protected]>
1 parent 35bd427 commit 6ac2818

File tree

6 files changed

+639
-36
lines changed

6 files changed

+639
-36
lines changed

subsys/net/lib/lwm2m/lwm2m_observation.c

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,9 @@ int lwm2m_engine_add_path_to_list(sys_slist_t *lwm2m_path_list, sys_slist_t *lwm
14991499
new_entry->path = *path;
15001500
if (!sys_slist_is_empty(lwm2m_path_list)) {
15011501

1502-
/* Keep list Ordered by Object ID/ Object instance/ resource ID */
1502+
/* Keep list Ordered by Object ID / Object instance / resource ID /
1503+
* Resource Instance ID
1504+
*/
15031505
SYS_SLIST_FOR_EACH_CONTAINER(lwm2m_path_list, entry, node) {
15041506
if (entry->path.level == LWM2M_PATH_LEVEL_NONE ||
15051507
lwm2m_obj_path_equal(&entry->path, &new_entry->path)) {
@@ -1508,39 +1510,63 @@ int lwm2m_engine_add_path_to_list(sys_slist_t *lwm2m_path_list, sys_slist_t *lwm
15081510
return 0;
15091511
}
15101512

1511-
if (entry->path.obj_id > path->obj_id) {
1512-
/* New entry have smaller Object ID */
1513-
add_before_current = true;
1514-
} else if (entry->path.obj_id == path->obj_id &&
1515-
entry->path.level > path->level) {
1516-
add_before_current = true;
1517-
} else if (entry->path.obj_id == path->obj_id &&
1518-
entry->path.level == path->level) {
1519-
if (path->level >= LWM2M_PATH_LEVEL_OBJECT_INST &&
1520-
entry->path.obj_inst_id > path->obj_inst_id) {
1521-
/*
1522-
* New have same Object ID
1523-
* but smaller Object Instance ID
1524-
*/
1525-
add_before_current = true;
1526-
} else if (path->level >= LWM2M_PATH_LEVEL_RESOURCE &&
1527-
entry->path.obj_inst_id == path->obj_inst_id &&
1528-
entry->path.res_id > path->res_id) {
1529-
/*
1530-
* Object ID and Object Instance id same
1531-
* but Resource ID is smaller
1532-
*/
1533-
add_before_current = true;
1534-
} else if (path->level >= LWM2M_PATH_LEVEL_RESOURCE_INST &&
1535-
entry->path.obj_inst_id == path->obj_inst_id &&
1536-
entry->path.res_id == path->res_id &&
1537-
entry->path.res_inst_id > path->res_inst_id) {
1538-
/*
1539-
* Object ID, Object Instance id & Resource ID same
1540-
* but Resource instance ID is smaller
1541-
*/
1542-
add_before_current = true;
1543-
}
1513+
/*
1514+
* algorithm assumes that list is already properly sorted and that
1515+
* there are no duplicates. general idea:
1516+
* - if at any level up to new entry's path level, IDs below the level
1517+
* match and the ID of the new entry at that level is smaller,
1518+
* insert before.
1519+
* - if all IDs of the new entry match the existing entry, insert before.
1520+
* Because of sorting and no duplicates, the existing entry must have
1521+
* higher path level and come after the new entry.
1522+
*/
1523+
switch (new_entry->path.level) {
1524+
case LWM2M_PATH_LEVEL_OBJECT:
1525+
add_before_current = new_entry->path.obj_id <= entry->path.obj_id;
1526+
break;
1527+
1528+
case LWM2M_PATH_LEVEL_OBJECT_INST:
1529+
add_before_current =
1530+
(new_entry->path.obj_id < entry->path.obj_id) ||
1531+
1532+
(entry->path.level >= LWM2M_PATH_LEVEL_OBJECT_INST &&
1533+
entry->path.obj_id == new_entry->path.obj_id &&
1534+
new_entry->path.obj_inst_id <= entry->path.obj_inst_id);
1535+
break;
1536+
1537+
case LWM2M_PATH_LEVEL_RESOURCE:
1538+
add_before_current =
1539+
(new_entry->path.obj_id < entry->path.obj_id) ||
1540+
1541+
(entry->path.level >= LWM2M_PATH_LEVEL_OBJECT_INST &&
1542+
entry->path.obj_id == new_entry->path.obj_id &&
1543+
new_entry->path.obj_inst_id < entry->path.obj_inst_id) ||
1544+
1545+
(entry->path.level >= LWM2M_PATH_LEVEL_RESOURCE &&
1546+
entry->path.obj_id == new_entry->path.obj_id &&
1547+
entry->path.obj_inst_id == new_entry->path.obj_inst_id &&
1548+
new_entry->path.res_id <= entry->path.res_id);
1549+
break;
1550+
1551+
case LWM2M_PATH_LEVEL_RESOURCE_INST:
1552+
add_before_current =
1553+
(new_entry->path.obj_id < entry->path.obj_id) ||
1554+
1555+
(entry->path.level >= LWM2M_PATH_LEVEL_OBJECT_INST &&
1556+
entry->path.obj_id == new_entry->path.obj_id &&
1557+
new_entry->path.obj_inst_id < entry->path.obj_inst_id) ||
1558+
1559+
(entry->path.level >= LWM2M_PATH_LEVEL_RESOURCE &&
1560+
entry->path.obj_id == new_entry->path.obj_id &&
1561+
entry->path.obj_inst_id == new_entry->path.obj_inst_id &&
1562+
new_entry->path.res_id < entry->path.res_id) ||
1563+
1564+
(entry->path.level >= LWM2M_PATH_LEVEL_RESOURCE_INST &&
1565+
entry->path.obj_id == new_entry->path.obj_id &&
1566+
entry->path.obj_inst_id == new_entry->path.obj_inst_id &&
1567+
entry->path.res_id == new_entry->path.res_id &&
1568+
new_entry->path.res_inst_id <= entry->path.res_inst_id);
1569+
break;
15441570
}
15451571

15461572
if (add_before_current) {

subsys/net/lib/lwm2m/lwm2m_observation.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,29 @@ struct lwm2m_obj_path_list {
6161
void lwm2m_engine_path_list_init(sys_slist_t *lwm2m_path_list, sys_slist_t *lwm2m_free_list,
6262
struct lwm2m_obj_path_list path_object_buf[],
6363
uint8_t path_object_size);
64-
/* Add new Path to the list */
64+
/**
65+
* Add new path to the list while maintaining hierarchical sort order
66+
*
67+
* @param lwm2m_path_list sorted path list
68+
* @param lwm2m_free_list free list
69+
* @param path path to be added
70+
* @return 0 on success or a negative error code
71+
*/
6572
int lwm2m_engine_add_path_to_list(sys_slist_t *lwm2m_path_list, sys_slist_t *lwm2m_free_list,
6673
struct lwm2m_obj_path *path);
6774

6875
int lwm2m_get_path_reference_ptr(struct lwm2m_engine_obj *obj, struct lwm2m_obj_path *path,
6976
void **ref);
70-
/* Remove paths when parent already exist in the list. */
77+
78+
/**
79+
* Remove paths when parent already exists in the list
80+
*
81+
* @note Path list must be sorted
82+
* @see lwm2m_engine_add_path_to_list()
83+
*
84+
* @param lwm2m_path_list sorted path list
85+
* @param lwm2m_free_list free list
86+
*/
7187
void lwm2m_engine_clear_duplicate_path(sys_slist_t *lwm2m_path_list, sys_slist_t *lwm2m_free_list);
7288

7389
/* Resources */
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(lwm2m_engine)
7+
8+
target_include_directories(app PRIVATE
9+
${ZEPHYR_BASE}/subsys/net/lib/lwm2m
10+
)
11+
FILE(GLOB app_sources src/*.c)
12+
target_sources(app PRIVATE ${app_sources})

tests/net/lib/lwm2m/engine/prj.conf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CONFIG_NETWORKING=y
2+
CONFIG_NET_TEST=y
3+
CONFIG_ZTEST=y
4+
CONFIG_ZTEST_NEW_API=y
5+
6+
CONFIG_ENTROPY_GENERATOR=y
7+
CONFIG_TEST_RANDOM_GENERATOR=y
8+
CONFIG_NEWLIB_LIBC=y
9+
10+
CONFIG_LWM2M=y
11+
CONFIG_LWM2M_COAP_MAX_MSG_SIZE=512

0 commit comments

Comments
 (0)