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

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

commit adb161aa10ec70f0643e0dca8d715c49e5a38724
Author: zhanghongyu <[email protected]>
AuthorDate: Fri Aug 29 16:15:18 2025 +0800

    arp: the manually configured arp table should not have a timeout period
    
    Improve the behavior of the ARP table so that the manually configured
    ARP table has the highest priority, can only be manually modified to
    other values, otherwise will never change again, and will not time out.
    The modified behavior is consistent with that of Linux.
    
    Signed-off-by: zhanghongyu <[email protected]>
---
 net/arp/arp.h             |  6 ++++--
 net/arp/arp_out.c         |  2 +-
 net/arp/arp_send.c        |  2 +-
 net/arp/arp_table.c       | 28 +++++++++++++++++++---------
 net/netdev/netdev_ioctl.c |  3 ++-
 5 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/net/arp/arp.h b/net/arp/arp.h
index 1c4d44849c6..06a715b93db 100644
--- a/net/arp/arp.h
+++ b/net/arp/arp.h
@@ -164,6 +164,7 @@ struct arp_entry_s
   in_addr_t                at_ipaddr;   /* IP address */
   struct ether_addr        at_ethaddr;  /* Hardware address */
   clock_t                  at_time;     /* Time of last usage */
+  uint8_t                  at_flags;    /* Flags, examples: ATF_PERM */
   FAR struct net_driver_s *at_dev;      /* The device driver structure */
 };
 
@@ -471,6 +472,7 @@ void arp_cleanup(FAR struct net_driver_s *dev);
  *   dev     - The device driver structure
  *   ipaddr  - The IP address as an inaddr_t
  *   ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN]
+ *   flags   - Flags, examples: ATF_PERM(Permanent entry)
  *
  * Returned Value:
  *   Zero (OK) if the ARP table entry was successfully modified.  A negated
@@ -482,7 +484,7 @@ void arp_cleanup(FAR struct net_driver_s *dev);
  ****************************************************************************/
 
 int arp_update(FAR struct net_driver_s *dev, in_addr_t ipaddr,
-               FAR const uint8_t *ethaddr);
+               FAR const uint8_t *ethaddr, uint8_t flags);
 
 /****************************************************************************
  * Name: arp_hdr_update
@@ -623,7 +625,7 @@ void arp_acd_setup(FAR struct net_driver_s *dev);
 #  define arp_find(i,e,d,u) (-ENOSYS)
 #  define arp_delete(i,d) (-ENOSYS)
 #  define arp_cleanup(d)
-#  define arp_update(d,i,m);
+#  define arp_update(d,i,m,f);
 #  define arp_hdr_update(d,i,m);
 #  define arp_snapshot(s,n) (0)
 #  define arp_dump(arp)
diff --git a/net/arp/arp_out.c b/net/arp/arp_out.c
index fa465e30922..120b2deef10 100644
--- a/net/arp/arp_out.c
+++ b/net/arp/arp_out.c
@@ -283,7 +283,7 @@ void arp_out(FAR struct net_driver_s *dev)
        * send ARP request for same destination.
        */
 
-      arp_update(dev, ipaddr, NULL);
+      arp_update(dev, ipaddr, NULL, 0);
 
       /* The destination address was not in our ARP table, so we overwrite
        * the IP packet with an ARP request.
diff --git a/net/arp/arp_send.c b/net/arp/arp_send.c
index 34c5f1acf14..a44bf3dd763 100644
--- a/net/arp/arp_send.c
+++ b/net/arp/arp_send.c
@@ -367,7 +367,7 @@ int arp_send(in_addr_t ipaddr)
 
       if (state.snd_retries == 0)
         {
-          arp_update(dev, ipaddr, NULL);
+          arp_update(dev, ipaddr, NULL, 0);
           sending = true;
         }
 
diff --git a/net/arp/arp_table.c b/net/arp/arp_table.c
index 3cdf35c4c0a..7c65b0f498f 100644
--- a/net/arp/arp_table.c
+++ b/net/arp/arp_table.c
@@ -169,6 +169,10 @@ arp_return_old_entry(FAR struct arp_entry_s *e1, FAR 
struct arp_entry_s *e2)
     {
       return e2;
     }
+  else if ((e1->at_flags & ATF_PERM) != (e2->at_flags & ATF_PERM))
+    {
+      return (e1->at_flags & ATF_PERM) == 0 ? e1 : e2;
+    }
   else if ((int)(e1->at_time - e2->at_time) <= 0)
     {
       return e1;
@@ -220,7 +224,8 @@ static FAR struct arp_entry_s *arp_lookup(in_addr_t ipaddr,
 
           /* Check if it has expired */
 
-          if (clock_systime_ticks() - tabptr->at_time <= ARP_MAXAGE_TICK)
+          if ((tabptr->at_flags & ATF_PERM) != 0 ||
+              clock_systime_ticks() - tabptr->at_time <= ARP_MAXAGE_TICK)
             {
               return tabptr;
             }
@@ -279,6 +284,7 @@ static void arp_get_arpreq(FAR struct arpreq *output,
  *   dev     - The device driver structure
  *   ipaddr  - The IP address as an inaddr_t
  *   ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN]
+ *   flags   - Flags, examples: ATF_PERM(Permanent entry)
  *
  * Returned Value:
  *   Zero (OK) if the ARP table entry was successfully modified.  A negated
@@ -290,7 +296,7 @@ static void arp_get_arpreq(FAR struct arpreq *output,
  ****************************************************************************/
 
 int arp_update(FAR struct net_driver_s *dev, in_addr_t ipaddr,
-               FAR const uint8_t *ethaddr)
+               FAR const uint8_t *ethaddr, uint8_t flags)
 {
   FAR struct arp_entry_s *tabptr = &g_arptable[0];
 #ifdef CONFIG_NETLINK_ROUTE
@@ -355,10 +361,14 @@ int arp_update(FAR struct net_driver_s *dev, in_addr_t 
ipaddr,
    * information.
    */
 
-  tabptr->at_ipaddr = ipaddr;
-  memcpy(tabptr->at_ethaddr.ether_addr_octet, ethaddr, ETHER_ADDR_LEN);
-  tabptr->at_dev = dev;
-  tabptr->at_time = clock_systime_ticks();
+  if ((tabptr->at_flags & ATF_PERM) == 0 || (flags & ATF_PERM) != 0)
+    {
+      memcpy(tabptr->at_ethaddr.ether_addr_octet, ethaddr, ETHER_ADDR_LEN);
+      tabptr->at_ipaddr = ipaddr;
+      tabptr->at_time   = clock_systime_ticks();
+      tabptr->at_flags  = flags;
+      tabptr->at_dev    = dev;
+    }
 
   /* Notify the new entry */
 
@@ -401,7 +411,7 @@ void arp_hdr_update(FAR struct net_driver_s *dev, FAR 
uint16_t *pipaddr,
 
   /* Update the ARP table */
 
-  arp_update(dev, ipaddr, ethaddr);
+  arp_update(dev, ipaddr, ethaddr, 0);
 }
 
 /****************************************************************************
@@ -598,8 +608,8 @@ unsigned int arp_snapshot(FAR struct arpreq *snapshot,
        i++)
     {
       tabptr = &g_arptable[i];
-      if (tabptr->at_ipaddr != 0 &&
-          now - tabptr->at_time <= ARP_MAXAGE_TICK)
+      if (tabptr->at_ipaddr != 0 && ((tabptr->at_flags & ATF_PERM) != 0 ||
+          now - tabptr->at_time <= ARP_MAXAGE_TICK))
         {
           arp_get_arpreq(&snapshot[ncopied], tabptr);
           ncopied++;
diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c
index 61efcac5f0f..70b05275f7d 100644
--- a/net/netdev/netdev_ioctl.c
+++ b/net/netdev/netdev_ioctl.c
@@ -1491,7 +1491,8 @@ static int netdev_arp_ioctl(FAR struct socket *psock, int 
cmd,
                */
 
               ret = arp_update(dev, addr->sin_addr.s_addr,
-                               (FAR const uint8_t *)req->arp_ha.sa_data);
+                               (FAR const uint8_t *)req->arp_ha.sa_data,
+                               req->arp_flags);
             }
           else
             {

Reply via email to