This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "".
The branch, master has been updated via ad3417a6fd2ba93616b937f9a2d8642eceeb0bf8 (commit) via db62337f2c0a3add91bbdbaa096f2a3c04162c60 (commit) via df1c292ed40d4c2c480917f1eab06a046c93c3b1 (commit) from 49c671e80fd2c88b6f36337ebd1cd4748eb8bae1 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit ad3417a6fd2ba93616b937f9a2d8642eceeb0bf8 Author: Bogdan Pricope bogdan.pricope@linaro.org Date: Thu May 10 13:52:43 2018 +0300
linux-gen: pktio: dpdk: integrate csum with packet parser
Merge csum validation and packet parser to reduce branching.
Signed-off-by: Bogdan Pricope bogdan.pricope@linaro.org Reviewed-and-tested-by: Matias Elo matias.elo@nokia.com Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_packet_dpdk.h b/platform/linux-generic/include/odp_packet_dpdk.h index 31d4557e..020c2b97 100644 --- a/platform/linux-generic/include/odp_packet_dpdk.h +++ b/platform/linux-generic/include/odp_packet_dpdk.h @@ -78,16 +78,18 @@ int dpdk_packet_parse_common(packet_parser_t *pkt_hdr, uint32_t pkt_len, uint32_t seg_len, struct rte_mbuf *mbuf, - int layer); + int layer, + odp_pktin_config_opt_t pktin_cfg);
static inline int dpdk_packet_parse_layer(odp_packet_hdr_t *pkt_hdr, struct rte_mbuf *mbuf, - odp_pktio_parser_layer_t layer) + odp_pktio_parser_layer_t layer, + odp_pktin_config_opt_t pktin_cfg) { uint32_t seg_len = pkt_hdr->buf_hdr.seg[0].len; void *base = pkt_hdr->buf_hdr.seg[0].data;
return dpdk_packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, - seg_len, mbuf, layer); + seg_len, mbuf, layer, pktin_cfg); } #endif diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index 6d045ebd..206a6a45 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -418,73 +418,6 @@ static struct rte_mempool_ops ops_stack = {
MEMPOOL_REGISTER_OPS(ops_stack);
-#define IP4_CSUM_RESULT(m) (m->ol_flags & PKT_RX_IP_CKSUM_MASK) -#define L4_CSUM_RESULT(m) (m->ol_flags & PKT_RX_L4_CKSUM_MASK) -#define UDP4_CSUM(_p) (((_odp_udphdr_t *)_odp_packet_l4_ptr(_p, NULL))->chksum) - -#define PKTIN_CSUM_BITS 0x1C - -static inline int pkt_set_ol_rx(odp_pktin_config_opt_t *pktin_cfg, - odp_packet_hdr_t *pkt_hdr, - struct rte_mbuf *mbuf) -{ - uint64_t packet_csum_result; - - if (pktin_cfg->bit.ipv4_chksum && - pkt_hdr->p.input_flags.ipv4) { - packet_csum_result = IP4_CSUM_RESULT(mbuf); - - if (packet_csum_result == PKT_RX_IP_CKSUM_GOOD) { - pkt_hdr->p.input_flags.l3_chksum_done = 1; - } else if (packet_csum_result != PKT_RX_IP_CKSUM_UNKNOWN) { - if (pktin_cfg->bit.drop_ipv4_err) - return -1; - - pkt_hdr->p.input_flags.l3_chksum_done = 1; - pkt_hdr->p.flags.ip_err = 1; - pkt_hdr->p.flags.l3_chksum_err = 1; - } - } - - if (pktin_cfg->bit.udp_chksum && - pkt_hdr->p.input_flags.udp) { - packet_csum_result = L4_CSUM_RESULT(mbuf); - - if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) { - pkt_hdr->p.input_flags.l4_chksum_done = 1; - } else if (packet_csum_result != PKT_RX_L4_CKSUM_UNKNOWN) { - if (pkt_hdr->p.input_flags.ipv4 && - pkt_hdr->p.input_flags.udp && - !UDP4_CSUM(packet_handle(pkt_hdr))) { - pkt_hdr->p.input_flags.l4_chksum_done = 1; - return 0; - } - if (pktin_cfg->bit.drop_udp_err) - return -1; - - pkt_hdr->p.input_flags.l4_chksum_done = 1; - pkt_hdr->p.flags.udp_err = 1; - pkt_hdr->p.flags.l4_chksum_err = 1; - } - } else if (pktin_cfg->bit.tcp_chksum && - pkt_hdr->p.input_flags.tcp) { - packet_csum_result = L4_CSUM_RESULT(mbuf); - - if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) { - pkt_hdr->p.input_flags.l4_chksum_done = 1; - } else if (packet_csum_result != PKT_RX_L4_CKSUM_UNKNOWN) { - if (pktin_cfg->bit.drop_tcp_err) - return -1; - - pkt_hdr->p.input_flags.l4_chksum_done = 1; - pkt_hdr->p.flags.tcp_err = 1; - pkt_hdr->p.flags.l4_chksum_err = 1; - } - } - - return 0; -} - static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], struct rte_mbuf *mbuf_table[], @@ -499,7 +432,7 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, int nb_pkts = 0; int alloc_len, num; odp_pool_t pool = pktio_entry->s.pkt_dpdk.pool; - odp_pktin_config_opt_t *pktin_cfg = &pktio_entry->s.config.pktin; + odp_pktin_config_opt_t pktin_cfg = pktio_entry->s.config.pktin; odp_proto_layer_t parse_layer = pktio_entry->s.config.parser.layer; odp_pktio_t input = pktio_entry->s.handle;
@@ -531,9 +464,14 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) { packet_parse_reset(&parsed_hdr); packet_set_len(&parsed_hdr, pkt_len); - dpdk_packet_parse_common(&parsed_hdr.p, data, - pkt_len, pkt_len, mbuf, - ODP_PROTO_LAYER_ALL); + if (dpdk_packet_parse_common(&parsed_hdr.p, data, + pkt_len, pkt_len, mbuf, + ODP_PROTO_LAYER_ALL, + pktin_cfg)) { + odp_packet_free(pkt_table[i]); + rte_pktmbuf_free(mbuf); + continue; + } if (cls_classify_packet(pktio_entry, (const uint8_t *)data, pkt_len, pkt_len, &pool, @@ -553,21 +491,18 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) copy_packet_cls_metadata(&parsed_hdr, pkt_hdr); else if (parse_layer != ODP_PROTO_LAYER_NONE) - dpdk_packet_parse_layer(pkt_hdr, mbuf, parse_layer); + if (dpdk_packet_parse_layer(pkt_hdr, mbuf, parse_layer, + pktin_cfg)) { + odp_packet_free(pkt); + rte_pktmbuf_free(mbuf); + continue; + }
if (mbuf->ol_flags & PKT_RX_RSS_HASH) packet_set_flow_hash(pkt_hdr, mbuf->hash.rss);
packet_set_ts(pkt_hdr, ts);
- if (pktin_cfg->all_bits & PKTIN_CSUM_BITS) { - if (pkt_set_ol_rx(pktin_cfg, pkt_hdr, mbuf)) { - odp_packet_free(pkt); - rte_pktmbuf_free(mbuf); - continue; - } - } - pkt_table[nb_pkts++] = pkt;
rte_pktmbuf_free(mbuf); @@ -756,7 +691,7 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry, int i; int nb_pkts = 0; odp_pool_t pool = pktio_entry->s.pkt_dpdk.pool; - odp_pktin_config_opt_t *pktin_cfg = &pktio_entry->s.config.pktin; + odp_pktin_config_opt_t pktin_cfg = pktio_entry->s.config.pktin; odp_proto_layer_t parse_layer = pktio_entry->s.config.parser.layer; odp_pktio_t input = pktio_entry->s.handle;
@@ -781,9 +716,13 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) { packet_parse_reset(&parsed_hdr); packet_set_len(&parsed_hdr, pkt_len); - dpdk_packet_parse_common(&parsed_hdr.p, data, - pkt_len, pkt_len, mbuf, - ODP_PROTO_LAYER_ALL); + if (dpdk_packet_parse_common(&parsed_hdr.p, data, + pkt_len, pkt_len, mbuf, + ODP_PROTO_LAYER_ALL, + pktin_cfg)) { + rte_pktmbuf_free(mbuf); + continue; + } if (cls_classify_packet(pktio_entry, (const uint8_t *)data, pkt_len, pkt_len, &pool, @@ -804,20 +743,17 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) copy_packet_cls_metadata(&parsed_hdr, pkt_hdr); else if (parse_layer != ODP_PROTO_LAYER_NONE) - dpdk_packet_parse_layer(pkt_hdr, mbuf, parse_layer); + if (dpdk_packet_parse_layer(pkt_hdr, mbuf, parse_layer, + pktin_cfg)) { + rte_pktmbuf_free(mbuf); + continue; + }
if (mbuf->ol_flags & PKT_RX_RSS_HASH) packet_set_flow_hash(pkt_hdr, mbuf->hash.rss);
packet_set_ts(pkt_hdr, ts);
- if (pktin_cfg->all_bits & PKTIN_CSUM_BITS) { - if (pkt_set_ol_rx(pktin_cfg, pkt_hdr, mbuf)) { - rte_pktmbuf_free(mbuf); - continue; - } - } - pkt_table[nb_pkts++] = pkt; }
diff --git a/platform/linux-generic/pktio/dpdk_parse.c b/platform/linux-generic/pktio/dpdk_parse.c index 1a388b10..155c6832 100644 --- a/platform/linux-generic/pktio/dpdk_parse.c +++ b/platform/linux-generic/pktio/dpdk_parse.c @@ -20,6 +20,9 @@ #include <rte_config.h> #include <rte_mbuf.h>
+#define IP4_CSUM_RESULT(ol_flags) (ol_flags & PKT_RX_IP_CKSUM_MASK) +#define L4_CSUM_RESULT(ol_flags) (ol_flags & PKT_RX_L4_CKSUM_MASK) + /** Parser helper function for Ethernet packets */ static inline uint16_t dpdk_parse_eth(packet_parser_t *prs, const uint8_t **parseptr, @@ -126,7 +129,9 @@ error: static inline uint8_t dpdk_parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, uint32_t *offset, uint32_t frame_len, - uint32_t mbuf_packet_type) + uint32_t mbuf_packet_type, + uint64_t mbuf_ol, + uint32_t do_csum) { const _odp_ipv4hdr_t *ipv4 = (const _odp_ipv4hdr_t *)*parseptr; uint32_t dstaddr = _odp_be_to_cpu_32(ipv4->dst_addr); @@ -147,6 +152,18 @@ static inline uint8_t dpdk_parse_ipv4(packet_parser_t *prs, *offset += ihl * 4; *parseptr += ihl * 4;
+ if (do_csum) { + uint64_t packet_csum_result = IP4_CSUM_RESULT(mbuf_ol); + + if (packet_csum_result == PKT_RX_IP_CKSUM_GOOD) { + prs->input_flags.l3_chksum_done = 1; + } else if (packet_csum_result != PKT_RX_IP_CKSUM_UNKNOWN) { + prs->input_flags.l3_chksum_done = 1; + prs->flags.ip_err = 1; + prs->flags.l3_chksum_err = 1; + } + } + if (odp_unlikely(ihl > _ODP_IPV4HDR_IHL_MIN)) prs->input_flags.ipopt = 1;
@@ -252,7 +269,9 @@ static inline uint8_t dpdk_parse_ipv6(packet_parser_t *prs, * Parser helper function for TCP */ static inline void dpdk_parse_tcp(packet_parser_t *prs, - const uint8_t **parseptr) + const uint8_t **parseptr, + uint64_t mbuf_ol, + uint32_t do_csum) { const _odp_tcphdr_t *tcp = (const _odp_tcphdr_t *)*parseptr; uint32_t len = tcp->hl * 4; @@ -260,6 +279,18 @@ static inline void dpdk_parse_tcp(packet_parser_t *prs, if (odp_unlikely(tcp->hl < sizeof(_odp_tcphdr_t) / sizeof(uint32_t))) prs->flags.tcp_err = 1;
+ if (do_csum) { + uint64_t packet_csum_result = L4_CSUM_RESULT(mbuf_ol); + + if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) { + prs->input_flags.l4_chksum_done = 1; + } else if (packet_csum_result != PKT_RX_L4_CKSUM_UNKNOWN) { + prs->input_flags.l4_chksum_done = 1; + prs->flags.tcp_err = 1; + prs->flags.l4_chksum_err = 1; + } + } + *parseptr += len; }
@@ -267,7 +298,9 @@ static inline void dpdk_parse_tcp(packet_parser_t *prs, * Parser helper function for UDP */ static inline void dpdk_parse_udp(packet_parser_t *prs, - const uint8_t **parseptr) + const uint8_t **parseptr, + uint64_t mbuf_ol, + uint32_t do_csum) { const _odp_udphdr_t *udp = (const _odp_udphdr_t *)*parseptr; uint32_t udplen = _odp_be_to_cpu_16(udp->length); @@ -276,6 +309,22 @@ static inline void dpdk_parse_udp(packet_parser_t *prs, if (odp_unlikely(udplen < sizeof(_odp_udphdr_t))) prs->flags.udp_err = 1;
+ if (do_csum) { + uint64_t packet_csum_result = L4_CSUM_RESULT(mbuf_ol); + + if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) { + prs->input_flags.l4_chksum_done = 1; + } else if (packet_csum_result != PKT_RX_L4_CKSUM_UNKNOWN) { + if (prs->input_flags.ipv4 && !udp->chksum) { + prs->input_flags.l4_chksum_done = 1; + } else { + prs->input_flags.l4_chksum_done = 1; + prs->flags.udp_err = 1; + prs->flags.l4_chksum_err = 1; + } + } + } + if (odp_unlikely(ipsec_port == udp->dst_port && udplen > 4)) { uint32_t val;
@@ -295,14 +344,16 @@ int dpdk_packet_parse_common_l3_l4(packet_parser_t *prs, uint32_t offset, uint32_t frame_len, uint32_t seg_len, int layer, uint16_t ethtype, - uint32_t mbuf_packet_type) + uint32_t mbuf_packet_type, + uint64_t mbuf_ol, + odp_pktin_config_opt_t pktin_cfg) { uint8_t ip_proto;
prs->l3_offset = offset;
if (odp_unlikely(layer <= ODP_PROTO_LAYER_L2)) - return prs->flags.all.error != 0; + return 0;
/* Set l3 flag only for known ethtypes */ prs->input_flags.l3 = 1; @@ -312,8 +363,11 @@ int dpdk_packet_parse_common_l3_l4(packet_parser_t *prs, case _ODP_ETHTYPE_IPV4: prs->input_flags.ipv4 = 1; ip_proto = dpdk_parse_ipv4(prs, &parseptr, &offset, frame_len, - mbuf_packet_type); + mbuf_packet_type, mbuf_ol, + pktin_cfg.bit.ipv4_chksum); prs->l4_offset = offset; + if (prs->flags.ip_err && pktin_cfg.bit.drop_ipv4_err) + return -1; /* drop */ break;
case _ODP_ETHTYPE_IPV6: @@ -321,6 +375,8 @@ int dpdk_packet_parse_common_l3_l4(packet_parser_t *prs, ip_proto = dpdk_parse_ipv6(prs, &parseptr, &offset, frame_len, seg_len, mbuf_packet_type); prs->l4_offset = offset; + if (prs->flags.ip_err && pktin_cfg.bit.drop_ipv6_err) + return -1; /* drop */ break;
case _ODP_ETHTYPE_ARP: @@ -334,7 +390,7 @@ int dpdk_packet_parse_common_l3_l4(packet_parser_t *prs, }
if (layer == ODP_PROTO_LAYER_L3) - return prs->flags.all.error != 0; + return 0;
/* Set l4 flag only for known ip_proto */ prs->input_flags.l4 = 1; @@ -354,16 +410,22 @@ int dpdk_packet_parse_common_l3_l4(packet_parser_t *prs,
case _ODP_IPPROTO_TCP: if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) - return -1; + return -1; /* drop */ prs->input_flags.tcp = 1; - dpdk_parse_tcp(prs, &parseptr); + dpdk_parse_tcp(prs, &parseptr, mbuf_ol, + pktin_cfg.bit.tcp_chksum); + if (prs->flags.tcp_err && pktin_cfg.bit.drop_tcp_err) + return -1; /* drop */ break;
case _ODP_IPPROTO_UDP: if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) - return -1; + return -1; /* drop */ prs->input_flags.udp = 1; - dpdk_parse_udp(prs, &parseptr); + dpdk_parse_udp(prs, &parseptr, mbuf_ol, + pktin_cfg.bit.udp_chksum); + if (prs->flags.udp_err && pktin_cfg.bit.drop_udp_err) + return -1; /* drop */ break;
case _ODP_IPPROTO_AH: @@ -389,7 +451,7 @@ int dpdk_packet_parse_common_l3_l4(packet_parser_t *prs, break; }
- return prs->flags.all.error != 0; + return 0; }
/** @@ -397,12 +459,14 @@ int dpdk_packet_parse_common_l3_l4(packet_parser_t *prs, */ int dpdk_packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, uint32_t frame_len, uint32_t seg_len, - struct rte_mbuf *mbuf, int layer) + struct rte_mbuf *mbuf, int layer, + odp_pktin_config_opt_t pktin_cfg) { uint32_t offset; uint16_t ethtype; const uint8_t *parseptr; uint32_t mbuf_packet_type; + uint64_t mbuf_ol;
parseptr = ptr; offset = 0; @@ -411,6 +475,7 @@ int dpdk_packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, return 0;
mbuf_packet_type = mbuf->packet_type; + mbuf_ol = mbuf->ol_flags;
/* Assume valid L2 header, no CRC/FCS check in SW */ prs->l2_offset = offset; @@ -420,7 +485,8 @@ int dpdk_packet_parse_common(packet_parser_t *prs, const uint8_t *ptr,
return dpdk_packet_parse_common_l3_l4(prs, parseptr, offset, frame_len, seg_len, layer, ethtype, - mbuf_packet_type); + mbuf_packet_type, mbuf_ol, + pktin_cfg); }
#endif /* ODP_PKTIO_DPDK */
commit db62337f2c0a3add91bbdbaa096f2a3c04162c60 Author: Bogdan Pricope bogdan.pricope@linaro.org Date: Wed May 2 12:56:07 2018 +0300
linux-gen: pktio: dpdk: add specific packet parser
Increase packet parsing performance by using dpdk provided information.
Signed-off-by: Bogdan Pricope bogdan.pricope@linaro.org Reviewed-and-tested-by: Matias Elo matias.elo@nokia.com Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index f9e99afd..b904877c 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -201,6 +201,7 @@ __LIB__libodp_linux_la_SOURCES = \ odp_version.c \ odp_weak.c \ pktio/dpdk.c \ + pktio/dpdk_parse.c \ pktio/ethtool.c \ pktio/io_ops.c \ pktio/ipc.c \ diff --git a/platform/linux-generic/include/odp_packet_dpdk.h b/platform/linux-generic/include/odp_packet_dpdk.h index 7600b57e..31d4557e 100644 --- a/platform/linux-generic/include/odp_packet_dpdk.h +++ b/platform/linux-generic/include/odp_packet_dpdk.h @@ -72,4 +72,22 @@ typedef struct ODP_ALIGNED_CACHE { dpdk_opt_t opt; } pkt_dpdk_t;
+/** Packet parser using DPDK interface */ +int dpdk_packet_parse_common(packet_parser_t *pkt_hdr, + const uint8_t *ptr, + uint32_t pkt_len, + uint32_t seg_len, + struct rte_mbuf *mbuf, + int layer); + +static inline int dpdk_packet_parse_layer(odp_packet_hdr_t *pkt_hdr, + struct rte_mbuf *mbuf, + odp_pktio_parser_layer_t layer) +{ + uint32_t seg_len = pkt_hdr->buf_hdr.seg[0].len; + void *base = pkt_hdr->buf_hdr.seg[0].data; + + return dpdk_packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, + seg_len, mbuf, layer); +} #endif diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index c8d7d0d4..6d045ebd 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -420,7 +420,6 @@ MEMPOOL_REGISTER_OPS(ops_stack);
#define IP4_CSUM_RESULT(m) (m->ol_flags & PKT_RX_IP_CKSUM_MASK) #define L4_CSUM_RESULT(m) (m->ol_flags & PKT_RX_L4_CKSUM_MASK) -#define HAS_L4_PROTO(m, proto) ((m->packet_type & RTE_PTYPE_L4_MASK) == proto) #define UDP4_CSUM(_p) (((_odp_udphdr_t *)_odp_packet_l4_ptr(_p, NULL))->chksum)
#define PKTIN_CSUM_BITS 0x1C @@ -432,7 +431,7 @@ static inline int pkt_set_ol_rx(odp_pktin_config_opt_t *pktin_cfg, uint64_t packet_csum_result;
if (pktin_cfg->bit.ipv4_chksum && - RTE_ETH_IS_IPV4_HDR(mbuf->packet_type)) { + pkt_hdr->p.input_flags.ipv4) { packet_csum_result = IP4_CSUM_RESULT(mbuf);
if (packet_csum_result == PKT_RX_IP_CKSUM_GOOD) { @@ -448,7 +447,7 @@ static inline int pkt_set_ol_rx(odp_pktin_config_opt_t *pktin_cfg, }
if (pktin_cfg->bit.udp_chksum && - HAS_L4_PROTO(mbuf, RTE_PTYPE_L4_UDP)) { + pkt_hdr->p.input_flags.udp) { packet_csum_result = L4_CSUM_RESULT(mbuf);
if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) { @@ -468,7 +467,7 @@ static inline int pkt_set_ol_rx(odp_pktin_config_opt_t *pktin_cfg, pkt_hdr->p.flags.l4_chksum_err = 1; } } else if (pktin_cfg->bit.tcp_chksum && - HAS_L4_PROTO(mbuf, RTE_PTYPE_L4_TCP)) { + pkt_hdr->p.input_flags.tcp) { packet_csum_result = L4_CSUM_RESULT(mbuf);
if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) { @@ -530,10 +529,15 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, pkt_len = rte_pktmbuf_pkt_len(mbuf);
if (pktio_cls_enabled(pktio_entry)) { + packet_parse_reset(&parsed_hdr); + packet_set_len(&parsed_hdr, pkt_len); + dpdk_packet_parse_common(&parsed_hdr.p, data, + pkt_len, pkt_len, mbuf, + ODP_PROTO_LAYER_ALL); if (cls_classify_packet(pktio_entry, (const uint8_t *)data, pkt_len, pkt_len, &pool, - &parsed_hdr, true)) + &parsed_hdr, false)) goto fail; }
@@ -549,7 +553,7 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) copy_packet_cls_metadata(&parsed_hdr, pkt_hdr); else if (parse_layer != ODP_PROTO_LAYER_NONE) - packet_parse_layer(pkt_hdr, parse_layer); + dpdk_packet_parse_layer(pkt_hdr, mbuf, parse_layer);
if (mbuf->ol_flags & PKT_RX_RSS_HASH) packet_set_flow_hash(pkt_hdr, mbuf->hash.rss); @@ -775,13 +779,19 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry, pkt_hdr = packet_hdr(pkt);
if (pktio_cls_enabled(pktio_entry)) { + packet_parse_reset(&parsed_hdr); + packet_set_len(&parsed_hdr, pkt_len); + dpdk_packet_parse_common(&parsed_hdr.p, data, + pkt_len, pkt_len, mbuf, + ODP_PROTO_LAYER_ALL); if (cls_classify_packet(pktio_entry, (const uint8_t *)data, pkt_len, pkt_len, &pool, - &parsed_hdr, true)) + &parsed_hdr, false)) { ODP_ERR("Unable to classify packet\n"); rte_pktmbuf_free(mbuf); continue; + } }
/* Init buffer segments. Currently, only single segment packets @@ -794,7 +804,7 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) copy_packet_cls_metadata(&parsed_hdr, pkt_hdr); else if (parse_layer != ODP_PROTO_LAYER_NONE) - packet_parse_layer(pkt_hdr, parse_layer); + dpdk_packet_parse_layer(pkt_hdr, mbuf, parse_layer);
if (mbuf->ol_flags & PKT_RX_RSS_HASH) packet_set_flow_hash(pkt_hdr, mbuf->hash.rss); diff --git a/platform/linux-generic/pktio/dpdk_parse.c b/platform/linux-generic/pktio/dpdk_parse.c new file mode 100644 index 00000000..1a388b10 --- /dev/null +++ b/platform/linux-generic/pktio/dpdk_parse.c @@ -0,0 +1,426 @@ +/* Copyright (c) 2018, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "config.h" + +#ifdef ODP_PKTIO_DPDK + +#include <odp_packet_io_internal.h> +#include <odp_packet_dpdk.h> +#include <odp/api/byteorder.h> +#include <odp/api/plat/byteorder_inlines.h> + +#include <protocols/eth.h> +#include <protocols/udp.h> +#include <protocols/tcp.h> + +#include <rte_config.h> +#include <rte_mbuf.h> + +/** Parser helper function for Ethernet packets */ +static inline uint16_t dpdk_parse_eth(packet_parser_t *prs, + const uint8_t **parseptr, + uint32_t *offset, uint32_t frame_len, + uint32_t mbuf_packet_type) +{ + uint16_t ethtype; + const _odp_ethhdr_t *eth; + uint16_t macaddr0, macaddr2, macaddr4; + const _odp_vlanhdr_t *vlan; + _odp_packet_input_flags_t input_flags; + uint32_t l2_packet_type; + + input_flags.all = 0; + input_flags.l2 = 1; + input_flags.eth = 1; + + eth = (const _odp_ethhdr_t *)*parseptr; + + /* Detect jumbo frames */ + if (odp_unlikely(frame_len > _ODP_ETH_LEN_MAX)) + input_flags.jumbo = 1; + + /* Handle Ethernet broadcast/multicast addresses */ + macaddr0 = _odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth)); + if (odp_unlikely((macaddr0 & 0x0100) == 0x0100)) + input_flags.eth_mcast = 1; + + if (odp_unlikely(macaddr0 == 0xffff)) { + macaddr2 = + _odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 1)); + macaddr4 = + _odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 2)); + + if ((macaddr2 == 0xffff) && (macaddr4 == 0xffff)) + input_flags.eth_bcast = 1; + } + + /* Get Ethertype */ + l2_packet_type = mbuf_packet_type & RTE_PTYPE_L2_MASK; + switch (l2_packet_type) { + case RTE_PTYPE_L2_ETHER: + if (RTE_ETH_IS_IPV4_HDR(mbuf_packet_type)) + ethtype = _ODP_ETHTYPE_IPV4; + else if (RTE_ETH_IS_IPV6_HDR(mbuf_packet_type)) + ethtype = _ODP_ETHTYPE_IPV6; + else + ethtype = _odp_be_to_cpu_16(eth->type); + break; + case RTE_PTYPE_L2_ETHER_VLAN: + ethtype = _ODP_ETHTYPE_VLAN; + break; + default: + ethtype = _odp_be_to_cpu_16(eth->type); + } + + *offset += sizeof(*eth); + *parseptr += sizeof(*eth); + + /* Check for SNAP vs. DIX */ + if (odp_unlikely(ethtype < _ODP_ETH_LEN_MAX)) { + input_flags.snap = 1; + if (ethtype > frame_len - *offset) { + prs->flags.snap_len_err = 1; + ethtype = 0; + goto error; + } + ethtype = _odp_be_to_cpu_16(*((const uint16_t *)(uintptr_t) + (parseptr + 6))); + *offset += 8; + *parseptr += 8; + } + + /* Parse the VLAN header(s), if present */ + if (odp_unlikely(ethtype == _ODP_ETHTYPE_VLAN_OUTER)) { + input_flags.vlan_qinq = 1; + input_flags.vlan = 1; + + vlan = (const _odp_vlanhdr_t *)*parseptr; + ethtype = _odp_be_to_cpu_16(vlan->type); + *offset += sizeof(_odp_vlanhdr_t); + *parseptr += sizeof(_odp_vlanhdr_t); + } + + if (ethtype == _ODP_ETHTYPE_VLAN) { + input_flags.vlan = 1; + vlan = (const _odp_vlanhdr_t *)*parseptr; + ethtype = _odp_be_to_cpu_16(vlan->type); + *offset += sizeof(_odp_vlanhdr_t); + *parseptr += sizeof(_odp_vlanhdr_t); + } + +error: + prs->input_flags.all |= input_flags.all; + + return ethtype; +} + +/** + * Parser helper function for IPv4 + */ +static inline uint8_t dpdk_parse_ipv4(packet_parser_t *prs, + const uint8_t **parseptr, + uint32_t *offset, uint32_t frame_len, + uint32_t mbuf_packet_type) +{ + const _odp_ipv4hdr_t *ipv4 = (const _odp_ipv4hdr_t *)*parseptr; + uint32_t dstaddr = _odp_be_to_cpu_32(ipv4->dst_addr); + uint32_t l3_len = _odp_be_to_cpu_16(ipv4->tot_len); + uint8_t ver = _ODP_IPV4HDR_VER(ipv4->ver_ihl); + uint8_t ihl = _ODP_IPV4HDR_IHL(ipv4->ver_ihl); + uint32_t l4_packet_type = mbuf_packet_type & RTE_PTYPE_L4_MASK; + uint16_t frag_offset; + uint8_t proto; + + if (odp_unlikely(ihl < _ODP_IPV4HDR_IHL_MIN || + ver != 4 || + (l3_len > frame_len - *offset))) { + prs->flags.ip_err = 1; + return 0; + } + + *offset += ihl * 4; + *parseptr += ihl * 4; + + if (odp_unlikely(ihl > _ODP_IPV4HDR_IHL_MIN)) + prs->input_flags.ipopt = 1; + + if (l4_packet_type == RTE_PTYPE_L4_UDP) { + proto = _ODP_IPPROTO_UDP; + } else if (l4_packet_type == RTE_PTYPE_L4_TCP) { + proto = _ODP_IPPROTO_TCP; + } else { + proto = ipv4->proto; + frag_offset = _odp_be_to_cpu_16(ipv4->frag_offset); + + /* A packet is a fragment if: + * "more fragments" flag is set (all fragments except the last) + * OR + * "fragment offset" field is nonzero (all fragments except + * the first) + */ + if (odp_unlikely(l4_packet_type == RTE_PTYPE_L4_FRAG || + _ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) + prs->input_flags.ipfrag = 1; + } + + /**/ + /* Handle IPv4 broadcast / multicast */ + if (odp_unlikely(dstaddr == 0xffffffff)) + prs->input_flags.ip_bcast = 1; + + if (odp_unlikely((dstaddr >> 28) == 0xe)) + prs->input_flags.ip_mcast = 1; + + return proto; +} + +static inline uint8_t dpdk_parse_ipv6(packet_parser_t *prs, + const uint8_t **parseptr, + uint32_t *offset, uint32_t frame_len, + uint32_t seg_len, + uint32_t mbuf_packet_type) +{ + const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr; + const _odp_ipv6hdr_ext_t *ipv6ext; + uint32_t dstaddr0 = _odp_be_to_cpu_32(ipv6->dst_addr.u8[0]); + uint32_t l3_len = _odp_be_to_cpu_16(ipv6->payload_len) + + _ODP_IPV6HDR_LEN; + uint32_t l4_packet_type = mbuf_packet_type & RTE_PTYPE_L4_MASK; + + /* Basic sanity checks on IPv6 header */ + if ((_odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 || + l3_len > frame_len - *offset) { + prs->flags.ip_err = 1; + return 0; + } + + /* IPv6 broadcast / multicast flags */ + prs->input_flags.ip_mcast = (dstaddr0 & 0xff000000) == 0xff000000; + prs->input_flags.ip_bcast = 0; + + /* Skip past IPv6 header */ + *offset += sizeof(_odp_ipv6hdr_t); + *parseptr += sizeof(_odp_ipv6hdr_t); + + if (l4_packet_type == RTE_PTYPE_L4_UDP) + return _ODP_IPPROTO_UDP; + else if (l4_packet_type == RTE_PTYPE_L4_TCP) + return _ODP_IPPROTO_TCP; + + /* Skip past any IPv6 extension headers */ + if (ipv6->next_hdr == _ODP_IPPROTO_HOPOPTS || + ipv6->next_hdr == _ODP_IPPROTO_ROUTE) { + prs->input_flags.ipopt = 1; + + do { + ipv6ext = (const _odp_ipv6hdr_ext_t *)*parseptr; + uint16_t extlen = 8 + ipv6ext->ext_len * 8; + + *offset += extlen; + *parseptr += extlen; + } while ((ipv6ext->next_hdr == _ODP_IPPROTO_HOPOPTS || + ipv6ext->next_hdr == _ODP_IPPROTO_ROUTE) && + *offset < seg_len); + + if (*offset >= prs->l3_offset + + _odp_be_to_cpu_16(ipv6->payload_len)) { + prs->flags.ip_err = 1; + return 0; + } + + if (ipv6ext->next_hdr == _ODP_IPPROTO_FRAG) + prs->input_flags.ipfrag = 1; + + return ipv6ext->next_hdr; + } + + if (odp_unlikely(ipv6->next_hdr == _ODP_IPPROTO_FRAG)) { + prs->input_flags.ipopt = 1; + prs->input_flags.ipfrag = 1; + } + + return ipv6->next_hdr; +} + +/** + * Parser helper function for TCP + */ +static inline void dpdk_parse_tcp(packet_parser_t *prs, + const uint8_t **parseptr) +{ + const _odp_tcphdr_t *tcp = (const _odp_tcphdr_t *)*parseptr; + uint32_t len = tcp->hl * 4; + + if (odp_unlikely(tcp->hl < sizeof(_odp_tcphdr_t) / sizeof(uint32_t))) + prs->flags.tcp_err = 1; + + *parseptr += len; +} + +/** + * Parser helper function for UDP + */ +static inline void dpdk_parse_udp(packet_parser_t *prs, + const uint8_t **parseptr) +{ + const _odp_udphdr_t *udp = (const _odp_udphdr_t *)*parseptr; + uint32_t udplen = _odp_be_to_cpu_16(udp->length); + uint16_t ipsec_port = _odp_cpu_to_be_16(_ODP_UDP_IPSEC_PORT); + + if (odp_unlikely(udplen < sizeof(_odp_udphdr_t))) + prs->flags.udp_err = 1; + + if (odp_unlikely(ipsec_port == udp->dst_port && udplen > 4)) { + uint32_t val; + + memcpy(&val, udp + 1, 4); + if (val != 0) { + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_udp = 1; + } + } + + *parseptr += sizeof(_odp_udphdr_t); +} + +static inline +int dpdk_packet_parse_common_l3_l4(packet_parser_t *prs, + const uint8_t *parseptr, + uint32_t offset, + uint32_t frame_len, uint32_t seg_len, + int layer, uint16_t ethtype, + uint32_t mbuf_packet_type) +{ + uint8_t ip_proto; + + prs->l3_offset = offset; + + if (odp_unlikely(layer <= ODP_PROTO_LAYER_L2)) + return prs->flags.all.error != 0; + + /* Set l3 flag only for known ethtypes */ + prs->input_flags.l3 = 1; + + /* Parse Layer 3 headers */ + switch (ethtype) { + case _ODP_ETHTYPE_IPV4: + prs->input_flags.ipv4 = 1; + ip_proto = dpdk_parse_ipv4(prs, &parseptr, &offset, frame_len, + mbuf_packet_type); + prs->l4_offset = offset; + break; + + case _ODP_ETHTYPE_IPV6: + prs->input_flags.ipv6 = 1; + ip_proto = dpdk_parse_ipv6(prs, &parseptr, &offset, frame_len, + seg_len, mbuf_packet_type); + prs->l4_offset = offset; + break; + + case _ODP_ETHTYPE_ARP: + prs->input_flags.arp = 1; + ip_proto = 255; /* Reserved invalid by IANA */ + break; + + default: + prs->input_flags.l3 = 0; + ip_proto = 255; /* Reserved invalid by IANA */ + } + + if (layer == ODP_PROTO_LAYER_L3) + return prs->flags.all.error != 0; + + /* Set l4 flag only for known ip_proto */ + prs->input_flags.l4 = 1; + + /* Parse Layer 4 headers */ + switch (ip_proto) { + case _ODP_IPPROTO_ICMPV4: + /* Fall through */ + + case _ODP_IPPROTO_ICMPV6: + prs->input_flags.icmp = 1; + break; + + case _ODP_IPPROTO_IPIP: + /* Do nothing */ + break; + + case _ODP_IPPROTO_TCP: + if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) + return -1; + prs->input_flags.tcp = 1; + dpdk_parse_tcp(prs, &parseptr); + break; + + case _ODP_IPPROTO_UDP: + if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) + return -1; + prs->input_flags.udp = 1; + dpdk_parse_udp(prs, &parseptr); + break; + + case _ODP_IPPROTO_AH: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_ah = 1; + break; + + case _ODP_IPPROTO_ESP: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_esp = 1; + break; + + case _ODP_IPPROTO_SCTP: + prs->input_flags.sctp = 1; + break; + + case _ODP_IPPROTO_NO_NEXT: + prs->input_flags.no_next_hdr = 1; + break; + + default: + prs->input_flags.l4 = 0; + break; + } + + return prs->flags.all.error != 0; +} + +/** + * DPDK packet parser + */ +int dpdk_packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, + uint32_t frame_len, uint32_t seg_len, + struct rte_mbuf *mbuf, int layer) +{ + uint32_t offset; + uint16_t ethtype; + const uint8_t *parseptr; + uint32_t mbuf_packet_type; + + parseptr = ptr; + offset = 0; + + if (odp_unlikely(layer == ODP_PROTO_LAYER_NONE)) + return 0; + + mbuf_packet_type = mbuf->packet_type; + + /* Assume valid L2 header, no CRC/FCS check in SW */ + prs->l2_offset = offset; + + ethtype = dpdk_parse_eth(prs, &parseptr, &offset, frame_len, + mbuf_packet_type); + + return dpdk_packet_parse_common_l3_l4(prs, parseptr, offset, frame_len, + seg_len, layer, ethtype, + mbuf_packet_type); +} + +#endif /* ODP_PKTIO_DPDK */
commit df1c292ed40d4c2c480917f1eab06a046c93c3b1 Author: Bogdan Pricope bogdan.pricope@linaro.org Date: Wed May 2 11:29:48 2018 +0300
linux-gen: classification: permit packet parsing at pktio level
This change is needed to support pktio specific parsers.
Signed-off-by: Bogdan Pricope bogdan.pricope@linaro.org Reviewed-and-tested-by: Matias Elo matias.elo@nokia.com Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_classification_internal.h b/platform/linux-generic/include/odp_classification_internal.h index 47f80dc2..84d605e6 100644 --- a/platform/linux-generic/include/odp_classification_internal.h +++ b/platform/linux-generic/include/odp_classification_internal.h @@ -39,7 +39,7 @@ selects destination queue and packet pool based on selected PMR and CoS. **/ int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base, uint16_t pkt_len, uint32_t seg_len, odp_pool_t *pool, - odp_packet_hdr_t *pkt_hdr); + odp_packet_hdr_t *pkt_hdr, odp_bool_t parse);
/** Packet IO classifier init diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c index 14720924..46fcf67e 100644 --- a/platform/linux-generic/odp_classification.c +++ b/platform/linux-generic/odp_classification.c @@ -987,17 +987,19 @@ static uint32_t packet_rss_hash(odp_packet_hdr_t *pkt_hdr, */ int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base, uint16_t pkt_len, uint32_t seg_len, odp_pool_t *pool, - odp_packet_hdr_t *pkt_hdr) + odp_packet_hdr_t *pkt_hdr, odp_bool_t parse) { cos_t *cos; uint32_t tbl_index; uint32_t hash;
- packet_parse_reset(pkt_hdr); - packet_set_len(pkt_hdr, pkt_len); + if (parse) { + packet_parse_reset(pkt_hdr); + packet_set_len(pkt_hdr, pkt_len);
- packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len, - ODP_PROTO_LAYER_ALL); + packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len, + ODP_PROTO_LAYER_ALL); + } cos = cls_select_cos(entry, base, pkt_hdr);
if (cos == NULL) diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index 14d59d8e..c8d7d0d4 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -533,7 +533,7 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, if (cls_classify_packet(pktio_entry, (const uint8_t *)data, pkt_len, pkt_len, &pool, - &parsed_hdr)) + &parsed_hdr, true)) goto fail; }
@@ -778,7 +778,7 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry, if (cls_classify_packet(pktio_entry, (const uint8_t *)data, pkt_len, pkt_len, &pool, - &parsed_hdr)) + &parsed_hdr, true)) ODP_ERR("Unable to classify packet\n"); rte_pktmbuf_free(mbuf); continue; diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c index fc80e801..779e4c62 100644 --- a/platform/linux-generic/pktio/loop.c +++ b/platform/linux-generic/pktio/loop.c @@ -131,7 +131,7 @@ static int loopback_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED,
ret = cls_classify_packet(pktio_entry, pkt_addr, pkt_len, seg_len, - &new_pool, pkt_hdr); + &new_pool, pkt_hdr, true); if (ret) { failed++; odp_packet_free(pkt); diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c index 835d81eb..567bc9f9 100644 --- a/platform/linux-generic/pktio/netmap.c +++ b/platform/linux-generic/pktio/netmap.c @@ -705,7 +705,7 @@ static inline int netmap_pkt_to_odp(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) { if (cls_classify_packet(pktio_entry, (const uint8_t *)slot.buf, len, - len, &pool, &parsed_hdr)) + len, &pool, &parsed_hdr, true)) goto fail; }
diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c index f6f3288c..8b7200e6 100644 --- a/platform/linux-generic/pktio/socket.c +++ b/platform/linux-generic/pktio/socket.c @@ -655,7 +655,8 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, seg_len = msgvec[i].msg_hdr.msg_iov->iov_len;
if (cls_classify_packet(pktio_entry, base, pkt_len, - seg_len, &pool, pkt_hdr)) { + seg_len, &pool, pkt_hdr, + true)) { ODP_ERR("cls_classify_packet failed"); odp_packet_free(pkt); continue; diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c index deaa6da1..847eb71a 100644 --- a/platform/linux-generic/pktio/socket_mmap.c +++ b/platform/linux-generic/pktio/socket_mmap.c @@ -228,7 +228,8 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t *pktio_entry,
if (pktio_cls_enabled(pktio_entry)) { if (cls_classify_packet(pktio_entry, pkt_buf, pkt_len, - pkt_len, &pool, &parsed_hdr)) { + pkt_len, &pool, &parsed_hdr, + true)) { mmap_rx_user_ready(ppd.raw); /* drop */ frame_num = next_frame_num; continue; diff --git a/platform/linux-generic/pktio/tap.c b/platform/linux-generic/pktio/tap.c index 56f90b31..af766e0d 100644 --- a/platform/linux-generic/pktio/tap.c +++ b/platform/linux-generic/pktio/tap.c @@ -264,7 +264,7 @@ static odp_packet_t pack_odp_pkt(pktio_entry_t *pktio_entry, const void *data, if (pktio_cls_enabled(pktio_entry)) { if (cls_classify_packet(pktio_entry, data, len, len, &pktio_entry->s.pkt_tap.pool, - &parsed_hdr)) { + &parsed_hdr, true)) { return ODP_PACKET_INVALID; } }
-----------------------------------------------------------------------
Summary of changes: platform/linux-generic/Makefile.am | 1 + .../include/odp_classification_internal.h | 2 +- platform/linux-generic/include/odp_packet_dpdk.h | 20 + platform/linux-generic/odp_classification.c | 12 +- platform/linux-generic/pktio/dpdk.c | 124 ++---- platform/linux-generic/pktio/dpdk_parse.c | 492 +++++++++++++++++++++ platform/linux-generic/pktio/loop.c | 2 +- platform/linux-generic/pktio/netmap.c | 2 +- platform/linux-generic/pktio/socket.c | 3 +- platform/linux-generic/pktio/socket_mmap.c | 3 +- platform/linux-generic/pktio/tap.c | 2 +- 11 files changed, 563 insertions(+), 100 deletions(-) create mode 100644 platform/linux-generic/pktio/dpdk_parse.c
hooks/post-receive