Line data Source code
1 : /*
2 : * dpdkinfo.c - CLI dpdkinfo to get info. about bond, lacp, mem etc.
3 : *
4 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
5 : * Copyright Contributors to the OpenSDN project
6 : */
7 :
8 : #include <stdio.h>
9 : #include <stdlib.h>
10 : #include <unistd.h>
11 : #include <string.h>
12 : #include <errno.h>
13 : #include <inttypes.h>
14 : #include <stdlib.h>
15 : #include <stdbool.h>
16 : #include <getopt.h>
17 :
18 : #include <sys/types.h>
19 : #include <sys/socket.h>
20 :
21 : #include <net/if.h>
22 :
23 : #include "ini_parser.h"
24 : #include "vr_os.h"
25 : #include "vr_types.h"
26 : #include "vr_nexthop.h"
27 : #include "ini_parser.h"
28 : #include "nl_util.h"
29 : #include "ini_parser.h"
30 : #include "vr_packet.h"
31 : #include "vr_interface.h"
32 :
33 : static struct nl_client *cl;
34 : static bool dump_pending = false;
35 : static int dump_marker = -1;
36 : /* For supporting multiple CLI clients, Message buffer table id is stored and
37 : * resend if dump_pending is true */
38 : /* Optional parameter: buffsz -> Send buffer size for the Output buffer(outbuf)
39 : * */
40 : static int buff_table_id, buffsz;
41 :
42 : static int help_set, ver_set, bond_set, lacp_set, mempool_set, stats_set,
43 : xstats_set, lcore_set, app_set, ddp_set, sock_dir_set, link_set;
44 : static unsigned int core = (unsigned)-1;
45 : static unsigned int stats_index = 0;
46 : /* For few CLI, Inbuf has to send to vrouter for processing(i.e kind of filter
47 : */
48 : static uint8_t *vr_info_inbuf;
49 :
50 : static vr_info_msg_en msginfo;
51 :
52 : enum opt_index {
53 : HELP_OPT_INDEX,
54 : VER_OPT_INDEX,
55 : BOND_OPT_INDEX,
56 : LACP_OPT_INDEX,
57 : MEMPOOL_OPT_INDEX,
58 : STATS_OPT_INDEX,
59 : XSTATS_OPT_INDEX,
60 : BUFFSZ_OPT_INDEX,
61 : LCORE_OPT_INDEX,
62 : APP_OPT_INDEX,
63 : DDP_OPT_INDEX,
64 : SOCK_DIR_OPT_INDEX,
65 : LINK_OPT_INDEX,
66 : MAX_OPT_INDEX,
67 : };
68 :
69 : static struct option long_options[] = {
70 : [HELP_OPT_INDEX] = {"help", no_argument, &help_set, 1},
71 : [VER_OPT_INDEX] = {"version", no_argument, &ver_set, 1},
72 : [BOND_OPT_INDEX] = {"bond", no_argument, &bond_set, 1},
73 : [LACP_OPT_INDEX] = {"lacp", required_argument, &lacp_set, 1},
74 : [MEMPOOL_OPT_INDEX] = {"mempool", required_argument, &mempool_set, 1},
75 : [STATS_OPT_INDEX] = {"stats", required_argument, &stats_set, 1},
76 : [XSTATS_OPT_INDEX] = {"xstats", optional_argument, &xstats_set, 1},
77 : [LCORE_OPT_INDEX] = {"lcore", no_argument, &lcore_set, 1},
78 : [APP_OPT_INDEX] = {"app", no_argument, &app_set, 1},
79 : [DDP_OPT_INDEX] = {"ddp", required_argument, &ddp_set, 1},
80 : [BUFFSZ_OPT_INDEX] = {"buffsz", required_argument, &buffsz, 1},
81 : [SOCK_DIR_OPT_INDEX] = {"sock-dir", required_argument, &sock_dir_set, 1},
82 : [LINK_OPT_INDEX] = {"link", required_argument, &link_set, 1},
83 : [MAX_OPT_INDEX] = {NULL, 0, 0, 0},
84 : };
85 :
86 : static void
87 0 : Usage()
88 : {
89 0 : printf("Usage: dpdkinfo [--help]\n");
90 0 : printf(" --version|-v\
91 : Show DPDK Version\n");
92 0 : printf(" --bond|-b\
93 : Show Master/Slave bond information\n");
94 0 : printf(" --lacp|-l <all/conf>\
95 : Show LACP information from DPDK\n");
96 0 : printf(" --mempool|-m <all/<mempool-name>>\
97 : Show Mempool information\n");
98 0 : printf(" --stats|-n <eth>\
99 : Show Stats information\n");
100 0 : printf(" --xstats|-x < =all/ =0(Master)/ =1(Slave(0))/ =2(Slave(1))>\
101 : Show Extended Stats information\n");
102 0 : printf(" --lcore|-c\
103 : Show Lcore information\n");
104 0 : printf(" --app|-a\
105 : Show App information\n");
106 0 : printf(" --ddp|-d <list>\
107 : Show DDP information for X710 NIC\n");
108 0 : printf(" Optional: --buffsz <value>\
109 : Send output buffer size (less than 1000Mb)\n");
110 0 : exit(-EINVAL);
111 : }
112 :
113 : static void
114 1 : validate_options(void)
115 : {
116 1 : if(!(ver_set || bond_set || lacp_set || mempool_set ||
117 0 : stats_set || xstats_set || lcore_set || app_set|| ddp_set || link_set))
118 0 : Usage();
119 :
120 1 : return;
121 : }
122 :
123 : /*
124 : * Response messages are sent through character buffer via Sandesh and it has
125 : * a limitation of sending upto 4K(PAGE_SIZE) for each iteration.
126 : * */
127 : static void
128 1 : dpdkinfo_resp_cb_process(void *s_req)
129 : {
130 1 : int ret = 0;
131 1 : vr_info_req *resp = (vr_info_req *)s_req;
132 1 : if(resp != NULL && resp->vdu_proc_info) {
133 : /* Print the Message buffer(character buffer)
134 : * sent by vRouter(Server) */
135 1 : printf("%s", resp->vdu_proc_info);
136 : }
137 :
138 : /* For Sandesh DUMP, we should update the marker id and buff_table_id for
139 : * the next interation. */
140 1 : if (resp->h_op == SANDESH_OP_DUMP) {
141 1 : dump_marker = resp->vdu_index;
142 1 : buff_table_id = resp->vdu_buff_table_id;
143 : }
144 1 : }
145 :
146 : static void
147 1 : response_process(void *s)
148 : {
149 1 : vr_response_common_process((vr_response *)s, &dump_pending);
150 1 : }
151 :
152 : static void
153 1 : dpdkinfo_fill_nl_callbacks()
154 : {
155 1 : nl_cb.vr_info_req_process = dpdkinfo_resp_cb_process;
156 1 : nl_cb.vr_response_process = response_process;
157 1 : }
158 :
159 : static void
160 2 : parse_long_opts(int opt_index, char *opt_arg)
161 : {
162 2 : errno = 0;
163 :
164 2 : switch (opt_index) {
165 0 : case VER_OPT_INDEX:
166 0 : msginfo = INFO_VER_DPDK;
167 0 : break;
168 :
169 0 : case BOND_OPT_INDEX:
170 0 : msginfo = INFO_BOND;
171 0 : break;
172 :
173 0 : case LACP_OPT_INDEX:
174 0 : msginfo = INFO_LACP;
175 0 : if (!strcmp(opt_arg, "all") || !strcmp(opt_arg, "conf")){
176 0 : vr_info_inbuf = opt_arg;
177 : } else {
178 0 : Usage();
179 : }
180 0 : break;
181 :
182 1 : case MEMPOOL_OPT_INDEX:
183 1 : msginfo = INFO_MEMPOOL;
184 1 : vr_info_inbuf = opt_arg;
185 1 : break;
186 :
187 0 : case STATS_OPT_INDEX:
188 0 : msginfo = INFO_STATS;
189 0 : if (strcmp(opt_arg,"eth") == 0){
190 0 : vr_info_inbuf = opt_arg;
191 : } else {
192 0 : Usage();
193 : }
194 0 : break;
195 :
196 0 : case XSTATS_OPT_INDEX:
197 0 : msginfo = INFO_XSTATS;
198 0 : if (!opt_arg){
199 0 : opt_arg = "";
200 : }
201 0 : if (!strcmp(opt_arg, "all") || !strcmp(opt_arg, "") ||
202 0 : !strcmp(opt_arg, "0") || ((atoi(opt_arg) > 0) &&
203 0 : (atoi(opt_arg) <= VR_INTERFACE_BOND_MAX_SLAVES))){
204 0 : vr_info_inbuf = opt_arg;
205 : } else {
206 0 : Usage();
207 : }
208 0 : break;
209 :
210 0 : case LCORE_OPT_INDEX:
211 0 : msginfo = INFO_LCORE;
212 0 : break;
213 :
214 0 : case APP_OPT_INDEX:
215 0 : msginfo = INFO_APP;
216 0 : break;
217 :
218 0 : case DDP_OPT_INDEX:
219 0 : msginfo = INFO_DDP;
220 0 : if (!strcmp(opt_arg, "list")){
221 0 : vr_info_inbuf = opt_arg;
222 : } else {
223 0 : Usage();
224 : }
225 0 : break;
226 :
227 1 : case SOCK_DIR_OPT_INDEX:
228 1 : vr_socket_dir = opt_arg;
229 1 : break;
230 :
231 0 : case BUFFSZ_OPT_INDEX:
232 : /* Setting buffsz limit to 1000Mb */
233 0 : if ((unsigned)strtol(opt_arg, NULL, 0) >= 0x3E800000){
234 0 : Usage();
235 : }
236 0 : buffsz = (unsigned)strtol(opt_arg, NULL, 0);
237 0 : break;
238 :
239 0 : case LINK_OPT_INDEX:
240 0 : msginfo = INFO_LINK;
241 0 : vr_info_inbuf = opt_arg;
242 0 : break;
243 :
244 0 : case HELP_OPT_INDEX:
245 : default:
246 0 : Usage();
247 : }
248 :
249 2 : return;
250 : }
251 :
252 : /* vr_get_dpdkinfo API send request to vRouter(server) and uses
253 : * h_op = DUMP for message request.
254 : * */
255 : static int
256 1 : vr_get_dpdkinfo(struct nl_client *cl)
257 : {
258 : int ret;
259 1 : bool dump = true;
260 :
261 1 : op_retry:
262 1 : ret = vr_send_info_dump(cl, 0, dump_marker, buff_table_id, msginfo, buffsz,
263 : vr_info_inbuf);
264 1 : if (ret < 0)
265 0 : return ret;
266 :
267 1 : ret = vr_recvmsg(cl, dump);
268 1 : if (ret <= 0)
269 0 : return ret;
270 :
271 : /* Will loop through till it reaches end of buffer */
272 1 : if (dump_pending)
273 0 : goto op_retry;
274 1 : return 0;
275 : }
276 :
277 : int
278 1 : main(int argc, char *argv[])
279 : {
280 : char opt;
281 1 : int ret, option_index, log_core = 0, i = 0;
282 1 : int platform = 0;
283 :
284 : /* Register callback function for Netlink message */
285 1 : dpdkinfo_fill_nl_callbacks();
286 :
287 1 : parse_ini_file();
288 :
289 3 : while (((opt = getopt_long(argc, argv, "-:hvbl:m:sn:p:d:cax::",
290 3 : long_options, &option_index)) >= 0)) {
291 2 : switch (opt) {
292 0 : case 'v':
293 0 : ver_set = 1;
294 0 : msginfo = INFO_VER_DPDK;
295 0 : break;
296 :
297 0 : case 'b':
298 0 : bond_set = 1;
299 0 : msginfo = INFO_BOND;
300 0 : break;
301 :
302 0 : case 'l':
303 0 : lacp_set = 1;
304 0 : msginfo = INFO_LACP;
305 0 : parse_long_opts(LACP_OPT_INDEX, optarg);
306 0 : break;
307 :
308 0 : case 'm':
309 0 : mempool_set = 1;
310 0 : msginfo = INFO_MEMPOOL;
311 0 : parse_long_opts(MEMPOOL_OPT_INDEX, optarg);
312 0 : break;
313 :
314 0 : case 'n':
315 0 : stats_set = 1;
316 0 : msginfo = INFO_STATS;
317 0 : parse_long_opts(STATS_OPT_INDEX, optarg);
318 0 : break;
319 :
320 0 : case 's':
321 0 : sock_dir_set = 1;
322 0 : parse_long_opts(SOCK_DIR_OPT_INDEX, optarg);
323 0 : break;
324 :
325 0 : case 'x':
326 0 : xstats_set = 1;
327 0 : msginfo = INFO_XSTATS;
328 0 : parse_long_opts(XSTATS_OPT_INDEX, optarg);
329 0 : break;
330 :
331 0 : case 'c':
332 0 : lcore_set = 1;
333 0 : msginfo = INFO_LCORE;
334 0 : break;
335 :
336 0 : case 'a':
337 0 : app_set = 1;
338 0 : msginfo = INFO_APP;
339 0 : break;
340 :
341 0 : case 'p':
342 0 : link_set = 1;
343 0 : msginfo = INFO_LINK;
344 0 : parse_long_opts(LINK_OPT_INDEX, optarg);
345 0 : break;
346 :
347 0 : case 'd':
348 0 : ddp_set = 1;
349 0 : msginfo = INFO_DDP;
350 0 : parse_long_opts(DDP_OPT_INDEX, optarg);
351 0 : break;
352 :
353 2 : case 0:
354 2 : parse_long_opts(option_index, optarg);
355 2 : break;
356 :
357 0 : case 'h':
358 : default:
359 0 : Usage();
360 : }
361 : }
362 1 : validate_options();
363 :
364 : /* Support for running from VTEST(vRouter UT Framework)*/
365 1 : if (sock_dir_set) {
366 1 : set_platform_vtest();
367 : }
368 1 : platform = get_platform();
369 1 : if ((platform != DPDK_PLATFORM) && (platform != VTEST_PLATFORM)) {
370 0 : Usage();
371 : }
372 :
373 1 : cl = vr_get_nl_client(VR_NETLINK_PROTO_DEFAULT);
374 1 : if (!cl)
375 0 : return -1;
376 :
377 1 : vr_get_dpdkinfo(cl);
378 :
379 1 : return 0;
380 : }
|