[VLAN]: Propagate selected feature bits to VLAN devices

Propagate feature bits from the NETDEV_FEAT_CHANGE notifier. For now
only TSO is propagated for devices that announce their ability to
support TSO in combination with VLAN accel by setting the NETIF_F_VLAN_TSO
flag.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Patrick McHardy and committed by
David S. Miller
5fb13570 7ff6e6f7

+41 -2
+4 -2
include/linux/netdevice.h
··· 514 514 #define NETIF_F_NETNS_LOCAL 8192 /* Does not change network namespaces */ 515 515 #define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */ 516 516 #define NETIF_F_LRO 32768 /* large receive offload */ 517 + #define NETIF_F_VLAN_TSO 65536 /* Supports TSO for VLANs */ 518 + #define NETIF_F_VLAN_CSUM 131072 /* Supports TX checksumming for VLANs */ 517 519 518 520 /* Segmentation offload features */ 519 - #define NETIF_F_GSO_SHIFT 16 520 - #define NETIF_F_GSO_MASK 0xffff0000 521 + #define NETIF_F_GSO_SHIFT 20 522 + #define NETIF_F_GSO_MASK 0xfff00000 521 523 #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) 522 524 #define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT) 523 525 #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
+30
net/8021q/vlan.c
··· 382 382 memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); 383 383 } 384 384 385 + static void vlan_transfer_features(struct net_device *dev, 386 + struct net_device *vlandev) 387 + { 388 + unsigned long old_features = vlandev->features; 389 + 390 + if (dev->features & NETIF_F_VLAN_TSO) { 391 + vlandev->features &= ~VLAN_TSO_FEATURES; 392 + vlandev->features |= dev->features & VLAN_TSO_FEATURES; 393 + } 394 + if (dev->features & NETIF_F_VLAN_CSUM) { 395 + vlandev->features &= ~NETIF_F_ALL_CSUM; 396 + vlandev->features |= dev->features & NETIF_F_ALL_CSUM; 397 + } 398 + 399 + if (old_features != vlandev->features) 400 + netdev_features_change(vlandev); 401 + } 402 + 385 403 static void __vlan_device_event(struct net_device *dev, unsigned long event) 386 404 { 387 405 switch (event) { ··· 464 446 465 447 vlan_sync_address(dev, vlandev); 466 448 } 449 + break; 450 + 451 + case NETDEV_FEAT_CHANGE: 452 + /* Propagate device features to underlying device */ 453 + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 454 + vlandev = vlan_group_get_device(grp, i); 455 + if (!vlandev) 456 + continue; 457 + 458 + vlan_transfer_features(dev, vlandev); 459 + } 460 + 467 461 break; 468 462 469 463 case NETDEV_DOWN:
+2
net/8021q/vlan.h
··· 7 7 #define VLAN_GRP_HASH_SIZE (1 << VLAN_GRP_HASH_SHIFT) 8 8 #define VLAN_GRP_HASH_MASK (VLAN_GRP_HASH_SIZE - 1) 9 9 10 + #define VLAN_TSO_FEATURES (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG) 11 + 10 12 /* Find a VLAN device by the MAC address of its Ethernet device, and 11 13 * it's VLAN ID. The default configuration is to have VLAN's scope 12 14 * to be box-wide, so the MAC will be ignored. The mac will only be
+5
net/8021q/vlan_dev.c
··· 663 663 (1<<__LINK_STATE_DORMANT))) | 664 664 (1<<__LINK_STATE_PRESENT); 665 665 666 + if (real_dev->features & NETIF_F_VLAN_TSO) 667 + dev->features |= real_dev->features & VLAN_TSO_FEATURES; 668 + if (real_dev->features & NETIF_F_VLAN_CSUM) 669 + dev->features |= real_dev->features & NETIF_F_ALL_CSUM; 670 + 666 671 /* ipv6 shared card related stuff */ 667 672 dev->dev_id = real_dev->dev_id; 668 673