Commit 87269a1e authored by Leonardo Lai's avatar Leonardo Lai

implementing init routine

parent 9464aa0d
**/*.a
**/*.marker
**/*.o
**/*.ro
......
......@@ -10,13 +10,15 @@ PREFIX_INCLUDE=/usr/local/include
PREFIX_BIN=/usr/local/bin
UDPDK_VERSION=0.1
# root is only needed to perform install
ifneq ($(shell id -u), 0)
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif
ifeq ($(RTE_TARGET),)
$(error "Please define RTE_TARGET environment variable")
endif
endif
UDPDK_DPDK=${RTE_SDK}/${RTE_TARGET}
......@@ -43,6 +45,7 @@ OBJS+= $(patsubst %.c,%.o,${SRCS})
all: libudpdk.a
# Export only symbols defined in the UDPDK API (also exclude DPDK symbols)
libudpdk.a: ${OBJS}
${LD} -d -r -o $*.ro ${OBJS}
nm $*.ro | grep -v ' U ' | cut -d ' ' -f 3 > $*_localize_list.tmp
......@@ -65,12 +68,15 @@ install:
rm -rf ${PREFIX_LIB}/libudpdk.a.${UDPDK_VERSION}
rm -rf ${PREFIX_LIB}/libudpdk.a
rm -rf ${PREFIX_INCLUDE}/udpdk_api.h
rm -rf ${PREFIX_INCLUDE}/udpdk_constants.h
cp -f libudpdk.a ${PREFIX_LIB}/libudpdk.a.${UDPDK_VERSION}
ln -sf ${PREFIX_LIB}/libudpdk.a.${UDPDK_VERSION} ${PREFIX_LIB}/libudpdk.a
cp -f udpdk_api.h ${PREFIX_INCLUDE}/udpdk_api.h
cp -f udpdk_api.h ${PREFIX_INCLUDE}/udpdk_constants.h
uninstall:
rm -rf ${PREFIX_LIB}/libudpdk.a.${UDPDK_VERSION}
rm -rf ${PREFIX_LIB}/libudpdk.a
rm -rf ${PREFIX_INCLUDE}/udpdk_api.h
rm -rf ${PREFIX_INCLUDE}/udpdk_constants.h
//
// Created by leoll2 on 9/26/20.
// Copyright (c) 2020 Leonardo Lai. All rights reserved.
//
#ifndef UDPDK_CONSTANTS_H
#define UDPDK_CONSTANTS_H
#define NUM_SOCKETS_MAX 1024
/* Exchange memzone */
#define EXCH_MEMZONE_NAME "UDPDK_exchange_desc"
#define EXCH_SLOTS_NAME "UDPDK_exchange_slots"
#define EXCH_RING_SIZE 128
#define EXCH_RX_RING_NAME "UDPDK_exchange_ring_%u_RX"
#define EXCH_TX_RING_NAME "UDPDK_exchange_ring_%u_TX"
/* DPDK ports */
#define PORT_RX 0
#define PORT_TX 0
#define NUM_RX_DESC_DEFAULT 1024
#define NUM_TX_DESC_DEFAULT 1024
#define PKTMBUF_POOL_NAME "UDPDK_mbuf_pool"
#define MBUF_CACHE_SIZE 512
#endif //UDPDK_CONSTANTS_H
......@@ -7,26 +7,291 @@
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_launch.h>
#include "rte_log.h"
#include <rte_lcore.h>
#include <rte_log.h>
#include <rte_malloc.h>
#include <rte_memory.h>
#include <rte_memzone.h>
#include "udpdk_api.h"
#include "udpdk_constants.h"
#define RTE_LOGTYPE_INIT RTE_LOGTYPE_USER1
static int init_mbuf_pools(void)
struct exch_slot_info {
int active;
int sockfd;
} __rte_cache_aligned;
struct exch_zone_info {
uint64_t n_zones_active;
struct exch_slot_info slots[NUM_SOCKETS_MAX];
};
struct exch_zone_info *exch_zone_desc = NULL;
struct exch_slot {
struct rte_ring *rx_q;
struct rte_ring *tx_q;
unsigned id;
};
struct exch_slot *exch_slots = NULL;
static struct rte_mempool *pktmbuf_pool;
// TODO move to a utility file
enum exch_ring_func {EXCH_RING_RX, EXCH_RING_TX};
/* Get the name of the rings of exchange slots */
static inline const char * get_exch_ring_name(unsigned id, enum exch_ring_func func)
{
static char buffer[sizeof(EXCH_RX_RING_NAME) + 8];
if (func == EXCH_RING_RX) {
snprintf(buffer, sizeof(buffer), EXCH_RX_RING_NAME, id);
} else {
snprintf(buffer, sizeof(buffer), EXCH_TX_RING_NAME, id);
}
return buffer;
}
/* Initialize a pool of mbuf for reception and transmission */
static int init_mbuf_pool(void)
{
const unsigned int num_mbufs_rx = NUM_RX_DESC_DEFAULT;
const unsigned int num_mbufs_tx = NUM_TX_DESC_DEFAULT;
const unsigned int num_mbufs_cache = 2 * MBUF_CACHE_SIZE;
const unsigned int num_mbufs = num_mbufs_rx + num_mbufs_tx + num_mbufs_cache;
pktmbuf_pool = rte_pktmbuf_pool_create(PKTMBUF_POOL_NAME, num_mbufs, MBUF_CACHE_SIZE, 0,
RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
return pktmbuf_pool == NULL; // 0 on success
}
/* Initialize a DPDK port */
static int init_port(uint16_t port_num)
{
// TODO add support for multiple rings
const struct rte_eth_conf port_conf = {
.rxmode = {
.mq_mode = ETH_MQ_RX_RSS
}
};
const uint16_t rx_rings = 1;
const uint16_t tx_rings = 1;
uint16_t rx_ring_size = NUM_RX_DESC_DEFAULT;
uint16_t tx_ring_size = NUM_TX_DESC_DEFAULT;
uint16_t q;
int retval;
// Configure mode and number of rings
retval = rte_eth_dev_configure(port_num, rx_rings, tx_rings, &port_conf);
if (retval != 0) {
RTE_LOG(ERR, INIT, "Could not configure port %d\n", port_num);
return retval;
}
// Adjust the number of descriptors
retval = rte_eth_dev_adjust_nb_rx_tx_desc(port_num, &rx_ring_size, &tx_ring_size);
if (retval != 0) {
RTE_LOG(ERR, INIT, "Could not adjust rx/tx descriptors on port %d\n", port_num);
return retval;
}
// Setup the RX queues
for (q = 0; q < rx_rings; q++) {
retval = rte_eth_rx_queue_setup(port_num, q, rx_ring_size,
rte_eth_dev_socket_id(port_num), NULL, pktmbuf_pool);
if (retval < 0) {
RTE_LOG(ERR, INIT, "Could not setup RX queue %d on port %d\n", q, port_num);
return retval;
}
}
// Setup the TX queues
for (q = 0; q < tx_rings; q++) {
retval = rte_eth_tx_queue_setup(port_num, q, tx_ring_size,
rte_eth_dev_socket_id(port_num), NULL); // no particular configuration needed
if (retval < 0) {
RTE_LOG(ERR, INIT, "Could not setup TX queue %d on port %d\n", q, port_num);
return retval;
}
}
// Enable promiscuous mode
retval = rte_eth_promiscuous_enable(port_num);
if (retval < 0) {
RTE_LOG(ERR, INIT, "Could not set port %d to promiscous mode\n", port_num);
return retval;
}
// Start the DPDK port
retval = rte_eth_dev_start(port_num);
if (retval < 0) {
RTE_LOG(ERR, INIT, "Could not start port %d\n", port_num);
return retval;
}
RTE_LOG(INFO, INIT, "Initialized port %d.\n", port_num);
return 0;
}
static void check_port_link_status(uint16_t portid) {
#define CHECK_INTERVAL 100 // 100ms
#define MAX_CHECK_TIME 90 // how many times
uint8_t count, all_ports_up, print_flag = 0;
struct rte_eth_link link;
int ret;
RTE_LOG(INFO, INIT, "Checking link status of port %d.\n", portid);
for (count = 0; count <= MAX_CHECK_TIME; count++) {
all_ports_up = 1;
memset(&link, 0, sizeof(link));
ret = rte_eth_link_get_nowait(portid, &link);
if (ret < 0) {
all_ports_up = 0;
if (print_flag == 1)
RTE_LOG(WARNING, INIT, "Port %u link get failed: %s\n", portid, rte_strerror(-ret));
continue;
}
if (print_flag == 1) {
if (link.link_status) {
RTE_LOG(INFO, INIT, "Port %d Link Up - speed %u Mbps - %s\n", portid, (unsigned) link.link_speed,
(link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n"));
break;
} else {
RTE_LOG(INFO, INIT, "Port %d Link Down\n", (uint8_t) portid);
}
continue;
}
if (link.link_status == ETH_LINK_DOWN) {
all_ports_up = 0;
break;
}
if (print_flag == 1)
return;
if (all_ports_up == 0) {
printf(".");
fflush(stdout);
rte_delay_ms(CHECK_INTERVAL);
}
if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
print_flag = 1;
}
}
}
/* Initialize a shared memory region to contain descriptors for the exchange slots */
static int init_shared_memzone(void)
{
const struct rte_memzone *mz;
mz = rte_memzone_reserve(EXCH_MEMZONE_NAME, sizeof(*exch_zone_desc), rte_socket_id(), 0);
if (mz == NULL)
return -1;
memset(mz->addr, 0, sizeof(*exch_zone_desc));
exch_zone_desc = mz->addr;
// TODO any field to set to a specific value?
return 0;
}
static int init_exchange_slots(void)
{
// TODO implement
// TODO allocate slots dynamically in udpdk_socket() instead of pre-allocating all them statically
unsigned i;
unsigned socket_id;
const char *q_name;
socket_id = rte_socket_id();
// Allocate enough memory to store the exchange slots
exch_slots = rte_malloc(EXCH_SLOTS_NAME, sizeof(*exch_slots) * NUM_SOCKETS_MAX, 0);
if (exch_slots == NULL)
rte_exit(EXIT_FAILURE, "Cannot allocate memory for exchange slots\n");
// Create a rte_ring for each RX and TX slot
for (i = 0; i < NUM_SOCKETS_MAX; i++) {
q_name = get_exch_ring_name(i, EXCH_RING_RX);
exch_slots[i].rx_q = rte_ring_create(q_name, EXCH_RING_SIZE, socket_id, RING_F_SP_ENQ | RING_F_SC_DEQ);
q_name = get_exch_ring_name(i, EXCH_RING_TX);
exch_slots[i].tx_q = rte_ring_create(q_name, EXCH_RING_SIZE, socket_id, RING_F_SP_ENQ | RING_F_SC_DEQ);
if (exch_slots[i].rx_q == NULL || exch_slots[i].tx_q == NULL) {
RTE_LOG(ERR, INIT, "Cannot create exchange RX/TX exchange rings (index %d)\n", i);
return -1;
}
}
return 0;
}
/* Initialize DPDK */
int udpdk_init(int argc, char *argv[])
{
// TODO implement
int retval;
// Initialize EAL (returns how many arguments it consumed)
retval = rte_eal_init(argc, argv);
if (retval < 0) {
RTE_LOG(ERR, INIT, "Cannot initialize EAL\n");
return -1;
}
argc -= retval;
argv += retval;
// Initialize pool of mbuf
retval = init_mbuf_pool();
if (retval < 0) {
RTE_LOG(ERR, INIT, "Cannot initialize pool of mbufs\n");
return -1;
}
// Initialize DPDK ports
retval = init_port(PORT_RX);
if (retval < 0) {
RTE_LOG(ERR, INIT, "Cannot initialize RX port %d\n", PORT_RX);
return -1;
}
check_port_link_status(PORT_RX);
if (PORT_TX != PORT_RX) {
retval = init_port(PORT_TX);
if (retval < 0) {
RTE_LOG(ERR, INIT, "Cannot initialize TX port %d\n", PORT_TX);
return -1;
}
check_port_link_status(PORT_TX);
} else {
RTE_LOG(INFO, INIT, "Using the same port for RX and TX\n");
}
// Initialize memzone for exchange
retval = init_shared_memzone();
if (retval < 0) {
RTE_LOG(ERR, INIT, "Cannot initialize memzone for exchange zone descriptors\n");
return -1;
}
retval = init_exchange_slots();
if (retval < 0) {
RTE_LOG(ERR, INIT, "Cannot initialize exchange slots\n");
return -1;
}
// TODO initialize shared structures
// TODO start the secondary process
return 0;
}
void udpdk_cleanup(void)
{
// TODO implement
uint16_t port_id;
// Stop and close DPDK ports
RTE_ETH_FOREACH_DEV(port_id) {
rte_eth_dev_stop(port_id);
rte_eth_dev_close(port_id);
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment