You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ar...@apache.org on 2026/04/23 07:11:14 UTC

(nuttx) branch master updated: net/devif: Reorder ipv4_input packet classification.

This is an automated email from the ASF dual-hosted git repository.

anchao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 5428220062f net/devif: Reorder ipv4_input packet classification.
5428220062f is described below

commit 5428220062f84f7867d050e3db5ae0e3c5b3bb07
Author: Shunchao Hu <an...@gmail.com>
AuthorDate: Sun Apr 19 10:25:15 2026 +0800

    net/devif: Reorder ipv4_input packet classification.
    
    Rework ipv4_input() packet classification to make the control flow
    clearer and keep the common local-unicast case first.
    
    This change:
    - handles local packets first
    - keeps broadcast/multicast handling in dedicated branches
    
    It also prevents broadcast and multicast packets from falling through
    into the unicast forward path.
    
    Signed-off-by: Shunchao Hu <an...@gmail.com>
---
 net/devif/ipv4_input.c | 154 ++++++++++++++++++-------------------------------
 1 file changed, 57 insertions(+), 97 deletions(-)

diff --git a/net/devif/ipv4_input.c b/net/devif/ipv4_input.c
index 5c167a793ee..77ea651499b 100644
--- a/net/devif/ipv4_input.c
+++ b/net/devif/ipv4_input.c
@@ -311,140 +311,100 @@ static int ipv4_in(FAR struct net_driver_s *dev)
 
   destipaddr = net_ip4addr_conv32(ipv4->destipaddr);
 
-#if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK)
-  /* If IP broadcast support is configured, we check for a broadcast
-   * UDP packet, which may be destined to us (even if there is no IP
-   * address yet assigned to the device as is the case when we are
-   * negotiating over DHCP for an address).
+  /* Keep the common local-unicast case on the fast path, then classify
+   * non-local packets as broadcast, multicast, or forwardable unicast.
    */
 
-  if (ipv4->proto == IP_PROTO_UDP &&
-      net_ipv4addr_cmp(destipaddr, INADDR_BROADCAST))
+  if (net_ipv4addr_cmp(destipaddr, dev->d_ipaddr))
     {
-#ifdef CONFIG_NET_IPFORWARD_BROADCAST
-      /* Forward broadcast packets */
-
-      ipv4_forward_broadcast(dev, ipv4);
-
-      /* Process the incoming packet if not forwardable */
-
-      if (dev->d_len > 0)
-#endif
+#ifdef CONFIG_NET_ICMP
+      if (net_ipv4addr_cmp(dev->d_ipaddr, INADDR_ANY))
         {
-          ret = udp_ipv4_input(dev);
+          nwarn("WARNING: No IP address assigned\n");
+          goto drop;
         }
-
-      goto done;
-    }
-  else
 #endif
-#if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK)
-  /* The address is not the broadcast address and we have been assigned a
-   * address.  So there is also the possibility that the destination address
-   * is a sub-net broadcast address which we will need to handle just as for
-   * the broadcast address above.
-   */
-
-  if (ipv4->proto == IP_PROTO_UDP &&
-      net_ipv4addr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask) &&
-      net_ipv4addr_broadcast(destipaddr, dev->d_netmask))
+    }
+  else if (net_ipv4addr_cmp(destipaddr, INADDR_BROADCAST) ||
+           (net_ipv4addr_maskcmp(destipaddr, dev->d_ipaddr,
+                                 dev->d_netmask) &&
+            net_ipv4addr_broadcast(destipaddr, dev->d_netmask)))
     {
 #ifdef CONFIG_NET_IPFORWARD_BROADCAST
-      /* Forward broadcast packets */
-
       ipv4_forward_broadcast(dev, ipv4);
-
-      /* Process the incoming packet if not forwardable */
-
-      if (dev->d_len > 0)
 #endif
+
+#if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK)
+      if (ipv4->proto == IP_PROTO_UDP)
         {
           ret = udp_ipv4_input(dev);
+          goto done;
         }
-
-      goto done;
-    }
-  else
 #endif
-  /* Check if the packet is destined for our IP address. */
 
-  if (!net_ipv4addr_cmp(destipaddr, dev->d_ipaddr))
+#ifdef CONFIG_NET_STATISTICS
+      g_netstats.ipv4.drop++;
+#endif
+      goto drop;
+    }
+  else if (IN_MULTICAST(NTOHL(destipaddr)))
     {
-      /* No.. This is not our IP address. Check for an IPv4 IGMP group
-       * address
-       */
-
 #ifdef CONFIG_NET_IGMP
-      in_addr_t destip = net_ip4addr_conv32(ipv4->destipaddr);
-      if (igmp_grpfind(dev, &destip) != NULL)
+      if (igmp_grpfind(dev, &destipaddr) != NULL)
         {
 #ifdef CONFIG_NET_IPFORWARD_BROADCAST
-          /* Forward multicast packets */
-
           ipv4_forward_broadcast(dev, ipv4);
-
-          /* Return success if the packet was forwarded. */
-
-          if (dev->d_len == 0)
-            {
-              goto done;
-            }
 #endif
         }
       else
 #endif
         {
-          /* No.. The packet is not destined for us. */
-
+#ifdef CONFIG_NET_STATISTICS
+          g_netstats.ipv4.drop++;
+#endif
+          goto drop;
+        }
+    }
+  else
+    {
 #ifdef CONFIG_NET_IPFORWARD
-          /* Try to forward the packet */
+      /* Try to forward the unicast packet. */
 
-          if (ipv4_forward(dev, ipv4) >= 0)
-            {
-              /* The packet was forwarded.  Return success; d_len will
-               * be set appropriately by the forwarding logic:  Cleared
-               * if the packet is forward via anoother device or non-
-               * zero if it will be forwarded by the same device that
-               * it was received on.
-               */
-
-              goto done;
-            }
-          else
+      if (ipv4_forward(dev, ipv4) >= 0)
+        {
+          /* The packet was forwarded.  Return success; d_len will
+           * be set appropriately by the forwarding logic:  Cleared
+           * if the packet is forward via another device or non-zero
+           * if it will be forwarded by the same device that it was
+           * received on.
+           */
+
+          goto done;
+        }
+      else
 #endif
 #if defined(NET_UDP_HAVE_STACK) && defined(CONFIG_NET_BINDTODEVICE)
-          /* If the protocol specific socket option NET_BINDTODEVICE
-           * is selected, then we must forward all UDP packets to the bound
-           * socket.
-           */
+      /* If the protocol specific socket option NET_BINDTODEVICE
+       * is selected, then we must forward all UDP packets to the bound
+       * socket.
+       */
 
-          if (ipv4->proto != IP_PROTO_UDP)
+      if (ipv4->proto != IP_PROTO_UDP)
 #endif
-            {
-              /* Not destined for us and not forwardable... Drop the
-               * packet.
-               */
+        {
+          /* Not destined for us and not forwardable... Drop the
+           * packet.
+           */
 
-              ninfo("WARNING: Not destined for us; not forwardable... "
-                    "Dropping!\n");
+          ninfo("WARNING: Not destined for us; not forwardable... "
+                "Dropping!\n");
 
 #ifdef CONFIG_NET_STATISTICS
-              g_netstats.ipv4.drop++;
+          g_netstats.ipv4.drop++;
 #endif
-              goto drop;
-            }
+          goto drop;
         }
     }
-#ifdef CONFIG_NET_ICMP
-
-  /* In other cases, the device must be assigned a non-zero IP address. */
-
-  else if (net_ipv4addr_cmp(dev->d_ipaddr, INADDR_ANY))
-    {
-      nwarn("WARNING: No IP address assigned\n");
-      goto drop;
-    }
-#endif
 
 #ifdef CONFIG_NET_IPV4_CHECKSUMS
   if (((dev->d_features & NETDEV_RX_CSUM) == 0)