[PATCH] if_lagg driver enhancements.
Tushar Mulkar
tmulkar at sandvine.com
Tue Feb 7 14:41:01 UTC 2012
Hello,
A patch is developed that has following enhancements in lagg driver
- Sending a gratuitous ARP when link state changes on primary port of
lag (kern/156226)
- Support of new ioctl command to change primary port of the lag
These enhancements are quite handy and useful. Please check if it can
be added to FreeBSD
------------------------------------------------------------------
--- /vobs/fw-bsd/src/sys/net/if_lagg.c 2012-01-24 05:28:25.000000000 -0500
+++ /vobs/fw-bsd/src/sys/net/if_lagg.c 2012-02-03 09:11:50.000000000 -0500
@@ -54,13 +54,19 @@
#ifdef INET
#include <netinet/in.h>
+#include <netinet/in_var.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#endif
#ifdef INET6
+#include <netinet/icmp6.h>
#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/scope6_var.h>
+#include <netinet6/nd6.h>
#endif
#include <net/if_vlan_var.h>
@@ -746,6 +752,7 @@
switch (dst->sa_family) {
case pseudo_AF_HDRCMPLT:
+ return ((*lp->lp_output)(ifp, m, dst, ro));
case AF_UNSPEC:
eh = (struct ether_header *)dst->sa_data;
type = eh->ether_type;
@@ -1053,7 +1060,38 @@
error = EINVAL;
break;
- default:
+ case SIOCSPLAGGPORT:
+
+ if (rp->rp_portname[0] == '\0' ||
+ (tpif = ifunit(rp->rp_portname)) == NULL) {
+ error = EINVAL;
+ break;
+ }
+
+ LAGG_WLOCK(sc);
+ if ((lp = (struct lagg_port *)tpif->if_lagg) == NULL ||
+ lp->lp_softc != sc) {
+ error = ENOENT;
+ LAGG_WUNLOCK(sc);
+ break;
+ }
+ /* This port is already primary port no need to do any thing */
+ if(SLIST_FIRST(&sc->sc_ports)== lp){
+ LAGG_WUNLOCK(sc);
+ return (error);
+ }
+ else{
+ SLIST_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entries);
+ SLIST_INSERT_HEAD(&sc->sc_ports, lp, lp_entries);
+ sc->sc_primary = lp;
+ lagg_lladdr(sc, lp->lp_lladdr);
+ sc->sc_ifp->if_mtu = tpif->if_mtu;
+ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
+ lagg_port_lladdr(lp, IF_LLADDR(ifp));
+ LAGG_WUNLOCK(sc);
+ }
+ break;
+ default:
error = ether_ioctl(ifp, cmd, data);
break;
}
@@ -1309,17 +1347,47 @@
{
struct lagg_port *lp = (struct lagg_port *)ifp->if_lagg;
struct lagg_softc *sc = NULL;
+ struct ifaddr *ifa ;
+ struct in6_ifaddr *ia = NULL;
+ struct in6_addr *in6 = NULL;
+ struct ifaddrhead ifaddrh;
+ struct in_ifaddr *laddr = NULL;
if (lp != NULL)
sc = lp->lp_softc;
if (sc == NULL)
return;
-
+
LAGG_WLOCK(sc);
lagg_linkstate(sc);
+
if (sc->sc_linkstate != NULL)
(*sc->sc_linkstate)(lp);
+
LAGG_WUNLOCK(sc);
+
+ /* If status changed on primary port send gratuitous ARP */
+
+ if(sc->sc_primary == lp){
+ IFP_TO_IA(sc->sc_ifp, laddr);
+ if (laddr == NULL)
+ return;
+ ifaddrh = sc->sc_ifp->if_addrhead;
+ TAILQ_FOREACH(ifa, &ifaddrh, ifa_link) {
+#ifdef INET
+ if(ifa->ifa_addr->sa_family == AF_INET)
+ arp_ifinit(sc->sc_ifp,(struct ifaddr *) laddr);
+#endif
+
+#ifdef INET6
+ if (ifa->ifa_addr->sa_family == AF_INET6){
+ ia = in6ifa_ifpforlinklocal(sc->sc_ifp, 0);
+ in6 = &ifatoia6(ifa)->ia_addr.sin6_addr;
+ nd6_ns_output(sc->sc_ifp, NULL,in6, 0, 1);
+ }
+#endif
+ }
+ }
}
struct lagg_port *
--- /vobs/fw-bsd/src/sys/net/if_lagg.h 2012-02-03 03:45:32.000000000 -0500
+++ /vobs/fw-bsd/src/sys/net/if_lagg.h 2012-02-03 03:53:18.000000000 -0500
@@ -119,6 +119,7 @@
#define SIOCGLAGG _IOWR('i', 143, struct lagg_reqall)
#define SIOCSLAGG _IOW('i', 144, struct lagg_reqall)
+#define SIOCSPLAGGPORT _IOWR('i', 145, struct lagg_reqport)
#ifdef _KERNEL
/*
--- /vobs/fw-bsd/src/sbin/ifconfig/iflagg.c 2012-02-03 00:48:38.000000000 -0500
+++ /vobs/fw-bsd/src/sbin/ifconfig/iflagg.c 2012-02-03 01:41:34.000000000 -0500
@@ -43,6 +43,18 @@
if (ioctl(s, SIOCSLAGGPORT, &rp))
err(1, "SIOCSLAGGPORT");
}
+static void
+setlaggpport(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct lagg_reqport rp;
+
+ bzero(&rp, sizeof(rp));
+ strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
+ strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
+
+ if (ioctl(s, SIOCSLAGGPPORT, &rp))
+ err(1, "SIOCSLAGPPORT");
+}
static void
unsetlaggport(const char *val, int d, int s, const struct afswtch *afp)
@@ -174,6 +186,7 @@
DEF_CMD_ARG("laggport", setlaggport),
DEF_CMD_ARG("-laggport", unsetlaggport),
DEF_CMD_ARG("laggproto", setlaggproto),
+ DEF_CMD_ARG("laggpport", setlaggpport),
};
static struct afswtch af_lagg = {
.af_name = "af_lagg",
--------------------------------------------------------------------------------------------------------
Tushar Mulkar
Senior Software Engineer , Sandvine India
Mobile: +91-9845146601
Skype: tushar.mulkar
www.sandvine.com
More information about the freebsd-net
mailing list