Packet parsing and type detection fail for packets containing Arista Vendor Specific Protocol (AVSP) headers. This patch adds support for three L2 headers: Arista TGen, Arista 64-bit Timestamp and Arista 48-bit Timestamp. Signed-off-by: Denis Davidoglu --- lib/net/rte_ether.h | 31 ++++++++++++++ lib/net/rte_net.c | 99 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/lib/net/rte_ether.h b/lib/net/rte_ether.h index c9a0b536c3..054a54af40 100644 --- a/lib/net/rte_ether.h +++ b/lib/net/rte_ether.h @@ -62,6 +62,13 @@ extern "C" {                               ((pri) << RTE_VLAN_PRI_SHIFT) |    \                               ((dei) << RTE_VLAN_DEI_SHIFT)) +/* Arista Vendor Specific Protocol (AVSP) Header Types */ +#define RTE_AVSP_SUBTYPE_TGEN            0xCAFE +#define RTE_AVSP_VERSION_TGEN            0x0001 +#define RTE_AVSP_SUBTYPE_TIMESTAMP 0x0001 +#define RTE_AVSP_VERSION_64_MASK   0x0010 +#define RTE_AVSP_VERSION_48_MASK   0x0020 + /** * Ethernet address: * A universally administered address is uniquely assigned to a device by its @@ -323,7 +330,30 @@ static_assert(sizeof(struct rte_vlan_hdr) == 4, static_assert(alignof(struct rte_vlan_hdr) == 2,            "alignof(struct rte_vlan_hdr) == 2"); +/* Arista Vendor Specific Protocol (AVSP) Headers */ +struct __rte_packed_begin rte_avsp_common_hdr { +     rte_be16_t subtype; +     rte_be16_t version; +} __rte_packed_end; + +struct __rte_packed_begin rte_avsp_tgen_hdr { +     struct rte_avsp_common_hdr common; +     rte_be16_t eth_proto; /**< Ethernet type of encapsulated frame. */ +} __rte_packed_end; + +struct __rte_packed_begin rte_avsp_timestamp_64_hdr { +     struct rte_avsp_common_hdr common; +     rte_be32_t sec; /**< Seconds (IEEE 1588 time of day format). */ +     rte_be32_t ns; /**< Nanoseconds (IEEE 1588 time of day format). */ +     rte_be16_t eth_proto; /**< Ethernet type of encapsulated frame. */ +} __rte_packed_end; +struct __rte_packed_begin rte_avsp_timestamp_48_hdr { +     struct rte_avsp_common_hdr common; +     rte_be16_t sec; /**< Seconds (IEEE 1588 time of day format). */ +     rte_be32_t ns; /**< Nanoseconds (IEEE 1588 time of day format). */ +     rte_be16_t eth_proto; /**< Ethernet type of encapsulated frame. */ +} __rte_packed_end; /* Ethernet frame types */ #define RTE_ETHER_TYPE_IPV4 0x0800 /**< IPv4 Protocol. */ @@ -346,6 +376,7 @@ static_assert(alignof(struct rte_vlan_hdr) == 2, #define RTE_ETHER_TYPE_MPLS 0x8847 /**< MPLS ethertype. */ #define RTE_ETHER_TYPE_MPLSM 0x8848 /**< MPLS multicast ethertype. */ #define RTE_ETHER_TYPE_ECPRI 0xAEFE /**< eCPRI ethertype (.1Q supported). */ +#define RTE_ETHER_TYPE_AVSP 0xD28B /**< Arista ethertype */ /** * Extract VLAN tag information into mbuf diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c index d680accc16..d260cfdf0a 100644 --- a/lib/net/rte_net.c +++ b/lib/net/rte_net.c @@ -269,7 +269,56 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,            off += 2 * sizeof(*vh);            hdr_lens->l2_len += 2 * sizeof(*vh);            proto = vh->eth_proto; -     } else if ((proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) || +     } +     if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_AVSP)) { +           union { +                 const struct rte_avsp_common_hdr *common; +                 const struct rte_avsp_tgen_hdr *tgen; +                 const struct rte_avsp_timestamp_64_hdr *t64; +                 const struct rte_avsp_timestamp_48_hdr *t48; +           } ah; +           union { +                 struct rte_avsp_common_hdr common; +                 struct rte_avsp_tgen_hdr tgen; +                 struct rte_avsp_timestamp_64_hdr t64; +                 struct rte_avsp_timestamp_48_hdr t48; +           } ah_copy; + +           ah.common = rte_pktmbuf_read(m, off, sizeof(*ah.common), +                                                      &ah_copy.common); +           if (unlikely(ah.common == NULL)) +                 return pkt_type; +           uint16_t subtype = rte_be_to_cpu_16(ah.common->subtype); +           uint16_t version = rte_be_to_cpu_16(ah.common->version); + +           if (subtype == RTE_AVSP_SUBTYPE_TGEN && +                       (version == RTE_AVSP_VERSION_TGEN)) { +                 ah.tgen = rte_pktmbuf_read(m, off, sizeof(*ah.tgen), &ah_copy); +                 if (unlikely(ah.tgen == NULL)) +                       return pkt_type; +                 off += sizeof(*ah.tgen); +                 hdr_lens->l2_len += sizeof(*ah.tgen); +                 proto = ah.tgen->eth_proto; +           } else if ((subtype == RTE_AVSP_SUBTYPE_TIMESTAMP && +                             (version & RTE_AVSP_VERSION_64_MASK) != 0)) { +                 ah.t64 = rte_pktmbuf_read(m, off, sizeof(*ah.t64), &ah_copy); +                 if (unlikely(ah.t64 == NULL)) +                       return pkt_type; +                 off += sizeof(*ah.t64); +                 hdr_lens->l2_len += sizeof(*ah.t64); +                 proto = ah.t64->eth_proto; +           } else if ((subtype == RTE_AVSP_SUBTYPE_TIMESTAMP && +                             (version & RTE_AVSP_VERSION_48_MASK) != 0)) { +                 ah.t48 = rte_pktmbuf_read(m, off, sizeof(*ah.t48), &ah_copy); +                 if (unlikely(ah.t48 == NULL)) +                       return pkt_type; +                 off += sizeof(*ah.t48); +                 hdr_lens->l2_len += sizeof(*ah.t48); +                 proto = ah.t48->eth_proto; +           } else +                 return pkt_type; +     } +     if ((proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) ||            (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLSM))) {            unsigned int i;            const struct rte_mpls_hdr *mh; @@ -421,6 +470,54 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,            hdr_lens->inner_l2_len += 2 * sizeof(*vh);            proto = vh->eth_proto;      } +     if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_AVSP)) { +           union { +                 const struct rte_avsp_common_hdr *common; +                 const struct rte_avsp_tgen_hdr *tgen; +                 const struct rte_avsp_timestamp_64_hdr *t64; +                 const struct rte_avsp_timestamp_48_hdr *t48; +           } ah; +           union { +                 struct rte_avsp_common_hdr common; +                 struct rte_avsp_tgen_hdr tgen; +                 struct rte_avsp_timestamp_64_hdr t64; +                 struct rte_avsp_timestamp_48_hdr t48; +           } ah_copy; + +           ah.common = rte_pktmbuf_read(m, off, sizeof(*ah.common), +                                                      &ah_copy.common); +           if (unlikely(ah.common == NULL)) +                 return pkt_type; +           uint16_t subtype = rte_be_to_cpu_16(ah.common->subtype); +           uint16_t version = rte_be_to_cpu_16(ah.common->version); + +           if (subtype == RTE_AVSP_SUBTYPE_TGEN && +                       (version == RTE_AVSP_VERSION_TGEN)) { +                 ah.tgen = rte_pktmbuf_read(m, off, sizeof(*ah.tgen), &ah_copy); +                 if (unlikely(ah.tgen == NULL)) +                       return pkt_type; +                 off += sizeof(*ah.tgen); +                 hdr_lens->inner_l2_len += sizeof(*ah.tgen); +                 proto = ah.tgen->eth_proto; +           } else if ((subtype == RTE_AVSP_SUBTYPE_TIMESTAMP && +                             (version & RTE_AVSP_VERSION_64_MASK) != 0)) { +                 ah.t64 = rte_pktmbuf_read(m, off, sizeof(*ah.t64), &ah_copy); +                 if (unlikely(ah.t64 == NULL)) +                       return pkt_type; +                 off += sizeof(*ah.t64); +                 hdr_lens->inner_l2_len += sizeof(*ah.t64); +                 proto = ah.t64->eth_proto; +           } else if ((subtype == RTE_AVSP_SUBTYPE_TIMESTAMP && +                             (version & RTE_AVSP_VERSION_48_MASK) != 0)) { +                 ah.t48 = rte_pktmbuf_read(m, off, sizeof(*ah.t48), &ah_copy); +                 if (unlikely(ah.t48 == NULL)) +                       return pkt_type; +                 off += sizeof(*ah.t48); +                 hdr_lens->inner_l2_len += sizeof(*ah.t48); +                 proto = ah.t48->eth_proto; +           } else +                 return pkt_type; +     }      if ((layers & RTE_PTYPE_INNER_L3_MASK) == 0)            return pkt_type; -- 2.48.1