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 = ð_type;
102171412662SHawker pattern_[0].mask = ð_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