]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: hsr: Add VLAN support
authorWingMan Kwok <w-kwok2@ti.com>
Wed, 6 Nov 2024 09:17:07 +0000 (14:47 +0530)
committerJakub Kicinski <kuba@kernel.org>
Tue, 12 Nov 2024 00:40:44 +0000 (16:40 -0800)
Add support for creating VLAN interfaces over HSR/PRP interface.

Signed-off-by: WingMan Kwok <w-kwok2@ti.com>
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Link: https://patch.msgid.link/20241106091710.3308519-2-danishanwar@ti.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/hsr/hsr_device.c
net/hsr/hsr_forward.c

index ebdfd5b64e17a2a22555ee3c8a878d117919ac87..0ca47ebb01d36f20c76282314ceaac9cd1137297 100644 (file)
@@ -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.
index b38060246e62e8a8d94d78d32a530e3820e752a1..aa6acebc7c1ef6547451329fa23dafdc5443a5ba 100644 (file)
@@ -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;