Index: sbin/ifconfig/ifconfig.8 =================================================================== --- sbin/ifconfig/ifconfig.8 +++ sbin/ifconfig/ifconfig.8 @@ -2319,7 +2319,7 @@ .It Cm laggproto Ar proto Set the aggregation protocol. The default is failover. -The available options are failover, fec, lacp, loadbalance, roundrobin and +The available options are failover, lacp, loadbalance, roundrobin, broadcast and none. .It Cm lagghash Ar option Ns Oo , Ns Ar option Oc Set the packet layers to hash for aggregation protocols which load balance. Index: share/man/man4/lagg.4 =================================================================== --- share/man/man4/lagg.4 +++ share/man/man4/lagg.4 @@ -61,10 +61,10 @@ The driver currently supports the aggregation protocols .Ic failover (the default), -.Ic fec , .Ic lacp , .Ic loadbalance , .Ic roundrobin , +.Ic broadcast , and .Ic none . The protocols determine which ports are used for outgoing traffic @@ -86,11 +86,6 @@ .Xr sysctl 8 variable to a nonzero value, which is useful for certain bridged network setups. -.It Ic fec -Supports Cisco EtherChannel. -This is an alias for -.Ic loadbalance -mode. .It Ic lacp Supports the IEEE 802.1AX (formerly 802.3ad) Link Aggregation Control Protocol (LACP) and the Marker Protocol. @@ -113,6 +108,8 @@ Distributes outgoing traffic using a round-robin scheduler through all active ports and accepts incoming traffic from any active port. +.It Ic broadcast +Sends frames to all ports of the LAG and receives frames on any port of the LAG. .It Ic none This protocol is intended to do nothing: it disables any traffic without disabling the Index: sys/net/if_lagg.h =================================================================== --- sys/net/if_lagg.h +++ sys/net/if_lagg.h @@ -52,8 +52,8 @@ #define LAGG_PROTO_FAILOVER 2 /* active failover */ #define LAGG_PROTO_LOADBALANCE 3 /* loadbalance */ #define LAGG_PROTO_LACP 4 /* 802.3ad lacp */ -#define LAGG_PROTO_ETHERCHANNEL 5 /* Cisco FEC */ -#define LAGG_PROTO_MAX 6 +#define LAGG_PROTO_BROADCAST 5 /* broadcast */ +#define LAGG_PROTO_MAX 6 struct lagg_protos { const char *lpr_name; @@ -61,14 +61,14 @@ }; #define LAGG_PROTO_DEFAULT LAGG_PROTO_FAILOVER -#define LAGG_PROTOS { \ - { "failover", LAGG_PROTO_FAILOVER }, \ - { "fec", LAGG_PROTO_ETHERCHANNEL }, \ - { "lacp", LAGG_PROTO_LACP }, \ - { "loadbalance", LAGG_PROTO_LOADBALANCE }, \ - { "roundrobin", LAGG_PROTO_ROUNDROBIN }, \ - { "none", LAGG_PROTO_NONE }, \ - { "default", LAGG_PROTO_DEFAULT } \ +#define LAGG_PROTOS { \ + { "failover", LAGG_PROTO_FAILOVER }, \ + { "broadcast", LAGG_PROTO_BROADCAST}, \ + { "lacp", LAGG_PROTO_LACP }, \ + { "loadbalance", LAGG_PROTO_LOADBALANCE }, \ + { "roundrobin", LAGG_PROTO_ROUNDROBIN }, \ + { "none", LAGG_PROTO_NONE }, \ + { "default", LAGG_PROTO_DEFAULT } \ } /* Index: sys/net/if_lagg.c =================================================================== --- sys/net/if_lagg.c +++ sys/net/if_lagg.c @@ -138,6 +138,13 @@ static struct mbuf *lagg_fail_input(struct lagg_softc *, struct lagg_port *, struct mbuf *); +/* Broadcast mode */ +static int lagg_bcast_attach(struct lagg_softc *); +static int lagg_bcast_detach(struct lagg_softc *); +static int lagg_bcast_start(struct lagg_softc *, struct mbuf *); +static struct mbuf *lagg_bcast_input(struct lagg_softc *, struct lagg_port *, + struct mbuf *); + /* Loadbalancing */ static int lagg_lb_attach(struct lagg_softc *); static int lagg_lb_detach(struct lagg_softc *); @@ -166,7 +173,7 @@ { LAGG_PROTO_ROUNDROBIN, lagg_rr_attach }, { LAGG_PROTO_FAILOVER, lagg_fail_attach }, { LAGG_PROTO_LOADBALANCE, lagg_lb_attach }, - { LAGG_PROTO_ETHERCHANNEL, lagg_lb_attach }, + { LAGG_PROTO_BROADCAST, lagg_bcast_attach }, { LAGG_PROTO_LACP, lagg_lacp_attach }, { LAGG_PROTO_NONE, NULL } }; @@ -918,7 +925,7 @@ case LAGG_PROTO_ROUNDROBIN: case LAGG_PROTO_LOADBALANCE: - case LAGG_PROTO_ETHERCHANNEL: + case LAGG_PROTO_BROADCAST: if (LAGG_PORTACTIVE(lp)) rp->rp_flags |= LAGG_PORT_ACTIVE; break; @@ -1436,7 +1443,7 @@ break; case LAGG_PROTO_ROUNDROBIN: case LAGG_PROTO_LOADBALANCE: - case LAGG_PROTO_ETHERCHANNEL: + case LAGG_PROTO_BROADCAST: speed = 0; SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) speed += lp->lp_ifp->if_baudrate; @@ -1719,6 +1726,89 @@ } /* + * Broadcast mode + */ + +static int +lagg_bcast_attach(struct lagg_softc *sc) +{ + sc->sc_detach = lagg_bcast_detach; + sc->sc_start = lagg_bcast_start; + sc->sc_input = lagg_bcast_input; + sc->sc_port_create = NULL; + sc->sc_port_destroy = NULL; + sc->sc_linkstate = NULL; + sc->sc_req = NULL; + sc->sc_portreq = NULL; + + return (0); +} + +static int +lagg_bcast_detach(struct lagg_softc *sc) +{ + return (0); +} + +static int +lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m) +{ + int active_ports = 0; + int errors = 0; + int ret; + struct lagg_port *lp, *last = NULL; + struct mbuf *m0; + + SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + if (!LAGG_PORTACTIVE(lp)) + continue; + + active_ports++; + + if (last != NULL) { + m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT); + if (m0 == NULL) { + ret = ENOBUFS; + errors++; + break; + } + + ret = lagg_enqueue(last->lp_ifp, m0); + if (ret != 0) + errors++; + } + last = lp; + } + if (last == NULL) { + m_freem(m); + return (ENOENT); + } + if ((last = lagg_link_active(sc, last)) == NULL) { + m_freem(m); + return (ENETDOWN); + } + + ret = lagg_enqueue(last->lp_ifp, m); + if (ret != 0) + errors++; + + if (errors == 0) + return (ret); + + return (0); +} + +static struct mbuf * +lagg_bcast_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) +{ + struct ifnet *ifp = sc->sc_ifp; + + /* Just pass in the packet to our lagg device */ + m->m_pkthdr.rcvif = ifp; + return (m); +} + +/* * Active failover */