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 <mkubecek@suse.cz> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								98a6eeb8f5
							
						
					
				
			
			
				commit
				
					
						da08143b85
					
				
			
		
					 2 changed files with 16 additions and 2 deletions
				
			
		|  | @ -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) | ||||
| { | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Michal Kubeček
				Michal Kubeček