forked from Minki/linux
net: dsa: create a helper for locating EtherType DSA headers on RX
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>
This commit is contained in:
parent
6bef794da6
commit
5d928ff486
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
@ -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. */
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user