Date: Thu, 22 May 2008 06:57:03 +0300 From: "Niki Denev" <nike_d@cytexbg.com> To: "Max Laier" <max@love2party.net> Cc: freebsd-net@freebsd.org Subject: Re: lagg0.2 style vlans on lagg(4) interface Message-ID: <2e77fc10805212057y7cbeca00kd096a7b090413616@mail.gmail.com> In-Reply-To: <200805220041.24096.max@love2party.net> References: <2e77fc10805211031n6c42ffd2u3dee28164094b83b@mail.gmail.com> <200805212332.13993.max@love2party.net> <2e77fc10805211514q59dd0eadkac2edce50d6c22f7@mail.gmail.com> <200805220041.24096.max@love2party.net>
next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, May 22, 2008 at 1:41 AM, Max Laier <max@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2e77fc10805212057y7cbeca00kd096a7b090413616>