diff options
-rw-r--r-- | include/linux/netdevice.h | 6 | ||||
-rw-r--r-- | net/8021q/vlan.c | 30 | ||||
-rw-r--r-- | net/8021q/vlan.h | 2 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 5 |
4 files changed, 41 insertions, 2 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b11e6e19e96c..2b0266484c84 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -514,10 +514,12 @@ struct net_device | |||
514 | #define NETIF_F_NETNS_LOCAL 8192 /* Does not change network namespaces */ | 514 | #define NETIF_F_NETNS_LOCAL 8192 /* Does not change network namespaces */ |
515 | #define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */ | 515 | #define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */ |
516 | #define NETIF_F_LRO 32768 /* large receive offload */ | 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 | /* Segmentation offload features */ | 520 | /* Segmentation offload features */ |
519 | #define NETIF_F_GSO_SHIFT 16 | 521 | #define NETIF_F_GSO_SHIFT 20 |
520 | #define NETIF_F_GSO_MASK 0xffff0000 | 522 | #define NETIF_F_GSO_MASK 0xfff00000 |
521 | #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) | 523 | #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) |
522 | #define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT) | 524 | #define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT) |
523 | #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) | 525 | #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index b934159a6f07..51961300b586 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -382,6 +382,24 @@ static void vlan_sync_address(struct net_device *dev, | |||
382 | memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); | 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 | static void __vlan_device_event(struct net_device *dev, unsigned long event) | 403 | static void __vlan_device_event(struct net_device *dev, unsigned long event) |
386 | { | 404 | { |
387 | switch (event) { | 405 | switch (event) { |
@@ -448,6 +466,18 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
448 | } | 466 | } |
449 | break; | 467 | break; |
450 | 468 | ||
469 | case NETDEV_FEAT_CHANGE: | ||
470 | /* Propagate device features to underlying device */ | ||
471 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | ||
472 | vlandev = vlan_group_get_device(grp, i); | ||
473 | if (!vlandev) | ||
474 | continue; | ||
475 | |||
476 | vlan_transfer_features(dev, vlandev); | ||
477 | } | ||
478 | |||
479 | break; | ||
480 | |||
451 | case NETDEV_DOWN: | 481 | case NETDEV_DOWN: |
452 | /* Put all VLANs for this dev in the down state too. */ | 482 | /* Put all VLANs for this dev in the down state too. */ |
453 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 483 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { |
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 5229a72c7ea1..79625696e86a 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
@@ -7,6 +7,8 @@ | |||
7 | #define VLAN_GRP_HASH_SIZE (1 << VLAN_GRP_HASH_SHIFT) | 7 | #define VLAN_GRP_HASH_SIZE (1 << VLAN_GRP_HASH_SHIFT) |
8 | #define VLAN_GRP_HASH_MASK (VLAN_GRP_HASH_SIZE - 1) | 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 | /* Find a VLAN device by the MAC address of its Ethernet device, and | 12 | /* Find a VLAN device by the MAC address of its Ethernet device, and |
11 | * it's VLAN ID. The default configuration is to have VLAN's scope | 13 | * it's VLAN ID. The default configuration is to have VLAN's scope |
12 | * to be box-wide, so the MAC will be ignored. The mac will only be | 14 | * to be box-wide, so the MAC will be ignored. The mac will only be |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index c961f0826005..b1cfbaa88db2 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -663,6 +663,11 @@ static int vlan_dev_init(struct net_device *dev) | |||
663 | (1<<__LINK_STATE_DORMANT))) | | 663 | (1<<__LINK_STATE_DORMANT))) | |
664 | (1<<__LINK_STATE_PRESENT); | 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 | /* ipv6 shared card related stuff */ | 671 | /* ipv6 shared card related stuff */ |
667 | dev->dev_id = real_dev->dev_id; | 672 | dev->dev_id = real_dev->dev_id; |
668 | 673 | ||