#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 <rte_ip.h>
#include <cmdline_socket.h>
#include "commands.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 members[RTE_MAX_ETHPORTS];
uint16_t members_count;
static uint16_t BOND_PORT = 0xffff;
},
.rx_adv_conf = {
.rss_conf = {
.rss_key = NULL,
.rss_hf = RTE_ETH_RSS_IP,
},
},
.txmode = {
},
};
static void
member_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));
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,
mbuf_pool);
if (retval < 0)
rte_exit(retval,
" port %u: RX queue 0 setup failed (res=%d)",
portid, retval);
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);
struct rte_ether_addr addr;
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 < members_count; i++) {
rte_exit(-1,
"Oooops! adding member (%u) to bond (%u) failed!\n",
members[i], BOND_PORT);
}
&rxq_conf, mbuf_pool);
if (retval < 0)
rte_exit(retval,
" port %u: RX queue 0 setup failed (res=%d)",
BOND_PORT, retval);
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 members to become active...");
while (wait_counter) {
uint16_t act_members[16] = {0};
members_count) {
printf("\n");
break;
}
sleep(1);
printf("...");
if (--wait_counter == 0)
rte_exit(-1,
"\nFailed to activate members\n");
}
if (retval != 0) {
"port %u: promiscuous mode enable failed: %s\n",
return;
}
struct rte_ether_addr addr;
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;
{
alignas(RTE_CACHE_LINE_SIZE)
struct rte_mbuf *pkts[MAX_PKT_BURST];
struct rte_ether_addr dst_addr;
struct rte_ether_addr bond_mac_addr;
struct rte_arp_hdr *arp_hdr;
struct rte_ipv4_hdr *ipv4_hdr;
uint16_t ether_type, offset;
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:");
offset = get_vlan_offset(eth_hdr, ðer_type);
if (offset > 0)
printf("%d\n", offset);
global_flag_stru_p->port_packets[1]++;
}
arp_hdr = (struct rte_arp_hdr *)(
(char *)(eth_hdr + 1) + offset);
if (arp_hdr->arp_data.arp_tip == bond_ip) {
&arp_hdr->arp_data.arp_tha);
arp_hdr->arp_data.arp_tip = arp_hdr->arp_data.arp_sip;
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 (ipv4_hdr->dst_addr == bond_ip) {
ipv4_hdr->dst_addr = ipv4_hdr->src_addr;
ipv4_hdr->src_addr = bond_ip;
}
}
if (is_free == 0)
}
}
printf("BYE lcore_main\n");
return 0;
}
static inline void get_string(struct cmd_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])
);
}
void
{
struct cmd_send_result *res = parsed_result;
char ip_str[INET6_ADDRSTRLEN];
struct rte_ether_addr bond_mac_addr;
struct rte_arp_hdr *arp_hdr;
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;
}
pkt_size =
sizeof(
struct rte_ether_hdr) + sizeof(struct rte_arp_hdr);
arp_hdr = (struct rte_arp_hdr *)(
arp_hdr->arp_plen = sizeof(uint32_t);
arp_hdr->arp_data.arp_sip = bond_ip;
arp_hdr->arp_data.arp_tip =
((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");
}
void
{
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
);
}
void
{
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 members etc.\n"
"help - prints help.\n"
"quit - terminate all threads and quit.\n"
);
}
void
{
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);
}
void
{
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);
}
void
{
uint16_t members[16] = {0};
uint8_t len = 16;
struct rte_ether_addr addr;
uint16_t i;
int ret;
for (i = 0; i < members_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_members:%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]);
}
{
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");
members_count = nb_ports;
member_port_init(i, mbuf_pool);
members[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;
}