numam-dpdk/examples/l3fwd/l3fwd_event.c
Conor Walsh 9510dd1feb examples/l3fwd: add FIB infrastructure
The purpose of this commit is to add the necessary function calls
and supporting infrastructure to allow the Forwarding Information Base
(FIB) library to be integrated into the l3fwd sample app.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>
2021-04-20 20:13:34 +02:00

277 lines
7.4 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(C) 2019 Marvell International Ltd.
*/
#include <stdbool.h>
#include <getopt.h>
#include <rte_malloc.h>
#include "l3fwd.h"
#include "l3fwd_event.h"
static void
print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
{
char buf[RTE_ETHER_ADDR_FMT_SIZE];
rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
printf("%s%s", name, buf);
}
struct l3fwd_event_resources *
l3fwd_get_eventdev_rsrc(void)
{
static struct l3fwd_event_resources *rsrc;
if (rsrc != NULL)
return rsrc;
rsrc = rte_zmalloc("l3fwd", sizeof(struct l3fwd_event_resources), 0);
if (rsrc != NULL) {
rsrc->sched_type = RTE_SCHED_TYPE_ATOMIC;
rsrc->eth_rx_queues = 1;
return rsrc;
}
rte_exit(EXIT_FAILURE, "Unable to allocate memory for eventdev cfg\n");
return NULL;
}
static void
l3fwd_eth_dev_port_setup(struct rte_eth_conf *port_conf)
{
struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc();
uint16_t nb_ports = rte_eth_dev_count_avail();
uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
unsigned int nb_lcores = rte_lcore_count();
struct rte_eth_conf local_port_conf;
struct rte_eth_dev_info dev_info;
struct rte_eth_txconf txconf;
struct rte_eth_rxconf rxconf;
unsigned int nb_mbuf;
uint16_t port_id;
uint8_t eth_qid;
int32_t ret;
/* initialize all ports */
RTE_ETH_FOREACH_DEV(port_id) {
local_port_conf = *port_conf;
/* skip ports that are not enabled */
if ((evt_rsrc->port_mask & (1 << port_id)) == 0) {
printf("\nSkipping disabled port %d\n", port_id);
continue;
}
/* init port */
printf("Initializing port %d ... ", port_id);
fflush(stdout);
printf("Creating queues: nb_rxq=%d nb_txq=1...\n",
evt_rsrc->eth_rx_queues);
ret = rte_eth_dev_info_get(port_id, &dev_info);
if (ret != 0)
rte_panic("Error during getting device (port %u) info:"
"%s\n", port_id, 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;
local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
dev_info.flow_type_rss_offloads;
if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
port_conf->rx_adv_conf.rss_conf.rss_hf) {
printf("Port %u modified RSS hash function "
"based on hardware support,"
"requested:%#"PRIx64" configured:%#"PRIx64"\n",
port_id,
port_conf->rx_adv_conf.rss_conf.rss_hf,
local_port_conf.rx_adv_conf.rss_conf.rss_hf);
}
ret = rte_eth_dev_configure(port_id, evt_rsrc->eth_rx_queues,
1, &local_port_conf);
if (ret < 0)
rte_exit(EXIT_FAILURE,
"Cannot configure device: err=%d, port=%d\n",
ret, port_id);
ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd,
&nb_txd);
if (ret < 0)
rte_exit(EXIT_FAILURE,
"Cannot adjust number of descriptors: err=%d, "
"port=%d\n", ret, port_id);
rte_eth_macaddr_get(port_id, &ports_eth_addr[port_id]);
print_ethaddr(" Address:", &ports_eth_addr[port_id]);
printf(", ");
print_ethaddr("Destination:",
(const struct rte_ether_addr *)&dest_eth_addr[port_id]);
printf(", ");
/* prepare source MAC for each port. */
rte_ether_addr_copy(&ports_eth_addr[port_id],
(struct rte_ether_addr *)(val_eth + port_id) + 1);
/* init memory */
if (!evt_rsrc->per_port_pool) {
/* port_id = 0; this is *not* signifying the first port,
* rather, it signifies that port_id is ignored.
*/
nb_mbuf = RTE_MAX(nb_ports * nb_rxd +
nb_ports * nb_txd +
nb_ports * nb_lcores *
MAX_PKT_BURST +
nb_lcores * MEMPOOL_CACHE_SIZE,
8192u);
ret = init_mem(0, nb_mbuf);
} else {
nb_mbuf = RTE_MAX(nb_rxd + nb_rxd +
nb_lcores * MAX_PKT_BURST +
nb_lcores * MEMPOOL_CACHE_SIZE,
8192u);
ret = init_mem(port_id, nb_mbuf);
}
/* init Rx queues per port */
rxconf = dev_info.default_rxconf;
rxconf.offloads = local_port_conf.rxmode.offloads;
for (eth_qid = 0; eth_qid < evt_rsrc->eth_rx_queues;
eth_qid++) {
if (!evt_rsrc->per_port_pool)
ret = rte_eth_rx_queue_setup(port_id, eth_qid,
nb_rxd, 0, &rxconf,
evt_rsrc->pkt_pool[0][0]);
else
ret = rte_eth_rx_queue_setup(port_id, eth_qid,
nb_rxd, 0, &rxconf,
evt_rsrc->pkt_pool[port_id][0]);
if (ret < 0)
rte_exit(EXIT_FAILURE,
"rte_eth_rx_queue_setup: err=%d, "
"port=%d, eth_qid: %d\n",
ret, port_id, eth_qid);
}
/* init one Tx queue per port */
txconf = dev_info.default_txconf;
txconf.offloads = local_port_conf.txmode.offloads;
ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd, 0, &txconf);
if (ret < 0)
rte_exit(EXIT_FAILURE,
"rte_eth_tx_queue_setup: err=%d, "
"port=%d\n", ret, port_id);
}
}
static void
l3fwd_event_capability_setup(void)
{
struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc();
uint32_t caps = 0;
uint16_t i;
int ret;
RTE_ETH_FOREACH_DEV(i) {
ret = rte_event_eth_tx_adapter_caps_get(0, i, &caps);
if (ret)
rte_exit(EXIT_FAILURE,
"Invalid capability for Tx adptr port %d\n",
i);
evt_rsrc->tx_mode_q |= !(caps &
RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT);
}
if (evt_rsrc->tx_mode_q)
l3fwd_event_set_generic_ops(&evt_rsrc->ops);
else
l3fwd_event_set_internal_port_ops(&evt_rsrc->ops);
}
int
l3fwd_get_free_event_port(struct l3fwd_event_resources *evt_rsrc)
{
static int index;
int port_id;
rte_spinlock_lock(&evt_rsrc->evp.lock);
if (index >= evt_rsrc->evp.nb_ports) {
printf("No free event port is available\n");
return -1;
}
port_id = evt_rsrc->evp.event_p_id[index];
index++;
rte_spinlock_unlock(&evt_rsrc->evp.lock);
return port_id;
}
void
l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
{
struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc();
const event_loop_cb lpm_event_loop[2][2] = {
[0][0] = lpm_event_main_loop_tx_d,
[0][1] = lpm_event_main_loop_tx_d_burst,
[1][0] = lpm_event_main_loop_tx_q,
[1][1] = lpm_event_main_loop_tx_q_burst,
};
const event_loop_cb em_event_loop[2][2] = {
[0][0] = em_event_main_loop_tx_d,
[0][1] = em_event_main_loop_tx_d_burst,
[1][0] = em_event_main_loop_tx_q,
[1][1] = em_event_main_loop_tx_q_burst,
};
const event_loop_cb fib_event_loop[2][2] = {
[0][0] = fib_event_main_loop_tx_d,
[0][1] = fib_event_main_loop_tx_d_burst,
[1][0] = fib_event_main_loop_tx_q,
[1][1] = fib_event_main_loop_tx_q_burst,
};
uint32_t event_queue_cfg;
int ret;
if (!evt_rsrc->enabled)
return;
if (!rte_event_dev_count())
rte_exit(EXIT_FAILURE, "No Eventdev found");
/* Setup eventdev capability callbacks */
l3fwd_event_capability_setup();
/* Ethernet device configuration */
l3fwd_eth_dev_port_setup(port_conf);
/* Event device configuration */
event_queue_cfg = evt_rsrc->ops.event_device_setup();
/* Event queue configuration */
evt_rsrc->ops.event_queue_setup(event_queue_cfg);
/* Event port configuration */
evt_rsrc->ops.event_port_setup();
/* Rx/Tx adapters configuration */
evt_rsrc->ops.adapter_setup();
/* Start event device */
ret = rte_event_dev_start(evt_rsrc->event_d_id);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Error in starting eventdev");
evt_rsrc->ops.lpm_event_loop = lpm_event_loop[evt_rsrc->tx_mode_q]
[evt_rsrc->has_burst];
evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
[evt_rsrc->has_burst];
evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
[evt_rsrc->has_burst];
}