diff options
author | thompsa <thompsa@FreeBSD.org> | 2006-01-14 03:51:31 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2006-01-14 03:51:31 +0000 |
commit | dfb4dff72d447694faafb9e0fe0ffb31863c7173 (patch) | |
tree | cf3a69e94b7d6d48da6db40cd0b9c13fda45922d /sys/net/if_bridge.c | |
parent | e634f0353637189d142075431b0c24910521d15e (diff) | |
download | FreeBSD-src-dfb4dff72d447694faafb9e0fe0ffb31863c7173.zip FreeBSD-src-dfb4dff72d447694faafb9e0fe0ffb31863c7173.tar.gz |
Add code that clears certain capabilities from the member interface, these are
restored when its removed from the bridge.
At the moment we only clear IFCAP_TXCSUM. Since a locally generated packet on
the bridge may be sent out any one or more interfaces it cant be assumed that
every card does hardware csums. Most bridges don't generate a lot of traffic
themselves so turning off offloading won't hurt, bridged packets are
unaffected.
Tested by: Bruce Walker (bmw borderware.com)
MFC after: 5 days
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r-- | sys/net/if_bridge.c | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index ad462ae..1b0875b 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -170,6 +170,11 @@ __FBSDID("$FreeBSD$"); #define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60) #endif +/* + * List of capabilities to mask on the member interface. + */ +#define BRIDGE_IFCAPS_MASK IFCAP_TXCSUM + static struct mtx bridge_list_mtx; eventhandler_tag bridge_detach_cookie = NULL; @@ -181,6 +186,7 @@ static int bridge_clone_create(struct if_clone *, int); static void bridge_clone_destroy(struct ifnet *); static int bridge_ioctl(struct ifnet *, u_long, caddr_t); +static void bridge_mutecaps(struct bridge_iflist *, int); static void bridge_ifdetach(void *arg __unused, struct ifnet *); static void bridge_init(void *); static void bridge_dummynet(struct mbuf *, struct ifnet *); @@ -665,6 +671,42 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } /* + * bridge_mutecaps: + * + * Clear or restore unwanted capabilities on the member interface + */ +static void +bridge_mutecaps(struct bridge_iflist *bif, int mute) +{ + struct ifnet *ifp = bif->bif_ifp; + struct ifreq ifr; + int error; + + if (ifp->if_ioctl == NULL) + return; + + bzero(&ifr, sizeof ifr); + ifr.ifr_reqcap = ifp->if_capenable; + + if (mute) { + /* mask off and save capabilities */ + bif->bif_mutecap = ifr.ifr_reqcap & BRIDGE_IFCAPS_MASK; + if (bif->bif_mutecap != 0) + ifr.ifr_reqcap &= ~BRIDGE_IFCAPS_MASK; + } else + /* restore muted capabilities */ + ifr.ifr_reqcap |= bif->bif_mutecap; + + + if (bif->bif_mutecap != 0) { + IFF_LOCKGIANT(ifp); + error = (*ifp->if_ioctl)(ifp, SIOCSIFCAP, (caddr_t)&ifr); + IFF_UNLOCKGIANT(ifp); + } +} + + +/* * bridge_lookup_member: * * Lookup a bridge member interface. @@ -727,6 +769,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, * Take the interface out of promiscuous mode. */ (void) ifpromisc(ifs, 0); + bridge_mutecaps(bif, 0); break; case IFT_GIF: @@ -810,6 +853,11 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) if (bif == NULL) return (ENOMEM); + bif->bif_ifp = ifs; + bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; + bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY; + bif->bif_path_cost = BSTP_DEFAULT_PATH_COST; + switch (ifs->if_type) { case IFT_ETHER: case IFT_L2VLAN: @@ -819,6 +867,8 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) error = ifpromisc(ifs, 1); if (error) goto out; + + bridge_mutecaps(bif, 1); break; case IFT_GIF: @@ -829,11 +879,6 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) goto out; } - bif->bif_ifp = ifs; - bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; - bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY; - bif->bif_path_cost = BSTP_DEFAULT_PATH_COST; - ifs->if_bridge = sc; /* * XXX: XLOCK HERE!?! @@ -1436,11 +1481,6 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m) int len, err; short mflags; - /* - * Clear any in-bound checksum flags for this packet. - */ - m->m_pkthdr.csum_flags = 0; - len = m->m_pkthdr.len; mflags = m->m_flags; |