X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_net%2Frte_net.c;h=a3ca04032745c8a53b0c24daea8c167b12e97aaf;hb=5aac4f74cd5a04c416366c285660c7f56c768c04;hp=87294bba9a55e41baaa2c15b8d502b10c04d4eb4;hpb=b32159dccacf54d49b5754b35ac3109331840121;p=dpdk.git diff --git a/lib/librte_net/rte_net.c b/lib/librte_net/rte_net.c index 87294bba9a..a3ca040327 100644 --- a/lib/librte_net/rte_net.c +++ b/lib/librte_net/rte_net.c @@ -41,6 +41,7 @@ #include #include #include +#include #include /* get l3 packet type from ip6 next protocol */ @@ -150,11 +151,43 @@ ptype_inner_l4(uint8_t proto) return ptype_inner_l4_proto[proto]; } -/* get the tunnel packet type if any, update proto. */ +/* get the tunnel packet type if any, update proto and off. */ static uint32_t -ptype_tunnel(uint16_t *proto) +ptype_tunnel(uint16_t *proto, const struct rte_mbuf *m, + uint32_t *off) { switch (*proto) { + case IPPROTO_GRE: { + static const uint8_t opt_len[16] = { + [0x0] = 4, + [0x1] = 8, + [0x2] = 8, + [0x8] = 8, + [0x3] = 12, + [0x9] = 12, + [0xa] = 12, + [0xb] = 16, + }; + const struct gre_hdr *gh; + struct gre_hdr gh_copy; + uint16_t flags; + + gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy); + if (unlikely(gh == NULL)) + return 0; + + flags = rte_be_to_cpu_16(*(const uint16_t *)gh); + flags >>= 12; + if (opt_len[flags] == 0) + return 0; + + *off += opt_len[flags]; + *proto = gh->proto; + if (*proto == rte_cpu_to_be_16(ETHER_TYPE_TEB)) + return RTE_PTYPE_TUNNEL_NVGRE; + else + return RTE_PTYPE_TUNNEL_GRE; + } case IPPROTO_IPIP: *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv4); return RTE_PTYPE_TUNNEL_IP; @@ -221,7 +254,7 @@ skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off, /* parse mbuf data to get packet type */ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, - struct rte_net_hdr_lens *hdr_lens) + struct rte_net_hdr_lens *hdr_lens, uint32_t layers) { struct rte_net_hdr_lens local_hdr_lens; const struct ether_hdr *eh; @@ -240,6 +273,9 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, off = sizeof(*eh); hdr_lens->l2_len = off; + if ((layers & RTE_PTYPE_L2_MASK) == 0) + return 0; + if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) goto l3; /* fast path if packet is IPv4 */ @@ -269,6 +305,9 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, } l3: + if ((layers & RTE_PTYPE_L3_MASK) == 0) + return pkt_type; + if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) { const struct ipv4_hdr *ip4h; struct ipv4_hdr ip4h_copy; @@ -280,6 +319,10 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, pkt_type |= ptype_l3_ip(ip4h->version_ihl); hdr_lens->l3_len = ip4_hlen(ip4h); off += hdr_lens->l3_len; + + if ((layers & RTE_PTYPE_L4_MASK) == 0) + return pkt_type; + if (ip4h->fragment_offset & rte_cpu_to_be_16( IPV4_HDR_OFFSET_MASK | IPV4_HDR_MF_FLAG)) { pkt_type |= RTE_PTYPE_L4_FRAG; @@ -307,6 +350,10 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, } if (proto == 0) return pkt_type; + + if ((layers & RTE_PTYPE_L4_MASK) == 0) + return pkt_type; + if (frag) { pkt_type |= RTE_PTYPE_L4_FRAG; hdr_lens->l4_len = 0; @@ -332,15 +379,63 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, hdr_lens->l4_len = sizeof(struct sctp_hdr); return pkt_type; } else { + uint32_t prev_off = off; + hdr_lens->l4_len = 0; - pkt_type |= ptype_tunnel(&proto); - hdr_lens->tunnel_len = 0; + + if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0) + return pkt_type; + + pkt_type |= ptype_tunnel(&proto, m, &off); + hdr_lens->tunnel_len = off - prev_off; } /* same job for inner header: we need to duplicate the code * because the packet types do not have the same value. */ + if ((layers & RTE_PTYPE_INNER_L2_MASK) == 0) + return pkt_type; + hdr_lens->inner_l2_len = 0; + if (proto == rte_cpu_to_be_16(ETHER_TYPE_TEB)) { + eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy); + if (unlikely(eh == NULL)) + return pkt_type; + pkt_type |= RTE_PTYPE_INNER_L2_ETHER; + proto = eh->ether_type; + off += sizeof(*eh); + hdr_lens->inner_l2_len = sizeof(*eh); + } + + if (proto == rte_cpu_to_be_16(ETHER_TYPE_VLAN)) { + const struct vlan_hdr *vh; + struct vlan_hdr vh_copy; + + pkt_type &= ~RTE_PTYPE_INNER_L2_MASK; + pkt_type |= RTE_PTYPE_INNER_L2_ETHER_VLAN; + vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy); + if (unlikely(vh == NULL)) + return pkt_type; + off += sizeof(*vh); + hdr_lens->inner_l2_len += sizeof(*vh); + proto = vh->eth_proto; + } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_QINQ)) { + const struct vlan_hdr *vh; + struct vlan_hdr vh_copy; + + pkt_type &= ~RTE_PTYPE_INNER_L2_MASK; + pkt_type |= RTE_PTYPE_INNER_L2_ETHER_QINQ; + vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh), + &vh_copy); + if (unlikely(vh == NULL)) + return pkt_type; + off += 2 * sizeof(*vh); + hdr_lens->inner_l2_len += 2 * sizeof(*vh); + proto = vh->eth_proto; + } + + if ((layers & RTE_PTYPE_INNER_L3_MASK) == 0) + return pkt_type; if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) { const struct ipv4_hdr *ip4h; @@ -353,6 +448,9 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl); hdr_lens->inner_l3_len = ip4_hlen(ip4h); off += hdr_lens->inner_l3_len; + + if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0) + return pkt_type; if (ip4h->fragment_offset & rte_cpu_to_be_16(IPV4_HDR_OFFSET_MASK | IPV4_HDR_MF_FLAG)) { @@ -385,6 +483,10 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, } if (proto == 0) return pkt_type; + + if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0) + return pkt_type; + if (frag) { pkt_type |= RTE_PTYPE_INNER_L4_FRAG; hdr_lens->inner_l4_len = 0;