]> xenbits.xensource.com Git - people/liuw/freebsd.git/commitdiff
Use lladdr_event to propagate gratiotus arp.
authormelifaro <melifaro@FreeBSD.org>
Mon, 9 Nov 2015 10:11:14 +0000 (10:11 +0000)
committermelifaro <melifaro@FreeBSD.org>
Mon, 9 Nov 2015 10:11:14 +0000 (10:11 +0000)
Differential Revision: https://reviews.freebsd.org/D4019

sys/net/if.c
sys/net/if_vlan.c
sys/netgraph/ng_eiface.c
sys/netgraph/ng_ether.c
sys/netinet/if_ether.c

index 118e63b0658994dd7a3bae7c3343ce3d9eb8514c..74c30d0159dca67a6eb51f714ae23a24a2df2f51 100644 (file)
@@ -2512,7 +2512,8 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
                        return (error);
                error = if_setlladdr(ifp,
                    ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len);
-               EVENTHANDLER_INVOKE(iflladdr_event, ifp);
+               if (error == 0)
+                       EVENTHANDLER_INVOKE(iflladdr_event, ifp);
                break;
 
        case SIOCAIFGROUP:
@@ -3375,16 +3376,6 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
                        ifr.ifr_flagshigh = ifp->if_flags >> 16;
                        (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
                }
-#ifdef INET
-               /*
-                * Also send gratuitous ARPs to notify other nodes about
-                * the address change.
-                */
-               TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
-                       if (ifa->ifa_addr->sa_family == AF_INET)
-                               arp_ifinit(ifp, ifa);
-               }
-#endif
        }
        return (0);
 }
index 462c9078fbc1c39b768227d2122f5b620a954ae5..dc079750b61ea7819f9b9d12c2567e22af17d3b1 100644 (file)
@@ -523,7 +523,7 @@ vlan_iflladdr(void *arg __unused, struct ifnet *ifp)
 #ifndef VLAN_ARRAY
        struct ifvlan *next;
 #endif
-       int i;
+       int error, i;
 
        /*
         * Check if it's a trunk interface first of all
@@ -544,8 +544,11 @@ vlan_iflladdr(void *arg __unused, struct ifnet *ifp)
                LIST_FOREACH_SAFE(ifv, &ifp->if_vlantrunk->hash[i], ifv_list, next) {
 #endif /* VLAN_ARRAY */
                        VLAN_UNLOCK();
-                       if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp),
+                       error = if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp),
                            ifp->if_addrlen);
+                       if (error == 0)
+                               EVENTHANDLER_INVOKE(iflladdr_event,
+                                   ifv->ifv_ifp);
                        VLAN_LOCK();
                }
        VLAN_UNLOCK();
index ae573da0254181c91fb2cd7e41612dfdc7dfe7fe..ab7071914f6e72e7d0b0a8b3a1f4bfaec0735b51 100644 (file)
@@ -489,7 +489,8 @@ ng_eiface_rcvmsg(node_p node, item_p item, hook_p lasthook)
                        }
                        error = if_setlladdr(priv->ifp,
                            (u_char *)msg->data, ETHER_ADDR_LEN);
-                       EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp);
+                       if (error == 0)
+                               EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp);
                        break;
                    }
 
index fcde08c070920a14d1551b4e3b187c90ea811970..63179a5edd102f3dcaecbabfa548ad8d584ea33d 100644 (file)
@@ -534,7 +534,8 @@ ng_ether_rcvmsg(node_p node, item_p item, hook_p lasthook)
                        }
                        error = if_setlladdr(priv->ifp,
                            (u_char *)msg->data, ETHER_ADDR_LEN);
-                       EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp);
+                       if (error == 0)
+                               EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp);
                        break;
                    }
                case NGM_ETHER_GET_PROMISC:
index f9d3612b046a3f90eb8df9592ce36d301f1075e6..fd005c795456c4d7fe725dc68d73fec46160d823 100644 (file)
@@ -142,7 +142,9 @@ static void in_arpinput(struct mbuf *);
 static void arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr,
     struct ifnet *ifp, int bridged, struct llentry *la);
 static void arp_mark_lle_reachable(struct llentry *la);
+static void arp_iflladdr(void *arg __unused, struct ifnet *ifp);
 
+static eventhandler_tag iflladdr_tag;
 
 static const struct netisr_handler arp_nh = {
        .nh_name = "arp",
@@ -1150,10 +1152,39 @@ arp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr)
        ifa->ifa_rtrequest = NULL;
 }
 
+/*
+ * Sends gratuitous ARPs for each ifaddr to notify other
+ * nodes about the address change.
+ */
+static __noinline void
+arp_handle_ifllchange(struct ifnet *ifp)
+{
+       struct ifaddr *ifa;
+
+       TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+               if (ifa->ifa_addr->sa_family == AF_INET)
+                       arp_ifinit(ifp, ifa);
+       }
+}
+
+/*
+ * A handler for interface link layer address change event.
+ */
+static __noinline void
+arp_iflladdr(void *arg __unused, struct ifnet *ifp)
+{
+
+       if ((ifp->if_flags & IFF_UP) != 0)
+               arp_handle_ifllchange(ifp);
+}
+
 static void
 arp_init(void)
 {
 
        netisr_register(&arp_nh);
+       if (IS_DEFAULT_VNET(curvnet))
+               iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
+                   arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
 }
 SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0);