aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q')
-rw-r--r--net/8021q/vlan.c26
-rw-r--r--net/8021q/vlan.h6
-rw-r--r--net/8021q/vlan_core.c44
-rw-r--r--net/8021q/vlan_dev.c76
-rw-r--r--net/8021q/vlanproc.c2
5 files changed, 110 insertions, 44 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index f0e335aa20df..41e8f65bd3f0 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -46,10 +46,10 @@ int vlan_net_id;
46/* Our listing of VLAN group(s) */ 46/* Our listing of VLAN group(s) */
47static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE]; 47static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
48 48
49static char vlan_fullname[] = "802.1Q VLAN Support"; 49const char vlan_fullname[] = "802.1Q VLAN Support";
50static char vlan_version[] = DRV_VERSION; 50const char vlan_version[] = DRV_VERSION;
51static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>"; 51static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
52static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>"; 52static const char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
53 53
54static struct packet_type vlan_packet_type = { 54static struct packet_type vlan_packet_type = {
55 .type = __constant_htons(ETH_P_8021Q), 55 .type = __constant_htons(ETH_P_8021Q),
@@ -144,6 +144,7 @@ void unregister_vlan_dev(struct net_device *dev)
144{ 144{
145 struct vlan_dev_info *vlan = vlan_dev_info(dev); 145 struct vlan_dev_info *vlan = vlan_dev_info(dev);
146 struct net_device *real_dev = vlan->real_dev; 146 struct net_device *real_dev = vlan->real_dev;
147 const struct net_device_ops *ops = real_dev->netdev_ops;
147 struct vlan_group *grp; 148 struct vlan_group *grp;
148 u16 vlan_id = vlan->vlan_id; 149 u16 vlan_id = vlan->vlan_id;
149 150
@@ -156,7 +157,7 @@ void unregister_vlan_dev(struct net_device *dev)
156 * HW accelerating devices or SW vlan input packet processing. 157 * HW accelerating devices or SW vlan input packet processing.
157 */ 158 */
158 if (real_dev->features & NETIF_F_HW_VLAN_FILTER) 159 if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
159 real_dev->vlan_rx_kill_vid(real_dev, vlan_id); 160 ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id);
160 161
161 vlan_group_set_device(grp, vlan_id, NULL); 162 vlan_group_set_device(grp, vlan_id, NULL);
162 grp->nr_vlans--; 163 grp->nr_vlans--;
@@ -170,7 +171,7 @@ void unregister_vlan_dev(struct net_device *dev)
170 vlan_gvrp_uninit_applicant(real_dev); 171 vlan_gvrp_uninit_applicant(real_dev);
171 172
172 if (real_dev->features & NETIF_F_HW_VLAN_RX) 173 if (real_dev->features & NETIF_F_HW_VLAN_RX)
173 real_dev->vlan_rx_register(real_dev, NULL); 174 ops->ndo_vlan_rx_register(real_dev, NULL);
174 175
175 hlist_del_rcu(&grp->hlist); 176 hlist_del_rcu(&grp->hlist);
176 177
@@ -205,21 +206,21 @@ static void vlan_transfer_operstate(const struct net_device *dev,
205 206
206int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id) 207int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
207{ 208{
208 char *name = real_dev->name; 209 const char *name = real_dev->name;
210 const struct net_device_ops *ops = real_dev->netdev_ops;
209 211
210 if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { 212 if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
211 pr_info("8021q: VLANs not supported on %s\n", name); 213 pr_info("8021q: VLANs not supported on %s\n", name);
212 return -EOPNOTSUPP; 214 return -EOPNOTSUPP;
213 } 215 }
214 216
215 if ((real_dev->features & NETIF_F_HW_VLAN_RX) && 217 if ((real_dev->features & NETIF_F_HW_VLAN_RX) && !ops->ndo_vlan_rx_register) {
216 !real_dev->vlan_rx_register) {
217 pr_info("8021q: device %s has buggy VLAN hw accel\n", name); 218 pr_info("8021q: device %s has buggy VLAN hw accel\n", name);
218 return -EOPNOTSUPP; 219 return -EOPNOTSUPP;
219 } 220 }
220 221
221 if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && 222 if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
222 (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) { 223 (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
223 pr_info("8021q: Device %s has buggy VLAN hw accel\n", name); 224 pr_info("8021q: Device %s has buggy VLAN hw accel\n", name);
224 return -EOPNOTSUPP; 225 return -EOPNOTSUPP;
225 } 226 }
@@ -240,6 +241,7 @@ int register_vlan_dev(struct net_device *dev)
240{ 241{
241 struct vlan_dev_info *vlan = vlan_dev_info(dev); 242 struct vlan_dev_info *vlan = vlan_dev_info(dev);
242 struct net_device *real_dev = vlan->real_dev; 243 struct net_device *real_dev = vlan->real_dev;
244 const struct net_device_ops *ops = real_dev->netdev_ops;
243 u16 vlan_id = vlan->vlan_id; 245 u16 vlan_id = vlan->vlan_id;
244 struct vlan_group *grp, *ngrp = NULL; 246 struct vlan_group *grp, *ngrp = NULL;
245 int err; 247 int err;
@@ -275,9 +277,9 @@ int register_vlan_dev(struct net_device *dev)
275 grp->nr_vlans++; 277 grp->nr_vlans++;
276 278
277 if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX) 279 if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
278 real_dev->vlan_rx_register(real_dev, ngrp); 280 ops->ndo_vlan_rx_register(real_dev, ngrp);
279 if (real_dev->features & NETIF_F_HW_VLAN_FILTER) 281 if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
280 real_dev->vlan_rx_add_vid(real_dev, vlan_id); 282 ops->ndo_vlan_rx_add_vid(real_dev, vlan_id);
281 283
282 return 0; 284 return 0;
283 285
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index a6603a4d917f..82570bc2a180 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -108,8 +108,10 @@ static inline int vlan_gvrp_init(void) { return 0; }
108static inline void vlan_gvrp_uninit(void) {} 108static inline void vlan_gvrp_uninit(void) {}
109#endif 109#endif
110 110
111int vlan_netlink_init(void); 111extern const char vlan_fullname[];
112void vlan_netlink_fini(void); 112extern const char vlan_version[];
113extern int vlan_netlink_init(void);
114extern void vlan_netlink_fini(void);
113 115
114extern struct rtnl_link_ops vlan_link_ops; 116extern struct rtnl_link_ops vlan_link_ops;
115 117
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 916061f681b6..dd86a1dc4cd0 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -3,11 +3,20 @@
3#include <linux/if_vlan.h> 3#include <linux/if_vlan.h>
4#include "vlan.h" 4#include "vlan.h"
5 5
6struct vlan_hwaccel_cb {
7 struct net_device *dev;
8};
9
10static inline struct vlan_hwaccel_cb *vlan_hwaccel_cb(struct sk_buff *skb)
11{
12 return (struct vlan_hwaccel_cb *)skb->cb;
13}
14
6/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ 15/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */
7int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, 16int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
8 u16 vlan_tci, int polling) 17 u16 vlan_tci, int polling)
9{ 18{
10 struct net_device_stats *stats; 19 struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb);
11 20
12 if (skb_bond_should_drop(skb)) { 21 if (skb_bond_should_drop(skb)) {
13 dev_kfree_skb_any(skb); 22 dev_kfree_skb_any(skb);
@@ -15,23 +24,33 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
15 } 24 }
16 25
17 skb->vlan_tci = vlan_tci; 26 skb->vlan_tci = vlan_tci;
27 cb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK);
28
29 return (polling ? netif_receive_skb(skb) : netif_rx(skb));
30}
31EXPORT_SYMBOL(__vlan_hwaccel_rx);
32
33int vlan_hwaccel_do_receive(struct sk_buff *skb)
34{
35 struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb);
36 struct net_device *dev = cb->dev;
37 struct net_device_stats *stats;
38
18 netif_nit_deliver(skb); 39 netif_nit_deliver(skb);
19 40
20 skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); 41 if (dev == NULL) {
21 if (skb->dev == NULL) { 42 kfree_skb(skb);
22 dev_kfree_skb_any(skb); 43 return -1;
23 /* Not NET_RX_DROP, this is not being dropped
24 * due to congestion. */
25 return NET_RX_SUCCESS;
26 } 44 }
27 skb->dev->last_rx = jiffies; 45
46 skb->dev = dev;
47 skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
28 skb->vlan_tci = 0; 48 skb->vlan_tci = 0;
29 49
30 stats = &skb->dev->stats; 50 stats = &dev->stats;
31 stats->rx_packets++; 51 stats->rx_packets++;
32 stats->rx_bytes += skb->len; 52 stats->rx_bytes += skb->len;
33 53
34 skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tci);
35 switch (skb->pkt_type) { 54 switch (skb->pkt_type) {
36 case PACKET_BROADCAST: 55 case PACKET_BROADCAST:
37 break; 56 break;
@@ -43,13 +62,12 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
43 * This allows the VLAN to have a different MAC than the 62 * This allows the VLAN to have a different MAC than the
44 * underlying device, and still route correctly. */ 63 * underlying device, and still route correctly. */
45 if (!compare_ether_addr(eth_hdr(skb)->h_dest, 64 if (!compare_ether_addr(eth_hdr(skb)->h_dest,
46 skb->dev->dev_addr)) 65 dev->dev_addr))
47 skb->pkt_type = PACKET_HOST; 66 skb->pkt_type = PACKET_HOST;
48 break; 67 break;
49 }; 68 };
50 return (polling ? netif_receive_skb(skb) : netif_rx(skb)); 69 return 0;
51} 70}
52EXPORT_SYMBOL(__vlan_hwaccel_rx);
53 71
54struct net_device *vlan_dev_real_dev(const struct net_device *dev) 72struct net_device *vlan_dev_real_dev(const struct net_device *dev)
55{ 73{
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 8883e9c8a223..89a3bbdfca3f 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -163,8 +163,6 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
163 goto err_unlock; 163 goto err_unlock;
164 } 164 }
165 165
166 skb->dev->last_rx = jiffies;
167
168 stats = &skb->dev->stats; 166 stats = &skb->dev->stats;
169 stats->rx_packets++; 167 stats->rx_packets++;
170 stats->rx_bytes += skb->len; 168 stats->rx_bytes += skb->len;
@@ -526,6 +524,7 @@ out:
526static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 524static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
527{ 525{
528 struct net_device *real_dev = vlan_dev_info(dev)->real_dev; 526 struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
527 const struct net_device_ops *ops = real_dev->netdev_ops;
529 struct ifreq ifrr; 528 struct ifreq ifrr;
530 int err = -EOPNOTSUPP; 529 int err = -EOPNOTSUPP;
531 530
@@ -536,8 +535,8 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
536 case SIOCGMIIPHY: 535 case SIOCGMIIPHY:
537 case SIOCGMIIREG: 536 case SIOCGMIIREG:
538 case SIOCSMIIREG: 537 case SIOCSMIIREG:
539 if (real_dev->do_ioctl && netif_device_present(real_dev)) 538 if (netif_device_present(real_dev) && ops->ndo_do_ioctl)
540 err = real_dev->do_ioctl(real_dev, &ifrr, cmd); 539 err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd);
541 break; 540 break;
542 } 541 }
543 542
@@ -594,6 +593,8 @@ static const struct header_ops vlan_header_ops = {
594 .parse = eth_header_parse, 593 .parse = eth_header_parse,
595}; 594};
596 595
596static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops;
597
597static int vlan_dev_init(struct net_device *dev) 598static int vlan_dev_init(struct net_device *dev)
598{ 599{
599 struct net_device *real_dev = vlan_dev_info(dev)->real_dev; 600 struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
@@ -620,11 +621,11 @@ static int vlan_dev_init(struct net_device *dev)
620 if (real_dev->features & NETIF_F_HW_VLAN_TX) { 621 if (real_dev->features & NETIF_F_HW_VLAN_TX) {
621 dev->header_ops = real_dev->header_ops; 622 dev->header_ops = real_dev->header_ops;
622 dev->hard_header_len = real_dev->hard_header_len; 623 dev->hard_header_len = real_dev->hard_header_len;
623 dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit; 624 dev->netdev_ops = &vlan_netdev_accel_ops;
624 } else { 625 } else {
625 dev->header_ops = &vlan_header_ops; 626 dev->header_ops = &vlan_header_ops;
626 dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; 627 dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
627 dev->hard_start_xmit = vlan_dev_hard_start_xmit; 628 dev->netdev_ops = &vlan_netdev_ops;
628 } 629 }
629 630
630 if (is_vlan_dev(real_dev)) 631 if (is_vlan_dev(real_dev))
@@ -648,6 +649,26 @@ static void vlan_dev_uninit(struct net_device *dev)
648 } 649 }
649} 650}
650 651
652static int vlan_ethtool_get_settings(struct net_device *dev,
653 struct ethtool_cmd *cmd)
654{
655 const struct vlan_dev_info *vlan = vlan_dev_info(dev);
656 struct net_device *real_dev = vlan->real_dev;
657
658 if (!real_dev->ethtool_ops->get_settings)
659 return -EOPNOTSUPP;
660
661 return real_dev->ethtool_ops->get_settings(real_dev, cmd);
662}
663
664static void vlan_ethtool_get_drvinfo(struct net_device *dev,
665 struct ethtool_drvinfo *info)
666{
667 strcpy(info->driver, vlan_fullname);
668 strcpy(info->version, vlan_version);
669 strcpy(info->fw_version, "N/A");
670}
671
651static u32 vlan_ethtool_get_rx_csum(struct net_device *dev) 672static u32 vlan_ethtool_get_rx_csum(struct net_device *dev)
652{ 673{
653 const struct vlan_dev_info *vlan = vlan_dev_info(dev); 674 const struct vlan_dev_info *vlan = vlan_dev_info(dev);
@@ -672,11 +693,43 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev)
672} 693}
673 694
674static const struct ethtool_ops vlan_ethtool_ops = { 695static const struct ethtool_ops vlan_ethtool_ops = {
696 .get_settings = vlan_ethtool_get_settings,
697 .get_drvinfo = vlan_ethtool_get_drvinfo,
675 .get_link = ethtool_op_get_link, 698 .get_link = ethtool_op_get_link,
676 .get_rx_csum = vlan_ethtool_get_rx_csum, 699 .get_rx_csum = vlan_ethtool_get_rx_csum,
677 .get_flags = vlan_ethtool_get_flags, 700 .get_flags = vlan_ethtool_get_flags,
678}; 701};
679 702
703static const struct net_device_ops vlan_netdev_ops = {
704 .ndo_change_mtu = vlan_dev_change_mtu,
705 .ndo_init = vlan_dev_init,
706 .ndo_uninit = vlan_dev_uninit,
707 .ndo_open = vlan_dev_open,
708 .ndo_stop = vlan_dev_stop,
709 .ndo_start_xmit = vlan_dev_hard_start_xmit,
710 .ndo_validate_addr = eth_validate_addr,
711 .ndo_set_mac_address = vlan_dev_set_mac_address,
712 .ndo_set_rx_mode = vlan_dev_set_rx_mode,
713 .ndo_set_multicast_list = vlan_dev_set_rx_mode,
714 .ndo_change_rx_flags = vlan_dev_change_rx_flags,
715 .ndo_do_ioctl = vlan_dev_ioctl,
716};
717
718static const struct net_device_ops vlan_netdev_accel_ops = {
719 .ndo_change_mtu = vlan_dev_change_mtu,
720 .ndo_init = vlan_dev_init,
721 .ndo_uninit = vlan_dev_uninit,
722 .ndo_open = vlan_dev_open,
723 .ndo_stop = vlan_dev_stop,
724 .ndo_start_xmit = vlan_dev_hwaccel_hard_start_xmit,
725 .ndo_validate_addr = eth_validate_addr,
726 .ndo_set_mac_address = vlan_dev_set_mac_address,
727 .ndo_set_rx_mode = vlan_dev_set_rx_mode,
728 .ndo_set_multicast_list = vlan_dev_set_rx_mode,
729 .ndo_change_rx_flags = vlan_dev_change_rx_flags,
730 .ndo_do_ioctl = vlan_dev_ioctl,
731};
732
680void vlan_setup(struct net_device *dev) 733void vlan_setup(struct net_device *dev)
681{ 734{
682 ether_setup(dev); 735 ether_setup(dev);
@@ -684,16 +737,7 @@ void vlan_setup(struct net_device *dev)
684 dev->priv_flags |= IFF_802_1Q_VLAN; 737 dev->priv_flags |= IFF_802_1Q_VLAN;
685 dev->tx_queue_len = 0; 738 dev->tx_queue_len = 0;
686 739
687 dev->change_mtu = vlan_dev_change_mtu; 740 dev->netdev_ops = &vlan_netdev_ops;
688 dev->init = vlan_dev_init;
689 dev->uninit = vlan_dev_uninit;
690 dev->open = vlan_dev_open;
691 dev->stop = vlan_dev_stop;
692 dev->set_mac_address = vlan_dev_set_mac_address;
693 dev->set_rx_mode = vlan_dev_set_rx_mode;
694 dev->set_multicast_list = vlan_dev_set_rx_mode;
695 dev->change_rx_flags = vlan_dev_change_rx_flags;
696 dev->do_ioctl = vlan_dev_ioctl;
697 dev->destructor = free_netdev; 741 dev->destructor = free_netdev;
698 dev->ethtool_ops = &vlan_ethtool_ops; 742 dev->ethtool_ops = &vlan_ethtool_ops;
699 743
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index 0feefa4e1a4b..3628e0a81b40 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -314,7 +314,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset)
314 dev_info->ingress_priority_map[6], 314 dev_info->ingress_priority_map[6],
315 dev_info->ingress_priority_map[7]); 315 dev_info->ingress_priority_map[7]);
316 316
317 seq_printf(seq, "EGRESSS priority Mappings: "); 317 seq_printf(seq, " EGRESS priority mappings: ");
318 for (i = 0; i < 16; i++) { 318 for (i = 0; i < 16; i++) {
319 const struct vlan_priority_tci_mapping *mp 319 const struct vlan_priority_tci_mapping *mp
320 = dev_info->egress_priority_map[i]; 320 = dev_info->egress_priority_map[i];