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