Skip to content

Commit da08143

Browse files
mkubecekdavem330
authored andcommitted
vlan: more careful checksum features handling
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 98a6eeb commit da08143

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

include/linux/netdevice.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3153,6 +3153,20 @@ const char *netdev_drivername(const struct net_device *dev);
31533153

31543154
void linkwatch_run_queue(void);
31553155

3156+
static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
3157+
netdev_features_t f2)
3158+
{
3159+
if (f1 & NETIF_F_GEN_CSUM)
3160+
f1 |= (NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);
3161+
if (f2 & NETIF_F_GEN_CSUM)
3162+
f2 |= (NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);
3163+
f1 &= f2;
3164+
if (f1 & NETIF_F_GEN_CSUM)
3165+
f1 &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);
3166+
3167+
return f1;
3168+
}
3169+
31563170
static inline netdev_features_t netdev_get_wanted_features(
31573171
struct net_device *dev)
31583172
{

net/8021q/vlan_dev.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,9 +678,9 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
678678
struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
679679
netdev_features_t old_features = features;
680680

681-
features &= real_dev->vlan_features;
681+
features = netdev_intersect_features(features, real_dev->vlan_features);
682682
features |= NETIF_F_RXCSUM;
683-
features &= real_dev->features;
683+
features = netdev_intersect_features(features, real_dev->features);
684684

685685
features |= old_features & NETIF_F_SOFT_FEATURES;
686686
features |= NETIF_F_LLTX;

0 commit comments

Comments
 (0)