aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/8021q/vlan_dev.c55
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