summaryrefslogtreecommitdiffstats
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2006-01-14 03:51:31 +0000
committerthompsa <thompsa@FreeBSD.org>2006-01-14 03:51:31 +0000
commitdfb4dff72d447694faafb9e0fe0ffb31863c7173 (patch)
treecf3a69e94b7d6d48da6db40cd0b9c13fda45922d /sys/net/if_bridge.c
parente634f0353637189d142075431b0c24910521d15e (diff)
downloadFreeBSD-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.c60
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;
OpenPOWER on IntegriCloud