if_bridge VIMAGE patch
Nikos Vassiliadis
nvass9573 at gmx.com
Thu Jan 13 12:44:00 UTC 2011
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
-------------- next part --------------
#!/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 at 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
-------------- next part --------------
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 */
More information about the freebsd-virtualization
mailing list