ipv4: Fix ARP behavior with many mac-vlans
authorBen Greear <greearb@candelatech.com>
Mon, 17 Nov 2008 03:19:38 +0000 (19:19 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 17 Nov 2008 03:19:38 +0000 (19:19 -0800)
Ben Greear wrote:
> I have 500 mac-vlans on a system talking to 500 other
> mac-vlans.  My problem is that the arp-table gets extremely
> huge because every time an arp-request comes in on all mac-vlans,
> a stale arp entry is added for each mac-vlan.  I have filtering
> turned on, but that doesn't help because the neigh_event_ns call
> below will cause a stale neighbor entry to be created regardless
> of whether a replay will be sent or not.
> Maybe the neigh_event code should be below the checks for dont_send,
> and only create check neigh_event_ns if we are !dont_send?

The attached patch makes it work much better for me.  The patch
will cause the code to NOT create a stale neighbor entry if we
are not going to respond to the ARP request.  The old code
*would* create a stale entry even if we are not going to respond.

Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/arp.c

index 957c87d..29a74c0 100644 (file)
@@ -818,18 +818,18 @@ static int arp_process(struct sk_buff *skb)
                addr_type = rt->rt_type;
 
                if (addr_type == RTN_LOCAL) {
-                       n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
-                       if (n) {
-                               int dont_send = 0;
-
-                               if (!dont_send)
-                                       dont_send |= arp_ignore(in_dev, sip, tip);
-                               if (!dont_send && IN_DEV_ARPFILTER(in_dev))
-                                       dont_send |= arp_filter(sip, tip, dev);
-                               if (!dont_send)
-                                       arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+                       int dont_send = 0;
 
-                               neigh_release(n);
+                       if (!dont_send)
+                               dont_send |= arp_ignore(in_dev,sip,tip);
+                       if (!dont_send && IN_DEV_ARPFILTER(in_dev))
+                               dont_send |= arp_filter(sip,tip,dev);
+                       if (!dont_send) {
+                               n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
+                               if (n) {
+                                       arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+                                       neigh_release(n);
+                               }
                        }
                        goto out;
                } else if (IN_DEV_FORWARD(in_dev)) {