1*7faf4bd3SDavid Marchand /* SPDX-License-Identifier: BSD-3-Clause
2*7faf4bd3SDavid Marchand * Copyright(c) 2016-2017 Intel Corporation
3*7faf4bd3SDavid Marchand */
4*7faf4bd3SDavid Marchand
5*7faf4bd3SDavid Marchand #include <stdio.h>
6*7faf4bd3SDavid Marchand #include <stdlib.h>
7*7faf4bd3SDavid Marchand #include <stdint.h>
8*7faf4bd3SDavid Marchand #include <getopt.h>
9*7faf4bd3SDavid Marchand #include <stdarg.h>
10*7faf4bd3SDavid Marchand #include <errno.h>
11*7faf4bd3SDavid Marchand
12*7faf4bd3SDavid Marchand #include <rte_memory.h>
13*7faf4bd3SDavid Marchand #include <rte_string_fns.h>
14*7faf4bd3SDavid Marchand
15*7faf4bd3SDavid Marchand #include "common.h"
16*7faf4bd3SDavid Marchand #include "args.h"
17*7faf4bd3SDavid Marchand #include "init.h"
18*7faf4bd3SDavid Marchand
19*7faf4bd3SDavid Marchand /* 1M flows by default */
20*7faf4bd3SDavid Marchand #define DEFAULT_NUM_FLOWS 0x100000
21*7faf4bd3SDavid Marchand
22*7faf4bd3SDavid Marchand /* global var for number of nodes - extern in header */
23*7faf4bd3SDavid Marchand uint8_t num_nodes;
24*7faf4bd3SDavid Marchand /* global var for number of flows - extern in header */
25*7faf4bd3SDavid Marchand uint32_t num_flows = DEFAULT_NUM_FLOWS;
26*7faf4bd3SDavid Marchand
27*7faf4bd3SDavid Marchand static const char *progname;
28*7faf4bd3SDavid Marchand
29*7faf4bd3SDavid Marchand /**
30*7faf4bd3SDavid Marchand * Prints out usage information to stdout
31*7faf4bd3SDavid Marchand */
32*7faf4bd3SDavid Marchand static void
usage(void)33*7faf4bd3SDavid Marchand usage(void)
34*7faf4bd3SDavid Marchand {
35*7faf4bd3SDavid Marchand printf("%s [EAL options] -- -p PORTMASK -n NUM_NODES -f NUM_FLOWS\n"
36*7faf4bd3SDavid Marchand " -p PORTMASK: hexadecimal bitmask of ports to use\n"
37*7faf4bd3SDavid Marchand " -n NUM_NODES: number of node processes to use\n"
38*7faf4bd3SDavid Marchand " -f NUM_FLOWS: number of flows to be added in the EFD table\n",
39*7faf4bd3SDavid Marchand progname);
40*7faf4bd3SDavid Marchand }
41*7faf4bd3SDavid Marchand
42*7faf4bd3SDavid Marchand /**
43*7faf4bd3SDavid Marchand * The ports to be used by the application are passed in
44*7faf4bd3SDavid Marchand * the form of a bitmask. This function parses the bitmask
45*7faf4bd3SDavid Marchand * and places the port numbers to be used into the port[]
46*7faf4bd3SDavid Marchand * array variable
47*7faf4bd3SDavid Marchand */
48*7faf4bd3SDavid Marchand static int
parse_portmask(uint8_t max_ports,const char * portmask)49*7faf4bd3SDavid Marchand parse_portmask(uint8_t max_ports, const char *portmask)
50*7faf4bd3SDavid Marchand {
51*7faf4bd3SDavid Marchand char *end = NULL;
52*7faf4bd3SDavid Marchand unsigned long pm;
53*7faf4bd3SDavid Marchand uint8_t count = 0;
54*7faf4bd3SDavid Marchand
55*7faf4bd3SDavid Marchand if (portmask == NULL || *portmask == '\0')
56*7faf4bd3SDavid Marchand return -1;
57*7faf4bd3SDavid Marchand
58*7faf4bd3SDavid Marchand /* convert parameter to a number and verify */
59*7faf4bd3SDavid Marchand pm = strtoul(portmask, &end, 16);
60*7faf4bd3SDavid Marchand if (end == NULL || *end != '\0' || pm == 0)
61*7faf4bd3SDavid Marchand return -1;
62*7faf4bd3SDavid Marchand
63*7faf4bd3SDavid Marchand /* loop through bits of the mask and mark ports */
64*7faf4bd3SDavid Marchand while (pm != 0) {
65*7faf4bd3SDavid Marchand if (pm & 0x01) { /* bit is set in mask, use port */
66*7faf4bd3SDavid Marchand if (count >= max_ports)
67*7faf4bd3SDavid Marchand printf("WARNING: requested port %u not present"
68*7faf4bd3SDavid Marchand " - ignoring\n", (unsigned int)count);
69*7faf4bd3SDavid Marchand else
70*7faf4bd3SDavid Marchand info->id[info->num_ports++] = count;
71*7faf4bd3SDavid Marchand }
72*7faf4bd3SDavid Marchand pm = (pm >> 1);
73*7faf4bd3SDavid Marchand count++;
74*7faf4bd3SDavid Marchand }
75*7faf4bd3SDavid Marchand
76*7faf4bd3SDavid Marchand return 0;
77*7faf4bd3SDavid Marchand }
78*7faf4bd3SDavid Marchand
79*7faf4bd3SDavid Marchand /**
80*7faf4bd3SDavid Marchand * Take the number of nodes parameter passed to the app
81*7faf4bd3SDavid Marchand * and convert to a number to store in the num_nodes variable
82*7faf4bd3SDavid Marchand */
83*7faf4bd3SDavid Marchand static int
parse_num_nodes(const char * nodes)84*7faf4bd3SDavid Marchand parse_num_nodes(const char *nodes)
85*7faf4bd3SDavid Marchand {
86*7faf4bd3SDavid Marchand char *end = NULL;
87*7faf4bd3SDavid Marchand unsigned long temp;
88*7faf4bd3SDavid Marchand
89*7faf4bd3SDavid Marchand if (nodes == NULL || *nodes == '\0')
90*7faf4bd3SDavid Marchand return -1;
91*7faf4bd3SDavid Marchand
92*7faf4bd3SDavid Marchand temp = strtoul(nodes, &end, 10);
93*7faf4bd3SDavid Marchand if (end == NULL || *end != '\0' || temp == 0)
94*7faf4bd3SDavid Marchand return -1;
95*7faf4bd3SDavid Marchand
96*7faf4bd3SDavid Marchand num_nodes = (uint8_t)temp;
97*7faf4bd3SDavid Marchand return 0;
98*7faf4bd3SDavid Marchand }
99*7faf4bd3SDavid Marchand
100*7faf4bd3SDavid Marchand static int
parse_num_flows(const char * flows)101*7faf4bd3SDavid Marchand parse_num_flows(const char *flows)
102*7faf4bd3SDavid Marchand {
103*7faf4bd3SDavid Marchand char *end = NULL;
104*7faf4bd3SDavid Marchand
105*7faf4bd3SDavid Marchand /* parse hexadecimal string */
106*7faf4bd3SDavid Marchand num_flows = strtoul(flows, &end, 16);
107*7faf4bd3SDavid Marchand if ((flows[0] == '\0') || (end == NULL) || (*end != '\0'))
108*7faf4bd3SDavid Marchand return -1;
109*7faf4bd3SDavid Marchand
110*7faf4bd3SDavid Marchand if (num_flows == 0)
111*7faf4bd3SDavid Marchand return -1;
112*7faf4bd3SDavid Marchand
113*7faf4bd3SDavid Marchand return 0;
114*7faf4bd3SDavid Marchand }
115*7faf4bd3SDavid Marchand
116*7faf4bd3SDavid Marchand /**
117*7faf4bd3SDavid Marchand * The application specific arguments follow the DPDK-specific
118*7faf4bd3SDavid Marchand * arguments which are stripped by the DPDK init. This function
119*7faf4bd3SDavid Marchand * processes these application arguments, printing usage info
120*7faf4bd3SDavid Marchand * on error.
121*7faf4bd3SDavid Marchand */
122*7faf4bd3SDavid Marchand int
parse_app_args(uint8_t max_ports,int argc,char * argv[])123*7faf4bd3SDavid Marchand parse_app_args(uint8_t max_ports, int argc, char *argv[])
124*7faf4bd3SDavid Marchand {
125*7faf4bd3SDavid Marchand int option_index, opt;
126*7faf4bd3SDavid Marchand char **argvopt = argv;
127*7faf4bd3SDavid Marchand static struct option lgopts[] = { /* no long options */
128*7faf4bd3SDavid Marchand {NULL, 0, 0, 0 }
129*7faf4bd3SDavid Marchand };
130*7faf4bd3SDavid Marchand progname = argv[0];
131*7faf4bd3SDavid Marchand
132*7faf4bd3SDavid Marchand while ((opt = getopt_long(argc, argvopt, "n:f:p:", lgopts,
133*7faf4bd3SDavid Marchand &option_index)) != EOF) {
134*7faf4bd3SDavid Marchand switch (opt) {
135*7faf4bd3SDavid Marchand case 'p':
136*7faf4bd3SDavid Marchand if (parse_portmask(max_ports, optarg) != 0) {
137*7faf4bd3SDavid Marchand usage();
138*7faf4bd3SDavid Marchand return -1;
139*7faf4bd3SDavid Marchand }
140*7faf4bd3SDavid Marchand break;
141*7faf4bd3SDavid Marchand case 'n':
142*7faf4bd3SDavid Marchand if (parse_num_nodes(optarg) != 0) {
143*7faf4bd3SDavid Marchand usage();
144*7faf4bd3SDavid Marchand return -1;
145*7faf4bd3SDavid Marchand }
146*7faf4bd3SDavid Marchand break;
147*7faf4bd3SDavid Marchand case 'f':
148*7faf4bd3SDavid Marchand if (parse_num_flows(optarg) != 0) {
149*7faf4bd3SDavid Marchand usage();
150*7faf4bd3SDavid Marchand return -1;
151*7faf4bd3SDavid Marchand }
152*7faf4bd3SDavid Marchand break;
153*7faf4bd3SDavid Marchand default:
154*7faf4bd3SDavid Marchand printf("ERROR: Unknown option '%c'\n", opt);
155*7faf4bd3SDavid Marchand usage();
156*7faf4bd3SDavid Marchand return -1;
157*7faf4bd3SDavid Marchand }
158*7faf4bd3SDavid Marchand }
159*7faf4bd3SDavid Marchand
160*7faf4bd3SDavid Marchand if (info->num_ports == 0 || num_nodes == 0) {
161*7faf4bd3SDavid Marchand usage();
162*7faf4bd3SDavid Marchand return -1;
163*7faf4bd3SDavid Marchand }
164*7faf4bd3SDavid Marchand
165*7faf4bd3SDavid Marchand if (info->num_ports % 2 != 0) {
166*7faf4bd3SDavid Marchand printf("ERROR: application requires an even "
167*7faf4bd3SDavid Marchand "number of ports to use\n");
168*7faf4bd3SDavid Marchand return -1;
169*7faf4bd3SDavid Marchand }
170*7faf4bd3SDavid Marchand return 0;
171*7faf4bd3SDavid Marchand }
172