Commit 9c13289b authored by Leonardo Lai's avatar Leonardo Lai

parsing configuration file

parent 79657fbd
......@@ -33,3 +33,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This software uses code from:
- DPDK: https://www.dpdk.org/
License: BSD 3-Clause
- inih: https://github.com/benhoyt/inih
License: BSD 3-Clause
# UDPDK
UDPDK is a minimal UDP/IP stack based on DPDK for fast point-to-point communication between hosts.
UDPDK API is POSIX to facilitate porting of existing applications.
## Install dependencies
```
git submodule init
git submodule update
```
### DPDK
TODO
### inih
```
cd inih
meson build
cd build
ninja
```
## Install UDPDK
```
cd udpdk
make
sudo make install
```
# UDPDK configuration file
[dpdk]
lcores_primary=2
lcores_secondary=4
n_mem_channels=2
[port0]
mac_addr=68:05:ca:95:f8:ec
[port0_dst]
mac_addr=68:05:ca:95:fa:64
......@@ -22,8 +22,10 @@ endif
UDPDK_DPDK=${RTE_SDK}/${RTE_TARGET}
INIH=${ROOTDIR}/inih
CFLAGS= -march=native -O2
CFLAGS+= -Wall -Wno-deprecated-declarations -Werror
CFLAGS+= -Wall -Wno-deprecated-declarations -Werror -Wno-unused-variable
CFLAGS+= -fno-common -finline-limit=8000
CFLAGS+= --param inline-unit-growth=100
CFLAGS+= --param large-function-growth=1000
......@@ -32,26 +34,30 @@ DPDK_CFLAGS= -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_
DPDK_CFLAGS+= -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2
DPDK_CFLAGS+= -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2
DPDK_CFLAGS+= -I${UDPDK_DPDK}/include
DPDK_CFLAGS+= -I${INIH}
UDPDK_C= ${CC} -c $(DPDK_CFLAGS) ${CFLAGS} ${WERROR} $<
UDPDK_SRCS+= \
udpdk_syscall.c \
udpdk_args.c \
udpdk_globals.c \
udpdk_init.c \
udpdk_poller.c \
udpdk_lookup_table.c \
udpdk_globals.c \
udpdk_poller.c \
udpdk_syscall.c \
SRCS= ${UDPDK_SRCS}
OBJS+= $(patsubst %.c,%.o,${SRCS})
INIH_OBJS+= ${INIH}/build/libinih.a
all: libudpdk.a
# Export only symbols defined in the UDPDK API (also exclude DPDK symbols)
libudpdk.a: ${OBJS}
${LD} -d -r -o $*.ro ${OBJS}
${LD} -d -r -o $*.ro ${OBJS} ${INIH_OBJS}
nm $*.ro | grep -v ' U ' | cut -d ' ' -f 3 > $*_localize_list.tmp
objcopy --localize-symbols=$*_localize_list.tmp $*.ro
rm $*_localize_list.tmp
......@@ -72,6 +78,7 @@ 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_args.h
rm -rf ${PREFIX_INCLUDE}/udpdk_constants.h
rm -rf ${PREFIX_INCLUDE}/udpdk_poller.h
rm -rf ${PREFIX_INCLUDE}/udpdk_types.h
......@@ -80,6 +87,7 @@ install:
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_args.h
cp -f udpdk_constants.h ${PREFIX_INCLUDE}/udpdk_constants.h
cp -f udpdk_lookup_table.h ${PREFIX_INCLUDE}/udpdk_lookup_table.h
cp -f udpdk_poller.h ${PREFIX_INCLUDE}/udpdk_poller.h
......@@ -90,6 +98,7 @@ 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_args.h
rm -rf ${PREFIX_INCLUDE}/udpdk_constants.h
rm -rf ${PREFIX_INCLUDE}/udpdk_poller.h
rm -rf ${PREFIX_INCLUDE}/udpdk_types.h
......
//
// Created by leoll2 on 10/6/20.
// Copyright (c) 2020 Leonardo Lai. All rights reserved.
//
#include <rte_ether.h>
#include "ini.h"
#include "udpdk_args.h"
#include "udpdk_types.h"
extern configuration config;
extern int primary_argc;
extern int secondary_argc;
extern char *primary_argv[MAX_ARGC];
extern char *secondary_argv[MAX_ARGC];
static char *progname;
static int parse_handler(void* configuration, const char* section, const char* name, const char* value)
{
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
if (MATCH("port0", "mac_addr")) {
if (rte_ether_unformat_addr(value, &config.src_mac_addr) < 0) {
fprintf(stderr, "Can't parse MAC address: %s\n", value);
return 0;
}
} else if (MATCH("port0_dst", "mac_addr")) {
if (rte_ether_unformat_addr(value, &config.dst_mac_addr) < 0) {
fprintf(stderr, "Can't parse MAC address: %s\n", value);
return 0;
}
} else if (MATCH("dpdk", "lcores_primary")) {
strncpy(config.lcores_primary, value, MAX_ARG_LEN);
} else if (MATCH("dpdk", "lcores_secondary")) {
strncpy(config.lcores_secondary, value, MAX_ARG_LEN);
} else if (MATCH("dpdk", "n_mem_channels")) {
config.n_mem_channels = atoi(value);
} else {
fprintf(stderr, "Do not know how to parse section:%s name:%s\n", section, name);
return 0; // unknown section/name
}
return 1;
}
static int setup_primary_secondary_args(int argc, char *argv[])
{
// Build primary args
primary_argc = 0;
primary_argv[primary_argc] = malloc(strlen(progname)+1);
snprintf(primary_argv[primary_argc], MAX_ARG_LEN, "%s", progname);
primary_argc++;
primary_argv[primary_argc] = malloc(3);
snprintf(primary_argv[primary_argc], 3, "-l");
primary_argc++;
primary_argv[primary_argc] = malloc(strlen(config.lcores_primary)+1);
snprintf(primary_argv[primary_argc], MAX_ARG_LEN, "%s", config.lcores_primary);
primary_argc++;
primary_argv[primary_argc] = malloc(3);
snprintf(primary_argv[primary_argc], 3, "-n");
primary_argc++;
primary_argv[primary_argc] = malloc(8);
snprintf(primary_argv[primary_argc], MAX_ARG_LEN, "%d", config.n_mem_channels);
primary_argc++;
primary_argv[primary_argc] = malloc(strlen("--proc-type=primary")+1);
snprintf(primary_argv[primary_argc], MAX_ARG_LEN, "--proc-type=primary");
primary_argc++;
// Build secondary args
secondary_argc = 0;
secondary_argv[secondary_argc] = malloc(strlen(progname)+1);
snprintf(secondary_argv[secondary_argc], MAX_ARG_LEN, "%s", progname);
secondary_argc++;
secondary_argv[secondary_argc] = malloc(3);
snprintf(secondary_argv[secondary_argc], 3, "-l");
secondary_argc++;
secondary_argv[secondary_argc] = malloc(strlen(config.lcores_secondary)+1);
snprintf(secondary_argv[secondary_argc], MAX_ARG_LEN, "%s", config.lcores_secondary);
secondary_argc++;
secondary_argv[secondary_argc] = malloc(3);
snprintf(secondary_argv[secondary_argc], 3, "-n");
secondary_argc++;
secondary_argv[secondary_argc] = malloc(8);
snprintf(secondary_argv[secondary_argc], MAX_ARG_LEN, "%d", config.n_mem_channels);
secondary_argc++;
secondary_argv[secondary_argc] = malloc(strlen("--proc-type=secondary")+1);
snprintf(secondary_argv[secondary_argc], MAX_ARG_LEN, "--proc-type=secondary");
secondary_argc++;
if (primary_argc + argc >= MAX_ARGC) {
return -1;
}
// Append app arguments to primary after --
primary_argv[primary_argc] = malloc(3);
snprintf(primary_argv[primary_argc], 3, "--");
primary_argc++;
for (int i = 0; i < argc; i++) {
primary_argv[primary_argc] = malloc(strlen(argv[i])+1);
snprintf(primary_argv[primary_argc], MAX_ARG_LEN, "%s", argv[i]);
primary_argc++;
}
printf("Application args: ");
for (int i = 0; i < primary_argc; i++)
printf("%s ", primary_argv[i]);
printf("\n");
printf("Poller args: ");
for (int i = 0; i < secondary_argc; i++)
printf("%s ", secondary_argv[i]);
printf("\n");
return 0;
}
int udpdk_parse_args(int argc, char *argv[])
{
int c;
char *cfg_filename;
if (argc < 3) {
fprintf(stderr, "Too few arguments (must specify at least the configuration file\n");
return -1;
}
progname = argv[0];
// Get the name of the .ini config file
c = getopt (argc, argv, "c:");
if (c == 'c') {
cfg_filename = optarg;
if (strlen(optarg) <= 4 || strcmp(optarg + strlen(optarg) - 4, ".ini")) {
fprintf(stderr, "The configuration file (%s) is not a .ini file apparently!\n", cfg_filename);
return -1;
}
argc -= 2;
argv += 2;
} else {
fprintf(stderr, "Unknown option `-%c'.\n", optopt);
return -1;
}
argc--;
argv++;
if (ini_parse(cfg_filename, parse_handler, NULL) < 0) {
fprintf(stderr, "Can not parse configuration file %s\n", cfg_filename);
return -1;
}
// Initialize global arrays of arguments for primary and secondary
if (setup_primary_secondary_args(argc, argv) < 0) {
fprintf(stderr, "Failed to initialize primary/secondary arguments\n");
return -1;
}
return 0;
}
\ No newline at end of file
//
// Created by leoll2 on 10/6/20.
// Copyright (c) 2020 Leonardo Lai. All rights reserved.
//
#ifndef UDPDK_ARGS_H
#define UDPDK_ARGS_H
int udpdk_parse_args(int argc, char *argv[]);
#endif //UDPDK_ARGS_H
......@@ -56,4 +56,8 @@
#define IP_HDRLEN 0x05
#define IP_VHL_DEF (IP_VERSION | IP_HDRLEN)
/* Parser */
#define MAX_ARGC 64
#define MAX_ARG_LEN 256
#endif //UDPDK_CONSTANTS_H
......@@ -3,11 +3,22 @@
// Copyright (c) 2020 Leonardo Lai. All rights reserved.
//
#include "udpdk_constants.h"
#include "udpdk_lookup_table.h"
#include "udpdk_types.h"
volatile int interrupted = 0;
configuration config;
int primary_argc = 0;
int secondary_argc = 0;
char *primary_argv[MAX_ARGC];
char *secondary_argv[MAX_ARGC];
struct rte_mempool *rx_pktmbuf_pool = NULL;
struct rte_mempool *tx_pktmbuf_pool = NULL;
......
......@@ -21,6 +21,7 @@
#include <rte_memzone.h>
#include "udpdk_api.h"
#include "udpdk_args.h"
#include "udpdk_constants.h"
#include "udpdk_lookup_table.h"
#include "udpdk_poller.h"
......@@ -38,6 +39,10 @@ extern struct rte_mempool *rx_pktmbuf_pool;
extern struct rte_mempool *tx_pktmbuf_pool;
extern struct rte_mempool *tx_pktmbuf_direct_pool;
extern struct rte_mempool *tx_pktmbuf_indirect_pool;
extern int primary_argc;
extern int secondary_argc;
extern char *primary_argv[MAX_ARGC];
extern char *secondary_argv[MAX_ARGC];
static pid_t poller_pid;
/* Get the name of the rings of exchange slots */
......@@ -278,14 +283,19 @@ static int init_exchange_slots(void)
/* Initialize UDPDK */
int udpdk_init(int argc, char *argv[])
{
int retval, args_consumed;
int retval;
// Initialize UDPDK
if (udpdk_parse_args(argc, argv) < 0) { // initializes primary and secondary argc argv
RTE_LOG(ERR, INIT, "Invalid arguments for UDPDK\n");
return -1;
}
// Start the secondary process
poller_pid = fork();
if (poller_pid != 0) { // parent -> application
// Initialize EAL (returns how many arguments it consumed)
args_consumed = rte_eal_init(argc, argv);
if (args_consumed < 0) {
if (rte_eal_init(primary_argc, (char **)primary_argv) < 0) {
RTE_LOG(ERR, INIT, "Cannot initialize EAL\n");
return -1;
}
......@@ -335,25 +345,15 @@ int udpdk_init(int argc, char *argv[])
return -1;
}
} else { // child -> packet poller
// TODO the arguments should come from a config rather than being hardcoded
int poller_argc = 6;
char *poller_argv[6] = {
"./testapp",
"-l",
"3-4",
"-n",
"2",
"--proc-type=secondary"
};
sleep(1); // TODO use some synchronization mechanism between primary and secondary
if (poller_init(poller_argc, poller_argv) < 0) {
if (poller_init(secondary_argc, (char **)secondary_argv) < 0) {
RTE_LOG(INFO, INIT, "Poller initialization failed\n");
return -1;
}
poller_body();
}
// The parent process (application) returns immediately from init; instead, poller doesn't till it dies (or error)
return args_consumed;
return 0;
}
void udpdk_interrupt(int signum)
......
......@@ -195,7 +195,7 @@ ssize_t udpdk_sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr_in *dest_addr_in = (struct sockaddr_in *)dest_addr;
static struct rte_ether_addr src_eth_addr = { {0x68, 0x05, 0xca, 0x95, 0xf8, 0xec} }; // TODO from configuration
static uint32_t src_ip_addr = RTE_IPV4(2, 100, 31, 172); // TODO from bind (reversed for endianness=
static uint32_t src_ip_addr = RTE_IPV4(2, 100, 31, 172); // TODO from bind (reversed for endianness)
static struct rte_ether_addr dst_eth_addr = { {0x68, 0x05, 0xca, 0x95, 0xfa, 0x64} }; // TODO from configuration
// Validate the arguments
......
......@@ -43,4 +43,12 @@ struct exch_slot {
uint16_t rx_count; // current number of packets in the rx buffer
} __rte_cache_aligned;
typedef struct {
struct rte_ether_addr src_mac_addr;
struct rte_ether_addr dst_mac_addr;
char lcores_primary[MAX_ARG_LEN];
char lcores_secondary[MAX_ARG_LEN];
int n_mem_channels;
} configuration;
#endif //UDPDK_TYPES_H
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