From ed01468aa1b3116353424f29b2441dbc1d5e0713 Mon Sep 17 00:00:00 2001 From: Shrek Wang Date: Sat, 14 Sep 2024 11:10:39 +0800 Subject: [PATCH] net: Add onlink and forwarding check to IPv6-prepare Deadloop happens when CONFIG_NET_ROUTING and VLAN are enabled. In function net_ipv6_prepare_for_send(), pkt->iface will be updated with net_pkt_set_iface(pkt, iface) in 2 scenarios: 1. ip_hdr->dst is onlink 2. check_route or nbr_lookup VLAN is virtual-iface which attaches to a physical-iface. Each time a packet being sent to a VLAN port will invoke twice of the net_send_data(). The 1st time, pkt->iface is set to virtual iface and the 2nd time to physical iface. However in above 2 scenarios, at the 2nd time of calling the net_send_data(), the pkt-iface will be changed back to virtual iface. The system runs into a deadloop. This can be proved by enabling CONFIG_NET_ROUTING with the VLAN sample. The main purpose for net_ipv6_prepare_for_send() is to set the right ll_dst address. If the ll_dst address is already set, then no need to go through it again. If the packet has done with the forwarding and set the ll_dst, then no need to check_route again. And, the pkt->iface will not be changed back to virtual iface. (cherry picked from commit 0b24b960fe1f20bc7a4de7993c511295dbb7e21f) Original-Fixes: #77402 Original-Signed-off-by: Shrek Wang GitOrigin-RevId: 0b24b960fe1f20bc7a4de7993c511295dbb7e21f Cr-Build-Id: 8736464299640945217 Cr-Build-Url: https://cr-buildbucket.appspot.com/build/8736464299640945217 Copybot-Job-Name: zephyr-main-copybot-downstream Change-Id: I908768dc7b747e49b4e51ab2568a458945646b52 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/5873058 Commit-Queue: Tristan Honscheid Tested-by: Tristan Honscheid Tested-by: ChromeOS Prod (Robot) Reviewed-by: Tristan Honscheid --- subsys/net/ip/ipv6_nbr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subsys/net/ip/ipv6_nbr.c b/subsys/net/ip/ipv6_nbr.c index b1928f7d138..6677df73ae8 100644 --- a/subsys/net/ip/ipv6_nbr.c +++ b/subsys/net/ip/ipv6_nbr.c @@ -852,7 +852,9 @@ enum net_verdict net_ipv6_prepare_for_send(struct net_pkt *pkt) */ if ((net_pkt_lladdr_dst(pkt)->addr && ((IS_ENABLED(CONFIG_NET_ROUTING) && - net_ipv6_is_ll_addr((struct in6_addr *)ip_hdr->dst)) || + (net_ipv6_is_ll_addr((struct in6_addr *)ip_hdr->dst) || + net_if_ipv6_addr_onlink(NULL, (struct in6_addr *)ip_hdr->dst) || + net_pkt_forwarding(pkt))) || !IS_ENABLED(CONFIG_NET_ROUTING))) || net_ipv6_is_addr_mcast((struct in6_addr *)ip_hdr->dst) || /* Workaround Linux bug, see: