]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2016-2017 Intel Corporation | |
7c673cae FG |
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_string_fns.h> | |
14 | ||
15 | #include "common.h" | |
16 | #include "args.h" | |
17 | #include "init.h" | |
18 | ||
11fdf7f2 TL |
19 | /* 1M flows by default */ |
20 | #define DEFAULT_NUM_FLOWS 0x100000 | |
21 | ||
22 | /* global var for number of nodes - extern in header */ | |
23 | uint8_t num_nodes; | |
24 | /* global var for number of flows - extern in header */ | |
25 | uint32_t num_flows = DEFAULT_NUM_FLOWS; | |
7c673cae FG |
26 | |
27 | static const char *progname; | |
28 | ||
29 | /** | |
30 | * Prints out usage information to stdout | |
31 | */ | |
32 | static void | |
33 | usage(void) | |
34 | { | |
11fdf7f2 TL |
35 | printf("%s [EAL options] -- -p PORTMASK -n NUM_NODES -f NUM_FLOWS\n" |
36 | " -p PORTMASK: hexadecimal bitmask of ports to use\n" | |
37 | " -n NUM_NODES: number of node processes to use\n" | |
38 | " -f NUM_FLOWS: number of flows to be added in the EFD table\n", | |
39 | progname); | |
7c673cae FG |
40 | } |
41 | ||
42 | /** | |
43 | * The ports to be used by the application are passed in | |
44 | * the form of a bitmask. This function parses the bitmask | |
45 | * and places the port numbers to be used into the port[] | |
46 | * array variable | |
47 | */ | |
48 | static int | |
49 | parse_portmask(uint8_t max_ports, const char *portmask) | |
50 | { | |
51 | char *end = NULL; | |
52 | unsigned long pm; | |
53 | uint8_t count = 0; | |
54 | ||
55 | if (portmask == NULL || *portmask == '\0') | |
56 | return -1; | |
57 | ||
58 | /* convert parameter to a number and verify */ | |
59 | pm = strtoul(portmask, &end, 16); | |
60 | if (end == NULL || *end != '\0' || pm == 0) | |
61 | return -1; | |
62 | ||
63 | /* loop through bits of the mask and mark ports */ | |
11fdf7f2 TL |
64 | while (pm != 0) { |
65 | if (pm & 0x01) { /* bit is set in mask, use port */ | |
7c673cae FG |
66 | if (count >= max_ports) |
67 | printf("WARNING: requested port %u not present" | |
11fdf7f2 | 68 | " - ignoring\n", (unsigned int)count); |
7c673cae | 69 | else |
11fdf7f2 | 70 | info->id[info->num_ports++] = count; |
7c673cae FG |
71 | } |
72 | pm = (pm >> 1); | |
73 | count++; | |
74 | } | |
75 | ||
76 | return 0; | |
77 | } | |
78 | ||
79 | /** | |
11fdf7f2 TL |
80 | * Take the number of nodes parameter passed to the app |
81 | * and convert to a number to store in the num_nodes variable | |
7c673cae FG |
82 | */ |
83 | static int | |
11fdf7f2 | 84 | parse_num_nodes(const char *nodes) |
7c673cae FG |
85 | { |
86 | char *end = NULL; | |
87 | unsigned long temp; | |
88 | ||
11fdf7f2 | 89 | if (nodes == NULL || *nodes == '\0') |
7c673cae FG |
90 | return -1; |
91 | ||
11fdf7f2 | 92 | temp = strtoul(nodes, &end, 10); |
7c673cae FG |
93 | if (end == NULL || *end != '\0' || temp == 0) |
94 | return -1; | |
95 | ||
11fdf7f2 TL |
96 | num_nodes = (uint8_t)temp; |
97 | return 0; | |
98 | } | |
99 | ||
100 | static int | |
101 | parse_num_flows(const char *flows) | |
102 | { | |
103 | char *end = NULL; | |
104 | ||
105 | /* parse hexadecimal string */ | |
106 | num_flows = strtoul(flows, &end, 16); | |
107 | if ((flows[0] == '\0') || (end == NULL) || (*end != '\0')) | |
108 | return -1; | |
109 | ||
110 | if (num_flows == 0) | |
111 | return -1; | |
112 | ||
7c673cae FG |
113 | return 0; |
114 | } | |
115 | ||
116 | /** | |
117 | * The application specific arguments follow the DPDK-specific | |
118 | * arguments which are stripped by the DPDK init. This function | |
119 | * processes these application arguments, printing usage info | |
120 | * on error. | |
121 | */ | |
122 | int | |
123 | parse_app_args(uint8_t max_ports, int argc, char *argv[]) | |
124 | { | |
125 | int option_index, opt; | |
126 | char **argvopt = argv; | |
127 | static struct option lgopts[] = { /* no long options */ | |
128 | {NULL, 0, 0, 0 } | |
129 | }; | |
130 | progname = argv[0]; | |
131 | ||
11fdf7f2 TL |
132 | while ((opt = getopt_long(argc, argvopt, "n:f:p:", lgopts, |
133 | &option_index)) != EOF) { | |
134 | switch (opt) { | |
135 | case 'p': | |
136 | if (parse_portmask(max_ports, optarg) != 0) { | |
137 | usage(); | |
138 | return -1; | |
139 | } | |
140 | break; | |
141 | case 'n': | |
142 | if (parse_num_nodes(optarg) != 0) { | |
143 | usage(); | |
144 | return -1; | |
145 | } | |
146 | break; | |
147 | case 'f': | |
148 | if (parse_num_flows(optarg) != 0) { | |
7c673cae FG |
149 | usage(); |
150 | return -1; | |
11fdf7f2 TL |
151 | } |
152 | break; | |
153 | default: | |
154 | printf("ERROR: Unknown option '%c'\n", opt); | |
155 | usage(); | |
156 | return -1; | |
7c673cae FG |
157 | } |
158 | } | |
159 | ||
11fdf7f2 | 160 | if (info->num_ports == 0 || num_nodes == 0) { |
7c673cae FG |
161 | usage(); |
162 | return -1; | |
163 | } | |
164 | ||
11fdf7f2 TL |
165 | if (info->num_ports % 2 != 0) { |
166 | printf("ERROR: application requires an even " | |
167 | "number of ports to use\n"); | |
7c673cae FG |
168 | return -1; |
169 | } | |
170 | return 0; | |
171 | } |