Skip to content

Commit

Permalink
net: dsa: create a helper for locating EtherType DSA headers on RX
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vladimir Oltean authored and David S. Miller committed Aug 11, 2021
1 parent 6bef794 commit 5d928ff
Show file tree
Hide file tree
Showing 8 changed files with 21 additions and 26 deletions.
14 changes: 14 additions & 0 deletions net/dsa/dsa_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion net/dsa/tag_brcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion net/dsa/tag_dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 1 addition & 7 deletions net/dsa/tag_lan9303.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
6 changes: 1 addition & 5 deletions net/dsa/tag_mtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
6 changes: 1 addition & 5 deletions net/dsa/tag_qca.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
7 changes: 1 addition & 6 deletions net/dsa/tag_rtl4_a.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion net/dsa/tag_sja1105.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 5d928ff

Please sign in to comment.