diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-08-10 15:47:58 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-08-13 22:52:14 -0700 |
commit | 7f353bf29e162459f2f1e2ca25e41011fae65241 (patch) | |
tree | 8df6d6c66b69f18d521f76018ff98706e4e2a1b3 /net/bridge | |
parent | f71417614d63932cf56ed98a0947568d6259d11e (diff) |
[NET]: Share correct feature code between bridging and bonding
http://bugzilla.kernel.org/show_bug.cgi?id=8797 shows that the
bonding driver may produce bogus combinations of the checksum
flags and SG/TSO.
For example, if you bond devices with NETIF_F_HW_CSUM and
NETIF_F_IP_CSUM you'll end up with a bonding device that
has neither flag set. If both have TSO then this produces
an illegal combination.
The bridge device on the other hand has the correct code to
deal with this.
In fact, the same code can be used for both. So this patch
moves that logic into net/core/dev.c and uses it for both
bonding and bridging.
In the process I've made small adjustments such as only
setting GSO_ROBUST if at least one constituent device
supports it.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_device.c | 2 | ||||
-rw-r--r-- | net/bridge/br_if.c | 36 |
2 files changed, 5 insertions, 33 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 5e1892d8d87..0eded176ce9 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -179,5 +179,5 @@ void br_dev_setup(struct net_device *dev) dev->priv_flags = IFF_EBRIDGE; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | - NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST; + NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX; } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index b40dada002b..749f0e8f541 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -349,43 +349,15 @@ int br_min_mtu(const struct net_bridge *br) void br_features_recompute(struct net_bridge *br) { struct net_bridge_port *p; - unsigned long features, checksum; + unsigned long features; - checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0; - features = br->feature_mask & ~NETIF_F_ALL_CSUM; + features = br->feature_mask; list_for_each_entry(p, &br->port_list, list) { - unsigned long feature = p->dev->features; - - /* if device needs checksumming, downgrade to hw checksumming */ - if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM)) - checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; - - /* if device can't do all checksum, downgrade to ipv4/ipv6 */ - if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM)) - checksum ^= NETIF_F_HW_CSUM - | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - - if (checksum & NETIF_F_IPV6_CSUM && !(feature & NETIF_F_IPV6_CSUM)) - checksum &= ~NETIF_F_IPV6_CSUM; - - if (!(feature & NETIF_F_IP_CSUM)) - checksum = 0; - - if (feature & NETIF_F_GSO) - feature |= NETIF_F_GSO_SOFTWARE; - feature |= NETIF_F_GSO; - - features &= feature; + features = netdev_compute_features(features, p->dev->features); } - if (!(checksum & NETIF_F_ALL_CSUM)) - features &= ~NETIF_F_SG; - if (!(features & NETIF_F_SG)) - features &= ~NETIF_F_GSO_MASK; - - br->dev->features = features | checksum | NETIF_F_LLTX | - NETIF_F_GSO_ROBUST; + br->dev->features = features; } /* called with RTNL */ |