1*5bf882b4S10077240 /* 2*5bf882b4S10077240 * Copyright (C) 2017 THL A29 Limited, a Tencent company. 3*5bf882b4S10077240 * All rights reserved. 4*5bf882b4S10077240 * 5*5bf882b4S10077240 * Redistribution and use in source and binary forms, with or without 6*5bf882b4S10077240 * modification, are permitted provided that the following conditions are met: 7*5bf882b4S10077240 * 8*5bf882b4S10077240 * 1. Redistributions of source code must retain the above copyright notice, this 9*5bf882b4S10077240 * list of conditions and the following disclaimer. 10*5bf882b4S10077240 * 2. Redistributions in binary form must reproduce the above copyright notice, 11*5bf882b4S10077240 * this list of conditions and the following disclaimer in the documentation 12*5bf882b4S10077240 * and/or other materials provided with the distribution. 13*5bf882b4S10077240 * 14*5bf882b4S10077240 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15*5bf882b4S10077240 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16*5bf882b4S10077240 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17*5bf882b4S10077240 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18*5bf882b4S10077240 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19*5bf882b4S10077240 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20*5bf882b4S10077240 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21*5bf882b4S10077240 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22*5bf882b4S10077240 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23*5bf882b4S10077240 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*5bf882b4S10077240 * 25*5bf882b4S10077240 */ 26*5bf882b4S10077240 #include <assert.h> 27*5bf882b4S10077240 #include <unistd.h> 28*5bf882b4S10077240 #include <sys/mman.h> 29*5bf882b4S10077240 #include <errno.h> 30*5bf882b4S10077240 31*5bf882b4S10077240 #include <rte_common.h> 32*5bf882b4S10077240 #include <rte_byteorder.h> 33*5bf882b4S10077240 #include <rte_log.h> 34*5bf882b4S10077240 #include <rte_memory.h> 35*5bf882b4S10077240 #include <rte_memcpy.h> 36*5bf882b4S10077240 #include <rte_memzone.h> 37*5bf882b4S10077240 #include <rte_config.h> 38*5bf882b4S10077240 #include <rte_eal.h> 39*5bf882b4S10077240 #include <rte_pci.h> 40*5bf882b4S10077240 #include <rte_mbuf.h> 41*5bf882b4S10077240 #include <rte_lcore.h> 42*5bf882b4S10077240 #include <rte_launch.h> 43*5bf882b4S10077240 #include <rte_ethdev.h> 44*5bf882b4S10077240 #include <rte_debug.h> 45*5bf882b4S10077240 #include <rte_ether.h> 46*5bf882b4S10077240 #include <rte_malloc.h> 47*5bf882b4S10077240 #include <rte_cycles.h> 48*5bf882b4S10077240 #include <rte_timer.h> 49*5bf882b4S10077240 #include <rte_thash.h> 50*5bf882b4S10077240 #include <rte_ip.h> 51*5bf882b4S10077240 #include <rte_tcp.h> 52*5bf882b4S10077240 #include <rte_udp.h> 53*5bf882b4S10077240 54*5bf882b4S10077240 #include "ff_dpdk_if.h" 55*5bf882b4S10077240 #include "ff_dpdk_pcap.h" 56*5bf882b4S10077240 #include "ff_dpdk_kni.h" 57*5bf882b4S10077240 #include "ff_config.h" 58*5bf882b4S10077240 #include "ff_veth.h" 59*5bf882b4S10077240 #include "ff_host_interface.h" 60*5bf882b4S10077240 #include "ff_msg.h" 61*5bf882b4S10077240 #include "ff_api.h" 62*5bf882b4S10077240 #include "ff_memory.h" 63*5bf882b4S10077240 64*5bf882b4S10077240 #define PAGE_SIZE 4096 65*5bf882b4S10077240 #define PAGE_SHIFT 12 66*5bf882b4S10077240 #define PAGE_MASK (PAGE_SIZE - 1) 67*5bf882b4S10077240 #define trunc_page(x) ((x) & ~PAGE_MASK) 68*5bf882b4S10077240 #define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK) 69*5bf882b4S10077240 70*5bf882b4S10077240 extern struct rte_mempool *pktmbuf_pool[NB_SOCKETS]; 71*5bf882b4S10077240 extern struct lcore_conf lcore_conf; 72*5bf882b4S10077240 73*5bf882b4S10077240 //struct ff_tx_offload; 74*5bf882b4S10077240 75*5bf882b4S10077240 // ff_ref_pool allocate rte_mbuf without data space, which data point to bsd mbuf's data address. 76*5bf882b4S10077240 static struct rte_mempool *ff_ref_pool[NB_SOCKETS]; 77*5bf882b4S10077240 78*5bf882b4S10077240 #define Head_INC(h) {\ 79*5bf882b4S10077240 if ( ++h >= TX_QUEUE_SIZE ) \ 80*5bf882b4S10077240 h = 0;\ 81*5bf882b4S10077240 }; 82*5bf882b4S10077240 83*5bf882b4S10077240 #define Head_DEC(h) do{\ 84*5bf882b4S10077240 if ( --h < 0 ) \ 85*5bf882b4S10077240 h = TX_QUEUE_SIZE-1;\ 86*5bf882b4S10077240 }while(0); 87*5bf882b4S10077240 88*5bf882b4S10077240 // bsd mbuf was moved into nic_tx_ring from tmp_tables, after rte_eth_tx_burst() succeed. 89*5bf882b4S10077240 static struct mbuf_txring nic_tx_ring[RTE_MAX_ETHPORTS]; 90*5bf882b4S10077240 static inline int ff_txring_enqueue(struct mbuf_txring* q, void *p, int seg_num); 91*5bf882b4S10077240 static inline void ff_txring_init(struct mbuf_txring* r, uint32_t len); 92*5bf882b4S10077240 93*5bf882b4S10077240 typedef struct _list_manager_s 94*5bf882b4S10077240 { 95*5bf882b4S10077240 uint64_t *ele; 96*5bf882b4S10077240 int size; 97*5bf882b4S10077240 //int FreeNum; 98*5bf882b4S10077240 int top; 99*5bf882b4S10077240 }StackList_t; 100*5bf882b4S10077240 101*5bf882b4S10077240 static StackList_t ff_mpage_ctl = {0}; 102*5bf882b4S10077240 static uint64_t ff_page_start = NULL, ff_page_end = NULL; 103*5bf882b4S10077240 static phys_addr_t *ff_mpage_phy = NULL; 104*5bf882b4S10077240 105*5bf882b4S10077240 static inline void *stklist_pop(StackList_t *p); 106*5bf882b4S10077240 static inline int stklist_push(StackList_t * p, uint64_t val); 107*5bf882b4S10077240 108*5bf882b4S10077240 static int stklist_init(StackList_t*p, int size) 109*5bf882b4S10077240 { 110*5bf882b4S10077240 int i = 0; 111*5bf882b4S10077240 112*5bf882b4S10077240 if (p==NULL || size<=0){ 113*5bf882b4S10077240 return -1; 114*5bf882b4S10077240 } 115*5bf882b4S10077240 p->size = size; 116*5bf882b4S10077240 p->top = 0; 117*5bf882b4S10077240 if ( posix_memalign((void**)&p->ele, sizeof(uint64_t), sizeof(uint64_t)*size) != 0) 118*5bf882b4S10077240 return -2; 119*5bf882b4S10077240 120*5bf882b4S10077240 return 0; 121*5bf882b4S10077240 } 122*5bf882b4S10077240 123*5bf882b4S10077240 static inline void *stklist_pop(StackList_t *p) 124*5bf882b4S10077240 { 125*5bf882b4S10077240 int head = 0; 126*5bf882b4S10077240 127*5bf882b4S10077240 if (p==NULL) 128*5bf882b4S10077240 return NULL; 129*5bf882b4S10077240 130*5bf882b4S10077240 if (p->top > 0 ){ 131*5bf882b4S10077240 return (void*)p->ele[--p->top]; 132*5bf882b4S10077240 } 133*5bf882b4S10077240 else 134*5bf882b4S10077240 return NULL; 135*5bf882b4S10077240 } 136*5bf882b4S10077240 137*5bf882b4S10077240 //id: the id of element to be freed. 138*5bf882b4S10077240 //return code: -1: faile; >=0:OK. 139*5bf882b4S10077240 static inline int stklist_push(StackList_t *p, const uint64_t val){ 140*5bf882b4S10077240 int tail = 0; 141*5bf882b4S10077240 142*5bf882b4S10077240 if (p==NULL) 143*5bf882b4S10077240 return -1; 144*5bf882b4S10077240 if (p->top < p->size){ 145*5bf882b4S10077240 p->ele[p->top++] = val; 146*5bf882b4S10077240 return 0; 147*5bf882b4S10077240 } 148*5bf882b4S10077240 else 149*5bf882b4S10077240 return -1; 150*5bf882b4S10077240 } 151*5bf882b4S10077240 152*5bf882b4S10077240 static inline int stklist_size(StackList_t * p) 153*5bf882b4S10077240 { 154*5bf882b4S10077240 return p->size; 155*5bf882b4S10077240 } 156*5bf882b4S10077240 157*5bf882b4S10077240 // set (void*) to rte_mbuf's priv_data. 158*5bf882b4S10077240 static inline int ff_mbuf_set_uint64(struct rte_mbuf* p, uint64_t data) 159*5bf882b4S10077240 { 160*5bf882b4S10077240 if (rte_pktmbuf_priv_size(p->pool) >= sizeof(uint64_t)) 161*5bf882b4S10077240 *((uint64_t*)(p+1)) = data; 162*5bf882b4S10077240 return 0; 163*5bf882b4S10077240 } 164*5bf882b4S10077240 165*5bf882b4S10077240 /************************* 166*5bf882b4S10077240 * if mbuf has num segment in all, Dev's sw_ring will use num descriptions. ff_txring also use num segments as below: 167*5bf882b4S10077240 * <--- num-1 ---->|ptr| head | 168*5bf882b4S10077240 * ---------------------------------------------- 169*5bf882b4S10077240 * | 0 | 0 | ..............| 0 | p | XXX | 170*5bf882b4S10077240 *----------------------------------------------- 171*5bf882b4S10077240 *************************/ 172*5bf882b4S10077240 static inline int ff_txring_enqueue(struct mbuf_txring* q, void *p, int seg_num) 173*5bf882b4S10077240 { 174*5bf882b4S10077240 int i = 0; 175*5bf882b4S10077240 for ( i=0; i<seg_num-1; i++){ 176*5bf882b4S10077240 if ( q->m_table[q->head] ){ 177*5bf882b4S10077240 ff_mbuf_free(q->m_table[q->head]); 178*5bf882b4S10077240 q->m_table[q->head] = NULL; 179*5bf882b4S10077240 } 180*5bf882b4S10077240 Head_INC(q->head); 181*5bf882b4S10077240 } 182*5bf882b4S10077240 if ( q->m_table[q->head] ) 183*5bf882b4S10077240 ff_mbuf_free(q->m_table[q->head]); 184*5bf882b4S10077240 q->m_table[q->head] = p; 185*5bf882b4S10077240 Head_INC(q->head); 186*5bf882b4S10077240 187*5bf882b4S10077240 return 0; 188*5bf882b4S10077240 } 189*5bf882b4S10077240 190*5bf882b4S10077240 // pop out from head-1 . 191*5bf882b4S10077240 static inline int ff_txring_pop(struct mbuf_txring* q, int num) 192*5bf882b4S10077240 { 193*5bf882b4S10077240 int i = 0; 194*5bf882b4S10077240 195*5bf882b4S10077240 for (i=0; i<num; i++){ 196*5bf882b4S10077240 Head_DEC(q->head); 197*5bf882b4S10077240 if ( (i==0 && q->m_table[q->head]==NULL) || (i>0 && q->m_table[q->head]!=NULL) ){ 198*5bf882b4S10077240 rte_panic("ff_txring_pop fatal error!"); 199*5bf882b4S10077240 } 200*5bf882b4S10077240 if ( q->m_table[q->head] != NULL ){ 201*5bf882b4S10077240 ff_mbuf_free(q->m_table[q->head]); 202*5bf882b4S10077240 q->m_table[q->head] = NULL; 203*5bf882b4S10077240 } 204*5bf882b4S10077240 } 205*5bf882b4S10077240 } 206*5bf882b4S10077240 207*5bf882b4S10077240 static inline void ff_txring_init(struct mbuf_txring* q, uint32_t num) 208*5bf882b4S10077240 { 209*5bf882b4S10077240 memset(q, 0, sizeof(struct mbuf_txring)*num); 210*5bf882b4S10077240 } 211*5bf882b4S10077240 212*5bf882b4S10077240 void ff_init_ref_pool(int nb_mbuf, int socketid) 213*5bf882b4S10077240 { 214*5bf882b4S10077240 char s[64] = {0}; 215*5bf882b4S10077240 216*5bf882b4S10077240 if (ff_ref_pool[socketid] != NULL) { 217*5bf882b4S10077240 return; 218*5bf882b4S10077240 } 219*5bf882b4S10077240 snprintf(s, sizeof(s), "ff_ref_pool_%d", socketid); 220*5bf882b4S10077240 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 221*5bf882b4S10077240 ff_ref_pool[socketid] = rte_pktmbuf_pool_create(s, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, 0, socketid); 222*5bf882b4S10077240 } else { 223*5bf882b4S10077240 ff_ref_pool[socketid] = rte_mempool_lookup(s); 224*5bf882b4S10077240 } 225*5bf882b4S10077240 } 226*5bf882b4S10077240 227*5bf882b4S10077240 int ff_mmap_init() 228*5bf882b4S10077240 { 229*5bf882b4S10077240 int err = 0; 230*5bf882b4S10077240 int i = 0; 231*5bf882b4S10077240 uint64_t virt_addr = NULL; 232*5bf882b4S10077240 phys_addr_t phys_addr = 0; 233*5bf882b4S10077240 uint64_t bsd_memsz = (ff_global_cfg.freebsd.mem_size << 20); 234*5bf882b4S10077240 unsigned int bsd_pagesz = 0; 235*5bf882b4S10077240 236*5bf882b4S10077240 ff_page_start = (uint64_t)mmap( NULL, bsd_memsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, -1, 0); 237*5bf882b4S10077240 if (ff_page_start == (uint64_t)-1){ 238*5bf882b4S10077240 rte_panic("ff_mmap_init get ff_page_start failed, err=%d.\n", errno); 239*5bf882b4S10077240 return -1; 240*5bf882b4S10077240 } 241*5bf882b4S10077240 242*5bf882b4S10077240 if ( mlock((void*)ff_page_start, bsd_memsz)<0 ) { 243*5bf882b4S10077240 rte_panic("mlock failed, err=%d.\n", errno); 244*5bf882b4S10077240 return -1; 245*5bf882b4S10077240 } 246*5bf882b4S10077240 ff_page_end = ff_page_start + bsd_memsz; 247*5bf882b4S10077240 bsd_pagesz = (bsd_memsz>>12); 248*5bf882b4S10077240 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); 249*5bf882b4S10077240 printf("ff_mmap_init mem[0x%lx:0x%lx]\n", ff_page_start, ff_page_end); 250*5bf882b4S10077240 251*5bf882b4S10077240 if (posix_memalign((void**)&ff_mpage_phy, sizeof(phys_addr_t), bsd_pagesz*sizeof(phys_addr_t))!=0){ 252*5bf882b4S10077240 rte_panic("posix_memalign get ff_mpage_phy failed, err=%d.\n", errno); 253*5bf882b4S10077240 return -1; 254*5bf882b4S10077240 } 255*5bf882b4S10077240 256*5bf882b4S10077240 stklist_init(&ff_mpage_ctl, bsd_pagesz); 257*5bf882b4S10077240 258*5bf882b4S10077240 for (i=0; i<bsd_pagesz; i++ ){ 259*5bf882b4S10077240 virt_addr = ff_page_start + PAGE_SIZE*i; 260*5bf882b4S10077240 memset((void*)virt_addr, 0, PAGE_SIZE); 261*5bf882b4S10077240 262*5bf882b4S10077240 stklist_push( &ff_mpage_ctl, virt_addr); 263*5bf882b4S10077240 ff_mpage_phy[i] = rte_mem_virt2phy((const void*)virt_addr); 264*5bf882b4S10077240 if ( ff_mpage_phy[i] == RTE_BAD_IOVA ){ 265*5bf882b4S10077240 rte_panic("rte_mem_virt2phy return invalid address."); 266*5bf882b4S10077240 return -1; 267*5bf882b4S10077240 } 268*5bf882b4S10077240 } 269*5bf882b4S10077240 270*5bf882b4S10077240 ff_txring_init(&nic_tx_ring[0], RTE_MAX_ETHPORTS); 271*5bf882b4S10077240 272*5bf882b4S10077240 return 0; 273*5bf882b4S10077240 } 274*5bf882b4S10077240 275*5bf882b4S10077240 // 1: vma in fstack page table; 0: vma not in fstack pages, in DPDK pool. 276*5bf882b4S10077240 static inline int ff_chk_vma(const uint64_t virtaddr) 277*5bf882b4S10077240 { 278*5bf882b4S10077240 return !!( virtaddr > ff_page_start && virtaddr < ff_page_end ); 279*5bf882b4S10077240 } 280*5bf882b4S10077240 281*5bf882b4S10077240 /* 282*5bf882b4S10077240 * Get physical address of any mapped virtual address in the current process. 283*5bf882b4S10077240 */ 284*5bf882b4S10077240 static inline uint64_t ff_mem_virt2phy(const void* virtaddr) 285*5bf882b4S10077240 { 286*5bf882b4S10077240 uint64_t addr = 0; 287*5bf882b4S10077240 uint32_t pages = 0; 288*5bf882b4S10077240 289*5bf882b4S10077240 pages = (((uint64_t)virtaddr - (uint64_t)ff_page_start)>>PAGE_SHIFT); 290*5bf882b4S10077240 if (pages >= stklist_size(&ff_mpage_ctl)){ 291*5bf882b4S10077240 rte_panic("ff_mbuf_virt2phy get invalid pages %d.", pages); 292*5bf882b4S10077240 return -1; 293*5bf882b4S10077240 } 294*5bf882b4S10077240 295*5bf882b4S10077240 addr = ff_mpage_phy[pages] + ((const uint64_t)virtaddr & PAGE_MASK); 296*5bf882b4S10077240 return addr; 297*5bf882b4S10077240 } 298*5bf882b4S10077240 299*5bf882b4S10077240 void *ff_mem_get_page() 300*5bf882b4S10077240 { 301*5bf882b4S10077240 return (void*)stklist_pop(&ff_mpage_ctl); 302*5bf882b4S10077240 } 303*5bf882b4S10077240 304*5bf882b4S10077240 int ff_mem_free_addr(void *p) 305*5bf882b4S10077240 { 306*5bf882b4S10077240 stklist_push(&ff_mpage_ctl, (const uint64_t)p); 307*5bf882b4S10077240 return 0; 308*5bf882b4S10077240 } 309*5bf882b4S10077240 310*5bf882b4S10077240 static inline void ff_offload_set(struct ff_dpdk_if_context *ctx, void *m, struct rte_mbuf *head) 311*5bf882b4S10077240 { 312*5bf882b4S10077240 void *data = NULL; 313*5bf882b4S10077240 struct ff_tx_offload offload = {0}; 314*5bf882b4S10077240 315*5bf882b4S10077240 ff_mbuf_tx_offload(m, &offload); 316*5bf882b4S10077240 data = rte_pktmbuf_mtod(head, void*); 317*5bf882b4S10077240 318*5bf882b4S10077240 if (offload.ip_csum) { 319*5bf882b4S10077240 /* ipv6 not supported yet */ 320*5bf882b4S10077240 struct ipv4_hdr *iph; 321*5bf882b4S10077240 int iph_len; 322*5bf882b4S10077240 iph = (struct ipv4_hdr *)(data + ETHER_HDR_LEN); 323*5bf882b4S10077240 iph_len = (iph->version_ihl & 0x0f) << 2; 324*5bf882b4S10077240 325*5bf882b4S10077240 head->ol_flags |= PKT_TX_IP_CKSUM | PKT_TX_IPV4; 326*5bf882b4S10077240 head->l2_len = ETHER_HDR_LEN; 327*5bf882b4S10077240 head->l3_len = iph_len; 328*5bf882b4S10077240 } 329*5bf882b4S10077240 330*5bf882b4S10077240 if (ctx->hw_features.tx_csum_l4) { 331*5bf882b4S10077240 struct ipv4_hdr *iph; 332*5bf882b4S10077240 int iph_len; 333*5bf882b4S10077240 iph = (struct ipv4_hdr *)(data + ETHER_HDR_LEN); 334*5bf882b4S10077240 iph_len = (iph->version_ihl & 0x0f) << 2; 335*5bf882b4S10077240 336*5bf882b4S10077240 if (offload.tcp_csum) { 337*5bf882b4S10077240 head->ol_flags |= PKT_TX_TCP_CKSUM; 338*5bf882b4S10077240 head->l2_len = ETHER_HDR_LEN; 339*5bf882b4S10077240 head->l3_len = iph_len; 340*5bf882b4S10077240 } 341*5bf882b4S10077240 342*5bf882b4S10077240 /* 343*5bf882b4S10077240 * TCP segmentation offload. 344*5bf882b4S10077240 * 345*5bf882b4S10077240 * - set the PKT_TX_TCP_SEG flag in mbuf->ol_flags (this flag 346*5bf882b4S10077240 * implies PKT_TX_TCP_CKSUM) 347*5bf882b4S10077240 * - set the flag PKT_TX_IPV4 or PKT_TX_IPV6 348*5bf882b4S10077240 * - if it's IPv4, set the PKT_TX_IP_CKSUM flag and 349*5bf882b4S10077240 * write the IP checksum to 0 in the packet 350*5bf882b4S10077240 * - fill the mbuf offload information: l2_len, 351*5bf882b4S10077240 * l3_len, l4_len, tso_segsz 352*5bf882b4S10077240 * - calculate the pseudo header checksum without taking ip_len 353*5bf882b4S10077240 * in account, and set it in the TCP header. Refer to 354*5bf882b4S10077240 * rte_ipv4_phdr_cksum() and rte_ipv6_phdr_cksum() that can be 355*5bf882b4S10077240 * used as helpers. 356*5bf882b4S10077240 */ 357*5bf882b4S10077240 if (offload.tso_seg_size) { 358*5bf882b4S10077240 struct tcp_hdr *tcph; 359*5bf882b4S10077240 int tcph_len; 360*5bf882b4S10077240 tcph = (struct tcp_hdr *)((char *)iph + iph_len); 361*5bf882b4S10077240 tcph_len = (tcph->data_off & 0xf0) >> 2; 362*5bf882b4S10077240 tcph->cksum = rte_ipv4_phdr_cksum(iph, PKT_TX_TCP_SEG); 363*5bf882b4S10077240 364*5bf882b4S10077240 head->ol_flags |= PKT_TX_TCP_SEG; 365*5bf882b4S10077240 head->l4_len = tcph_len; 366*5bf882b4S10077240 head->tso_segsz = offload.tso_seg_size; 367*5bf882b4S10077240 } 368*5bf882b4S10077240 369*5bf882b4S10077240 if (offload.udp_csum) { 370*5bf882b4S10077240 head->ol_flags |= PKT_TX_UDP_CKSUM; 371*5bf882b4S10077240 head->l2_len = ETHER_HDR_LEN; 372*5bf882b4S10077240 head->l3_len = iph_len; 373*5bf882b4S10077240 } 374*5bf882b4S10077240 } 375*5bf882b4S10077240 } 376*5bf882b4S10077240 377*5bf882b4S10077240 // create rte_buf refer to data which is transmit from bsd stack by EXT_CLUSTER. 378*5bf882b4S10077240 static inline struct rte_mbuf* ff_extcl_to_rte(void *m ) 379*5bf882b4S10077240 { 380*5bf882b4S10077240 struct rte_mempool *mbuf_pool = pktmbuf_pool[lcore_conf.socket_id]; 381*5bf882b4S10077240 struct rte_mbuf *src_mbuf = NULL; 382*5bf882b4S10077240 struct rte_mbuf *p_head = NULL; 383*5bf882b4S10077240 384*5bf882b4S10077240 src_mbuf = (struct rte_mbuf*)ff_rte_frm_extcl(m); 385*5bf882b4S10077240 if ( NULL==src_mbuf ){ 386*5bf882b4S10077240 return NULL; 387*5bf882b4S10077240 } 388*5bf882b4S10077240 p_head = rte_pktmbuf_clone(src_mbuf, mbuf_pool); 389*5bf882b4S10077240 if (p_head == NULL){ 390*5bf882b4S10077240 return NULL; 391*5bf882b4S10077240 } 392*5bf882b4S10077240 393*5bf882b4S10077240 return p_head; 394*5bf882b4S10077240 } 395*5bf882b4S10077240 396*5bf882b4S10077240 // create rte_mbuf refer to data in bsd mbuf. 397*5bf882b4S10077240 static inline struct rte_mbuf* ff_bsd_to_rte(void *m, int total) 398*5bf882b4S10077240 { 399*5bf882b4S10077240 struct rte_mempool *mbuf_pool = ff_ref_pool[lcore_conf.socket_id]; 400*5bf882b4S10077240 struct rte_mbuf *p_head = NULL; 401*5bf882b4S10077240 struct rte_mbuf *cur = NULL, *prev = NULL, *tmp=NULL; 402*5bf882b4S10077240 void *data = NULL; 403*5bf882b4S10077240 void *p_bsdbuf = NULL; 404*5bf882b4S10077240 unsigned len = 0; 405*5bf882b4S10077240 406*5bf882b4S10077240 p_head = rte_pktmbuf_alloc(mbuf_pool); 407*5bf882b4S10077240 if (p_head == NULL){ 408*5bf882b4S10077240 return NULL; 409*5bf882b4S10077240 } 410*5bf882b4S10077240 p_head->pkt_len = total; 411*5bf882b4S10077240 p_head->nb_segs = 0; 412*5bf882b4S10077240 cur = p_head; 413*5bf882b4S10077240 p_bsdbuf = m; 414*5bf882b4S10077240 while ( p_bsdbuf ){ 415*5bf882b4S10077240 if (cur == NULL) { 416*5bf882b4S10077240 cur = rte_pktmbuf_alloc(mbuf_pool); 417*5bf882b4S10077240 if (cur == NULL) { 418*5bf882b4S10077240 rte_pktmbuf_free(p_head); 419*5bf882b4S10077240 return NULL; 420*5bf882b4S10077240 } 421*5bf882b4S10077240 } 422*5bf882b4S10077240 ff_next_mbuf(&p_bsdbuf, &data, &len); // p_bsdbuf move to next mbuf. 423*5bf882b4S10077240 cur->buf_addr = data; 424*5bf882b4S10077240 cur->buf_physaddr = ff_mem_virt2phy((const void*)(cur->buf_addr)); 425*5bf882b4S10077240 cur->data_off = 0; 426*5bf882b4S10077240 cur->data_len = len; 427*5bf882b4S10077240 428*5bf882b4S10077240 p_head->nb_segs++; 429*5bf882b4S10077240 if (prev != NULL) { 430*5bf882b4S10077240 prev->next = cur; 431*5bf882b4S10077240 } 432*5bf882b4S10077240 prev = cur; 433*5bf882b4S10077240 cur = NULL; 434*5bf882b4S10077240 } 435*5bf882b4S10077240 436*5bf882b4S10077240 return p_head; 437*5bf882b4S10077240 } 438*5bf882b4S10077240 439*5bf882b4S10077240 int ff_if_send_onepkt(struct ff_dpdk_if_context *ctx, void *m, int total) 440*5bf882b4S10077240 { 441*5bf882b4S10077240 struct rte_mbuf *head = NULL; 442*5bf882b4S10077240 void *src_buf = NULL; 443*5bf882b4S10077240 void *p_data = NULL; 444*5bf882b4S10077240 struct lcore_conf *qconf = NULL; 445*5bf882b4S10077240 unsigned len = 0; 446*5bf882b4S10077240 447*5bf882b4S10077240 if ( !m ){ 448*5bf882b4S10077240 rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_USER1, "ff_dpdk_if_send_ex input invalid NULL address."); 449*5bf882b4S10077240 return 0; 450*5bf882b4S10077240 } 451*5bf882b4S10077240 p_data = ff_mbuf_mtod(m); 452*5bf882b4S10077240 if ( ff_chk_vma((uint64_t)p_data)){ 453*5bf882b4S10077240 head = ff_bsd_to_rte(m, total); 454*5bf882b4S10077240 } 455*5bf882b4S10077240 else if ( (head = ff_extcl_to_rte(m)) == NULL ){ 456*5bf882b4S10077240 rte_panic("data address 0x%lx is out of page bound or not malloced by DPDK recver.", (uint64_t)p_data); 457*5bf882b4S10077240 return 0; 458*5bf882b4S10077240 } 459*5bf882b4S10077240 460*5bf882b4S10077240 if (head == NULL){ 461*5bf882b4S10077240 rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_USER1, "ff_if_send_onepkt call ff_bsd_to_rte failed."); 462*5bf882b4S10077240 ff_mbuf_free(m); 463*5bf882b4S10077240 return 0; 464*5bf882b4S10077240 } 465*5bf882b4S10077240 466*5bf882b4S10077240 ff_offload_set(ctx, m, head); 467*5bf882b4S10077240 qconf = &lcore_conf; 468*5bf882b4S10077240 len = qconf->tx_mbufs[ctx->port_id].len; 469*5bf882b4S10077240 qconf->tx_mbufs[ctx->port_id].m_table[len] = head; 470*5bf882b4S10077240 qconf->tx_mbufs[ctx->port_id].bsd_m_table[len] = m; 471*5bf882b4S10077240 len++; 472*5bf882b4S10077240 473*5bf882b4S10077240 return len; 474*5bf882b4S10077240 } 475*5bf882b4S10077240 476*5bf882b4S10077240 int ff_enq_tx_bsdmbuf(uint8_t portid, void *p_mbuf, int nb_segs) 477*5bf882b4S10077240 { 478*5bf882b4S10077240 return ff_txring_enqueue(&nic_tx_ring[portid], p_mbuf, nb_segs); 479*5bf882b4S10077240 } 480*5bf882b4S10077240 481