diff options
Diffstat (limited to 'net/8021q/vlan_dev.c')
-rw-r--r-- | net/8021q/vlan_dev.c | 243 |
1 files changed, 31 insertions, 212 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index be737539f34d..f247f5bff88d 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -65,179 +65,6 @@ static int vlan_dev_rebuild_header(struct sk_buff *skb) | |||
65 | return 0; | 65 | return 0; |
66 | } | 66 | } |
67 | 67 | ||
68 | static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) | ||
69 | { | ||
70 | if (vlan_dev_info(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) { | ||
71 | if (skb_cow(skb, skb_headroom(skb)) < 0) | ||
72 | skb = NULL; | ||
73 | if (skb) { | ||
74 | /* Lifted from Gleb's VLAN code... */ | ||
75 | memmove(skb->data - ETH_HLEN, | ||
76 | skb->data - VLAN_ETH_HLEN, 12); | ||
77 | skb->mac_header += VLAN_HLEN; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | return skb; | ||
82 | } | ||
83 | |||
84 | static inline void vlan_set_encap_proto(struct sk_buff *skb, | ||
85 | struct vlan_hdr *vhdr) | ||
86 | { | ||
87 | __be16 proto; | ||
88 | unsigned char *rawp; | ||
89 | |||
90 | /* | ||
91 | * Was a VLAN packet, grab the encapsulated protocol, which the layer | ||
92 | * three protocols care about. | ||
93 | */ | ||
94 | |||
95 | proto = vhdr->h_vlan_encapsulated_proto; | ||
96 | if (ntohs(proto) >= 1536) { | ||
97 | skb->protocol = proto; | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | rawp = skb->data; | ||
102 | if (*(unsigned short *)rawp == 0xFFFF) | ||
103 | /* | ||
104 | * This is a magic hack to spot IPX packets. Older Novell | ||
105 | * breaks the protocol design and runs IPX over 802.3 without | ||
106 | * an 802.2 LLC layer. We look for FFFF which isn't a used | ||
107 | * 802.2 SSAP/DSAP. This won't work for fault tolerant netware | ||
108 | * but does for the rest. | ||
109 | */ | ||
110 | skb->protocol = htons(ETH_P_802_3); | ||
111 | else | ||
112 | /* | ||
113 | * Real 802.2 LLC | ||
114 | */ | ||
115 | skb->protocol = htons(ETH_P_802_2); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Determine the packet's protocol ID. The rule here is that we | ||
120 | * assume 802.3 if the type field is short enough to be a length. | ||
121 | * This is normal practice and works for any 'now in use' protocol. | ||
122 | * | ||
123 | * Also, at this point we assume that we ARE dealing exclusively with | ||
124 | * VLAN packets, or packets that should be made into VLAN packets based | ||
125 | * on a default VLAN ID. | ||
126 | * | ||
127 | * NOTE: Should be similar to ethernet/eth.c. | ||
128 | * | ||
129 | * SANITY NOTE: This method is called when a packet is moving up the stack | ||
130 | * towards userland. To get here, it would have already passed | ||
131 | * through the ethernet/eth.c eth_type_trans() method. | ||
132 | * SANITY NOTE 2: We are referencing to the VLAN_HDR frields, which MAY be | ||
133 | * stored UNALIGNED in the memory. RISC systems don't like | ||
134 | * such cases very much... | ||
135 | * SANITY NOTE 2a: According to Dave Miller & Alexey, it will always be | ||
136 | * aligned, so there doesn't need to be any of the unaligned | ||
137 | * stuff. It has been commented out now... --Ben | ||
138 | * | ||
139 | */ | ||
140 | int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | ||
141 | struct packet_type *ptype, struct net_device *orig_dev) | ||
142 | { | ||
143 | struct vlan_hdr *vhdr; | ||
144 | struct vlan_pcpu_stats *rx_stats; | ||
145 | struct net_device *vlan_dev; | ||
146 | u16 vlan_id; | ||
147 | u16 vlan_tci; | ||
148 | |||
149 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
150 | if (skb == NULL) | ||
151 | goto err_free; | ||
152 | |||
153 | if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) | ||
154 | goto err_free; | ||
155 | |||
156 | vhdr = (struct vlan_hdr *)skb->data; | ||
157 | vlan_tci = ntohs(vhdr->h_vlan_TCI); | ||
158 | vlan_id = vlan_tci & VLAN_VID_MASK; | ||
159 | |||
160 | rcu_read_lock(); | ||
161 | vlan_dev = vlan_find_dev(dev, vlan_id); | ||
162 | |||
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 | ||
165 | * really a VLAN), so we will just netif_rx it later to the | ||
166 | * original interface, but with the skb->proto set to the | ||
167 | * wrapped proto: we do nothing here. | ||
168 | */ | ||
169 | |||
170 | if (!vlan_dev) { | ||
171 | if (vlan_id) { | ||
172 | pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n", | ||
173 | __func__, vlan_id, dev->name); | ||
174 | goto err_unlock; | ||
175 | } | ||
176 | rx_stats = NULL; | ||
177 | } else { | ||
178 | skb->dev = vlan_dev; | ||
179 | |||
180 | rx_stats = this_cpu_ptr(vlan_dev_info(skb->dev)->vlan_pcpu_stats); | ||
181 | |||
182 | u64_stats_update_begin(&rx_stats->syncp); | ||
183 | rx_stats->rx_packets++; | ||
184 | rx_stats->rx_bytes += skb->len; | ||
185 | |||
186 | skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tci); | ||
187 | |||
188 | pr_debug("%s: priority: %u for TCI: %hu\n", | ||
189 | __func__, skb->priority, vlan_tci); | ||
190 | |||
191 | switch (skb->pkt_type) { | ||
192 | case PACKET_BROADCAST: | ||
193 | /* Yeah, stats collect these together.. */ | ||
194 | /* stats->broadcast ++; // no such counter :-( */ | ||
195 | break; | ||
196 | |||
197 | case PACKET_MULTICAST: | ||
198 | rx_stats->rx_multicast++; | ||
199 | break; | ||
200 | |||
201 | case PACKET_OTHERHOST: | ||
202 | /* Our lower layer thinks this is not local, let's make | ||
203 | * sure. | ||
204 | * This allows the VLAN to have a different MAC than the | ||
205 | * underlying device, and still route correctly. | ||
206 | */ | ||
207 | if (!compare_ether_addr(eth_hdr(skb)->h_dest, | ||
208 | skb->dev->dev_addr)) | ||
209 | skb->pkt_type = PACKET_HOST; | ||
210 | break; | ||
211 | default: | ||
212 | break; | ||
213 | } | ||
214 | u64_stats_update_end(&rx_stats->syncp); | ||
215 | } | ||
216 | |||
217 | skb_pull_rcsum(skb, VLAN_HLEN); | ||
218 | vlan_set_encap_proto(skb, vhdr); | ||
219 | |||
220 | if (vlan_dev) { | ||
221 | skb = vlan_check_reorder_header(skb); | ||
222 | if (!skb) { | ||
223 | rx_stats->rx_errors++; | ||
224 | goto err_unlock; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | netif_rx(skb); | ||
229 | |||
230 | rcu_read_unlock(); | ||
231 | return NET_RX_SUCCESS; | ||
232 | |||
233 | err_unlock: | ||
234 | rcu_read_unlock(); | ||
235 | err_free: | ||
236 | atomic_long_inc(&dev->rx_dropped); | ||
237 | kfree_skb(skb); | ||
238 | return NET_RX_DROP; | ||
239 | } | ||
240 | |||
241 | static inline u16 | 68 | static inline u16 |
242 | vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb) | 69 | vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb) |
243 | { | 70 | { |
@@ -487,9 +314,6 @@ static int vlan_dev_stop(struct net_device *dev) | |||
487 | struct vlan_dev_info *vlan = vlan_dev_info(dev); | 314 | struct vlan_dev_info *vlan = vlan_dev_info(dev); |
488 | struct net_device *real_dev = vlan->real_dev; | 315 | struct net_device *real_dev = vlan->real_dev; |
489 | 316 | ||
490 | if (vlan->flags & VLAN_FLAG_GVRP) | ||
491 | vlan_gvrp_request_leave(dev); | ||
492 | |||
493 | dev_mc_unsync(real_dev, dev); | 317 | dev_mc_unsync(real_dev, dev); |
494 | dev_uc_unsync(real_dev, dev); | 318 | dev_uc_unsync(real_dev, dev); |
495 | if (dev->flags & IFF_ALLMULTI) | 319 | if (dev->flags & IFF_ALLMULTI) |
@@ -625,6 +449,19 @@ static int vlan_dev_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type) | |||
625 | rc = ops->ndo_fcoe_get_wwn(real_dev, wwn, type); | 449 | rc = ops->ndo_fcoe_get_wwn(real_dev, wwn, type); |
626 | return rc; | 450 | return rc; |
627 | } | 451 | } |
452 | |||
453 | static int vlan_dev_fcoe_ddp_target(struct net_device *dev, u16 xid, | ||
454 | struct scatterlist *sgl, unsigned int sgc) | ||
455 | { | ||
456 | struct net_device *real_dev = vlan_dev_info(dev)->real_dev; | ||
457 | const struct net_device_ops *ops = real_dev->netdev_ops; | ||
458 | int rc = 0; | ||
459 | |||
460 | if (ops->ndo_fcoe_ddp_target) | ||
461 | rc = ops->ndo_fcoe_ddp_target(real_dev, xid, sgl, sgc); | ||
462 | |||
463 | return rc; | ||
464 | } | ||
628 | #endif | 465 | #endif |
629 | 466 | ||
630 | static void vlan_dev_change_rx_flags(struct net_device *dev, int change) | 467 | static void vlan_dev_change_rx_flags(struct net_device *dev, int change) |
@@ -691,8 +528,8 @@ static int vlan_dev_init(struct net_device *dev) | |||
691 | (1<<__LINK_STATE_DORMANT))) | | 528 | (1<<__LINK_STATE_DORMANT))) | |
692 | (1<<__LINK_STATE_PRESENT); | 529 | (1<<__LINK_STATE_PRESENT); |
693 | 530 | ||
694 | dev->features |= real_dev->features & real_dev->vlan_features; | 531 | dev->hw_features = NETIF_F_ALL_TX_OFFLOADS; |
695 | dev->features |= NETIF_F_LLTX; | 532 | dev->features |= real_dev->vlan_features | NETIF_F_LLTX; |
696 | dev->gso_max_size = real_dev->gso_max_size; | 533 | dev->gso_max_size = real_dev->gso_max_size; |
697 | 534 | ||
698 | /* ipv6 shared card related stuff */ | 535 | /* ipv6 shared card related stuff */ |
@@ -707,6 +544,7 @@ static int vlan_dev_init(struct net_device *dev) | |||
707 | dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid; | 544 | dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid; |
708 | #endif | 545 | #endif |
709 | 546 | ||
547 | dev->needed_headroom = real_dev->needed_headroom; | ||
710 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { | 548 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { |
711 | dev->header_ops = real_dev->header_ops; | 549 | dev->header_ops = real_dev->header_ops; |
712 | dev->hard_header_len = real_dev->hard_header_len; | 550 | dev->hard_header_len = real_dev->hard_header_len; |
@@ -745,6 +583,19 @@ static void vlan_dev_uninit(struct net_device *dev) | |||
745 | } | 583 | } |
746 | } | 584 | } |
747 | 585 | ||
586 | static u32 vlan_dev_fix_features(struct net_device *dev, u32 features) | ||
587 | { | ||
588 | struct net_device *real_dev = vlan_dev_info(dev)->real_dev; | ||
589 | |||
590 | features &= real_dev->features; | ||
591 | features &= real_dev->vlan_features; | ||
592 | if (dev_ethtool_get_rx_csum(real_dev)) | ||
593 | features |= NETIF_F_RXCSUM; | ||
594 | features |= NETIF_F_LLTX; | ||
595 | |||
596 | return features; | ||
597 | } | ||
598 | |||
748 | static int vlan_ethtool_get_settings(struct net_device *dev, | 599 | static int vlan_ethtool_get_settings(struct net_device *dev, |
749 | struct ethtool_cmd *cmd) | 600 | struct ethtool_cmd *cmd) |
750 | { | 601 | { |
@@ -760,18 +611,6 @@ static void vlan_ethtool_get_drvinfo(struct net_device *dev, | |||
760 | strcpy(info->fw_version, "N/A"); | 611 | strcpy(info->fw_version, "N/A"); |
761 | } | 612 | } |
762 | 613 | ||
763 | static u32 vlan_ethtool_get_rx_csum(struct net_device *dev) | ||
764 | { | ||
765 | const struct vlan_dev_info *vlan = vlan_dev_info(dev); | ||
766 | return dev_ethtool_get_rx_csum(vlan->real_dev); | ||
767 | } | ||
768 | |||
769 | static u32 vlan_ethtool_get_flags(struct net_device *dev) | ||
770 | { | ||
771 | const struct vlan_dev_info *vlan = vlan_dev_info(dev); | ||
772 | return dev_ethtool_get_flags(vlan->real_dev); | ||
773 | } | ||
774 | |||
775 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) | 614 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) |
776 | { | 615 | { |
777 | 616 | ||
@@ -809,32 +648,10 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st | |||
809 | return stats; | 648 | return stats; |
810 | } | 649 | } |
811 | 650 | ||
812 | static int vlan_ethtool_set_tso(struct net_device *dev, u32 data) | ||
813 | { | ||
814 | if (data) { | ||
815 | struct net_device *real_dev = vlan_dev_info(dev)->real_dev; | ||
816 | |||
817 | /* Underlying device must support TSO for VLAN-tagged packets | ||
818 | * and must have TSO enabled now. | ||
819 | */ | ||
820 | if (!(real_dev->vlan_features & NETIF_F_TSO)) | ||
821 | return -EOPNOTSUPP; | ||
822 | if (!(real_dev->features & NETIF_F_TSO)) | ||
823 | return -EINVAL; | ||
824 | dev->features |= NETIF_F_TSO; | ||
825 | } else { | ||
826 | dev->features &= ~NETIF_F_TSO; | ||
827 | } | ||
828 | return 0; | ||
829 | } | ||
830 | |||
831 | static const struct ethtool_ops vlan_ethtool_ops = { | 651 | static const struct ethtool_ops vlan_ethtool_ops = { |
832 | .get_settings = vlan_ethtool_get_settings, | 652 | .get_settings = vlan_ethtool_get_settings, |
833 | .get_drvinfo = vlan_ethtool_get_drvinfo, | 653 | .get_drvinfo = vlan_ethtool_get_drvinfo, |
834 | .get_link = ethtool_op_get_link, | 654 | .get_link = ethtool_op_get_link, |
835 | .get_rx_csum = vlan_ethtool_get_rx_csum, | ||
836 | .get_flags = vlan_ethtool_get_flags, | ||
837 | .set_tso = vlan_ethtool_set_tso, | ||
838 | }; | 655 | }; |
839 | 656 | ||
840 | static const struct net_device_ops vlan_netdev_ops = { | 657 | static const struct net_device_ops vlan_netdev_ops = { |
@@ -858,7 +675,9 @@ static const struct net_device_ops vlan_netdev_ops = { | |||
858 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, | 675 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, |
859 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, | 676 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, |
860 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, | 677 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, |
678 | .ndo_fcoe_ddp_target = vlan_dev_fcoe_ddp_target, | ||
861 | #endif | 679 | #endif |
680 | .ndo_fix_features = vlan_dev_fix_features, | ||
862 | }; | 681 | }; |
863 | 682 | ||
864 | void vlan_setup(struct net_device *dev) | 683 | void vlan_setup(struct net_device *dev) |