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