diff options
Diffstat (limited to 'platform')
23 files changed, 701 insertions, 187 deletions
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 8da6c6bf5..9269a73c0 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -189,3 +189,7 @@ EXTRA_DIST = \ arch/linux/odp_cpu_cycles.c \ arch/mips64/odp_cpu_cycles.c \ arch/x86/odp_cpu_cycles.c + +if HAVE_PCAP +__LIB__libodp_la_SOURCES += pktio/pcap.c +endif diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h index 8a1a21976..14ba15900 100644 --- a/platform/linux-generic/include/odp_internal.h +++ b/platform/linux-generic/include/odp_internal.h @@ -54,6 +54,7 @@ int odp_shm_term_global(void); int odp_shm_init_local(void); int odp_pool_init_global(void); +int odp_pool_init_local(void); int odp_pool_term_global(void); int odp_pool_term_local(void); diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index ba2cd7e1a..6f1521ca3 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -36,7 +36,8 @@ typedef union { uint32_t all; struct { - uint32_t unparsed:1; /**< Set to inticate parse needed */ + uint32_t parsed_l2:1; /**< L2 parsed */ + uint32_t parsed_all:1;/**< Parsing complete */ uint32_t l2:1; /**< known L2 protocol present */ uint32_t l3:1; /**< known L3 protocol present */ @@ -155,43 +156,6 @@ static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt) return (odp_packet_hdr_t *)odp_buf_to_hdr((odp_buffer_t)pkt); } -/** - * Initialize packet buffer - */ -static inline void packet_init(pool_entry_t *pool, - odp_packet_hdr_t *pkt_hdr, - size_t size) -{ - /* - * Reset parser metadata. Note that we clear via memset to make - * this routine indepenent of any additional adds to packet metadata. - */ - const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr); - uint8_t *start; - size_t len; - - start = (uint8_t *)pkt_hdr + start_offset; - len = sizeof(odp_packet_hdr_t) - start_offset; - memset(start, 0, len); - - /* Set metadata items that initialize to non-zero values */ - pkt_hdr->l2_offset = ODP_PACKET_OFFSET_INVALID; - pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID; - pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID; - pkt_hdr->payload_offset = ODP_PACKET_OFFSET_INVALID; - - /* - * Packet headroom is set from the pool's headroom - * Packet tailroom is rounded up to fill the last - * segment occupied by the allocated length. - */ - pkt_hdr->frame_len = size; - pkt_hdr->headroom = pool->s.headroom; - pkt_hdr->tailroom = - (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) - - (pool->s.headroom + size); -} - static inline void copy_packet_parser_metadata(odp_packet_hdr_t *src_hdr, odp_packet_hdr_t *dst_hdr) { @@ -253,12 +217,14 @@ static inline void packet_set_len(odp_packet_t pkt, uint32_t len) odp_packet_hdr(pkt)->frame_len = len; } -#define ODP_PACKET_UNPARSED ~0 +static inline int packet_parse_l2_not_done(odp_packet_hdr_t *pkt_hdr) +{ + return !pkt_hdr->input_flags.parsed_l2; +} -static inline void _odp_packet_reset_parse(odp_packet_t pkt) +static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr) { - odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - pkt_hdr->input_flags.all = ODP_PACKET_UNPARSED; + return !pkt_hdr->input_flags.parsed_all; } /* Forward declarations */ @@ -268,9 +234,16 @@ int _odp_packet_copy_to_packet(odp_packet_t srcpkt, uint32_t srcoffset, void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt); -odp_packet_t _odp_packet_alloc(odp_pool_t pool_hdl); +odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse); + +/* Fill in parser metadata for L2 */ +void packet_parse_l2(odp_packet_hdr_t *pkt_hdr); + +/* Perform full packet parse */ +int packet_parse_full(odp_packet_hdr_t *pkt_hdr); -int _odp_packet_parse(odp_packet_hdr_t *pkt_hdr); +/* Reset parser metadata for a new parse */ +void packet_parse_reset(odp_packet_t pkt); /* Convert a packet handle to a buffer handle */ odp_buffer_t _odp_packet_to_buffer(odp_packet_t pkt); diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h index 353b40d94..4745bd5c0 100644 --- a/platform/linux-generic/include/odp_packet_io_internal.h +++ b/platform/linux-generic/include/odp_packet_io_internal.h @@ -30,6 +30,8 @@ extern "C" { #include <odp/hints.h> #include <net/if.h> +#define PKTIO_NAME_LEN 256 + /* Forward declaration */ struct pktio_if_ops; @@ -38,6 +40,21 @@ typedef struct { odp_bool_t promisc; /**< promiscuous mode state */ } pkt_loop_t; +#ifdef HAVE_PCAP +typedef struct { + char *fname_rx; /**< name of pcap file for rx */ + char *fname_tx; /**< name of pcap file for tx */ + void *rx; /**< rx pcap handle */ + void *tx; /**< tx pcap handle */ + void *tx_dump; /**< tx pcap dumper handle */ + odp_pool_t pool; /**< rx pool */ + unsigned char *buf; /**< per-pktio temp buffer */ + int loops; /**< number of times to loop rx pcap */ + int loop_cnt; /**< number of loops completed */ + odp_bool_t promisc; /**< promiscuous mode state */ +} pkt_pcap_t; +#endif + struct pktio_entry { const struct pktio_if_ops *ops; /**< Implementation specific methods */ odp_ticketlock_t lock; /**< entry ticketlock */ @@ -52,13 +69,16 @@ struct pktio_entry { pkt_sock_mmap_t pkt_sock_mmap; /**< using socket mmap * API for IO */ pkt_netmap_t pkt_nm; /**< using netmap API for IO */ +#ifdef HAVE_PCAP + pkt_pcap_t pkt_pcap; /**< Using pcap for IO */ +#endif }; enum { STATE_START = 0, STATE_STOP } state; classifier_t cls; /**< classifier linked with this pktio*/ - char name[IF_NAMESIZE]; /**< name of pktio provided to + char name[PKTIO_NAME_LEN]; /**< name of pktio provided to pktio_open() */ odp_pktio_param_t param; }; @@ -128,6 +148,9 @@ extern const pktio_if_ops_t netmap_pktio_ops; extern const pktio_if_ops_t sock_mmsg_pktio_ops; extern const pktio_if_ops_t sock_mmap_pktio_ops; extern const pktio_if_ops_t loopback_pktio_ops; +#ifdef HAVE_PCAP +extern const pktio_if_ops_t pcap_pktio_ops; +#endif extern const pktio_if_ops_t * const pktio_if_ops[]; #ifdef __cplusplus diff --git a/platform/linux-generic/include/odp_pool_internal.h b/platform/linux-generic/include/odp_pool_internal.h index 136db2c21..94bf1faee 100644 --- a/platform/linux-generic/include/odp_pool_internal.h +++ b/platform/linux-generic/include/odp_pool_internal.h @@ -53,9 +53,14 @@ typedef struct _odp_buffer_pool_init_t { /* Local cache for buffer alloc/free acceleration */ typedef struct local_cache_t { - odp_buffer_hdr_t *buf_freelist; /* The local cache */ - uint64_t bufallocs; /* Local buffer alloc count */ - uint64_t buffrees; /* Local buffer free count */ + union { + struct { + odp_buffer_hdr_t *buf_freelist; /* The local cache */ + uint64_t bufallocs; /* Local buffer alloc count */ + uint64_t buffrees; /* Local buffer free count */ + }; + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(uint64_t))]; + }; } local_cache_t; /* Use ticketlock instead of spinlock */ @@ -133,6 +138,8 @@ struct pool_entry_s { uint32_t low_wm; uint32_t headroom; uint32_t tailroom; + + local_cache_t local_cache[_ODP_INTERNAL_MAX_THREADS] ODP_ALIGNED_CACHE; }; typedef union pool_entry_u { diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4 index f2d42f109..df6dc640b 100644 --- a/platform/linux-generic/m4/configure.m4 +++ b/platform/linux-generic/m4/configure.m4 @@ -19,6 +19,7 @@ AC_LINK_IFELSE( m4_include([platform/linux-generic/m4/odp_pthread.m4]) m4_include([platform/linux-generic/m4/odp_openssl.m4]) m4_include([platform/linux-generic/m4/odp_netmap.m4]) +m4_include([platform/linux-generic/m4/odp_pcap.m4]) AC_CONFIG_FILES([platform/linux-generic/Makefile platform/linux-generic/test/Makefile diff --git a/platform/linux-generic/m4/odp_pcap.m4 b/platform/linux-generic/m4/odp_pcap.m4 new file mode 100644 index 000000000..734b79005 --- /dev/null +++ b/platform/linux-generic/m4/odp_pcap.m4 @@ -0,0 +1,15 @@ +######################################################################### +# Check for libpcap availability +######################################################################### +have_pcap=no +AC_CHECK_HEADER(pcap/pcap.h, + [AC_CHECK_HEADER(pcap/bpf.h, + [AC_CHECK_LIB(pcap, pcap_open_offline, have_pcap=yes, [])], + [])], +[]) + +AM_CONDITIONAL([HAVE_PCAP], [test $have_pcap = yes]) +if test $have_pcap == yes; then + AM_CFLAGS="$AM_CFLAGS -DHAVE_PCAP" + LIBS="$LIBS -lpcap" +fi diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c index d5ca13fd4..1b6d5931a 100644 --- a/platform/linux-generic/odp_classification.c +++ b/platform/linux-generic/odp_classification.c @@ -860,8 +860,8 @@ cos_t *pktio_select_cos(pktio_entry_t *entry, uint8_t *pkt_addr, cls = &entry->s.cls; /* Check for lazy parse needed */ - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); + if (packet_parse_not_complete(pkt_hdr)) + packet_parse_full(pkt_hdr); /* Return error cos for error packet */ if (pkt_hdr->error_flags.all) diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c index 48d9b2036..5e19d86c6 100644 --- a/platform/linux-generic/odp_init.c +++ b/platform/linux-generic/odp_init.c @@ -138,6 +138,11 @@ int odp_init_local(odp_thread_type_t thr_type) return -1; } + if (odp_pool_init_local()) { + ODP_ERR("ODP pool local init failed.\n"); + return -1; + } + if (odp_schedule_init_local()) { ODP_ERR("ODP schedule local init failed.\n"); return -1; diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index 209a6e6a0..1b496247f 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -25,8 +25,73 @@ * */ -odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len) +static inline void packet_parse_disable(odp_packet_hdr_t *pkt_hdr) +{ + pkt_hdr->input_flags.parsed_l2 = 1; + pkt_hdr->input_flags.parsed_all = 1; +} + +void packet_parse_reset(odp_packet_t pkt) +{ + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + + /* Reset parser metadata before new parse */ + pkt_hdr->error_flags.all = 0; + pkt_hdr->input_flags.all = 0; + pkt_hdr->output_flags.all = 0; + pkt_hdr->l2_offset = 0; + pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID; + pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID; + pkt_hdr->payload_offset = ODP_PACKET_OFFSET_INVALID; + pkt_hdr->vlan_s_tag = 0; + pkt_hdr->vlan_c_tag = 0; + pkt_hdr->l3_protocol = 0; + pkt_hdr->l4_protocol = 0; +} + +/** + * Initialize packet + */ +static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr, + size_t size, int parse) { + /* + * Reset parser metadata. Note that we clear via memset to make + * this routine indepenent of any additional adds to packet metadata. + */ + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr); + uint8_t *start; + size_t len; + + start = (uint8_t *)pkt_hdr + start_offset; + len = sizeof(odp_packet_hdr_t) - start_offset; + memset(start, 0, len); + + /* Set metadata items that initialize to non-zero values */ + pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID; + pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID; + pkt_hdr->payload_offset = ODP_PACKET_OFFSET_INVALID; + + /* Disable lazy parsing on user allocated packets */ + if (!parse) + packet_parse_disable(pkt_hdr); + + /* + * Packet headroom is set from the pool's headroom + * Packet tailroom is rounded up to fill the last + * segment occupied by the allocated length. + */ + pkt_hdr->frame_len = size; + pkt_hdr->headroom = pool->s.headroom; + pkt_hdr->tailroom = + (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) - + (pool->s.headroom + size); +} + +odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse) +{ + odp_packet_t pkt; + odp_packet_hdr_t *pkt_hdr; pool_entry_t *pool = odp_pool_to_entry(pool_hdl); if (pool->s.params.type != ODP_POOL_PACKET) @@ -34,17 +99,32 @@ odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len) /* Handle special case for zero-length packets */ if (len == 0) { - odp_packet_t pkt = - (odp_packet_t)buffer_alloc(pool_hdl, - pool->s.params.buf.size); - if (pkt != ODP_PACKET_INVALID) - pull_tail(odp_packet_hdr(pkt), - pool->s.params.buf.size); - - return pkt; + len = pool->s.params.buf.size; + + pkt = (odp_packet_t)buffer_alloc(pool_hdl, len); + + if (pkt == ODP_PACKET_INVALID) + return ODP_PACKET_INVALID; + + pull_tail(odp_packet_hdr(pkt), len); + + } else { + pkt = (odp_packet_t)buffer_alloc(pool_hdl, len); + + if (pkt == ODP_PACKET_INVALID) + return ODP_PACKET_INVALID; } - return (odp_packet_t)buffer_alloc(pool_hdl, len); + pkt_hdr = odp_packet_hdr(pkt); + + packet_init(pool, pkt_hdr, len, parse); + + return pkt; +} + +odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len) +{ + return packet_alloc(pool_hdl, len, 0); } void odp_packet_free(odp_packet_t pkt) @@ -61,7 +141,8 @@ int odp_packet_reset(odp_packet_t pkt, uint32_t len) if (totsize > pkt_hdr->buf_hdr.size) return -1; - packet_init(pool, pkt_hdr, len); + packet_init(pool, pkt_hdr, len, 0); + return 0; } @@ -242,16 +323,12 @@ uint32_t odp_packet_user_area_size(odp_packet_t pkt) void *odp_packet_l2_ptr(odp_packet_t pkt, uint32_t *len) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); return packet_map(pkt_hdr, pkt_hdr->l2_offset, len); } uint32_t odp_packet_l2_offset(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); return pkt_hdr->l2_offset; } @@ -262,8 +339,6 @@ int odp_packet_l2_offset_set(odp_packet_t pkt, uint32_t offset) if (offset >= pkt_hdr->frame_len) return -1; - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); pkt_hdr->l2_offset = offset; return 0; } @@ -271,16 +346,16 @@ int odp_packet_l2_offset_set(odp_packet_t pkt, uint32_t offset) void *odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); + if (packet_parse_not_complete(pkt_hdr)) + packet_parse_full(pkt_hdr); return packet_map(pkt_hdr, pkt_hdr->l3_offset, len); } uint32_t odp_packet_l3_offset(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); + if (packet_parse_not_complete(pkt_hdr)) + packet_parse_full(pkt_hdr); return pkt_hdr->l3_offset; } @@ -291,8 +366,8 @@ int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset) if (offset >= pkt_hdr->frame_len) return -1; - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); + if (packet_parse_not_complete(pkt_hdr)) + packet_parse_full(pkt_hdr); pkt_hdr->l3_offset = offset; return 0; } @@ -300,16 +375,16 @@ int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset) void *odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); + if (packet_parse_not_complete(pkt_hdr)) + packet_parse_full(pkt_hdr); return packet_map(pkt_hdr, pkt_hdr->l4_offset, len); } uint32_t odp_packet_l4_offset(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); + if (packet_parse_not_complete(pkt_hdr)) + packet_parse_full(pkt_hdr); return pkt_hdr->l4_offset; } @@ -320,8 +395,8 @@ int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t offset) if (offset >= pkt_hdr->frame_len) return -1; - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); + if (packet_parse_not_complete(pkt_hdr)) + packet_parse_full(pkt_hdr); pkt_hdr->l4_offset = offset; return 0; } @@ -442,22 +517,7 @@ odp_packet_t odp_packet_add_data(odp_packet_t pkt, uint32_t offset, odp_packet_free(newpkt); newpkt = ODP_PACKET_INVALID; } else { - odp_packet_hdr_t *new_hdr = odp_packet_hdr(newpkt); - new_hdr->input = pkt_hdr->input; - new_hdr->buf_hdr.buf_u64 = pkt_hdr->buf_hdr.buf_u64; - if (new_hdr->buf_hdr.uarea_addr != NULL && - pkt_hdr->buf_hdr.uarea_addr != NULL) - memcpy(new_hdr->buf_hdr.uarea_addr, - pkt_hdr->buf_hdr.uarea_addr, - new_hdr->buf_hdr.uarea_size <= - pkt_hdr->buf_hdr.uarea_size ? - new_hdr->buf_hdr.uarea_size : - pkt_hdr->buf_hdr.uarea_size); - odp_atomic_store_u32( - &new_hdr->buf_hdr.ref_count, - odp_atomic_load_u32( - &pkt_hdr->buf_hdr.ref_count)); - copy_packet_parser_metadata(pkt_hdr, new_hdr); + _odp_packet_copy_md_to_packet(pkt, newpkt); odp_packet_free(pkt); } } @@ -486,22 +546,7 @@ odp_packet_t odp_packet_rem_data(odp_packet_t pkt, uint32_t offset, odp_packet_free(newpkt); newpkt = ODP_PACKET_INVALID; } else { - odp_packet_hdr_t *new_hdr = odp_packet_hdr(newpkt); - new_hdr->input = pkt_hdr->input; - new_hdr->buf_hdr.buf_u64 = pkt_hdr->buf_hdr.buf_u64; - if (new_hdr->buf_hdr.uarea_addr != NULL && - pkt_hdr->buf_hdr.uarea_addr != NULL) - memcpy(new_hdr->buf_hdr.uarea_addr, - pkt_hdr->buf_hdr.uarea_addr, - new_hdr->buf_hdr.uarea_size <= - pkt_hdr->buf_hdr.uarea_size ? - new_hdr->buf_hdr.uarea_size : - pkt_hdr->buf_hdr.uarea_size); - odp_atomic_store_u32( - &new_hdr->buf_hdr.ref_count, - odp_atomic_load_u32( - &pkt_hdr->buf_hdr.ref_count)); - copy_packet_parser_metadata(pkt_hdr, new_hdr); + _odp_packet_copy_md_to_packet(pkt, newpkt); odp_packet_free(pkt); } } @@ -699,17 +744,6 @@ int _odp_packet_copy_to_packet(odp_packet_t srcpkt, uint32_t srcoffset, return 0; } -odp_packet_t _odp_packet_alloc(odp_pool_t pool_hdl) -{ - pool_entry_t *pool = odp_pool_to_entry(pool_hdl); - - if (pool->s.params.type != ODP_POOL_PACKET) - return ODP_PACKET_INVALID; - - return (odp_packet_t)buffer_alloc(pool_hdl, - pool->s.params.buf.size); -} - /** * Parser helper function for IPv4 */ @@ -847,30 +881,11 @@ static inline void parse_udp(odp_packet_hdr_t *pkt_hdr, } /** - * Simple packet parser + * Initialize L2 related parser flags and metadata */ - -int _odp_packet_parse(odp_packet_hdr_t *pkt_hdr) +void packet_parse_l2(odp_packet_hdr_t *pkt_hdr) { - odph_ethhdr_t *eth; - odph_vlanhdr_t *vlan; - uint16_t ethtype; - uint8_t *parseptr; - uint32_t offset, seglen; - uint8_t ip_proto = 0; - - /* Reset parser metadata for new parse */ - pkt_hdr->error_flags.all = 0; - pkt_hdr->input_flags.all = 0; - pkt_hdr->output_flags.all = 0; - pkt_hdr->l2_offset = 0; - pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID; - pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID; - pkt_hdr->payload_offset = ODP_PACKET_OFFSET_INVALID; - pkt_hdr->vlan_s_tag = 0; - pkt_hdr->vlan_c_tag = 0; - pkt_hdr->l3_protocol = 0; - pkt_hdr->l4_protocol = 0; + /* Packet alloc or reset have already init other offsets and flags */ /* We only support Ethernet for now */ pkt_hdr->input_flags.eth = 1; @@ -882,6 +897,24 @@ int _odp_packet_parse(odp_packet_hdr_t *pkt_hdr) /* Assume valid L2 header, no CRC/FCS check in SW */ pkt_hdr->input_flags.l2 = 1; + pkt_hdr->input_flags.parsed_l2 = 1; +} + +/** + * Simple packet parser + */ +int packet_parse_full(odp_packet_hdr_t *pkt_hdr) +{ + odph_ethhdr_t *eth; + odph_vlanhdr_t *vlan; + uint16_t ethtype; + uint8_t *parseptr; + uint32_t offset, seglen; + uint8_t ip_proto = 0; + + if (packet_parse_l2_not_done(pkt_hdr)) + packet_parse_l2(pkt_hdr); + eth = (odph_ethhdr_t *)packet_map(pkt_hdr, 0, &seglen); offset = sizeof(odph_ethhdr_t); parseptr = (uint8_t *)ð->type; @@ -993,5 +1026,6 @@ int _odp_packet_parse(odp_packet_hdr_t *pkt_hdr) pkt_hdr->payload_offset = offset; parse_exit: + pkt_hdr->input_flags.parsed_all = 1; return pkt_hdr->error_flags.all != 0; } diff --git a/platform/linux-generic/odp_packet_flags.c b/platform/linux-generic/odp_packet_flags.c index ea308f711..dbc313748 100644 --- a/platform/linux-generic/odp_packet_flags.c +++ b/platform/linux-generic/odp_packet_flags.c @@ -9,23 +9,23 @@ #define retflag(p, x) do { \ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(p); \ - if (pkt_hdr->input_flags.unparsed) \ - _odp_packet_parse(pkt_hdr); \ + if (packet_parse_not_complete(pkt_hdr)) \ + packet_parse_full(pkt_hdr); \ return pkt_hdr->x; \ } while (0) #define setflag(p, x, v) do { \ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(p); \ - if (pkt_hdr->input_flags.unparsed) \ - _odp_packet_parse(pkt_hdr); \ + if (packet_parse_not_complete(pkt_hdr)) \ + packet_parse_full(pkt_hdr); \ pkt_hdr->x = v & 1; \ } while (0) int odp_packet_has_error(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->input_flags.unparsed) - _odp_packet_parse(pkt_hdr); + if (packet_parse_not_complete(pkt_hdr)) + packet_parse_full(pkt_hdr); return odp_packet_hdr(pkt)->error_flags.all != 0; } @@ -33,7 +33,9 @@ int odp_packet_has_error(odp_packet_t pkt) int odp_packet_has_l2(odp_packet_t pkt) { - retflag(pkt, input_flags.l2); + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + + return pkt_hdr->input_flags.l2; } int odp_packet_has_l3(odp_packet_t pkt) @@ -48,12 +50,16 @@ int odp_packet_has_l4(odp_packet_t pkt) int odp_packet_has_eth(odp_packet_t pkt) { - retflag(pkt, input_flags.eth); + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + + return pkt_hdr->input_flags.eth; } int odp_packet_has_jumbo(odp_packet_t pkt) { - retflag(pkt, input_flags.jumbo); + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + + return pkt_hdr->input_flags.jumbo; } int odp_packet_has_vlan(odp_packet_t pkt) diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index b3ca4c818..1246bff71 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -91,6 +91,12 @@ int odp_pktio_term_global(void) int id; int pktio_if; + for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) { + pktio_entry = &pktio_tbl->entries[id - 1]; + odp_pktio_close(pktio_entry->s.handle); + odp_queue_destroy(pktio_entry->s.outq_default); + } + for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) { if (pktio_if_ops[pktio_if]->term) if (pktio_if_ops[pktio_if]->term()) @@ -98,11 +104,6 @@ int odp_pktio_term_global(void) pktio_if); } - for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) { - pktio_entry = &pktio_tbl->entries[id - 1]; - odp_queue_destroy(pktio_entry->s.outq_default); - } - ret = odp_shm_free(odp_shm_lookup("odp_pktio_entries")); if (ret < 0) ODP_ERR("shm free failed for odp_pktio_entries"); @@ -203,10 +204,10 @@ static odp_pktio_t setup_pktio_entry(const char *dev, odp_pool_t pool, int ret = -1; int pktio_if; - if (strlen(dev) >= IF_NAMESIZE) { + if (strlen(dev) >= PKTIO_NAME_LEN - 1) { /* ioctl names limitation */ ODP_ERR("pktio name %s is too big, limit is %d bytes\n", - dev, IF_NAMESIZE); + dev, PKTIO_NAME_LEN - 1); return ODP_PKTIO_INVALID; } @@ -238,7 +239,8 @@ static odp_pktio_t setup_pktio_entry(const char *dev, odp_pool_t pool, id = ODP_PKTIO_INVALID; ODP_ERR("Unable to init any I/O type.\n"); } else { - snprintf(pktio_entry->s.name, IF_NAMESIZE, "%s", dev); + snprintf(pktio_entry->s.name, + sizeof(pktio_entry->s.name), "%s", dev); pktio_entry->s.state = STATE_STOP; unlock_entry_classifier(pktio_entry); } @@ -358,7 +360,7 @@ odp_pktio_t odp_pktio_lookup(const char *dev) lock_entry(entry); if (!is_free(entry) && - strncmp(entry->s.name, dev, IF_NAMESIZE) == 0) + strncmp(entry->s.name, dev, sizeof(entry->s.name)) == 0) id = _odp_cast_scalar(odp_pktio_t, i); unlock_entry(entry); diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c index 30d4b2b65..76a4aa585 100644 --- a/platform/linux-generic/odp_pool.c +++ b/platform/linux-generic/odp_pool.c @@ -57,8 +57,8 @@ static const char SHM_DEFAULT_NAME[] = "odp_buffer_pools"; /* Pool entry pointers (for inlining) */ void *pool_entry_ptr[ODP_CONFIG_POOLS]; -/* Local cache for buffer alloc/free acceleration */ -static __thread local_cache_t local_cache[ODP_CONFIG_POOLS]; +/* Cache thread id locally for local cache performance */ +static __thread int local_id; int odp_pool_init_global(void) { @@ -107,6 +107,12 @@ int odp_pool_init_global(void) return 0; } +int odp_pool_init_local(void) +{ + local_id = odp_thread_id(); + return 0; +} + int odp_pool_term_global(void) { int i; @@ -442,6 +448,7 @@ int odp_pool_destroy(odp_pool_t pool_hdl) { uint32_t pool_id = pool_handle_to_index(pool_hdl); pool_entry_t *pool = get_pool_entry(pool_id); + int i; if (pool == NULL) return -1; @@ -455,8 +462,9 @@ int odp_pool_destroy(odp_pool_t pool_hdl) return -1; } - /* Make sure local cache is empty */ - flush_cache(&local_cache[pool_id], &pool->s); + /* Make sure local caches are empty */ + for (i = 0; i < _ODP_INTERNAL_MAX_THREADS; i++) + flush_cache(&pool->s.local_cache[i], &pool->s); /* Call fails if pool has allocated buffers */ if (odp_atomic_load_u32(&pool->s.bufcount) < pool->s.buf_num) { @@ -485,8 +493,9 @@ odp_buffer_t buffer_alloc(odp_pool_t pool_hdl, size_t size) return ODP_BUFFER_INVALID; /* Try to satisfy request from the local cache */ - buf = (odp_anybuf_t *)(void *)get_local_buf(&local_cache[pool_id], - &pool->s, totsize); + buf = (odp_anybuf_t *) + (void *)get_local_buf(&pool->s.local_cache[local_id], + &pool->s, totsize); /* If cache is empty, satisfy request from the pool */ if (odp_unlikely(buf == NULL)) { @@ -517,9 +526,6 @@ odp_buffer_t buffer_alloc(odp_pool_t pool_hdl, size_t size) /* By default, buffers are not associated with an ordered queue */ buf->buf.origin_qe = NULL; - if (buf->buf.type == ODP_EVENT_PACKET) - packet_init(pool, &buf->pkt, size); - return odp_hdr_to_buf(&buf->buf); } @@ -537,7 +543,7 @@ void odp_buffer_free(odp_buffer_t buf) if (odp_unlikely(pool->s.low_wm_assert)) ret_buf(&pool->s, buf_hdr); else - ret_local_buf(&local_cache[pool->s.pool_id], buf_hdr); + ret_local_buf(&pool->s.local_cache[local_id], buf_hdr); } void _odp_flush_caches(void) @@ -546,7 +552,7 @@ void _odp_flush_caches(void) for (i = 0; i < ODP_CONFIG_POOLS; i++) { pool_entry_t *pool = get_pool_entry(i); - flush_cache(&local_cache[i], &pool->s); + flush_cache(&pool->s.local_cache[local_id], &pool->s); } } diff --git a/platform/linux-generic/pktio/io_ops.c b/platform/linux-generic/pktio/io_ops.c index bd4cc4839..3b344e6ad 100644 --- a/platform/linux-generic/pktio/io_ops.c +++ b/platform/linux-generic/pktio/io_ops.c @@ -15,6 +15,9 @@ const pktio_if_ops_t * const pktio_if_ops[] = { #ifdef ODP_NETMAP &netmap_pktio_ops, #endif +#ifdef HAVE_PCAP + &pcap_pktio_ops, +#endif &sock_mmap_pktio_ops, &sock_mmsg_pktio_ops, NULL diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c index 22f04758f..0d8dadd0f 100644 --- a/platform/linux-generic/pktio/loop.c +++ b/platform/linux-generic/pktio/loop.c @@ -55,13 +55,16 @@ static int loopback_recv(pktio_entry_t *pktio_entry, odp_packet_t pkts[], int nbr, i; odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX]; queue_entry_t *qentry; + odp_packet_hdr_t *pkt_hdr; qentry = queue_to_qentry(pktio_entry->s.pkt_loop.loopq); nbr = queue_deq_multi(qentry, hdr_tbl, len); for (i = 0; i < nbr; ++i) { pkts[i] = _odp_packet_from_buffer(odp_hdr_to_buf(hdr_tbl[i])); - _odp_packet_reset_parse(pkts[i]); + pkt_hdr = odp_packet_hdr(pkts[i]); + packet_parse_reset(pkts[i]); + packet_parse_l2(pkt_hdr); } return nbr; diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c index ab4667e9c..ecda9c58a 100644 --- a/platform/linux-generic/pktio/netmap.c +++ b/platform/linux-generic/pktio/netmap.c @@ -168,6 +168,7 @@ static void netmap_recv_cb(u_char *arg, const struct nm_pkthdr *hdr, struct dispatch_args *args = (struct dispatch_args *)arg; pkt_netmap_t *pkt_nm = &args->pktio_entry->s.pkt_nm; odp_packet_t pkt; + odp_packet_hdr_t *pkt_hdr; size_t frame_len = (size_t)hdr->len; if (odp_unlikely(frame_len > pkt_nm->max_frame_len)) { @@ -181,10 +182,12 @@ static void netmap_recv_cb(u_char *arg, const struct nm_pkthdr *hdr, return; } - pkt = odp_packet_alloc(pkt_nm->pool, frame_len); + pkt = packet_alloc(pkt_nm->pool, frame_len, 1); if (pkt == ODP_PACKET_INVALID) return; + pkt_hdr = odp_packet_hdr(pkt); + /* For now copy the data in the mbuf, worry about zero-copy later */ if (odp_packet_copydata_in(pkt, 0, frame_len, buf) != 0) { @@ -192,7 +195,7 @@ static void netmap_recv_cb(u_char *arg, const struct nm_pkthdr *hdr, return; } - _odp_packet_reset_parse(pkt); + packet_parse_l2(pkt_hdr); args->pkt_table[args->nb_rx++] = pkt; } diff --git a/platform/linux-generic/pktio/pcap.c b/platform/linux-generic/pktio/pcap.c new file mode 100644 index 000000000..0817bf595 --- /dev/null +++ b/platform/linux-generic/pktio/pcap.c @@ -0,0 +1,381 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * PCAP pktio type + * + * This file provides a pktio interface that allows for reading from + * and writing to pcap capture files. It is intended to be used as + * simple way of injecting test packets into an application for the + * purpose of functional testing. + * + * To use this interface the name passed to odp_pktio_open() must begin + * with "pcap:" and be in the format; + * + * pcap:in=test.pcap:out=test_out.pcap:loops=10 + * + * in the name of the input pcap file. If no input file is given + * attempts to receive from the pktio will just return no + * packets. If an input file is specified it must exist and be + * a readable pcap file with a link type of DLT_EN10MB. + * out the name of the output pcap file. If no output file is + * given any packets transmitted over the interface will just + * be freed. If an output file is specified and the file + * doesn't exist it will be created, if it does exist it will + * be overwritten. + * loops the number of times to iterate through the input file, set + * to 0 to loop indefinitely. The default value is 1. + * + * The total length of the string is limited by PKTIO_NAME_LEN. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <odp.h> +#include <odp_packet_internal.h> +#include <odp_packet_io_internal.h> + +#include <odp/helper/eth.h> + +#include <errno.h> +#include <pcap/pcap.h> +#include <pcap/bpf.h> + +#define PKTIO_PCAP_MTU (64 * 1024) +static const char pcap_mac[] = {0x02, 0xe9, 0x34, 0x80, 0x73, 0x04}; + +static int _pcapif_parse_devname(pkt_pcap_t *pcap, const char *devname) +{ + char *tok; + char in[PKTIO_NAME_LEN]; + + if (strncmp(devname, "pcap:", 5) != 0) + return -1; + + snprintf(in, sizeof(in), "%s", devname); + + for (tok = strtok(in + 5, ":"); tok; tok = strtok(NULL, ":")) { + if (strncmp(tok, "in=", 3) == 0 && !pcap->fname_rx) { + tok += 3; + pcap->fname_rx = strdup(tok); + } else if (strncmp(tok, "out=", 4) == 0 && !pcap->fname_tx) { + tok += 4; + pcap->fname_tx = strdup(tok); + } else if (strncmp(tok, "loops=", 6) == 0) { + pcap->loops = atoi(tok + 6); + if (pcap->loops < 0) { + ODP_ERR("invalid loop count\n"); + return -1; + } + } + } + + return 0; +} + +static int _pcapif_init_rx(pkt_pcap_t *pcap) +{ + char errbuf[PCAP_ERRBUF_SIZE]; + int linktype; + + pcap->rx = pcap_open_offline(pcap->fname_rx, errbuf); + if (!pcap->rx) { + ODP_ERR("failed to open pcap file %s (%s)\n", + pcap->fname_rx, errbuf); + return -1; + } + + linktype = pcap_datalink(pcap->rx); + if (linktype != DLT_EN10MB) { + ODP_ERR("unsupported datalink type: %d\n", linktype); + return -1; + } + + return 0; +} + +static int _pcapif_init_tx(pkt_pcap_t *pcap) +{ + pcap_t *tx = pcap->rx; + + if (!tx) { + /* if there is no rx pcap_t already open for rx, a dummy + * one needs to be opened for writing the dump */ + tx = pcap_open_dead(DLT_EN10MB, PKTIO_PCAP_MTU); + if (!tx) { + ODP_ERR("failed to open TX dump\n"); + return -1; + } + + pcap->tx = tx; + } + + pcap->buf = malloc(PKTIO_PCAP_MTU); + if (!pcap->buf) { + ODP_ERR("failed to malloc temp buffer\n"); + return -1; + } + + pcap->tx_dump = pcap_dump_open(tx, pcap->fname_tx); + if (!pcap->tx_dump) { + ODP_ERR("failed to open dump file %s (%s)\n", + pcap->fname_tx, pcap_geterr(tx)); + return -1; + } + + return pcap_dump_flush(pcap->tx_dump); +} + +static int pcapif_init(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, + const char *devname, odp_pool_t pool) +{ + pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + int ret; + + memset(pcap, 0, sizeof(pkt_pcap_t)); + pcap->loop_cnt = 1; + pcap->loops = 1; + pcap->pool = pool; + pcap->promisc = 1; + + ret = _pcapif_parse_devname(pcap, devname); + + if (ret == 0 && pcap->fname_rx) + ret = _pcapif_init_rx(pcap); + + if (ret == 0 && pcap->fname_tx) + ret = _pcapif_init_tx(pcap); + + if (ret == 0 && (!pcap->rx && !pcap->tx_dump)) + ret = -1; + + return ret; +} + +static int pcapif_close(pktio_entry_t *pktio_entry) +{ + pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + + if (pcap->tx_dump) + pcap_dump_close(pcap->tx_dump); + + if (pcap->tx) + pcap_close(pcap->tx); + + if (pcap->rx) + pcap_close(pcap->rx); + + free(pcap->buf); + free(pcap->fname_rx); + free(pcap->fname_tx); + + return 0; +} + +static int _pcapif_reopen(pkt_pcap_t *pcap) +{ + char errbuf[PCAP_ERRBUF_SIZE]; + + if (pcap->loops != 0 && ++pcap->loop_cnt >= pcap->loops) + return 1; + + if (pcap->rx) + pcap_close(pcap->rx); + + pcap->rx = pcap_open_offline(pcap->fname_rx, errbuf); + if (!pcap->rx) { + ODP_ERR("failed to reopen pcap file %s (%s)\n", + pcap->fname_rx, errbuf); + return 1; + } + + return 0; +} + +static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, odp_packet_t pkts[], + unsigned len) +{ + unsigned i; + struct pcap_pkthdr *hdr; + const u_char *data; + odp_packet_t pkt; + odp_packet_hdr_t *pkt_hdr; + uint32_t pkt_len; + pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + + ODP_ASSERT(pktio_entry->s.state == STATE_START); + + if (!pcap->rx) + return 0; + + pkt = ODP_PACKET_INVALID; + pkt_len = 0; + + for (i = 0; i < len; ) { + int ret; + + if (pkt == ODP_PACKET_INVALID) { + pkt = packet_alloc(pcap->pool, 0 /*default len*/, 1); + if (odp_unlikely(pkt == ODP_PACKET_INVALID)) + break; + pkt_len = odp_packet_len(pkt); + } + + ret = pcap_next_ex(pcap->rx, &hdr, &data); + + /* end of file, attempt to reopen if within loop limit */ + if (ret == -2 && _pcapif_reopen(pcap) == 0) + continue; + + if (ret != 1) + break; + + pkt_hdr = odp_packet_hdr(pkt); + + if (!odp_packet_pull_tail(pkt, pkt_len - hdr->caplen)) { + ODP_ERR("failed to pull tail: pkt_len: %d caplen: %d\n", + pkt_len, hdr->caplen); + break; + } + + if (odp_packet_copydata_in(pkt, 0, hdr->caplen, data) != 0) { + ODP_ERR("failed to copy packet data\n"); + break; + } + + packet_parse_l2(pkt_hdr); + + pkts[i] = pkt; + pkt = ODP_PACKET_INVALID; + + i++; + } + + if (pkt != ODP_PACKET_INVALID) + odp_packet_free(pkt); + + return i; +} + +static int _pcapif_dump_pkt(pkt_pcap_t *pcap, odp_packet_t pkt) +{ + struct pcap_pkthdr hdr; + + if (!pcap->tx_dump) + return 0; + + hdr.caplen = odp_packet_len(pkt); + hdr.len = hdr.caplen; + (void)gettimeofday(&hdr.ts, NULL); + + if (odp_packet_copydata_out(pkt, 0, hdr.len, pcap->buf) != 0) + return -1; + + pcap_dump(pcap->tx_dump, &hdr, pcap->buf); + (void)pcap_dump_flush(pcap->tx_dump); + + return 0; +} + +static int pcapif_send_pkt(pktio_entry_t *pktio_entry, odp_packet_t pkts[], + unsigned len) +{ + pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + unsigned i; + + ODP_ASSERT(pktio_entry->s.state == STATE_START); + + for (i = 0; i < len; ++i) { + if (odp_packet_len(pkts[i]) > PKTIO_PCAP_MTU) { + if (i == 0) + return -1; + break; + } + + if (_pcapif_dump_pkt(pcap, pkts[i]) != 0) + break; + + odp_packet_free(pkts[i]); + } + + return i; +} + +static int pcapif_mtu_get(pktio_entry_t *pktio_entry ODP_UNUSED) +{ + return PKTIO_PCAP_MTU; +} + +static int pcapif_mac_addr_get(pktio_entry_t *pktio_entry ODP_UNUSED, + void *mac_addr) +{ + memcpy(mac_addr, pcap_mac, ODPH_ETHADDR_LEN); + + return ODPH_ETHADDR_LEN; +} + +static int pcapif_promisc_mode_set(pktio_entry_t *pktio_entry, + odp_bool_t enable) +{ + char filter_exp[64] = {0}; + struct bpf_program bpf; + pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + + if (!pcap->rx) { + pcap->promisc = enable; + return 0; + } + + if (!enable) { + char mac_str[18]; + + snprintf(mac_str, sizeof(mac_str), + "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + pcap_mac[0], pcap_mac[1], pcap_mac[2], + pcap_mac[3], pcap_mac[4], pcap_mac[5]); + + snprintf(filter_exp, sizeof(filter_exp), + "ether dst %s or broadcast or multicast", + mac_str); + } + + if (pcap_compile(pcap->rx, &bpf, filter_exp, + 0, PCAP_NETMASK_UNKNOWN) != 0) { + ODP_ERR("failed to compile promisc mode filter: %s\n", + pcap_geterr(pcap->rx)); + return -1; + } + + if (pcap_setfilter(pcap->rx, &bpf) != 0) { + ODP_ERR("failed to set promisc mode filter: %s\n", + pcap_geterr(pcap->rx)); + return -1; + } + + pcap->promisc = enable; + + return 0; +} + +static int pcapif_promisc_mode_get(pktio_entry_t *pktio_entry) +{ + return pktio_entry->s.pkt_pcap.promisc; +} + +const pktio_if_ops_t pcap_pktio_ops = { + .open = pcapif_init, + .close = pcapif_close, + .recv = pcapif_recv_pkt, + .send = pcapif_send_pkt, + .mtu_get = pcapif_mtu_get, + .promisc_mode_set = pcapif_promisc_mode_set, + .promisc_mode_get = pcapif_promisc_mode_get, + .mac_get = pcapif_mac_addr_get +}; diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c index a95b9a80e..7e3002740 100644 --- a/platform/linux-generic/pktio/socket.c +++ b/platform/linux-generic/pktio/socket.c @@ -322,7 +322,7 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, memset(msgvec, 0, sizeof(msgvec)); for (i = 0; i < (int)len; i++) { - pkt_table[i] = _odp_packet_alloc(pkt_sock->pool); + pkt_table[i] = packet_alloc(pkt_sock->pool, 0 /*default*/, 1); if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID)) break; @@ -336,6 +336,7 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, recv_msgs = recvmmsg(sockfd, msgvec, msgvec_len, MSG_DONTWAIT, NULL); for (i = 0; i < recv_msgs; i++) { + odp_packet_hdr_t *pkt_hdr; void *base = msgvec[i].msg_hdr.msg_iov->iov_base; struct ethhdr *eth_hdr = base; @@ -346,11 +347,13 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, continue; } - /* Parse and set packet header data */ + pkt_hdr = odp_packet_hdr(pkt_table[i]); + odp_packet_pull_tail(pkt_table[i], odp_packet_len(pkt_table[i]) - msgvec[i].msg_len); - _odp_packet_reset_parse(pkt_table[i]); + + packet_parse_l2(pkt_hdr); pkt_table[nb_rx] = pkt_table[i]; nb_rx++; diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c index ba773a3e6..35d24c693 100644 --- a/platform/linux-generic/pktio/socket_mmap.c +++ b/platform/linux-generic/pktio/socket_mmap.c @@ -118,6 +118,7 @@ static inline unsigned pkt_mmap_v2_rx(int sock, struct ring *ring, uint8_t *pkt_buf; int pkt_len; struct ethhdr *eth_hdr; + odp_packet_hdr_t *pkt_hdr; unsigned i = 0; (void)sock; @@ -142,20 +143,21 @@ static inline unsigned pkt_mmap_v2_rx(int sock, struct ring *ring, continue; } - pkt_table[i] = odp_packet_alloc(pool, pkt_len); + pkt_table[i] = packet_alloc(pool, pkt_len, 1); if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID)) break; + pkt_hdr = odp_packet_hdr(pkt_table[i]); + if (odp_packet_copydata_in(pkt_table[i], 0, pkt_len, pkt_buf) != 0) { odp_packet_free(pkt_table[i]); break; } - mmap_rx_user_ready(ppd.raw); + packet_parse_l2(pkt_hdr); - /* Parse and set packet header data */ - _odp_packet_reset_parse(pkt_table[i]); + mmap_rx_user_ready(ppd.raw); frame_num = next_frame_num; i++; diff --git a/platform/linux-generic/test/Makefile.am b/platform/linux-generic/test/Makefile.am index 327d5bf2f..a657de9fc 100644 --- a/platform/linux-generic/test/Makefile.am +++ b/platform/linux-generic/test/Makefile.am @@ -27,6 +27,11 @@ TESTS = pktio/pktio_run \ ${top_builddir}/test/validation/system/system_main$(EXEEXT) SUBDIRS = $(ODP_MODULES) + +if HAVE_PCAP +TESTS += pktio/pktio_run_pcap +endif + endif #performance tests refer to pktio_env diff --git a/platform/linux-generic/test/pktio/Makefile.am b/platform/linux-generic/test/pktio/Makefile.am index 93281dd1b..6fe20139c 100644 --- a/platform/linux-generic/test/pktio/Makefile.am +++ b/platform/linux-generic/test/pktio/Makefile.am @@ -1,2 +1,6 @@ dist_bin_SCRIPTS = pktio_env \ pktio_run + +if HAVE_PCAP +dist_bin_SCRIPTS += pktio_run_pcap +endif diff --git a/platform/linux-generic/test/pktio/pktio_env b/platform/linux-generic/test/pktio/pktio_env index 5e547e47b..345b5bd56 100644 --- a/platform/linux-generic/test/pktio/pktio_env +++ b/platform/linux-generic/test/pktio/pktio_env @@ -18,10 +18,10 @@ # Network set up # IF0 <---> IF1 # IF2 <---> IF3 -IF0=pktio-p0-p1 -IF1=pktio-p1-p0 -IF2=pktio-p2-p3 -IF3=pktio-p3-p2 +IF0=pktiop0p1 +IF1=pktiop1p0 +IF2=pktiop2p3 +IF3=pktiop3p2 if [ "$0" = "$BASH_SOURCE" ]; then echo "Error: Platform specific env file has to be sourced." diff --git a/platform/linux-generic/test/pktio/pktio_run_pcap b/platform/linux-generic/test/pktio/pktio_run_pcap new file mode 100755 index 000000000..c130417c5 --- /dev/null +++ b/platform/linux-generic/test/pktio/pktio_run_pcap @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Copyright (c) 2015, Linaro Limited +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# directories where pktio_main binary can be found: +# -in the validation dir when running make check (intree or out of tree) +# -in the script directory, when running after 'make install', or +# -in the validation when running standalone intree. +# -in the current directory. +# running stand alone out of tree requires setting PATH +PATH=${TEST_DIR}/pktio:$PATH +PATH=$(dirname $0):$PATH +PATH=$(dirname $0)/../../../../test/validation/pktio:$PATH +PATH=.:$PATH + +pktio_main_path=$(which pktio_main${EXEEXT}) +if [ -x "$pktio_main_path" ] ; then + echo "running with $pktio_main_path" +else + echo "cannot find pktio_main${EXEEXT}: please set you PATH for it." +fi + +PCAP_FNAME=vald.pcap +export ODP_PKTIO_IF0="pcap:out=${PCAP_FNAME}" +export ODP_PKTIO_IF1="pcap:in=${PCAP_FNAME}" +pktio_main${EXEEXT} +ret=$? +rm -f ${PCAP_FNAME} +exit $ret |