You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by je...@apache.org on 2024/04/24 06:24:52 UTC

(nuttx) branch master updated: net/udp_input: Only dup packets for broadcast / multicast.

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

jerpelea 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 41ab3a9cfe net/udp_input: Only dup packets for broadcast / multicast.
41ab3a9cfe is described below

commit 41ab3a9cfe899642fa380be1fac2f4535f40bffa
Author: Zhe Weng <we...@xiaomi.com>
AuthorDate: Tue Apr 23 12:20:22 2024 +0800

    net/udp_input: Only dup packets for broadcast / multicast.
    
    We found previous multicast support (https://github.com/apache/nuttx/pull/12015) harms some unicast situation, and the `udp_input` should not dup packets for unicast.
    Now, we only pass broadcast / multicast packets into each listener and let the code under control of `CONFIG_NET_BROADCAST`.
    
    Ref: https://github.com/torvalds/linux/blob/v6.8/net/ipv4/udp.c#L2219
    
    Signed-off-by: Zhe Weng <we...@xiaomi.com>
---
 net/udp/udp_input.c | 97 +++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 75 insertions(+), 22 deletions(-)

diff --git a/net/udp/udp_input.c b/net/udp/udp_input.c
index 3b9c9910f4..47d995ff63 100644
--- a/net/udp/udp_input.c
+++ b/net/udp/udp_input.c
@@ -63,6 +63,53 @@
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: udp_is_broadcast
+ *
+ * Description:
+ *   Check if the destination address is a broadcast/multicast address.
+ *
+ * Input Parameters:
+ *   dev - The device driver structure containing the received UDP packet
+ *
+ * Returned Value:
+ *   True if the destination address is a broadcast/multicast address
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_SOCKOPTS) && defined(CONFIG_NET_BROADCAST)
+static bool udp_is_broadcast(FAR struct net_driver_s *dev)
+{
+  /* Check if the destination address is a broadcast/multicast address */
+
+#ifdef CONFIG_NET_IPv4
+#  ifdef CONFIG_NET_IPv6
+  if (IFF_IS_IPv4(dev->d_flags))
+#  endif
+    {
+      FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
+      in_addr_t destipaddr = net_ip4addr_conv32(ipv4->destipaddr);
+
+      return net_ipv4addr_cmp(destipaddr, INADDR_BROADCAST) ||
+             IN_MULTICAST(NTOHL(destipaddr)) ||
+             (net_ipv4addr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask)
+              && net_ipv4addr_broadcast(destipaddr, dev->d_netmask));
+    }
+#endif
+#ifdef CONFIG_NET_IPv6
+#  ifdef CONFIG_NET_IPv4
+  else
+#  endif
+    {
+      FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
+      return net_is_addr_mcast(ipv6->destipaddr);
+    }
+#endif
+
+  return false;
+}
+#endif
+
 /****************************************************************************
  * Name: udp_input_conn
  *
@@ -162,7 +209,7 @@ static int udp_input(FAR struct net_driver_s *dev, unsigned int iplen)
 {
   FAR struct udp_hdr_s *udp;
   FAR struct udp_conn_s *conn;
-#ifdef CONFIG_NET_SOCKOPTS
+#if defined(CONFIG_NET_SOCKOPTS) && defined(CONFIG_NET_BROADCAST)
   FAR struct udp_conn_s *nextconn;
   FAR struct iob_s *iob;
 #endif
@@ -243,32 +290,38 @@ static int udp_input(FAR struct net_driver_s *dev, unsigned int iplen)
         {
           /* We'll only get multiple conn when we support SO_REUSEADDR */
 
-#ifdef CONFIG_NET_SOCKOPTS
-          /* Do we have second connection that can hold this packet? */
+#if defined(CONFIG_NET_SOCKOPTS) && defined(CONFIG_NET_BROADCAST)
+          /* Check if the destination is a broadcast/multicast address */
 
-          while ((nextconn = udp_active(dev, conn, udp)) != NULL)
+          if (udp_is_broadcast(dev))
             {
-              /* Yes... There are multiple listeners on the same port.
-               * We need to clone the packet and deliver it to each listener.
-               */
+              /* Do we have second connection that can hold this packet? */
 
-              iob = netdev_iob_clone(dev, true);
-              if (iob == NULL)
+              while ((nextconn = udp_active(dev, conn, udp)) != NULL)
                 {
-                  nerr("ERROR: IOB clone failed.\n");
-                  break; /* We can still process one time without clone. */
+                  /* Yes... There are multiple listeners on the same port.
+                   * We need to clone the packet and deliver it to each
+                   * listener.
+                   */
+
+                  iob = netdev_iob_clone(dev, true);
+                  if (iob == NULL)
+                    {
+                      nerr("ERROR: IOB clone failed.\n");
+                      break; /* We can still process once without clone. */
+                    }
+
+                  ret = udp_input_conn(dev, conn, udpiplen);
+                  if (ret < 0)
+                    {
+                      nwarn("WARNING: A conn failed to process the pkt %d\n",
+                            ret); /* We can still continue for next conn. */
+                    }
+
+                  netdev_iob_replace(dev, iob);
+                  udp  = IPBUF(iplen);
+                  conn = nextconn;
                 }
-
-              ret = udp_input_conn(dev, conn, udpiplen);
-              if (ret < 0)
-                {
-                  nwarn("WARNING: A conn failed to process the packet %d\n",
-                        ret); /* We can still continue for next conn. */
-                }
-
-              netdev_iob_replace(dev, iob);
-              udp  = IPBUF(iplen);
-              conn = nextconn;
             }
 #endif