diff options
-rw-r--r-- | net/8021q/vlan_dev.c | 55 |
1 files changed, 9 insertions, 46 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 29aa4cc2a260..c6678605fc03 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -256,43 +256,18 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, | |||
256 | unsigned int len) | 256 | unsigned int len) |
257 | { | 257 | { |
258 | struct vlan_hdr *vhdr; | 258 | struct vlan_hdr *vhdr; |
259 | unsigned int vhdrlen = 0; | ||
259 | u16 vlan_tci = 0; | 260 | u16 vlan_tci = 0; |
260 | int rc = 0; | 261 | int rc; |
261 | int build_vlan_header = 0; | ||
262 | |||
263 | pr_debug("%s: skb: %p type: %hx len: %u vlan_id: %hx, daddr: %p\n", | ||
264 | __func__, skb, type, len, vlan_dev_info(dev)->vlan_id, | ||
265 | daddr); | ||
266 | 262 | ||
267 | if (WARN_ON(skb_headroom(skb) < dev->hard_header_len)) | 263 | if (WARN_ON(skb_headroom(skb) < dev->hard_header_len)) |
268 | return -ENOSPC; | 264 | return -ENOSPC; |
269 | 265 | ||
270 | /* build vlan header only if re_order_header flag is NOT set. This | 266 | if (!(vlan_dev_info(dev)->flags & VLAN_FLAG_REORDER_HDR)) { |
271 | * fixes some programs that get confused when they see a VLAN device | ||
272 | * sending a frame that is VLAN encoded (the consensus is that the VLAN | ||
273 | * device should look completely like an Ethernet device when the | ||
274 | * REORDER_HEADER flag is set) The drawback to this is some extra | ||
275 | * header shuffling in the hard_start_xmit. Users can turn off this | ||
276 | * REORDER behaviour with the vconfig tool. | ||
277 | */ | ||
278 | if (!(vlan_dev_info(dev)->flags & VLAN_FLAG_REORDER_HDR)) | ||
279 | build_vlan_header = 1; | ||
280 | |||
281 | if (build_vlan_header) { | ||
282 | vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN); | 267 | vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN); |
283 | 268 | ||
284 | /* build the four bytes that make this a VLAN header. */ | ||
285 | |||
286 | /* Now, construct the second two bytes. This field looks | ||
287 | * something like: | ||
288 | * usr_priority: 3 bits (high bits) | ||
289 | * CFI 1 bit | ||
290 | * VLAN ID 12 bits (low bits) | ||
291 | * | ||
292 | */ | ||
293 | vlan_tci = vlan_dev_info(dev)->vlan_id; | 269 | vlan_tci = vlan_dev_info(dev)->vlan_id; |
294 | vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); | 270 | vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); |
295 | |||
296 | vhdr->h_vlan_TCI = htons(vlan_tci); | 271 | vhdr->h_vlan_TCI = htons(vlan_tci); |
297 | 272 | ||
298 | /* | 273 | /* |
@@ -300,37 +275,25 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, | |||
300 | * put the length in here instead. It is up to the 802.2 | 275 | * put the length in here instead. It is up to the 802.2 |
301 | * layer to carry protocol information. | 276 | * layer to carry protocol information. |
302 | */ | 277 | */ |
303 | |||
304 | if (type != ETH_P_802_3) | 278 | if (type != ETH_P_802_3) |
305 | vhdr->h_vlan_encapsulated_proto = htons(type); | 279 | vhdr->h_vlan_encapsulated_proto = htons(type); |
306 | else | 280 | else |
307 | vhdr->h_vlan_encapsulated_proto = htons(len); | 281 | vhdr->h_vlan_encapsulated_proto = htons(len); |
308 | 282 | ||
309 | skb->protocol = htons(ETH_P_8021Q); | 283 | skb->protocol = htons(ETH_P_8021Q); |
284 | type = ETH_P_8021Q; | ||
285 | vhdrlen = VLAN_HLEN; | ||
310 | } | 286 | } |
311 | 287 | ||
312 | /* Before delegating work to the lower layer, enter our MAC-address */ | 288 | /* Before delegating work to the lower layer, enter our MAC-address */ |
313 | if (saddr == NULL) | 289 | if (saddr == NULL) |
314 | saddr = dev->dev_addr; | 290 | saddr = dev->dev_addr; |
315 | 291 | ||
292 | /* Now make the underlying real hard header */ | ||
316 | dev = vlan_dev_info(dev)->real_dev; | 293 | dev = vlan_dev_info(dev)->real_dev; |
317 | 294 | rc = dev_hard_header(skb, dev, type, daddr, saddr, len + vhdrlen); | |
318 | if (build_vlan_header) { | 295 | if (rc > 0) |
319 | /* Now make the underlying real hard header */ | 296 | rc += vhdrlen; |
320 | rc = dev_hard_header(skb, dev, ETH_P_8021Q, daddr, saddr, | ||
321 | len + VLAN_HLEN); | ||
322 | if (rc > 0) | ||
323 | rc += VLAN_HLEN; | ||
324 | else if (rc < 0) | ||
325 | rc -= VLAN_HLEN; | ||
326 | } else | ||
327 | /* If here, then we'll just make a normal looking ethernet | ||
328 | * frame, but, the hard_start_xmit method will insert the tag | ||
329 | * (it has to be able to do this for bridged and other skbs | ||
330 | * that don't come down the protocol stack in an orderly manner. | ||
331 | */ | ||
332 | rc = dev_hard_header(skb, dev, type, daddr, saddr, len); | ||
333 | |||
334 | return rc; | 297 | return rc; |
335 | } | 298 | } |
336 | 299 | ||