diff options
Diffstat (limited to 'net/8021q/vlan_dev.c')
-rw-r--r-- | net/8021q/vlan_dev.c | 197 |
1 files changed, 38 insertions, 159 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 14e3d1fa07a0..be737539f34d 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -141,7 +141,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
141 | struct packet_type *ptype, struct net_device *orig_dev) | 141 | struct packet_type *ptype, struct net_device *orig_dev) |
142 | { | 142 | { |
143 | struct vlan_hdr *vhdr; | 143 | struct vlan_hdr *vhdr; |
144 | struct vlan_rx_stats *rx_stats; | 144 | struct vlan_pcpu_stats *rx_stats; |
145 | struct net_device *vlan_dev; | 145 | struct net_device *vlan_dev; |
146 | u16 vlan_id; | 146 | u16 vlan_id; |
147 | u16 vlan_tci; | 147 | u16 vlan_tci; |
@@ -177,7 +177,7 @@ 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 = this_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats); | 180 | rx_stats = this_cpu_ptr(vlan_dev_info(skb->dev)->vlan_pcpu_stats); |
181 | 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++; |
@@ -274,9 +274,6 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, | |||
274 | u16 vlan_tci = 0; | 274 | u16 vlan_tci = 0; |
275 | int rc; | 275 | int rc; |
276 | 276 | ||
277 | if (WARN_ON(skb_headroom(skb) < dev->hard_header_len)) | ||
278 | return -ENOSPC; | ||
279 | |||
280 | if (!(vlan_dev_info(dev)->flags & VLAN_FLAG_REORDER_HDR)) { | 277 | if (!(vlan_dev_info(dev)->flags & VLAN_FLAG_REORDER_HDR)) { |
281 | vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN); | 278 | vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN); |
282 | 279 | ||
@@ -313,8 +310,6 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, | |||
313 | static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, | 310 | static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, |
314 | struct net_device *dev) | 311 | struct net_device *dev) |
315 | { | 312 | { |
316 | int i = skb_get_queue_mapping(skb); | ||
317 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); | ||
318 | struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); | 313 | struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); |
319 | unsigned int len; | 314 | unsigned int len; |
320 | int ret; | 315 | int ret; |
@@ -326,71 +321,31 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, | |||
326 | */ | 321 | */ |
327 | if (veth->h_vlan_proto != htons(ETH_P_8021Q) || | 322 | if (veth->h_vlan_proto != htons(ETH_P_8021Q) || |
328 | vlan_dev_info(dev)->flags & VLAN_FLAG_REORDER_HDR) { | 323 | vlan_dev_info(dev)->flags & VLAN_FLAG_REORDER_HDR) { |
329 | unsigned int orig_headroom = skb_headroom(skb); | ||
330 | u16 vlan_tci; | 324 | u16 vlan_tci; |
331 | |||
332 | vlan_dev_info(dev)->cnt_encap_on_xmit++; | ||
333 | |||
334 | vlan_tci = vlan_dev_info(dev)->vlan_id; | 325 | vlan_tci = vlan_dev_info(dev)->vlan_id; |
335 | vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); | 326 | vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); |
336 | skb = __vlan_put_tag(skb, vlan_tci); | 327 | skb = __vlan_hwaccel_put_tag(skb, vlan_tci); |
337 | if (!skb) { | ||
338 | txq->tx_dropped++; | ||
339 | return NETDEV_TX_OK; | ||
340 | } | ||
341 | |||
342 | if (orig_headroom < VLAN_HLEN) | ||
343 | vlan_dev_info(dev)->cnt_inc_headroom_on_tx++; | ||
344 | } | 328 | } |
345 | 329 | ||
346 | |||
347 | skb_set_dev(skb, vlan_dev_info(dev)->real_dev); | 330 | skb_set_dev(skb, vlan_dev_info(dev)->real_dev); |
348 | len = skb->len; | 331 | len = skb->len; |
349 | ret = dev_queue_xmit(skb); | 332 | ret = dev_queue_xmit(skb); |
350 | 333 | ||
351 | if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { | 334 | if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { |
352 | txq->tx_packets++; | 335 | struct vlan_pcpu_stats *stats; |
353 | txq->tx_bytes += len; | ||
354 | } else | ||
355 | txq->tx_dropped++; | ||
356 | 336 | ||
357 | return ret; | 337 | stats = this_cpu_ptr(vlan_dev_info(dev)->vlan_pcpu_stats); |
358 | } | 338 | u64_stats_update_begin(&stats->syncp); |
359 | 339 | stats->tx_packets++; | |
360 | static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, | 340 | stats->tx_bytes += len; |
361 | struct net_device *dev) | 341 | u64_stats_update_begin(&stats->syncp); |
362 | { | 342 | } else { |
363 | int i = skb_get_queue_mapping(skb); | 343 | this_cpu_inc(vlan_dev_info(dev)->vlan_pcpu_stats->tx_dropped); |
364 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); | 344 | } |
365 | u16 vlan_tci; | ||
366 | unsigned int len; | ||
367 | int ret; | ||
368 | |||
369 | vlan_tci = vlan_dev_info(dev)->vlan_id; | ||
370 | vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); | ||
371 | skb = __vlan_hwaccel_put_tag(skb, vlan_tci); | ||
372 | |||
373 | skb->dev = vlan_dev_info(dev)->real_dev; | ||
374 | len = skb->len; | ||
375 | ret = dev_queue_xmit(skb); | ||
376 | |||
377 | if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { | ||
378 | txq->tx_packets++; | ||
379 | txq->tx_bytes += len; | ||
380 | } else | ||
381 | txq->tx_dropped++; | ||
382 | 345 | ||
383 | return ret; | 346 | return ret; |
384 | } | 347 | } |
385 | 348 | ||
386 | static u16 vlan_dev_select_queue(struct net_device *dev, struct sk_buff *skb) | ||
387 | { | ||
388 | struct net_device *rdev = vlan_dev_info(dev)->real_dev; | ||
389 | const struct net_device_ops *ops = rdev->netdev_ops; | ||
390 | |||
391 | return ops->ndo_select_queue(rdev, skb); | ||
392 | } | ||
393 | |||
394 | static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) | 349 | static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) |
395 | { | 350 | { |
396 | /* TODO: gotta make sure the underlying layer can handle it, | 351 | /* TODO: gotta make sure the underlying layer can handle it, |
@@ -719,8 +674,7 @@ static const struct header_ops vlan_header_ops = { | |||
719 | .parse = eth_header_parse, | 674 | .parse = eth_header_parse, |
720 | }; | 675 | }; |
721 | 676 | ||
722 | static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops, | 677 | static const struct net_device_ops vlan_netdev_ops; |
723 | vlan_netdev_ops_sq, vlan_netdev_accel_ops_sq; | ||
724 | 678 | ||
725 | static int vlan_dev_init(struct net_device *dev) | 679 | static int vlan_dev_init(struct net_device *dev) |
726 | { | 680 | { |
@@ -738,6 +692,7 @@ static int vlan_dev_init(struct net_device *dev) | |||
738 | (1<<__LINK_STATE_PRESENT); | 692 | (1<<__LINK_STATE_PRESENT); |
739 | 693 | ||
740 | dev->features |= real_dev->features & real_dev->vlan_features; | 694 | dev->features |= real_dev->features & real_dev->vlan_features; |
695 | dev->features |= NETIF_F_LLTX; | ||
741 | dev->gso_max_size = real_dev->gso_max_size; | 696 | dev->gso_max_size = real_dev->gso_max_size; |
742 | 697 | ||
743 | /* ipv6 shared card related stuff */ | 698 | /* ipv6 shared card related stuff */ |
@@ -755,26 +710,20 @@ static int vlan_dev_init(struct net_device *dev) | |||
755 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { | 710 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { |
756 | dev->header_ops = real_dev->header_ops; | 711 | dev->header_ops = real_dev->header_ops; |
757 | dev->hard_header_len = real_dev->hard_header_len; | 712 | dev->hard_header_len = real_dev->hard_header_len; |
758 | if (real_dev->netdev_ops->ndo_select_queue) | ||
759 | dev->netdev_ops = &vlan_netdev_accel_ops_sq; | ||
760 | else | ||
761 | dev->netdev_ops = &vlan_netdev_accel_ops; | ||
762 | } else { | 713 | } else { |
763 | dev->header_ops = &vlan_header_ops; | 714 | dev->header_ops = &vlan_header_ops; |
764 | dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; | 715 | dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; |
765 | if (real_dev->netdev_ops->ndo_select_queue) | ||
766 | dev->netdev_ops = &vlan_netdev_ops_sq; | ||
767 | else | ||
768 | dev->netdev_ops = &vlan_netdev_ops; | ||
769 | } | 716 | } |
770 | 717 | ||
718 | dev->netdev_ops = &vlan_netdev_ops; | ||
719 | |||
771 | if (is_vlan_dev(real_dev)) | 720 | if (is_vlan_dev(real_dev)) |
772 | subclass = 1; | 721 | subclass = 1; |
773 | 722 | ||
774 | vlan_dev_set_lockdep_class(dev, subclass); | 723 | vlan_dev_set_lockdep_class(dev, subclass); |
775 | 724 | ||
776 | vlan_dev_info(dev)->vlan_rx_stats = alloc_percpu(struct vlan_rx_stats); | 725 | vlan_dev_info(dev)->vlan_pcpu_stats = alloc_percpu(struct vlan_pcpu_stats); |
777 | if (!vlan_dev_info(dev)->vlan_rx_stats) | 726 | if (!vlan_dev_info(dev)->vlan_pcpu_stats) |
778 | return -ENOMEM; | 727 | return -ENOMEM; |
779 | 728 | ||
780 | return 0; | 729 | return 0; |
@@ -786,8 +735,8 @@ static void vlan_dev_uninit(struct net_device *dev) | |||
786 | struct vlan_dev_info *vlan = vlan_dev_info(dev); | 735 | struct vlan_dev_info *vlan = vlan_dev_info(dev); |
787 | int i; | 736 | int i; |
788 | 737 | ||
789 | free_percpu(vlan->vlan_rx_stats); | 738 | free_percpu(vlan->vlan_pcpu_stats); |
790 | vlan->vlan_rx_stats = NULL; | 739 | vlan->vlan_pcpu_stats = NULL; |
791 | for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) { | 740 | for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) { |
792 | while ((pm = vlan->egress_priority_map[i]) != NULL) { | 741 | while ((pm = vlan->egress_priority_map[i]) != NULL) { |
793 | vlan->egress_priority_map[i] = pm->next; | 742 | vlan->egress_priority_map[i] = pm->next; |
@@ -825,33 +774,37 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev) | |||
825 | 774 | ||
826 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) | 775 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) |
827 | { | 776 | { |
828 | dev_txq_stats_fold(dev, stats); | ||
829 | 777 | ||
830 | if (vlan_dev_info(dev)->vlan_rx_stats) { | 778 | if (vlan_dev_info(dev)->vlan_pcpu_stats) { |
831 | struct vlan_rx_stats *p, accum = {0}; | 779 | struct vlan_pcpu_stats *p; |
780 | u32 rx_errors = 0, tx_dropped = 0; | ||
832 | int i; | 781 | int i; |
833 | 782 | ||
834 | for_each_possible_cpu(i) { | 783 | for_each_possible_cpu(i) { |
835 | u64 rxpackets, rxbytes, rxmulticast; | 784 | u64 rxpackets, rxbytes, rxmulticast, txpackets, txbytes; |
836 | unsigned int start; | 785 | unsigned int start; |
837 | 786 | ||
838 | p = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats, i); | 787 | p = per_cpu_ptr(vlan_dev_info(dev)->vlan_pcpu_stats, i); |
839 | do { | 788 | do { |
840 | start = u64_stats_fetch_begin_bh(&p->syncp); | 789 | start = u64_stats_fetch_begin_bh(&p->syncp); |
841 | rxpackets = p->rx_packets; | 790 | rxpackets = p->rx_packets; |
842 | rxbytes = p->rx_bytes; | 791 | rxbytes = p->rx_bytes; |
843 | rxmulticast = p->rx_multicast; | 792 | rxmulticast = p->rx_multicast; |
793 | txpackets = p->tx_packets; | ||
794 | txbytes = p->tx_bytes; | ||
844 | } while (u64_stats_fetch_retry_bh(&p->syncp, start)); | 795 | } while (u64_stats_fetch_retry_bh(&p->syncp, start)); |
845 | accum.rx_packets += rxpackets; | 796 | |
846 | accum.rx_bytes += rxbytes; | 797 | stats->rx_packets += rxpackets; |
847 | accum.rx_multicast += rxmulticast; | 798 | stats->rx_bytes += rxbytes; |
848 | /* rx_errors is ulong, not protected by syncp */ | 799 | stats->multicast += rxmulticast; |
849 | accum.rx_errors += p->rx_errors; | 800 | stats->tx_packets += txpackets; |
801 | stats->tx_bytes += txbytes; | ||
802 | /* rx_errors & tx_dropped are u32 */ | ||
803 | rx_errors += p->rx_errors; | ||
804 | tx_dropped += p->tx_dropped; | ||
850 | } | 805 | } |
851 | stats->rx_packets = accum.rx_packets; | 806 | stats->rx_errors = rx_errors; |
852 | stats->rx_bytes = accum.rx_bytes; | 807 | stats->tx_dropped = tx_dropped; |
853 | stats->rx_errors = accum.rx_errors; | ||
854 | stats->multicast = accum.rx_multicast; | ||
855 | } | 808 | } |
856 | return stats; | 809 | return stats; |
857 | } | 810 | } |
@@ -908,80 +861,6 @@ static const struct net_device_ops vlan_netdev_ops = { | |||
908 | #endif | 861 | #endif |
909 | }; | 862 | }; |
910 | 863 | ||
911 | static const struct net_device_ops vlan_netdev_accel_ops = { | ||
912 | .ndo_change_mtu = vlan_dev_change_mtu, | ||
913 | .ndo_init = vlan_dev_init, | ||
914 | .ndo_uninit = vlan_dev_uninit, | ||
915 | .ndo_open = vlan_dev_open, | ||
916 | .ndo_stop = vlan_dev_stop, | ||
917 | .ndo_start_xmit = vlan_dev_hwaccel_hard_start_xmit, | ||
918 | .ndo_validate_addr = eth_validate_addr, | ||
919 | .ndo_set_mac_address = vlan_dev_set_mac_address, | ||
920 | .ndo_set_rx_mode = vlan_dev_set_rx_mode, | ||
921 | .ndo_set_multicast_list = vlan_dev_set_rx_mode, | ||
922 | .ndo_change_rx_flags = vlan_dev_change_rx_flags, | ||
923 | .ndo_do_ioctl = vlan_dev_ioctl, | ||
924 | .ndo_neigh_setup = vlan_dev_neigh_setup, | ||
925 | .ndo_get_stats64 = vlan_dev_get_stats64, | ||
926 | #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) | ||
927 | .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, | ||
928 | .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, | ||
929 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, | ||
930 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, | ||
931 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, | ||
932 | #endif | ||
933 | }; | ||
934 | |||
935 | static const struct net_device_ops vlan_netdev_ops_sq = { | ||
936 | .ndo_select_queue = vlan_dev_select_queue, | ||
937 | .ndo_change_mtu = vlan_dev_change_mtu, | ||
938 | .ndo_init = vlan_dev_init, | ||
939 | .ndo_uninit = vlan_dev_uninit, | ||
940 | .ndo_open = vlan_dev_open, | ||
941 | .ndo_stop = vlan_dev_stop, | ||
942 | .ndo_start_xmit = vlan_dev_hard_start_xmit, | ||
943 | .ndo_validate_addr = eth_validate_addr, | ||
944 | .ndo_set_mac_address = vlan_dev_set_mac_address, | ||
945 | .ndo_set_rx_mode = vlan_dev_set_rx_mode, | ||
946 | .ndo_set_multicast_list = vlan_dev_set_rx_mode, | ||
947 | .ndo_change_rx_flags = vlan_dev_change_rx_flags, | ||
948 | .ndo_do_ioctl = vlan_dev_ioctl, | ||
949 | .ndo_neigh_setup = vlan_dev_neigh_setup, | ||
950 | .ndo_get_stats64 = vlan_dev_get_stats64, | ||
951 | #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) | ||
952 | .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, | ||
953 | .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, | ||
954 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, | ||
955 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, | ||
956 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, | ||
957 | #endif | ||
958 | }; | ||
959 | |||
960 | static const struct net_device_ops vlan_netdev_accel_ops_sq = { | ||
961 | .ndo_select_queue = vlan_dev_select_queue, | ||
962 | .ndo_change_mtu = vlan_dev_change_mtu, | ||
963 | .ndo_init = vlan_dev_init, | ||
964 | .ndo_uninit = vlan_dev_uninit, | ||
965 | .ndo_open = vlan_dev_open, | ||
966 | .ndo_stop = vlan_dev_stop, | ||
967 | .ndo_start_xmit = vlan_dev_hwaccel_hard_start_xmit, | ||
968 | .ndo_validate_addr = eth_validate_addr, | ||
969 | .ndo_set_mac_address = vlan_dev_set_mac_address, | ||
970 | .ndo_set_rx_mode = vlan_dev_set_rx_mode, | ||
971 | .ndo_set_multicast_list = vlan_dev_set_rx_mode, | ||
972 | .ndo_change_rx_flags = vlan_dev_change_rx_flags, | ||
973 | .ndo_do_ioctl = vlan_dev_ioctl, | ||
974 | .ndo_neigh_setup = vlan_dev_neigh_setup, | ||
975 | .ndo_get_stats64 = vlan_dev_get_stats64, | ||
976 | #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) | ||
977 | .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, | ||
978 | .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, | ||
979 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, | ||
980 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, | ||
981 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, | ||
982 | #endif | ||
983 | }; | ||
984 | |||
985 | void vlan_setup(struct net_device *dev) | 864 | void vlan_setup(struct net_device *dev) |
986 | { | 865 | { |
987 | ether_setup(dev); | 866 | ether_setup(dev); |