From: WingMan Kwok <w-kw...@ti.com>

Add support for creating VLAN interfaces over HSR/PRP interface.

Signed-off-by: WingMan Kwok <w-kw...@ti.com>
Signed-off-by: Murali Karicheri <m-kariche...@ti.com>
Signed-off-by: MD Danish Anwar <danishan...@ti.com>
---
 net/hsr/hsr_device.c  |  5 -----
 net/hsr/hsr_forward.c | 19 ++++++++++++++-----
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index ebdfd5b64e17..0ca47ebb01d3 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -572,11 +572,6 @@ void hsr_dev_setup(struct net_device *dev)
                           NETIF_F_HW_VLAN_CTAG_TX;
 
        dev->features = dev->hw_features;
-
-       /* VLAN on top of HSR needs testing and probably some work on
-        * hsr_header_create() etc.
-        */
-       dev->features |= NETIF_F_VLAN_CHALLENGED;
 }
 
 /* Return true if dev is a HSR master; return false otherwise.
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;
-- 
2.34.1


Reply via email to