return ptype_l4_proto[proto];
}
+/* get inner l3 packet type from ip6 next protocol */
+static uint32_t
+ptype_inner_l3_ip6(uint8_t ip6_proto)
+{
+ static const uint32_t ptype_inner_ip6_ext_proto_map[256] = {
+ [IPPROTO_HOPOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_ROUTING] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_FRAGMENT] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_ESP] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_AH] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_DSTOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ };
+
+ return RTE_PTYPE_INNER_L3_IPV6 +
+ ptype_inner_ip6_ext_proto_map[ip6_proto];
+}
+
+/* get inner l3 packet type from ip version and header length */
+static uint32_t
+ptype_inner_l3_ip(uint8_t ipv_ihl)
+{
+ static const uint32_t ptype_inner_l3_ip_proto_map[256] = {
+ [0x45] = RTE_PTYPE_INNER_L3_IPV4,
+ [0x46] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x47] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x48] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x49] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4A] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4B] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4C] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4D] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4E] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4F] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ };
+
+ return ptype_inner_l3_ip_proto_map[ipv_ihl];
+}
+
+/* get inner l4 packet type from proto */
+static uint32_t
+ptype_inner_l4(uint8_t proto)
+{
+ static const uint32_t ptype_inner_l4_proto[256] = {
+ [IPPROTO_UDP] = RTE_PTYPE_INNER_L4_UDP,
+ [IPPROTO_TCP] = RTE_PTYPE_INNER_L4_TCP,
+ [IPPROTO_SCTP] = RTE_PTYPE_INNER_L4_SCTP,
+ };
+
+ return ptype_inner_l4_proto[proto];
+}
+
+/* get the tunnel packet type if any, update proto. */
+static uint32_t
+ptype_tunnel(uint16_t *proto)
+{
+ switch (*proto) {
+ case IPPROTO_IPIP:
+ *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+ return RTE_PTYPE_TUNNEL_IP;
+ case IPPROTO_IPV6:
+ *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
+ return RTE_PTYPE_TUNNEL_IP; /* IP is also valid for IPv6 */
+ default:
+ return 0;
+ }
+}
+
/* get the ipv4 header length */
static uint8_t
ip4_hlen(const struct ipv4_hdr *hdr)
pkt_type |= ptype_l3_ip(ip4h->version_ihl);
hdr_lens->l3_len = ip4_hlen(ip4h);
off += hdr_lens->l3_len;
- if (ip4h->fragment_offset &
- rte_cpu_to_be_16(IPV4_HDR_OFFSET_MASK |
- IPV4_HDR_MF_FLAG)) {
+ if (ip4h->fragment_offset & rte_cpu_to_be_16(
+ IPV4_HDR_OFFSET_MASK | IPV4_HDR_MF_FLAG)) {
pkt_type |= RTE_PTYPE_L4_FRAG;
hdr_lens->l4_len = 0;
return pkt_type;
if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP) {
hdr_lens->l4_len = sizeof(struct udp_hdr);
+ return pkt_type;
} else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) {
const struct tcp_hdr *th;
struct tcp_hdr th_copy;
return pkt_type & (RTE_PTYPE_L2_MASK |
RTE_PTYPE_L3_MASK);
hdr_lens->l4_len = (th->data_off & 0xf0) >> 2;
+ return pkt_type;
} else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_SCTP) {
hdr_lens->l4_len = sizeof(struct sctp_hdr);
+ return pkt_type;
} else {
hdr_lens->l4_len = 0;
+ pkt_type |= ptype_tunnel(&proto);
+ hdr_lens->tunnel_len = 0;
+ }
+
+ /* same job for inner header: we need to duplicate the code
+ * because the packet types do not have the same value.
+ */
+ hdr_lens->inner_l2_len = 0;
+
+ if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
+ const struct ipv4_hdr *ip4h;
+ struct ipv4_hdr ip4h_copy;
+
+ ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
+ if (unlikely(ip4h == NULL))
+ return pkt_type;
+
+ pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl);
+ hdr_lens->inner_l3_len = ip4_hlen(ip4h);
+ off += hdr_lens->inner_l3_len;
+ if (ip4h->fragment_offset &
+ rte_cpu_to_be_16(IPV4_HDR_OFFSET_MASK |
+ IPV4_HDR_MF_FLAG)) {
+ pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
+ hdr_lens->inner_l4_len = 0;
+ return pkt_type;
+ }
+ proto = ip4h->next_proto_id;
+ pkt_type |= ptype_inner_l4(proto);
+ } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv6)) {
+ const struct ipv6_hdr *ip6h;
+ struct ipv6_hdr ip6h_copy;
+ int frag = 0;
+
+ ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
+ if (unlikely(ip6h == NULL))
+ return pkt_type;
+
+ proto = ip6h->proto;
+ hdr_lens->inner_l3_len = sizeof(*ip6h);
+ off += hdr_lens->inner_l3_len;
+ pkt_type |= ptype_inner_l3_ip6(proto);
+ if ((pkt_type & RTE_PTYPE_INNER_L3_MASK) ==
+ RTE_PTYPE_INNER_L3_IPV6_EXT) {
+ uint32_t prev_off;
+
+ prev_off = off;
+ proto = skip_ip6_ext(proto, m, &off, &frag);
+ hdr_lens->inner_l3_len += off - prev_off;
+ }
+ if (proto == 0)
+ return pkt_type;
+ if (frag) {
+ pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
+ hdr_lens->inner_l4_len = 0;
+ return pkt_type;
+ }
+ pkt_type |= ptype_inner_l4(proto);
+ }
+
+ if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_UDP) {
+ hdr_lens->inner_l4_len = sizeof(struct udp_hdr);
+ } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
+ RTE_PTYPE_INNER_L4_TCP) {
+ const struct tcp_hdr *th;
+ struct tcp_hdr th_copy;
+
+ th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
+ if (unlikely(th == NULL))
+ return pkt_type & (RTE_PTYPE_INNER_L2_MASK |
+ RTE_PTYPE_INNER_L3_MASK);
+ hdr_lens->inner_l4_len = (th->data_off & 0xf0) >> 2;
+ } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
+ RTE_PTYPE_INNER_L4_SCTP) {
+ hdr_lens->inner_l4_len = sizeof(struct sctp_hdr);
+ } else {
+ hdr_lens->inner_l4_len = 0;
}
return pkt_type;