]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
net: dsa: create a helper for locating EtherType DSA headers on RX
authorVladimir Oltean <vladimir.oltean@nxp.com>
Tue, 10 Aug 2021 13:13:55 +0000 (16:13 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 11 Aug 2021 13:44:58 +0000 (14:44 +0100)
It seems that protocol tagging driver writers are always surprised about
the formula they use to reach their EtherType header on RX, which
becomes apparent from the fact that there are comments in multiple
drivers that mention the same information.

Create a helper that returns a void pointer to skb->data - 2, as well as
centralize the explanation why that is the case.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/dsa/dsa_priv.h
net/dsa/tag_brcm.c
net/dsa/tag_dsa.c
net/dsa/tag_lan9303.c
net/dsa/tag_mtk.c
net/dsa/tag_qca.c
net/dsa/tag_rtl4_a.c
net/dsa/tag_sja1105.c

index 28e1fbe64ee0dfb8ba5a829c1b69340e75f8d27a..ee194df6890261789901c50f6bd21be0737e81b3 100644 (file)
@@ -507,6 +507,20 @@ static inline void dsa_alloc_etype_header(struct sk_buff *skb, int len)
        memmove(skb->data, skb->data + len, 2 * ETH_ALEN);
 }
 
+/* On RX, eth_type_trans() on the DSA master pulls ETH_HLEN bytes starting from
+ * skb_mac_header(skb), which leaves skb->data pointing at the first byte after
+ * what the DSA master perceives as the EtherType (the beginning of the L3
+ * protocol). Since DSA EtherType header taggers treat the EtherType as part of
+ * the DSA tag itself, and the EtherType is 2 bytes in length, the DSA header
+ * is located 2 bytes behind skb->data. Note that EtherType in this context
+ * means the first 2 bytes of the DSA header, not the encapsulated EtherType
+ * that will become visible after the DSA header is stripped.
+ */
+static inline void *dsa_etype_header_pos_rx(struct sk_buff *skb)
+{
+       return skb->data - 2;
+}
+
 /* switch.c */
 int dsa_switch_register_notifier(struct dsa_switch *ds);
 void dsa_switch_unregister_notifier(struct dsa_switch *ds);
index c62a89bb8de3c6b509d6dada1836748827548d94..96dbb8ee2fee111390988241ac562fbc90f1de39 100644 (file)
@@ -254,7 +254,7 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
        if (unlikely(!pskb_may_pull(skb, BRCM_LEG_PORT_ID)))
                return NULL;
 
-       brcm_tag = skb->data - 2;
+       brcm_tag = dsa_etype_header_pos_rx(skb);
 
        source_port = brcm_tag[5] & BRCM_LEG_PORT_ID;
 
index ab2c63859d121e2225a8eb83602b5ec39d745360..2eeabab27078a5f0ecb2244caa7da61ef5d9abd1 100644 (file)
@@ -205,7 +205,7 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
        u8 *dsa_header;
 
        /* The ethertype field is part of the DSA header. */
-       dsa_header = skb->data - 2;
+       dsa_header = dsa_etype_header_pos_rx(skb);
 
        cmd = dsa_header[0] >> 6;
        switch (cmd) {
index e8ad3727433edda3a79c45960112eddf4b82d27f..d06951273127024b7f69431287a38fda307a5f4f 100644 (file)
@@ -86,13 +86,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)
                return NULL;
        }
 
-       /* '->data' points into the middle of our special VLAN tag information:
-        *
-        * ~ MAC src   | 0x81 | 0x00 | 0xyy | 0xzz | ether type
-        *                           ^
-        *                        ->data
-        */
-       lan9303_tag = (__be16 *)(skb->data - 2);
+       lan9303_tag = dsa_etype_header_pos_rx(skb);
 
        if (lan9303_tag[0] != htons(ETH_P_8021Q)) {
                dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid VLAN marker\n");
index 06d1cfc6d19b42ab19de95f21073ee262157f334..a75f99e5fbe39cd385b858585f872e086069438e 100644 (file)
@@ -70,11 +70,7 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
        if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
                return NULL;
 
-       /* The MTK header is added by the switch between src addr
-        * and ethertype at this point, skb->data points to 2 bytes
-        * after src addr so header should be 2 bytes right before.
-        */
-       phdr = (__be16 *)(skb->data - 2);
+       phdr = dsa_etype_header_pos_rx(skb);
        hdr = ntohs(*phdr);
 
        /* Remove MTK tag and recalculate checksum. */
index c68a814188e7cb5bbb5d56bbdfc7315f0cd90f8f..79a81569d7ec177a5f3e8d6143061cbd926851ce 100644 (file)
@@ -58,11 +58,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
        if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN)))
                return NULL;
 
-       /* The QCA header is added by the switch between src addr and Ethertype
-        * At this point, skb->data points to ethertype so header should be
-        * right before
-        */
-       phdr = (__be16 *)(skb->data - 2);
+       phdr = dsa_etype_header_pos_rx(skb);
        hdr = ntohs(*phdr);
 
        /* Make sure the version is correct */
index 06e901eda29801521b96a35118616cb3c0345bf1..947247d2124e430cb9c01e9504f471fae4a1691a 100644 (file)
@@ -76,12 +76,7 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
        if (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN)))
                return NULL;
 
-       /* The RTL4 header has its own custom Ethertype 0x8899 and that
-        * starts right at the beginning of the packet, after the src
-        * ethernet addr. Apparently skb->data always points 2 bytes in,
-        * behind the Ethertype.
-        */
-       tag = skb->data - 2;
+       tag = dsa_etype_header_pos_rx(skb);
        p = (__be16 *)tag;
        etype = ntohs(*p);
        if (etype != RTL4_A_ETHERTYPE) {
index 03d500236e0ed31ebbc25f9e1a9f028b5d50d3de..4f90e2756124f67b637136abc81bd0808c1d67db 100644 (file)
@@ -442,11 +442,11 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
 
 static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)
 {
+       u8 *buf = dsa_etype_header_pos_rx(skb) + SJA1110_HEADER_LEN;
        int switch_id = SJA1110_RX_HEADER_SWITCH_ID(rx_header);
        int n_ts = SJA1110_RX_HEADER_N_TS(rx_header);
        struct net_device *master = skb->dev;
        struct dsa_port *cpu_dp;
-       u8 *buf = skb->data + 2;
        struct dsa_switch *ds;
        int i;