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

Reply via email to