4 * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/queue.h>
36 #include <sys/socket.h>
50 #include <rte_common.h>
52 #include <rte_memory.h>
53 #include <rte_memcpy.h>
54 #include <rte_memzone.h>
56 #include <rte_per_lcore.h>
57 #include <rte_launch.h>
58 #include <rte_atomic.h>
59 #include <rte_cycles.h>
60 #include <rte_prefetch.h>
61 #include <rte_lcore.h>
62 #include <rte_per_lcore.h>
63 #include <rte_branch_prediction.h>
64 #include <rte_interrupts.h>
66 #include <rte_random.h>
67 #include <rte_debug.h>
68 #include <rte_ether.h>
69 #include <rte_ethdev.h>
71 #include <rte_mempool.h>
73 #include <rte_memcpy.h>
77 #include <rte_spinlock.h>
79 #include <cmdline_rdline.h>
80 #include <cmdline_parse.h>
81 #include <cmdline_parse_num.h>
82 #include <cmdline_parse_string.h>
83 #include <cmdline_parse_ipaddr.h>
84 #include <cmdline_parse_etheraddr.h>
85 #include <cmdline_socket.h>
90 #include <rte_devargs.h>
93 #include "rte_byteorder.h"
94 #include "rte_cpuflags.h"
95 #include "rte_eth_bond.h"
97 #define RTE_LOGTYPE_DCB RTE_LOGTYPE_USER1
99 #define NB_MBUF (1024*8)
101 #define MAX_PKT_BURST 32
102 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
103 #define BURST_RX_INTERVAL_NS (10) /* RX poll interval ~100ns */
106 * RX and TX Prefetch, Host, and Write-back threshold values should be
107 * carefully set for optimal performance. Consult the network
108 * controller's datasheet and supporting DPDK documentation for guidance
109 * on how these parameters should be set.
111 #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
112 #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
113 #define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */
114 #define RX_FTHRESH (MAX_PKT_BURST * 2)/**< Default values of RX free threshold reg. */
117 * These default values are optimized for use with the Intel(R) 82599 10 GbE
118 * Controller and the DPDK ixgbe PMD. Consider using other values for other
119 * network controllers and/or network drivers.
121 #define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */
122 #define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */
123 #define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */
126 * Configurable number of RX/TX ring descriptors
128 #define RTE_RX_DESC_DEFAULT 128
129 #define RTE_TX_DESC_DEFAULT 512
136 /* not defined under linux */
138 #define NIPQUAD_FMT "%u.%u.%u.%u"
142 #define PRINT_MAC(addr) printf("%02"PRIx8":%02"PRIx8":%02"PRIx8 \
143 ":%02"PRIx8":%02"PRIx8":%02"PRIx8, \
144 addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], \
145 addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5])
147 uint8_t slaves
[RTE_MAX_ETHPORTS
];
148 uint8_t slaves_count
;
150 static uint8_t BOND_PORT
= 0xff;
152 static struct rte_mempool
*mbuf_pool
;
154 static struct rte_eth_conf port_conf
= {
156 .mq_mode
= ETH_MQ_RX_NONE
,
157 .max_rx_pkt_len
= ETHER_MAX_LEN
,
159 .header_split
= 0, /**< Header Split disabled */
160 .hw_ip_checksum
= 0, /**< IP checksum offload enabled */
161 .hw_vlan_filter
= 0, /**< VLAN filtering disabled */
162 .jumbo_frame
= 0, /**< Jumbo Frame Support disabled */
163 .hw_strip_crc
= 0, /**< CRC stripped by hardware */
168 .rss_hf
= ETH_RSS_IP
,
172 .mq_mode
= ETH_MQ_TX_NONE
,
177 slave_port_init(uint8_t portid
, struct rte_mempool
*mbuf_pool
)
181 if (portid
>= rte_eth_dev_count())
182 rte_exit(EXIT_FAILURE
, "Invalid port\n");
184 retval
= rte_eth_dev_configure(portid
, 1, 1, &port_conf
);
186 rte_exit(EXIT_FAILURE
, "port %u: configuration failed (res=%d)\n",
190 retval
= rte_eth_rx_queue_setup(portid
, 0, RTE_RX_DESC_DEFAULT
,
191 rte_eth_dev_socket_id(portid
), NULL
,
194 rte_exit(retval
, " port %u: RX queue 0 setup failed (res=%d)",
198 retval
= rte_eth_tx_queue_setup(portid
, 0, RTE_TX_DESC_DEFAULT
,
199 rte_eth_dev_socket_id(portid
), NULL
);
202 rte_exit(retval
, "port %u: TX queue 0 setup failed (res=%d)",
205 retval
= rte_eth_dev_start(portid
);
208 "Start port %d failed (res=%d)",
211 struct ether_addr addr
;
213 rte_eth_macaddr_get(portid
, &addr
);
214 printf("Port %u MAC: ", (unsigned)portid
);
220 bond_port_init(struct rte_mempool
*mbuf_pool
)
225 retval
= rte_eth_bond_create("bond0", BONDING_MODE_ALB
,
226 0 /*SOCKET_ID_ANY*/);
228 rte_exit(EXIT_FAILURE
,
229 "Faled to create bond port\n");
231 BOND_PORT
= (uint8_t)retval
;
233 retval
= rte_eth_dev_configure(BOND_PORT
, 1, 1, &port_conf
);
235 rte_exit(EXIT_FAILURE
, "port %u: configuration failed (res=%d)\n",
239 retval
= rte_eth_rx_queue_setup(BOND_PORT
, 0, RTE_RX_DESC_DEFAULT
,
240 rte_eth_dev_socket_id(BOND_PORT
), NULL
,
243 rte_exit(retval
, " port %u: RX queue 0 setup failed (res=%d)",
247 retval
= rte_eth_tx_queue_setup(BOND_PORT
, 0, RTE_TX_DESC_DEFAULT
,
248 rte_eth_dev_socket_id(BOND_PORT
), NULL
);
251 rte_exit(retval
, "port %u: TX queue 0 setup failed (res=%d)",
254 for (i
= 0; i
< slaves_count
; i
++) {
255 if (rte_eth_bond_slave_add(BOND_PORT
, slaves
[i
]) == -1)
256 rte_exit(-1, "Oooops! adding slave (%u) to bond (%u) failed!\n",
257 slaves
[i
], BOND_PORT
);
261 retval
= rte_eth_dev_start(BOND_PORT
);
263 rte_exit(retval
, "Start port %d failed (res=%d)", BOND_PORT
, retval
);
265 rte_eth_promiscuous_enable(BOND_PORT
);
267 struct ether_addr addr
;
269 rte_eth_macaddr_get(BOND_PORT
, &addr
);
270 printf("Port %u MAC: ", (unsigned)BOND_PORT
);
276 get_vlan_offset(struct ether_hdr
*eth_hdr
, uint16_t *proto
)
278 size_t vlan_offset
= 0;
280 if (rte_cpu_to_be_16(ETHER_TYPE_VLAN
) == *proto
) {
281 struct vlan_hdr
*vlan_hdr
= (struct vlan_hdr
*)(eth_hdr
+ 1);
283 vlan_offset
= sizeof(struct vlan_hdr
);
284 *proto
= vlan_hdr
->eth_proto
;
286 if (rte_cpu_to_be_16(ETHER_TYPE_VLAN
) == *proto
) {
287 vlan_hdr
= vlan_hdr
+ 1;
289 *proto
= vlan_hdr
->eth_proto
;
290 vlan_offset
+= sizeof(struct vlan_hdr
);
296 struct global_flag_stru_t
{
297 int LcoreMainIsRunning
;
299 uint32_t port_packets
[4];
302 struct global_flag_stru_t global_flag_stru
;
303 struct global_flag_stru_t
*global_flag_stru_p
= &global_flag_stru
;
306 * Main thread that does the work, reading from INPUT_PORT
307 * and writing to OUTPUT_PORT
309 static int lcore_main(__attribute__((unused
)) void *arg1
)
311 struct rte_mbuf
*pkts
[MAX_PKT_BURST
] __rte_cache_aligned
;
312 struct ether_addr d_addr
;
314 struct ether_hdr
*eth_hdr
;
315 struct arp_hdr
*arp_hdr
;
316 struct ipv4_hdr
*ipv4_hdr
;
317 uint16_t ether_type
, offset
;
324 bond_ip
= BOND_IP_1
| (BOND_IP_2
<< 8) |
325 (BOND_IP_3
<< 16) | (BOND_IP_4
<< 24);
327 rte_spinlock_trylock(&global_flag_stru_p
->lock
);
329 while (global_flag_stru_p
->LcoreMainIsRunning
) {
330 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
331 rx_cnt
= rte_eth_rx_burst(BOND_PORT
, 0, pkts
, MAX_PKT_BURST
);
334 /* If didn't receive any packets, wait and go to next iteration */
340 /* Search incoming data for ARP packets and prepare response */
341 for (i
= 0; i
< rx_cnt
; i
++) {
342 if (rte_spinlock_trylock(&global_flag_stru_p
->lock
) == 1) {
343 global_flag_stru_p
->port_packets
[0]++;
344 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
346 eth_hdr
= rte_pktmbuf_mtod(pkts
[i
], struct ether_hdr
*);
347 ether_type
= eth_hdr
->ether_type
;
348 if (ether_type
== rte_cpu_to_be_16(ETHER_TYPE_VLAN
))
349 printf("VLAN taged frame, offset:");
350 offset
= get_vlan_offset(eth_hdr
, ðer_type
);
352 printf("%d\n", offset
);
353 if (ether_type
== rte_cpu_to_be_16(ETHER_TYPE_ARP
)) {
354 if (rte_spinlock_trylock(&global_flag_stru_p
->lock
) == 1) {
355 global_flag_stru_p
->port_packets
[1]++;
356 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
358 arp_hdr
= (struct arp_hdr
*)((char *)(eth_hdr
+ 1) + offset
);
359 if (arp_hdr
->arp_data
.arp_tip
== bond_ip
) {
360 if (arp_hdr
->arp_op
== rte_cpu_to_be_16(ARP_OP_REQUEST
)) {
361 arp_hdr
->arp_op
= rte_cpu_to_be_16(ARP_OP_REPLY
);
362 /* Switch src and dst data and set bonding MAC */
363 ether_addr_copy(ð_hdr
->s_addr
, ð_hdr
->d_addr
);
364 rte_eth_macaddr_get(BOND_PORT
, ð_hdr
->s_addr
);
365 ether_addr_copy(&arp_hdr
->arp_data
.arp_sha
, &arp_hdr
->arp_data
.arp_tha
);
366 arp_hdr
->arp_data
.arp_tip
= arp_hdr
->arp_data
.arp_sip
;
367 rte_eth_macaddr_get(BOND_PORT
, &d_addr
);
368 ether_addr_copy(&d_addr
, &arp_hdr
->arp_data
.arp_sha
);
369 arp_hdr
->arp_data
.arp_sip
= bond_ip
;
370 rte_eth_tx_burst(BOND_PORT
, 0, &pkts
[i
], 1);
373 rte_eth_tx_burst(BOND_PORT
, 0, NULL
, 0);
376 } else if (ether_type
== rte_cpu_to_be_16(ETHER_TYPE_IPv4
)) {
377 if (rte_spinlock_trylock(&global_flag_stru_p
->lock
) == 1) {
378 global_flag_stru_p
->port_packets
[2]++;
379 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
381 ipv4_hdr
= (struct ipv4_hdr
*)((char *)(eth_hdr
+ 1) + offset
);
382 if (ipv4_hdr
->dst_addr
== bond_ip
) {
383 ether_addr_copy(ð_hdr
->s_addr
, ð_hdr
->d_addr
);
384 rte_eth_macaddr_get(BOND_PORT
, ð_hdr
->s_addr
);
385 ipv4_hdr
->dst_addr
= ipv4_hdr
->src_addr
;
386 ipv4_hdr
->src_addr
= bond_ip
;
387 rte_eth_tx_burst(BOND_PORT
, 0, &pkts
[i
], 1);
392 /* Free processed packets */
394 rte_pktmbuf_free(pkts
[i
]);
396 rte_spinlock_trylock(&global_flag_stru_p
->lock
);
398 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
399 printf("BYE lcore_main\n");
403 struct cmd_obj_send_result
{
404 cmdline_fixed_string_t action
;
407 static inline void get_string(struct cmd_obj_send_result
*res
, char *buf
, uint8_t size
)
409 snprintf(buf
, size
, NIPQUAD_FMT
,
410 ((unsigned)((unsigned char *)&(res
->ip
.addr
.ipv4
))[0]),
411 ((unsigned)((unsigned char *)&(res
->ip
.addr
.ipv4
))[1]),
412 ((unsigned)((unsigned char *)&(res
->ip
.addr
.ipv4
))[2]),
413 ((unsigned)((unsigned char *)&(res
->ip
.addr
.ipv4
))[3])
416 static void cmd_obj_send_parsed(void *parsed_result
,
417 __attribute__((unused
)) struct cmdline
*cl
,
418 __attribute__((unused
)) void *data
)
421 struct cmd_obj_send_result
*res
= parsed_result
;
422 char ip_str
[INET6_ADDRSTRLEN
];
424 struct rte_mbuf
*created_pkt
;
425 struct ether_hdr
*eth_hdr
;
426 struct arp_hdr
*arp_hdr
;
431 if (res
->ip
.family
== AF_INET
)
432 get_string(res
, ip_str
, INET_ADDRSTRLEN
);
434 cmdline_printf(cl
, "Wrong IP format. Only IPv4 is supported\n");
436 bond_ip
= BOND_IP_1
| (BOND_IP_2
<< 8) |
437 (BOND_IP_3
<< 16) | (BOND_IP_4
<< 24);
439 created_pkt
= rte_pktmbuf_alloc(mbuf_pool
);
440 pkt_size
= sizeof(struct ether_hdr
) + sizeof(struct arp_hdr
);
441 created_pkt
->data_len
= pkt_size
;
442 created_pkt
->pkt_len
= pkt_size
;
444 eth_hdr
= rte_pktmbuf_mtod(created_pkt
, struct ether_hdr
*);
445 rte_eth_macaddr_get(BOND_PORT
, ð_hdr
->s_addr
);
446 memset(ð_hdr
->d_addr
, 0xFF, ETHER_ADDR_LEN
);
447 eth_hdr
->ether_type
= rte_cpu_to_be_16(ETHER_TYPE_ARP
);
449 arp_hdr
= (struct arp_hdr
*)((char *)eth_hdr
+ sizeof(struct ether_hdr
));
450 arp_hdr
->arp_hrd
= rte_cpu_to_be_16(ARP_HRD_ETHER
);
451 arp_hdr
->arp_pro
= rte_cpu_to_be_16(ETHER_TYPE_IPv4
);
452 arp_hdr
->arp_hln
= ETHER_ADDR_LEN
;
453 arp_hdr
->arp_pln
= sizeof(uint32_t);
454 arp_hdr
->arp_op
= rte_cpu_to_be_16(ARP_OP_REQUEST
);
456 rte_eth_macaddr_get(BOND_PORT
, &arp_hdr
->arp_data
.arp_sha
);
457 arp_hdr
->arp_data
.arp_sip
= bond_ip
;
458 memset(&arp_hdr
->arp_data
.arp_tha
, 0, ETHER_ADDR_LEN
);
459 arp_hdr
->arp_data
.arp_tip
=
460 ((unsigned char *)&res
->ip
.addr
.ipv4
)[0] |
461 (((unsigned char *)&res
->ip
.addr
.ipv4
)[1] << 8) |
462 (((unsigned char *)&res
->ip
.addr
.ipv4
)[2] << 16) |
463 (((unsigned char *)&res
->ip
.addr
.ipv4
)[3] << 24);
464 rte_eth_tx_burst(BOND_PORT
, 0, &created_pkt
, 1);
467 cmdline_printf(cl
, "\n");
470 cmdline_parse_token_string_t cmd_obj_action_send
=
471 TOKEN_STRING_INITIALIZER(struct cmd_obj_send_result
, action
, "send");
472 cmdline_parse_token_ipaddr_t cmd_obj_ip
=
473 TOKEN_IPV4_INITIALIZER(struct cmd_obj_send_result
, ip
);
475 cmdline_parse_inst_t cmd_obj_send
= {
476 .f
= cmd_obj_send_parsed
, /* function to call */
477 .data
= NULL
, /* 2nd arg of func */
478 .help_str
= "send client_ip",
479 .tokens
= { /* token list, NULL terminated */
480 (void *)&cmd_obj_action_send
,
486 struct cmd_start_result
{
487 cmdline_fixed_string_t start
;
490 static void cmd_start_parsed(__attribute__((unused
)) void *parsed_result
,
492 __attribute__((unused
)) void *data
)
494 int slave_core_id
= rte_lcore_id();
496 rte_spinlock_trylock(&global_flag_stru_p
->lock
);
497 if (global_flag_stru_p
->LcoreMainIsRunning
== 0) {
498 if (lcore_config
[global_flag_stru_p
->LcoreMainCore
].state
!= WAIT
) {
499 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
502 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
504 cmdline_printf(cl
, "lcore_main already running on core:%d\n",
505 global_flag_stru_p
->LcoreMainCore
);
506 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
510 /* start lcore main on core != master_core - ARP response thread */
511 slave_core_id
= rte_get_next_lcore(rte_lcore_id(), 1, 0);
512 if ((slave_core_id
>= RTE_MAX_LCORE
) || (slave_core_id
== 0))
515 rte_spinlock_trylock(&global_flag_stru_p
->lock
);
516 global_flag_stru_p
->LcoreMainIsRunning
= 1;
517 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
519 "Starting lcore_main on core %d:%d "
520 "Our IP:%d.%d.%d.%d\n",
522 rte_eal_remote_launch(lcore_main
, NULL
, slave_core_id
),
530 cmdline_parse_token_string_t cmd_start_start
=
531 TOKEN_STRING_INITIALIZER(struct cmd_start_result
, start
, "start");
533 cmdline_parse_inst_t cmd_start
= {
534 .f
= cmd_start_parsed
, /* function to call */
535 .data
= NULL
, /* 2nd arg of func */
536 .help_str
= "starts listening if not started at startup",
537 .tokens
= { /* token list, NULL terminated */
538 (void *)&cmd_start_start
,
543 struct cmd_help_result
{
544 cmdline_fixed_string_t help
;
547 static void cmd_help_parsed(__attribute__((unused
)) void *parsed_result
,
549 __attribute__((unused
)) void *data
)
552 "ALB - link bonding mode 6 example\n"
553 "send IP - sends one ARPrequest thru bonding for IP.\n"
554 "start - starts listening ARPs.\n"
555 "stop - stops lcore_main.\n"
556 "show - shows some bond info: ex. active slaves etc.\n"
557 "help - prints help.\n"
558 "quit - terminate all threads and quit.\n"
562 cmdline_parse_token_string_t cmd_help_help
=
563 TOKEN_STRING_INITIALIZER(struct cmd_help_result
, help
, "help");
565 cmdline_parse_inst_t cmd_help
= {
566 .f
= cmd_help_parsed
, /* function to call */
567 .data
= NULL
, /* 2nd arg of func */
568 .help_str
= "show help",
569 .tokens
= { /* token list, NULL terminated */
570 (void *)&cmd_help_help
,
575 struct cmd_stop_result
{
576 cmdline_fixed_string_t stop
;
579 static void cmd_stop_parsed(__attribute__((unused
)) void *parsed_result
,
581 __attribute__((unused
)) void *data
)
583 rte_spinlock_trylock(&global_flag_stru_p
->lock
);
584 if (global_flag_stru_p
->LcoreMainIsRunning
== 0) {
586 "lcore_main not running on core:%d\n",
587 global_flag_stru_p
->LcoreMainCore
);
588 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
591 global_flag_stru_p
->LcoreMainIsRunning
= 0;
592 if (rte_eal_wait_lcore(global_flag_stru_p
->LcoreMainCore
) < 0)
594 "error: lcore_main can not stop on core:%d\n",
595 global_flag_stru_p
->LcoreMainCore
);
598 "lcore_main stopped on core:%d\n",
599 global_flag_stru_p
->LcoreMainCore
);
600 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
603 cmdline_parse_token_string_t cmd_stop_stop
=
604 TOKEN_STRING_INITIALIZER(struct cmd_stop_result
, stop
, "stop");
606 cmdline_parse_inst_t cmd_stop
= {
607 .f
= cmd_stop_parsed
, /* function to call */
608 .data
= NULL
, /* 2nd arg of func */
609 .help_str
= "this command do not handle any arguments",
610 .tokens
= { /* token list, NULL terminated */
611 (void *)&cmd_stop_stop
,
616 struct cmd_quit_result
{
617 cmdline_fixed_string_t quit
;
620 static void cmd_quit_parsed(__attribute__((unused
)) void *parsed_result
,
622 __attribute__((unused
)) void *data
)
624 rte_spinlock_trylock(&global_flag_stru_p
->lock
);
625 if (global_flag_stru_p
->LcoreMainIsRunning
== 0) {
627 "lcore_main not running on core:%d\n",
628 global_flag_stru_p
->LcoreMainCore
);
629 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
633 global_flag_stru_p
->LcoreMainIsRunning
= 0;
634 if (rte_eal_wait_lcore(global_flag_stru_p
->LcoreMainCore
) < 0)
636 "error: lcore_main can not stop on core:%d\n",
637 global_flag_stru_p
->LcoreMainCore
);
640 "lcore_main stopped on core:%d\n",
641 global_flag_stru_p
->LcoreMainCore
);
642 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
646 cmdline_parse_token_string_t cmd_quit_quit
=
647 TOKEN_STRING_INITIALIZER(struct cmd_quit_result
, quit
, "quit");
649 cmdline_parse_inst_t cmd_quit
= {
650 .f
= cmd_quit_parsed
, /* function to call */
651 .data
= NULL
, /* 2nd arg of func */
652 .help_str
= "this command do not handle any arguments",
653 .tokens
= { /* token list, NULL terminated */
654 (void *)&cmd_quit_quit
,
659 struct cmd_show_result
{
660 cmdline_fixed_string_t show
;
663 static void cmd_show_parsed(__attribute__((unused
)) void *parsed_result
,
665 __attribute__((unused
)) void *data
)
667 uint8_t slaves
[16] = {0};
669 struct ether_addr addr
;
672 while (i
< slaves_count
) {
673 rte_eth_macaddr_get(i
, &addr
);
679 rte_spinlock_trylock(&global_flag_stru_p
->lock
);
682 "packets received:Tot:%d Arp:%d IPv4:%d\n",
683 rte_eth_bond_active_slaves_get(BOND_PORT
, slaves
, len
),
684 global_flag_stru_p
->port_packets
[0],
685 global_flag_stru_p
->port_packets
[1],
686 global_flag_stru_p
->port_packets
[2]);
687 rte_spinlock_unlock(&global_flag_stru_p
->lock
);
690 cmdline_parse_token_string_t cmd_show_show
=
691 TOKEN_STRING_INITIALIZER(struct cmd_show_result
, show
, "show");
693 cmdline_parse_inst_t cmd_show
= {
694 .f
= cmd_show_parsed
, /* function to call */
695 .data
= NULL
, /* 2nd arg of func */
696 .help_str
= "this command do not handle any arguments",
697 .tokens
= { /* token list, NULL terminated */
698 (void *)&cmd_show_show
,
703 /****** CONTEXT (list of instruction) */
705 cmdline_parse_ctx_t main_ctx
[] = {
706 (cmdline_parse_inst_t
*)&cmd_start
,
707 (cmdline_parse_inst_t
*)&cmd_obj_send
,
708 (cmdline_parse_inst_t
*)&cmd_stop
,
709 (cmdline_parse_inst_t
*)&cmd_show
,
710 (cmdline_parse_inst_t
*)&cmd_quit
,
711 (cmdline_parse_inst_t
*)&cmd_help
,
715 /* prompt function, called from main on MASTER lcore */
716 static void prompt(__attribute__((unused
)) void *arg1
)
720 cl
= cmdline_stdin_new(main_ctx
, "bond6>");
722 cmdline_interact(cl
);
723 cmdline_stdin_exit(cl
);
727 /* Main function, does initialisation and calls the per-lcore functions */
729 main(int argc
, char *argv
[])
735 ret
= rte_eal_init(argc
, argv
);
736 rte_eal_devargs_dump(stdout
);
738 rte_exit(EXIT_FAILURE
, "Error with EAL initialization\n");
742 nb_ports
= rte_eth_dev_count();
744 rte_exit(EXIT_FAILURE
, "Give at least one port\n");
745 else if (nb_ports
> MAX_PORTS
)
746 rte_exit(EXIT_FAILURE
, "You can have max 4 ports\n");
748 mbuf_pool
= rte_pktmbuf_pool_create("MBUF_POOL", NB_MBUF
, 32,
749 0, RTE_MBUF_DEFAULT_BUF_SIZE
, rte_socket_id());
750 if (mbuf_pool
== NULL
)
751 rte_exit(EXIT_FAILURE
, "Cannot create mbuf pool\n");
753 /* initialize all ports */
754 slaves_count
= nb_ports
;
755 for (i
= 0; i
< nb_ports
; i
++) {
756 slave_port_init(i
, mbuf_pool
);
760 bond_port_init(mbuf_pool
);
762 rte_spinlock_init(&global_flag_stru_p
->lock
);
763 int slave_core_id
= rte_lcore_id();
765 /* check state of lcores */
766 RTE_LCORE_FOREACH_SLAVE(slave_core_id
) {
767 if (lcore_config
[slave_core_id
].state
!= WAIT
)
770 /* start lcore main on core != master_core - ARP response thread */
771 slave_core_id
= rte_get_next_lcore(rte_lcore_id(), 1, 0);
772 if ((slave_core_id
>= RTE_MAX_LCORE
) || (slave_core_id
== 0))
775 global_flag_stru_p
->LcoreMainIsRunning
= 1;
776 global_flag_stru_p
->LcoreMainCore
= slave_core_id
;
777 printf("Starting lcore_main on core %d:%d Our IP:%d.%d.%d.%d\n",
779 rte_eal_remote_launch((lcore_function_t
*)lcore_main
,
788 /* Start prompt for user interact */