On Wed, 11 Jan 2017 08:17:59 -0800, Stephen Hemminger <step...@networkplumber.org> wrote: > On Fri, 30 Dec 2016 04:50:16 +0700 > Sergey Vyazmitinov <s.vyazmiti...@brain4net.com> wrote: > > > /** > > + * Free n packets mbuf back into its original mempool. > > + * > > + * Free each mbuf, and all its segments in case of chained > > buffers. Each > > + * segment is added back into its original mempool. > > + * > > + * @param mp > > + * The packets mempool. > > + * @param mbufs > > + * The packets mbufs array to be freed. > > + * @param n > > + * Number of packets. > > + */ > > +static inline void rte_pktmbuf_free_bulk(struct rte_mempool *mp, > > + struct rte_mbuf **mbufs, unsigned n) > > +{ > > + struct rte_mbuf *mbuf, *m_next; > > + unsigned i; > > + for (i = 0; i < n; ++i) { > > + mbuf = mbufs[i]; > > + __rte_mbuf_sanity_check(mbuf, 1); > > + > > + mbuf = mbuf->next; > > + while (mbuf != NULL) { > > + m_next = mbuf->next; > > + rte_pktmbuf_free_seg(mbuf); > > + mbuf = m_next; > > + } > > + } > > + rte_mempool_put_bulk(mp, (void * const *)mbufs, n); > > +} > > The mbufs may come from different pools. You need to handle that.
I have an implementation for that in an endless-work-in-progress patchset: /** + * Free several mbufs segments. + * + * This function frees a table of mbufs, ensuring that each mbuf is + * returned into its original pool. It is the equivalent of calling + * rte_pktmbuf_free_seg() on all mbuf of the table. + * + * @param mbufs + * Array of mbuf pointers. + * @param n + * Array size. + */ +static inline void +rte_pktmbuf_free_seg_bulk(struct rte_mbuf * const *m_tab, unsigned n) +{ + struct rte_mbuf *m; + struct rte_mbuf * const *start = NULL; + unsigned n_free = 0, i; + struct rte_mempool *free_pool = NULL; + + for (i = 0; i < n; i++) { + m = m_tab[i]; + + if (__rte_pktmbuf_prefree_seg(m) == NULL) { + if (n_free != 0) + rte_mempool_put_bulk(free_pool, + (void * const *)start, n_free); + + free_pool = NULL; + n_free = 0; + continue; + } + + if (unlikely(m->pool != free_pool)) { + if (n_free != 0) + rte_mempool_put_bulk(free_pool, + (void * const *)start, n_free); + + free_pool = m->pool; + start = &m_tab[i]; + n_free = 1; + } else { + n_free++; + } + } + + if (n_free != 0) + rte_mempool_put_bulk(free_pool, + (void * const *)start, n_free); +} In the same patch, I also remove the tx_free_bulk_mbuf() functions that does almost the same job in specific drivers. Unfortunately, this patch needs to be rebased and better tested, so it's not ready yet. Regards, Olivier