xref: /f-stack/lib/ff_memory.c (revision 403ae71d)
15bf882b4S10077240 /*
22317ada5Sfengbojiang  * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
35bf882b4S10077240  * All rights reserved.
45bf882b4S10077240  *
55bf882b4S10077240  * Redistribution and use in source and binary forms, with or without
65bf882b4S10077240  * modification, are permitted provided that the following conditions are met:
75bf882b4S10077240  *
85bf882b4S10077240  * 1. Redistributions of source code must retain the above copyright notice, this
95bf882b4S10077240  *   list of conditions and the following disclaimer.
105bf882b4S10077240  * 2. Redistributions in binary form must reproduce the above copyright notice,
115bf882b4S10077240  *   this list of conditions and the following disclaimer in the documentation
125bf882b4S10077240  *   and/or other materials provided with the distribution.
135bf882b4S10077240  *
145bf882b4S10077240  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
155bf882b4S10077240  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
165bf882b4S10077240  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
175bf882b4S10077240  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
185bf882b4S10077240  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
195bf882b4S10077240  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
205bf882b4S10077240  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
215bf882b4S10077240  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225bf882b4S10077240  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
235bf882b4S10077240  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245bf882b4S10077240  *
255bf882b4S10077240  */
265bf882b4S10077240 #include <assert.h>
275bf882b4S10077240 #include <unistd.h>
285bf882b4S10077240 #include <sys/mman.h>
295bf882b4S10077240 #include <errno.h>
305bf882b4S10077240 
315bf882b4S10077240 #include <rte_common.h>
325bf882b4S10077240 #include <rte_byteorder.h>
335bf882b4S10077240 #include <rte_log.h>
345bf882b4S10077240 #include <rte_memory.h>
355bf882b4S10077240 #include <rte_memcpy.h>
365bf882b4S10077240 #include <rte_memzone.h>
375bf882b4S10077240 #include <rte_config.h>
385bf882b4S10077240 #include <rte_eal.h>
395bf882b4S10077240 #include <rte_pci.h>
405bf882b4S10077240 #include <rte_mbuf.h>
415bf882b4S10077240 #include <rte_lcore.h>
425bf882b4S10077240 #include <rte_launch.h>
435bf882b4S10077240 #include <rte_ethdev.h>
445bf882b4S10077240 #include <rte_debug.h>
455bf882b4S10077240 #include <rte_ether.h>
465bf882b4S10077240 #include <rte_malloc.h>
475bf882b4S10077240 #include <rte_cycles.h>
485bf882b4S10077240 #include <rte_timer.h>
495bf882b4S10077240 #include <rte_thash.h>
505bf882b4S10077240 #include <rte_ip.h>
515bf882b4S10077240 #include <rte_tcp.h>
525bf882b4S10077240 #include <rte_udp.h>
535bf882b4S10077240 
545bf882b4S10077240 #include "ff_dpdk_if.h"
555bf882b4S10077240 #include "ff_dpdk_pcap.h"
565bf882b4S10077240 #include "ff_dpdk_kni.h"
575bf882b4S10077240 #include "ff_config.h"
585bf882b4S10077240 #include "ff_veth.h"
595bf882b4S10077240 #include "ff_host_interface.h"
605bf882b4S10077240 #include "ff_msg.h"
615bf882b4S10077240 #include "ff_api.h"
625bf882b4S10077240 #include "ff_memory.h"
635bf882b4S10077240 
645bf882b4S10077240 #define PAGE_SIZE            4096
655bf882b4S10077240 #define    PAGE_SHIFT            12
665bf882b4S10077240 #define    PAGE_MASK            (PAGE_SIZE - 1)
675bf882b4S10077240 #define    trunc_page(x)        ((x) & ~PAGE_MASK)
685bf882b4S10077240 #define    round_page(x)        (((x) + PAGE_MASK) & ~PAGE_MASK)
695bf882b4S10077240 
705bf882b4S10077240 extern struct rte_mempool *pktmbuf_pool[NB_SOCKETS];
715bf882b4S10077240 extern struct lcore_conf lcore_conf;
725bf882b4S10077240 
735bf882b4S10077240 //struct ff_tx_offload;
745bf882b4S10077240 
755bf882b4S10077240 // ff_ref_pool allocate rte_mbuf without data space, which data point to bsd mbuf's data address.
765bf882b4S10077240 static struct rte_mempool *ff_ref_pool[NB_SOCKETS];
775bf882b4S10077240 
785bf882b4S10077240 #define    Head_INC(h)    {\
795bf882b4S10077240     if ( ++h >= TX_QUEUE_SIZE ) \
805bf882b4S10077240         h = 0;\
815bf882b4S10077240     };
825bf882b4S10077240 
835bf882b4S10077240 #define    Head_DEC(h)    do{\
845bf882b4S10077240     if ( --h < 0 ) \
855bf882b4S10077240         h = TX_QUEUE_SIZE-1;\
865bf882b4S10077240     }while(0);
875bf882b4S10077240 
885bf882b4S10077240 // bsd mbuf was moved into nic_tx_ring from tmp_tables, after rte_eth_tx_burst() succeed.
895bf882b4S10077240 static struct mbuf_txring nic_tx_ring[RTE_MAX_ETHPORTS];
905bf882b4S10077240 static inline int ff_txring_enqueue(struct mbuf_txring* q, void *p, int seg_num);
915bf882b4S10077240 static inline void ff_txring_init(struct mbuf_txring* r, uint32_t len);
925bf882b4S10077240 
935bf882b4S10077240 typedef struct _list_manager_s
945bf882b4S10077240 {
955bf882b4S10077240     uint64_t    *ele;
965bf882b4S10077240     int        size;
975bf882b4S10077240     //int        FreeNum;
985bf882b4S10077240     int     top;
995bf882b4S10077240 }StackList_t;
1005bf882b4S10077240 
1015bf882b4S10077240 static StackList_t         ff_mpage_ctl = {0};
102c211a249Sfengbojiang static uint64_t             ff_page_start = (uint64_t)NULL, ff_page_end = (uint64_t)NULL;
1035bf882b4S10077240 static phys_addr_t        *ff_mpage_phy = NULL;
1045bf882b4S10077240 
1055bf882b4S10077240 static inline void        *stklist_pop(StackList_t *p);
1065bf882b4S10077240 static inline int         stklist_push(StackList_t * p, uint64_t val);
1075bf882b4S10077240 
stklist_init(StackList_t * p,int size)1085bf882b4S10077240 static int                 stklist_init(StackList_t*p, int size)
1095bf882b4S10077240 {
1106149c274Sjin.hao1 
1115bf882b4S10077240     int i = 0;
1125bf882b4S10077240 
1135bf882b4S10077240     if (p==NULL || size<=0){
1145bf882b4S10077240         return -1;
1155bf882b4S10077240     }
1165bf882b4S10077240     p->size = size;
1175bf882b4S10077240     p->top = 0;
1185bf882b4S10077240     if ( posix_memalign((void**)&p->ele, sizeof(uint64_t), sizeof(uint64_t)*size) != 0)
1195bf882b4S10077240         return -2;
1205bf882b4S10077240 
1215bf882b4S10077240     return 0;
1225bf882b4S10077240 }
1235bf882b4S10077240 
stklist_pop(StackList_t * p)1245bf882b4S10077240 static inline void *stklist_pop(StackList_t *p)
1255bf882b4S10077240 {
1265bf882b4S10077240     int head = 0;
1275bf882b4S10077240 
1285bf882b4S10077240     if (p==NULL)
1295bf882b4S10077240         return NULL;
1305bf882b4S10077240 
1315bf882b4S10077240     if (p->top > 0 ){
1325bf882b4S10077240         return (void*)p->ele[--p->top];
1335bf882b4S10077240     }
1345bf882b4S10077240     else
1355bf882b4S10077240         return NULL;
1365bf882b4S10077240 }
1375bf882b4S10077240 
1385bf882b4S10077240 //id: the id of element to be freed.
1395bf882b4S10077240 //return code: -1: faile;  >=0:OK.
stklist_push(StackList_t * p,const uint64_t val)1405bf882b4S10077240 static inline int stklist_push(StackList_t *p,  const uint64_t val){
1415bf882b4S10077240     int tail = 0;
1425bf882b4S10077240 
1435bf882b4S10077240     if (p==NULL)
1445bf882b4S10077240         return -1;
1455bf882b4S10077240     if (p->top < p->size){
1465bf882b4S10077240         p->ele[p->top++] = val;
1475bf882b4S10077240         return 0;
1485bf882b4S10077240     }
1495bf882b4S10077240     else
1505bf882b4S10077240         return -1;
1515bf882b4S10077240 }
1525bf882b4S10077240 
stklist_size(StackList_t * p)1535bf882b4S10077240 static inline int stklist_size(StackList_t * p)
1545bf882b4S10077240 {
1555bf882b4S10077240     return p->size;
1565bf882b4S10077240 }
1575bf882b4S10077240 
1585bf882b4S10077240 // set (void*) to rte_mbuf's priv_data.
ff_mbuf_set_uint64(struct rte_mbuf * p,uint64_t data)1595bf882b4S10077240 static inline int ff_mbuf_set_uint64(struct rte_mbuf* p, uint64_t data)
1605bf882b4S10077240 {
1615bf882b4S10077240     if (rte_pktmbuf_priv_size(p->pool) >= sizeof(uint64_t))
1625bf882b4S10077240         *((uint64_t*)(p+1)) = data;
1635bf882b4S10077240     return 0;
1645bf882b4S10077240 }
1655bf882b4S10077240 
1665bf882b4S10077240 /*************************
1675bf882b4S10077240 * if mbuf has num segment in all, Dev's sw_ring will use num descriptions. ff_txring also use num segments as below:
1685bf882b4S10077240 * <---     num-1          ---->|ptr| head |
1695bf882b4S10077240 * ----------------------------------------------
1705bf882b4S10077240 * | 0 | 0 | ..............| 0  | p | XXX  |
1715bf882b4S10077240 *-----------------------------------------------
1725bf882b4S10077240 *************************/
ff_txring_enqueue(struct mbuf_txring * q,void * p,int seg_num)1735bf882b4S10077240 static inline int ff_txring_enqueue(struct mbuf_txring* q, void *p, int seg_num)
1745bf882b4S10077240 {
1755bf882b4S10077240     int i = 0;
1765bf882b4S10077240     for ( i=0; i<seg_num-1; i++){
1775bf882b4S10077240         if ( q->m_table[q->head] ){
1785bf882b4S10077240             ff_mbuf_free(q->m_table[q->head]);
1795bf882b4S10077240             q->m_table[q->head] = NULL;
1805bf882b4S10077240         }
1815bf882b4S10077240         Head_INC(q->head);
1825bf882b4S10077240     }
1835bf882b4S10077240     if ( q->m_table[q->head] )
1845bf882b4S10077240         ff_mbuf_free(q->m_table[q->head]);
1855bf882b4S10077240     q->m_table[q->head] = p;
1865bf882b4S10077240     Head_INC(q->head);
1875bf882b4S10077240 
1885bf882b4S10077240     return 0;
1895bf882b4S10077240 }
1905bf882b4S10077240 
1915bf882b4S10077240 // pop out from head-1 .
ff_txring_pop(struct mbuf_txring * q,int num)1925bf882b4S10077240 static inline int ff_txring_pop(struct mbuf_txring* q, int num)
1935bf882b4S10077240 {
1945bf882b4S10077240     int i = 0;
1955bf882b4S10077240 
1965bf882b4S10077240     for (i=0; i<num; i++){
1975bf882b4S10077240         Head_DEC(q->head);
1985bf882b4S10077240         if ( (i==0 && q->m_table[q->head]==NULL) || (i>0 && q->m_table[q->head]!=NULL) ){
1995bf882b4S10077240             rte_panic("ff_txring_pop fatal error!");
2005bf882b4S10077240         }
2015bf882b4S10077240         if ( q->m_table[q->head] != NULL ){
2025bf882b4S10077240             ff_mbuf_free(q->m_table[q->head]);
2035bf882b4S10077240             q->m_table[q->head] = NULL;
2045bf882b4S10077240         }
2055bf882b4S10077240     }
2065bf882b4S10077240 }
2075bf882b4S10077240 
ff_txring_init(struct mbuf_txring * q,uint32_t num)2085bf882b4S10077240 static inline void ff_txring_init(struct mbuf_txring* q, uint32_t num)
2095bf882b4S10077240 {
2105bf882b4S10077240     memset(q, 0, sizeof(struct mbuf_txring)*num);
2115bf882b4S10077240 }
2125bf882b4S10077240 
ff_init_ref_pool(int nb_mbuf,int socketid)2135bf882b4S10077240 void ff_init_ref_pool(int nb_mbuf, int socketid)
2145bf882b4S10077240 {
2155bf882b4S10077240     char s[64] = {0};
2165bf882b4S10077240 
2175bf882b4S10077240     if (ff_ref_pool[socketid] != NULL) {
2185bf882b4S10077240             return;
2195bf882b4S10077240     }
2205bf882b4S10077240     snprintf(s, sizeof(s), "ff_ref_pool_%d", socketid);
2215bf882b4S10077240     if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
2225bf882b4S10077240         ff_ref_pool[socketid] = rte_pktmbuf_pool_create(s, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, 0, socketid);
2235bf882b4S10077240     } else {
2245bf882b4S10077240         ff_ref_pool[socketid] = rte_mempool_lookup(s);
2255bf882b4S10077240     }
2265bf882b4S10077240 }
2275bf882b4S10077240 
ff_mmap_init()2285bf882b4S10077240 int ff_mmap_init()
2295bf882b4S10077240 {
2305bf882b4S10077240     int err = 0;
2315bf882b4S10077240     int i = 0;
232c211a249Sfengbojiang     uint64_t    virt_addr = (uint64_t)NULL;
2335bf882b4S10077240     phys_addr_t    phys_addr = 0;
2345bf882b4S10077240     uint64_t    bsd_memsz = (ff_global_cfg.freebsd.mem_size << 20);
2355bf882b4S10077240     unsigned int bsd_pagesz = 0;
2365bf882b4S10077240 
2375bf882b4S10077240     ff_page_start = (uint64_t)mmap( NULL, bsd_memsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, -1, 0);
2385bf882b4S10077240     if (ff_page_start == (uint64_t)-1){
2395bf882b4S10077240         rte_panic("ff_mmap_init get ff_page_start failed, err=%d.\n", errno);
2405bf882b4S10077240         return -1;
2415bf882b4S10077240     }
2425bf882b4S10077240 
2435bf882b4S10077240     if ( mlock((void*)ff_page_start, bsd_memsz)<0 )    {
2445bf882b4S10077240         rte_panic("mlock failed, err=%d.\n", errno);
2455bf882b4S10077240         return -1;
2465bf882b4S10077240     }
2475bf882b4S10077240     ff_page_end = ff_page_start + bsd_memsz;
2485bf882b4S10077240     bsd_pagesz = (bsd_memsz>>12);
2495bf882b4S10077240     rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "ff_mmap_init mmap %d pages, %d MB.\n", bsd_pagesz, ff_global_cfg.freebsd.mem_size);
2505bf882b4S10077240     printf("ff_mmap_init mem[0x%lx:0x%lx]\n", ff_page_start, ff_page_end);
2515bf882b4S10077240 
2525bf882b4S10077240     if (posix_memalign((void**)&ff_mpage_phy, sizeof(phys_addr_t), bsd_pagesz*sizeof(phys_addr_t))!=0){
2535bf882b4S10077240         rte_panic("posix_memalign get ff_mpage_phy failed, err=%d.\n", errno);
2545bf882b4S10077240         return -1;
2555bf882b4S10077240     }
2565bf882b4S10077240 
2575bf882b4S10077240     stklist_init(&ff_mpage_ctl, bsd_pagesz);
2585bf882b4S10077240 
2595bf882b4S10077240     for (i=0; i<bsd_pagesz; i++ ){
2605bf882b4S10077240         virt_addr = ff_page_start + PAGE_SIZE*i;
2615bf882b4S10077240         memset((void*)virt_addr, 0, PAGE_SIZE);
2625bf882b4S10077240 
2635bf882b4S10077240         stklist_push( &ff_mpage_ctl, virt_addr);
2645bf882b4S10077240         ff_mpage_phy[i] = rte_mem_virt2phy((const void*)virt_addr);
2655bf882b4S10077240         if ( ff_mpage_phy[i] == RTE_BAD_IOVA ){
2665bf882b4S10077240             rte_panic("rte_mem_virt2phy return invalid address.");
2675bf882b4S10077240             return -1;
2685bf882b4S10077240         }
2695bf882b4S10077240     }
2705bf882b4S10077240 
2715bf882b4S10077240     ff_txring_init(&nic_tx_ring[0], RTE_MAX_ETHPORTS);
2725bf882b4S10077240 
2735bf882b4S10077240     return 0;
2745bf882b4S10077240 }
2755bf882b4S10077240 
2765bf882b4S10077240 // 1: vma in fstack page table;  0: vma not in fstack pages, in DPDK pool.
ff_chk_vma(const uint64_t virtaddr)2775bf882b4S10077240 static inline int ff_chk_vma(const uint64_t virtaddr)
2785bf882b4S10077240 {
2795bf882b4S10077240     return  !!( virtaddr > ff_page_start && virtaddr < ff_page_end );
2805bf882b4S10077240 }
2815bf882b4S10077240 
2825bf882b4S10077240 /*
2835bf882b4S10077240  * Get physical address of any mapped virtual address in the current process.
2845bf882b4S10077240  */
ff_mem_virt2phy(const void * virtaddr)2855bf882b4S10077240 static inline uint64_t ff_mem_virt2phy(const void* virtaddr)
2865bf882b4S10077240 {
2875bf882b4S10077240     uint64_t    addr = 0;
2885bf882b4S10077240     uint32_t    pages = 0;
2895bf882b4S10077240 
2905bf882b4S10077240     pages = (((uint64_t)virtaddr - (uint64_t)ff_page_start)>>PAGE_SHIFT);
2915bf882b4S10077240     if (pages >= stklist_size(&ff_mpage_ctl)){
2925bf882b4S10077240         rte_panic("ff_mbuf_virt2phy get invalid pages %d.", pages);
2935bf882b4S10077240         return -1;
2945bf882b4S10077240     }
2955bf882b4S10077240 
2965bf882b4S10077240     addr = ff_mpage_phy[pages] + ((const uint64_t)virtaddr & PAGE_MASK);
2975bf882b4S10077240     return addr;
2985bf882b4S10077240 }
2995bf882b4S10077240 
ff_mem_get_page()3005bf882b4S10077240 void *ff_mem_get_page()
3015bf882b4S10077240 {
3025bf882b4S10077240     return (void*)stklist_pop(&ff_mpage_ctl);
3035bf882b4S10077240 }
3045bf882b4S10077240 
ff_mem_free_addr(void * p)3055bf882b4S10077240 int    ff_mem_free_addr(void *p)
3065bf882b4S10077240 {
3075bf882b4S10077240     stklist_push(&ff_mpage_ctl, (const uint64_t)p);
3085bf882b4S10077240     return 0;
3095bf882b4S10077240 }
3105bf882b4S10077240 
ff_offload_set(struct ff_dpdk_if_context * ctx,void * m,struct rte_mbuf * head)3115bf882b4S10077240 static inline void ff_offload_set(struct ff_dpdk_if_context *ctx, void *m, struct rte_mbuf *head)
3125bf882b4S10077240 {
3135bf882b4S10077240     void                    *data = NULL;
3145bf882b4S10077240     struct ff_tx_offload     offload = {0};
3155bf882b4S10077240 
3165bf882b4S10077240     ff_mbuf_tx_offload(m, &offload);
3175bf882b4S10077240     data = rte_pktmbuf_mtod(head, void*);
3185bf882b4S10077240 
3195bf882b4S10077240     if (offload.ip_csum) {
3205bf882b4S10077240         /* ipv6 not supported yet */
321c211a249Sfengbojiang         struct rte_ipv4_hdr *iph;
3225bf882b4S10077240         int iph_len;
323c211a249Sfengbojiang         iph = (struct rte_ipv4_hdr *)(data + RTE_ETHER_HDR_LEN);
3245bf882b4S10077240         iph_len = (iph->version_ihl & 0x0f) << 2;
3255bf882b4S10077240 
3265bf882b4S10077240         head->ol_flags |= PKT_TX_IP_CKSUM | PKT_TX_IPV4;
327c211a249Sfengbojiang         head->l2_len = RTE_ETHER_HDR_LEN;
3285bf882b4S10077240         head->l3_len = iph_len;
3295bf882b4S10077240     }
3305bf882b4S10077240 
3315bf882b4S10077240     if (ctx->hw_features.tx_csum_l4) {
332c211a249Sfengbojiang         struct rte_ipv4_hdr *iph;
3335bf882b4S10077240         int iph_len;
334c211a249Sfengbojiang         iph = (struct rte_ipv4_hdr *)(data + RTE_ETHER_HDR_LEN);
3355bf882b4S10077240         iph_len = (iph->version_ihl & 0x0f) << 2;
3365bf882b4S10077240 
3375bf882b4S10077240         if (offload.tcp_csum) {
3385bf882b4S10077240             head->ol_flags |= PKT_TX_TCP_CKSUM;
339c211a249Sfengbojiang             head->l2_len = RTE_ETHER_HDR_LEN;
3405bf882b4S10077240             head->l3_len = iph_len;
3415bf882b4S10077240         }
3425bf882b4S10077240 
3435bf882b4S10077240        /*
3445bf882b4S10077240          *  TCP segmentation offload.
3455bf882b4S10077240          *
3465bf882b4S10077240          *  - set the PKT_TX_TCP_SEG flag in mbuf->ol_flags (this flag
3475bf882b4S10077240          *    implies PKT_TX_TCP_CKSUM)
3485bf882b4S10077240          *  - set the flag PKT_TX_IPV4 or PKT_TX_IPV6
3495bf882b4S10077240          *  - if it's IPv4, set the PKT_TX_IP_CKSUM flag and
3505bf882b4S10077240          *    write the IP checksum to 0 in the packet
3515bf882b4S10077240          *  - fill the mbuf offload information: l2_len,
3525bf882b4S10077240          *    l3_len, l4_len, tso_segsz
3535bf882b4S10077240          *  - calculate the pseudo header checksum without taking ip_len
3545bf882b4S10077240          *    in account, and set it in the TCP header. Refer to
3555bf882b4S10077240          *    rte_ipv4_phdr_cksum() and rte_ipv6_phdr_cksum() that can be
3565bf882b4S10077240          *    used as helpers.
3575bf882b4S10077240          */
3585bf882b4S10077240         if (offload.tso_seg_size) {
359c211a249Sfengbojiang             struct rte_tcp_hdr *tcph;
3605bf882b4S10077240             int tcph_len;
361c211a249Sfengbojiang             tcph = (struct rte_tcp_hdr *)((char *)iph + iph_len);
3625bf882b4S10077240             tcph_len = (tcph->data_off & 0xf0) >> 2;
3635bf882b4S10077240             tcph->cksum = rte_ipv4_phdr_cksum(iph, PKT_TX_TCP_SEG);
3645bf882b4S10077240 
3655bf882b4S10077240             head->ol_flags |= PKT_TX_TCP_SEG;
3665bf882b4S10077240             head->l4_len = tcph_len;
3675bf882b4S10077240             head->tso_segsz = offload.tso_seg_size;
3685bf882b4S10077240         }
3695bf882b4S10077240 
3705bf882b4S10077240         if (offload.udp_csum) {
3715bf882b4S10077240             head->ol_flags |= PKT_TX_UDP_CKSUM;
372c211a249Sfengbojiang             head->l2_len = RTE_ETHER_HDR_LEN;
3735bf882b4S10077240             head->l3_len = iph_len;
3745bf882b4S10077240         }
3755bf882b4S10077240     }
3765bf882b4S10077240 }
3775bf882b4S10077240 
3785bf882b4S10077240 // create rte_buf refer to data which is transmit from bsd stack by EXT_CLUSTER.
ff_extcl_to_rte(void * m)3795bf882b4S10077240 static inline struct rte_mbuf*     ff_extcl_to_rte(void *m )
3805bf882b4S10077240 {
3815bf882b4S10077240     struct rte_mempool *mbuf_pool = pktmbuf_pool[lcore_conf.socket_id];
3825bf882b4S10077240     struct rte_mbuf *src_mbuf = NULL;
3835bf882b4S10077240     struct rte_mbuf *p_head = NULL;
3845bf882b4S10077240 
3855bf882b4S10077240     src_mbuf = (struct rte_mbuf*)ff_rte_frm_extcl(m);
3865bf882b4S10077240     if ( NULL==src_mbuf ){
3875bf882b4S10077240         return NULL;
3885bf882b4S10077240     }
3895bf882b4S10077240     p_head = rte_pktmbuf_clone(src_mbuf, mbuf_pool);
3905bf882b4S10077240     if (p_head == NULL){
3915bf882b4S10077240         return NULL;
3925bf882b4S10077240     }
3935bf882b4S10077240 
3945bf882b4S10077240     return p_head;
3955bf882b4S10077240 }
3965bf882b4S10077240 
3975bf882b4S10077240 //  create rte_mbuf refer to data in bsd mbuf.
ff_bsd_to_rte(void * m,int total)3985bf882b4S10077240 static inline struct rte_mbuf*     ff_bsd_to_rte(void *m, int total)
3995bf882b4S10077240 {
4005bf882b4S10077240     struct rte_mempool *mbuf_pool = ff_ref_pool[lcore_conf.socket_id];
4015bf882b4S10077240     struct rte_mbuf *p_head = NULL;
4025bf882b4S10077240     struct rte_mbuf *cur = NULL, *prev = NULL, *tmp=NULL;
4035bf882b4S10077240     void    *data = NULL;
4045bf882b4S10077240     void    *p_bsdbuf = NULL;
4055bf882b4S10077240     unsigned len = 0;
4065bf882b4S10077240 
4075bf882b4S10077240     p_head = rte_pktmbuf_alloc(mbuf_pool);
4085bf882b4S10077240     if (p_head == NULL){
4095bf882b4S10077240         return NULL;
4105bf882b4S10077240     }
4115bf882b4S10077240     p_head->pkt_len = total;
4125bf882b4S10077240     p_head->nb_segs = 0;
4135bf882b4S10077240     cur = p_head;
4145bf882b4S10077240     p_bsdbuf = m;
4155bf882b4S10077240     while ( p_bsdbuf ){
4165bf882b4S10077240         if (cur == NULL) {
4175bf882b4S10077240             cur = rte_pktmbuf_alloc(mbuf_pool);
4185bf882b4S10077240             if (cur == NULL) {
4195bf882b4S10077240                 rte_pktmbuf_free(p_head);
4205bf882b4S10077240                 return NULL;
4215bf882b4S10077240             }
4225bf882b4S10077240         }
4235bf882b4S10077240         ff_next_mbuf(&p_bsdbuf, &data, &len);        // p_bsdbuf move to next mbuf.
4245bf882b4S10077240         cur->buf_addr = data;
425*403ae71dSfengbojiang         cur->buf_iova = ff_mem_virt2phy((const void*)(cur->buf_addr));
4265bf882b4S10077240         cur->data_off = 0;
4275bf882b4S10077240         cur->data_len = len;
4285bf882b4S10077240 
4295bf882b4S10077240         p_head->nb_segs++;
4305bf882b4S10077240         if (prev != NULL) {
4315bf882b4S10077240             prev->next = cur;
4325bf882b4S10077240         }
4335bf882b4S10077240         prev = cur;
4345bf882b4S10077240         cur = NULL;
4355bf882b4S10077240     }
4365bf882b4S10077240 
4375bf882b4S10077240     return p_head;
4385bf882b4S10077240 }
4395bf882b4S10077240 
ff_if_send_onepkt(struct ff_dpdk_if_context * ctx,void * m,int total)4405bf882b4S10077240 int ff_if_send_onepkt(struct ff_dpdk_if_context *ctx, void *m, int total)
4415bf882b4S10077240 {
4425bf882b4S10077240     struct rte_mbuf *head = NULL;
4435bf882b4S10077240     void            *src_buf = NULL;
4445bf882b4S10077240     void            *p_data = NULL;
4455bf882b4S10077240     struct lcore_conf *qconf = NULL;
4465bf882b4S10077240     unsigned        len = 0;
4475bf882b4S10077240 
4485bf882b4S10077240     if ( !m ){
4495bf882b4S10077240         rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_USER1, "ff_dpdk_if_send_ex input invalid NULL address.");
4505bf882b4S10077240         return 0;
4515bf882b4S10077240     }
4525bf882b4S10077240     p_data = ff_mbuf_mtod(m);
4535bf882b4S10077240     if ( ff_chk_vma((uint64_t)p_data)){
4545bf882b4S10077240         head = ff_bsd_to_rte(m, total);
4555bf882b4S10077240     }
4565bf882b4S10077240     else if ( (head = ff_extcl_to_rte(m)) == NULL ){
4575bf882b4S10077240            rte_panic("data address 0x%lx is out of page bound or not malloced by DPDK recver.", (uint64_t)p_data);
4585bf882b4S10077240         return 0;
4595bf882b4S10077240     }
4605bf882b4S10077240 
4615bf882b4S10077240     if (head == NULL){
4625bf882b4S10077240         rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_USER1, "ff_if_send_onepkt call ff_bsd_to_rte failed.");
4635bf882b4S10077240         ff_mbuf_free(m);
4645bf882b4S10077240         return 0;
4655bf882b4S10077240     }
4665bf882b4S10077240 
4675bf882b4S10077240     ff_offload_set(ctx, m, head);
4685bf882b4S10077240     qconf = &lcore_conf;
4695bf882b4S10077240     len = qconf->tx_mbufs[ctx->port_id].len;
4705bf882b4S10077240     qconf->tx_mbufs[ctx->port_id].m_table[len] = head;
4715bf882b4S10077240     qconf->tx_mbufs[ctx->port_id].bsd_m_table[len] = m;
4725bf882b4S10077240     len++;
4735bf882b4S10077240 
4745bf882b4S10077240     return len;
4755bf882b4S10077240 }
4765bf882b4S10077240 
ff_enq_tx_bsdmbuf(uint8_t portid,void * p_mbuf,int nb_segs)4775bf882b4S10077240 int ff_enq_tx_bsdmbuf(uint8_t portid, void *p_mbuf, int nb_segs)
4785bf882b4S10077240 {
4795bf882b4S10077240     return ff_txring_enqueue(&nic_tx_ring[portid], p_mbuf, nb_segs);
4805bf882b4S10077240 }
4815bf882b4S10077240 
482