xref: /dpdk/examples/multi_process/client_server_mp/mp_server/args.c (revision 1f41d98c207aee8982ced709864c96c463d4503a)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 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_ethdev.h>
14 #include <rte_string_fns.h>
15 
16 #include "common.h"
17 #include "args.h"
18 #include "init.h"
19 
20 /* global var for number of clients - extern in header */
21 uint8_t num_clients;
22 
23 static const char *progname;
24 
25 /**
26  * Prints out usage information to stdout
27  */
28 static void
usage(void)29 usage(void)
30 {
31 	printf(
32 	    "%s [EAL options] -- -p PORTMASK -n NUM_CLIENTS [-s NUM_SOCKETS]\n"
33 	    " -p PORTMASK: hexadecimal bitmask of ports to use\n"
34 	    " -n NUM_CLIENTS: number of client processes to use\n"
35 	    , progname);
36 }
37 
38 /**
39  * The ports to be used by the application are passed in
40  * the form of a bitmask. This function parses the bitmask
41  * and places the port numbers to be used into the port[]
42  * array variable
43  */
44 static int
parse_portmask(const char * portmask)45 parse_portmask(const char *portmask)
46 {
47 	char *end = NULL;
48 	unsigned long long pm;
49 	uint16_t id;
50 
51 	if (portmask == NULL || *portmask == '\0')
52 		return -1;
53 
54 	/* convert parameter to a number and verify */
55 	errno = 0;
56 	pm = strtoull(portmask, &end, 16);
57 	if (errno != 0 || end == NULL || *end != '\0')
58 		return -1;
59 
60 	RTE_ETH_FOREACH_DEV(id) {
61 		unsigned long msk = 1u << id;
62 
63 		if ((pm & msk) == 0)
64 			continue;
65 
66 		pm &= ~msk;
67 		ports->id[ports->num_ports++] = id;
68 	}
69 
70 	if (pm != 0) {
71 		printf("WARNING: leftover ports in mask %#llx - ignoring\n",
72 		       pm);
73 	}
74 
75 	return 0;
76 }
77 
78 /**
79  * Take the number of clients parameter passed to the app
80  * and convert to a number to store in the num_clients variable
81  */
82 static int
parse_num_clients(const char * clients)83 parse_num_clients(const char *clients)
84 {
85 	char *end = NULL;
86 	unsigned long temp;
87 
88 	if (clients == NULL || *clients == '\0')
89 		return -1;
90 
91 	temp = strtoul(clients, &end, 10);
92 	if (end == NULL || *end != '\0' || temp == 0)
93 		return -1;
94 
95 	num_clients = (uint8_t)temp;
96 	return 0;
97 }
98 
99 /**
100  * The application specific arguments follow the DPDK-specific
101  * arguments which are stripped by the DPDK init. This function
102  * processes these application arguments, printing usage info
103  * on error.
104  */
105 int
parse_app_args(int argc,char * argv[])106 parse_app_args(int argc, char *argv[])
107 {
108 	int option_index, opt;
109 	char **argvopt = argv;
110 	static struct option lgopts[] = { /* no long options */
111 		{NULL, 0, 0, 0 }
112 	};
113 	progname = argv[0];
114 
115 	while ((opt = getopt_long(argc, argvopt, "n:p:", lgopts,
116 		&option_index)) != EOF){
117 		switch (opt){
118 			case 'p':
119 				if (parse_portmask(optarg) != 0) {
120 					usage();
121 					return -1;
122 				}
123 				break;
124 			case 'n':
125 				if (parse_num_clients(optarg) != 0){
126 					usage();
127 					return -1;
128 				}
129 				break;
130 			default:
131 				printf("ERROR: Unknown option '%c'\n", opt);
132 				usage();
133 				return -1;
134 		}
135 	}
136 
137 	if (ports->num_ports == 0 || num_clients == 0){
138 		usage();
139 		return -1;
140 	}
141 
142 	if (ports->num_ports % 2 != 0){
143 		printf("ERROR: application requires an even number of ports to use\n");
144 		return -1;
145 	}
146 	return 0;
147 }
148