@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include <example_debug.h>
#include <odp_api.h>
#include <odp/helper/linux.h>
#include <odp/helper/eth.h>
@@ -14,19 +15,27 @@
#include <odp/helper/udp.h>
#include <odp/helper/tcp.h>
+#include <getopt.h>
+
#include "odp_l3fwd_db.h"
#define POOL_NUM_PKT 8192
#define POOL_SEG_LEN 1856
#define MAX_PKT_BURST 32
-static const char * const route_str[] = {
- "1.1.1.0/24:fm1-mac1:00.e0.0c.00.85.00",
- "2.1.1.0/24:fm1-mac2:00.e0.0c.00.85.01",
-};
-
#define MAX_NB_WORKER 8
#define MAX_NB_PKTIO 4
+#define MAX_NB_ROUTE 32
+
+/** Get rid of path in filename - only for unix-type paths using '/' */
+#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
+ strrchr((file_name), '/') + 1 : (file_name))
+
+typedef struct {
+ char *if_names[MAX_NB_PKTIO];
+ uint32_t if_count;
+ char *route_str[MAX_NB_ROUTE];
+} app_args_t;
struct l3fwd_pktio_s {
odp_pktio_t pktio;
@@ -39,6 +48,7 @@ struct thread_arg_s {
};
struct {
+ app_args_t cmd_args;
struct l3fwd_pktio_s l3fwd_pktios[MAX_NB_PKTIO];
odph_linux_pthread_t l3fwd_workers[MAX_NB_WORKER];
struct thread_arg_s worker_args[MAX_NB_WORKER];
@@ -46,6 +56,10 @@ struct {
uint32_t nb_worker; /* effective workers */
} global;
+static void print_usage(char *progname);
+static void print_info(char *progname, app_args_t *args);
+static void parse_cmdline_args(int argc, char *argv[], app_args_t *args);
+
static odp_pktio_t create_pktio(const char *name, odp_pool_t pool,
odp_pktin_queue_t *pktin,
odp_pktout_queue_t *pktout)
@@ -97,16 +111,17 @@ static void *run_worker(void *arg)
odp_packet_t pkt_tbl_drop[MAX_PKT_BURST];
uint32_t pkts, i;
struct l3fwd_pktio_s *port;
+ char *if_name;
i = ((struct thread_arg_s *)arg)->if_idx;
port = &global.l3fwd_pktios[i];
-
+ if_name = global.cmd_args.if_names[i];
if (odp_pktio_start(port->pktio)) {
- printf("unable to start interface: %d\n", i);
+ printf("unable to start pktio: %s\n", if_name);
exit(1);
}
- printf("start interface: %d\n", i);
+ printf("start pktio: %s\n", if_name);
for (;;) {
int need_to_drop = 0;
@@ -180,13 +195,7 @@ int main(int argc, char **argv)
odph_linux_thr_params_t thr_params;
uint32_t cpu, i;
uint8_t mac[ODPH_ETHADDR_LEN];
-
- if (argc != 3) {
- printf("Usage: odp_l3fwd eth0 eth1\n");
- printf("Where eth0 and eth1 are the used interfaces"
- " (must have 2 of them)\n");
- exit(1);
- }
+ app_args_t *args;
if (odp_init_global(&instance, NULL, NULL)) {
printf("Error: ODP global init failed.\n");
@@ -201,17 +210,21 @@ int main(int argc, char **argv)
/* Clear global argument */
memset(&global, 0, sizeof(global));
+ /* Parse cmdline arguments */
+ args = &global.cmd_args;
+ parse_cmdline_args(argc, argv, args);
+
/* Init l3fwd tale */
init_fwd_db();
/* Add route into table */
- for (i = 0; i < sizeof(route_str) / sizeof(char *); i++) {
- char buf[128];
-
- snprintf(buf, 128, "%s", route_str[i]);
- create_fwd_db_entry(buf);
+ for (i = 0; i < MAX_NB_ROUTE; i++) {
+ if (args->route_str[i])
+ create_fwd_db_entry(args->route_str[i]);
}
+ print_info(NO_PATH(argv[0]), args);
+
/* Create packet pool */
odp_pool_param_init(¶ms);
params.pkt.seg_len = POOL_SEG_LEN;
@@ -226,20 +239,25 @@ int main(int argc, char **argv)
exit(1);
}
- /* TODO: parse cmdline to get pktio number, name */
- global.nb_pktio = 2;
+ global.nb_pktio = args->if_count;
for (i = 0; i < global.nb_pktio; i++) {
struct l3fwd_pktio_s *port;
- char *ifname = argv[i + 1];
+ char buf[16];
port = &global.l3fwd_pktios[i];
- port->pktio = create_pktio(ifname, pool, &port->ifin,
+ port->pktio = create_pktio(args->if_names[i], pool, &port->ifin,
&port->ifout);
odp_pktio_mac_addr(port->pktio, mac, ODPH_ETHADDR_LEN);
- resolve_fwd_db(ifname, port->pktio, mac);
+ resolve_fwd_db(args->if_names[i], port->pktio, mac);
+
+ /* print mac string, could be used to config pktgen */
+ sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ printf("create pktio %s, mac %s\n", args->if_names[i], buf);
}
- global.nb_worker = 2;
+ /* one thread for each port */
+ global.nb_worker = args->if_count;
memset(&thr_params, 0, sizeof(thr_params));
thr_params.start = run_worker;
thr_params.thr_type = ODP_THREAD_WORKER;
@@ -264,3 +282,149 @@ int main(int argc, char **argv)
return 0;
}
+
+static void print_usage(char *progname)
+{
+ printf("\n"
+ "ODP L3 forwarding application.\n"
+ "\n"
+ "Usage: %s OPTIONS\n"
+ " E.g. %s -i eth0,eth1\n"
+ " In the above example,\n"
+ " eth0 will send pkts to eth1 and vice versa\n"
+ "\n"
+ "Mandatory OPTIONS:\n"
+ " -i, --interface eth interfaces (comma-separated, no spaces)\n"
+ " -r, --route SubNet:Intf[:NextHopMAC]\n"
+ " NextHopMAC can be optional, in this case, zeroed mac\n"
+ "\n"
+ "Optional OPTIONS\n"
+ " -h, --help Display help and exit.\n\n"
+ "\n", NO_PATH(progname), NO_PATH(progname)
+ );
+}
+
+static void parse_cmdline_args(int argc, char *argv[], app_args_t *args)
+{
+ int opt;
+ int long_index;
+ char *token, *local;
+ size_t len, route_index = 0;
+ int i, mem_failure = 0;
+
+ static struct option longopts[] = {
+ {"interface", required_argument, NULL, 'i'}, /* return 'i' */
+ {"route", required_argument, NULL, 'r'}, /* return 'r' */
+ {"help", no_argument, NULL, 'h'}, /* return 'h' */
+ {NULL, 0, NULL, 0}
+ };
+
+ while (1) {
+ opt = getopt_long(argc, argv, "+i:r:h",
+ longopts, &long_index);
+
+ if (opt == -1)
+ break; /* No more options */
+
+ switch (opt) {
+ /* parse packet-io interface names */
+ case 'i':
+ len = strlen(optarg);
+ if (len == 0) {
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ len += 1; /* add room for '\0' */
+
+ local = malloc(len);
+ if (!local) {
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* count the number of tokens separated by ',' */
+ strcpy(local, optarg);
+ for (token = strtok(local, ","), i = 0;
+ token != NULL;
+ token = strtok(NULL, ","), i++)
+ ;
+
+ if (i == 0) {
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ args->if_count = i;
+
+ /* store the if names (reset names string) */
+ strcpy(local, optarg);
+ for (token = strtok(local, ","), i = 0;
+ token != NULL; token = strtok(NULL, ","), i++) {
+ args->if_names[i] = token;
+ }
+ break;
+
+ /*Configure Route in forwarding database*/
+ case 'r':
+ if (route_index >= MAX_NB_ROUTE) {
+ printf("No more routes can be added\n");
+ break;
+ }
+ local = calloc(1, strlen(optarg) + 1);
+ if (!local) {
+ mem_failure = 1;
+ break;
+ }
+ memcpy(local, optarg, strlen(optarg));
+ local[strlen(optarg)] = '\0';
+ args->route_str[route_index++] = local;
+ break;
+
+ case 'h':
+ print_usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (args->if_count == 0 || mem_failure == 1) {
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ optind = 1; /* reset 'extern optind' from the getopt lib */
+}
+
+static void print_info(char *progname, app_args_t *args)
+{
+ uint32_t i;
+
+ printf("\n"
+ "ODP system info\n"
+ "---------------\n"
+ "ODP API version: %s\n"
+ "ODP impl name: %s\n"
+ "CPU model: %s\n"
+ "CPU freq (hz): %" PRIu64 "\n"
+ "Cache line size: %i\n"
+ "CPU count: %i\n"
+ "\n",
+ odp_version_api_str(), odp_version_impl_name(),
+ odp_cpu_model_str(), odp_cpu_hz_max(),
+ odp_sys_cache_line_size(), odp_cpu_count());
+
+ printf("Running ODP appl: \"%s\"\n"
+ "-----------------\n"
+ "IF-count: %i\n"
+ "Using IFs: ",
+ progname, args->if_count);
+
+ for (i = 0; i < args->if_count; ++i)
+ printf(" %s", args->if_names[i]);
+
+ printf("\n\n");
+ fflush(NULL);
+}
@@ -342,15 +342,6 @@ int create_fwd_db_entry(char *input)
pos++;
}
- /* Verify we parsed exactly the number of tokens we expected */
- if (3 != pos) {
- printf("ERROR: \"%s\" contains %d tokens, expected 3\n",
- input,
- pos);
- free(local);
- return -1;
- }
-
/* Reset pktio to invalid */
entry->pktio = ODP_PKTIO_INVALID;