#include <rte_memcpy.h>
#include <rte_eal.h>
#include <rte_launch.h>
-#include <rte_atomic.h>
#include <rte_cycles.h>
#include <rte_prefetch.h>
#include <rte_lcore.h>
static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
/* ethernet addresses of ports */
-static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
+static struct rte_ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
/* mask of enabled ports */
static uint32_t l2fwd_enabled_port_mask;
#define MAX_RX_QUEUE_PER_LCORE 16
#define MAX_TX_QUEUE_PER_PORT 16
+/* List of queues to be polled for given lcore. 8< */
struct lcore_queue_conf {
unsigned n_rx_port;
unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];
struct rte_jobstats idle_job;
struct rte_jobstats_context jobs_context;
- rte_atomic16_t stats_read_pending;
+ uint16_t stats_read_pending;
rte_spinlock_t lock;
} __rte_cache_aligned;
+/* >8 End of list of queues to be polled for given lcore. */
struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];
static struct rte_eth_conf port_conf = {
.rxmode = {
.split_hdr_size = 0,
- .ignore_offload_bitfield = 1,
- .offloads = DEV_RX_OFFLOAD_CRC_STRIP,
},
.txmode = {
.mq_mode = ETH_MQ_TX_NONE,
uint64_t collection_time = rte_get_timer_cycles();
/* Ask forwarding thread to give us stats. */
- rte_atomic16_set(&qconf->stats_read_pending, 1);
+ __atomic_store_n(&qconf->stats_read_pending, 1, __ATOMIC_RELAXED);
rte_spinlock_lock(&qconf->lock);
- rte_atomic16_set(&qconf->stats_read_pending, 0);
+ __atomic_store_n(&qconf->stats_read_pending, 0, __ATOMIC_RELAXED);
/* Collect context statistics. */
stats_period = ctx->state_time - ctx->start_time;
}
printf("\n====================================================\n");
+
+ fflush(stdout);
+
rte_eal_alarm_set(timer_period * US_PER_S, show_stats_cb, NULL);
}
+/* Start of l2fwd_simple_forward. 8< */
static void
l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)
{
- struct ether_hdr *eth;
+ struct rte_ether_hdr *eth;
void *tmp;
int sent;
unsigned dst_port;
struct rte_eth_dev_tx_buffer *buffer;
dst_port = l2fwd_dst_ports[portid];
- eth = rte_pktmbuf_mtod(m, struct ether_hdr *);
+ eth = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
/* 02:00:00:00:00:xx */
- tmp = ð->d_addr.addr_bytes[0];
+ tmp = ð->dst_addr.addr_bytes[0];
*((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40);
/* src addr */
- ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr);
+ rte_ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->src_addr);
buffer = tx_buffer[dst_port];
sent = rte_eth_tx_buffer(dst_port, 0, buffer, m);
if (sent)
port_statistics[dst_port].tx += sent;
}
+/* >8 End of l2fwd_simple_forward. */
static void
l2fwd_job_update_cb(struct rte_jobstats *job, int64_t result)
/* Call rx burst 2 times. This allow rte_jobstats logic to see if this
* function must be called more frequently. */
+ /* Call rx burst 2 times. 8< */
total_nb_rx = rte_eth_rx_burst(portid, 0, pkts_burst,
MAX_PKT_BURST);
rte_prefetch0(rte_pktmbuf_mtod(m, void *));
l2fwd_simple_forward(m, portid);
}
+ /* >8 End of call rx burst 2 times. */
+ /* Read second try. 8< */
if (total_nb_rx == MAX_PKT_BURST) {
const uint16_t nb_rx = rte_eth_rx_burst(portid, 0, pkts_burst,
MAX_PKT_BURST);
l2fwd_simple_forward(m, portid);
}
}
+ /* >8 End of read second try. */
port_statistics[portid].rx += total_nb_rx;
- /* Adjust period time in which we are running here. */
+ /* Adjust period time in which we are running here. 8< */
if (rte_jobstats_finish(job, total_nb_rx) != 0) {
rte_timer_reset(&qconf->rx_timers[port_idx], job->period, PERIODICAL,
lcore_id, l2fwd_fwd_job, arg);
}
+ /* >8 End of adjust period time in which we are running. */
}
+/* Draining TX queue of each port. 8< */
static void
l2fwd_flush_job(__rte_unused struct rte_timer *timer, __rte_unused void *arg)
{
* in which it was called. */
rte_jobstats_finish(&qconf->flush_job, qconf->flush_job.target);
}
+/* >8 End of draining TX queue of each port. */
/* main processing loop */
static void
rte_jobstats_init(&qconf->idle_job, "idle", 0, 0, 0, 0);
+ /* Minimize impact of stats reading. 8< */
for (;;) {
rte_spinlock_lock(&qconf->lock);
repeats++;
need_manage = qconf->flush_timer.expire < now;
/* Check if we was esked to give a stats. */
- stats_read_pending =
- rte_atomic16_read(&qconf->stats_read_pending);
+ stats_read_pending = __atomic_load_n(&qconf->stats_read_pending,
+ __ATOMIC_RELAXED);
need_manage |= stats_read_pending;
for (i = 0; i < qconf->n_rx_port && !need_manage; i++)
rte_spinlock_unlock(&qconf->lock);
rte_pause();
}
+ /* >8 End of minimize impact of stats reading. */
}
static int
-l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy)
+l2fwd_launch_one_lcore(__rte_unused void *dummy)
{
l2fwd_main_loop();
return 0;
/* parse hexadecimal string */
pm = strtoul(portmask, &end, 16);
if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
- return -1;
-
- if (pm == 0)
- return -1;
+ return 0;
return pm;
}
/* Check the link status of all ports in up to 9s, and print them finally */
static void
-check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
+check_all_ports_link_status(uint32_t port_mask)
{
#define CHECK_INTERVAL 100 /* 100ms */
#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
uint16_t portid;
uint8_t count, all_ports_up, print_flag = 0;
struct rte_eth_link link;
+ int ret;
+ char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
printf("\nChecking link status");
fflush(stdout);
for (count = 0; count <= MAX_CHECK_TIME; count++) {
all_ports_up = 1;
- for (portid = 0; portid < port_num; portid++) {
+ RTE_ETH_FOREACH_DEV(portid) {
if ((port_mask & (1 << portid)) == 0)
continue;
memset(&link, 0, sizeof(link));
- rte_eth_link_get_nowait(portid, &link);
+ ret = rte_eth_link_get_nowait(portid, &link);
+ if (ret < 0) {
+ all_ports_up = 0;
+ if (print_flag == 1)
+ printf("Port %u link get failed: %s\n",
+ portid, rte_strerror(-ret));
+ continue;
+ }
/* print link status if flag set */
if (print_flag == 1) {
- if (link.link_status)
- printf(
- "Port%d Link Up. Speed %u Mbps - %s\n",
- portid, link.link_speed,
- (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
- ("full-duplex") : ("half-duplex\n"));
- else
- printf("Port %d Link Down\n", portid);
+ rte_eth_link_to_str(link_status_text,
+ sizeof(link_status_text), &link);
+ printf("Port %d %s\n", portid,
+ link_status_text);
continue;
}
/* clear all_ports_up flag if any link down */
int ret;
char name[RTE_JOBSTATS_NAMESIZE];
uint16_t nb_ports;
- uint16_t nb_ports_available;
+ uint16_t nb_ports_available = 0;
uint16_t portid, last_port;
uint8_t i;
- /* init EAL */
+ /* Init EAL. 8< */
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
ret = l2fwd_parse_args(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n");
+ /* >8 End of init EAL. */
rte_timer_subsystem_init();
/* fetch default timer frequency. */
hz = rte_get_timer_hz();
- /* create the mbuf pool */
+ /* Create the mbuf pool. 8< */
l2fwd_pktmbuf_pool =
rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32,
0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
if (l2fwd_pktmbuf_pool == NULL)
rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
-
- nb_ports = rte_eth_dev_count();
+ /* >8 End of creation of mbuf pool. */
+ nb_ports = rte_eth_dev_count_avail();
if (nb_ports == 0)
rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
- /* reset l2fwd_dst_ports */
+ /* Reset l2fwd_dst_ports. 8< */
for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
l2fwd_dst_ports[portid] = 0;
last_port = 0;
/*
* Each logical core is assigned a dedicated TX queue on each port.
*/
- for (portid = 0; portid < nb_ports; portid++) {
+ RTE_ETH_FOREACH_DEV(portid) {
/* skip ports that are not enabled */
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
continue;
nb_ports_in_mask++;
}
+ /* >8 End of reset l2fwd_dst_ports. */
if (nb_ports_in_mask % 2) {
printf("Notice: odd number of ports in portmask.\n");
l2fwd_dst_ports[last_port] = last_port;
qconf = NULL;
/* Initialize the port/queue configuration of each logical core */
- for (portid = 0; portid < nb_ports; portid++) {
+ RTE_ETH_FOREACH_DEV(portid) {
/* skip ports that are not enabled */
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
continue;
printf("Lcore %u: RX port %u\n", rx_lcore_id, portid);
}
- nb_ports_available = nb_ports;
-
/* Initialise each port */
- for (portid = 0; portid < nb_ports; portid++) {
+ RTE_ETH_FOREACH_DEV(portid) {
struct rte_eth_dev_info dev_info;
struct rte_eth_rxconf rxq_conf;
struct rte_eth_txconf txq_conf;
/* skip ports that are not enabled */
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) {
printf("Skipping disabled port %u\n", portid);
- nb_ports_available--;
continue;
}
+ nb_ports_available++;
+
/* init port */
printf("Initializing port %u... ", portid);
fflush(stdout);
- rte_eth_dev_info_get(portid, &dev_info);
+
+ ret = rte_eth_dev_info_get(portid, &dev_info);
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE,
+ "Error during getting device (port %u) info: %s\n",
+ portid, strerror(-ret));
+
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
local_port_conf.txmode.offloads |=
DEV_TX_OFFLOAD_MBUF_FAST_FREE;
+ /* Configure the RX and TX queues. 8< */
ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n",
ret, portid);
+ /* >8 End of configuring the RX and TX queues. */
ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
&nb_txd);
"Cannot adjust number of descriptors: err=%d, port=%u\n",
ret, portid);
- rte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]);
+ ret = rte_eth_macaddr_get(portid,
+ &l2fwd_ports_eth_addr[portid]);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "Cannot get MAC address: err=%d, port=%u\n",
+ ret, portid);
/* init one RX queue */
fflush(stdout);
rxq_conf = dev_info.default_rxconf;
rxq_conf.offloads = local_port_conf.rxmode.offloads;
+ /* RX queue initialization. 8< */
ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
rte_eth_dev_socket_id(portid),
&rxq_conf,
if (ret < 0)
rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n",
ret, portid);
+ /* >8 End of RX queue initialization. */
- /* init one TX queue on each port */
+ /* Init one TX queue on each port. 8< */
txq_conf = dev_info.default_txconf;
- txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE;
txq_conf.offloads = local_port_conf.txmode.offloads;
fflush(stdout);
ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
rte_exit(EXIT_FAILURE,
"rte_eth_tx_queue_setup:err=%d, port=%u\n",
ret, portid);
+ /* >8 End of init one TX queue on each port. */
/* Initialize TX buffers */
tx_buffer[portid] = rte_zmalloc_socket("tx_buffer",
printf("done:\n");
- rte_eth_promiscuous_enable(portid);
+ ret = rte_eth_promiscuous_enable(portid);
+ if (ret != 0) {
+ rte_exit(EXIT_FAILURE,
+ "rte_eth_promiscuous_enable:err=%s, port=%u\n",
+ rte_strerror(-ret), portid);
+ return ret;
+
+ }
- printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
- portid,
- l2fwd_ports_eth_addr[portid].addr_bytes[0],
- l2fwd_ports_eth_addr[portid].addr_bytes[1],
- l2fwd_ports_eth_addr[portid].addr_bytes[2],
- l2fwd_ports_eth_addr[portid].addr_bytes[3],
- l2fwd_ports_eth_addr[portid].addr_bytes[4],
- l2fwd_ports_eth_addr[portid].addr_bytes[5]);
+ printf("Port %u, MAC address: " RTE_ETHER_ADDR_PRT_FMT "\n\n",
+ portid,
+ RTE_ETHER_ADDR_BYTES(&l2fwd_ports_eth_addr[portid]));
/* initialize port stats */
memset(&port_statistics, 0, sizeof(port_statistics));
"All available ports are disabled. Please set portmask.\n");
}
- check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask);
+ check_all_ports_link_status(l2fwd_enabled_port_mask);
drain_tsc = (hz + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US;
lcore_id);
continue;
}
- /* Add flush job.
- * Set fixed period by setting min = max = initial period. Set target to
- * zero as it is irrelevant for this job. */
+ /* Add flush job. 8< */
+
+ /* Set fixed period by setting min = max = initial period. Set target to
+ * zero as it is irrelevant for this job.
+ */
rte_jobstats_init(&qconf->flush_job, "flush", drain_tsc, drain_tsc,
drain_tsc, 0);
rte_exit(1, "Failed to reset flush job timer for lcore %u: %s",
lcore_id, rte_strerror(-ret));
}
+ /* >8 End of add flush job. */
for (i = 0; i < qconf->n_rx_port; i++) {
struct rte_jobstats *job = &qconf->port_fwd_jobs[i];
printf("Setting forward job for port %u\n", portid);
snprintf(name, RTE_DIM(name), "port %u fwd", portid);
- /* Setup forward job.
- * Set min, max and initial period. Set target to MAX_PKT_BURST as
- * this is desired optimal RX/TX burst size. */
+ /* Setup forward job. 8< */
+
+ /* Set min, max and initial period. Set target to MAX_PKT_BURST as
+ * this is desired optimal RX/TX burst size.
+ */
rte_jobstats_init(job, name, 0, drain_tsc, 0, MAX_PKT_BURST);
rte_jobstats_set_update_period_function(job, l2fwd_job_update_cb);
rte_exit(1, "Failed to reset lcore %u port %u job timer: %s",
lcore_id, qconf->rx_port_list[i], rte_strerror(-ret));
}
+ /* >8 End of forward job. */
}
}
RTE_LOG(INFO, L2FWD, "Stats display disabled\n");
/* launch per-lcore init on every lcore */
- rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MASTER);
- RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MAIN);
+ RTE_LCORE_FOREACH_WORKER(lcore_id) {
if (rte_eal_wait_lcore(lcore_id) < 0)
return -1;
}
+ /* clean up the EAL */
+ rte_eal_cleanup();
+
return 0;
}