diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2010-12-09 12:17:25 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-12-09 12:17:25 -0500 |
commit | d834a9dcecae834cd6b2bc5e50e1907738d9cf6a (patch) | |
tree | 0589d753465d3fe359ba451ba6cb7798df03aaa2 /net/8021q | |
parent | a38c5380ef9f088be9f49b6e4c5d80af8b1b5cd4 (diff) | |
parent | f658bcfb2607bf0808966a69cf74135ce98e5c2d (diff) |
Merge branch 'x86/amd-nb' into x86/apic-cleanups
Reason: apic cleanup series depends on x86/apic, x86/amd-nb x86/platform
Conflicts:
arch/x86/include/asm/io_apic.h
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'net/8021q')
-rw-r--r-- | net/8021q/vlan.c | 93 | ||||
-rw-r--r-- | net/8021q/vlan.h | 17 | ||||
-rw-r--r-- | net/8021q/vlan_core.c | 121 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 10 |
4 files changed, 57 insertions, 184 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index a2ad15250575..52077ca22072 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -44,9 +44,6 @@ | |||
44 | 44 | ||
45 | int vlan_net_id __read_mostly; | 45 | int vlan_net_id __read_mostly; |
46 | 46 | ||
47 | /* Our listing of VLAN group(s) */ | ||
48 | static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE]; | ||
49 | |||
50 | const char vlan_fullname[] = "802.1Q VLAN Support"; | 47 | const char vlan_fullname[] = "802.1Q VLAN Support"; |
51 | const char vlan_version[] = DRV_VERSION; | 48 | const char vlan_version[] = DRV_VERSION; |
52 | static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>"; | 49 | static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>"; |
@@ -59,40 +56,6 @@ static struct packet_type vlan_packet_type __read_mostly = { | |||
59 | 56 | ||
60 | /* End of global variables definitions. */ | 57 | /* End of global variables definitions. */ |
61 | 58 | ||
62 | static inline unsigned int vlan_grp_hashfn(unsigned int idx) | ||
63 | { | ||
64 | return ((idx >> VLAN_GRP_HASH_SHIFT) ^ idx) & VLAN_GRP_HASH_MASK; | ||
65 | } | ||
66 | |||
67 | /* Must be invoked with RCU read lock (no preempt) */ | ||
68 | static struct vlan_group *__vlan_find_group(struct net_device *real_dev) | ||
69 | { | ||
70 | struct vlan_group *grp; | ||
71 | struct hlist_node *n; | ||
72 | int hash = vlan_grp_hashfn(real_dev->ifindex); | ||
73 | |||
74 | hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) { | ||
75 | if (grp->real_dev == real_dev) | ||
76 | return grp; | ||
77 | } | ||
78 | |||
79 | return NULL; | ||
80 | } | ||
81 | |||
82 | /* Find the protocol handler. Assumes VID < VLAN_VID_MASK. | ||
83 | * | ||
84 | * Must be invoked with RCU read lock (no preempt) | ||
85 | */ | ||
86 | struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id) | ||
87 | { | ||
88 | struct vlan_group *grp = __vlan_find_group(real_dev); | ||
89 | |||
90 | if (grp) | ||
91 | return vlan_group_get_device(grp, vlan_id); | ||
92 | |||
93 | return NULL; | ||
94 | } | ||
95 | |||
96 | static void vlan_group_free(struct vlan_group *grp) | 59 | static void vlan_group_free(struct vlan_group *grp) |
97 | { | 60 | { |
98 | int i; | 61 | int i; |
@@ -111,8 +74,6 @@ static struct vlan_group *vlan_group_alloc(struct net_device *real_dev) | |||
111 | return NULL; | 74 | return NULL; |
112 | 75 | ||
113 | grp->real_dev = real_dev; | 76 | grp->real_dev = real_dev; |
114 | hlist_add_head_rcu(&grp->hlist, | ||
115 | &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]); | ||
116 | return grp; | 77 | return grp; |
117 | } | 78 | } |
118 | 79 | ||
@@ -151,7 +112,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) | |||
151 | 112 | ||
152 | ASSERT_RTNL(); | 113 | ASSERT_RTNL(); |
153 | 114 | ||
154 | grp = __vlan_find_group(real_dev); | 115 | grp = rtnl_dereference(real_dev->vlgrp); |
155 | BUG_ON(!grp); | 116 | BUG_ON(!grp); |
156 | 117 | ||
157 | /* Take it out of our own structures, but be sure to interlock with | 118 | /* Take it out of our own structures, but be sure to interlock with |
@@ -173,11 +134,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) | |||
173 | if (grp->nr_vlans == 0) { | 134 | if (grp->nr_vlans == 0) { |
174 | vlan_gvrp_uninit_applicant(real_dev); | 135 | vlan_gvrp_uninit_applicant(real_dev); |
175 | 136 | ||
176 | if (real_dev->features & NETIF_F_HW_VLAN_RX) | 137 | rcu_assign_pointer(real_dev->vlgrp, NULL); |
138 | if (ops->ndo_vlan_rx_register) | ||
177 | ops->ndo_vlan_rx_register(real_dev, NULL); | 139 | ops->ndo_vlan_rx_register(real_dev, NULL); |
178 | 140 | ||
179 | hlist_del_rcu(&grp->hlist); | ||
180 | |||
181 | /* Free the group, after all cpu's are done. */ | 141 | /* Free the group, after all cpu's are done. */ |
182 | call_rcu(&grp->rcu, vlan_rcu_free); | 142 | call_rcu(&grp->rcu, vlan_rcu_free); |
183 | } | 143 | } |
@@ -196,18 +156,13 @@ int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id) | |||
196 | return -EOPNOTSUPP; | 156 | return -EOPNOTSUPP; |
197 | } | 157 | } |
198 | 158 | ||
199 | if ((real_dev->features & NETIF_F_HW_VLAN_RX) && !ops->ndo_vlan_rx_register) { | ||
200 | pr_info("8021q: device %s has buggy VLAN hw accel\n", name); | ||
201 | return -EOPNOTSUPP; | ||
202 | } | ||
203 | |||
204 | if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && | 159 | if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && |
205 | (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) { | 160 | (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) { |
206 | pr_info("8021q: Device %s has buggy VLAN hw accel\n", name); | 161 | pr_info("8021q: Device %s has buggy VLAN hw accel\n", name); |
207 | return -EOPNOTSUPP; | 162 | return -EOPNOTSUPP; |
208 | } | 163 | } |
209 | 164 | ||
210 | if (__find_vlan_dev(real_dev, vlan_id) != NULL) | 165 | if (vlan_find_dev(real_dev, vlan_id) != NULL) |
211 | return -EEXIST; | 166 | return -EEXIST; |
212 | 167 | ||
213 | return 0; | 168 | return 0; |
@@ -222,7 +177,7 @@ int register_vlan_dev(struct net_device *dev) | |||
222 | struct vlan_group *grp, *ngrp = NULL; | 177 | struct vlan_group *grp, *ngrp = NULL; |
223 | int err; | 178 | int err; |
224 | 179 | ||
225 | grp = __vlan_find_group(real_dev); | 180 | grp = rtnl_dereference(real_dev->vlgrp); |
226 | if (!grp) { | 181 | if (!grp) { |
227 | ngrp = grp = vlan_group_alloc(real_dev); | 182 | ngrp = grp = vlan_group_alloc(real_dev); |
228 | if (!grp) | 183 | if (!grp) |
@@ -252,8 +207,11 @@ int register_vlan_dev(struct net_device *dev) | |||
252 | vlan_group_set_device(grp, vlan_id, dev); | 207 | vlan_group_set_device(grp, vlan_id, dev); |
253 | grp->nr_vlans++; | 208 | grp->nr_vlans++; |
254 | 209 | ||
255 | if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX) | 210 | if (ngrp) { |
256 | ops->ndo_vlan_rx_register(real_dev, ngrp); | 211 | if (ops->ndo_vlan_rx_register) |
212 | ops->ndo_vlan_rx_register(real_dev, ngrp); | ||
213 | rcu_assign_pointer(real_dev->vlgrp, ngrp); | ||
214 | } | ||
257 | if (real_dev->features & NETIF_F_HW_VLAN_FILTER) | 215 | if (real_dev->features & NETIF_F_HW_VLAN_FILTER) |
258 | ops->ndo_vlan_rx_add_vid(real_dev, vlan_id); | 216 | ops->ndo_vlan_rx_add_vid(real_dev, vlan_id); |
259 | 217 | ||
@@ -264,7 +222,6 @@ out_uninit_applicant: | |||
264 | vlan_gvrp_uninit_applicant(real_dev); | 222 | vlan_gvrp_uninit_applicant(real_dev); |
265 | out_free_group: | 223 | out_free_group: |
266 | if (ngrp) { | 224 | if (ngrp) { |
267 | hlist_del_rcu(&ngrp->hlist); | ||
268 | /* Free the group, after all cpu's are done. */ | 225 | /* Free the group, after all cpu's are done. */ |
269 | call_rcu(&ngrp->rcu, vlan_rcu_free); | 226 | call_rcu(&ngrp->rcu, vlan_rcu_free); |
270 | } | 227 | } |
@@ -321,7 +278,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) | |||
321 | if (new_dev == NULL) | 278 | if (new_dev == NULL) |
322 | return -ENOBUFS; | 279 | return -ENOBUFS; |
323 | 280 | ||
324 | new_dev->real_num_tx_queues = real_dev->real_num_tx_queues; | 281 | netif_copy_real_num_queues(new_dev, real_dev); |
325 | dev_net_set(new_dev, net); | 282 | dev_net_set(new_dev, net); |
326 | /* need 4 bytes for extra VLAN header info, | 283 | /* need 4 bytes for extra VLAN header info, |
327 | * hope the underlying device can handle it. | 284 | * hope the underlying device can handle it. |
@@ -428,7 +385,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
428 | dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0); | 385 | dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0); |
429 | } | 386 | } |
430 | 387 | ||
431 | grp = __vlan_find_group(dev); | 388 | grp = rtnl_dereference(dev->vlgrp); |
432 | if (!grp) | 389 | if (!grp) |
433 | goto out; | 390 | goto out; |
434 | 391 | ||
@@ -439,7 +396,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
439 | switch (event) { | 396 | switch (event) { |
440 | case NETDEV_CHANGE: | 397 | case NETDEV_CHANGE: |
441 | /* Propagate real device state to vlan devices */ | 398 | /* Propagate real device state to vlan devices */ |
442 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 399 | for (i = 0; i < VLAN_N_VID; i++) { |
443 | vlandev = vlan_group_get_device(grp, i); | 400 | vlandev = vlan_group_get_device(grp, i); |
444 | if (!vlandev) | 401 | if (!vlandev) |
445 | continue; | 402 | continue; |
@@ -450,7 +407,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
450 | 407 | ||
451 | case NETDEV_CHANGEADDR: | 408 | case NETDEV_CHANGEADDR: |
452 | /* Adjust unicast filters on underlying device */ | 409 | /* Adjust unicast filters on underlying device */ |
453 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 410 | for (i = 0; i < VLAN_N_VID; i++) { |
454 | vlandev = vlan_group_get_device(grp, i); | 411 | vlandev = vlan_group_get_device(grp, i); |
455 | if (!vlandev) | 412 | if (!vlandev) |
456 | continue; | 413 | continue; |
@@ -464,7 +421,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
464 | break; | 421 | break; |
465 | 422 | ||
466 | case NETDEV_CHANGEMTU: | 423 | case NETDEV_CHANGEMTU: |
467 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 424 | for (i = 0; i < VLAN_N_VID; i++) { |
468 | vlandev = vlan_group_get_device(grp, i); | 425 | vlandev = vlan_group_get_device(grp, i); |
469 | if (!vlandev) | 426 | if (!vlandev) |
470 | continue; | 427 | continue; |
@@ -478,7 +435,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
478 | 435 | ||
479 | case NETDEV_FEAT_CHANGE: | 436 | case NETDEV_FEAT_CHANGE: |
480 | /* Propagate device features to underlying device */ | 437 | /* Propagate device features to underlying device */ |
481 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 438 | for (i = 0; i < VLAN_N_VID; i++) { |
482 | vlandev = vlan_group_get_device(grp, i); | 439 | vlandev = vlan_group_get_device(grp, i); |
483 | if (!vlandev) | 440 | if (!vlandev) |
484 | continue; | 441 | continue; |
@@ -490,7 +447,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
490 | 447 | ||
491 | case NETDEV_DOWN: | 448 | case NETDEV_DOWN: |
492 | /* Put all VLANs for this dev in the down state too. */ | 449 | /* Put all VLANs for this dev in the down state too. */ |
493 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 450 | for (i = 0; i < VLAN_N_VID; i++) { |
494 | vlandev = vlan_group_get_device(grp, i); | 451 | vlandev = vlan_group_get_device(grp, i); |
495 | if (!vlandev) | 452 | if (!vlandev) |
496 | continue; | 453 | continue; |
@@ -508,7 +465,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
508 | 465 | ||
509 | case NETDEV_UP: | 466 | case NETDEV_UP: |
510 | /* Put all VLANs for this dev in the up state too. */ | 467 | /* Put all VLANs for this dev in the up state too. */ |
511 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 468 | for (i = 0; i < VLAN_N_VID; i++) { |
512 | vlandev = vlan_group_get_device(grp, i); | 469 | vlandev = vlan_group_get_device(grp, i); |
513 | if (!vlandev) | 470 | if (!vlandev) |
514 | continue; | 471 | continue; |
@@ -525,10 +482,14 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
525 | break; | 482 | break; |
526 | 483 | ||
527 | case NETDEV_UNREGISTER: | 484 | case NETDEV_UNREGISTER: |
485 | /* twiddle thumbs on netns device moves */ | ||
486 | if (dev->reg_state != NETREG_UNREGISTERING) | ||
487 | break; | ||
488 | |||
528 | /* Delete all VLANs for this dev. */ | 489 | /* Delete all VLANs for this dev. */ |
529 | grp->killall = 1; | 490 | grp->killall = 1; |
530 | 491 | ||
531 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 492 | for (i = 0; i < VLAN_N_VID; i++) { |
532 | vlandev = vlan_group_get_device(grp, i); | 493 | vlandev = vlan_group_get_device(grp, i); |
533 | if (!vlandev) | 494 | if (!vlandev) |
534 | continue; | 495 | continue; |
@@ -536,7 +497,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
536 | /* unregistration of last vlan destroys group, abort | 497 | /* unregistration of last vlan destroys group, abort |
537 | * afterwards */ | 498 | * afterwards */ |
538 | if (grp->nr_vlans == 1) | 499 | if (grp->nr_vlans == 1) |
539 | i = VLAN_GROUP_ARRAY_LEN; | 500 | i = VLAN_N_VID; |
540 | 501 | ||
541 | unregister_vlan_dev(vlandev, &list); | 502 | unregister_vlan_dev(vlandev, &list); |
542 | } | 503 | } |
@@ -742,8 +703,6 @@ err0: | |||
742 | 703 | ||
743 | static void __exit vlan_cleanup_module(void) | 704 | static void __exit vlan_cleanup_module(void) |
744 | { | 705 | { |
745 | unsigned int i; | ||
746 | |||
747 | vlan_ioctl_set(NULL); | 706 | vlan_ioctl_set(NULL); |
748 | vlan_netlink_fini(); | 707 | vlan_netlink_fini(); |
749 | 708 | ||
@@ -751,10 +710,6 @@ static void __exit vlan_cleanup_module(void) | |||
751 | 710 | ||
752 | dev_remove_pack(&vlan_packet_type); | 711 | dev_remove_pack(&vlan_packet_type); |
753 | 712 | ||
754 | /* This table must be empty if there are no module references left. */ | ||
755 | for (i = 0; i < VLAN_GRP_HASH_SIZE; i++) | ||
756 | BUG_ON(!hlist_empty(&vlan_group_hash[i])); | ||
757 | |||
758 | unregister_pernet_subsys(&vlan_net_ops); | 713 | unregister_pernet_subsys(&vlan_net_ops); |
759 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 714 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
760 | 715 | ||
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 8d9503ad01da..db01b3181fdc 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
@@ -72,23 +72,6 @@ static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev) | |||
72 | return netdev_priv(dev); | 72 | return netdev_priv(dev); |
73 | } | 73 | } |
74 | 74 | ||
75 | #define VLAN_GRP_HASH_SHIFT 5 | ||
76 | #define VLAN_GRP_HASH_SIZE (1 << VLAN_GRP_HASH_SHIFT) | ||
77 | #define VLAN_GRP_HASH_MASK (VLAN_GRP_HASH_SIZE - 1) | ||
78 | |||
79 | /* Find a VLAN device by the MAC address of its Ethernet device, and | ||
80 | * it's VLAN ID. The default configuration is to have VLAN's scope | ||
81 | * to be box-wide, so the MAC will be ignored. The mac will only be | ||
82 | * looked at if we are configured to have a separate set of VLANs per | ||
83 | * each MAC addressable interface. Note that this latter option does | ||
84 | * NOT follow the spec for VLANs, but may be useful for doing very | ||
85 | * large quantities of VLAN MUX/DEMUX onto FrameRelay or ATM PVCs. | ||
86 | * | ||
87 | * Must be invoked with rcu_read_lock (ie preempt disabled) | ||
88 | * or with RTNL. | ||
89 | */ | ||
90 | struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id); | ||
91 | |||
92 | /* found in vlan_dev.c */ | 75 | /* found in vlan_dev.c */ |
93 | int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | 76 | int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, |
94 | struct packet_type *ptype, struct net_device *orig_dev); | 77 | struct packet_type *ptype, struct net_device *orig_dev); |
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 0eb96f7e44be..69b2f79800a5 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
@@ -4,53 +4,29 @@ | |||
4 | #include <linux/netpoll.h> | 4 | #include <linux/netpoll.h> |
5 | #include "vlan.h" | 5 | #include "vlan.h" |
6 | 6 | ||
7 | /* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ | 7 | bool vlan_hwaccel_do_receive(struct sk_buff **skbp) |
8 | int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, | ||
9 | u16 vlan_tci, int polling) | ||
10 | { | 8 | { |
9 | struct sk_buff *skb = *skbp; | ||
10 | u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK; | ||
11 | struct net_device *vlan_dev; | 11 | struct net_device *vlan_dev; |
12 | u16 vlan_id; | 12 | struct vlan_rx_stats *rx_stats; |
13 | |||
14 | if (netpoll_rx(skb)) | ||
15 | return NET_RX_DROP; | ||
16 | |||
17 | if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master))) | ||
18 | skb->deliver_no_wcard = 1; | ||
19 | 13 | ||
20 | skb->skb_iif = skb->dev->ifindex; | 14 | vlan_dev = vlan_find_dev(skb->dev, vlan_id); |
21 | __vlan_hwaccel_put_tag(skb, vlan_tci); | 15 | if (!vlan_dev) { |
22 | vlan_id = vlan_tci & VLAN_VID_MASK; | 16 | if (vlan_id) |
23 | vlan_dev = vlan_group_get_device(grp, vlan_id); | 17 | skb->pkt_type = PACKET_OTHERHOST; |
24 | 18 | return false; | |
25 | if (vlan_dev) | ||
26 | skb->dev = vlan_dev; | ||
27 | else if (vlan_id) { | ||
28 | if (!(skb->dev->flags & IFF_PROMISC)) | ||
29 | goto drop; | ||
30 | skb->pkt_type = PACKET_OTHERHOST; | ||
31 | } | 19 | } |
32 | 20 | ||
33 | return (polling ? netif_receive_skb(skb) : netif_rx(skb)); | 21 | skb = *skbp = skb_share_check(skb, GFP_ATOMIC); |
22 | if (unlikely(!skb)) | ||
23 | return false; | ||
34 | 24 | ||
35 | drop: | 25 | skb->dev = vlan_dev; |
36 | dev_kfree_skb_any(skb); | 26 | skb->priority = vlan_get_ingress_priority(vlan_dev, skb->vlan_tci); |
37 | return NET_RX_DROP; | ||
38 | } | ||
39 | EXPORT_SYMBOL(__vlan_hwaccel_rx); | ||
40 | |||
41 | int vlan_hwaccel_do_receive(struct sk_buff *skb) | ||
42 | { | ||
43 | struct net_device *dev = skb->dev; | ||
44 | struct vlan_rx_stats *rx_stats; | ||
45 | |||
46 | skb->dev = vlan_dev_info(dev)->real_dev; | ||
47 | netif_nit_deliver(skb); | ||
48 | |||
49 | skb->dev = dev; | ||
50 | skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci); | ||
51 | skb->vlan_tci = 0; | 27 | skb->vlan_tci = 0; |
52 | 28 | ||
53 | rx_stats = this_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats); | 29 | rx_stats = this_cpu_ptr(vlan_dev_info(vlan_dev)->vlan_rx_stats); |
54 | 30 | ||
55 | u64_stats_update_begin(&rx_stats->syncp); | 31 | u64_stats_update_begin(&rx_stats->syncp); |
56 | rx_stats->rx_packets++; | 32 | rx_stats->rx_packets++; |
@@ -67,12 +43,13 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb) | |||
67 | * This allows the VLAN to have a different MAC than the | 43 | * This allows the VLAN to have a different MAC than the |
68 | * underlying device, and still route correctly. */ | 44 | * underlying device, and still route correctly. */ |
69 | if (!compare_ether_addr(eth_hdr(skb)->h_dest, | 45 | if (!compare_ether_addr(eth_hdr(skb)->h_dest, |
70 | dev->dev_addr)) | 46 | vlan_dev->dev_addr)) |
71 | skb->pkt_type = PACKET_HOST; | 47 | skb->pkt_type = PACKET_HOST; |
72 | break; | 48 | break; |
73 | } | 49 | } |
74 | u64_stats_update_end(&rx_stats->syncp); | 50 | u64_stats_update_end(&rx_stats->syncp); |
75 | return 0; | 51 | |
52 | return true; | ||
76 | } | 53 | } |
77 | 54 | ||
78 | struct net_device *vlan_dev_real_dev(const struct net_device *dev) | 55 | struct net_device *vlan_dev_real_dev(const struct net_device *dev) |
@@ -87,71 +64,27 @@ u16 vlan_dev_vlan_id(const struct net_device *dev) | |||
87 | } | 64 | } |
88 | EXPORT_SYMBOL(vlan_dev_vlan_id); | 65 | EXPORT_SYMBOL(vlan_dev_vlan_id); |
89 | 66 | ||
90 | static gro_result_t | 67 | /* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ |
91 | vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, | 68 | int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, |
92 | unsigned int vlan_tci, struct sk_buff *skb) | 69 | u16 vlan_tci, int polling) |
93 | { | 70 | { |
94 | struct sk_buff *p; | ||
95 | struct net_device *vlan_dev; | ||
96 | u16 vlan_id; | ||
97 | |||
98 | if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master))) | ||
99 | skb->deliver_no_wcard = 1; | ||
100 | |||
101 | skb->skb_iif = skb->dev->ifindex; | ||
102 | __vlan_hwaccel_put_tag(skb, vlan_tci); | 71 | __vlan_hwaccel_put_tag(skb, vlan_tci); |
103 | vlan_id = vlan_tci & VLAN_VID_MASK; | 72 | return polling ? netif_receive_skb(skb) : netif_rx(skb); |
104 | vlan_dev = vlan_group_get_device(grp, vlan_id); | ||
105 | |||
106 | if (vlan_dev) | ||
107 | skb->dev = vlan_dev; | ||
108 | else if (vlan_id) { | ||
109 | if (!(skb->dev->flags & IFF_PROMISC)) | ||
110 | goto drop; | ||
111 | skb->pkt_type = PACKET_OTHERHOST; | ||
112 | } | ||
113 | |||
114 | for (p = napi->gro_list; p; p = p->next) { | ||
115 | NAPI_GRO_CB(p)->same_flow = | ||
116 | p->dev == skb->dev && !compare_ether_header( | ||
117 | skb_mac_header(p), skb_gro_mac_header(skb)); | ||
118 | NAPI_GRO_CB(p)->flush = 0; | ||
119 | } | ||
120 | |||
121 | return dev_gro_receive(napi, skb); | ||
122 | |||
123 | drop: | ||
124 | return GRO_DROP; | ||
125 | } | 73 | } |
74 | EXPORT_SYMBOL(__vlan_hwaccel_rx); | ||
126 | 75 | ||
127 | gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, | 76 | gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, |
128 | unsigned int vlan_tci, struct sk_buff *skb) | 77 | unsigned int vlan_tci, struct sk_buff *skb) |
129 | { | 78 | { |
130 | if (netpoll_rx_on(skb)) | 79 | __vlan_hwaccel_put_tag(skb, vlan_tci); |
131 | return vlan_hwaccel_receive_skb(skb, grp, vlan_tci) | 80 | return napi_gro_receive(napi, skb); |
132 | ? GRO_DROP : GRO_NORMAL; | ||
133 | |||
134 | skb_gro_reset_offset(skb); | ||
135 | |||
136 | return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb); | ||
137 | } | 81 | } |
138 | EXPORT_SYMBOL(vlan_gro_receive); | 82 | EXPORT_SYMBOL(vlan_gro_receive); |
139 | 83 | ||
140 | gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, | 84 | gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, |
141 | unsigned int vlan_tci) | 85 | unsigned int vlan_tci) |
142 | { | 86 | { |
143 | struct sk_buff *skb = napi_frags_skb(napi); | 87 | __vlan_hwaccel_put_tag(napi->skb, vlan_tci); |
144 | 88 | return napi_gro_frags(napi); | |
145 | if (!skb) | ||
146 | return GRO_DROP; | ||
147 | |||
148 | if (netpoll_rx_on(skb)) { | ||
149 | skb->protocol = eth_type_trans(skb, skb->dev); | ||
150 | return vlan_hwaccel_receive_skb(skb, grp, vlan_tci) | ||
151 | ? GRO_DROP : GRO_NORMAL; | ||
152 | } | ||
153 | |||
154 | return napi_frags_finish(napi, skb, | ||
155 | vlan_gro_common(napi, grp, vlan_tci, skb)); | ||
156 | } | 89 | } |
157 | EXPORT_SYMBOL(vlan_gro_frags); | 90 | EXPORT_SYMBOL(vlan_gro_frags); |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 3bccdd12a264..14e3d1fa07a0 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -158,7 +158,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
158 | vlan_id = vlan_tci & VLAN_VID_MASK; | 158 | vlan_id = vlan_tci & VLAN_VID_MASK; |
159 | 159 | ||
160 | rcu_read_lock(); | 160 | rcu_read_lock(); |
161 | vlan_dev = __find_vlan_dev(dev, vlan_id); | 161 | vlan_dev = vlan_find_dev(dev, vlan_id); |
162 | 162 | ||
163 | /* If the VLAN device is defined, we use it. | 163 | /* If the VLAN device is defined, we use it. |
164 | * If not, and the VID is 0, it is a 802.1p packet (not | 164 | * If not, and the VID is 0, it is a 802.1p packet (not |
@@ -177,8 +177,8 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
177 | } else { | 177 | } else { |
178 | skb->dev = vlan_dev; | 178 | skb->dev = vlan_dev; |
179 | 179 | ||
180 | rx_stats = per_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats, | 180 | rx_stats = this_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats); |
181 | smp_processor_id()); | 181 | |
182 | u64_stats_update_begin(&rx_stats->syncp); | 182 | u64_stats_update_begin(&rx_stats->syncp); |
183 | rx_stats->rx_packets++; | 183 | rx_stats->rx_packets++; |
184 | rx_stats->rx_bytes += skb->len; | 184 | rx_stats->rx_bytes += skb->len; |
@@ -226,12 +226,14 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
226 | } | 226 | } |
227 | 227 | ||
228 | netif_rx(skb); | 228 | netif_rx(skb); |
229 | |||
229 | rcu_read_unlock(); | 230 | rcu_read_unlock(); |
230 | return NET_RX_SUCCESS; | 231 | return NET_RX_SUCCESS; |
231 | 232 | ||
232 | err_unlock: | 233 | err_unlock: |
233 | rcu_read_unlock(); | 234 | rcu_read_unlock(); |
234 | err_free: | 235 | err_free: |
236 | atomic_long_inc(&dev->rx_dropped); | ||
235 | kfree_skb(skb); | 237 | kfree_skb(skb); |
236 | return NET_RX_DROP; | 238 | return NET_RX_DROP; |
237 | } | 239 | } |
@@ -843,7 +845,7 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st | |||
843 | accum.rx_packets += rxpackets; | 845 | accum.rx_packets += rxpackets; |
844 | accum.rx_bytes += rxbytes; | 846 | accum.rx_bytes += rxbytes; |
845 | accum.rx_multicast += rxmulticast; | 847 | accum.rx_multicast += rxmulticast; |
846 | /* rx_errors is an ulong, not protected by syncp */ | 848 | /* rx_errors is ulong, not protected by syncp */ |
847 | accum.rx_errors += p->rx_errors; | 849 | accum.rx_errors += p->rx_errors; |
848 | } | 850 | } |
849 | stats->rx_packets = accum.rx_packets; | 851 | stats->rx_packets = accum.rx_packets; |