summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorMichal Kubeček <mkubecek@suse.cz>2014-05-20 08:29:25 +0200
committerJiri Slaby <jslaby@suse.cz>2014-06-27 10:25:17 +0200
commit306ba5b24eab33ed30f13ff2005e021881b3d2bf (patch)
tree8fb1530fa97d6a97ec44aefa2f9b320654201330 /include
parente45145b6eb158405fe5cbbcce0a206d3b3090842 (diff)
vlan: more careful checksum features handling
commit da08143b85203b581f4a6461b149186b0e9592df upstream. When combining real_dev's features and vlan_features, simple bitwise AND is used. This doesn't work well for checksum offloading features as if one set has NETIF_F_HW_CSUM and the other NETIF_F_IP_CSUM and/or NETIF_F_IPV6_CSUM, we end up with no checksum offloading. However, from the logical point of view (how can_checksum_protocol() works), NETIF_F_HW_CSUM contains the functionality of NETIF_F_IP_CSUM and NETIF_F_IPV6_CSUM so that the result should be IP/IPV6. Add helper function netdev_intersect_features() implementing this logic and use it in vlan_dev_fix_features(). Signed-off-by: Michal Kubecek <mkubecek@suse.cz> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'include')
-rw-r--r--include/linux/netdevice.h14
1 files changed, 14 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9f2a0cbc7d06..51bfd7a68272 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2892,6 +2892,20 @@ extern const char *netdev_drivername(const struct net_device *dev);
extern void linkwatch_run_queue(void);
+static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
+ netdev_features_t f2)
+{
+ if (f1 & NETIF_F_GEN_CSUM)
+ f1 |= (NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);
+ if (f2 & NETIF_F_GEN_CSUM)
+ f2 |= (NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);
+ f1 &= f2;
+ if (f1 & NETIF_F_GEN_CSUM)
+ f1 &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);
+
+ return f1;
+}
+
static inline netdev_features_t netdev_get_wanted_features(
struct net_device *dev)
{