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