xref: /f-stack/lib/ff_dpdk_if.c (revision 2317ada5)
1a9643ea8Slogwang /*
2*2317ada5Sfengbojiang  * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
3a9643ea8Slogwang  * All rights reserved.
4a9643ea8Slogwang  *
5a9643ea8Slogwang  * Redistribution and use in source and binary forms, with or without
6a9643ea8Slogwang  * modification, are permitted provided that the following conditions are met:
7a9643ea8Slogwang  *
8a9643ea8Slogwang  * 1. Redistributions of source code must retain the above copyright notice, this
9a9643ea8Slogwang  *   list of conditions and the following disclaimer.
10a9643ea8Slogwang  * 2. Redistributions in binary form must reproduce the above copyright notice,
11a9643ea8Slogwang  *   this list of conditions and the following disclaimer in the documentation
12a9643ea8Slogwang  *   and/or other materials provided with the distribution.
13a9643ea8Slogwang  *
14a9643ea8Slogwang  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15a9643ea8Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16a9643ea8Slogwang  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17a9643ea8Slogwang  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18a9643ea8Slogwang  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19a9643ea8Slogwang  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20a9643ea8Slogwang  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21a9643ea8Slogwang  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22a9643ea8Slogwang  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23a9643ea8Slogwang  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24a9643ea8Slogwang  *
25a9643ea8Slogwang  */
26a9e7dcf4Slogwang #include <assert.h>
27c506e436Sfengbojiang #include <unistd.h>
28ef5ab859S10077240 #include <sys/mman.h>
29ef5ab859S10077240 #include <errno.h>
30a9643ea8Slogwang 
31a9643ea8Slogwang #include <rte_common.h>
32a9643ea8Slogwang #include <rte_byteorder.h>
33a9643ea8Slogwang #include <rte_log.h>
34a9643ea8Slogwang #include <rte_memory.h>
35a9643ea8Slogwang #include <rte_memcpy.h>
36a9643ea8Slogwang #include <rte_memzone.h>
37a9643ea8Slogwang #include <rte_config.h>
38a9643ea8Slogwang #include <rte_eal.h>
39a9643ea8Slogwang #include <rte_pci.h>
40a9643ea8Slogwang #include <rte_mbuf.h>
41a9643ea8Slogwang #include <rte_memory.h>
42a9643ea8Slogwang #include <rte_lcore.h>
43a9643ea8Slogwang #include <rte_launch.h>
44a9643ea8Slogwang #include <rte_ethdev.h>
45a9643ea8Slogwang #include <rte_debug.h>
46a9643ea8Slogwang #include <rte_common.h>
47a9643ea8Slogwang #include <rte_ether.h>
48a9643ea8Slogwang #include <rte_malloc.h>
49a9643ea8Slogwang #include <rte_cycles.h>
50a9643ea8Slogwang #include <rte_timer.h>
51a9643ea8Slogwang #include <rte_thash.h>
52213fa7b3Slogwang #include <rte_ip.h>
53213fa7b3Slogwang #include <rte_tcp.h>
54213fa7b3Slogwang #include <rte_udp.h>
55c0f66684Sfengbojiang(姜凤波) #include <rte_eth_bond.h>
56a9643ea8Slogwang 
57a9643ea8Slogwang #include "ff_dpdk_if.h"
58a9643ea8Slogwang #include "ff_dpdk_pcap.h"
59a9643ea8Slogwang #include "ff_dpdk_kni.h"
60a9643ea8Slogwang #include "ff_config.h"
61a9643ea8Slogwang #include "ff_veth.h"
62a9643ea8Slogwang #include "ff_host_interface.h"
637abd0fb2Slogwang #include "ff_msg.h"
647abd0fb2Slogwang #include "ff_api.h"
655bf882b4S10077240 #include "ff_memory.h"
66a9643ea8Slogwang 
677b9d3e87Swhl739 #ifdef FF_KNI
68bed8feabSroot #define KNI_MBUF_MAX 2048
69bed8feabSroot #define KNI_QUEUE_SIZE 2048
70bed8feabSroot 
7110b909a1Sfengbojiang(姜凤波) int enable_kni;
72f47e38d9Slogwang static int kni_accept;
7347507c15Spengtian static int knictl_action = FF_KNICTL_ACTION_DEFAULT;
74dc42d452Swhl739 #endif
75a9643ea8Slogwang 
76df692c60Slogwang static int numa_on;
77df692c60Slogwang 
78c506e436Sfengbojiang static unsigned idle_sleep;
7959bb71f6Sfengbojiang(姜凤波) static unsigned pkt_tx_delay;
80c506e436Sfengbojiang static uint64_t usr_cb_tsc;
81a9643ea8Slogwang 
82a9643ea8Slogwang static struct rte_timer freebsd_clock;
83a9643ea8Slogwang 
84a9643ea8Slogwang // Mellanox Linux's driver key
85a9643ea8Slogwang static uint8_t default_rsskey_40bytes[40] = {
86a9643ea8Slogwang     0xd1, 0x81, 0xc6, 0x2c, 0xf7, 0xf4, 0xdb, 0x5b,
87a9643ea8Slogwang     0x19, 0x83, 0xa2, 0xfc, 0x94, 0x3e, 0x1a, 0xdb,
88a9643ea8Slogwang     0xd9, 0x38, 0x9e, 0x6b, 0xd1, 0x03, 0x9c, 0x2c,
89a9643ea8Slogwang     0xa7, 0x44, 0x99, 0xad, 0x59, 0x3d, 0x56, 0xd9,
90a9643ea8Slogwang     0xf3, 0x25, 0x3c, 0x06, 0x2a, 0xdc, 0x1f, 0xfc
91a9643ea8Slogwang };
9234e766d2S10077240 
9334e766d2S10077240 static uint8_t default_rsskey_52bytes[52] = {
9434e766d2S10077240     0x44, 0x39, 0x79, 0x6b, 0xb5, 0x4c, 0x50, 0x23,
9534e766d2S10077240     0xb6, 0x75, 0xea, 0x5b, 0x12, 0x4f, 0x9f, 0x30,
9634e766d2S10077240     0xb8, 0xa2, 0xc0, 0x3d, 0xdf, 0xdc, 0x4d, 0x02,
9734e766d2S10077240     0xa0, 0x8c, 0x9b, 0x33, 0x4a, 0xf6, 0x4a, 0x4c,
9834e766d2S10077240     0x05, 0xc6, 0xfa, 0x34, 0x39, 0x58, 0xd8, 0x55,
9934e766d2S10077240     0x7d, 0x99, 0x58, 0x3a, 0xe1, 0x38, 0xc9, 0x2e,
10034e766d2S10077240     0x81, 0x15, 0x03, 0x66
10134e766d2S10077240 };
102f41205e9Sfengbojiang 
103f41205e9Sfengbojiang static uint8_t symmetric_rsskey[52] = {
104f41205e9Sfengbojiang     0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
105f41205e9Sfengbojiang     0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
106f41205e9Sfengbojiang     0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
107f41205e9Sfengbojiang     0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
108f41205e9Sfengbojiang     0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
109f41205e9Sfengbojiang     0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
110f41205e9Sfengbojiang     0x6d, 0x5a, 0x6d, 0x5a
111f41205e9Sfengbojiang };
112f41205e9Sfengbojiang 
113f41205e9Sfengbojiang static int rsskey_len = sizeof(default_rsskey_40bytes);
114f41205e9Sfengbojiang static uint8_t *rsskey = default_rsskey_40bytes;
1155bf882b4S10077240 
116ef5ab859S10077240 struct lcore_conf lcore_conf;
1175bf882b4S10077240 
118a9643ea8Slogwang struct rte_mempool *pktmbuf_pool[NB_SOCKETS];
119aa61e4b5Sfengbojiang(姜凤波) 
120aa61e4b5Sfengbojiang(姜凤波) static pcblddr_func_t pcblddr_fun;
121eb5902d9Slogwang 
122eb5902d9Slogwang static struct rte_ring **dispatch_ring[RTE_MAX_ETHPORTS];
123a9643ea8Slogwang static dispatch_func_t packet_dispatcher;
124a9e7dcf4Slogwang 
125a9e7dcf4Slogwang static uint16_t rss_reta_size[RTE_MAX_ETHPORTS];
126c0f66684Sfengbojiang(姜凤波) 
127c0f66684Sfengbojiang(姜凤波) #define BOND_DRIVER_NAME    "net_bonding"
128ee6c3aa3Sfengbojiang(姜凤波) 
129ee6c3aa3Sfengbojiang(姜凤波) static inline int send_single_packet(struct rte_mbuf *m, uint8_t port);
1307abd0fb2Slogwang 
1310f5432bbSfengbojiang struct ff_msg_ring {
1327abd0fb2Slogwang     char ring_name[FF_MSG_NUM][RTE_RING_NAMESIZE];
1337abd0fb2Slogwang     /* ring[0] for lcore recv msg, other send */
1340f5432bbSfengbojiang     /* ring[1] for lcore send msg, other read */
1357abd0fb2Slogwang     struct rte_ring *ring[FF_MSG_NUM];
1367abd0fb2Slogwang } __rte_cache_aligned;
1377abd0fb2Slogwang 
1387abd0fb2Slogwang static struct ff_msg_ring msg_ring[RTE_MAX_LCORE];
139a9643ea8Slogwang static struct rte_mempool *message_pool;
140a9643ea8Slogwang static struct ff_dpdk_if_context *veth_ctx[RTE_MAX_ETHPORTS];
14103df98deSfengbojiang 
14203df98deSfengbojiang static struct ff_top_args ff_top_status;
143a9643ea8Slogwang static struct ff_traffic_args ff_traffic;
144a9643ea8Slogwang extern void ff_hardclock(void);
145a9643ea8Slogwang 
1467e048838Slogwang static void
ff_hardclock_job(__rte_unused struct rte_timer * timer,__rte_unused void * arg)147a9643ea8Slogwang ff_hardclock_job(__rte_unused struct rte_timer *timer,
148a9643ea8Slogwang     __rte_unused void *arg) {
1497e048838Slogwang     ff_hardclock();
150a9643ea8Slogwang     ff_update_current_ts();
151a9643ea8Slogwang }
152a9643ea8Slogwang 
153a9643ea8Slogwang struct ff_dpdk_if_context *
ff_dpdk_register_if(void * sc,void * ifp,struct ff_port_cfg * cfg)154a9643ea8Slogwang ff_dpdk_register_if(void *sc, void *ifp, struct ff_port_cfg *cfg)
155a9643ea8Slogwang {
156a9643ea8Slogwang     struct ff_dpdk_if_context *ctx;
157a9643ea8Slogwang 
158a9643ea8Slogwang     ctx = calloc(1, sizeof(struct ff_dpdk_if_context));
159a9643ea8Slogwang     if (ctx == NULL)
160a9643ea8Slogwang         return NULL;
161a9643ea8Slogwang 
162a9643ea8Slogwang     ctx->sc = sc;
163a9643ea8Slogwang     ctx->ifp = ifp;
164213fa7b3Slogwang     ctx->port_id = cfg->port_id;
165a9643ea8Slogwang     ctx->hw_features = cfg->hw_features;
166a9643ea8Slogwang 
167a9643ea8Slogwang     return ctx;
168a9643ea8Slogwang }
169a9643ea8Slogwang 
170a9643ea8Slogwang void
ff_dpdk_deregister_if(struct ff_dpdk_if_context * ctx)171a9643ea8Slogwang ff_dpdk_deregister_if(struct ff_dpdk_if_context *ctx)
172a9643ea8Slogwang {
173a9643ea8Slogwang     free(ctx);
174a9643ea8Slogwang }
175a9643ea8Slogwang 
176a9643ea8Slogwang static void
check_all_ports_link_status(void)177a9643ea8Slogwang check_all_ports_link_status(void)
178a9643ea8Slogwang {
179a9643ea8Slogwang     #define CHECK_INTERVAL 100 /* 100ms */
180a9643ea8Slogwang     #define MAX_CHECK_TIME 90  /* 9s (90 * 100ms) in total */
1812bfe3f2eSlogwang 
1822bfe3f2eSlogwang     uint16_t portid;
183a9643ea8Slogwang     uint8_t count, all_ports_up, print_flag = 0;
184a9643ea8Slogwang     struct rte_eth_link link;
185a9643ea8Slogwang 
186a9643ea8Slogwang     printf("\nChecking link status");
187a9643ea8Slogwang     fflush(stdout);
188a9643ea8Slogwang 
189a9643ea8Slogwang     int i, nb_ports;
190a9643ea8Slogwang     nb_ports = ff_global_cfg.dpdk.nb_ports;
191a9643ea8Slogwang     for (count = 0; count <= MAX_CHECK_TIME; count++) {
192a9643ea8Slogwang         all_ports_up = 1;
1932bfe3f2eSlogwang         for (i = 0; i < nb_ports; i++) {
194a9643ea8Slogwang             uint16_t portid = ff_global_cfg.dpdk.portid_list[i];
195a9643ea8Slogwang             memset(&link, 0, sizeof(link));
196a9643ea8Slogwang             rte_eth_link_get_nowait(portid, &link);
197a9643ea8Slogwang 
198a9643ea8Slogwang             /* print link status if flag set */
199a9643ea8Slogwang             if (print_flag == 1) {
200a9643ea8Slogwang                 if (link.link_status) {
201a9643ea8Slogwang                     printf("Port %d Link Up - speed %u "
202a9643ea8Slogwang                         "Mbps - %s\n", (int)portid,
203a9643ea8Slogwang                         (unsigned)link.link_speed,
204a9643ea8Slogwang                         (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
205a9643ea8Slogwang                         ("full-duplex") : ("half-duplex\n"));
206a9643ea8Slogwang                 } else {
207a9643ea8Slogwang                     printf("Port %d Link Down\n", (int)portid);
208a9643ea8Slogwang                 }
209a9643ea8Slogwang                 continue;
210a9643ea8Slogwang             }
211a9643ea8Slogwang             /* clear all_ports_up flag if any link down */
212a9643ea8Slogwang             if (link.link_status == 0) {
213a9643ea8Slogwang                 all_ports_up = 0;
214a9643ea8Slogwang                 break;
215a9643ea8Slogwang             }
216a9643ea8Slogwang         }
217a9643ea8Slogwang 
218a9643ea8Slogwang         /* after finally printing all link status, get out */
219a9643ea8Slogwang         if (print_flag == 1)
220a9643ea8Slogwang             break;
221a9643ea8Slogwang 
222a9643ea8Slogwang         if (all_ports_up == 0) {
223a9643ea8Slogwang             printf(".");
224a9643ea8Slogwang             fflush(stdout);
225a9643ea8Slogwang             rte_delay_ms(CHECK_INTERVAL);
226a9643ea8Slogwang         }
227a9643ea8Slogwang 
228a9643ea8Slogwang         /* set the print_flag if all ports up or timeout */
229a9643ea8Slogwang         if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
230a9643ea8Slogwang             print_flag = 1;
231a9643ea8Slogwang             printf("done\n");
232a9643ea8Slogwang         }
233a9643ea8Slogwang     }
234a9643ea8Slogwang }
235a9643ea8Slogwang 
236a9643ea8Slogwang static int
init_lcore_conf(void)237a9643ea8Slogwang init_lcore_conf(void)
238d30ea906Sjfb8856606 {
23980a6164cSYuYang     uint8_t nb_dev_ports = rte_eth_dev_count_avail();
240a9643ea8Slogwang     if (nb_dev_ports == 0) {
241a9643ea8Slogwang         rte_exit(EXIT_FAILURE, "No probed ethernet devices\n");
24285aab0a6Slogwang     }
24380a6164cSYuYang 
24480a6164cSYuYang     if (ff_global_cfg.dpdk.max_portid >= nb_dev_ports) {
24580a6164cSYuYang         rte_exit(EXIT_FAILURE, "this machine doesn't have port %d.\n",
24680a6164cSYuYang                  ff_global_cfg.dpdk.max_portid);
247a9643ea8Slogwang     }
24885aab0a6Slogwang 
249a9643ea8Slogwang     lcore_conf.port_cfgs = ff_global_cfg.dpdk.port_cfgs;
250a9643ea8Slogwang     lcore_conf.proc_id = ff_global_cfg.dpdk.proc_id;
251a9643ea8Slogwang 
252df692c60Slogwang     uint16_t socket_id = 0;
253a9643ea8Slogwang     if (numa_on) {
254a9643ea8Slogwang         socket_id = rte_lcore_to_socket_id(rte_lcore_id());
255a9643ea8Slogwang     }
256a9643ea8Slogwang 
257a9643ea8Slogwang     lcore_conf.socket_id = socket_id;
25880a6164cSYuYang 
2594418919fSjohnjiang     uint16_t lcore_id = ff_global_cfg.dpdk.proc_lcore[lcore_conf.proc_id];
2604418919fSjohnjiang     if (!rte_lcore_is_enabled(lcore_id)) {
2614418919fSjohnjiang         rte_exit(EXIT_FAILURE, "lcore %u unavailable\n", lcore_id);
2624418919fSjohnjiang     }
26380a6164cSYuYang 
26480a6164cSYuYang     int j;
26580a6164cSYuYang     for (j = 0; j < ff_global_cfg.dpdk.nb_ports; ++j) {
26680a6164cSYuYang         uint16_t port_id = ff_global_cfg.dpdk.portid_list[j];
26780a6164cSYuYang         struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[port_id];
26880a6164cSYuYang 
26980a6164cSYuYang         int queueid = -1;
27080a6164cSYuYang         int i;
27180a6164cSYuYang         for (i = 0; i < pconf->nb_lcores; i++) {
27280a6164cSYuYang             if (pconf->lcore_list[i] == lcore_id) {
27380a6164cSYuYang                 queueid = i;
27480a6164cSYuYang             }
27580a6164cSYuYang         }
276a9643ea8Slogwang         if (queueid < 0) {
277a9643ea8Slogwang             continue;
27880a6164cSYuYang         }
279a9643ea8Slogwang         printf("lcore: %u, port: %u, queue: %u\n", lcore_id, port_id, queueid);
280a9643ea8Slogwang         uint16_t nb_rx_queue = lcore_conf.nb_rx_queue;
28180a6164cSYuYang         lcore_conf.rx_queue_list[nb_rx_queue].port_id = port_id;
282a9643ea8Slogwang         lcore_conf.rx_queue_list[nb_rx_queue].queue_id = queueid;
283a9643ea8Slogwang         lcore_conf.nb_rx_queue++;
28480a6164cSYuYang 
28585aab0a6Slogwang         lcore_conf.tx_queue_id[port_id] = queueid;
28685aab0a6Slogwang         lcore_conf.tx_port_id[lcore_conf.nb_tx_port] = port_id;
287a9643ea8Slogwang         lcore_conf.nb_tx_port++;
288819aafb6Sjinhao2 
289819aafb6Sjinhao2         /* Enable pcap dump */
290819aafb6Sjinhao2         if (ff_global_cfg.pcap.enable) {
291819aafb6Sjinhao2             ff_enable_pcap(ff_global_cfg.pcap.save_path, ff_global_cfg.pcap.snap_len);
292819aafb6Sjinhao2         }
29380a6164cSYuYang 
294a9643ea8Slogwang         lcore_conf.nb_queue_list[port_id] = pconf->nb_lcores;
295a9643ea8Slogwang     }
296eb5902d9Slogwang 
297eb5902d9Slogwang     if (lcore_conf.nb_rx_queue == 0) {
298eb5902d9Slogwang         rte_exit(EXIT_FAILURE, "lcore %u has nothing to do\n", lcore_id);
299eb5902d9Slogwang     }
300a9643ea8Slogwang 
301a9643ea8Slogwang     return 0;
302a9643ea8Slogwang }
303a9643ea8Slogwang 
304a9643ea8Slogwang static int
init_mem_pool(void)305a9643ea8Slogwang init_mem_pool(void)
306a9643ea8Slogwang {
307a9643ea8Slogwang     uint8_t nb_ports = ff_global_cfg.dpdk.nb_ports;
308a9643ea8Slogwang     uint32_t nb_lcores = ff_global_cfg.dpdk.nb_procs;
309a9643ea8Slogwang     uint32_t nb_tx_queue = nb_lcores;
310c0f66684Sfengbojiang(姜凤波)     uint32_t nb_rx_queue = lcore_conf.nb_rx_queue * nb_lcores;
311a9643ea8Slogwang     uint16_t max_portid = ff_global_cfg.dpdk.max_portid;
31216d80a6dSfengbojiang(姜凤波) 
313c0f66684Sfengbojiang(姜凤波)     unsigned nb_mbuf = RTE_ALIGN_CEIL (
314c0f66684Sfengbojiang(姜凤波)         (nb_rx_queue * (max_portid + 1) * 2 * RX_QUEUE_SIZE          +
315c0f66684Sfengbojiang(姜凤波)         nb_ports * (max_portid + 1) * 2 * nb_lcores * MAX_PKT_BURST    +
316bed8feabSroot         nb_ports * (max_portid + 1) * 2 * nb_tx_queue * TX_QUEUE_SIZE  +
3177b9d3e87Swhl739         nb_lcores * MEMPOOL_CACHE_SIZE +
318bed8feabSroot #ifdef FF_KNI
319bed8feabSroot         nb_ports * KNI_MBUF_MAX +
3207b9d3e87Swhl739         nb_ports * KNI_QUEUE_SIZE +
321eb5902d9Slogwang #endif
322a9643ea8Slogwang         nb_lcores * nb_ports * DISPATCH_RING_SIZE),
323a9643ea8Slogwang         (unsigned)8192);
324a9643ea8Slogwang 
325a9643ea8Slogwang     unsigned socketid = 0;
326a9643ea8Slogwang     uint16_t i, lcore_id;
327a9643ea8Slogwang     char s[64];
32880a6164cSYuYang 
32980a6164cSYuYang     for (i = 0; i < ff_global_cfg.dpdk.nb_procs; i++) {
330a9643ea8Slogwang         lcore_id = ff_global_cfg.dpdk.proc_lcore[i];
331a9643ea8Slogwang         if (numa_on) {
332a9643ea8Slogwang             socketid = rte_lcore_to_socket_id(lcore_id);
333a9643ea8Slogwang         }
334a9643ea8Slogwang 
335a9643ea8Slogwang         if (socketid >= NB_SOCKETS) {
336a9643ea8Slogwang             rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is out of range %d\n",
337a9643ea8Slogwang                 socketid, i, NB_SOCKETS);
338a9643ea8Slogwang         }
339a9643ea8Slogwang 
340a9643ea8Slogwang         if (pktmbuf_pool[socketid] != NULL) {
341a9643ea8Slogwang             continue;
342a9643ea8Slogwang         }
343a9643ea8Slogwang 
344a9643ea8Slogwang         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
345a9643ea8Slogwang             snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
346a9643ea8Slogwang             pktmbuf_pool[socketid] =
347a9643ea8Slogwang                 rte_pktmbuf_pool_create(s, nb_mbuf,
348a9643ea8Slogwang                     MEMPOOL_CACHE_SIZE, 0,
349a9643ea8Slogwang                     RTE_MBUF_DEFAULT_BUF_SIZE, socketid);
350a9643ea8Slogwang         } else {
351a9643ea8Slogwang             snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
352a9643ea8Slogwang             pktmbuf_pool[socketid] = rte_mempool_lookup(s);
353a9643ea8Slogwang         }
354a9643ea8Slogwang 
355a9643ea8Slogwang         if (pktmbuf_pool[socketid] == NULL) {
356a9643ea8Slogwang             rte_exit(EXIT_FAILURE, "Cannot create mbuf pool on socket %d\n", socketid);
357a9643ea8Slogwang         } else {
358a9643ea8Slogwang             printf("create mbuf pool on socket %d\n", socketid);
359ef5ab859S10077240         }
3605bf882b4S10077240 
36116d80a6dSfengbojiang(姜凤波) #ifdef FF_USE_PAGE_ARRAY
362ef5ab859S10077240         nb_mbuf = RTE_ALIGN_CEIL (
363ef5ab859S10077240             nb_ports*nb_lcores*MAX_PKT_BURST    +
364ef5ab859S10077240             nb_ports*nb_tx_queue*TX_QUEUE_SIZE  +
365ef5ab859S10077240             nb_lcores*MEMPOOL_CACHE_SIZE,
3665bf882b4S10077240             (unsigned)4096);
367ef5ab859S10077240         ff_init_ref_pool(nb_mbuf, socketid);
368a9643ea8Slogwang #endif
369a9643ea8Slogwang     }
370a9643ea8Slogwang 
371a9643ea8Slogwang     return 0;
372a9643ea8Slogwang }
3737abd0fb2Slogwang 
3747abd0fb2Slogwang static struct rte_ring *
create_ring(const char * name,unsigned count,int socket_id,unsigned flags)3757abd0fb2Slogwang create_ring(const char *name, unsigned count, int socket_id, unsigned flags)
3767abd0fb2Slogwang {
3777abd0fb2Slogwang     struct rte_ring *ring;
3785523938cSroot 
3795523938cSroot     if (name == NULL) {
3805523938cSroot         rte_exit(EXIT_FAILURE, "create ring failed, no name!\n");
3817abd0fb2Slogwang     }
3827abd0fb2Slogwang 
3835523938cSroot     if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
3847abd0fb2Slogwang         ring = rte_ring_create(name, count, socket_id, flags);
3855523938cSroot     } else {
3867abd0fb2Slogwang         ring = rte_ring_lookup(name);
3875523938cSroot     }
3885523938cSroot 
3895523938cSroot     if (ring == NULL) {
3905523938cSroot         rte_exit(EXIT_FAILURE, "create ring:%s failed!\n", name);
3915523938cSroot     }
3925523938cSroot 
3937abd0fb2Slogwang     return ring;
3947abd0fb2Slogwang }
395a9643ea8Slogwang 
396eb5902d9Slogwang static int
init_dispatch_ring(void)397a9643ea8Slogwang init_dispatch_ring(void)
398257bb980SYuYang {
399a9643ea8Slogwang     int j;
400257bb980SYuYang     char name_buf[RTE_RING_NAMESIZE];
401a9643ea8Slogwang     int queueid;
402a9643ea8Slogwang 
403a9643ea8Slogwang     unsigned socketid = lcore_conf.socket_id;
404a9643ea8Slogwang 
40580a6164cSYuYang     /* Create ring according to ports actually being used. */
406c15aae71Swhl739     int nb_ports = ff_global_cfg.dpdk.nb_ports;
407257bb980SYuYang     for (j = 0; j < nb_ports; j++) {
408257bb980SYuYang         uint16_t portid = ff_global_cfg.dpdk.portid_list[j];
409257bb980SYuYang         struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[portid];
410eb5902d9Slogwang         int nb_queues = pconf->nb_lcores;
411257bb980SYuYang         if (dispatch_ring[portid] == NULL) {
412a9643ea8Slogwang             snprintf(name_buf, RTE_RING_NAMESIZE, "ring_ptr_p%d", portid);
413eb5902d9Slogwang 
414257bb980SYuYang             dispatch_ring[portid] = rte_zmalloc(name_buf,
415257bb980SYuYang                 sizeof(struct rte_ring *) * nb_queues,
416eb5902d9Slogwang                 RTE_CACHE_LINE_SIZE);
417257bb980SYuYang             if (dispatch_ring[portid] == NULL) {
418257bb980SYuYang                 rte_exit(EXIT_FAILURE, "rte_zmalloc(%s (struct rte_ring*)) "
419257bb980SYuYang                     "failed\n", name_buf);
420257bb980SYuYang             }
421257bb980SYuYang         }
422257bb980SYuYang 
423eb5902d9Slogwang         for(queueid = 0; queueid < nb_queues; ++queueid) {
424eb5902d9Slogwang             snprintf(name_buf, RTE_RING_NAMESIZE, "dispatch_ring_p%d_q%d",
425eb5902d9Slogwang                 portid, queueid);
426eb5902d9Slogwang             dispatch_ring[portid][queueid] = create_ring(name_buf,
427a9643ea8Slogwang                 DISPATCH_RING_SIZE, socketid, RING_F_SC_DEQ);
428eb5902d9Slogwang 
4297abd0fb2Slogwang             if (dispatch_ring[portid][queueid] == NULL)
430a9643ea8Slogwang                 rte_panic("create ring:%s failed!\n", name_buf);
4317abd0fb2Slogwang 
432eb5902d9Slogwang             printf("create ring:%s success, %u ring entries are now free!\n",
433a9643ea8Slogwang                 name_buf, rte_ring_free_count(dispatch_ring[portid][queueid]));
434a9643ea8Slogwang         }
435a9643ea8Slogwang     }
436a9643ea8Slogwang 
437a9643ea8Slogwang     return 0;
438a9643ea8Slogwang }
4397abd0fb2Slogwang 
4407abd0fb2Slogwang static void
ff_msg_init(struct rte_mempool * mp,void * opaque_arg,void * obj,unsigned i)4417abd0fb2Slogwang ff_msg_init(struct rte_mempool *mp,
4427abd0fb2Slogwang     __attribute__((unused)) void *opaque_arg,
4437abd0fb2Slogwang     void *obj, __attribute__((unused)) unsigned i)
4447abd0fb2Slogwang {
445df6ad731Slogwang     struct ff_msg *msg = (struct ff_msg *)obj;
4467abd0fb2Slogwang     msg->msg_type = FF_UNKNOWN;
4477abd0fb2Slogwang     msg->buf_addr = (char *)msg + sizeof(struct ff_msg);
44832ff8fdaSfengbojiang     msg->buf_len = mp->elt_size - sizeof(struct ff_msg);
44932ff8fdaSfengbojiang     msg->original_buf = NULL;
4507abd0fb2Slogwang     msg->original_buf_len = 0;
4517abd0fb2Slogwang }
4527abd0fb2Slogwang 
4537abd0fb2Slogwang static int
init_msg_ring(void)4547abd0fb2Slogwang init_msg_ring(void)
4556194fcd2Sfengbojiang(姜凤波) {
4567abd0fb2Slogwang     uint16_t i, j;
4577abd0fb2Slogwang     uint16_t nb_procs = ff_global_cfg.dpdk.nb_procs;
4587abd0fb2Slogwang     unsigned socketid = lcore_conf.socket_id;
4597abd0fb2Slogwang 
4607abd0fb2Slogwang     /* Create message buffer pool */
4617abd0fb2Slogwang     if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
4627abd0fb2Slogwang         message_pool = rte_mempool_create(FF_MSG_POOL,
4637abd0fb2Slogwang            MSG_RING_SIZE * 2 * nb_procs,
4647abd0fb2Slogwang            MAX_MSG_BUF_SIZE, MSG_RING_SIZE / 2, 0,
4657abd0fb2Slogwang            NULL, NULL, ff_msg_init, NULL,
4667abd0fb2Slogwang            socketid, 0);
4677abd0fb2Slogwang     } else {
4687abd0fb2Slogwang         message_pool = rte_mempool_lookup(FF_MSG_POOL);
4697abd0fb2Slogwang     }
4707abd0fb2Slogwang 
4717abd0fb2Slogwang     if (message_pool == NULL) {
4727abd0fb2Slogwang         rte_panic("Create msg mempool failed\n");
4737abd0fb2Slogwang     }
4747abd0fb2Slogwang 
4757abd0fb2Slogwang     for(i = 0; i < nb_procs; ++i) {
4767abd0fb2Slogwang         snprintf(msg_ring[i].ring_name[0], RTE_RING_NAMESIZE,
4777abd0fb2Slogwang             "%s%u", FF_MSG_RING_IN, i);
4787abd0fb2Slogwang         msg_ring[i].ring[0] = create_ring(msg_ring[i].ring_name[0],
4797abd0fb2Slogwang             MSG_RING_SIZE, socketid, RING_F_SP_ENQ | RING_F_SC_DEQ);
4807abd0fb2Slogwang         if (msg_ring[i].ring[0] == NULL)
4817abd0fb2Slogwang             rte_panic("create ring::%s failed!\n", msg_ring[i].ring_name[0]);
4820f5432bbSfengbojiang 
4836194fcd2Sfengbojiang(姜凤波)         for (j = FF_SYSCTL; j < FF_MSG_NUM; j++) {
4846194fcd2Sfengbojiang(姜凤波)             snprintf(msg_ring[i].ring_name[j], RTE_RING_NAMESIZE,
4856194fcd2Sfengbojiang(姜凤波)                 "%s%u_%u", FF_MSG_RING_OUT, i, j);
4867abd0fb2Slogwang             msg_ring[i].ring[j] = create_ring(msg_ring[i].ring_name[j],
4876194fcd2Sfengbojiang(姜凤波)                 MSG_RING_SIZE, socketid, RING_F_SP_ENQ | RING_F_SC_DEQ);
4886194fcd2Sfengbojiang(姜凤波)             if (msg_ring[i].ring[j] == NULL)
4896194fcd2Sfengbojiang(姜凤波)                 rte_panic("create ring::%s failed!\n", msg_ring[i].ring_name[j]);
4907abd0fb2Slogwang         }
4917abd0fb2Slogwang     }
4927abd0fb2Slogwang 
4937abd0fb2Slogwang     return 0;
4947abd0fb2Slogwang }
495dc42d452Swhl739 
49647507c15Spengtian #ifdef FF_KNI
49747507c15Spengtian 
get_kni_action(const char * c)49847507c15Spengtian static enum FF_KNICTL_CMD get_kni_action(const char *c){
49947507c15Spengtian     if (!c)
50047507c15Spengtian         return FF_KNICTL_ACTION_DEFAULT;
50147507c15Spengtian     if (0 == strcasecmp(c, "alltokni")){
50247507c15Spengtian         return FF_KNICTL_ACTION_ALL_TO_KNI;
50347507c15Spengtian     } else  if (0 == strcasecmp(c, "alltoff")){
50447507c15Spengtian         return FF_KNICTL_ACTION_ALL_TO_FF;
50547507c15Spengtian     } else if (0 == strcasecmp(c, "default")){
50647507c15Spengtian         return FF_KNICTL_ACTION_DEFAULT;
50747507c15Spengtian     } else {
50847507c15Spengtian         return FF_KNICTL_ACTION_DEFAULT;
50947507c15Spengtian     }
51047507c15Spengtian }
511a9643ea8Slogwang 
512a9643ea8Slogwang static int
init_kni(void)513a9643ea8Slogwang init_kni(void)
514d30ea906Sjfb8856606 {
515f47e38d9Slogwang     int nb_ports = rte_eth_dev_count_avail();
516a9643ea8Slogwang     kni_accept = 0;
517f47e38d9Slogwang     if(strcasecmp(ff_global_cfg.kni.method, "accept") == 0)
518a9643ea8Slogwang         kni_accept = 1;
51947507c15Spengtian 
52047507c15Spengtian     knictl_action = get_kni_action(ff_global_cfg.kni.kni_action);
521f47e38d9Slogwang 
522f47e38d9Slogwang     ff_kni_init(nb_ports, ff_global_cfg.kni.tcp_port,
523a9643ea8Slogwang         ff_global_cfg.kni.udp_port);
524a9643ea8Slogwang 
525a9643ea8Slogwang     unsigned socket_id = lcore_conf.socket_id;
526a9643ea8Slogwang     struct rte_mempool *mbuf_pool = pktmbuf_pool[socket_id];
527a9643ea8Slogwang 
528a9643ea8Slogwang     nb_ports = ff_global_cfg.dpdk.nb_ports;
529a9643ea8Slogwang     int i, ret;
53080a6164cSYuYang     for (i = 0; i < nb_ports; i++) {
531bed8feabSroot         uint16_t port_id = ff_global_cfg.dpdk.portid_list[i];
532a9643ea8Slogwang         ff_kni_alloc(port_id, socket_id, mbuf_pool, KNI_QUEUE_SIZE);
533a9643ea8Slogwang     }
534a9643ea8Slogwang 
535a9643ea8Slogwang     return 0;
536dc42d452Swhl739 }
537a9643ea8Slogwang #endif
5382474e163SHawker 
5392474e163SHawker //RSS reta update will failed when enable flow isolate
540a9e7dcf4Slogwang #ifndef FF_FLOW_ISOLATE
5412bfe3f2eSlogwang static void
set_rss_table(uint16_t port_id,uint16_t reta_size,uint16_t nb_queues)542a9e7dcf4Slogwang set_rss_table(uint16_t port_id, uint16_t reta_size, uint16_t nb_queues)
543a9e7dcf4Slogwang {
544a9e7dcf4Slogwang     if (reta_size == 0) {
545a9e7dcf4Slogwang         return;
546a9e7dcf4Slogwang     }
547a9e7dcf4Slogwang 
548a9e7dcf4Slogwang     int reta_conf_size = RTE_MAX(1, reta_size / RTE_RETA_GROUP_SIZE);
549a9e7dcf4Slogwang     struct rte_eth_rss_reta_entry64 reta_conf[reta_conf_size];
550a9e7dcf4Slogwang 
551a9e7dcf4Slogwang     /* config HW indirection table */
552a9e7dcf4Slogwang     unsigned i, j, hash=0;
553a9e7dcf4Slogwang     for (i = 0; i < reta_conf_size; i++) {
554a9e7dcf4Slogwang         reta_conf[i].mask = ~0ULL;
555a9e7dcf4Slogwang         for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) {
556a9e7dcf4Slogwang             reta_conf[i].reta[j] = hash++ % nb_queues;
557a9e7dcf4Slogwang         }
558a9e7dcf4Slogwang     }
559a9e7dcf4Slogwang 
560a9e7dcf4Slogwang     if (rte_eth_dev_rss_reta_update(port_id, reta_conf, reta_size)) {
561a9e7dcf4Slogwang         rte_exit(EXIT_FAILURE, "port[%d], failed to update rss table\n",
562a9e7dcf4Slogwang             port_id);
563a9e7dcf4Slogwang     }
5642474e163SHawker }
565a9e7dcf4Slogwang #endif
566a9643ea8Slogwang 
567a9643ea8Slogwang static int
init_port_start(void)568a9643ea8Slogwang init_port_start(void)
569a9643ea8Slogwang {
570c2eceaadSXiaozhou Liu     int nb_ports = ff_global_cfg.dpdk.nb_ports;
571c2eceaadSXiaozhou Liu     unsigned socketid = 0;
572c0f66684Sfengbojiang(姜凤波)     struct rte_mempool *mbuf_pool;
573a9643ea8Slogwang     uint16_t i, j;
574a9643ea8Slogwang 
575c0f66684Sfengbojiang(姜凤波)     for (i = 0; i < nb_ports; i++) {
576c0f66684Sfengbojiang(姜凤波)         uint16_t port_id, u_port_id = ff_global_cfg.dpdk.portid_list[i];
57780a6164cSYuYang         struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[u_port_id];
578a9643ea8Slogwang         uint16_t nb_queues = pconf->nb_lcores;
579c0f66684Sfengbojiang(姜凤波) 
580c0f66684Sfengbojiang(姜凤波)         for (j=0; j<=pconf->nb_slaves; j++) {
581c0f66684Sfengbojiang(姜凤波)             if (j < pconf->nb_slaves) {
582c0f66684Sfengbojiang(姜凤波)                 port_id = pconf->slave_portid_list[j];
583c0f66684Sfengbojiang(姜凤波)                 printf("To init %s's %d'st slave port[%d]\n",
584c0f66684Sfengbojiang(姜凤波)                         ff_global_cfg.dpdk.bond_cfgs->name,
585c0f66684Sfengbojiang(姜凤波)                         j, port_id);
586c0f66684Sfengbojiang(姜凤波)             } else {
587c0f66684Sfengbojiang(姜凤波)                 port_id = u_port_id;
588c0f66684Sfengbojiang(姜凤波)             }
589a9643ea8Slogwang 
590e8591dc5Sfengbojiang(姜凤波)             struct rte_eth_dev_info dev_info;
591e8591dc5Sfengbojiang(姜凤波)             struct rte_eth_conf port_conf = {0};
592e8591dc5Sfengbojiang(姜凤波)             struct rte_eth_rxconf rxq_conf;
593e8591dc5Sfengbojiang(姜凤波)             struct rte_eth_txconf txq_conf;
5944418919fSjohnjiang 
5954418919fSjohnjiang             int ret = rte_eth_dev_info_get(port_id, &dev_info);
5964418919fSjohnjiang             if (ret != 0)
5974418919fSjohnjiang                 rte_exit(EXIT_FAILURE,
5984418919fSjohnjiang                     "Error during getting device (port %u) info: %s\n",
599a9643ea8Slogwang                     port_id, strerror(-ret));
60080a6164cSYuYang 
601a9643ea8Slogwang             if (nb_queues > dev_info.max_rx_queues) {
60280a6164cSYuYang                 rte_exit(EXIT_FAILURE, "num_procs[%d] bigger than max_rx_queues[%d]\n",
603a9643ea8Slogwang                     nb_queues,
604a9643ea8Slogwang                     dev_info.max_rx_queues);
605a9643ea8Slogwang             }
60680a6164cSYuYang 
607a9643ea8Slogwang             if (nb_queues > dev_info.max_tx_queues) {
60880a6164cSYuYang                 rte_exit(EXIT_FAILURE, "num_procs[%d] bigger than max_tx_queues[%d]\n",
609a9643ea8Slogwang                     nb_queues,
610a9643ea8Slogwang                     dev_info.max_tx_queues);
611a9643ea8Slogwang             }
6124418919fSjohnjiang 
613c9b3c75aSfengbojiang(姜凤波)             struct rte_ether_addr addr;
614c9b3c75aSfengbojiang(姜凤波)             rte_eth_macaddr_get(port_id, &addr);
615c9b3c75aSfengbojiang(姜凤波)             printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
616c9b3c75aSfengbojiang(姜凤波)                        " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
617c9b3c75aSfengbojiang(姜凤波)                     (unsigned)port_id,
618c9b3c75aSfengbojiang(姜凤波)                     addr.addr_bytes[0], addr.addr_bytes[1],
619c9b3c75aSfengbojiang(姜凤波)                     addr.addr_bytes[2], addr.addr_bytes[3],
620c9b3c75aSfengbojiang(姜凤波)                     addr.addr_bytes[4], addr.addr_bytes[5]);
621c9b3c75aSfengbojiang(姜凤波) 
6224418919fSjohnjiang             rte_memcpy(pconf->mac,
623c9b3c75aSfengbojiang(姜凤波)                 addr.addr_bytes, RTE_ETHER_ADDR_LEN);
624213fa7b3Slogwang 
625d30ea906Sjfb8856606             /* Set RSS mode */
626213fa7b3Slogwang             uint64_t default_rss_hf = ETH_RSS_PROTO_MASK;
627d30ea906Sjfb8856606             port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
62834e766d2S10077240             port_conf.rx_adv_conf.rss_conf.rss_hf = default_rss_hf;
629f41205e9Sfengbojiang             if (dev_info.hash_key_size == 52) {
630f41205e9Sfengbojiang                 rsskey = default_rsskey_52bytes;
63134e766d2S10077240                 rsskey_len = 52;
632f41205e9Sfengbojiang             }
633f41205e9Sfengbojiang             if (ff_global_cfg.dpdk.symmetric_rss) {
634f41205e9Sfengbojiang                 printf("Use symmetric Receive-side Scaling(RSS) key\n");
635f41205e9Sfengbojiang                 rsskey = symmetric_rsskey;
636f41205e9Sfengbojiang             }
637f41205e9Sfengbojiang             port_conf.rx_adv_conf.rss_conf.rss_key = rsskey;
638d30ea906Sjfb8856606             port_conf.rx_adv_conf.rss_conf.rss_key_len = rsskey_len;
639d30ea906Sjfb8856606             port_conf.rx_adv_conf.rss_conf.rss_hf &= dev_info.flow_type_rss_offloads;
640d30ea906Sjfb8856606             if (port_conf.rx_adv_conf.rss_conf.rss_hf !=
641d30ea906Sjfb8856606                     ETH_RSS_PROTO_MASK) {
642d30ea906Sjfb8856606                 printf("Port %u modified RSS hash function based on hardware support,"
643d30ea906Sjfb8856606                         "requested:%#"PRIx64" configured:%#"PRIx64"\n",
644d30ea906Sjfb8856606                         port_id, default_rss_hf,
645d30ea906Sjfb8856606                         port_conf.rx_adv_conf.rss_conf.rss_hf);
646d30ea906Sjfb8856606             }
647d30ea906Sjfb8856606 
648d30ea906Sjfb8856606             if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) {
649d30ea906Sjfb8856606                 port_conf.txmode.offloads |=
650d30ea906Sjfb8856606                     DEV_TX_OFFLOAD_MBUF_FAST_FREE;
651213fa7b3Slogwang             }
652213fa7b3Slogwang 
65364abcf71Slogwang             /* Set Rx VLAN stripping */
654213fa7b3Slogwang             if (ff_global_cfg.dpdk.vlan_strip) {
655d30ea906Sjfb8856606                 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP) {
656213fa7b3Slogwang                     port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
65764abcf71Slogwang                 }
658213fa7b3Slogwang             }
659213fa7b3Slogwang 
660e4b44391Sroot             /* Enable HW CRC stripping */
661213fa7b3Slogwang             port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_KEEP_CRC;
662213fa7b3Slogwang 
663213fa7b3Slogwang             /* FIXME: Enable TCP LRO ?*/
664213fa7b3Slogwang             #if 0
665213fa7b3Slogwang             if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) {
666d30ea906Sjfb8856606                 printf("LRO is supported\n");
66780a6164cSYuYang                 port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_TCP_LRO;
668213fa7b3Slogwang                 pconf->hw_features.rx_lro = 1;
669213fa7b3Slogwang             }
670213fa7b3Slogwang             #endif
671213fa7b3Slogwang 
672213fa7b3Slogwang             /* Set Rx checksum checking */
673213fa7b3Slogwang             if ((dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) &&
674213fa7b3Slogwang                 (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) &&
675213fa7b3Slogwang                 (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)) {
676d30ea906Sjfb8856606                 printf("RX checksum offload supported\n");
67780a6164cSYuYang                 port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CHECKSUM;
678213fa7b3Slogwang                 pconf->hw_features.rx_csum = 1;
679213fa7b3Slogwang             }
6803a3642c7SJayath Sathyanarayana 
681213fa7b3Slogwang             if (ff_global_cfg.dpdk.tx_csum_offoad_skip == 0) {
682213fa7b3Slogwang                 if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)) {
683d3f2221cSfengbojiang(姜凤波)                     printf("TX ip checksum offload supported\n");
68480a6164cSYuYang                     port_conf.txmode.offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM;
685213fa7b3Slogwang                     pconf->hw_features.tx_csum_ip = 1;
686213fa7b3Slogwang                 }
687213fa7b3Slogwang 
688213fa7b3Slogwang                 if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) &&
689213fa7b3Slogwang                     (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)) {
690d3f2221cSfengbojiang(姜凤波)                     printf("TX TCP&UDP checksum offload supported\n");
69180a6164cSYuYang                     port_conf.txmode.offloads |= DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM;
692213fa7b3Slogwang                     pconf->hw_features.tx_csum_l4 = 1;
6933a3642c7SJayath Sathyanarayana                 }
6943a3642c7SJayath Sathyanarayana             } else {
6953a3642c7SJayath Sathyanarayana                 printf("TX checksum offoad is disabled\n");
696213fa7b3Slogwang             }
697213fa7b3Slogwang 
698213fa7b3Slogwang             if (ff_global_cfg.dpdk.tso) {
699213fa7b3Slogwang                 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) {
700d3f2221cSfengbojiang(姜凤波)                     printf("TSO is supported\n");
70180a6164cSYuYang                     port_conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_TSO;
702213fa7b3Slogwang                     pconf->hw_features.tx_tso = 1;
703213fa7b3Slogwang                 }
704213fa7b3Slogwang             } else {
705213fa7b3Slogwang                 printf("TSO is disabled\n");
706213fa7b3Slogwang             }
707a9e7dcf4Slogwang 
708a9e7dcf4Slogwang             if (dev_info.reta_size) {
709a9e7dcf4Slogwang                 /* reta size must be power of 2 */
710a9e7dcf4Slogwang                 assert((dev_info.reta_size & (dev_info.reta_size - 1)) == 0);
711a9e7dcf4Slogwang 
712a9e7dcf4Slogwang                 rss_reta_size[port_id] = dev_info.reta_size;
713a9e7dcf4Slogwang                 printf("port[%d]: rss table size: %d\n", port_id,
714a9e7dcf4Slogwang                     dev_info.reta_size);
715a9e7dcf4Slogwang             }
716a9643ea8Slogwang 
717144c6bcdSlogwang             if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
718a9643ea8Slogwang                 continue;
719a9643ea8Slogwang             }
7204418919fSjohnjiang 
721a9643ea8Slogwang             ret = rte_eth_dev_configure(port_id, nb_queues, nb_queues, &port_conf);
722a9643ea8Slogwang             if (ret != 0) {
723a9643ea8Slogwang                 return ret;
724e8591dc5Sfengbojiang(姜凤波)             }
725e8591dc5Sfengbojiang(姜凤波) 
726e8591dc5Sfengbojiang(姜凤波)             static uint16_t nb_rxd = RX_QUEUE_SIZE;
727e8591dc5Sfengbojiang(姜凤波)             static uint16_t nb_txd = TX_QUEUE_SIZE;
728e8591dc5Sfengbojiang(姜凤波)             ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd);
729e8591dc5Sfengbojiang(姜凤波)             if (ret < 0)
730e8591dc5Sfengbojiang(姜凤波)                 printf("Could not adjust number of descriptors "
731e8591dc5Sfengbojiang(姜凤波)                         "for port%u (%d)\n", (unsigned)port_id, ret);
732a9643ea8Slogwang 
73380a6164cSYuYang             uint16_t q;
734c2eceaadSXiaozhou Liu             for (q = 0; q < nb_queues; q++) {
735c2eceaadSXiaozhou Liu                 if (numa_on) {
736c2eceaadSXiaozhou Liu                     uint16_t lcore_id = lcore_conf.port_cfgs[port_id].lcore_list[q];
737c2eceaadSXiaozhou Liu                     socketid = rte_lcore_to_socket_id(lcore_id);
738c2eceaadSXiaozhou Liu                 }
739c2eceaadSXiaozhou Liu                 mbuf_pool = pktmbuf_pool[socketid];
740e8591dc5Sfengbojiang(姜凤波) 
741e8591dc5Sfengbojiang(姜凤波)                 txq_conf = dev_info.default_txconf;
742e8591dc5Sfengbojiang(姜凤波)                 txq_conf.offloads = port_conf.txmode.offloads;
743e8591dc5Sfengbojiang(姜凤波)                 ret = rte_eth_tx_queue_setup(port_id, q, nb_txd,
744a9643ea8Slogwang                     socketid, &txq_conf);
745a9643ea8Slogwang                 if (ret < 0) {
746a9643ea8Slogwang                     return ret;
747a9643ea8Slogwang                 }
748e8591dc5Sfengbojiang(姜凤波) 
749e8591dc5Sfengbojiang(姜凤波)                 rxq_conf = dev_info.default_rxconf;
750e8591dc5Sfengbojiang(姜凤波)                 rxq_conf.offloads = port_conf.rxmode.offloads;
751e8591dc5Sfengbojiang(姜凤波)                 ret = rte_eth_rx_queue_setup(port_id, q, nb_rxd,
752a9643ea8Slogwang                     socketid, &rxq_conf, mbuf_pool);
753a9643ea8Slogwang                 if (ret < 0) {
754a9643ea8Slogwang                     return ret;
755a9643ea8Slogwang                 }
756a9643ea8Slogwang             }
757c9b3c75aSfengbojiang(姜凤波) 
758c9b3c75aSfengbojiang(姜凤波) 
759c9b3c75aSfengbojiang(姜凤波)             if (strncmp(dev_info.driver_name, BOND_DRIVER_NAME,
760c9b3c75aSfengbojiang(姜凤波)                     strlen(dev_info.driver_name)) == 0) {
761c0f66684Sfengbojiang(姜凤波) 
762c0f66684Sfengbojiang(姜凤波)                 rte_eth_macaddr_get(port_id, &addr);
763c0f66684Sfengbojiang(姜凤波)                 printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
764c0f66684Sfengbojiang(姜凤波)                            " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
765c0f66684Sfengbojiang(姜凤波)                         (unsigned)port_id,
766c0f66684Sfengbojiang(姜凤波)                         addr.addr_bytes[0], addr.addr_bytes[1],
767c0f66684Sfengbojiang(姜凤波)                         addr.addr_bytes[2], addr.addr_bytes[3],
768c0f66684Sfengbojiang(姜凤波)                         addr.addr_bytes[4], addr.addr_bytes[5]);
769c0f66684Sfengbojiang(姜凤波) 
7704418919fSjohnjiang                 rte_memcpy(pconf->mac,
771c0f66684Sfengbojiang(姜凤波)                     addr.addr_bytes, RTE_ETHER_ADDR_LEN);
772c0f66684Sfengbojiang(姜凤波) 
773c0f66684Sfengbojiang(姜凤波)                 int mode, count, x;
774c0f66684Sfengbojiang(姜凤波)                 uint16_t slaves[RTE_MAX_ETHPORTS], len = RTE_MAX_ETHPORTS;
775c0f66684Sfengbojiang(姜凤波) 
776c9b3c75aSfengbojiang(姜凤波)                 mode = rte_eth_bond_mode_get(port_id);
777c0f66684Sfengbojiang(姜凤波)                 printf("Port %u, bond mode:%d\n", port_id, mode);
778c0f66684Sfengbojiang(姜凤波) 
779c9b3c75aSfengbojiang(姜凤波)                 count = rte_eth_bond_slaves_get(port_id, slaves, len);
780c0f66684Sfengbojiang(姜凤波)                 printf("Port %u, %s's slave ports count:%d\n", port_id,
781c0f66684Sfengbojiang(姜凤波)                             ff_global_cfg.dpdk.bond_cfgs->name, count);
782c9b3c75aSfengbojiang(姜凤波)                 for (x=0; x<count; x++) {
783c0f66684Sfengbojiang(姜凤波)                     printf("Port %u, %s's slave port[%u]\n", port_id,
784c0f66684Sfengbojiang(姜凤波)                             ff_global_cfg.dpdk.bond_cfgs->name, slaves[x]);
785c0f66684Sfengbojiang(姜凤波)                 }
786c0f66684Sfengbojiang(姜凤波)             }
787a9643ea8Slogwang 
788a9643ea8Slogwang             ret = rte_eth_dev_start(port_id);
789a9643ea8Slogwang             if (ret < 0) {
790a9643ea8Slogwang                 return ret;
7912474e163SHawker             }
7922474e163SHawker     //RSS reta update will failed when enable flow isolate
79380a6164cSYuYang     #ifndef FF_FLOW_ISOLATE
7948d76b62eSfengbojiang             if (nb_queues > 1) {
7958d76b62eSfengbojiang                 /*
7968d76b62eSfengbojiang                  * FIXME: modify RSS set to FDIR
79780a6164cSYuYang                  */
798a9e7dcf4Slogwang                 set_rss_table(port_id, dev_info.reta_size, nb_queues);
7992474e163SHawker             }
800a9e7dcf4Slogwang     #endif
801a9643ea8Slogwang 
802a9643ea8Slogwang             /* Enable RX in promiscuous mode for the Ethernet device. */
8034418919fSjohnjiang             if (ff_global_cfg.dpdk.promiscuous) {
8044418919fSjohnjiang                 ret = rte_eth_promiscuous_enable(port_id);
805a9643ea8Slogwang                 if (ret == 0) {
806a9643ea8Slogwang                     printf("set port %u to promiscuous mode ok\n", port_id);
807a9643ea8Slogwang                 } else {
808a9643ea8Slogwang                     printf("set port %u to promiscuous mode error\n", port_id);
809a9643ea8Slogwang                 }
810a9643ea8Slogwang             }
811c0f66684Sfengbojiang(姜凤波)         }
812a9643ea8Slogwang     }
8137e048838Slogwang 
8147e048838Slogwang     if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
8157e048838Slogwang         check_all_ports_link_status();
8167e048838Slogwang     }
817a9643ea8Slogwang 
818a9643ea8Slogwang     return 0;
819a9643ea8Slogwang }
820a9643ea8Slogwang 
8217e048838Slogwang static int
init_clock(void)822a9643ea8Slogwang init_clock(void)
823a9643ea8Slogwang {
824a9643ea8Slogwang     rte_timer_subsystem_init();
825a9643ea8Slogwang     uint64_t hz = rte_get_timer_hz();
826a9643ea8Slogwang     uint64_t intrs = MS_PER_S/ff_global_cfg.freebsd.hz;
827a9643ea8Slogwang     uint64_t tsc = (hz + MS_PER_S - 1) / MS_PER_S*intrs;
828a9643ea8Slogwang 
829a9643ea8Slogwang     rte_timer_init(&freebsd_clock);
8307e048838Slogwang     rte_timer_reset(&freebsd_clock, tsc, PERIODICAL,
8317e048838Slogwang         rte_lcore_id(), &ff_hardclock_job, NULL);
8327e048838Slogwang 
833a9643ea8Slogwang     ff_update_current_ts();
834a9643ea8Slogwang 
835a9643ea8Slogwang     return 0;
836a9643ea8Slogwang }
8372474e163SHawker 
8382474e163SHawker #ifdef FF_FLOW_ISOLATE
8392474e163SHawker /** Print a message out of a flow error. */
8402474e163SHawker static int
port_flow_complain(struct rte_flow_error * error)8412474e163SHawker port_flow_complain(struct rte_flow_error *error)
8422474e163SHawker {
8432474e163SHawker     static const char *const errstrlist[] = {
8442474e163SHawker         [RTE_FLOW_ERROR_TYPE_NONE] = "no error",
8452474e163SHawker         [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified",
8462474e163SHawker         [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)",
8472474e163SHawker         [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field",
8482474e163SHawker         [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field",
8492474e163SHawker         [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field",
8502474e163SHawker         [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field",
8512474e163SHawker         [RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER] = "transfer field",
8522474e163SHawker         [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure",
8532474e163SHawker         [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length",
8542474e163SHawker         [RTE_FLOW_ERROR_TYPE_ITEM_SPEC] = "item specification",
8552474e163SHawker         [RTE_FLOW_ERROR_TYPE_ITEM_LAST] = "item specification range",
8562474e163SHawker         [RTE_FLOW_ERROR_TYPE_ITEM_MASK] = "item specification mask",
8572474e163SHawker         [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item",
8582474e163SHawker         [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions",
8592474e163SHawker         [RTE_FLOW_ERROR_TYPE_ACTION_CONF] = "action configuration",
8602474e163SHawker         [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action",
8612474e163SHawker     };
8622474e163SHawker     const char *errstr;
8632474e163SHawker     char buf[32];
8642474e163SHawker     int err = rte_errno;
8652474e163SHawker 
8662474e163SHawker     if ((unsigned int)error->type >= RTE_DIM(errstrlist) ||
8672474e163SHawker         !errstrlist[error->type])
8682474e163SHawker         errstr = "unknown type";
8692474e163SHawker     else
8702474e163SHawker         errstr = errstrlist[error->type];
8712474e163SHawker     printf("Caught error type %d (%s): %s%s: %s\n",
8722474e163SHawker            error->type, errstr,
8732474e163SHawker            error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ",
8742474e163SHawker                                     error->cause), buf) : "",
8752474e163SHawker            error->message ? error->message : "(no stated reason)",
8762474e163SHawker            rte_strerror(err));
8772474e163SHawker     return -err;
8782474e163SHawker }
8792474e163SHawker 
8802474e163SHawker static int
port_flow_isolate(uint16_t port_id,int set)8812474e163SHawker port_flow_isolate(uint16_t port_id, int set)
8822474e163SHawker {
8832474e163SHawker     struct rte_flow_error error;
8842474e163SHawker 
8852474e163SHawker     /* Poisoning to make sure PMDs update it in case of error. */
8862474e163SHawker     memset(&error, 0x66, sizeof(error));
8872474e163SHawker     if (rte_flow_isolate(port_id, set, &error))
8882474e163SHawker         return port_flow_complain(&error);
8892474e163SHawker     printf("Ingress traffic on port %u is %s to the defined flow rules\n",
8902474e163SHawker            port_id,
8912474e163SHawker            set ? "now restricted" : "not restricted anymore");
8922474e163SHawker     return 0;
89371412662SHawker }
89471412662SHawker 
895bee2fff9SHawker static int
create_tcp_flow(uint16_t port_id,uint16_t tcp_port)89671412662SHawker create_tcp_flow(uint16_t port_id, uint16_t tcp_port) {
89771412662SHawker   struct rte_flow_attr attr = {.ingress = 1};
89871412662SHawker   struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[port_id];
89971412662SHawker   int nb_queues = pconf->nb_lcores;
90071412662SHawker   uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
90171412662SHawker   int i = 0, j = 0;
90271412662SHawker   for (i = 0, j = 0; i < nb_queues; ++i)
90371412662SHawker    queue[j++] = i;
90471412662SHawker   struct rte_flow_action_rss rss = {
90571412662SHawker    .types = ETH_RSS_NONFRAG_IPV4_TCP,
90671412662SHawker    .key_len = rsskey_len,
90771412662SHawker    .key = rsskey,
90871412662SHawker    .queue_num = j,
90971412662SHawker    .queue = queue,
91071412662SHawker   };
91171412662SHawker 
91271412662SHawker   struct rte_eth_dev_info dev_info;
91371412662SHawker   int ret = rte_eth_dev_info_get(port_id, &dev_info);
91471412662SHawker   if (ret != 0)
91571412662SHawker     rte_exit(EXIT_FAILURE, "Error during getting device (port %u) info: %s\n", port_id, strerror(-ret));
91671412662SHawker 
91771412662SHawker   struct rte_flow_item pattern[3];
91871412662SHawker   struct rte_flow_action action[2];
91971412662SHawker   struct rte_flow_item_tcp tcp_spec;
92071412662SHawker   struct rte_flow_item_tcp tcp_mask = {
92171412662SHawker           .hdr = {
92271412662SHawker                   .src_port = RTE_BE16(0x0000),
92371412662SHawker                   .dst_port = RTE_BE16(0xffff),
92471412662SHawker           },
92571412662SHawker   };
92671412662SHawker   struct rte_flow_error error;
92771412662SHawker 
92871412662SHawker   memset(pattern, 0, sizeof(pattern));
92971412662SHawker   memset(action, 0, sizeof(action));
93071412662SHawker 
93171412662SHawker   /* set the dst ipv4 packet to the required value */
93271412662SHawker   pattern[0].type = RTE_FLOW_ITEM_TYPE_IPV4;
93371412662SHawker 
93471412662SHawker   memset(&tcp_spec, 0, sizeof(struct rte_flow_item_tcp));
93571412662SHawker   tcp_spec.hdr.dst_port = rte_cpu_to_be_16(tcp_port);
93671412662SHawker   pattern[1].type = RTE_FLOW_ITEM_TYPE_TCP;
93771412662SHawker   pattern[1].spec = &tcp_spec;
93871412662SHawker   pattern[1].mask = &tcp_mask;
93971412662SHawker 
94071412662SHawker   /* end the pattern array */
94171412662SHawker   pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
94271412662SHawker 
94371412662SHawker   /* create the action */
94471412662SHawker   action[0].type = RTE_FLOW_ACTION_TYPE_RSS;
94571412662SHawker   action[0].conf = &rss;
94671412662SHawker   action[1].type = RTE_FLOW_ACTION_TYPE_END;
94771412662SHawker 
94871412662SHawker   struct rte_flow *flow;
94971412662SHawker   /* validate and create the flow rule */
95071412662SHawker   if (!rte_flow_validate(port_id, &attr, pattern, action, &error)) {
95171412662SHawker       flow = rte_flow_create(port_id, &attr, pattern, action, &error);
95271412662SHawker       if (!flow) {
95371412662SHawker           return port_flow_complain(&error);
95471412662SHawker       }
95571412662SHawker   }
95671412662SHawker 
95771412662SHawker   memset(pattern, 0, sizeof(pattern));
95871412662SHawker 
95971412662SHawker   /* set the dst ipv4 packet to the required value */
96071412662SHawker   pattern[0].type = RTE_FLOW_ITEM_TYPE_IPV4;
96171412662SHawker 
96271412662SHawker   struct rte_flow_item_tcp tcp_src_mask = {
96371412662SHawker           .hdr = {
96471412662SHawker                   .src_port = RTE_BE16(0xffff),
96571412662SHawker                   .dst_port = RTE_BE16(0x0000),
96671412662SHawker           },
96771412662SHawker   };
96871412662SHawker 
96971412662SHawker   memset(&tcp_spec, 0, sizeof(struct rte_flow_item_tcp));
97071412662SHawker   tcp_spec.hdr.src_port = rte_cpu_to_be_16(tcp_port);
97171412662SHawker   pattern[1].type = RTE_FLOW_ITEM_TYPE_TCP;
97271412662SHawker   pattern[1].spec = &tcp_spec;
97371412662SHawker   pattern[1].mask = &tcp_src_mask;
97471412662SHawker 
97571412662SHawker   /* end the pattern array */
97671412662SHawker   pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
97771412662SHawker 
97871412662SHawker   /* validate and create the flow rule */
97971412662SHawker   if (!rte_flow_validate(port_id, &attr, pattern, action, &error)) {
98071412662SHawker       flow = rte_flow_create(port_id, &attr, pattern, action, &error);
98171412662SHawker       if (!flow) {
98271412662SHawker           return port_flow_complain(&error);
98371412662SHawker       }
98471412662SHawker   }
98571412662SHawker 
98671412662SHawker   return 1;
98771412662SHawker }
98871412662SHawker 
9894542e5fbSHawker static int
init_flow(uint16_t port_id,uint16_t tcp_port)99071412662SHawker init_flow(uint16_t port_id, uint16_t tcp_port) {
99171412662SHawker   // struct ff_flow_cfg fcfg = ff_global_cfg.dpdk.flow_cfgs[0];
99271412662SHawker 
99371412662SHawker   // int i;
99471412662SHawker   // for (i = 0; i < fcfg.nb_port; i++) {
99571412662SHawker   //     if(!create_tcp_flow(fcfg.port_id, fcfg.tcp_ports[i])) {
99671412662SHawker   //         return 0;
99771412662SHawker   //     }
99871412662SHawker   // }
99971412662SHawker 
100071412662SHawker   if(!create_tcp_flow(port_id, tcp_port)) {
100171412662SHawker       rte_exit(EXIT_FAILURE, "create tcp flow failed\n");
100271412662SHawker       return -1;
100371412662SHawker   }
100471412662SHawker 
100571412662SHawker   /*  ARP rule */
100671412662SHawker   struct rte_flow_attr attr = {.ingress = 1};
100771412662SHawker   struct rte_flow_action_queue queue = {.index = 0};
100871412662SHawker 
100971412662SHawker   struct rte_flow_item pattern_[2];
101071412662SHawker   struct rte_flow_action action[2];
101171412662SHawker   struct rte_flow_item_eth eth_type = {.type = RTE_BE16(0x0806)};
101271412662SHawker   struct rte_flow_item_eth eth_mask = {
101371412662SHawker           .type = RTE_BE16(0xffff)
101471412662SHawker   };
101571412662SHawker 
101671412662SHawker   memset(pattern_, 0, sizeof(pattern_));
101771412662SHawker   memset(action, 0, sizeof(action));
101871412662SHawker 
101971412662SHawker   pattern_[0].type = RTE_FLOW_ITEM_TYPE_ETH;
102071412662SHawker   pattern_[0].spec = &eth_type;
102171412662SHawker   pattern_[0].mask = &eth_mask;
102271412662SHawker 
102371412662SHawker   pattern_[1].type = RTE_FLOW_ITEM_TYPE_END;
102471412662SHawker 
102571412662SHawker   /* create the action */
102671412662SHawker   action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
102771412662SHawker   action[0].conf = &queue;
102871412662SHawker   action[1].type = RTE_FLOW_ACTION_TYPE_END;
102971412662SHawker 
103071412662SHawker   struct rte_flow *flow;
103171412662SHawker   struct rte_flow_error error;
103271412662SHawker   /* validate and create the flow rule */
103371412662SHawker   if (!rte_flow_validate(port_id, &attr, pattern_, action, &error)) {
103471412662SHawker       flow = rte_flow_create(port_id, &attr, pattern_, action, &error);
103571412662SHawker       if (!flow) {
103671412662SHawker           return port_flow_complain(&error);
103771412662SHawker       }
103871412662SHawker   }
103971412662SHawker 
104071412662SHawker   return 1;
104171412662SHawker }
10422474e163SHawker 
10432474e163SHawker #endif
1044a9643ea8Slogwang 
1045a9643ea8Slogwang int
ff_dpdk_init(int argc,char ** argv)1046a9643ea8Slogwang ff_dpdk_init(int argc, char **argv)
1047a9643ea8Slogwang {
1048a9643ea8Slogwang     if (ff_global_cfg.dpdk.nb_procs < 1 ||
1049a9643ea8Slogwang         ff_global_cfg.dpdk.nb_procs > RTE_MAX_LCORE ||
10508f57dbbcSlogwang         ff_global_cfg.dpdk.proc_id >= ff_global_cfg.dpdk.nb_procs ||
1051a9643ea8Slogwang         ff_global_cfg.dpdk.proc_id < 0) {
1052a9643ea8Slogwang         printf("param num_procs[%d] or proc_id[%d] error!\n",
1053a9643ea8Slogwang             ff_global_cfg.dpdk.nb_procs,
1054a9643ea8Slogwang             ff_global_cfg.dpdk.proc_id);
1055a9643ea8Slogwang         exit(1);
1056a9643ea8Slogwang     }
1057a9643ea8Slogwang 
1058a9643ea8Slogwang     int ret = rte_eal_init(argc, argv);
1059a9643ea8Slogwang     if (ret < 0) {
1060a9643ea8Slogwang         rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
1061a9643ea8Slogwang     }
1062df692c60Slogwang 
1063df692c60Slogwang     numa_on = ff_global_cfg.dpdk.numa_on;
1064c506e436Sfengbojiang 
106559bb71f6Sfengbojiang(姜凤波)     idle_sleep = ff_global_cfg.dpdk.idle_sleep;
106659bb71f6Sfengbojiang(姜凤波)     pkt_tx_delay = ff_global_cfg.dpdk.pkt_tx_delay > BURST_TX_DRAIN_US ? \
1067c506e436Sfengbojiang         BURST_TX_DRAIN_US : ff_global_cfg.dpdk.pkt_tx_delay;
1068a9643ea8Slogwang 
1069a9643ea8Slogwang     init_lcore_conf();
1070a9643ea8Slogwang 
1071a9643ea8Slogwang     init_mem_pool();
1072eb5902d9Slogwang 
1073a9643ea8Slogwang     init_dispatch_ring();
10747abd0fb2Slogwang 
10757abd0fb2Slogwang     init_msg_ring();
1076dc42d452Swhl739 
1077a9643ea8Slogwang #ifdef FF_KNI
1078a9643ea8Slogwang     enable_kni = ff_global_cfg.kni.enable;
1079a9643ea8Slogwang     if (enable_kni) {
1080a9643ea8Slogwang         init_kni();
1081dc42d452Swhl739     }
1082a9643ea8Slogwang #endif
10835bf882b4S10077240 
1084ef5ab859S10077240 #ifdef FF_USE_PAGE_ARRAY
1085ef5ab859S10077240     ff_mmap_init();
1086ef5ab859S10077240 #endif
10872474e163SHawker 
10882474e163SHawker #ifdef FF_FLOW_ISOLATE
10892474e163SHawker     // run once in primary process
10902474e163SHawker     if (0 == lcore_conf.tx_queue_id[0]){
10912474e163SHawker         ret = port_flow_isolate(0, 1);
10922474e163SHawker         if (ret < 0)
10932474e163SHawker             rte_exit(EXIT_FAILURE, "init_port_isolate failed\n");
10942474e163SHawker     }
10952474e163SHawker #endif
1096a9643ea8Slogwang 
1097a9643ea8Slogwang     ret = init_port_start();
1098a9643ea8Slogwang     if (ret < 0) {
1099a9643ea8Slogwang         rte_exit(EXIT_FAILURE, "init_port_start failed\n");
1100a9643ea8Slogwang     }
11017e048838Slogwang 
110271412662SHawker     init_clock();
11031d7d040eSHawker #ifdef FF_FLOW_ISOLATE
1104e0b37068SHawker     //Only give a example usage: port_id=0, tcp_port= 80.
1105e0b37068SHawker     //Recommend:
1106e0b37068SHawker     //1. init_flow should replace `set_rss_table` in `init_port_start` loop, This can set all NIC's port_id_list instead only 0 device(port_id).
11074542e5fbSHawker     //2. using config options `tcp_port` replace magic number of 80
110871412662SHawker     ret = init_flow(0, 80);
110971412662SHawker     if (ret < 0) {
111071412662SHawker         rte_exit(EXIT_FAILURE, "init_port_flow failed\n");
111171412662SHawker     }
1112a9643ea8Slogwang #endif
1113a9643ea8Slogwang     return 0;
1114a9643ea8Slogwang }
1115a9643ea8Slogwang 
1116213fa7b3Slogwang static void
ff_veth_input(const struct ff_dpdk_if_context * ctx,struct rte_mbuf * pkt)1117a9643ea8Slogwang ff_veth_input(const struct ff_dpdk_if_context *ctx, struct rte_mbuf *pkt)
1118213fa7b3Slogwang {
1119213fa7b3Slogwang     uint8_t rx_csum = ctx->hw_features.rx_csum;
1120213fa7b3Slogwang     if (rx_csum) {
112196805858Schenwei         if (pkt->ol_flags & (PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD)) {
1122213fa7b3Slogwang             rte_pktmbuf_free(pkt);
1123213fa7b3Slogwang             return;
1124213fa7b3Slogwang         }
1125213fa7b3Slogwang     }
1126a9643ea8Slogwang 
1127a9643ea8Slogwang     void *data = rte_pktmbuf_mtod(pkt, void*);
1128a9643ea8Slogwang     uint16_t len = rte_pktmbuf_data_len(pkt);
1129213fa7b3Slogwang 
1130a9643ea8Slogwang     void *hdr = ff_mbuf_gethdr(pkt, pkt->pkt_len, data, len, rx_csum);
1131a9643ea8Slogwang     if (hdr == NULL) {
1132a9643ea8Slogwang         rte_pktmbuf_free(pkt);
1133a9643ea8Slogwang         return;
1134a9643ea8Slogwang     }
113549056e3aSHongBo Long 
113649056e3aSHongBo Long     if (pkt->ol_flags & PKT_RX_VLAN_STRIPPED) {
113749056e3aSHongBo Long         ff_mbuf_set_vlan_info(hdr, pkt->vlan_tci);
113849056e3aSHongBo Long     }
1139144c6bcdSlogwang 
1140a9643ea8Slogwang     struct rte_mbuf *pn = pkt->next;
1141144c6bcdSlogwang     void *prev = hdr;
11424b3bcd46SXu Jiaxuan     while(pn != NULL) {
11434b3bcd46SXu Jiaxuan         data = rte_pktmbuf_mtod(pn, void*);
1144a9643ea8Slogwang         len = rte_pktmbuf_data_len(pn);
1145fa552ee2SJianfeng Tan 
1146a9643ea8Slogwang         void *mb = ff_mbuf_get(prev, pn, data, len);
1147a9643ea8Slogwang         if (mb == NULL) {
1148144c6bcdSlogwang             ff_mbuf_free(hdr);
1149a9643ea8Slogwang             rte_pktmbuf_free(pkt);
1150a9643ea8Slogwang             return;
1151144c6bcdSlogwang         }
1152a9643ea8Slogwang         pn = pn->next;
1153a9643ea8Slogwang         prev = mb;
1154a9643ea8Slogwang     }
1155213fa7b3Slogwang 
1156a9643ea8Slogwang     ff_veth_process_packet(ctx->ifp, hdr);
1157a9643ea8Slogwang }
1158a9643ea8Slogwang 
1159a9643ea8Slogwang static enum FilterReturn
protocol_filter(const void * data,uint16_t len)1160a9643ea8Slogwang protocol_filter(const void *data, uint16_t len)
11614418919fSjohnjiang {
1162a9643ea8Slogwang     if(len < RTE_ETHER_ADDR_LEN)
1163a9643ea8Slogwang         return FILTER_UNKNOWN;
11644418919fSjohnjiang 
11654418919fSjohnjiang     const struct rte_ether_hdr *hdr;
11664418919fSjohnjiang     const struct rte_vlan_hdr *vlanhdr;
116700c65d22Sfengbojiang(姜凤波)     hdr = (const struct rte_ether_hdr *)data;
11684418919fSjohnjiang     uint16_t ether_type = rte_be_to_cpu_16(hdr->ether_type);
11694418919fSjohnjiang     data += RTE_ETHER_HDR_LEN;
1170a9643ea8Slogwang     len -= RTE_ETHER_HDR_LEN;
11714418919fSjohnjiang 
11724418919fSjohnjiang     if (ether_type == RTE_ETHER_TYPE_VLAN) {
117300c65d22Sfengbojiang(姜凤波)         vlanhdr = (struct rte_vlan_hdr *)data;
11744418919fSjohnjiang         ether_type = rte_be_to_cpu_16(vlanhdr->eth_proto);
11754418919fSjohnjiang         data += sizeof(struct rte_vlan_hdr);
117649056e3aSHongBo Long         len -= sizeof(struct rte_vlan_hdr);
117749056e3aSHongBo Long     }
11784418919fSjohnjiang 
1179a9643ea8Slogwang     if(ether_type == RTE_ETHER_TYPE_ARP)
1180a9643ea8Slogwang         return FILTER_ARP;
118110b909a1Sfengbojiang(姜凤波) 
11824418919fSjohnjiang #ifdef INET6
118367c27ffeSfengbojiang(姜凤波)     if (ether_type == RTE_ETHER_TYPE_IPV6) {
118467c27ffeSfengbojiang(姜凤波)         return ff_kni_proto_filter(data,
118510b909a1Sfengbojiang(姜凤波)             len, ether_type);
118610b909a1Sfengbojiang(姜凤波)     }
118710b909a1Sfengbojiang(姜凤波) #endif
1188dc42d452Swhl739 
1189dc42d452Swhl739 #ifndef FF_KNI
1190dc42d452Swhl739     return FILTER_UNKNOWN;
1191a9643ea8Slogwang #else
1192a9643ea8Slogwang     if (!enable_kni) {
1193a9643ea8Slogwang         return FILTER_UNKNOWN;
1194a9643ea8Slogwang     }
11954418919fSjohnjiang 
1196a9643ea8Slogwang     if(ether_type != RTE_ETHER_TYPE_IPV4)
1197a9643ea8Slogwang         return FILTER_UNKNOWN;
119867c27ffeSfengbojiang(姜凤波) 
119967c27ffeSfengbojiang(姜凤波)     return ff_kni_proto_filter(data,
1200dc42d452Swhl739         len, ether_type);
1201a9643ea8Slogwang #endif
1202a9643ea8Slogwang }
1203a9643ea8Slogwang 
1204bc0ac475Slogwang static inline void
pktmbuf_deep_attach(struct rte_mbuf * mi,const struct rte_mbuf * m)1205bc0ac475Slogwang pktmbuf_deep_attach(struct rte_mbuf *mi, const struct rte_mbuf *m)
1206bc0ac475Slogwang {
1207bc0ac475Slogwang     struct rte_mbuf *md;
1208bc0ac475Slogwang     void *src, *dst;
1209bc0ac475Slogwang 
1210bc0ac475Slogwang     dst = rte_pktmbuf_mtod(mi, void *);
1211bc0ac475Slogwang     src = rte_pktmbuf_mtod(m, void *);
1212bc0ac475Slogwang 
1213bc0ac475Slogwang     mi->data_len = m->data_len;
1214bc0ac475Slogwang     rte_memcpy(dst, src, m->data_len);
1215bc0ac475Slogwang 
1216bc0ac475Slogwang     mi->port = m->port;
1217bc0ac475Slogwang     mi->vlan_tci = m->vlan_tci;
1218bc0ac475Slogwang     mi->vlan_tci_outer = m->vlan_tci_outer;
1219bc0ac475Slogwang     mi->tx_offload = m->tx_offload;
1220bc0ac475Slogwang     mi->hash = m->hash;
1221bc0ac475Slogwang     mi->ol_flags = m->ol_flags;
1222bc0ac475Slogwang     mi->packet_type = m->packet_type;
1223bc0ac475Slogwang }
1224bc0ac475Slogwang 
1225bc0ac475Slogwang /* copied from rte_pktmbuf_clone */
1226bc0ac475Slogwang static inline struct rte_mbuf *
pktmbuf_deep_clone(const struct rte_mbuf * md,struct rte_mempool * mp)1227bc0ac475Slogwang pktmbuf_deep_clone(const struct rte_mbuf *md,
1228bc0ac475Slogwang     struct rte_mempool *mp)
1229bc0ac475Slogwang {
1230bc0ac475Slogwang     struct rte_mbuf *mc, *mi, **prev;
1231bc0ac475Slogwang     uint32_t pktlen;
1232bc0ac475Slogwang     uint8_t nseg;
1233bc0ac475Slogwang 
1234bc0ac475Slogwang     if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
1235bc0ac475Slogwang         return NULL;
1236bc0ac475Slogwang 
1237bc0ac475Slogwang     mi = mc;
1238bc0ac475Slogwang     prev = &mi->next;
1239bc0ac475Slogwang     pktlen = md->pkt_len;
1240bc0ac475Slogwang     nseg = 0;
1241bc0ac475Slogwang 
1242bc0ac475Slogwang     do {
1243bc0ac475Slogwang         nseg++;
1244bc0ac475Slogwang         pktmbuf_deep_attach(mi, md);
1245bc0ac475Slogwang         *prev = mi;
1246bc0ac475Slogwang         prev = &mi->next;
1247bc0ac475Slogwang     } while ((md = md->next) != NULL &&
1248bc0ac475Slogwang         (mi = rte_pktmbuf_alloc(mp)) != NULL);
1249bc0ac475Slogwang 
1250bc0ac475Slogwang     *prev = NULL;
1251bc0ac475Slogwang     mc->nb_segs = nseg;
1252bc0ac475Slogwang     mc->pkt_len = pktlen;
1253bc0ac475Slogwang 
1254bc0ac475Slogwang     /* Allocation of new indirect segment failed */
1255bc0ac475Slogwang     if (unlikely (mi == NULL)) {
1256bc0ac475Slogwang         rte_pktmbuf_free(mc);
1257bc0ac475Slogwang         return NULL;
1258bc0ac475Slogwang     }
1259bc0ac475Slogwang 
1260bc0ac475Slogwang     __rte_mbuf_sanity_check(mc, 1);
1261bc0ac475Slogwang     return mc;
1262bc0ac475Slogwang }
1263bc0ac475Slogwang 
12642bfe3f2eSlogwang static inline void
process_packets(uint16_t port_id,uint16_t queue_id,struct rte_mbuf ** bufs,uint16_t count,const struct ff_dpdk_if_context * ctx,int pkts_from_ring)1265213fa7b3Slogwang process_packets(uint16_t port_id, uint16_t queue_id, struct rte_mbuf **bufs,
1266a9643ea8Slogwang     uint16_t count, const struct ff_dpdk_if_context *ctx, int pkts_from_ring)
1267a9643ea8Slogwang {
1268eb5902d9Slogwang     struct lcore_conf *qconf = &lcore_conf;
1269a9643ea8Slogwang     uint16_t nb_queues = qconf->nb_queue_list[port_id];
1270a9643ea8Slogwang 
1271a9643ea8Slogwang     uint16_t i;
1272a9643ea8Slogwang     for (i = 0; i < count; i++) {
1273a9643ea8Slogwang         struct rte_mbuf *rtem = bufs[i];
1274819aafb6Sjinhao2 
1275eb5902d9Slogwang         if (unlikely( ff_global_cfg.pcap.enable)) {
1276819aafb6Sjinhao2             if (!pkts_from_ring) {
1277a9643ea8Slogwang                 ff_dump_packets( ff_global_cfg.pcap.save_path, rtem, ff_global_cfg.pcap.snap_len, ff_global_cfg.pcap.save_len);
1278eb5902d9Slogwang             }
1279a9643ea8Slogwang         }
1280a9643ea8Slogwang 
1281a9643ea8Slogwang         void *data = rte_pktmbuf_mtod(rtem, void*);
1282a9643ea8Slogwang         uint16_t len = rte_pktmbuf_data_len(rtem);
128303df98deSfengbojiang 
128403df98deSfengbojiang         if (!pkts_from_ring) {
128503df98deSfengbojiang             ff_traffic.rx_packets += rtem->nb_segs;
128603df98deSfengbojiang             ff_traffic.rx_bytes += rte_pktmbuf_pkt_len(rtem);
128703df98deSfengbojiang         }
1288eb5902d9Slogwang 
1289ee6c3aa3Sfengbojiang(姜凤波)         if (!pkts_from_ring && packet_dispatcher) {
1290ee6c3aa3Sfengbojiang(姜凤波)             uint64_t cur_tsc = rte_rdtsc();
1291ee6c3aa3Sfengbojiang(姜凤波)             int ret = (*packet_dispatcher)(data, &len, queue_id, nb_queues);
1292aa18b738Sfengbojiang(姜凤波)             usr_cb_tsc += rte_rdtsc() - cur_tsc;
1293aa18b738Sfengbojiang(姜凤波)             if (ret == FF_DISPATCH_RESPONSE) {
1294aa18b738Sfengbojiang(姜凤波)                 rte_pktmbuf_pkt_len(rtem) = rte_pktmbuf_data_len(rtem) = len;
1295aa18b738Sfengbojiang(姜凤波) 
1296aa18b738Sfengbojiang(姜凤波)                 /*
12974418919fSjohnjiang                  * We have not support vlan out strip
1298aa18b738Sfengbojiang(姜凤波)                  */
12994418919fSjohnjiang                 if (rtem->vlan_tci) {
13004418919fSjohnjiang                     data = rte_pktmbuf_prepend(rtem, sizeof(struct rte_vlan_hdr));
13014418919fSjohnjiang                     if (data != NULL) {
1302aa18b738Sfengbojiang(姜凤波)                         memmove(data, data + sizeof(struct rte_vlan_hdr), RTE_ETHER_HDR_LEN);
1303aa18b738Sfengbojiang(姜凤波)                         struct rte_ether_hdr *etherhdr = (struct rte_ether_hdr *)data;
13044418919fSjohnjiang                         struct rte_vlan_hdr *vlanhdr = (struct rte_vlan_hdr *)(data + RTE_ETHER_HDR_LEN);
1305aa18b738Sfengbojiang(姜凤波)                         vlanhdr->vlan_tci = rte_cpu_to_be_16(rtem->vlan_tci);
1306aa18b738Sfengbojiang(姜凤波)                         vlanhdr->eth_proto = etherhdr->ether_type;
1307ee6c3aa3Sfengbojiang(姜凤波)                         etherhdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
1308ee6c3aa3Sfengbojiang(姜凤波)                     }
1309ee6c3aa3Sfengbojiang(姜凤波)                 }
1310ee6c3aa3Sfengbojiang(姜凤波)                 send_single_packet(rtem, port_id);
1311ee6c3aa3Sfengbojiang(姜凤波)                 continue;
1312eb5902d9Slogwang             }
1313eb5902d9Slogwang 
1314eb5902d9Slogwang             if (ret == FF_DISPATCH_ERROR || ret >= nb_queues) {
1315eb5902d9Slogwang                 rte_pktmbuf_free(rtem);
1316eb5902d9Slogwang                 continue;
1317eb5902d9Slogwang             }
1318eb5902d9Slogwang 
1319eb5902d9Slogwang             if (ret != queue_id) {
1320eb5902d9Slogwang                 ret = rte_ring_enqueue(dispatch_ring[port_id][ret], rtem);
1321eb5902d9Slogwang                 if (ret < 0)
1322eb5902d9Slogwang                     rte_pktmbuf_free(rtem);
1323eb5902d9Slogwang 
1324eb5902d9Slogwang                 continue;
1325a9643ea8Slogwang             }
132610b909a1Sfengbojiang(姜凤波)         }
132710b909a1Sfengbojiang(姜凤波) 
132810b909a1Sfengbojiang(姜凤波)         enum FilterReturn filter = protocol_filter(data, len);
1329f47e38d9Slogwang #ifdef INET6
133010b909a1Sfengbojiang(姜凤波)         if (filter == FILTER_ARP || filter == FILTER_NDP) {
1331a9643ea8Slogwang #else
1332a9643ea8Slogwang         if (filter == FILTER_ARP) {
1333eb5902d9Slogwang #endif
1334eb5902d9Slogwang             struct rte_mempool *mbuf_pool;
1335eb5902d9Slogwang             struct rte_mbuf *mbuf_clone;
1336eb5902d9Slogwang             if (!pkts_from_ring) {
1337a9643ea8Slogwang                 uint16_t j;
1338a9643ea8Slogwang                 for(j = 0; j < nb_queues; ++j) {
1339df692c60Slogwang                     if(j == queue_id)
1340df692c60Slogwang                         continue;
1341eb5902d9Slogwang 
134280a6164cSYuYang                     unsigned socket_id = 0;
1343df692c60Slogwang                     if (numa_on) {
1344df692c60Slogwang                         uint16_t lcore_id = qconf->port_cfgs[port_id].lcore_list[j];
1345bc0ac475Slogwang                         socket_id = rte_lcore_to_socket_id(lcore_id);
1346a9643ea8Slogwang                     }
1347bc0ac475Slogwang                     mbuf_pool = pktmbuf_pool[socket_id];
1348bc0ac475Slogwang                     mbuf_clone = pktmbuf_deep_clone(rtem, mbuf_pool);
1349a9643ea8Slogwang                     if(mbuf_clone) {
1350a9643ea8Slogwang                         int ret = rte_ring_enqueue(dispatch_ring[port_id][j],
1351a9643ea8Slogwang                             mbuf_clone);
1352a9643ea8Slogwang                         if (ret < 0)
1353a9643ea8Slogwang                             rte_pktmbuf_free(mbuf_clone);
1354a9643ea8Slogwang                     }
1355dc42d452Swhl739                 }
1356a9643ea8Slogwang             }
1357a9643ea8Slogwang 
1358bc0ac475Slogwang #ifdef FF_KNI
1359a9643ea8Slogwang             if (enable_kni && rte_eal_process_type() == RTE_PROC_PRIMARY) {
1360c8722d26Slogwang                 mbuf_pool = pktmbuf_pool[qconf->socket_id];
1361a9643ea8Slogwang                 mbuf_clone = pktmbuf_deep_clone(rtem, mbuf_pool);
1362a9643ea8Slogwang                 if(mbuf_clone) {
1363dc42d452Swhl739                     ff_kni_enqueue(port_id, mbuf_clone);
1364213fa7b3Slogwang                 }
1365dc42d452Swhl739             }
136647507c15Spengtian #endif
136747507c15Spengtian             ff_veth_input(ctx, rtem);
136847507c15Spengtian #ifdef FF_KNI
136947507c15Spengtian         } else if (enable_kni) {
137047507c15Spengtian             if (knictl_action == FF_KNICTL_ACTION_ALL_TO_KNI){
137147507c15Spengtian                 ff_kni_enqueue(port_id, rtem);
137247507c15Spengtian             } else if (knictl_action == FF_KNICTL_ACTION_ALL_TO_FF){
1373bc0ac475Slogwang                 ff_veth_input(ctx, rtem);
1374f47e38d9Slogwang             } else if (knictl_action == FF_KNICTL_ACTION_DEFAULT){
1375f47e38d9Slogwang                 if (enable_kni &&
137647507c15Spengtian                         ((filter == FILTER_KNI && kni_accept) ||
137747507c15Spengtian                         (filter == FILTER_UNKNOWN && !kni_accept)) ) {
137847507c15Spengtian                         ff_kni_enqueue(port_id, rtem);
137947507c15Spengtian                 } else {
138047507c15Spengtian                     ff_veth_input(ctx, rtem);
138147507c15Spengtian                 }
1382dc42d452Swhl739             } else {
1383f47e38d9Slogwang                 ff_veth_input(ctx, rtem);
1384213fa7b3Slogwang             }
1385a9643ea8Slogwang #endif
1386a9643ea8Slogwang         } else {
1387a9643ea8Slogwang             ff_veth_input(ctx, rtem);
1388a9643ea8Slogwang         }
1389a9643ea8Slogwang     }
13902bfe3f2eSlogwang }
1391213fa7b3Slogwang 
1392a9643ea8Slogwang static inline int
1393a9643ea8Slogwang process_dispatch_ring(uint16_t port_id, uint16_t queue_id,
13947abd0fb2Slogwang     struct rte_mbuf **pkts_burst, const struct ff_dpdk_if_context *ctx)
1395eb5902d9Slogwang {
13962bfe3f2eSlogwang     /* read packet from ring buf and to process */
1397a9643ea8Slogwang     uint16_t nb_rb;
13987abd0fb2Slogwang     nb_rb = rte_ring_dequeue_burst(dispatch_ring[port_id][queue_id],
13997abd0fb2Slogwang         (void **)pkts_burst, MAX_PKT_BURST, NULL);
14007abd0fb2Slogwang 
14017abd0fb2Slogwang     if(nb_rb > 0) {
14027abd0fb2Slogwang         process_packets(port_id, queue_id, pkts_burst, nb_rb, ctx, 1);
14037abd0fb2Slogwang     }
14047abd0fb2Slogwang 
14057abd0fb2Slogwang     return nb_rb;
1406127dd473Swhl739 }
14077abd0fb2Slogwang 
14087abd0fb2Slogwang static inline void
14097abd0fb2Slogwang handle_sysctl_msg(struct ff_msg *msg)
14107abd0fb2Slogwang {
14117abd0fb2Slogwang     int ret = ff_sysctl(msg->sysctl.name, msg->sysctl.namelen,
14127abd0fb2Slogwang         msg->sysctl.old, msg->sysctl.oldlenp, msg->sysctl.new,
14137abd0fb2Slogwang         msg->sysctl.newlen);
14147abd0fb2Slogwang 
14157abd0fb2Slogwang     if (ret < 0) {
14167abd0fb2Slogwang         msg->result = errno;
14177abd0fb2Slogwang     } else {
14187abd0fb2Slogwang         msg->result = 0;
14197abd0fb2Slogwang     }
1420127dd473Swhl739 }
1421df6ad731Slogwang 
1422df6ad731Slogwang static inline void
1423d7140ab7Sfengbojiang(姜凤波) handle_ioctl_msg(struct ff_msg *msg)
1424d7140ab7Sfengbojiang(姜凤波) {
1425d7140ab7Sfengbojiang(姜凤波)     int fd, ret;
1426d7140ab7Sfengbojiang(姜凤波) #ifdef INET6
1427d7140ab7Sfengbojiang(姜凤波)     if (msg->msg_type == FF_IOCTL6) {
1428df6ad731Slogwang         fd = ff_socket(AF_INET6, SOCK_DGRAM, 0);
1429d7140ab7Sfengbojiang(姜凤波)     } else
1430df6ad731Slogwang #endif
1431df6ad731Slogwang         fd = ff_socket(AF_INET, SOCK_DGRAM, 0);
1432df6ad731Slogwang 
1433df6ad731Slogwang     if (fd < 0) {
1434df6ad731Slogwang         ret = -1;
1435867abe45Swhl739         goto done;
1436df6ad731Slogwang     }
1437df6ad731Slogwang 
1438df6ad731Slogwang     ret = ff_ioctl_freebsd(fd, msg->ioctl.cmd, msg->ioctl.data);
1439df6ad731Slogwang 
1440df6ad731Slogwang     ff_close(fd);
1441df6ad731Slogwang 
1442df6ad731Slogwang done:
1443df6ad731Slogwang     if (ret < 0) {
1444df6ad731Slogwang         msg->result = errno;
1445df6ad731Slogwang     } else {
1446df6ad731Slogwang         msg->result = 0;
1447df6ad731Slogwang     }
1448127dd473Swhl739 }
1449144c6bcdSlogwang 
14503b2bd0f6Slogwang static inline void
1451144c6bcdSlogwang handle_route_msg(struct ff_msg *msg)
14523b2bd0f6Slogwang {
14533b2bd0f6Slogwang     int ret = ff_rtioctl(msg->route.fib, msg->route.data,
14543b2bd0f6Slogwang         &msg->route.len, msg->route.maxlen);
14553b2bd0f6Slogwang     if (ret < 0) {
14563b2bd0f6Slogwang         msg->result = errno;
1457144c6bcdSlogwang     } else {
1458144c6bcdSlogwang         msg->result = 0;
1459e7741141SAndy     }
1460127dd473Swhl739 }
1461e7741141SAndy 
14625a73eef1Sfengbojiang static inline void
1463e7741141SAndy handle_top_msg(struct ff_msg *msg)
1464e7741141SAndy {
1465e7741141SAndy     msg->top = ff_top_status;
14663b2bd0f6Slogwang     msg->result = 0;
14673b2bd0f6Slogwang }
1468127dd473Swhl739 
14693b2bd0f6Slogwang #ifdef FF_NETGRAPH
14703b2bd0f6Slogwang static inline void
14713b2bd0f6Slogwang handle_ngctl_msg(struct ff_msg *msg)
14723b2bd0f6Slogwang {
14733b2bd0f6Slogwang     int ret = ff_ngctl(msg->ngctl.cmd, msg->ngctl.data);
14743b2bd0f6Slogwang     if (ret < 0) {
14753b2bd0f6Slogwang         msg->result = errno;
14763b2bd0f6Slogwang     } else {
1477127dd473Swhl739         msg->result = 0;
1478127dd473Swhl739         msg->ngctl.ret = ret;
14793b2bd0f6Slogwang     }
1480127dd473Swhl739 }
1481127dd473Swhl739 #endif
1482127dd473Swhl739 
1483127dd473Swhl739 #ifdef FF_IPFW
1484127dd473Swhl739 static inline void
1485127dd473Swhl739 handle_ipfw_msg(struct ff_msg *msg)
1486127dd473Swhl739 {
1487127dd473Swhl739     int fd, ret;
1488127dd473Swhl739     fd = ff_socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
1489127dd473Swhl739     if (fd < 0) {
1490127dd473Swhl739         ret = -1;
1491127dd473Swhl739         goto done;
1492127dd473Swhl739     }
1493867abe45Swhl739 
1494127dd473Swhl739     switch (msg->ipfw.cmd) {
1495127dd473Swhl739         case FF_IPFW_GET:
1496127dd473Swhl739             ret = ff_getsockopt_freebsd(fd, msg->ipfw.level,
1497127dd473Swhl739                 msg->ipfw.optname, msg->ipfw.optval,
1498867abe45Swhl739                 msg->ipfw.optlen);
1499127dd473Swhl739             break;
1500127dd473Swhl739         case FF_IPFW_SET:
1501127dd473Swhl739             ret = ff_setsockopt_freebsd(fd, msg->ipfw.level,
1502127dd473Swhl739                 msg->ipfw.optname, msg->ipfw.optval,
1503127dd473Swhl739                 *(msg->ipfw.optlen));
1504127dd473Swhl739             break;
1505127dd473Swhl739         default:
1506127dd473Swhl739             ret = -1;
1507127dd473Swhl739             errno = ENOTSUP;
1508127dd473Swhl739             break;
1509127dd473Swhl739     }
1510127dd473Swhl739 
1511127dd473Swhl739     ff_close(fd);
1512127dd473Swhl739 
1513127dd473Swhl739 done:
1514127dd473Swhl739     if (ret < 0) {
1515127dd473Swhl739         msg->result = errno;
15163b2bd0f6Slogwang     } else {
15173b2bd0f6Slogwang         msg->result = 0;
15183b2bd0f6Slogwang     }
1519144c6bcdSlogwang }
152003df98deSfengbojiang #endif
152103df98deSfengbojiang 
152203df98deSfengbojiang static inline void
152303df98deSfengbojiang handle_traffic_msg(struct ff_msg *msg)
152403df98deSfengbojiang {
152503df98deSfengbojiang     msg->traffic = ff_traffic;
152647507c15Spengtian     msg->result = 0;
152747507c15Spengtian }
152847507c15Spengtian 
152947507c15Spengtian #ifdef FF_KNI
153047507c15Spengtian static inline void
153147507c15Spengtian handle_knictl_msg(struct ff_msg *msg)
153247507c15Spengtian {
153347507c15Spengtian     if (msg->knictl.kni_cmd == FF_KNICTL_CMD_SET){
153447507c15Spengtian         switch (msg->knictl.kni_action){
153547507c15Spengtian             case FF_KNICTL_ACTION_ALL_TO_FF: knictl_action = FF_KNICTL_ACTION_ALL_TO_FF; msg->result = 0; printf("new kni action: alltoff\n"); break;
153647507c15Spengtian             case FF_KNICTL_ACTION_ALL_TO_KNI: knictl_action = FF_KNICTL_ACTION_ALL_TO_KNI; msg->result = 0; printf("new kni action: alltokni\n"); break;
153747507c15Spengtian             case FF_KNICTL_ACTION_DEFAULT: knictl_action = FF_KNICTL_ACTION_DEFAULT; msg->result = 0; printf("new kni action: default\n"); break;
153847507c15Spengtian             default: msg->result = -1;
153947507c15Spengtian         }
154047507c15Spengtian     }
154147507c15Spengtian     else if (msg->knictl.kni_cmd == FF_KNICTL_CMD_GET){
154247507c15Spengtian         msg->knictl.kni_action = knictl_action;
154347507c15Spengtian     } else {
154447507c15Spengtian         msg->result = -2;
154547507c15Spengtian     }
154603df98deSfengbojiang }
1547127dd473Swhl739 #endif
15487abd0fb2Slogwang 
15493b2bd0f6Slogwang static inline void
15507abd0fb2Slogwang handle_default_msg(struct ff_msg *msg)
15517abd0fb2Slogwang {
15527abd0fb2Slogwang     msg->result = ENOTSUP;
15537abd0fb2Slogwang }
15547abd0fb2Slogwang 
15557abd0fb2Slogwang static inline void
15567abd0fb2Slogwang handle_msg(struct ff_msg *msg, uint16_t proc_id)
1557127dd473Swhl739 {
15587abd0fb2Slogwang     switch (msg->msg_type) {
1559df6ad731Slogwang         case FF_SYSCTL:
1560d7140ab7Sfengbojiang(姜凤波)             handle_sysctl_msg(msg);
1561d7140ab7Sfengbojiang(姜凤波)             break;
1562d7140ab7Sfengbojiang(姜凤波)         case FF_IOCTL:
1563127dd473Swhl739 #ifdef INET6
1564df6ad731Slogwang         case FF_IOCTL6:
1565144c6bcdSlogwang #endif
1566127dd473Swhl739             handle_ioctl_msg(msg);
1567144c6bcdSlogwang             break;
1568e7741141SAndy         case FF_ROUTE:
1569127dd473Swhl739             handle_route_msg(msg);
1570e7741141SAndy             break;
15713b2bd0f6Slogwang         case FF_TOP:
15723b2bd0f6Slogwang             handle_top_msg(msg);
1573127dd473Swhl739             break;
1574127dd473Swhl739 #ifdef FF_NETGRAPH
1575127dd473Swhl739         case FF_NGCTL:
1576127dd473Swhl739             handle_ngctl_msg(msg);
1577127dd473Swhl739             break;
1578127dd473Swhl739 #endif
15793b2bd0f6Slogwang #ifdef FF_IPFW
15803b2bd0f6Slogwang         case FF_IPFW_CTL:
158103df98deSfengbojiang             handle_ipfw_msg(msg);
158203df98deSfengbojiang             break;
158303df98deSfengbojiang #endif
158447507c15Spengtian         case FF_TRAFFIC:
158547507c15Spengtian             handle_traffic_msg(msg);
158647507c15Spengtian             break;
158747507c15Spengtian #ifdef FF_KNI
158847507c15Spengtian         case FF_KNICTL:
15897abd0fb2Slogwang             handle_knictl_msg(msg);
1590127dd473Swhl739             break;
15917abd0fb2Slogwang #endif
15927abd0fb2Slogwang         default:
15938d0052bcSfengbojiang             handle_default_msg(msg);
15948d0052bcSfengbojiang             break;
15958d0052bcSfengbojiang     }
15968d0052bcSfengbojiang     if (rte_ring_enqueue(msg_ring[proc_id].ring[msg->msg_type], msg) < 0) {
15978d0052bcSfengbojiang         if (msg->original_buf) {
15988d0052bcSfengbojiang             rte_free(msg->buf_addr);
15998d0052bcSfengbojiang             msg->buf_addr = msg->original_buf;
16008d0052bcSfengbojiang             msg->buf_len = msg->original_buf_len;
16018d0052bcSfengbojiang             msg->original_buf = NULL;
16028d0052bcSfengbojiang         }
16037abd0fb2Slogwang 
16047abd0fb2Slogwang         rte_mempool_put(message_pool, msg);
16057abd0fb2Slogwang     }
16068d0052bcSfengbojiang }
16077abd0fb2Slogwang 
16088d0052bcSfengbojiang static inline int
16098d0052bcSfengbojiang process_msg_ring(uint16_t proc_id, struct rte_mbuf **pkts_burst)
16108d0052bcSfengbojiang {
16117abd0fb2Slogwang     /* read msg from ring buf and to process */
16128d0052bcSfengbojiang     uint16_t nb_rb;
16138d0052bcSfengbojiang     int i;
16148d0052bcSfengbojiang 
16158d0052bcSfengbojiang     nb_rb = rte_ring_dequeue_burst(msg_ring[proc_id].ring[0],
16168d0052bcSfengbojiang         (void **)pkts_burst, MAX_PKT_BURST, NULL);
16178d0052bcSfengbojiang 
16188d0052bcSfengbojiang     if (likely(nb_rb == 0))
16198d0052bcSfengbojiang         return 0;
1620a9643ea8Slogwang 
1621a9643ea8Slogwang     for (i = 0; i < nb_rb; ++i) {
1622a9643ea8Slogwang         handle_msg((struct ff_msg *)pkts_burst[i], proc_id);
1623a9643ea8Slogwang     }
1624a9643ea8Slogwang 
1625a9643ea8Slogwang     return 0;
1626a9643ea8Slogwang }
1627a9643ea8Slogwang 
1628a9643ea8Slogwang /* Send burst of packets on an output interface */
1629a9643ea8Slogwang static inline int
1630a9643ea8Slogwang send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port)
1631a9643ea8Slogwang {
1632a9643ea8Slogwang     struct rte_mbuf **m_table;
1633a9643ea8Slogwang     int ret;
1634a9643ea8Slogwang     uint16_t queueid;
1635a9643ea8Slogwang 
1636819aafb6Sjinhao2     queueid = qconf->tx_queue_id[port];
1637a9643ea8Slogwang     m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;
1638a9643ea8Slogwang 
16394dfcdbccSjinhao2     if (unlikely(ff_global_cfg.pcap.enable)) {
16404dfcdbccSjinhao2         uint16_t i;
1641a9643ea8Slogwang         for (i = 0; i < n; i++) {
1642a9643ea8Slogwang             ff_dump_packets( ff_global_cfg.pcap.save_path, m_table[i],
1643a9643ea8Slogwang                ff_global_cfg.pcap.snap_len, ff_global_cfg.pcap.save_len);
1644a9643ea8Slogwang         }
164526848803Sjin.hao1     }
164626848803Sjin.hao1 
164726848803Sjin.hao1     ret = rte_eth_tx_burst(port, queueid, m_table, n);
164826848803Sjin.hao1     ff_traffic.tx_packets += ret;
16495bf882b4S10077240     uint16_t i;
1650ef5ab859S10077240     for (i = 0; i < ret; i++) {
16515bf882b4S10077240         ff_traffic.tx_bytes += rte_pktmbuf_pkt_len(m_table[i]);
1652ef5ab859S10077240 #ifdef FF_USE_PAGE_ARRAY
165326848803Sjin.hao1         if (qconf->tx_mbufs[port].bsd_m_table[i])
165449d7ad40Sjin.hao1             ff_enq_tx_bsdmbuf(port, qconf->tx_mbufs[port].bsd_m_table[i], m_table[i]->nb_segs);
165549d7ad40Sjin.hao1 #endif
165649d7ad40Sjin.hao1     }
16575bf882b4S10077240     if (unlikely(ret < n)) {
1658ef5ab859S10077240         do {
1659ef5ab859S10077240             rte_pktmbuf_free(m_table[ret]);
1660ef5ab859S10077240 #ifdef FF_USE_PAGE_ARRAY
166149d7ad40Sjin.hao1             if ( qconf->tx_mbufs[port].bsd_m_table[ret] )
166249d7ad40Sjin.hao1                 ff_mbuf_free(qconf->tx_mbufs[port].bsd_m_table[ret]);
1663a9643ea8Slogwang #endif
1664a9643ea8Slogwang         } while (++ret < n);
1665a9643ea8Slogwang     }
1666a9643ea8Slogwang     return 0;
1667a9643ea8Slogwang }
1668a9643ea8Slogwang 
1669a9643ea8Slogwang /* Enqueue a single packet, and send burst if queue is filled */
1670a9643ea8Slogwang static inline int
1671a9643ea8Slogwang send_single_packet(struct rte_mbuf *m, uint8_t port)
1672a9643ea8Slogwang {
1673a9643ea8Slogwang     uint16_t len;
1674a9643ea8Slogwang     struct lcore_conf *qconf;
1675a9643ea8Slogwang 
1676a9643ea8Slogwang     qconf = &lcore_conf;
1677a9643ea8Slogwang     len = qconf->tx_mbufs[port].len;
1678a9643ea8Slogwang     qconf->tx_mbufs[port].m_table[len] = m;
1679a9643ea8Slogwang     len++;
1680a9643ea8Slogwang 
1681a9643ea8Slogwang     /* enough pkts to be sent */
1682a9643ea8Slogwang     if (unlikely(len == MAX_PKT_BURST)) {
1683a9643ea8Slogwang         send_burst(qconf, MAX_PKT_BURST, port);
1684a9643ea8Slogwang         len = 0;
1685a9643ea8Slogwang     }
1686a9643ea8Slogwang 
1687a9643ea8Slogwang     qconf->tx_mbufs[port].len = len;
1688a9643ea8Slogwang     return 0;
1689a9643ea8Slogwang }
1690a9643ea8Slogwang 
1691a9643ea8Slogwang int
16925bf882b4S10077240 ff_dpdk_if_send(struct ff_dpdk_if_context *ctx, void *m,
16935bf882b4S10077240     int total)
16945bf882b4S10077240 {
16955bf882b4S10077240 #ifdef FF_USE_PAGE_ARRAY
16965bf882b4S10077240     struct lcore_conf *qconf = &lcore_conf;
16975bf882b4S10077240     int    len = 0;
16985bf882b4S10077240 
16995bf882b4S10077240     len = ff_if_send_onepkt(ctx, m,total);
17005bf882b4S10077240     if (unlikely(len == MAX_PKT_BURST)) {
17015bf882b4S10077240         send_burst(qconf, MAX_PKT_BURST, ctx->port_id);
17025bf882b4S10077240         len = 0;
1703ef5ab859S10077240     }
1704a9643ea8Slogwang     qconf->tx_mbufs[ctx->port_id].len = len;
1705a9643ea8Slogwang     return 0;
1706a9643ea8Slogwang #endif
1707a9643ea8Slogwang     struct rte_mempool *mbuf_pool = pktmbuf_pool[lcore_conf.socket_id];
1708a9643ea8Slogwang     struct rte_mbuf *head = rte_pktmbuf_alloc(mbuf_pool);
1709a9643ea8Slogwang     if (head == NULL) {
1710a9643ea8Slogwang         ff_mbuf_free(m);
1711a9643ea8Slogwang         return -1;
1712213fa7b3Slogwang     }
1713a9643ea8Slogwang 
1714a9643ea8Slogwang     head->pkt_len = total;
1715a9643ea8Slogwang     head->nb_segs = 0;
1716a9643ea8Slogwang 
1717a9643ea8Slogwang     int off = 0;
1718213fa7b3Slogwang     struct rte_mbuf *cur = head, *prev = NULL;
1719a9643ea8Slogwang     while(total > 0) {
1720a9643ea8Slogwang         if (cur == NULL) {
1721a9643ea8Slogwang             cur = rte_pktmbuf_alloc(mbuf_pool);
1722a9643ea8Slogwang             if (cur == NULL) {
1723a9643ea8Slogwang                 rte_pktmbuf_free(head);
1724a9643ea8Slogwang                 ff_mbuf_free(m);
1725a9643ea8Slogwang                 return -1;
1726a8636dd5Szhanghaisen             }
1727a8636dd5Szhanghaisen         }
1728a8636dd5Szhanghaisen 
1729a8636dd5Szhanghaisen         if (prev != NULL) {
1730a8636dd5Szhanghaisen             prev->next = cur;
1731a8636dd5Szhanghaisen         }
1732a9643ea8Slogwang         head->nb_segs++;
1733a9643ea8Slogwang 
1734a9643ea8Slogwang         prev = cur;
1735a9643ea8Slogwang         void *data = rte_pktmbuf_mtod(cur, void*);
1736a9643ea8Slogwang         int len = total > RTE_MBUF_DEFAULT_DATAROOM ? RTE_MBUF_DEFAULT_DATAROOM : total;
1737a9643ea8Slogwang         int ret = ff_mbuf_copydata(m, data, off, len);
1738a9643ea8Slogwang         if (ret < 0) {
1739a9643ea8Slogwang             rte_pktmbuf_free(head);
1740a9643ea8Slogwang             ff_mbuf_free(m);
1741a9643ea8Slogwang             return -1;
1742a9643ea8Slogwang         }
1743a9643ea8Slogwang 
1744a9643ea8Slogwang 
1745213fa7b3Slogwang         cur->data_len = len;
1746a9643ea8Slogwang         off += len;
1747a9643ea8Slogwang         total -= len;
1748213fa7b3Slogwang         cur = NULL;
1749213fa7b3Slogwang     }
1750213fa7b3Slogwang 
17518cfa2923Slogwang     struct ff_tx_offload offload = {0};
17528cfa2923Slogwang     ff_mbuf_tx_offload(m, &offload);
1753213fa7b3Slogwang 
17548cfa2923Slogwang     void *data = rte_pktmbuf_mtod(head, void*);
17554418919fSjohnjiang 
17568cfa2923Slogwang     if (offload.ip_csum) {
17574418919fSjohnjiang         /* ipv6 not supported yet */
17588cfa2923Slogwang         struct rte_ipv4_hdr *iph;
17598cfa2923Slogwang         int iph_len;
17608cfa2923Slogwang         iph = (struct rte_ipv4_hdr *)(data + RTE_ETHER_HDR_LEN);
17614418919fSjohnjiang         iph_len = (iph->version_ihl & 0x0f) << 2;
17628cfa2923Slogwang 
1763213fa7b3Slogwang         head->ol_flags |= PKT_TX_IP_CKSUM | PKT_TX_IPV4;
1764213fa7b3Slogwang         head->l2_len = RTE_ETHER_HDR_LEN;
1765213fa7b3Slogwang         head->l3_len = iph_len;
17664418919fSjohnjiang     }
17678cfa2923Slogwang 
17684418919fSjohnjiang     if (ctx->hw_features.tx_csum_l4) {
17698cfa2923Slogwang         struct rte_ipv4_hdr *iph;
17708cfa2923Slogwang         int iph_len;
1771213fa7b3Slogwang         iph = (struct rte_ipv4_hdr *)(data + RTE_ETHER_HDR_LEN);
1772213fa7b3Slogwang         iph_len = (iph->version_ihl & 0x0f) << 2;
17734418919fSjohnjiang 
17748cfa2923Slogwang         if (offload.tcp_csum) {
1775213fa7b3Slogwang             head->ol_flags |= PKT_TX_TCP_CKSUM;
1776213fa7b3Slogwang             head->l2_len = RTE_ETHER_HDR_LEN;
17778cfa2923Slogwang             head->l3_len = iph_len;
17788cfa2923Slogwang         }
17798cfa2923Slogwang 
17808cfa2923Slogwang         /*
17818cfa2923Slogwang          *  TCP segmentation offload.
17828cfa2923Slogwang          *
17838cfa2923Slogwang          *  - set the PKT_TX_TCP_SEG flag in mbuf->ol_flags (this flag
17848cfa2923Slogwang          *    implies PKT_TX_TCP_CKSUM)
17858cfa2923Slogwang          *  - set the flag PKT_TX_IPV4 or PKT_TX_IPV6
17868cfa2923Slogwang          *  - if it's IPv4, set the PKT_TX_IP_CKSUM flag and
17878cfa2923Slogwang          *    write the IP checksum to 0 in the packet
17888cfa2923Slogwang          *  - fill the mbuf offload information: l2_len,
17898cfa2923Slogwang          *    l3_len, l4_len, tso_segsz
17908cfa2923Slogwang          *  - calculate the pseudo header checksum without taking ip_len
17918cfa2923Slogwang          *    in account, and set it in the TCP header. Refer to
1792213fa7b3Slogwang          *    rte_ipv4_phdr_cksum() and rte_ipv6_phdr_cksum() that can be
17934418919fSjohnjiang          *    used as helpers.
17948cfa2923Slogwang          */
17954418919fSjohnjiang         if (offload.tso_seg_size) {
17968cfa2923Slogwang             struct rte_tcp_hdr *tcph;
17978cfa2923Slogwang             int tcph_len;
17988cfa2923Slogwang             tcph = (struct rte_tcp_hdr *)((char *)iph + iph_len);
1799213fa7b3Slogwang             tcph_len = (tcph->data_off & 0xf0) >> 2;
18008cfa2923Slogwang             tcph->cksum = rte_ipv4_phdr_cksum(iph, PKT_TX_TCP_SEG);
1801213fa7b3Slogwang 
1802213fa7b3Slogwang             head->ol_flags |= PKT_TX_TCP_SEG;
1803213fa7b3Slogwang             head->l4_len = tcph_len;
1804213fa7b3Slogwang             head->tso_segsz = offload.tso_seg_size;
1805213fa7b3Slogwang         }
18064418919fSjohnjiang 
18078cfa2923Slogwang         if (offload.udp_csum) {
1808213fa7b3Slogwang             head->ol_flags |= PKT_TX_UDP_CKSUM;
1809213fa7b3Slogwang             head->l2_len = RTE_ETHER_HDR_LEN;
1810a9643ea8Slogwang             head->l3_len = iph_len;
1811a9643ea8Slogwang         }
1812a9643ea8Slogwang     }
1813a9643ea8Slogwang 
1814a9643ea8Slogwang     ff_mbuf_free(m);
1815a9643ea8Slogwang 
1816a9643ea8Slogwang     return send_single_packet(head, ctx->port_id);
1817a9643ea8Slogwang }
1818a9643ea8Slogwang 
1819a9643ea8Slogwang static int
1820a9643ea8Slogwang main_loop(void *arg)
1821a9643ea8Slogwang {
1822c506e436Sfengbojiang     struct loop_routine *lr = (struct loop_routine *)arg;
1823e7741141SAndy 
18242bfe3f2eSlogwang     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
1825a9643ea8Slogwang     uint64_t prev_tsc, diff_tsc, cur_tsc, usch_tsc, div_tsc, usr_tsc, sys_tsc, end_tsc, idle_sleep_tsc;
182659bb71f6Sfengbojiang(姜凤波)     int i, j, nb_rx, idle;
1827213fa7b3Slogwang     uint16_t port_id, queue_id;
1828a9643ea8Slogwang     struct lcore_conf *qconf;
182959bb71f6Sfengbojiang(姜凤波)     uint64_t drain_tsc = 0;
183059bb71f6Sfengbojiang(姜凤波)     struct ff_dpdk_if_context *ctx;
183159bb71f6Sfengbojiang(姜凤波) 
183259bb71f6Sfengbojiang(姜凤波)     if (pkt_tx_delay) {
1833a9643ea8Slogwang         drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * pkt_tx_delay;
18348fecf4ddSAndy     }
1835a9643ea8Slogwang 
1836a9643ea8Slogwang     prev_tsc = 0;
1837a9643ea8Slogwang     usch_tsc = 0;
1838a9643ea8Slogwang 
1839a9643ea8Slogwang     qconf = &lcore_conf;
1840a9643ea8Slogwang 
1841a9643ea8Slogwang     while (1) {
1842a9643ea8Slogwang         cur_tsc = rte_rdtsc();
1843a9643ea8Slogwang         if (unlikely(freebsd_clock.expire < cur_tsc)) {
1844e7741141SAndy             rte_timer_manage();
1845e7741141SAndy         }
1846e7741141SAndy 
1847e7741141SAndy         idle = 1;
1848a9643ea8Slogwang         sys_tsc = 0;
1849a9643ea8Slogwang         usr_tsc = 0;
1850a9643ea8Slogwang         usr_cb_tsc = 0;
1851a9643ea8Slogwang 
185259bb71f6Sfengbojiang(姜凤波)         /*
185385aab0a6Slogwang          * TX burst queue drain
185485aab0a6Slogwang          */
1855a9643ea8Slogwang         diff_tsc = cur_tsc - prev_tsc;
1856a9643ea8Slogwang         if (unlikely(diff_tsc >= drain_tsc)) {
1857e7741141SAndy             for (i = 0; i < qconf->nb_tx_port; i++) {
1858e7741141SAndy                 port_id = qconf->tx_port_id[i];
185985aab0a6Slogwang                 if (qconf->tx_mbufs[port_id].len == 0)
1860a9643ea8Slogwang                     continue;
1861a9643ea8Slogwang 
1862a9643ea8Slogwang                 idle = 0;
1863a9643ea8Slogwang 
1864a9643ea8Slogwang                 send_burst(qconf,
1865a9643ea8Slogwang                     qconf->tx_mbufs[port_id].len,
1866a9643ea8Slogwang                     port_id);
1867a9643ea8Slogwang                 qconf->tx_mbufs[port_id].len = 0;
1868a9643ea8Slogwang             }
1869a9643ea8Slogwang 
1870a9643ea8Slogwang             prev_tsc = cur_tsc;
1871a9643ea8Slogwang         }
1872a9643ea8Slogwang 
1873a9643ea8Slogwang         /*
1874a9643ea8Slogwang          * Read packet from RX queues
1875213fa7b3Slogwang          */
1876a9643ea8Slogwang         for (i = 0; i < qconf->nb_rx_queue; ++i) {
1877dc42d452Swhl739             port_id = qconf->rx_queue_list[i].port_id;
1878a9643ea8Slogwang             queue_id = qconf->rx_queue_list[i].queue_id;
1879a9643ea8Slogwang             ctx = veth_ctx[port_id];
1880a9643ea8Slogwang 
1881dc42d452Swhl739 #ifdef FF_KNI
1882a9643ea8Slogwang             if (enable_kni && rte_eal_process_type() == RTE_PROC_PRIMARY) {
1883eb5902d9Slogwang                 ff_kni_process(port_id, queue_id, pkts_burst, MAX_PKT_BURST);
1884a9643ea8Slogwang             }
1885a9643ea8Slogwang #endif
1886a9643ea8Slogwang 
1887a9643ea8Slogwang             idle &= !process_dispatch_ring(port_id, queue_id, pkts_burst, ctx);
1888a9643ea8Slogwang 
1889a9643ea8Slogwang             nb_rx = rte_eth_rx_burst(port_id, queue_id, pkts_burst,
1890e7741141SAndy                 MAX_PKT_BURST);
1891e7741141SAndy             if (nb_rx == 0)
1892a9643ea8Slogwang                 continue;
1893a9643ea8Slogwang 
1894a9643ea8Slogwang             idle = 0;
1895a9643ea8Slogwang 
1896a9643ea8Slogwang             /* Prefetch first packets */
1897a9643ea8Slogwang             for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) {
1898a9643ea8Slogwang                 rte_prefetch0(rte_pktmbuf_mtod(
1899a9643ea8Slogwang                         pkts_burst[j], void *));
1900a9643ea8Slogwang             }
1901a9643ea8Slogwang 
1902213fa7b3Slogwang             /* Prefetch and handle already prefetched packets */
1903a9643ea8Slogwang             for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
1904a9643ea8Slogwang                 rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
1905a9643ea8Slogwang                         j + PREFETCH_OFFSET], void *));
1906a9643ea8Slogwang                 process_packets(port_id, queue_id, &pkts_burst[j], 1, ctx, 0);
1907213fa7b3Slogwang             }
1908a9643ea8Slogwang 
1909a9643ea8Slogwang             /* Handle remaining prefetched packets */
1910a9643ea8Slogwang             for (; j < nb_rx; j++) {
19118d0052bcSfengbojiang                 process_packets(port_id, queue_id, &pkts_burst[j], 1, ctx, 0);
19127abd0fb2Slogwang             }
1913e7741141SAndy         }
1914e7741141SAndy 
191559bb71f6Sfengbojiang(姜凤波)         process_msg_ring(qconf->proc_id, pkts_burst);
19168fecf4ddSAndy 
1917a9643ea8Slogwang         div_tsc = rte_rdtsc();
1918a9643ea8Slogwang 
1919e7741141SAndy         if (likely(lr->loop != NULL && (!idle || cur_tsc - usch_tsc >= drain_tsc))) {
1920c506e436Sfengbojiang             usch_tsc = cur_tsc;
1921c506e436Sfengbojiang             lr->loop(lr->arg);
1922c506e436Sfengbojiang         }
1923c506e436Sfengbojiang 
1924c506e436Sfengbojiang         idle_sleep_tsc = rte_rdtsc();
1925c506e436Sfengbojiang         if (likely(idle && idle_sleep)) {
1926c506e436Sfengbojiang             usleep(idle_sleep);
1927c506e436Sfengbojiang             end_tsc = rte_rdtsc();
19288fecf4ddSAndy         } else {
1929c506e436Sfengbojiang             end_tsc = idle_sleep_tsc;
19308fecf4ddSAndy         }
1931e7741141SAndy 
1932e7741141SAndy         usr_tsc = usr_cb_tsc;
1933e7741141SAndy         if (usch_tsc == cur_tsc) {
193403df98deSfengbojiang             usr_tsc += idle_sleep_tsc - div_tsc;
1935e7741141SAndy         }
1936e7741141SAndy 
193703df98deSfengbojiang         if (!idle) {
193803df98deSfengbojiang             sys_tsc = div_tsc - cur_tsc - usr_cb_tsc;
193903df98deSfengbojiang             ff_top_status.sys_tsc += sys_tsc;
1940e7741141SAndy         }
194103df98deSfengbojiang 
1942a9643ea8Slogwang         ff_top_status.usr_tsc += usr_tsc;
1943eb5902d9Slogwang         ff_top_status.work_tsc += end_tsc - cur_tsc;
1944eb5902d9Slogwang         ff_top_status.idle_tsc += end_tsc - cur_tsc - usr_tsc - sys_tsc;
1945a9643ea8Slogwang 
1946a9643ea8Slogwang         ff_top_status.loops++;
1947a9643ea8Slogwang     }
1948a9643ea8Slogwang 
1949a9643ea8Slogwang     return 0;
195085aab0a6Slogwang }
195185aab0a6Slogwang 
195285aab0a6Slogwang int
195385aab0a6Slogwang ff_dpdk_if_up(void) {
195485aab0a6Slogwang     int i;
195580a6164cSYuYang     struct lcore_conf *qconf = &lcore_conf;
1956a9643ea8Slogwang     for (i = 0; i < qconf->nb_tx_port; i++) {
1957a9643ea8Slogwang         uint16_t port_id = qconf->tx_port_id[i];
1958a9643ea8Slogwang 
1959a9643ea8Slogwang         struct ff_port_cfg *pconf = &qconf->port_cfgs[port_id];
1960a9643ea8Slogwang         veth_ctx[port_id] = ff_veth_attach(pconf);
1961a9643ea8Slogwang         if (veth_ctx[port_id] == NULL) {
1962a9643ea8Slogwang             rte_exit(EXIT_FAILURE, "ff_veth_attach failed");
1963a9643ea8Slogwang         }
1964a9643ea8Slogwang     }
1965a9643ea8Slogwang 
196640600211Slogwang     return 0;
196740600211Slogwang }
1968a9643ea8Slogwang 
1969a9643ea8Slogwang void
19708d76b62eSfengbojiang ff_dpdk_run(loop_func_t loop, void *arg) {
1971a9643ea8Slogwang     struct loop_routine *lr = rte_malloc(NULL,
197240600211Slogwang         sizeof(struct loop_routine), 0);
1973a9643ea8Slogwang     lr->loop = loop;
1974a9643ea8Slogwang     lr->arg = arg;
1975a9643ea8Slogwang     rte_eal_mp_remote_launch(main_loop, lr, CALL_MAIN);
1976a9643ea8Slogwang     rte_eal_mp_wait_lcore();
1977a9643ea8Slogwang     rte_free(lr);
1978fa552ee2SJianfeng Tan }
1979a9643ea8Slogwang 
1980a9643ea8Slogwang void
1981a9643ea8Slogwang ff_dpdk_pktmbuf_free(void *m)
1982a9643ea8Slogwang {
1983a9643ea8Slogwang     rte_pktmbuf_free_seg((struct rte_mbuf *)m);
1984a9643ea8Slogwang }
1985a9643ea8Slogwang 
1986a9643ea8Slogwang static uint32_t
1987a9643ea8Slogwang toeplitz_hash(unsigned keylen, const uint8_t *key,
1988a9643ea8Slogwang     unsigned datalen, const uint8_t *data)
1989a9643ea8Slogwang {
1990a9643ea8Slogwang     uint32_t hash = 0, v;
1991a9643ea8Slogwang     u_int i, b;
1992a9643ea8Slogwang 
1993a9643ea8Slogwang     /* XXXRW: Perhaps an assertion about key length vs. data length? */
1994a9643ea8Slogwang 
1995a9643ea8Slogwang     v = (key[0]<<24) + (key[1]<<16) + (key[2] <<8) + key[3];
1996a9643ea8Slogwang     for (i = 0; i < datalen; i++) {
1997a9643ea8Slogwang         for (b = 0; b < 8; b++) {
1998a9643ea8Slogwang             if (data[i] & (1<<(7-b)))
1999a9643ea8Slogwang                 hash ^= v;
2000a9643ea8Slogwang             v <<= 1;
2001a9643ea8Slogwang             if ((i + 4) < keylen &&
2002a9643ea8Slogwang                 (key[i+4] & (1<<(7-b))))
2003a9643ea8Slogwang                 v |= 1;
2004a9643ea8Slogwang         }
2005aa61e4b5Sfengbojiang(姜凤波)     }
2006aa61e4b5Sfengbojiang(姜凤波)     return (hash);
2007aa61e4b5Sfengbojiang(姜凤波) }
2008aa61e4b5Sfengbojiang(姜凤波) 
2009aa61e4b5Sfengbojiang(姜凤波) int
2010aa61e4b5Sfengbojiang(姜凤波) ff_in_pcbladdr(uint16_t family, void *faddr, uint16_t fport, void *laddr)
2011aa61e4b5Sfengbojiang(姜凤波) {
2012aa61e4b5Sfengbojiang(姜凤波)     int ret = 0;
2013aa61e4b5Sfengbojiang(姜凤波)     uint16_t fa;
2014aa61e4b5Sfengbojiang(姜凤波) 
2015aa61e4b5Sfengbojiang(姜凤波)     if (!pcblddr_fun)
2016aa61e4b5Sfengbojiang(姜凤波)         return ret;
2017aa61e4b5Sfengbojiang(姜凤波) 
2018aa61e4b5Sfengbojiang(姜凤波)     if (family == AF_INET)
2019aa61e4b5Sfengbojiang(姜凤波)         fa = AF_INET;
2020aa61e4b5Sfengbojiang(姜凤波)     else if (family == AF_INET6_FREEBSD)
2021aa61e4b5Sfengbojiang(姜凤波)         fa = AF_INET6_LINUX;
2022aa61e4b5Sfengbojiang(姜凤波)     else
2023aa61e4b5Sfengbojiang(姜凤波)         return EADDRNOTAVAIL;
2024aa61e4b5Sfengbojiang(姜凤波) 
2025aa61e4b5Sfengbojiang(姜凤波)     ret = (*pcblddr_fun)(fa, faddr, fport, laddr);
2026aa61e4b5Sfengbojiang(姜凤波) 
2027aa61e4b5Sfengbojiang(姜凤波)     return ret;
2028aa61e4b5Sfengbojiang(姜凤波) }
2029aa61e4b5Sfengbojiang(姜凤波) 
2030aa61e4b5Sfengbojiang(姜凤波) void
2031aa61e4b5Sfengbojiang(姜凤波) ff_regist_pcblddr_fun(pcblddr_func_t func)
2032a9e7dcf4Slogwang {
2033a9e7dcf4Slogwang     pcblddr_fun = func;
2034a9643ea8Slogwang }
2035a9643ea8Slogwang 
203680a6164cSYuYang int
203780a6164cSYuYang ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr,
2038a9643ea8Slogwang     uint16_t sport, uint16_t dport)
203985aab0a6Slogwang {
2040a9643ea8Slogwang     struct lcore_conf *qconf = &lcore_conf;
2041a9643ea8Slogwang     struct ff_dpdk_if_context *ctx = ff_veth_softc_to_hostc(softc);
2042a9643ea8Slogwang     uint16_t nb_queues = qconf->nb_queue_list[ctx->port_id];
2043a9e7dcf4Slogwang 
204480a6164cSYuYang     if (nb_queues <= 1) {
2045a9e7dcf4Slogwang         return 1;
2046a9643ea8Slogwang     }
2047a9643ea8Slogwang 
2048a9643ea8Slogwang     uint16_t reta_size = rss_reta_size[ctx->port_id];
2049a9643ea8Slogwang     uint16_t queueid = qconf->tx_queue_id[ctx->port_id];
2050a9643ea8Slogwang 
2051a9643ea8Slogwang     uint8_t data[sizeof(saddr) + sizeof(daddr) + sizeof(sport) +
2052a9643ea8Slogwang         sizeof(dport)];
2053a9643ea8Slogwang 
2054a9643ea8Slogwang     unsigned datalen = 0;
2055a9643ea8Slogwang 
2056a9643ea8Slogwang     bcopy(&saddr, &data[datalen], sizeof(saddr));
2057a9643ea8Slogwang     datalen += sizeof(saddr);
2058a9643ea8Slogwang 
2059a9643ea8Slogwang     bcopy(&daddr, &data[datalen], sizeof(daddr));
2060a9643ea8Slogwang     datalen += sizeof(daddr);
2061a9643ea8Slogwang 
2062a9643ea8Slogwang     bcopy(&sport, &data[datalen], sizeof(sport));
206334e766d2S10077240     datalen += sizeof(sport);
2064f41205e9Sfengbojiang 
2065f41205e9Sfengbojiang     bcopy(&dport, &data[datalen], sizeof(dport));
206680a6164cSYuYang     datalen += sizeof(dport);
2067a9643ea8Slogwang 
2068eb5902d9Slogwang     uint32_t hash = 0;
2069eb5902d9Slogwang     hash = toeplitz_hash(rsskey_len, rsskey, datalen, data);
2070eb5902d9Slogwang 
2071eb5902d9Slogwang     return ((hash & (reta_size - 1)) % nb_queues) == queueid;
2072eb5902d9Slogwang }
2073eb5902d9Slogwang 
207439be5a50Slogwang void
207539be5a50Slogwang ff_regist_packet_dispatcher(dispatch_func_t func)
207639be5a50Slogwang {
207739be5a50Slogwang     packet_dispatcher = func;
207839be5a50Slogwang }
207939be5a50Slogwang 
208039be5a50Slogwang uint64_t
208139be5a50Slogwang ff_get_tsc_ns()
208239be5a50Slogwang {
2083     uint64_t cur_tsc = rte_rdtsc();
2084     uint64_t hz = rte_get_tsc_hz();
2085     return ((double)cur_tsc/(double)hz) * NS_PER_S;
2086 }
2087 
2088