Modify dpdk pktio to take advantage of multi-alloc/free. Others pktios do alloc/free still one packet at a time. For example, l2fwd test application packet throughput is increased about 10% (with dpdk pktio).
Signed-off-by: Petri Savolainen <[email protected]> Signed-off-by: Matias Elo <[email protected]> --- V2: - Allocate MTU sized packets with socket pktio .../linux-generic/include/odp_packet_internal.h | 4 +- platform/linux-generic/include/odp_packet_socket.h | 1 + platform/linux-generic/odp_packet.c | 71 +++++++++++++--------- platform/linux-generic/pktio/dpdk.c | 24 +++++--- platform/linux-generic/pktio/netmap.c | 5 +- platform/linux-generic/pktio/pcap.c | 26 ++------ platform/linux-generic/pktio/socket.c | 21 +++++-- platform/linux-generic/pktio/socket_mmap.c | 7 ++- platform/linux-generic/pktio/tap.c | 7 ++- 9 files changed, 94 insertions(+), 72 deletions(-) diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 4c4e36c..392d670 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -306,7 +306,9 @@ static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr) /* Forward declarations */ int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt); -odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse); +/* Packet alloc of pktios */ +int packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, + odp_packet_t pkt[], int max_num); /* Fill in parser metadata for L2 */ void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len); diff --git a/platform/linux-generic/include/odp_packet_socket.h b/platform/linux-generic/include/odp_packet_socket.h index ccff69a..dbfc9f1 100644 --- a/platform/linux-generic/include/odp_packet_socket.h +++ b/platform/linux-generic/include/odp_packet_socket.h @@ -45,6 +45,7 @@ typedef struct { int sockfd; /**< socket descriptor */ odp_pool_t pool; /**< pool to alloc packets from */ + uint32_t mtu; /**< maximum transmission unit */ unsigned char if_mac[ETH_ALEN]; /**< IF eth mac addr */ uint8_t *cache_ptr[ODP_PACKET_SOCKET_MAX_BURST_RX]; odp_shm_t shm; diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index 474fa81..c4cf324 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -76,35 +76,46 @@ static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr, pkt_hdr->input = ODP_PKTIO_INVALID; } -odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse) +int packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, + odp_packet_t pkt[], int max_num) { + odp_packet_hdr_t *pkt_hdr; + pool_entry_t *pool = odp_pool_to_entry(pool_hdl); + int num, i; + + num = buffer_alloc_multi(pool_hdl, len, (odp_buffer_t *)pkt, max_num); + + for (i = 0; i < num; i++) { + pkt_hdr = odp_packet_hdr(pkt[i]); + packet_init(pool, pkt_hdr, len, 1 /* do parse */); + + if (pkt_hdr->tailroom >= pkt_hdr->buf_hdr.segsize) + pull_tail_seg(pkt_hdr); + } + + return num; +} + +odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len) +{ + pool_entry_t *pool = odp_pool_to_entry(pool_hdl); + size_t pkt_size = len ? len : pool->s.params.buf.size; 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) + if (pool->s.params.type != ODP_POOL_PACKET) { + __odp_errno = EINVAL; return ODP_PACKET_INVALID; - - /* Handle special case for zero-length packets */ - if (len == 0) { - 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; } + pkt = (odp_packet_t)buffer_alloc(pool_hdl, pkt_size); + if (pkt == ODP_PACKET_INVALID) + return ODP_PACKET_INVALID; + pkt_hdr = odp_packet_hdr(pkt); - packet_init(pool, pkt_hdr, len, parse); + packet_init(pool, pkt_hdr, pkt_size, 0 /* do not parse */); + if (len == 0) + pull_tail(pkt_hdr, pkt_size); if (pkt_hdr->tailroom >= pkt_hdr->buf_hdr.segsize) pull_tail_seg(pkt_hdr); @@ -112,11 +123,6 @@ odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse) return pkt; } -odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len) -{ - return packet_alloc(pool_hdl, len, 0); -} - int odp_packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, odp_packet_t pkt[], int num) { @@ -135,9 +141,12 @@ int odp_packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, for (i = 0; i < count; ++i) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt[i]); - packet_init(pool, pkt_hdr, pkt_size, 0); + packet_init(pool, pkt_hdr, pkt_size, 0 /* do not parse */); if (len == 0) pull_tail(pkt_hdr, pkt_size); + + if (pkt_hdr->tailroom >= pkt_hdr->buf_hdr.segsize) + pull_tail_seg(pkt_hdr); } return count; @@ -145,12 +154,16 @@ int odp_packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, void odp_packet_free(odp_packet_t pkt) { - odp_buffer_free((odp_buffer_t)pkt); + uint32_t pool_id = pool_id_from_buf((odp_buffer_t)pkt); + + buffer_free(pool_id, (odp_buffer_t)pkt); } void odp_packet_free_multi(const odp_packet_t pkt[], int num) { - odp_buffer_free_multi((const odp_buffer_t *)pkt, num); + uint32_t pool_id = pool_id_from_buf((odp_buffer_t)pkt[0]); + + buffer_free_multi(pool_id, (const odp_buffer_t * const)pkt, num); } int odp_packet_reset(odp_packet_t pkt, uint32_t len) diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index a5934a5..1fad8a9 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -706,7 +706,7 @@ static int dpdk_stop(pktio_entry_t *pktio_entry) static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], struct rte_mbuf *mbuf_table[], - uint16_t num, odp_time_t *ts) + uint16_t mbuf_num, odp_time_t *ts) { odp_packet_t pkt; odp_packet_hdr_t *pkt_hdr; @@ -715,9 +715,15 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, void *buf; int i, j; int nb_pkts = 0; + int alloc_len, num; + odp_pool_t pool = pktio_entry->s.pkt_dpdk.pool; + + /* Allocate maximum sized packets */ + alloc_len = pktio_entry->s.pkt_dpdk.data_room; + + num = packet_alloc_multi(pool, alloc_len, pkt_table, mbuf_num); for (i = 0; i < num; i++) { - odp_pool_t pool = pktio_entry->s.pkt_dpdk.pool; odp_packet_hdr_t parsed_hdr; mbuf = mbuf_table[i]; @@ -738,18 +744,16 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, &parsed_hdr)) goto fail; } - pkt = packet_alloc(pool, pkt_len, 1); - if (pkt == ODP_PACKET_INVALID) - goto fail; + pkt = pkt_table[i]; pkt_hdr = odp_packet_hdr(pkt); + pull_tail(pkt_hdr, alloc_len - pkt_len); /* For now copy the data in the mbuf, worry about zero-copy later */ - if (odp_packet_copy_from_mem(pkt, 0, pkt_len, buf) != 0) { - odp_packet_free(pkt); + if (odp_packet_copy_from_mem(pkt, 0, pkt_len, buf) != 0) goto fail; - } + pkt_hdr->input = pktio_entry->s.handle; if (pktio_cls_enabled(pktio_entry)) @@ -770,7 +774,9 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, return nb_pkts; fail: - for (j = i; j < num; j++) + odp_packet_free_multi(&pkt_table[i], mbuf_num - i); + + for (j = i; j < mbuf_num; j++) rte_pktmbuf_free(mbuf_table[j]); return (i > 0 ? i : -1); diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c index 3017e40..6498429 100644 --- a/platform/linux-generic/pktio/netmap.c +++ b/platform/linux-generic/pktio/netmap.c @@ -599,6 +599,7 @@ static inline int netmap_pkt_to_odp(pktio_entry_t *pktio_entry, odp_pool_t pool = pktio_entry->s.pkt_nm.pool; odp_packet_hdr_t *pkt_hdr; odp_packet_hdr_t parsed_hdr; + int num; if (odp_unlikely(len > pktio_entry->s.pkt_nm.max_frame_len)) { ODP_ERR("RX: frame too big %" PRIu16 " %zu!\n", len, @@ -616,8 +617,8 @@ static inline int netmap_pkt_to_odp(pktio_entry_t *pktio_entry, len, &pool, &parsed_hdr)) return -1; } - pkt = packet_alloc(pool, len, 1); - if (pkt == ODP_PACKET_INVALID) + num = packet_alloc_multi(pool, len, &pkt, 1); + if (num != 1) return -1; pkt_hdr = odp_packet_hdr(pkt); diff --git a/platform/linux-generic/pktio/pcap.c b/platform/linux-generic/pktio/pcap.c index e501858..e54a56f 100644 --- a/platform/linux-generic/pktio/pcap.c +++ b/platform/linux-generic/pktio/pcap.c @@ -224,19 +224,9 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, int index ODP_UNUSED, pktio_entry->s.config.pktin.bit.ts_ptp) ts = &ts_val; - 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 */ @@ -246,17 +236,17 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, int index ODP_UNUSED, if (ret != 1) break; + pkt_len = hdr->caplen; + + ret = packet_alloc_multi(pcap->pool, pkt_len, &pkt, 1); + if (odp_unlikely(ret != 1)) + break; + if (ts != NULL) ts_val = odp_time_global(); 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_copy_from_mem(pkt, 0, hdr->caplen, data) != 0) { ODP_ERR("failed to copy packet data\n"); break; @@ -269,7 +259,6 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, int index ODP_UNUSED, pkt_hdr->input = pktio_entry->s.handle; pkts[i] = pkt; - pkt = ODP_PACKET_INVALID; i++; } @@ -277,9 +266,6 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, int index ODP_UNUSED, odp_ticketlock_unlock(&pktio_entry->s.rxl); - if (pkt != ODP_PACKET_INVALID) - odp_packet_free(pkt); - return i; } diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c index 0309b0d..e01b0a5 100644 --- a/platform/linux-generic/pktio/socket.c +++ b/platform/linux-generic/pktio/socket.c @@ -527,6 +527,10 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev, if (err != 0) goto error; + pkt_sock->mtu = mtu_get_fd(sockfd, netdev); + if (!pkt_sock->mtu) + goto error; + /* bind socket to if */ memset(&sa_ll, 0, sizeof(sa_ll)); sa_ll.sll_family = AF_PACKET; @@ -659,6 +663,7 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, void *base = msgvec[i].msg_hdr.msg_iov->iov_base; struct ethhdr *eth_hdr = base; uint16_t pkt_len = msgvec[i].msg_len; + int num; /* Don't receive packets sent by ourselves */ if (odp_unlikely(ethaddrs_equal(pkt_sock->if_mac, @@ -668,8 +673,8 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, if (cls_classify_packet(pktio_entry, base, pkt_len, pkt_len, &pool, &parsed_hdr)) continue; - pkt = packet_alloc(pool, pkt_len, 1); - if (pkt == ODP_PACKET_INVALID) + num = packet_alloc_multi(pool, pkt_len, &pkt, 1); + if (num != 1) continue; pkt_hdr = odp_packet_hdr(pkt); @@ -690,10 +695,14 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, [ODP_BUFFER_MAX_SEG]; for (i = 0; i < (int)len; i++) { - pkt_table[i] = packet_alloc(pkt_sock->pool, - 0 /*default*/, 1); - if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID)) + int num; + + num = packet_alloc_multi(pkt_sock->pool, pkt_sock->mtu, + &pkt_table[i], 1); + if (odp_unlikely(num != 1)) { + pkt_table[i] = ODP_PACKET_INVALID; break; + } msgvec[i].msg_hdr.msg_iovlen = _rx_pkt_to_iovec(pkt_table[i], iovecs[i]); @@ -818,7 +827,7 @@ static int sock_mmsg_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, */ static uint32_t sock_mtu_get(pktio_entry_t *pktio_entry) { - return mtu_get_fd(pktio_entry->s.pkt_sock.sockfd, pktio_entry->s.name); + return pktio_entry->s.pkt_sock.mtu; } /* diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c index b6be81a..8b24c99 100644 --- a/platform/linux-generic/pktio/socket_mmap.c +++ b/platform/linux-generic/pktio/socket_mmap.c @@ -171,6 +171,7 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t *pktio_entry, odp_packet_hdr_t *hdr; odp_packet_hdr_t parsed_hdr; odp_pool_t pool = pkt_sock->pool; + int num; if (!mmap_rx_kernel_ready(ring->rd[frame_num].iov_base)) break; @@ -208,8 +209,10 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t *pktio_entry, } } - pkt_table[nb_rx] = packet_alloc(pool, pkt_len, 1); - if (odp_unlikely(pkt_table[nb_rx] == ODP_PACKET_INVALID)) { + num = packet_alloc_multi(pool, pkt_len, &pkt_table[nb_rx], 1); + + if (odp_unlikely(num != 1)) { + pkt_table[nb_rx] = ODP_PACKET_INVALID; 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 a9a8886..d758a39 100644 --- a/platform/linux-generic/pktio/tap.c +++ b/platform/linux-generic/pktio/tap.c @@ -185,11 +185,12 @@ static odp_packet_t pack_odp_pkt(pktio_entry_t *pktio_entry, const void *data, { odp_packet_t pkt; odp_packet_hdr_t *pkt_hdr; + int num; - pkt = packet_alloc(pktio_entry->s.pkt_tap.pool, len, 1); + num = packet_alloc_multi(pktio_entry->s.pkt_tap.pool, len, &pkt, 1); - if (pkt == ODP_PACKET_INVALID) - return pkt; + if (num != 1) + return ODP_PACKET_INVALID; if (odp_packet_copy_from_mem(pkt, 0, len, data) < 0) { ODP_ERR("failed to copy packet data\n"); -- 2.7.4
