xref: /f-stack/lib/ff_memory.c (revision 5bf882b4)
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