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