From 5c30b378f02d1eea7ca6e4bad1fb13d8645f8354 Mon Sep 17 00:00:00 2001 From: Matt Macy Date: Fri, 11 May 2018 05:00:40 +0000 Subject: [PATCH] Allow different bridge types to coexist if_bridge has a lot of limitations that make it scale poorly to higher data rates. In my projects/VPC branch I leverage the bridge interface between layers for my high speed soft switch as well as for purposes of stacking in general. Reviewed by: sbruno@ Approved by: sbruno@ Differential Revision: https://reviews.freebsd.org/D15344 --- sys/net/if.c | 3 +-- sys/net/if_bridge.c | 13 ++++++------- sys/net/if_bridgevar.h | 13 +++++-------- sys/net/if_ethersubr.c | 3 --- sys/net/if_var.h | 4 ++++ 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index 6c5d09db9ea8..b03b30dae839 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -221,7 +221,6 @@ static MALLOC_DEFINE(M_IFDESCR, "ifdescr", "ifnet descriptions"); static struct sx ifdescr_sx; SX_SYSINIT(ifdescr_sx, &ifdescr_sx, "ifnet descr"); -void (*bridge_linkstate_p)(struct ifnet *ifp); void (*ng_ether_link_state_p)(struct ifnet *ifp, int state); void (*lagg_linkstate_p)(struct ifnet *ifp, int state); /* These are external hooks for CARP. */ @@ -2318,7 +2317,7 @@ do_link_state_change(void *arg, int pending) if (ifp->if_carp) (*carp_linkstate_p)(ifp); if (ifp->if_bridge) - (*bridge_linkstate_p)(ifp); + ifp->if_bridge_linkstate(ifp); if (ifp->if_lagg) (*lagg_linkstate_p)(ifp, link_state); diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index b09541b5e164..6c84d760b717 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -340,7 +340,6 @@ static int bridge_fragment(struct ifnet *, struct mbuf **mp, static void bridge_linkstate(struct ifnet *ifp); static void bridge_linkcheck(struct bridge_softc *sc); -extern void (*bridge_linkstate_p)(struct ifnet *ifp); /* The default bridge vlan is 1 (IEEE 802.1Q-2003 Table 9-2) */ #define VLANTAGOF(_m) \ @@ -556,10 +555,7 @@ bridge_modevent(module_t mod, int type, void *data) bridge_rtnode_zone = uma_zcreate("bridge_rtnode", sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); - bridge_input_p = bridge_input; - bridge_output_p = bridge_output; bridge_dn_p = bridge_dummynet; - bridge_linkstate_p = bridge_linkstate; bridge_detach_cookie = EVENTHANDLER_REGISTER( ifnet_departure_event, bridge_ifdetach, NULL, EVENTHANDLER_PRI_ANY); @@ -568,10 +564,7 @@ bridge_modevent(module_t mod, int type, void *data) EVENTHANDLER_DEREGISTER(ifnet_departure_event, bridge_detach_cookie); uma_zdestroy(bridge_rtnode_zone); - bridge_input_p = NULL; - bridge_output_p = NULL; bridge_dn_p = NULL; - bridge_linkstate_p = NULL; break; default: return (EOPNOTSUPP); @@ -1041,6 +1034,9 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, KASSERT(bif->bif_addrcnt == 0, ("%s: %d bridge routes referenced", __func__, bif->bif_addrcnt)); + ifs->if_bridge_output = NULL; + ifs->if_bridge_input = NULL; + ifs->if_bridge_linkstate = NULL; BRIDGE_UNLOCK(sc); if (!gone) { switch (ifs->if_type) { @@ -1198,6 +1194,9 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) } ifs->if_bridge = sc; + ifs->if_bridge_output = bridge_output; + ifs->if_bridge_input = bridge_input; + ifs->if_bridge_linkstate = bridge_linkstate; bstp_create(&sc->sc_stp, &bif->bif_stp, bif->bif_ifp); /* * XXX: XLOCK HERE!?! diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h index 84ff8d21357d..f4f61706c65f 100644 --- a/sys/net/if_bridgevar.h +++ b/sys/net/if_bridgevar.h @@ -309,23 +309,20 @@ struct ifbpstpconf { (_sc)->sc_iflist_xcnt--; \ } while (0) -#define BRIDGE_INPUT(_ifp, _m) do { \ - KASSERT(bridge_input_p != NULL, \ +#define BRIDGE_INPUT(_ifp, _m) do { \ + KASSERT((_ifp)->if_bridge_input != NULL, \ ("%s: if_bridge not loaded!", __func__)); \ - _m = (*bridge_input_p)(_ifp, _m); \ + _m = (*(_ifp)->if_bridge_input)(_ifp, _m); \ if (_m != NULL) \ _ifp = _m->m_pkthdr.rcvif; \ } while (0) #define BRIDGE_OUTPUT(_ifp, _m, _err) do { \ - KASSERT(bridge_output_p != NULL, \ + KASSERT((_ifp)->if_bridge_output != NULL, \ ("%s: if_bridge not loaded!", __func__)); \ - _err = (*bridge_output_p)(_ifp, _m, NULL, NULL); \ + _err = (*(_ifp)->if_bridge_output)(_ifp, _m, NULL, NULL); \ } while (0) -extern struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *); -extern int (*bridge_output_p)(struct ifnet *, struct mbuf *, - struct sockaddr *, struct rtentry *); extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *); #endif /* _KERNEL */ diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 7c3146ade4f0..c149214c8661 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -102,9 +102,6 @@ void (*ng_ether_detach_p)(struct ifnet *ifp); void (*vlan_input_p)(struct ifnet *, struct mbuf *); /* if_bridge(4) support */ -struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *); -int (*bridge_output_p)(struct ifnet *, struct mbuf *, - struct sockaddr *, struct rtentry *); void (*bridge_dn_p)(struct mbuf *, struct ifnet *); /* if_lagg(4) support */ diff --git a/sys/net/if_var.h b/sys/net/if_var.h index c72f637ac04f..adfadead633b 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -321,6 +321,10 @@ struct ifnet { struct route *); void (*if_input) /* input routine (from h/w driver) */ (struct ifnet *, struct mbuf *); + struct mbuf *(*if_bridge_input)(struct ifnet *, struct mbuf *); + int (*if_bridge_output)(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); + void (*if_bridge_linkstate)(struct ifnet *ifp); if_start_fn_t if_start; /* initiate output routine */ if_ioctl_fn_t if_ioctl; /* ioctl routine */ if_init_fn_t if_init; /* Init routine */