From 9f7898bade5dd2732e99c3d17f30c34709caa770 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 17 Feb 2025 17:17:25 +0100 Subject: [PATCH 1/3] tests: net: conn_mgr: Use valid LL address in tests Using L2 address of length 1 (invalid/unsupported one) confused IPv6 layer during LL address generation - since that length was not a valid one, the address was not initialized properly and a part of it was set semi-random. This could result for example in filling out the neighbor tables. Signed-off-by: Robert Lubos (cherry picked from commit 3089a5d116ab538a568c1617afccd481e274180a) --- tests/net/conn_mgr_conn/src/test_ifaces.c | 2 +- tests/net/conn_mgr_monitor/src/test_ifaces.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/net/conn_mgr_conn/src/test_ifaces.c b/tests/net/conn_mgr_conn/src/test_ifaces.c index 535eee07de80..bd21197160a5 100644 --- a/tests/net/conn_mgr_conn/src/test_ifaces.c +++ b/tests/net/conn_mgr_conn/src/test_ifaces.c @@ -16,7 +16,7 @@ static void test_iface_init(struct net_if *iface) { /* Fake link layer address is needed to silence assertions inside the net core */ - static uint8_t fake_lladdr[] = { 0x01 }; + static uint8_t fake_lladdr[] = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 }; net_if_set_link_addr(iface, fake_lladdr, sizeof(fake_lladdr), NET_LINK_DUMMY); diff --git a/tests/net/conn_mgr_monitor/src/test_ifaces.c b/tests/net/conn_mgr_monitor/src/test_ifaces.c index 1b7a5080ec1f..05eda78dfcf7 100644 --- a/tests/net/conn_mgr_monitor/src/test_ifaces.c +++ b/tests/net/conn_mgr_monitor/src/test_ifaces.c @@ -15,7 +15,7 @@ static void test_iface_init(struct net_if *iface) { /* Fake link layer address is needed to silence assertions inside the net core */ - static uint8_t fake_lladdr[] = { 0x01 }; + static uint8_t fake_lladdr[] = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 }; net_if_set_link_addr(iface, fake_lladdr, sizeof(fake_lladdr), NET_LINK_DUMMY); From 4230d58e449d3ad077ba330625b1b1867fcd8fd0 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 17 Feb 2025 17:32:52 +0100 Subject: [PATCH 2/3] net: if: Clear neighbor cache when removing IPv6 addr with active DAD DAD creates an entry in the neighbor cache for the queried (own) address. In case the address is removed from the interface while DAD is still incomplete, we need to remove the corresponding cache entry (just like in case of DAD timeout) to avoid stale entries in the cache. Signed-off-by: Robert Lubos (cherry picked from commit a09fd8e97fbeb7dfb28a50ebc2a165862eec263b) --- subsys/net/ip/net_if.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index f9f7f68b4142..b4ffff8a5f75 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -4932,8 +4932,13 @@ static void remove_ipv6_ifaddr(struct net_if *iface, #if defined(CONFIG_NET_IPV6_DAD) if (!net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) { k_mutex_lock(&lock, K_FOREVER); - sys_slist_find_and_remove(&active_dad_timers, - &ifaddr->dad_node); + if (sys_slist_find_and_remove(&active_dad_timers, + &ifaddr->dad_node)) { + /* Addreess with active DAD timer would still have + * stale entry in the neighbor cache. + */ + net_ipv6_nbr_rm(iface, &ifaddr->address.in6_addr); + } k_mutex_unlock(&lock); } #endif From 47ee608a9b50b4dea0f48d9164e89a48104b4514 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 17 Feb 2025 17:37:17 +0100 Subject: [PATCH 3/3] net: if: Setup DAD timer regardless of DAD query result In rare occasions when sending DAD NS packet fails, we should still setup the DAD timer, unless we implement some kind of more advanced retry mechanism. If we don't do that, the IPv6 address added to the interface will never be usable in such cases. Signed-off-by: Robert Lubos (cherry picked from commit 008a7ca2024cd0c28bcfd3f4e5a0ca91503341dc) --- subsys/net/ip/net_if.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index b4ffff8a5f75..d1b6f3a69c53 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -1295,21 +1295,25 @@ void net_if_ipv6_start_dad(struct net_if *iface, ifaddr->dad_count = 1U; - if (!net_ipv6_start_dad(iface, ifaddr)) { - ifaddr->dad_start = k_uptime_get_32(); - ifaddr->ifindex = net_if_get_by_iface(iface); - - k_mutex_lock(&lock, K_FOREVER); - sys_slist_find_and_remove(&active_dad_timers, - &ifaddr->dad_node); - sys_slist_append(&active_dad_timers, &ifaddr->dad_node); - k_mutex_unlock(&lock); - - /* FUTURE: use schedule, not reschedule. */ - if (!k_work_delayable_remaining_get(&dad_timer)) { - k_work_reschedule(&dad_timer, - K_MSEC(DAD_TIMEOUT)); - } + if (net_ipv6_start_dad(iface, ifaddr) != 0) { + NET_ERR("Interface %p failed to send DAD query for %s", + iface, + net_sprint_ipv6_addr(&ifaddr->address.in6_addr)); + } + + ifaddr->dad_start = k_uptime_get_32(); + ifaddr->ifindex = net_if_get_by_iface(iface); + + k_mutex_lock(&lock, K_FOREVER); + sys_slist_find_and_remove(&active_dad_timers, + &ifaddr->dad_node); + sys_slist_append(&active_dad_timers, &ifaddr->dad_node); + k_mutex_unlock(&lock); + + /* FUTURE: use schedule, not reschedule. */ + if (!k_work_delayable_remaining_get(&dad_timer)) { + k_work_reschedule(&dad_timer, + K_MSEC(DAD_TIMEOUT)); } } else { NET_DBG("Interface %p is down, starting DAD for %s later.",