get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/120445/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 120445,
    "url": "http://patches.dpdk.org/api/patches/120445/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20221204125458.32620-1-mb@smartsharesystems.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20221204125458.32620-1-mb@smartsharesystems.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20221204125458.32620-1-mb@smartsharesystems.com",
    "date": "2022-12-04T12:54:58",
    "name": "[v5] mbuf perf test, please ignore",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": true,
    "hash": "f6fc3e8a39db973dc6fa8dfe739cc9d410617bad",
    "submitter": {
        "id": 591,
        "url": "http://patches.dpdk.org/api/people/591/?format=api",
        "name": "Morten Brørup",
        "email": "mb@smartsharesystems.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20221204125458.32620-1-mb@smartsharesystems.com/mbox/",
    "series": [
        {
            "id": 25992,
            "url": "http://patches.dpdk.org/api/series/25992/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=25992",
            "date": "2022-12-04T12:54:58",
            "name": "[v5] mbuf perf test, please ignore",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/25992/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/120445/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/120445/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id D24D6A04FD;\n\tSun,  4 Dec 2022 13:55:01 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 78CD54068E;\n\tSun,  4 Dec 2022 13:55:01 +0100 (CET)",
            "from smartserver.smartsharesystems.com\n (smartserver.smartsharesystems.com [77.243.40.215])\n by mails.dpdk.org (Postfix) with ESMTP id 7007040042\n for <dev@dpdk.org>; Sun,  4 Dec 2022 13:55:00 +0100 (CET)",
            "from dkrd2.smartsharesys.local ([192.168.4.12]) by\n smartserver.smartsharesystems.com with Microsoft SMTPSVC(6.0.3790.4675);\n Sun, 4 Dec 2022 13:54:59 +0100"
        ],
        "From": "=?utf-8?q?Morten_Br=C3=B8rup?= <mb@smartsharesystems.com>",
        "To": "dev@dpdk.org",
        "Cc": "=?utf-8?q?Morten_Br=C3=B8rup?= <mb@smartsharesystems.com>",
        "Subject": "[PATCH v5] mbuf perf test, please ignore",
        "Date": "Sun,  4 Dec 2022 13:54:58 +0100",
        "Message-Id": "<20221204125458.32620-1-mb@smartsharesystems.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "\n <98CBD80474FA8B44BF855DF32C47DC35D8754C@smartserver.smartshare.dk>",
        "References": "<98CBD80474FA8B44BF855DF32C47DC35D8754C@smartserver.smartshare.dk>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "X-OriginalArrivalTime": "04 Dec 2022 12:54:59.0820 (UTC)\n FILETIME=[9E3F72C0:01D907DF]",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Playing around with the mbuf structure, trying to reduce the use of the\nsecond cache line in some common scenarios.\n\nv5:\n* Fix rte_pktmbuf_chain() for the case where the head is a single segment.\nv4:\n* Use tabs, not spaces.\n* Fix copy-paste bug in linearize.\nv3:\n* Make 'next' depend on 'nb_segs' > 1.\n* Implement new interpretation of 'nb_segs' in i40e PMD.\nv2:\n* Remove BUILD_BUG_ON in cnxk PMD.\n\nSigned-off-by: Morten Brørup <mb@smartsharesystems.com>\n---\n drivers/net/cnxk/cn10k_ethdev.c          |  2 ++\n drivers/net/cnxk/cn9k_ethdev.c           |  2 ++\n drivers/net/i40e/i40e_rxtx.c             |  9 ++++--\n drivers/net/i40e/i40e_rxtx_vec_altivec.c |  4 +++\n drivers/net/i40e/i40e_rxtx_vec_common.h  |  2 ++\n drivers/net/i40e/i40e_rxtx_vec_neon.c    |  4 +++\n lib/mbuf/rte_mbuf.c                      | 39 +++++++++++++-----------\n lib/mbuf/rte_mbuf.h                      | 24 ++++++++-------\n lib/mbuf/rte_mbuf_core.h                 | 38 +++++++++++------------\n 9 files changed, 73 insertions(+), 51 deletions(-)",
    "diff": "diff --git a/drivers/net/cnxk/cn10k_ethdev.c b/drivers/net/cnxk/cn10k_ethdev.c\nindex 4658713591..9f6086efe6 100644\n--- a/drivers/net/cnxk/cn10k_ethdev.c\n+++ b/drivers/net/cnxk/cn10k_ethdev.c\n@@ -72,8 +72,10 @@ nix_tx_offload_flags(struct rte_eth_dev *eth_dev)\n \t\t\t offsetof(struct rte_mbuf, buf_addr) + 24);\n \tRTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pkt_len) !=\n \t\t\t offsetof(struct rte_mbuf, ol_flags) + 12);\n+/*\n \tRTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, tx_offload) !=\n \t\t\t offsetof(struct rte_mbuf, pool) + 2 * sizeof(void *));\n+*/\n \n \tif (conf & RTE_ETH_TX_OFFLOAD_VLAN_INSERT ||\n \t    conf & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)\ndiff --git a/drivers/net/cnxk/cn9k_ethdev.c b/drivers/net/cnxk/cn9k_ethdev.c\nindex 3b702d9696..3e9161ca79 100644\n--- a/drivers/net/cnxk/cn9k_ethdev.c\n+++ b/drivers/net/cnxk/cn9k_ethdev.c\n@@ -72,8 +72,10 @@ nix_tx_offload_flags(struct rte_eth_dev *eth_dev)\n \t\t\t offsetof(struct rte_mbuf, buf_addr) + 24);\n \tRTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pkt_len) !=\n \t\t\t offsetof(struct rte_mbuf, ol_flags) + 12);\n+/*\n \tRTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, tx_offload) !=\n \t\t\t offsetof(struct rte_mbuf, pool) + 2 * sizeof(void *));\n+*/\n \n \tif (conf & RTE_ETH_TX_OFFLOAD_VLAN_INSERT ||\n \t    conf & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)\ndiff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c\nindex 788ffb51c2..a08afe0a13 100644\n--- a/drivers/net/i40e/i40e_rxtx.c\n+++ b/drivers/net/i40e/i40e_rxtx.c\n@@ -920,8 +920,9 @@ i40e_recv_scattered_pkts(void *rx_queue,\n \t\t\tfirst_seg->pkt_len =\n \t\t\t\t(uint16_t)(first_seg->pkt_len +\n \t\t\t\t\t\trx_packet_len);\n-\t\t\tfirst_seg->nb_segs++;\n+\t\t\tlast_seg->nb_segs = 2;\n \t\t\tlast_seg->next = rxm;\n+\t\t\tfirst_seg->nb_segs++;\n \t\t}\n \n \t\t/**\n@@ -944,6 +945,7 @@ i40e_recv_scattered_pkts(void *rx_queue,\n \t\t *  the length of that CRC part from the data length of the\n \t\t *  previous mbuf.\n \t\t */\n+\t\trxm->nb_segs = 1;\n \t\trxm->next = NULL;\n \t\tif (unlikely(rxq->crc_len > 0)) {\n \t\t\tfirst_seg->pkt_len -= RTE_ETHER_CRC_LEN;\n@@ -953,6 +955,7 @@ i40e_recv_scattered_pkts(void *rx_queue,\n \t\t\t\tlast_seg->data_len =\n \t\t\t\t\t(uint16_t)(last_seg->data_len -\n \t\t\t\t\t(RTE_ETHER_CRC_LEN - rx_packet_len));\n+\t\t\t\tlast_seg->nb_segs = 1;\n \t\t\t\tlast_seg->next = NULL;\n \t\t\t} else\n \t\t\t\trxm->data_len = (uint16_t)(rx_packet_len -\n@@ -1065,7 +1068,7 @@ i40e_calc_pkt_desc(struct rte_mbuf *tx_pkt)\n \n \twhile (txd != NULL) {\n \t\tcount += DIV_ROUND_UP(txd->data_len, I40E_MAX_DATA_PER_TXD);\n-\t\ttxd = txd->next;\n+\t\ttxd = (txd->nb_segs == 1) ? NULL : txd->next;\n \t}\n \n \treturn count;\n@@ -1282,7 +1285,7 @@ i40e_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n \t\t\ttxe->last_id = tx_last;\n \t\t\ttx_id = txe->next_id;\n \t\t\ttxe = txn;\n-\t\t\tm_seg = m_seg->next;\n+\t\t\tm_seg = (m_seg->nb_segs == 1) ? NULL : m_seg->next;\n \t\t} while (m_seg != NULL);\n \n \t\t/* The last packet data descriptor needs End Of Packet (EOP) */\ndiff --git a/drivers/net/i40e/i40e_rxtx_vec_altivec.c b/drivers/net/i40e/i40e_rxtx_vec_altivec.c\nindex 2dfa04599c..ad91b5cb60 100644\n--- a/drivers/net/i40e/i40e_rxtx_vec_altivec.c\n+++ b/drivers/net/i40e/i40e_rxtx_vec_altivec.c\n@@ -410,6 +410,10 @@ _recv_raw_pkts_vec(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_pkts,\n \t\t\tsplit_packet += RTE_I40E_DESCS_PER_LOOP;\n \n \t\t\t/* zero-out next pointers */\n+\t\t\trx_pkts[pos]->nb_segs = 1;\n+\t\t\trx_pkts[pos + 1]->nb_segs = 1;\n+\t\t\trx_pkts[pos + 2]->nb_segs = 1;\n+\t\t\trx_pkts[pos + 3]->nb_segs = 1;\n \t\t\trx_pkts[pos]->next = NULL;\n \t\t\trx_pkts[pos + 1]->next = NULL;\n \t\t\trx_pkts[pos + 2]->next = NULL;\ndiff --git a/drivers/net/i40e/i40e_rxtx_vec_common.h b/drivers/net/i40e/i40e_rxtx_vec_common.h\nindex fe1a6ec75e..d5799f5242 100644\n--- a/drivers/net/i40e/i40e_rxtx_vec_common.h\n+++ b/drivers/net/i40e/i40e_rxtx_vec_common.h\n@@ -27,6 +27,7 @@ reassemble_packets(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_bufs,\n \tfor (buf_idx = 0, pkt_idx = 0; buf_idx < nb_bufs; buf_idx++) {\n \t\tif (end != NULL) {\n \t\t\t/* processing a split packet */\n+\t\t\tend->nb_segs = 2;\n \t\t\tend->next = rx_bufs[buf_idx];\n \t\t\trx_bufs[buf_idx]->data_len += rxq->crc_len;\n \n@@ -52,6 +53,7 @@ reassemble_packets(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_bufs,\n \t\t\t\t\t\tsecondlast = secondlast->next;\n \t\t\t\t\tsecondlast->data_len -= (rxq->crc_len -\n \t\t\t\t\t\t\tend->data_len);\n+\t\t\t\t\tsecondlast->nb_segs = 1;\n \t\t\t\t\tsecondlast->next = NULL;\n \t\t\t\t\trte_pktmbuf_free_seg(end);\n \t\t\t\t}\ndiff --git a/drivers/net/i40e/i40e_rxtx_vec_neon.c b/drivers/net/i40e/i40e_rxtx_vec_neon.c\nindex 12e6f1cbcb..3199b0f8cf 100644\n--- a/drivers/net/i40e/i40e_rxtx_vec_neon.c\n+++ b/drivers/net/i40e/i40e_rxtx_vec_neon.c\n@@ -541,6 +541,10 @@ _recv_raw_pkts_vec(struct i40e_rx_queue *__rte_restrict rxq,\n \t\t\tsplit_packet += RTE_I40E_DESCS_PER_LOOP;\n \n \t\t\t/* zero-out next pointers */\n+\t\t\trx_pkts[pos]->nb_segs = 1;\n+\t\t\trx_pkts[pos + 1]->nb_segs = 1;\n+\t\t\trx_pkts[pos + 2]->nb_segs = 1;\n+\t\t\trx_pkts[pos + 3]->nb_segs = 1;\n \t\t\trx_pkts[pos]->next = NULL;\n \t\t\trx_pkts[pos + 1]->next = NULL;\n \t\t\trx_pkts[pos + 2]->next = NULL;\ndiff --git a/lib/mbuf/rte_mbuf.c b/lib/mbuf/rte_mbuf.c\nindex cfd8062f1e..6a8153b443 100644\n--- a/lib/mbuf/rte_mbuf.c\n+++ b/lib/mbuf/rte_mbuf.c\n@@ -123,10 +123,10 @@ rte_pktmbuf_free_pinned_extmem(void *addr, void *opaque)\n \n \trte_mbuf_ext_refcnt_set(m->shinfo, 1);\n \tm->ol_flags = RTE_MBUF_F_EXTERNAL;\n-\tif (m->next != NULL)\n-\t\tm->next = NULL;\n-\tif (m->nb_segs != 1)\n+\tif (m->nb_segs != 1) {\n \t\tm->nb_segs = 1;\n+\t\tm->next = NULL;\n+\t}\n \trte_mbuf_raw_free(m);\n }\n \n@@ -427,7 +427,7 @@ int rte_mbuf_check(const struct rte_mbuf *m, int is_header,\n \t\t}\n \t\tnb_segs -= 1;\n \t\tpkt_len -= m->data_len;\n-\t} while ((m = m->next) != NULL);\n+\t} while ((m = ((m->nb_segs == 1) ? NULL : m->next)) != NULL);\n \n \tif (nb_segs) {\n \t\t*reason = \"bad nb_segs\";\n@@ -495,7 +495,7 @@ void rte_pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int count)\n \t\t__rte_mbuf_sanity_check(m, 1);\n \n \t\tdo {\n-\t\t\tm_next = m->next;\n+\t\t\tm_next = (m->nb_segs == 1) ? NULL : m->next;\n \t\t\t__rte_pktmbuf_free_seg_via_array(m,\n \t\t\t\t\tpending, &nb_pending,\n \t\t\t\t\tRTE_PKTMBUF_FREE_PENDING_SZ);\n@@ -511,7 +511,7 @@ void rte_pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int count)\n struct rte_mbuf *\n rte_pktmbuf_clone(struct rte_mbuf *md, struct rte_mempool *mp)\n {\n-\tstruct rte_mbuf *mc, *mi, **prev;\n+\tstruct rte_mbuf *mc, *mi, *prev;\n \tuint32_t pktlen;\n \tuint16_t nseg;\n \n@@ -520,19 +520,21 @@ rte_pktmbuf_clone(struct rte_mbuf *md, struct rte_mempool *mp)\n \t\treturn NULL;\n \n \tmi = mc;\n-\tprev = &mi->next;\n+\tprev = mi;\n \tpktlen = md->pkt_len;\n \tnseg = 0;\n \n \tdo {\n \t\tnseg++;\n \t\trte_pktmbuf_attach(mi, md);\n-\t\t*prev = mi;\n-\t\tprev = &mi->next;\n-\t} while ((md = md->next) != NULL &&\n+\t\tprev->nb_segs = 2;\n+\t\tprev->next = mi;\n+\t\tprev = mi;\n+\t} while ((md = ((md->nb_segs == 1) ? NULL : md->next)) != NULL &&\n \t    (mi = rte_pktmbuf_alloc(mp)) != NULL);\n \n-\t*prev = NULL;\n+\tprev->nb_segs = 1;\n+\tprev->next = NULL;\n \tmc->nb_segs = nseg;\n \tmc->pkt_len = pktlen;\n \n@@ -565,9 +567,9 @@ __rte_pktmbuf_linearize(struct rte_mbuf *mbuf)\n \tmbuf->data_len = (uint16_t)(mbuf->pkt_len);\n \n \t/* Append data from next segments to the first one */\n-\tm = mbuf->next;\n+\tm = (mbuf->nb_segs == 1) ? NULL : mbuf->next;\n \twhile (m != NULL) {\n-\t\tm_next = m->next;\n+\t\tm_next = (m->nb_segs == 1) ? NULL : m->next;\n \n \t\tseg_len = rte_pktmbuf_data_len(m);\n \t\trte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len);\n@@ -589,7 +591,7 @@ rte_pktmbuf_copy(const struct rte_mbuf *m, struct rte_mempool *mp,\n \t\t uint32_t off, uint32_t len)\n {\n \tconst struct rte_mbuf *seg = m;\n-\tstruct rte_mbuf *mc, *m_last, **prev;\n+\tstruct rte_mbuf *mc, *m_last, *prev;\n \n \t/* garbage in check */\n \t__rte_mbuf_sanity_check(m, 1);\n@@ -611,7 +613,7 @@ rte_pktmbuf_copy(const struct rte_mbuf *m, struct rte_mempool *mp,\n \t/* copied mbuf is not indirect or external */\n \tmc->ol_flags = m->ol_flags & ~(RTE_MBUF_F_INDIRECT|RTE_MBUF_F_EXTERNAL);\n \n-\tprev = &mc->next;\n+\tprev = mc;\n \tm_last = mc;\n \twhile (len > 0) {\n \t\tuint32_t copy_len;\n@@ -629,9 +631,10 @@ rte_pktmbuf_copy(const struct rte_mbuf *m, struct rte_mempool *mp,\n \t\t\t\trte_pktmbuf_free(mc);\n \t\t\t\treturn NULL;\n \t\t\t}\n+\t\t\tprev->nb_segs = 2;\n+\t\t\tprev->next = m_last;\n \t\t\t++mc->nb_segs;\n-\t\t\t*prev = m_last;\n-\t\t\tprev = &m_last->next;\n+\t\t\tprev = m_last;\n \t\t}\n \n \t\t/*\n@@ -697,7 +700,7 @@ rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len)\n \t\tif (len != 0)\n \t\t\trte_hexdump(f, NULL, rte_pktmbuf_mtod(m, void *), len);\n \t\tdump_len -= len;\n-\t\tm = m->next;\n+\t\tm = (m->nb_segs == 1) ? NULL : m->next;\n \t\tnb_segs --;\n \t}\n }\ndiff --git a/lib/mbuf/rte_mbuf.h b/lib/mbuf/rte_mbuf.h\nindex 3a82eb136d..6d08c4ebfd 100644\n--- a/lib/mbuf/rte_mbuf.h\n+++ b/lib/mbuf/rte_mbuf.h\n@@ -1353,10 +1353,10 @@ rte_pktmbuf_prefree_seg(struct rte_mbuf *m)\n \t\t\t\treturn NULL;\n \t\t}\n \n-\t\tif (m->next != NULL)\n-\t\t\tm->next = NULL;\n-\t\tif (m->nb_segs != 1)\n+\t\tif (m->nb_segs != 1) {\n \t\t\tm->nb_segs = 1;\n+\t\t\tm->next = NULL;\n+\t\t}\n \n \t\treturn m;\n \n@@ -1370,10 +1370,10 @@ rte_pktmbuf_prefree_seg(struct rte_mbuf *m)\n \t\t\t\treturn NULL;\n \t\t}\n \n-\t\tif (m->next != NULL)\n-\t\t\tm->next = NULL;\n-\t\tif (m->nb_segs != 1)\n+\t\tif (m->nb_segs != 1) {\n \t\t\tm->nb_segs = 1;\n+\t\t\tm->next = NULL;\n+\t\t}\n \t\trte_mbuf_refcnt_set(m, 1);\n \n \t\treturn m;\n@@ -1415,7 +1415,7 @@ static inline void rte_pktmbuf_free(struct rte_mbuf *m)\n \t\t__rte_mbuf_sanity_check(m, 1);\n \n \twhile (m != NULL) {\n-\t\tm_next = m->next;\n+\t\tm_next = (m->nb_segs == 1) ? NULL : m->next;\n \t\trte_pktmbuf_free_seg(m);\n \t\tm = m_next;\n \t}\n@@ -1497,7 +1497,7 @@ static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v)\n \n \tdo {\n \t\trte_mbuf_refcnt_update(m, v);\n-\t} while ((m = m->next) != NULL);\n+\t} while ((m = ((m->nb_segs == 1) ? NULL : m->next)) != NULL);\n }\n \n /**\n@@ -1540,7 +1540,7 @@ static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)\n static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)\n {\n \t__rte_mbuf_sanity_check(m, 1);\n-\twhile (m->next != NULL)\n+\twhile (m->nb_segs != 1)\n \t\tm = m->next;\n \treturn m;\n }\n@@ -1758,20 +1758,22 @@ static inline const void *rte_pktmbuf_read(const struct rte_mbuf *m,\n static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail)\n {\n \tstruct rte_mbuf *cur_tail;\n+\tconst unsigned int nb_segs = head->nb_segs + tail->nb_segs;\n \n \t/* Check for number-of-segments-overflow */\n-\tif (head->nb_segs + tail->nb_segs > RTE_MBUF_MAX_NB_SEGS)\n+\tif (nb_segs > RTE_MBUF_MAX_NB_SEGS)\n \t\treturn -EOVERFLOW;\n \n \t/* Chain 'tail' onto the old tail */\n \tcur_tail = rte_pktmbuf_lastseg(head);\n+\tcur_tail->nb_segs = 2;\n \tcur_tail->next = tail;\n \n \t/* accumulate number of segments and total length.\n \t * NB: elaborating the addition like this instead of using\n \t *     -= allows us to ensure the result type is uint16_t\n \t *     avoiding compiler warnings on gcc 8.1 at least */\n-\thead->nb_segs = (uint16_t)(head->nb_segs + tail->nb_segs);\n+\thead->nb_segs = (uint16_t)nb_segs;\n \thead->pkt_len += tail->pkt_len;\n \n \t/* pkt_len is only set in the head */\ndiff --git a/lib/mbuf/rte_mbuf_core.h b/lib/mbuf/rte_mbuf_core.h\nindex a30e1e0eaf..c0c3b45024 100644\n--- a/lib/mbuf/rte_mbuf_core.h\n+++ b/lib/mbuf/rte_mbuf_core.h\n@@ -594,25 +594,6 @@ struct rte_mbuf {\n \n \tuint16_t buf_len;         /**< Length of segment buffer. */\n \n-\tstruct rte_mempool *pool; /**< Pool from which mbuf was allocated. */\n-\n-\t/* second cache line - fields only used in slow path or on TX */\n-\tRTE_MARKER cacheline1 __rte_cache_min_aligned;\n-\n-#if RTE_IOVA_AS_PA\n-\t/**\n-\t * Next segment of scattered packet. Must be NULL in the last\n-\t * segment or in case of non-segmented packet.\n-\t */\n-\tstruct rte_mbuf *next;\n-#else\n-\t/**\n-\t * Reserved for dynamic fields\n-\t * when the next pointer is in first cache line (i.e. RTE_IOVA_AS_PA is 0).\n-\t */\n-\tuint64_t dynfield2;\n-#endif\n-\n \t/* fields to support TX offloads */\n \tRTE_STD_C11\n \tunion {\n@@ -651,6 +632,25 @@ struct rte_mbuf {\n \t\t};\n \t};\n \n+\t/* second cache line - fields only used in slow path or on TX */\n+\tRTE_MARKER cacheline1 __rte_cache_min_aligned;\n+\n+#if RTE_IOVA_AS_PA\n+\t/**\n+\t * Next segment of scattered packet. Must be NULL in the last\n+\t * segment or in case of non-segmented packet.\n+\t */\n+\tstruct rte_mbuf *next;\n+#else\n+\t/**\n+\t * Reserved for dynamic fields\n+\t * when the next pointer is in first cache line (i.e. RTE_IOVA_AS_PA is 0).\n+\t */\n+\tuint64_t dynfield2;\n+#endif\n+\n+\tstruct rte_mempool *pool; /**< Pool from which mbuf was allocated. */\n+\n \t/** Shared data for external buffer attached to mbuf. See\n \t * rte_pktmbuf_attach_extbuf().\n \t */\n",
    "prefixes": [
        "v5"
    ]
}