#include <stdint.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <inttypes.h>
#include <getopt.h>
#include <termios.h>
#include <unistd.h>
#include <pthread.h>
#include <cmdline_rdline.h>
#include <cmdline_parse.h>
#include <cmdline_parse_num.h>
#include <cmdline_parse_string.h>
#include <cmdline_parse_ipaddr.h>
#include <cmdline_parse_etheraddr.h>
#include <cmdline_socket.h>
#include "main.h"
#define RTE_LOGTYPE_DCB RTE_LOGTYPE_USER1
#define NB_MBUF (1024*8)
#define MAX_PKT_BURST 32
#define BURST_TX_DRAIN_US 100
#define BURST_RX_INTERVAL_NS (10)
#define RX_PTHRESH 8
#define RX_HTHRESH 8
#define RX_WTHRESH 4
#define RX_FTHRESH (MAX_PKT_BURST * 2)
#define TX_PTHRESH 36
#define TX_HTHRESH 0
#define TX_WTHRESH 0
#define RTE_RX_DESC_DEFAULT 1024
#define RTE_TX_DESC_DEFAULT 1024
#define BOND_IP_1 7
#define BOND_IP_2 0
#define BOND_IP_3 0
#define BOND_IP_4 10
#ifndef NIPQUAD
#define NIPQUAD_FMT "%u.%u.%u.%u"
#endif
#define MAX_PORTS 4
#define PRINT_MAC(addr) printf("%02"PRIx8":%02"PRIx8":%02"PRIx8 \
":%02"PRIx8":%02"PRIx8":%02"PRIx8, \
RTE_ETHER_ADDR_BYTES(&addr))
uint16_t slaves[RTE_MAX_ETHPORTS];
uint16_t slaves_count;
static uint16_t BOND_PORT = 0xffff;
},
.rx_adv_conf = {
.rss_conf = {
.rss_key = NULL,
.rss_hf = RTE_ETH_RSS_IP,
},
},
.txmode = {
},
};
static void
slave_port_init(uint16_t portid,
struct rte_mempool *mbuf_pool)
{
int retval;
uint16_t nb_rxd = RTE_RX_DESC_DEFAULT;
uint16_t nb_txd = RTE_TX_DESC_DEFAULT;
rte_exit(EXIT_FAILURE,
"Invalid port\n");
if (retval != 0)
"Error during getting device (port %u) info: %s\n",
portid, strerror(-retval));
dev_info.flow_type_rss_offloads;
printf("Port %u modified RSS hash function based on hardware support,"
"requested:%#"PRIx64" configured:%#"PRIx64"\n",
portid,
}
if (retval != 0)
rte_exit(EXIT_FAILURE,
"port %u: configuration failed (res=%d)\n",
portid, retval);
if (retval != 0)
rte_exit(EXIT_FAILURE,
"port %u: rte_eth_dev_adjust_nb_rx_tx_desc "
"failed (res=%d)\n", portid, retval);
rxq_conf = dev_info.default_rxconf;
&rxq_conf,
mbuf_pool);
if (retval < 0)
rte_exit(retval,
" port %u: RX queue 0 setup failed (res=%d)",
portid, retval);
txq_conf = dev_info.default_txconf;
if (retval < 0)
rte_exit(retval,
"port %u: TX queue 0 setup failed (res=%d)",
portid, retval);
if (retval < 0)
"Start port %d failed (res=%d)",
portid, retval);
if (retval != 0)
"Mac address get port %d failed (res=%d)",
portid, retval);
printf("Port %u MAC: ", portid);
PRINT_MAC(addr);
printf("\n");
}
static void
{
int retval;
uint8_t i;
uint16_t nb_rxd = RTE_RX_DESC_DEFAULT;
uint16_t nb_txd = RTE_TX_DESC_DEFAULT;
uint16_t wait_counter = 20;
0 );
if (retval < 0)
"Failed to create bond port\n");
BOND_PORT = retval;
if (retval != 0)
"Error during getting device (port %u) info: %s\n",
BOND_PORT, strerror(-retval));
if (retval != 0)
rte_exit(EXIT_FAILURE,
"port %u: configuration failed (res=%d)\n",
BOND_PORT, retval);
if (retval != 0)
rte_exit(EXIT_FAILURE,
"port %u: rte_eth_dev_adjust_nb_rx_tx_desc "
"failed (res=%d)\n", BOND_PORT, retval);
for (i = 0; i < slaves_count; i++) {
rte_exit(-1,
"Oooops! adding slave (%u) to bond (%u) failed!\n",
slaves[i], BOND_PORT);
}
rxq_conf = dev_info.default_rxconf;
&rxq_conf, mbuf_pool);
if (retval < 0)
rte_exit(retval,
" port %u: RX queue 0 setup failed (res=%d)",
BOND_PORT, retval);
txq_conf = dev_info.default_txconf;
if (retval < 0)
rte_exit(retval,
"port %u: TX queue 0 setup failed (res=%d)",
BOND_PORT, retval);
if (retval < 0)
rte_exit(retval,
"Start port %d failed (res=%d)", BOND_PORT, retval);
printf("Waiting for slaves to become active...");
while (wait_counter) {
uint16_t act_slaves[16] = {0};
slaves_count) {
printf("\n");
break;
}
sleep(1);
printf("...");
if (--wait_counter == 0)
rte_exit(-1,
"\nFailed to activate slaves\n");
}
if (retval != 0) {
"port %u: promiscuous mode enable failed: %s\n",
return;
}
if (retval != 0)
rte_exit(retval,
"port %u: Mac address get failed (res=%d)",
BOND_PORT, retval);
printf("Port %u MAC: ", (unsigned)BOND_PORT);
PRINT_MAC(addr);
printf("\n");
}
static inline size_t
{
size_t vlan_offset = 0;
vlan_hdr = vlan_hdr + 1;
}
}
return vlan_offset;
}
struct global_flag_stru_t {
int LcoreMainIsRunning;
int LcoreMainCore;
uint32_t port_packets[4];
};
struct global_flag_stru_t global_flag_stru;
struct global_flag_stru_t *global_flag_stru_p = &global_flag_stru;
{
uint16_t rx_cnt;
uint32_t bond_ip;
int i = 0;
uint8_t is_free;
int ret;
bond_ip = BOND_IP_1 | (BOND_IP_2 << 8) |
(BOND_IP_3 << 16) | (BOND_IP_4 << 24);
while (global_flag_stru_p->LcoreMainIsRunning) {
is_free = 0;
if (rx_cnt == 0) {
continue;
}
if (ret != 0) {
printf("Bond (port %u) MAC address get failed: %s.\n"
"%u packets dropped", BOND_PORT, strerror(-ret),
rx_cnt);
continue;
}
for (i = 0; i < rx_cnt; i++) {
global_flag_stru_p->port_packets[0]++;
}
printf("VLAN tagged frame, offset:");
if (offset > 0)
printf("%d\n", offset);
global_flag_stru_p->port_packets[1]++;
}
(char *)(eth_hdr + 1) + offset);
if (arp_hdr->
arp_data.
arp_tip == bond_ip) {
arp_hdr->arp_data.
arp_sip = bond_ip;
is_free = 1;
} else {
}
}
global_flag_stru_p->port_packets[2]++;
}
ipv4_hdr = (
struct rte_ipv4_hdr *)((
char *)(eth_hdr + 1) + offset);
}
}
if (is_free == 0)
}
}
printf("BYE lcore_main\n");
return 0;
}
struct cmd_obj_send_result {
cmdline_fixed_string_t action;
cmdline_ipaddr_t ip;
};
static inline void get_string(struct cmd_obj_send_result *res, char *buf, uint8_t size)
{
snprintf(buf, size, NIPQUAD_FMT,
((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[0]),
((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[1]),
((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[2]),
((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[3])
);
}
static void cmd_obj_send_parsed(void *parsed_result,
{
struct cmd_obj_send_result *res = parsed_result;
char ip_str[INET6_ADDRSTRLEN];
uint32_t bond_ip;
size_t pkt_size;
int ret;
if (res->ip.family == AF_INET)
get_string(res, ip_str, INET_ADDRSTRLEN);
else
cmdline_printf(cl, "Wrong IP format. Only IPv4 is supported\n");
bond_ip = BOND_IP_1 | (BOND_IP_2 << 8) |
(BOND_IP_3 << 16) | (BOND_IP_4 << 24);
if (ret != 0) {
cmdline_printf(cl,
"Failed to get bond (port %u) MAC address: %s\n",
BOND_PORT, strerror(-ret));
}
if (created_pkt == NULL) {
cmdline_printf(cl, "Failed to allocate mbuf\n");
return;
}
arp_hdr->
arp_plen =
sizeof(uint32_t);
arp_hdr->arp_data.
arp_sip = bond_ip;
((unsigned char *)&res->ip.addr.ipv4)[0] |
(((unsigned char *)&res->ip.addr.ipv4)[1] << 8) |
(((unsigned char *)&res->ip.addr.ipv4)[2] << 16) |
(((unsigned char *)&res->ip.addr.ipv4)[3] << 24);
cmdline_printf(cl, "\n");
}
cmdline_parse_token_string_t cmd_obj_action_send =
TOKEN_STRING_INITIALIZER(struct cmd_obj_send_result, action, "send");
cmdline_parse_token_ipaddr_t cmd_obj_ip =
TOKEN_IPV4_INITIALIZER(struct cmd_obj_send_result, ip);
cmdline_parse_inst_t cmd_obj_send = {
.f = cmd_obj_send_parsed,
.data = NULL,
.help_str = "send client_ip",
.tokens = {
(void *)&cmd_obj_action_send,
(void *)&cmd_obj_ip,
NULL,
},
};
struct cmd_start_result {
cmdline_fixed_string_t start;
};
static void cmd_start_parsed(
__rte_unused void *parsed_result,
struct cmdline *cl,
{
if (global_flag_stru_p->LcoreMainIsRunning == 0) {
return;
}
} else {
cmdline_printf(cl, "lcore_main already running on core:%d\n",
global_flag_stru_p->LcoreMainCore);
return;
}
if ((worker_core_id >= RTE_MAX_LCORE) || (worker_core_id == 0))
return;
global_flag_stru_p->LcoreMainIsRunning = 1;
cmdline_printf(cl,
"Starting lcore_main on core %d:%d "
"Our IP:%d.%d.%d.%d\n",
worker_core_id,
BOND_IP_1,
BOND_IP_2,
BOND_IP_3,
BOND_IP_4
);
}
cmdline_parse_token_string_t cmd_start_start =
TOKEN_STRING_INITIALIZER(struct cmd_start_result, start, "start");
cmdline_parse_inst_t cmd_start = {
.f = cmd_start_parsed,
.data = NULL,
.help_str = "starts listening if not started at startup",
.tokens = {
(void *)&cmd_start_start,
NULL,
},
};
struct cmd_help_result {
cmdline_fixed_string_t help;
};
static void cmd_help_parsed(
__rte_unused void *parsed_result,
struct cmdline *cl,
{
cmdline_printf(cl,
"ALB - link bonding mode 6 example\n"
"send IP - sends one ARPrequest through bonding for IP.\n"
"start - starts listening ARPs.\n"
"stop - stops lcore_main.\n"
"show - shows some bond info: ex. active slaves etc.\n"
"help - prints help.\n"
"quit - terminate all threads and quit.\n"
);
}
cmdline_parse_token_string_t cmd_help_help =
TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help");
cmdline_parse_inst_t cmd_help = {
.f = cmd_help_parsed,
.data = NULL,
.help_str = "show help",
.tokens = {
(void *)&cmd_help_help,
NULL,
},
};
struct cmd_stop_result {
cmdline_fixed_string_t stop;
};
static void cmd_stop_parsed(
__rte_unused void *parsed_result,
struct cmdline *cl,
{
if (global_flag_stru_p->LcoreMainIsRunning == 0) {
cmdline_printf(cl,
"lcore_main not running on core:%d\n",
global_flag_stru_p->LcoreMainCore);
return;
}
global_flag_stru_p->LcoreMainIsRunning = 0;
cmdline_printf(cl,
"error: lcore_main can not stop on core:%d\n",
global_flag_stru_p->LcoreMainCore);
else
cmdline_printf(cl,
"lcore_main stopped on core:%d\n",
global_flag_stru_p->LcoreMainCore);
}
cmdline_parse_token_string_t cmd_stop_stop =
TOKEN_STRING_INITIALIZER(struct cmd_stop_result, stop, "stop");
cmdline_parse_inst_t cmd_stop = {
.f = cmd_stop_parsed,
.data = NULL,
.help_str = "this command do not handle any arguments",
.tokens = {
(void *)&cmd_stop_stop,
NULL,
},
};
struct cmd_quit_result {
cmdline_fixed_string_t quit;
};
static void cmd_quit_parsed(
__rte_unused void *parsed_result,
struct cmdline *cl,
{
if (global_flag_stru_p->LcoreMainIsRunning == 0) {
cmdline_printf(cl,
"lcore_main not running on core:%d\n",
global_flag_stru_p->LcoreMainCore);
cmdline_quit(cl);
return;
}
global_flag_stru_p->LcoreMainIsRunning = 0;
cmdline_printf(cl,
"error: lcore_main can not stop on core:%d\n",
global_flag_stru_p->LcoreMainCore);
else
cmdline_printf(cl,
"lcore_main stopped on core:%d\n",
global_flag_stru_p->LcoreMainCore);
cmdline_quit(cl);
}
cmdline_parse_token_string_t cmd_quit_quit =
TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
cmdline_parse_inst_t cmd_quit = {
.f = cmd_quit_parsed,
.data = NULL,
.help_str = "this command do not handle any arguments",
.tokens = {
(void *)&cmd_quit_quit,
NULL,
},
};
struct cmd_show_result {
cmdline_fixed_string_t show;
};
static void cmd_show_parsed(
__rte_unused void *parsed_result,
struct cmdline *cl,
{
uint16_t slaves[16] = {0};
uint8_t len = 16;
uint16_t i;
int ret;
for (i = 0; i < slaves_count; i++) {
if (ret != 0) {
cmdline_printf(cl,
"Failed to get port %u MAC address: %s\n",
i, strerror(-ret));
continue;
}
PRINT_MAC(addr);
printf("\n");
}
cmdline_printf(cl,
"Active_slaves:%d "
"packets received:Tot:%d Arp:%d IPv4:%d\n",
global_flag_stru_p->port_packets[0],
global_flag_stru_p->port_packets[1],
global_flag_stru_p->port_packets[2]);
}
cmdline_parse_token_string_t cmd_show_show =
TOKEN_STRING_INITIALIZER(struct cmd_show_result, show, "show");
cmdline_parse_inst_t cmd_show = {
.f = cmd_show_parsed,
.data = NULL,
.help_str = "this command do not handle any arguments",
.tokens = {
(void *)&cmd_show_show,
NULL,
},
};
cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *)&cmd_start,
(cmdline_parse_inst_t *)&cmd_obj_send,
(cmdline_parse_inst_t *)&cmd_stop,
(cmdline_parse_inst_t *)&cmd_show,
(cmdline_parse_inst_t *)&cmd_quit,
(cmdline_parse_inst_t *)&cmd_help,
NULL,
};
{
struct cmdline *cl;
cl = cmdline_stdin_new(main_ctx, "bond6>");
if (cl != NULL) {
cmdline_interact(cl);
cmdline_stdin_exit(cl);
}
}
int
main(int argc, char *argv[])
{
int ret, worker_core_id;
uint16_t nb_ports, i;
if (ret < 0)
rte_exit(EXIT_FAILURE,
"Error with EAL initialization\n");
argc -= ret;
argv += ret;
if (nb_ports == 0)
rte_exit(EXIT_FAILURE,
"Give at least one port\n");
else if (nb_ports > MAX_PORTS)
rte_exit(EXIT_FAILURE,
"You can have max 4 ports\n");
if (mbuf_pool == NULL)
rte_exit(EXIT_FAILURE,
"Cannot create mbuf pool\n");
slaves_count = nb_ports;
slave_port_init(i, mbuf_pool);
slaves[i] = i;
}
bond_port_init(mbuf_pool);
return -EBUSY;
}
if ((worker_core_id >= RTE_MAX_LCORE) || (worker_core_id == 0))
return -EPERM;
global_flag_stru_p->LcoreMainIsRunning = 1;
global_flag_stru_p->LcoreMainCore = worker_core_id;
printf("Starting lcore_main on core %d:%d Our IP:%d.%d.%d.%d\n",
worker_core_id,
NULL,
worker_core_id),
BOND_IP_1,
BOND_IP_2,
BOND_IP_3,
BOND_IP_4
);
prompt(NULL);
return 0;
}
static rte_be16_t rte_cpu_to_be_16(uint16_t x)
#define __rte_cache_aligned
__rte_noreturn void rte_exit(int exit_code, const char *format,...) __rte_format_printf(2
void(* rte_delay_us)(unsigned int us)
static void rte_delay_ms(unsigned ms)
void rte_devargs_dump(FILE *f)
int rte_eal_init(int argc, char **argv)
int rte_eal_cleanup(void)
const char * rte_strerror(int errnum)
int rte_eth_bond_active_slaves_get(uint16_t bonded_port_id, uint16_t slaves[], uint16_t len)
int rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
int rte_eth_bond_slave_add(uint16_t bonded_port_id, uint16_t slave_port_id)
int rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_queue, uint16_t nb_tx_queue, const struct rte_eth_conf *eth_conf)
int rte_eth_dev_is_valid_port(uint16_t port_id)
int rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool)
static uint16_t rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id, struct rte_mbuf **rx_pkts, const uint16_t nb_pkts)
#define RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
int rte_eth_promiscuous_enable(uint16_t port_id)
int rte_eth_dev_info_get(uint16_t port_id, struct rte_eth_dev_info *dev_info)
int rte_eth_tx_queue_setup(uint16_t port_id, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf)
static uint16_t rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
int rte_eth_macaddr_get(uint16_t port_id, struct rte_ether_addr *mac_addr)
uint16_t rte_eth_dev_count_avail(void)
int rte_eth_dev_socket_id(uint16_t port_id)
int rte_eth_dev_adjust_nb_rx_tx_desc(uint16_t port_id, uint16_t *nb_rx_desc, uint16_t *nb_tx_desc)
#define RTE_ETH_FOREACH_DEV(p)
int rte_eth_dev_start(uint16_t port_id)
#define RTE_ETHER_TYPE_IPV4
#define RTE_ETHER_TYPE_VLAN
#define RTE_ETHER_TYPE_ARP
#define RTE_ETHER_ADDR_LEN
struct rte_ether_addr dst_addr
static void rte_ether_addr_copy(const struct rte_ether_addr *__restrict ea_from, struct rte_ether_addr *__restrict ea_to)
int() lcore_function_t(void *)
int rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned worker_id)
enum rte_lcore_state_t rte_eal_get_lcore_state(unsigned int worker_id)
int rte_eal_wait_lcore(unsigned worker_id)
unsigned int rte_socket_id(void)
#define RTE_LCORE_FOREACH_WORKER(i)
unsigned int rte_get_next_lcore(unsigned int i, int skip_main, int wrap)
static unsigned rte_lcore_id(void)
static void rte_pktmbuf_free(struct rte_mbuf *m)
struct rte_mempool * rte_pktmbuf_pool_create(const char *name, unsigned n, unsigned cache_size, uint16_t priv_size, uint16_t data_room_size, int socket_id)
static struct rte_mbuf * rte_pktmbuf_alloc(struct rte_mempool *mp)
#define rte_pktmbuf_mtod(m, t)
static void rte_spinlock_unlock(rte_spinlock_t *sl)
static void rte_spinlock_lock(rte_spinlock_t *sl)
static __rte_warn_unused_result int rte_spinlock_trylock(rte_spinlock_t *sl)
static void rte_spinlock_init(rte_spinlock_t *sl)
struct rte_ether_addr arp_sha
struct rte_ether_addr arp_tha
struct rte_eth_txmode txmode
struct rte_eth_rxmode rxmode
struct rte_eth_rss_conf rss_conf
struct rte_eth_conf::@115 rx_adv_conf
enum rte_eth_rx_mq_mode mq_mode
struct rte_ether_addr src_addr
struct rte_ether_addr dst_addr