Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da08143b authored by Michal Kubeček's avatar Michal Kubeček Committed by David S. Miller
Browse files

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: default avatarMichal Kubecek <mkubecek@suse.cz>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 98a6eeb8
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -3153,6 +3153,20 @@ const char *netdev_drivername(const struct net_device *dev);

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)
{
+2 −2
Original line number Diff line number Diff line
@@ -678,9 +678,9 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
	netdev_features_t old_features = features;

	features &= real_dev->vlan_features;
	features = netdev_intersect_features(features, real_dev->vlan_features);
	features |= NETIF_F_RXCSUM;
	features &= real_dev->features;
	features = netdev_intersect_features(features, real_dev->features);

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