> From: Huichao Cai [mailto:chcch...@163.com] > Sent: Friday, 22 July 2022 15.02 > To: dev@dpdk.org > Cc: konstantin.v.anan...@yandex.ru > Subject: [PATCH v3] ip_frag: add IPv4 fragment copy packet API > > Some NIC drivers support MBUF_FAST_FREE(Device supports optimization > for fast release of mbufs. When set application must guarantee that > per-queue all mbufs comes from the same mempool and has refcnt = 1) > offload. In order to adapt to this offload function, add this API. > Add some test data for this API. > > Signed-off-by: Huichao Cai <chcch...@163.com> > --- > app/test/test_ipfrag.c | 8 +- > lib/ip_frag/rte_ip_frag.h | 27 +++++ > lib/ip_frag/rte_ipv4_fragmentation.c | 208 > +++++++++++++++++++++++++++++++++++ > lib/ip_frag/version.map | 1 + > 4 files changed, 243 insertions(+), 1 deletion(-) > > diff --git a/app/test/test_ipfrag.c b/app/test/test_ipfrag.c > index ba0ffd0..bb7c4d3 100644 > --- a/app/test/test_ipfrag.c > +++ b/app/test/test_ipfrag.c > @@ -418,10 +418,16 @@ static void ut_teardown(void) > } > > if (tests[i].ipv == 4) > - len = rte_ipv4_fragment_packet(b, pkts_out, BURST, > + if (i % 2) > + len = rte_ipv4_fragment_packet(b, pkts_out, > BURST, > tests[i].mtu_size, > direct_pool, > indirect_pool); > + else > + len = rte_ipv4_fragment_copy_packet(b, > pkts_out, > + BURST, > + tests[i].mtu_size, > + pkt_pool); > else if (tests[i].ipv == 6) > len = rte_ipv6_fragment_packet(b, pkts_out, BURST, > tests[i].mtu_size, > diff --git a/lib/ip_frag/rte_ip_frag.h b/lib/ip_frag/rte_ip_frag.h > index 7d2abe1..c2a7e1e 100644 > --- a/lib/ip_frag/rte_ip_frag.h > +++ b/lib/ip_frag/rte_ip_frag.h > @@ -179,6 +179,33 @@ int32_t rte_ipv4_fragment_packet(struct rte_mbuf > *pkt_in, > struct rte_mempool *pool_indirect); > > /** > + * IPv4 fragmentation by copy. > + * > + * This function implements the fragmentation of IPv4 packets by copy. > + * > + * @param pkt_in > + * The input packet. > + * @param pkts_out > + * Array storing the output fragments. > + * @param mtu_size > + * Size in bytes of the Maximum Transfer Unit (MTU) for the outgoing > IPv4 > + * datagrams. This value includes the size of the IPv4 header. > + * @param pool_direct > + * MBUF pool used for allocating direct buffers for the output > fragments. > + * @return > + * Upon successful completion - number of output fragments placed > + * in the pkts_out array. > + * Otherwise - (-1) * errno. > + */ > +__rte_experimental > +int32_t > +rte_ipv4_fragment_copy_packet(struct rte_mbuf *pkt_in, > + struct rte_mbuf **pkts_out, > + uint16_t nb_pkts_out, > + uint16_t mtu_size, > + struct rte_mempool *pool_direct); > + > +/** > * This function implements reassembly of fragmented IPv4 packets. > * Incoming mbufs should have its l2_len/l3_len fields setup > correctly. > * > diff --git a/lib/ip_frag/rte_ipv4_fragmentation.c > b/lib/ip_frag/rte_ipv4_fragmentation.c > index 27a8ad2..cb15781 100644 > --- a/lib/ip_frag/rte_ipv4_fragmentation.c > +++ b/lib/ip_frag/rte_ipv4_fragmentation.c > @@ -83,6 +83,48 @@ static inline uint16_t > __create_ipopt_frag_hdr(uint8_t *iph, > return ipopt_len; > } > > +static struct rte_mbuf * > +__copy_to_pktmbuf(char *src, struct rte_mbuf *m_head, > + struct rte_mbuf *m_tail, struct rte_mempool *mp, uint32_t len) > +{ > + struct rte_mbuf *m_last, **prev; > + > + m_last = m_tail; > + prev = &m_last->next; > + while (len > 0) { > + uint32_t copy_len; > + > + /* current buffer is full, chain a new one */ > + if (unlikely(rte_pktmbuf_tailroom(m_last) == 0)) { > + m_last = rte_pktmbuf_alloc(mp); > + if (unlikely(m_last == NULL)) > + return NULL; > + > + ++m_head->nb_segs; > + *prev = m_last; > + prev = &m_last->next; > + }
I think that MBUF_FAST_FREE also requires non-segmented packets, although this requirement is missing in the documentation. I have asked Olivier (as MBUF maintainer) to confirm this requirement [1]. [1] http://inbox.dpdk.org/dev/98cbd80474fa8b44bf855df32c47dc35d87...@smartserver.smartshare.dk/ > + > + /* > + * copy the min of data in len > + * vs space available in output (m_last) > + */ > + copy_len = RTE_MIN(rte_pktmbuf_tailroom(m_last), len); > + > + /* append from seg to m_last */ > + memcpy(rte_pktmbuf_mtod_offset(m_last, char *, m_last- > >data_len), > + src, copy_len); > + > + /* update offsets and lengths */ > + m_last->data_len += copy_len; > + m_head->pkt_len += copy_len; > + src += copy_len; > + len -= copy_len; > + } > + > + return m_last; > +} > + > /** > * IPv4 fragmentation. > *