diff options
Diffstat (limited to 'net/8021q')
-rw-r--r-- | net/8021q/vlan.c | 6 | ||||
-rw-r--r-- | net/8021q/vlan.h | 2 | ||||
-rw-r--r-- | net/8021q/vlan_core.c | 16 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 13 |
4 files changed, 25 insertions, 12 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index a2ad1525057..25c21332e9c 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -321,7 +321,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) if (new_dev == NULL) return -ENOBUFS; - new_dev->real_num_tx_queues = real_dev->real_num_tx_queues; + netif_copy_real_num_queues(new_dev, real_dev); dev_net_set(new_dev, net); /* need 4 bytes for extra VLAN header info, * hope the underlying device can handle it. @@ -525,6 +525,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, break; case NETDEV_UNREGISTER: + /* twiddle thumbs on netns device moves */ + if (dev->reg_state != NETREG_UNREGISTERING) + break; + /* Delete all VLANs for this dev. */ grp->killall = 1; diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 8d9503ad01d..b26ce343072 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -25,6 +25,7 @@ struct vlan_priority_tci_mapping { * @rx_multicast: number of received multicast packets * @syncp: synchronization point for 64bit counters * @rx_errors: number of errors + * @rx_dropped: number of dropped packets */ struct vlan_rx_stats { u64 rx_packets; @@ -32,6 +33,7 @@ struct vlan_rx_stats { u64 rx_multicast; struct u64_stats_sync syncp; unsigned long rx_errors; + unsigned long rx_dropped; }; /** diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 0eb96f7e44b..b6d55a9304f 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -30,7 +30,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, skb->pkt_type = PACKET_OTHERHOST; } - return (polling ? netif_receive_skb(skb) : netif_rx(skb)); + return polling ? netif_receive_skb(skb) : netif_rx(skb); drop: dev_kfree_skb_any(skb); @@ -38,12 +38,12 @@ drop: } EXPORT_SYMBOL(__vlan_hwaccel_rx); -int vlan_hwaccel_do_receive(struct sk_buff *skb) +void vlan_hwaccel_do_receive(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct vlan_rx_stats *rx_stats; - skb->dev = vlan_dev_info(dev)->real_dev; + skb->dev = vlan_dev_real_dev(dev); netif_nit_deliver(skb); skb->dev = dev; @@ -72,7 +72,6 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb) break; } u64_stats_update_end(&rx_stats->syncp); - return 0; } struct net_device *vlan_dev_real_dev(const struct net_device *dev) @@ -112,9 +111,12 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, } for (p = napi->gro_list; p; p = p->next) { - NAPI_GRO_CB(p)->same_flow = - p->dev == skb->dev && !compare_ether_header( - skb_mac_header(p), skb_gro_mac_header(skb)); + unsigned long diffs; + + diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev; + diffs |= compare_ether_header(skb_mac_header(p), + skb_gro_mac_header(skb)); + NAPI_GRO_CB(p)->same_flow = !diffs; NAPI_GRO_CB(p)->flush = 0; } diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 3bccdd12a26..f6fbcc0f1af 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -177,8 +177,8 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, } else { skb->dev = vlan_dev; - rx_stats = per_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats, - smp_processor_id()); + rx_stats = this_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats); + u64_stats_update_begin(&rx_stats->syncp); rx_stats->rx_packets++; rx_stats->rx_bytes += skb->len; @@ -225,7 +225,10 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, } } - netif_rx(skb); + if (unlikely(netif_rx(skb) == NET_RX_DROP)) { + if (rx_stats) + rx_stats->rx_dropped++; + } rcu_read_unlock(); return NET_RX_SUCCESS; @@ -843,13 +846,15 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st accum.rx_packets += rxpackets; accum.rx_bytes += rxbytes; accum.rx_multicast += rxmulticast; - /* rx_errors is an ulong, not protected by syncp */ + /* rx_errors, rx_dropped are ulong, not protected by syncp */ accum.rx_errors += p->rx_errors; + accum.rx_dropped += p->rx_dropped; } stats->rx_packets = accum.rx_packets; stats->rx_bytes = accum.rx_bytes; stats->rx_errors = accum.rx_errors; stats->multicast = accum.rx_multicast; + stats->rx_dropped = accum.rx_dropped; } return stats; } |