> > On Mon, Apr 23, 2018 at 11:53:04AM +0000, Ananyev, Konstantin wrote: > [...] > > > @@ -693,9 +711,14 @@ rte_mbuf_to_baddr(struct rte_mbuf *md) > > > #define RTE_MBUF_INDIRECT(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF) > > > > > > /** > > > + * Returns TRUE if given mbuf has external buffer, or FALSE otherwise. > > > + */ > > > +#define RTE_MBUF_HAS_EXTBUF(mb) ((mb)->ol_flags & EXT_ATTACHED_MBUF) > > > + > > > +/** > > > * Returns TRUE if given mbuf is direct, or FALSE otherwise. > > > */ > > > -#define RTE_MBUF_DIRECT(mb) (!RTE_MBUF_INDIRECT(mb)) > > > +#define RTE_MBUF_DIRECT(mb) (!RTE_MBUF_INDIRECT(mb) && > > > !RTE_MBUF_HAS_EXTBUF(mb)) > > > > As a nit: > > RTE_MBUF_DIRECT(mb) (((mb)->ol_flags & (IND_ATTACHED_MBUF | > > EXT_ATTACHED_MBUF)) == 0) > > It was for better readability and I expected compiler did the same. > But, if you still want this way, I can change it.
I know compilers are quite smart these days, but you never know for sure, so yes, I think better to do that explicitly. > > [...] > > > /** > > > - * Detach an indirect packet mbuf. > > > + * @internal used by rte_pktmbuf_detach(). > > > + * > > > + * Decrement the reference counter of the external buffer. When the > > > + * reference counter becomes 0, the buffer is freed by pre-registered > > > + * callback. > > > + */ > > > +static inline void > > > +__rte_pktmbuf_free_extbuf(struct rte_mbuf *m) > > > +{ > > > + struct rte_mbuf_ext_shared_info *shinfo; > > > + > > > + RTE_ASSERT(RTE_MBUF_HAS_EXTBUF(m)); > > > + > > > + shinfo = rte_mbuf_ext_shinfo(m); > > > + > > > + if (rte_extbuf_refcnt_update(shinfo, -1) == 0) > > > + shinfo->free_cb(m->buf_addr, shinfo->fcb_opaque); > > > > > > I understand the reason but extra function call for each external mbuf - > > seems quite expensive. > > Wonder is it possible to group them somehow and amortize the cost? > > Good point. I thought about it today. > > Comparing to the regular mbuf, maybe three differences. a) free function isn't > inlined but a real branch. b) no help from core local cache like mempool's c) > no > free_bulk func like rte_mempool_put_bulk(). But these look quite costly and > complicated for the external buffer attachment. > > For example, to free it in bulk, external buffers should be grouped as the > buffers would have different callback functions. To do that, I have to make an > API to pre-register an external buffer group to prepare resources for the bulk > free. Then, buffers can't be anonymous anymore but have to be registered in > advance. If so, it would be better to use existing APIs, especially when a > user > wants high throughput... > > Let me know if you have better idea to implement it. Then, I'll gladly take > that. Or, we can push any improvement patch in the next releases. I don't have any extra-smart thoughts here. One option I thought about - was to introduce group of external buffers with common free routine (I think o mentioned it already). Second - hide all that external buffer management inside mempool, i.e. if user wants to use external buffers he create a mempool (with rte_mbuf_ext_shared_info as elements?), then attach external buffer to shinfo and call mbuf_attach_external(mbuf, shinfo). Though for free we can just call mempool_put(shinfo) and let particular implementation decide when/how call free_cb(), etc. Konstantin