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