Messages in this thread Patch in this message | | | From | Vladimir Oltean <> | Subject | [PATCH v3 net-next 13/17] net: dsa: sja1105: Receive and decode meta frames | Date | Tue, 4 Jun 2019 20:07:52 +0300 |
| |
This adds support in the tagger for understanding the source port and switch id of meta frames. Their timestamp is also extracted but not used yet - this needs to be done in a state machine that modifies the previously received timestampable frame - will be added in a follow-up patch.
Signed-off-by: Vladimir Oltean <olteanv@gmail.com> --- Changes in v3:
Split from previous 09/10 patch (no functional changes).
Changes in v2:
None.
net/dsa/tag_sja1105.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index 9ff7cfa6ea20..6ec9a32dda62 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -7,6 +7,36 @@ #include <linux/packing.h> #include "dsa_priv.h" +struct sja1105_meta { + u64 tstamp; + u64 dmac_byte_4; + u64 dmac_byte_3; + u64 source_port; + u64 switch_id; +}; + +static void sja1105_meta_unpack(const struct sk_buff *skb, + struct sja1105_meta *meta) +{ + u8 *buf = skb_mac_header(skb) + ETH_HLEN; + + /* UM10944.pdf section 4.2.17 AVB Parameters: + * Structure of the meta-data follow-up frame. + * It is in network byte order, so there are no quirks + * while unpacking the meta frame. + * + * Also SJA1105 E/T only populates bits 23:0 of the timestamp + * whereas P/Q/R/S does 32 bits. Since the structure is the + * same and the E/T puts zeroes in the high-order byte, use + * a unified unpacking command for both device series. + */ + packing(buf, &meta->tstamp, 31, 0, 4, UNPACK, 0); + packing(buf + 4, &meta->dmac_byte_4, 7, 0, 1, UNPACK, 0); + packing(buf + 5, &meta->dmac_byte_3, 7, 0, 1, UNPACK, 0); + packing(buf + 6, &meta->source_port, 7, 0, 1, UNPACK, 0); + packing(buf + 7, &meta->switch_id, 7, 0, 1, UNPACK, 0); +} + static inline bool sja1105_is_meta_frame(const struct sk_buff *skb) { const struct ethhdr *hdr = eth_hdr(skb); @@ -28,6 +58,8 @@ static inline bool sja1105_is_meta_frame(const struct sk_buff *skb) */ static bool sja1105_filter(const struct sk_buff *skb, struct net_device *dev) { + if (sja1105_is_meta_frame(skb)) + return true; if (sja1105_is_link_local(skb)) return true; if (!dsa_port_is_vlan_filtering(dev->dsa_ptr)) @@ -66,13 +98,18 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, struct net_device *netdev, struct packet_type *pt) { + struct sja1105_meta meta = {0}; int source_port, switch_id; struct sk_buff *nskb; u16 tpid, vid, tci; + bool is_link_local; bool is_tagged; + bool is_meta; nskb = dsa_8021q_rcv(skb, netdev, pt, &tpid, &tci); is_tagged = (nskb && tpid == ETH_P_SJA1105); + is_link_local = sja1105_is_link_local(skb); + is_meta = sja1105_is_meta_frame(skb); skb->offload_fwd_mark = 1; @@ -82,7 +119,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, source_port = dsa_8021q_rx_source_port(vid); switch_id = dsa_8021q_rx_switch_id(vid); skb->priority = (tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; - } else if (sja1105_is_link_local(skb)) { + } else if (is_link_local) { struct ethhdr *hdr = eth_hdr(skb); /* Management traffic path. Switch embeds the switch ID and @@ -94,6 +131,10 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, /* Clear the DMAC bytes that were mangled by the switch */ hdr->h_dest[3] = 0; hdr->h_dest[4] = 0; + } else if (is_meta) { + sja1105_meta_unpack(skb, &meta); + source_port = meta.source_port; + switch_id = meta.switch_id; } else { return NULL; } -- 2.17.1
| |