https://www.yuque.com/zzqcn/opensource/oirzxh
m = rte_pktmbuf_alloc(mpool); rte_pktmbuf_append(m, 1000); mbuf_dump(m); m2 = rte_pktmbuf_alloc(mpool); rte_pktmbuf_append(m2, 500); mbuf_dump(m2); rte_pktmbuf_chain(m, m2); printf("after m rte_pktmbuf_chain "); mbuf_dump(m);
RTE_PKTMBUF_HEADROOM: 128 sizeof(mbuf): 128 m: 0x13f919c00 m->refcnt: 1 m->buf_addr: 0x13f919c90 m->data_off: 128 m->buf_len: 1646 m->pkt_len: 1000 m->data_len: 1000 m->nb_segs: 1 m->next: (nil) m->buf_addr+m->data_off: 0x13f919d10 rte_pktmbuf_mtod(m): 0x13f919d10 rte_pktmbuf_data_len(m): 1000 rte_pktmbuf_pkt_len(m): 1000 rte_pktmbuf_headroom(m): 128 rte_pktmbuf_tailroom(m): 518 rte_pktmbuf_data_room_size(mpool): 1646 rte_pktmbuf_priv_size(mpool): 16 RTE_PKTMBUF_HEADROOM: 128 sizeof(mbuf): 128 m: 0x13f919480 m->refcnt: 1 m->buf_addr: 0x13f919510 m->data_off: 128 m->buf_len: 1646 m->pkt_len: 500 m->data_len: 500 m->nb_segs: 1 m->next: (nil) m->buf_addr+m->data_off: 0x13f919590 rte_pktmbuf_mtod(m): 0x13f919590 rte_pktmbuf_data_len(m): 500 rte_pktmbuf_pkt_len(m): 500 rte_pktmbuf_headroom(m): 128 rte_pktmbuf_tailroom(m): 1018 rte_pktmbuf_data_room_size(mpool): 1646 rte_pktmbuf_priv_size(mpool): 16 ================== after m rte_pktmbuf_chain ===================== RTE_PKTMBUF_HEADROOM: 128 sizeof(mbuf): 128 m: 0x13f919c00 m->refcnt: 1 m->buf_addr: 0x13f919c90 m->data_off: 128 m->buf_len: 1646 m->pkt_len: 1500 m->data_len: 1000 m->nb_segs: 2 m->next: 0x13f919480 m->buf_addr+m->data_off: 0x13f919d10 rte_pktmbuf_mtod(m): 0x13f919d10 rte_pktmbuf_data_len(m): 1000 rte_pktmbuf_pkt_len(m): 1500 rte_pktmbuf_headroom(m): 128 rte_pktmbuf_tailroom(m): 518 rte_pktmbuf_data_room_size(mpool): 1646 rte_pktmbuf_priv_size(mpool): 16
rte_pktmbuf_clone(struct rte_mbuf *md, struct rte_mempool *mp) { struct rte_mbuf *mc, *mi, **prev; uint32_t pktlen; uint16_t nseg; mc = rte_pktmbuf_alloc(mp); if (unlikely(mc == NULL)) return NULL; mi = mc; prev = &mi->next; pktlen = md->pkt_len; nseg = 0; do { nseg++; rte_pktmbuf_attach(mi, md); *prev = mi; prev = &mi->next; } while ((md = md->next) != NULL && (mi = rte_pktmbuf_alloc(mp)) != NULL); *prev = NULL; mc->nb_segs = nseg; mc->pkt_len = pktlen; /* Allocation of new indirect segment failed */ if (unlikely(mi == NULL)) { rte_pktmbuf_free(mc); } __rte_mbuf_sanity_check(mc, 1); return mc; }
static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m) { RTE_ASSERT(RTE_MBUF_DIRECT(mi) && rte_mbuf_refcnt_read(mi) == 1); if (RTE_MBUF_HAS_EXTBUF(m)) { rte_mbuf_ext_refcnt_update(m->shinfo, 1); mi->ol_flags = m->ol_flags; mi->shinfo = m->shinfo; } else { /* if m is not direct, get the mbuf that embeds the data */ rte_mbuf_refcnt_update(rte_mbuf_from_indirect(m), 1); mi->priv_size = m->priv_size; mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF; } __rte_pktmbuf_copy_hdr(mi, m); mi->data_off = m->data_off; mi->data_len = m->data_len; mi->buf_iova = m->buf_iova; mi->buf_addr = m->buf_addr; mi->buf_len = m->buf_len; mi->next = NULL; mi->pkt_len = mi->data_len; mi->nb_segs = 1; __rte_mbuf_sanity_check(mi, 1); __rte_mbuf_sanity_check(m, 0); }
m = rte_pktmbuf_alloc(mpool); rte_pktmbuf_append(m, 1000); mbuf_dump(m); printf("================== after m rte_pktmbuf_clone===================== "); m2 = rte_pktmbuf_clone(m, mpool); mbuf_dump(m2); m3 = rte_pktmbuf_clone(m, mpool); printf("================== after m rte_pktmbuf_clone===================== "); mbuf_dump(m3);
RTE_PKTMBUF_HEADROOM: 128 sizeof(mbuf): 128 m: 0x13f919480 m->refcnt: 1 m->buf_addr: 0x13f919510 m->data_off: 128 m->buf_len: 1646 m->pkt_len: 1000 m->data_len: 1000 m->nb_segs: 1 m->next: (nil) m->buf_addr+m->data_off: 0x13f919590 rte_pktmbuf_mtod(m): 0x13f919590 rte_pktmbuf_data_len(m): 1000 rte_pktmbuf_pkt_len(m): 1000 rte_pktmbuf_headroom(m): 128 rte_pktmbuf_tailroom(m): 518 rte_pktmbuf_data_room_size(mpool): 1646 rte_pktmbuf_priv_size(mpool): 16 ================== after m rte_pktmbuf_clone===================== RTE_PKTMBUF_HEADROOM: 128 sizeof(mbuf): 128 m: 0x13f919c00 m->refcnt: 1 m->buf_addr: 0x13f919510 ---同m1 m->data_off: 128 m->buf_len: 1646 m->pkt_len: 1000 m->data_len: 1000 m->nb_segs: 1 m->next: (nil) m->buf_addr+m->data_off: 0x13f919590 rte_pktmbuf_mtod(m): 0x13f919590 rte_pktmbuf_data_len(m): 1000 rte_pktmbuf_pkt_len(m): 1000 rte_pktmbuf_headroom(m): 128 rte_pktmbuf_tailroom(m): 518 rte_pktmbuf_data_room_size(mpool): 1646 rte_pktmbuf_priv_size(mpool): 16 ================== after m rte_pktmbuf_clone===================== RTE_PKTMBUF_HEADROOM: 128 sizeof(mbuf): 128 m: 0x13f918d00 m->refcnt: 1 m->buf_addr: 0x13f919510 ---同m1 m->data_off: 128 m->buf_len: 1646 m->pkt_len: 1000 m->data_len: 1000 m->nb_segs: 1 m->next: (nil) m->buf_addr+m->data_off: 0x13f919590 rte_pktmbuf_mtod(m): 0x13f919590 rte_pktmbuf_data_len(m): 1000 rte_pktmbuf_pkt_len(m): 1000 rte_pktmbuf_headroom(m): 128 rte_pktmbuf_tailroom(m): 518 rte_pktmbuf_data_room_size(mpool): 1646 rte_pktmbuf_priv_size(mpool): 16
printf("mempool count before free: %u ", rte_mempool_avail_count(mpool)); printf("m->refcnt: %u ", m->refcnt); rte_pktmbuf_free(m); printf("mempool count after free: %u ", rte_mempool_avail_count(mpool)); printf("m->refcnt: %u ", m->refcnt); rte_pktmbuf_free(m3); printf("mempool count after free: %u ", rte_mempool_avail_count(mpool)); printf("m->refcnt: %u ", m->refcnt); rte_pktmbuf_free(m2); printf("mempool count after free: %u ", rte_mempool_avail_count(mpool)); printf("m->refcnt: %u ", m->refcnt); rte_pktmbuf_free(m); printf("mempool count after free: %u ", rte_mempool_avail_count(mpool)); printf("m->refcnt: %u ", m->refcnt);
mempool count before free: 1020 m->refcnt: 3 mempool count after free: 1020 m->refcnt: 2 //free(m) mempool count after free: 1021 m->refcnt: 1 // free(m3) mempool count after free: 1023 m->refcnt: 1 //free(m2) mempool count after free: 1023 m->refcnt: 1 //free(m)
rte_pktmbuf_free
回收mbuf或mbuf chain, 可以处理引用计数等内部细节rte_pktmbuf_free_seg
回收单个mbuf, 但不处理mbuf chain. 可以处理引用计数等内部细节
static inline void rte_pktmbuf_free(struct rte_mbuf *m) { struct rte_mbuf *m_next; if (m != NULL) __rte_mbuf_sanity_check(m, 1); while (m != NULL) { m_next = m->next; rte_pktmbuf_free_seg(m); m = m_next; } }
static __rte_always_inline void rte_pktmbuf_free_seg(struct rte_mbuf *m) { m = rte_pktmbuf_prefree_seg(m); if (likely(m != NULL)) rte_mbuf_raw_free(m); }
static __rte_always_inline struct rte_mbuf * rte_pktmbuf_prefree_seg(struct rte_mbuf *m) { __rte_mbuf_sanity_check(m, 0); if (likely(rte_mbuf_refcnt_read(m) == 1)) { if (!RTE_MBUF_DIRECT(m)) rte_pktmbuf_detach(m); if (m->next != NULL) { m->next = NULL; m->nb_segs = 1; } return m; } else if (__rte_mbuf_refcnt_update(m, -1) == 0) { if (!RTE_MBUF_DIRECT(m)) rte_pktmbuf_detach(m); if (m->next != NULL) { m->next = NULL; m->nb_segs = 1; } rte_mbuf_refcnt_set(m, 1); return m; } return NULL; }
/* internal */ static inline uint16_t __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) { m->refcnt = (uint16_t)(m->refcnt + value); return m->refcnt; }
/** * Returns TRUE if given mbuf is direct, or FALSE otherwise. * * If a mbuf embeds its own data after the rte_mbuf structure, this mbuf * can be defined as a direct mbuf. */ #define RTE_MBUF_DIRECT(mb) (!((mb)->ol_flags & (IND_ATTACHED_MBUF | EXT_ATTACHED_MBUF)))
static __rte_always_inline void rte_mbuf_raw_free(struct rte_mbuf *m) { RTE_ASSERT(RTE_MBUF_DIRECT(m)); RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); RTE_ASSERT(m->next == NULL); RTE_ASSERT(m->nb_segs == 1); __rte_mbuf_sanity_check(m, 0); rte_mempool_put(m->pool, m); }