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}; 102*c211a249Sfengbojiang 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 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 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. 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 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. 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 *************************/ 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 . 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 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 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 2285bf882b4S10077240 int ff_mmap_init() 2295bf882b4S10077240 { 2305bf882b4S10077240 int err = 0; 2315bf882b4S10077240 int i = 0; 232*c211a249Sfengbojiang 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. 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 */ 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 3005bf882b4S10077240 void *ff_mem_get_page() 3015bf882b4S10077240 { 3025bf882b4S10077240 return (void*)stklist_pop(&ff_mpage_ctl); 3035bf882b4S10077240 } 3045bf882b4S10077240 3055bf882b4S10077240 int ff_mem_free_addr(void *p) 3065bf882b4S10077240 { 3075bf882b4S10077240 stklist_push(&ff_mpage_ctl, (const uint64_t)p); 3085bf882b4S10077240 return 0; 3095bf882b4S10077240 } 3105bf882b4S10077240 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 */ 321*c211a249Sfengbojiang struct rte_ipv4_hdr *iph; 3225bf882b4S10077240 int iph_len; 323*c211a249Sfengbojiang 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; 327*c211a249Sfengbojiang head->l2_len = RTE_ETHER_HDR_LEN; 3285bf882b4S10077240 head->l3_len = iph_len; 3295bf882b4S10077240 } 3305bf882b4S10077240 3315bf882b4S10077240 if (ctx->hw_features.tx_csum_l4) { 332*c211a249Sfengbojiang struct rte_ipv4_hdr *iph; 3335bf882b4S10077240 int iph_len; 334*c211a249Sfengbojiang 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; 339*c211a249Sfengbojiang 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) { 359*c211a249Sfengbojiang struct rte_tcp_hdr *tcph; 3605bf882b4S10077240 int tcph_len; 361*c211a249Sfengbojiang 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; 372*c211a249Sfengbojiang 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. 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. 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; 4255bf882b4S10077240 cur->buf_physaddr = 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 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 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