lagg0.2 style vlans on lagg(4) interface

Niki Denev nike_d at cytexbg.com
Thu May 22 03:57:05 UTC 2008


On Thu, May 22, 2008 at 1:41 AM, Max Laier <max at love2party.net> wrote:
> I think if_ether.c would be good, where arp_ifinit() is.
>

Here is what i've come up with (some comments after the patch) :

diff -ur /usr/src/.zfs/snapshot/orig/sys/net/if.c /usr/src/sys/net/if.c
--- /usr/src/.zfs/snapshot/orig/sys/net/if.c    2008-04-29
23:43:08.000000000 +0300
+++ /usr/src/sys/net/if.c       2008-05-22 04:56:42.652730327 +0300
@@ -2636,17 +2636,12 @@
                        (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
                        IFF_UNLOCKGIANT(ifp);
                }
-#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
        }
+       /*
+        * Notify interested parties about the link layer address change.
+        */
+       EVENTHANDLER_INVOKE(ifaddr_event, ifp);
+
        return (0);
 }

diff -ur /usr/src/.zfs/snapshot/orig/sys/net/if_ethersubr.c
/usr/src/sys/net/if_ethersubr.c
--- /usr/src/.zfs/snapshot/orig/sys/net/if_ethersubr.c  2008-05-21
23:29:07.899194044 +0300
+++ /usr/src/sys/net/if_ethersubr.c     2008-05-22 06:38:35.698083868 +0300
@@ -48,6 +48,7 @@
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
+#include <sys/eventhandler.h>

 #include <net/if.h>
 #include <net/if_arp.h>
@@ -99,6 +100,8 @@

 #include <security/mac/mac_framework.h>

+static eventhandler_tag ifaddr_tag;
+
 /* netgraph node hooks for ng_ether(4) */
 void   (*ng_ether_input_p)(struct ifnet *ifp, struct mbuf **mp);
 void   (*ng_ether_input_orphan_p)(struct ifnet *ifp, struct mbuf *m);
@@ -910,6 +913,13 @@
                if_printf(ifp, "Ethernet address: %6D\n", lla, ":");
        if (ifp->if_flags & IFF_NEEDSGIANT)
                if_printf(ifp, "if_start running deferred for Giant\n");
+#ifdef INET
+       /* Register address change hook */
+       ifaddr_tag = EVENTHANDLER_REGISTER(ifaddr_event, arp_gratuit,
+               NULL, EVENTHANDLER_PRI_ANY);
+       //if (ifaddr_tag == NULL)
+       //      return (ENOMEM);
+#endif
 }

 /*
@@ -924,6 +934,8 @@
                (*ng_ether_detach_p)(ifp);
        }

+       EVENTHANDLER_DEREGISTER(ifaddr_event, ifaddr_tag);
+
        bpfdetach(ifp);
        if_detach(ifp);
 }
diff -ur /usr/src/.zfs/snapshot/orig/sys/net/if_vlan.c
/usr/src/sys/net/if_vlan.c
--- /usr/src/.zfs/snapshot/orig/sys/net/if_vlan.c       2007-10-28
18:24:16.000000000 +0200
+++ /usr/src/sys/net/if_vlan.c  2008-05-22 00:18:57.128613715 +0300
@@ -137,6 +137,7 @@
 static MALLOC_DEFINE(M_VLAN, VLANNAME, "802.1Q Virtual LAN Interface");

 static eventhandler_tag ifdetach_tag;
+static eventhandler_tag ifaddr_tag;

 /*
  * We have a global mutex, that is used to serialize configuration
@@ -518,6 +519,35 @@
 /* For if_link_state_change() eyes only... */
 extern void (*vlan_link_state_p)(struct ifnet *, int);

+/*
+ * Update vlan interface link layer address on
+ * parent interface link layer address change.
+ */
+static int
+vlan_lladdr_update(void *arg __unused, struct ifnet *ifp)
+{
+       struct ifvlantrunk *trunk = ifp->if_vlantrunk;
+       struct ifvlan *ifv;
+       int i;
+
+       if (trunk) {
+               TRUNK_LOCK(trunk);
+#ifdef VLAN_ARRAY
+               for (i = 0; i < VLAN_ARRAY_SIZE; i++)
+                       if (trunk->vlans[i] != NULL) {
+                               ifv = trunk->vlans[i];
+#else
+               for (i = 0; i < (1 << trunk->hwidth); i++) {
+                       LIST_FOREACH(ifv, &trunk->hash[i], ifv_list)
+#endif
+                               bcopy(IF_LLADDR(ifp), IF_LLADDR(ifv->ifv_ifp),
+                                       ETHER_ADDR_LEN);
+               }
+               TRUNK_UNLOCK(trunk);
+       }
+       return (0);
+}
+
 static int
 vlan_modevent(module_t mod, int type, void *data)
 {
@@ -528,6 +558,10 @@
                    vlan_ifdetach, NULL, EVENTHANDLER_PRI_ANY);
                if (ifdetach_tag == NULL)
                        return (ENOMEM);
+               ifaddr_tag = EVENTHANDLER_REGISTER(ifaddr_event,
+                       vlan_lladdr_update, NULL, EVENTHANDLER_PRI_ANY);
+               if (ifaddr_tag == NULL)
+                       return (ENOMEM);
                VLAN_LOCK_INIT();
                vlan_input_p = vlan_input;
                vlan_link_state_p = vlan_link_state;
@@ -546,6 +580,7 @@
        case MOD_UNLOAD:
                if_clone_detach(&vlan_cloner);
                EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_tag);
+               EVENTHANDLER_DEREGISTER(ifaddr_event, ifaddr_tag);
                vlan_input_p = NULL;
                vlan_link_state_p = NULL;
                vlan_trunk_cap_p = NULL;
diff -ur /usr/src/.zfs/snapshot/orig/sys/netinet/if_ether.c
/usr/src/sys/netinet/if_ether.c
--- /usr/src/.zfs/snapshot/orig/sys/netinet/if_ether.c  2007-10-07
23:44:22.000000000 +0300
+++ /usr/src/sys/netinet/if_ether.c     2008-05-22 06:41:34.966106759 +0300
@@ -956,6 +956,16 @@
        ifa->ifa_flags |= RTF_CLONING;
 }

+void
+arp_gratuit(void *arg __unused, 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);
+       }
+}
+
 static void
 arp_init(void)
 {
diff -ur /usr/src/.zfs/snapshot/orig/sys/netinet/if_ether.h
/usr/src/sys/netinet/if_ether.h
--- /usr/src/.zfs/snapshot/orig/sys/netinet/if_ether.h  2005-02-22
15:04:03.000000000 +0200
+++ /usr/src/sys/netinet/if_ether.h     2008-05-22 05:24:06.749938771 +0300
@@ -113,6 +113,7 @@
                struct mbuf *m, struct sockaddr *dst, u_char *desten);
 void   arp_ifinit(struct ifnet *, struct ifaddr *);
 void   arp_ifinit2(struct ifnet *, struct ifaddr *, u_char *);
+void   arp_gratuit(void *, struct ifnet *);
 #endif

 #endif

I think arp_gratuit() needs a better name.
Is if_ethersubr.c:ether_ifattach() good place to register the EVENT hook?
And if yes, what would be the best way to handle failure to register
the hook, as the function is void?
Should I worry about that, or just print a warning message and continue?


Niki


More information about the freebsd-net mailing list