Date: Thu, 13 Jan 2011 14:42:30 +0200 From: Nikos Vassiliadis <nvass9573@gmx.com> To: FreeBSD virtualization mailing list <freebsd-virtualization@freebsd.org> Subject: if_bridge VIMAGE patch Message-ID: <4D2EF336.5010905@gmx.com>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------070506010102070101080107 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hi, Please, review the attached patch. It is against yesterday's HEAD and it virtualizes if_bridge. You can use the bridgetest script to create quickly a topology with redundant links to test STP. Thanks, Nikos --------------070506010102070101080107 Content-Type: text/plain; name="bridgetest.sh" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="bridgetest.sh" #!/bin/sh __macaddress__() ( openssl rand 5 | od -tx1 | sed '1s/0000000/0/; s/ */ /g; s/ *$//; s/ /:/g;q' ) __link__() ( a=$(($# - 1)) for f in `jot $a` do eval p$f=`ifconfig epair create | sed 's@a$@@'` done a=0 center=$1 shift for f in $* do a=$(($a + 1)) pair=`echo '$'p$a` pair=`eval echo $pair` ifconfig ${pair}a vnet $center jexec $center ifconfig ${pair}a description "link to $f" jexec $center ifconfig ${pair}a ether `__macaddress__` ifconfig ${pair}b vnet $f jexec $f ifconfig ${pair}b description "link to $center" jexec $f ifconfig ${pair}b ether `__macaddress__` done ) link() ( if [ $# -ne 2 ]; then echo can link only two nodes return 1 fi __link__ $* ) star() ( if [ $# -lt 3 ]; then echo three nodes at least are needed to form a star return 1 fi __link__ $* ) params=`csh -c 'echo rootbridge{1,2,3,4} bridge{1,2,3,4} pc{1,2,3,4}{1,2,3}'` apply 'jail -c vnet persist name=%1' $params star rootbridge1 rootbridge2 rootbridge3 rootbridge4 star rootbridge2 rootbridge3 rootbridge4 rootbridge1 star rootbridge3 rootbridge4 rootbridge1 rootbridge2 star rootbridge4 rootbridge1 rootbridge2 rootbridge3 star bridge1 rootbridge1 rootbridge2 star bridge2 rootbridge2 rootbridge3 star bridge3 rootbridge3 rootbridge4 star bridge4 rootbridge4 rootbridge1 for f in 1 2 3 4 do link bridge$f pc${f}1 link bridge$f pc${f}2 link bridge$f pc${f}3 done ## patching ends here for f in 1 2 3 4 5 6 7 8 do ifconfig bridge$f create done ifconfig bridge1 vnet rootbridge1 ifconfig bridge2 vnet rootbridge2 ifconfig bridge3 vnet rootbridge3 ifconfig bridge4 vnet rootbridge4 ifconfig bridge5 vnet bridge1 ifconfig bridge6 vnet bridge2 ifconfig bridge7 vnet bridge3 ifconfig bridge8 vnet bridge4 #jexec rootbridge1 ifconfig bridge1 create #jexec rootbridge2 ifconfig bridge2 create #jexec rootbridge3 ifconfig bridge3 create #jexec rootbridge4 ifconfig bridge4 create #jexec bridge1 ifconfig bridge5 create #jexec bridge2 ifconfig bridge6 create #jexec bridge3 ifconfig bridge7 create #jexec bridge4 ifconfig bridge8 create a=0 for f in `csh -c 'echo rootbridge{1,2,3,4} bridge{1,2,3,4}'` do a=$(($a + 1)) jexec $f ifconfig lo0 127.1 apply "jexec $f ifconfig %1 up" `jexec $f ifconfig -l` bridge=`jexec $f ifconfig -l | tr ' ' '\n' | grep bridge` apply "jexec $f ifconfig $bridge addm %1 stp %1" `jexec $f ifconfig -l | tr ' ' '\n' | grep epair` jexec $f ifconfig $bridge 10.16.0.$a done for f in `csh -c 'echo rootbridge{1,2,3,4}'` do bridge=`jexec $f ifconfig -l | tr ' ' '\n' | grep bridge` jexec $f ifconfig $bridge priority 16384 done for f in `csh -c 'echo pc{1,2,3,4}{1,2,3}'` do jexec $f ifconfig lo0 127.1 ip=`echo $f | sed 's/pc/10.255.0./'` jexec $f ifconfig `jexec $f ifconfig -l | tr ' ' '\n' | grep epair` $ip done --------------070506010102070101080107 Content-Type: text/plain; name="bridge.20110113.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="bridge.20110113.diff" Index: sys/net/if_bridge.c =================================================================== --- sys/net/if_bridge.c (revision 217337) +++ sys/net/if_bridge.c (working copy) @@ -332,6 +332,9 @@ #endif /* INET6 */ static int bridge_fragment(struct ifnet *, struct mbuf *, struct ether_header *, int, struct llc *); +#ifdef VIMAGE +static void bridge_reassign(struct ifnet *, struct vnet *, char *unused); +#endif /* The default bridge vlan is 1 (IEEE 802.1Q-2003 Table 9-2) */ #define VLANTAGOF(_m) \ @@ -345,30 +348,38 @@ SYSCTL_DECL(_net_link); SYSCTL_NODE(_net_link, IFT_BRIDGE, bridge, CTLFLAG_RW, 0, "Bridge"); -static int pfil_onlyip = 1; /* only pass IP[46] packets when pfil is enabled */ -static int pfil_bridge = 1; /* run pfil hooks on the bridge interface */ -static int pfil_member = 1; /* run pfil hooks on the member interface */ -static int pfil_ipfw = 0; /* layer2 filter with ipfw */ -static int pfil_ipfw_arp = 0; /* layer2 filter with ipfw */ -static int pfil_local_phys = 0; /* run pfil hooks on the physical interface for +static VNET_DEFINE(int, pfil_onlyip) = 1; /* only pass IP[46] packets when pfil is enabled */ +static VNET_DEFINE(int, pfil_bridge) = 1; /* run pfil hooks on the bridge interface */ +static VNET_DEFINE(int, pfil_member) = 1; /* run pfil hooks on the member interface */ +static VNET_DEFINE(int, pfil_ipfw) = 0; /* layer2 filter with ipfw */ +static VNET_DEFINE(int, pfil_ipfw_arp) = 0; /* layer2 filter with ipfw */ +static VNET_DEFINE(int, pfil_local_phys) = 0; /* run pfil hooks on the physical interface for locally destined packets */ -static int log_stp = 0; /* log STP state changes */ -static int bridge_inherit_mac = 0; /* share MAC with first bridge member */ -SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip, CTLFLAG_RW, - &pfil_onlyip, 0, "Only pass IP packets when pfil is enabled"); -SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp, CTLFLAG_RW, - &pfil_ipfw_arp, 0, "Filter ARP packets through IPFW layer2"); -SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge, CTLFLAG_RW, - &pfil_bridge, 0, "Packet filter on the bridge interface"); -SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member, CTLFLAG_RW, - &pfil_member, 0, "Packet filter on the member interface"); -SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_local_phys, CTLFLAG_RW, - &pfil_local_phys, 0, +static VNET_DEFINE(int, log_stp) = 0; /* log STP state changes */ +static VNET_DEFINE(int, bridge_inherit_mac) = 0; /* share MAC with first bridge member */ +#define V_pfil_onlyip VNET(pfil_onlyip) +#define V_pfil_bridge VNET(pfil_bridge) +#define V_pfil_member VNET(pfil_member) +#define V_pfil_ipfw VNET(pfil_ipfw) +#define V_pfil_ipfw_arp VNET(pfil_ipfw_arp) +#define V_pfil_local_phys VNET(pfil_local_phys) +#define V_log_stp VNET(log_stp) +#define V_bridge_inherit_mac VNET(bridge_inherit_mac) +SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, pfil_onlyip, CTLFLAG_RW, + &VNET_NAME(pfil_onlyip), 0, "Only pass IP packets when pfil is enabled"); +SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, ipfw_arp, CTLFLAG_RW, + &VNET_NAME(pfil_ipfw_arp), 0, "Filter ARP packets through IPFW layer2"); +SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, pfil_bridge, CTLFLAG_RW, + &VNET_NAME(pfil_bridge), 0, "Packet filter on the bridge interface"); +SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, pfil_member, CTLFLAG_RW, + &VNET_NAME(pfil_member), 0, "Packet filter on the member interface"); +SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, pfil_local_phys, CTLFLAG_RW, + &VNET_NAME(pfil_local_phys), 0, "Packet filter on the physical interface for locally destined packets"); -SYSCTL_INT(_net_link_bridge, OID_AUTO, log_stp, CTLFLAG_RW, - &log_stp, 0, "Log STP state changes"); -SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac, CTLFLAG_RW, - &bridge_inherit_mac, 0, +SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, log_stp, CTLFLAG_RW, + &VNET_NAME(log_stp), 0, "Log STP state changes"); +SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, inherit_mac, CTLFLAG_RW, + &VNET_NAME(bridge_inherit_mac), 0, "Inherit MAC address from the first bridge member"); struct bridge_control { @@ -523,14 +534,14 @@ static int sysctl_pfil_ipfw(SYSCTL_HANDLER_ARGS) { - int enable = pfil_ipfw; + int enable = V_pfil_ipfw; int error; error = sysctl_handle_int(oidp, &enable, 0, req); enable = (enable) ? 1 : 0; - if (enable != pfil_ipfw) { - pfil_ipfw = enable; + if (enable != V_pfil_ipfw) { + V_pfil_ipfw = enable; /* * Disable pfil so that ipfw doesnt run twice, if the user @@ -538,17 +549,17 @@ * pfil_member. Also allow non-ip packets as ipfw can filter by * layer2 type. */ - if (pfil_ipfw) { - pfil_onlyip = 0; - pfil_bridge = 0; - pfil_member = 0; + if (V_pfil_ipfw) { + V_pfil_onlyip = 0; + V_pfil_bridge = 0; + V_pfil_member = 0; } } return (error); } -SYSCTL_PROC(_net_link_bridge, OID_AUTO, ipfw, CTLTYPE_INT|CTLFLAG_RW, - &pfil_ipfw, 0, &sysctl_pfil_ipfw, "I", "Layer2 filter with IPFW"); +SYSCTL_VNET_PROC(_net_link_bridge, OID_AUTO, ipfw, CTLTYPE_INT|CTLFLAG_RW, + &VNET_NAME(pfil_ipfw), 0, &sysctl_pfil_ipfw, "I", "Layer2 filter with IPFW"); /* * bridge_clone_create: @@ -620,6 +631,11 @@ /* Now undo some of the damage... */ ifp->if_baudrate = 0; ifp->if_type = IFT_BRIDGE; +#ifdef VIMAGE + ifp->if_reassign = bridge_reassign; +#else + ifp->if_reassign = NULL; +#endif mtx_lock(&bridge_list_mtx); LIST_INSERT_HEAD(&bridge_list, sc, sc_list); @@ -923,7 +939,7 @@ * the mac address of the bridge to the address of the next member, or * to its default address if no members are left. */ - if (bridge_inherit_mac && sc->sc_ifaddr == ifs) { + if (V_bridge_inherit_mac && sc->sc_ifaddr == ifs) { if (LIST_EMPTY(&sc->sc_iflist)) { bcopy(sc->sc_defaddr, IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); @@ -1046,7 +1062,7 @@ * member and the MAC address of the bridge has not been changed from * the default randomly generated one. */ - if (bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) && + if (V_bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) && !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN)) { bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = ifs; @@ -2279,7 +2295,7 @@ ETHER_BPF_MTAP(iface, m); \ iface->if_ipackets++; \ /* Filter on the physical interface. */ \ - if (pfil_local_phys && \ + if (V_pfil_local_phys && \ (PFIL_HOOKED(&V_inet_pfil_hook) \ OR_PFIL_HOOKED_INET6)) { \ if (bridge_pfil(&m, NULL, ifp, \ @@ -2937,9 +2953,11 @@ "discarding" }; - if (log_stp) + CURVNET_SET(ifp->if_vnet); + if (V_log_stp) log(LOG_NOTICE, "%s: state changed to %s on %s\n", sc->sc_ifp->if_xname, stpstates[state], ifp->if_xname); + CURVNET_RESTORE(); } /* @@ -2966,7 +2984,7 @@ KASSERT(M_WRITABLE(*mp), ("%s: modifying a shared mbuf", __func__)); #endif - if (pfil_bridge == 0 && pfil_member == 0 && pfil_ipfw == 0) + if (V_pfil_bridge == 0 && V_pfil_member == 0 && V_pfil_ipfw == 0) return (0); /* filtering is disabled */ i = min((*mp)->m_pkthdr.len, max_protohdr); @@ -3008,7 +3026,7 @@ switch (ether_type) { case ETHERTYPE_ARP: case ETHERTYPE_REVARP: - if (pfil_ipfw_arp == 0) + if (V_pfil_ipfw_arp == 0) return (0); /* Automatically pass */ break; @@ -3023,7 +3041,7 @@ * packets, these will not be checked by pfil(9) and * passed unconditionally so the default is to drop. */ - if (pfil_onlyip) + if (V_pfil_onlyip) goto bad; } @@ -3059,7 +3077,7 @@ /* XXX this section is also in if_ethersubr.c */ // XXX PFIL_OUT or DIR_OUT ? - if (V_ip_fw_chk_ptr && pfil_ipfw != 0 && + if (V_ip_fw_chk_ptr && V_pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) { struct m_tag *mtag; @@ -3136,21 +3154,21 @@ * Keep the order: * in_if -> bridge_if -> out_if */ - if (pfil_bridge && dir == PFIL_OUT && bifp != NULL) + if (V_pfil_bridge && dir == PFIL_OUT && bifp != NULL) error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp, dir, NULL); if (*mp == NULL || error != 0) /* filter may consume */ break; - if (pfil_member && ifp != NULL) + if (V_pfil_member && ifp != NULL) error = pfil_run_hooks(&V_inet_pfil_hook, mp, ifp, dir, NULL); if (*mp == NULL || error != 0) /* filter may consume */ break; - if (pfil_bridge && dir == PFIL_IN && bifp != NULL) + if (V_pfil_bridge && dir == PFIL_IN && bifp != NULL) error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp, dir, NULL); @@ -3158,7 +3176,7 @@ break; /* check if we need to fragment the packet */ - if (pfil_member && ifp != NULL && dir == PFIL_OUT) { + if (V_pfil_member && ifp != NULL && dir == PFIL_OUT) { i = (*mp)->m_pkthdr.len; if (i > ifp->if_mtu) { error = bridge_fragment(ifp, *mp, &eh2, snap, @@ -3190,21 +3208,21 @@ break; #ifdef INET6 case ETHERTYPE_IPV6: - if (pfil_bridge && dir == PFIL_OUT && bifp != NULL) + if (V_pfil_bridge && dir == PFIL_OUT && bifp != NULL) error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp, dir, NULL); if (*mp == NULL || error != 0) /* filter may consume */ break; - if (pfil_member && ifp != NULL) + if (V_pfil_member && ifp != NULL) error = pfil_run_hooks(&V_inet6_pfil_hook, mp, ifp, dir, NULL); if (*mp == NULL || error != 0) /* filter may consume */ break; - if (pfil_bridge && dir == PFIL_IN && bifp != NULL) + if (V_pfil_bridge && dir == PFIL_IN && bifp != NULL) error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp, dir, NULL); break; @@ -3454,3 +3472,26 @@ m_freem(m); return (error); } + +#ifdef VIMAGE +void +bridge_reassign(struct ifnet *ifp, struct vnet *new_vnet, char *unused __unused) +{ + struct bridge_softc *sc = ifp->if_softc; + struct bridge_iflist *bif; + + BRIDGE_LOCK(sc); + + bridge_stop(ifp, 1); + ifp->if_flags &= ~IFF_UP; + + while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL) + bridge_delete_member(sc, bif, 0); + + while ((bif = LIST_FIRST(&sc->sc_spanlist)) != NULL) { + bridge_delete_span(sc, bif); + } + + BRIDGE_UNLOCK(sc); +} +#endif /* VIMAGE */ Index: sys/net/bridgestp.c =================================================================== --- sys/net/bridgestp.c (revision 217337) +++ sys/net/bridgestp.c (working copy) @@ -1804,12 +1804,19 @@ bzero((char *)&ifmr, sizeof(ifmr)); error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr); - if ((error == 0) && (ifp->if_flags & IFF_UP)) { - if (ifmr.ifm_status & IFM_ACTIVE) { + if (ifp->if_flags & IFF_UP) { + if (ifp->if_link_state == LINK_STATE_UP) { /* A full-duplex link is assumed to be point to point */ if (bp->bp_flags & BSTP_PORT_AUTOPTP) { - bp->bp_ptp_link = - ifmr.ifm_active & IFM_FDX ? 1 : 0; + /* Interfaces that do not support ifmedia, + * are assumed to be full-duplex. if_epair + * and ng_eiface fall into this category. + */ + if (error == 0) + bp->bp_ptp_link = + ifmr.ifm_active & IFM_FDX ? 1 : 0; + else if (error == EINVAL) + bp->bp_ptp_link = 1; } /* Calc the cost if the link was down previously */ --------------070506010102070101080107--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4D2EF336.5010905>