diff options
Diffstat (limited to 'net/hsr/hsr_forward.c')
-rw-r--r-- | net/hsr/hsr_forward.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index b38060246e62..aa6acebc7c1e 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -280,6 +280,7 @@ static struct sk_buff *hsr_fill_tag(struct sk_buff *skb, struct hsr_port *port, u8 proto_version) { struct hsr_ethhdr *hsr_ethhdr; + unsigned char *pc; int lsdu_size; /* pad to minimum packet size which is 60 + 6 (HSR tag) */ @@ -290,7 +291,18 @@ static struct sk_buff *hsr_fill_tag(struct sk_buff *skb, if (frame->is_vlan) lsdu_size -= 4; - hsr_ethhdr = (struct hsr_ethhdr *)skb_mac_header(skb); + pc = skb_mac_header(skb); + if (frame->is_vlan) + /* This 4-byte shift (size of a vlan tag) does not + * mean that the ethhdr starts there. But rather it + * provides the proper environment for accessing + * the fields, such as hsr_tag etc., just like + * when the vlan tag is not there. This is because + * the hsr tag is after the vlan tag. + */ + hsr_ethhdr = (struct hsr_ethhdr *)(pc + VLAN_HLEN); + else + hsr_ethhdr = (struct hsr_ethhdr *)pc; hsr_set_path_id(hsr_ethhdr, port); set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size); @@ -368,7 +380,7 @@ struct sk_buff *prp_create_tagged_frame(struct hsr_frame_info *frame, return skb_clone(frame->skb_std, GFP_ATOMIC); } - skb = skb_copy_expand(frame->skb_std, 0, + skb = skb_copy_expand(frame->skb_std, skb_headroom(frame->skb_std), skb_tailroom(frame->skb_std) + HSR_HLEN, GFP_ATOMIC); return prp_fill_rct(skb, frame, port); @@ -690,9 +702,6 @@ static int fill_frame_info(struct hsr_frame_info *frame, if (frame->is_vlan) { vlan_hdr = (struct hsr_vlan_ethhdr *)ethhdr; proto = vlan_hdr->vlanhdr.h_vlan_encapsulated_proto; - /* FIXME: */ - netdev_warn_once(skb->dev, "VLAN not yet supported"); - return -EINVAL; } frame->is_from_san = false; |