xref: /dpdk/examples/server_node_efd/efd_server/args.c (revision 7faf4bd32566446fa0815eef743523ce6a95a355)
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