xref: /dpdk/examples/ethtool/ethtool-app/ethapp.c (revision eb21185d)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <cmdline_parse.h>
35 #include <cmdline_parse_num.h>
36 #include <cmdline_parse_string.h>
37 #include <cmdline_parse_etheraddr.h>
38 #include <cmdline_socket.h>
39 #include <cmdline.h>
40 
41 #include "rte_ethtool.h"
42 #include "ethapp.h"
43 
44 #define EEPROM_DUMP_CHUNKSIZE 1024
45 
46 
47 struct pcmd_get_params {
48 	cmdline_fixed_string_t cmd;
49 };
50 struct pcmd_int_params {
51 	cmdline_fixed_string_t cmd;
52 	uint16_t port;
53 };
54 struct pcmd_intstr_params {
55 	cmdline_fixed_string_t cmd;
56 	uint16_t port;
57 	cmdline_fixed_string_t opt;
58 };
59 struct pcmd_intmac_params {
60 	cmdline_fixed_string_t cmd;
61 	uint16_t port;
62 	struct ether_addr mac;
63 };
64 struct pcmd_str_params {
65 	cmdline_fixed_string_t cmd;
66 	cmdline_fixed_string_t opt;
67 };
68 struct pcmd_vlan_params {
69 	cmdline_fixed_string_t cmd;
70 	uint16_t port;
71 	cmdline_fixed_string_t mode;
72 	uint16_t vid;
73 };
74 struct pcmd_intintint_params {
75 	cmdline_fixed_string_t cmd;
76 	uint16_t port;
77 	uint16_t tx;
78 	uint16_t rx;
79 };
80 
81 
82 /* Parameter-less commands */
83 cmdline_parse_token_string_t pcmd_quit_token_cmd =
84 	TOKEN_STRING_INITIALIZER(struct pcmd_get_params, cmd, "quit");
85 cmdline_parse_token_string_t pcmd_stats_token_cmd =
86 	TOKEN_STRING_INITIALIZER(struct pcmd_get_params, cmd, "stats");
87 cmdline_parse_token_string_t pcmd_drvinfo_token_cmd =
88 	TOKEN_STRING_INITIALIZER(struct pcmd_get_params, cmd, "drvinfo");
89 cmdline_parse_token_string_t pcmd_link_token_cmd =
90 	TOKEN_STRING_INITIALIZER(struct pcmd_get_params, cmd, "link");
91 
92 /* Commands taking just port id */
93 cmdline_parse_token_string_t pcmd_open_token_cmd =
94 	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "open");
95 cmdline_parse_token_string_t pcmd_stop_token_cmd =
96 	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "stop");
97 cmdline_parse_token_string_t pcmd_rxmode_token_cmd =
98 	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "rxmode");
99 cmdline_parse_token_string_t pcmd_portstats_token_cmd =
100 	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "portstats");
101 cmdline_parse_token_num_t pcmd_int_token_port =
102 	TOKEN_NUM_INITIALIZER(struct pcmd_int_params, port, UINT16);
103 
104 /* Commands taking port id and string */
105 cmdline_parse_token_string_t pcmd_eeprom_token_cmd =
106 	TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom");
107 cmdline_parse_token_string_t pcmd_mtu_token_cmd =
108 	TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu");
109 cmdline_parse_token_string_t pcmd_regs_token_cmd =
110 	TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "regs");
111 
112 cmdline_parse_token_num_t pcmd_intstr_token_port =
113 	TOKEN_NUM_INITIALIZER(struct pcmd_intstr_params, port, UINT16);
114 cmdline_parse_token_string_t pcmd_intstr_token_opt =
115 	TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, opt, NULL);
116 
117 /* Commands taking port id and a MAC address string */
118 cmdline_parse_token_string_t pcmd_macaddr_token_cmd =
119 	TOKEN_STRING_INITIALIZER(struct pcmd_intmac_params, cmd, "macaddr");
120 cmdline_parse_token_num_t pcmd_intmac_token_port =
121 	TOKEN_NUM_INITIALIZER(struct pcmd_intmac_params, port, UINT16);
122 cmdline_parse_token_etheraddr_t pcmd_intmac_token_mac =
123 	TOKEN_ETHERADDR_INITIALIZER(struct pcmd_intmac_params, mac);
124 
125 /* Command taking just a MAC address */
126 cmdline_parse_token_string_t pcmd_validate_token_cmd =
127 	TOKEN_STRING_INITIALIZER(struct pcmd_intmac_params, cmd, "validate");
128 
129 
130 /* Commands taking port id and two integers */
131 cmdline_parse_token_string_t pcmd_ringparam_token_cmd =
132 	TOKEN_STRING_INITIALIZER(struct pcmd_intintint_params, cmd,
133 		"ringparam");
134 cmdline_parse_token_num_t pcmd_intintint_token_port =
135 	TOKEN_NUM_INITIALIZER(struct pcmd_intintint_params, port, UINT16);
136 cmdline_parse_token_num_t pcmd_intintint_token_tx =
137 	TOKEN_NUM_INITIALIZER(struct pcmd_intintint_params, tx, UINT16);
138 cmdline_parse_token_num_t pcmd_intintint_token_rx =
139 	TOKEN_NUM_INITIALIZER(struct pcmd_intintint_params, rx, UINT16);
140 
141 
142 /* Pause commands */
143 cmdline_parse_token_string_t pcmd_pause_token_cmd =
144 	TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "pause");
145 cmdline_parse_token_num_t pcmd_pause_token_port =
146 	TOKEN_NUM_INITIALIZER(struct pcmd_intstr_params, port, UINT16);
147 cmdline_parse_token_string_t pcmd_pause_token_opt =
148 	TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params,
149 		opt, "all#tx#rx#none");
150 
151 /* VLAN commands */
152 cmdline_parse_token_string_t pcmd_vlan_token_cmd =
153 	TOKEN_STRING_INITIALIZER(struct pcmd_vlan_params, cmd, "vlan");
154 cmdline_parse_token_num_t pcmd_vlan_token_port =
155 	TOKEN_NUM_INITIALIZER(struct pcmd_vlan_params, port, UINT16);
156 cmdline_parse_token_string_t pcmd_vlan_token_mode =
157 	TOKEN_STRING_INITIALIZER(struct pcmd_vlan_params, mode, "add#del");
158 cmdline_parse_token_num_t pcmd_vlan_token_vid =
159 	TOKEN_NUM_INITIALIZER(struct pcmd_vlan_params, vid, UINT16);
160 
161 
162 static void
163 pcmd_quit_callback(__rte_unused void *ptr_params,
164 	struct cmdline *ctx,
165 	__rte_unused void *ptr_data)
166 {
167 	cmdline_quit(ctx);
168 }
169 
170 
171 static void
172 pcmd_drvinfo_callback(__rte_unused void *ptr_params,
173 	__rte_unused struct cmdline *ctx,
174 	__rte_unused void *ptr_data)
175 {
176 	struct ethtool_drvinfo info;
177 	int id_port;
178 
179 	for (id_port = 0; id_port < rte_eth_dev_count(); id_port++) {
180 		memset(&info, 0, sizeof(info));
181 		if (rte_ethtool_get_drvinfo(id_port, &info)) {
182 			printf("Error getting info for port %i\n", id_port);
183 			return;
184 		}
185 		printf("Port %i driver: %s (ver: %s)\n",
186 			id_port, info.driver, info.version
187 		      );
188 		printf("firmware-version: %s\n", info.fw_version);
189 	}
190 }
191 
192 
193 static void
194 pcmd_link_callback(__rte_unused void *ptr_params,
195 	__rte_unused struct cmdline *ctx,
196 	__rte_unused void *ptr_data)
197 {
198 	int num_ports = rte_eth_dev_count();
199 	int id_port, stat_port;
200 
201 	for (id_port = 0; id_port < num_ports; id_port++) {
202 		if (!rte_eth_dev_is_valid_port(id_port))
203 			continue;
204 		stat_port = rte_ethtool_get_link(id_port);
205 		switch (stat_port) {
206 		case 0:
207 			printf("Port %i: Down\n", id_port);
208 			break;
209 		case 1:
210 			printf("Port %i: Up\n", id_port);
211 			break;
212 		default:
213 			printf("Port %i: Error getting link status\n",
214 				id_port
215 				);
216 			break;
217 		}
218 	}
219 	printf("\n");
220 }
221 
222 
223 static void
224 pcmd_regs_callback(void *ptr_params,
225 	__rte_unused struct cmdline *ctx,
226 	__rte_unused void *ptr_data)
227 {
228 	struct pcmd_intstr_params *params = ptr_params;
229 	int len_regs;
230 	struct ethtool_regs regs;
231 	unsigned char *buf_data;
232 	FILE *fp_regs;
233 
234 	if (!rte_eth_dev_is_valid_port(params->port)) {
235 		printf("Error: Invalid port number %i\n", params->port);
236 		return;
237 	}
238 	len_regs = rte_ethtool_get_regs_len(params->port);
239 	if (len_regs > 0) {
240 		printf("Port %i: %i bytes\n", params->port, len_regs);
241 		buf_data = malloc(len_regs);
242 		if (buf_data == NULL) {
243 			printf("Error allocating %i bytes for buffer\n",
244 				len_regs);
245 			return;
246 		}
247 		if (!rte_ethtool_get_regs(params->port, &regs, buf_data)) {
248 			fp_regs = fopen(params->opt, "wb");
249 			if (fp_regs == NULL) {
250 				printf("Error opening '%s' for writing\n",
251 					params->opt);
252 			} else {
253 				if ((int)fwrite(buf_data,
254 						1, len_regs,
255 						fp_regs) != len_regs)
256 					printf("Error writing '%s'\n",
257 						params->opt);
258 				fclose(fp_regs);
259 			}
260 		}
261 		free(buf_data);
262 	} else if (len_regs == -ENOTSUP)
263 		printf("Port %i: Operation not supported\n", params->port);
264 	else
265 		printf("Port %i: Error getting registers\n", params->port);
266 }
267 
268 
269 static void
270 pcmd_eeprom_callback(void *ptr_params,
271 	__rte_unused struct cmdline *ctx,
272 	__rte_unused void *ptr_data)
273 {
274 	struct pcmd_intstr_params *params = ptr_params;
275 	struct ethtool_eeprom info_eeprom;
276 	int len_eeprom;
277 	int pos_eeprom;
278 	int stat;
279 	unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE];
280 	FILE *fp_eeprom;
281 
282 	if (!rte_eth_dev_is_valid_port(params->port)) {
283 		printf("Error: Invalid port number %i\n", params->port);
284 		return;
285 	}
286 	len_eeprom = rte_ethtool_get_eeprom_len(params->port);
287 	if (len_eeprom > 0) {
288 		fp_eeprom = fopen(params->opt, "wb");
289 		if (fp_eeprom == NULL) {
290 			printf("Error opening '%s' for writing\n",
291 				params->opt);
292 			return;
293 		}
294 		printf("Total EEPROM length: %i bytes\n", len_eeprom);
295 		info_eeprom.len = EEPROM_DUMP_CHUNKSIZE;
296 		for (pos_eeprom = 0;
297 				pos_eeprom < len_eeprom;
298 				pos_eeprom += EEPROM_DUMP_CHUNKSIZE) {
299 			info_eeprom.offset = pos_eeprom;
300 			if (pos_eeprom + EEPROM_DUMP_CHUNKSIZE > len_eeprom)
301 				info_eeprom.len = len_eeprom - pos_eeprom;
302 			else
303 				info_eeprom.len = EEPROM_DUMP_CHUNKSIZE;
304 			stat = rte_ethtool_get_eeprom(
305 				params->port, &info_eeprom, bytes_eeprom
306 				);
307 			if (stat != 0) {
308 				printf("EEPROM read error %i\n", stat);
309 				break;
310 			}
311 			if (fwrite(bytes_eeprom,
312 					1, info_eeprom.len,
313 					fp_eeprom) != info_eeprom.len) {
314 				printf("Error writing '%s'\n", params->opt);
315 				break;
316 			}
317 		}
318 		fclose(fp_eeprom);
319 	} else if (len_eeprom == 0)
320 		printf("Port %i: Device does not have EEPROM\n", params->port);
321 	else if (len_eeprom == -ENOTSUP)
322 		printf("Port %i: Operation not supported\n", params->port);
323 	else
324 		printf("Port %i: Error getting EEPROM\n", params->port);
325 }
326 
327 
328 static void
329 pcmd_pause_callback(void *ptr_params,
330 	__rte_unused struct cmdline *ctx,
331 	void *ptr_data)
332 {
333 	struct pcmd_intstr_params *params = ptr_params;
334 	struct ethtool_pauseparam info;
335 	int stat;
336 
337 	if (!rte_eth_dev_is_valid_port(params->port)) {
338 		printf("Error: Invalid port number %i\n", params->port);
339 		return;
340 	}
341 	if (ptr_data != NULL) {
342 		stat = rte_ethtool_get_pauseparam(params->port, &info);
343 	} else {
344 		memset(&info, 0, sizeof(info));
345 		if (strcasecmp("all", params->opt) == 0) {
346 			info.tx_pause = 1;
347 			info.rx_pause = 1;
348 		} else if (strcasecmp("tx", params->opt) == 0) {
349 			info.tx_pause = 1;
350 			info.rx_pause = 0;
351 		} else if (strcasecmp("rx", params->opt) == 0) {
352 			info.tx_pause = 0;
353 			info.rx_pause = 1;
354 		} else {
355 			info.tx_pause = 0;
356 			info.rx_pause = 0;
357 		}
358 		/* Assume auto-negotiation wanted */
359 		info.autoneg = 1;
360 		stat = rte_ethtool_set_pauseparam(params->port, &info);
361 	}
362 	if (stat == 0) {
363 		if (info.rx_pause && info.tx_pause)
364 			printf("Port %i: Tx & Rx Paused\n", params->port);
365 		else if (info.rx_pause)
366 			printf("Port %i: Rx Paused\n", params->port);
367 		else if (info.tx_pause)
368 			printf("Port %i: Tx Paused\n", params->port);
369 		else
370 			printf("Port %i: Tx & Rx not paused\n", params->port);
371 	} else if (stat == -ENOTSUP)
372 		printf("Port %i: Operation not supported\n", params->port);
373 	else
374 		printf("Port %i: Error %i\n", params->port, stat);
375 }
376 
377 
378 static void
379 pcmd_open_callback(__rte_unused void *ptr_params,
380 	__rte_unused struct cmdline *ctx,
381 	__rte_unused void *ptr_data)
382 {
383 	struct pcmd_int_params *params = ptr_params;
384 	int stat;
385 
386 	if (!rte_eth_dev_is_valid_port(params->port)) {
387 		printf("Error: Invalid port number %i\n", params->port);
388 		return;
389 	}
390 	lock_port(params->port);
391 	stat = rte_ethtool_net_open(params->port);
392 	mark_port_active(params->port);
393 	unlock_port(params->port);
394 	if (stat == 0)
395 		return;
396 	else if (stat == -ENOTSUP)
397 		printf("Port %i: Operation not supported\n", params->port);
398 	else
399 		printf("Port %i: Error opening device\n", params->port);
400 }
401 
402 static void
403 pcmd_stop_callback(__rte_unused void *ptr_params,
404 	__rte_unused struct cmdline *ctx,
405 	__rte_unused void *ptr_data)
406 {
407 	struct pcmd_int_params *params = ptr_params;
408 	int stat;
409 
410 	if (!rte_eth_dev_is_valid_port(params->port)) {
411 		printf("Error: Invalid port number %i\n", params->port);
412 		return;
413 	}
414 	lock_port(params->port);
415 	stat = rte_ethtool_net_stop(params->port);
416 	mark_port_inactive(params->port);
417 	unlock_port(params->port);
418 	if (stat == 0)
419 		return;
420 	else if (stat == -ENOTSUP)
421 		printf("Port %i: Operation not supported\n", params->port);
422 	else
423 		printf("Port %i: Error stopping device\n", params->port);
424 }
425 
426 
427 static void
428 pcmd_rxmode_callback(void *ptr_params,
429 	__rte_unused struct cmdline *ctx,
430 	__rte_unused void *ptr_data)
431 {
432 	struct pcmd_intstr_params *params = ptr_params;
433 	int stat;
434 
435 	if (!rte_eth_dev_is_valid_port(params->port)) {
436 		printf("Error: Invalid port number %i\n", params->port);
437 		return;
438 	}
439 	stat = rte_ethtool_net_set_rx_mode(params->port);
440 	if (stat == 0)
441 		return;
442 	else if (stat == -ENOTSUP)
443 		printf("Port %i: Operation not supported\n", params->port);
444 	else
445 		printf("Port %i: Error setting rx mode\n", params->port);
446 }
447 
448 
449 static void
450 pcmd_macaddr_callback(void *ptr_params,
451 	__rte_unused struct cmdline *ctx,
452 	void *ptr_data)
453 {
454 	struct pcmd_intmac_params *params = ptr_params;
455 	struct ether_addr mac_addr;
456 	int stat;
457 
458 	stat = 0;
459 	if (!rte_eth_dev_is_valid_port(params->port)) {
460 		printf("Error: Invalid port number %i\n", params->port);
461 		return;
462 	}
463 	if (ptr_data != NULL) {
464 		lock_port(params->port);
465 		stat = rte_ethtool_net_set_mac_addr(params->port,
466 			&params->mac);
467 		mark_port_newmac(params->port);
468 		unlock_port(params->port);
469 		if (stat == 0) {
470 			printf("MAC address changed\n");
471 			return;
472 		}
473 	} else {
474 		stat = rte_ethtool_net_get_mac_addr(params->port, &mac_addr);
475 		if (stat == 0) {
476 			printf(
477 				"Port %i MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
478 				params->port,
479 				mac_addr.addr_bytes[0],
480 				mac_addr.addr_bytes[1],
481 				mac_addr.addr_bytes[2],
482 				mac_addr.addr_bytes[3],
483 				mac_addr.addr_bytes[4],
484 				mac_addr.addr_bytes[5]);
485 			return;
486 		}
487 	}
488 
489 	printf("Port %i: Error %s\n", params->port,
490 	       strerror(-stat));
491 }
492 
493 static void
494 pcmd_mtu_callback(void *ptr_params,
495 	__rte_unused struct cmdline *ctx,
496 	__rte_unused void *ptr_data)
497 {
498 	struct pcmd_intstr_params *params = ptr_params;
499 	int stat;
500 	int new_mtu;
501 	char *ptr_parse_end;
502 
503 	if (!rte_eth_dev_is_valid_port(params->port)) {
504 		printf("Error: Invalid port number %i\n", params->port);
505 		return;
506 	}
507 	new_mtu = atoi(params->opt);
508 	new_mtu = strtoul(params->opt, &ptr_parse_end, 10);
509 	if (*ptr_parse_end != '\0' ||
510 			new_mtu < ETHER_MIN_MTU ||
511 			new_mtu > ETHER_MAX_JUMBO_FRAME_LEN) {
512 		printf("Port %i: Invalid MTU value\n", params->port);
513 		return;
514 	}
515 	stat = rte_ethtool_net_change_mtu(params->port, new_mtu);
516 	if (stat == 0)
517 		printf("Port %i: MTU set to %i\n", params->port, new_mtu);
518 	else if (stat == -ENOTSUP)
519 		printf("Port %i: Operation not supported\n", params->port);
520 	else
521 		printf("Port %i: Error setting MTU\n", params->port);
522 }
523 
524 
525 
526 static void pcmd_portstats_callback(__rte_unused void *ptr_params,
527 	__rte_unused struct cmdline *ctx,
528 	__rte_unused void *ptr_data)
529 {
530 	struct pcmd_int_params *params = ptr_params;
531 	struct rte_eth_stats stat_info;
532 	int stat;
533 
534 	if (!rte_eth_dev_is_valid_port(params->port)) {
535 		printf("Error: Invalid port number %i\n", params->port);
536 		return;
537 	}
538 	stat = rte_ethtool_net_get_stats64(params->port, &stat_info);
539 	if (stat == 0) {
540 		printf("Port %i stats\n", params->port);
541 		printf("   In: %" PRIu64 " (%" PRIu64 " bytes)\n"
542 			"  Out: %"PRIu64" (%"PRIu64 " bytes)\n"
543 			"  Err: %"PRIu64"\n",
544 			stat_info.ipackets,
545 			stat_info.ibytes,
546 			stat_info.opackets,
547 			stat_info.obytes,
548 			stat_info.ierrors+stat_info.oerrors
549 		      );
550 	} else if (stat == -ENOTSUP)
551 		printf("Port %i: Operation not supported\n", params->port);
552 	else
553 		printf("Port %i: Error fetching statistics\n", params->port);
554 }
555 
556 static void pcmd_ringparam_callback(__rte_unused void *ptr_params,
557 	__rte_unused struct cmdline *ctx,
558 	void *ptr_data)
559 {
560 	struct pcmd_intintint_params *params = ptr_params;
561 	struct ethtool_ringparam ring_data;
562 	struct ethtool_ringparam ring_params;
563 	int stat;
564 
565 	if (!rte_eth_dev_is_valid_port(params->port)) {
566 		printf("Error: Invalid port number %i\n", params->port);
567 		return;
568 	}
569 	if (ptr_data == NULL) {
570 		stat = rte_ethtool_get_ringparam(params->port, &ring_data);
571 		if (stat == 0) {
572 			printf("Port %i ring parameters\n"
573 				"  Rx Pending: %i (%i max)\n"
574 				"  Tx Pending: %i (%i max)\n",
575 				params->port,
576 				ring_data.rx_pending,
577 				ring_data.rx_max_pending,
578 				ring_data.tx_pending,
579 				ring_data.tx_max_pending);
580 		}
581 	} else {
582 		if (params->tx < 1 || params->rx < 1) {
583 			printf("Error: Invalid parameters\n");
584 			return;
585 		}
586 		memset(&ring_params, 0, sizeof(struct ethtool_ringparam));
587 		ring_params.tx_pending = params->tx;
588 		ring_params.rx_pending = params->rx;
589 		lock_port(params->port);
590 		stat = rte_ethtool_set_ringparam(params->port, &ring_params);
591 		unlock_port(params->port);
592 	}
593 	if (stat == 0)
594 		return;
595 	else if (stat == -ENOTSUP)
596 		printf("Port %i: Operation not supported\n", params->port);
597 	else
598 		printf("Port %i: Error fetching statistics\n", params->port);
599 }
600 
601 static void pcmd_validate_callback(void *ptr_params,
602 	__rte_unused struct cmdline *ctx,
603 	__rte_unused void *ptr_data)
604 {
605 	struct pcmd_intmac_params *params = ptr_params;
606 
607 	if (rte_ethtool_net_validate_addr(0, &params->mac))
608 		printf("Address is unicast\n");
609 	else
610 		printf("Address is not unicast\n");
611 }
612 
613 
614 static void pcmd_vlan_callback(__rte_unused void *ptr_params,
615 	__rte_unused struct cmdline *ctx,
616 	__rte_unused void *ptr_data)
617 {
618 	struct pcmd_vlan_params *params = ptr_params;
619 	int stat;
620 
621 	if (!rte_eth_dev_is_valid_port(params->port)) {
622 		printf("Error: Invalid port number %i\n", params->port);
623 		return;
624 	}
625 	stat = 0;
626 
627 	if (strcasecmp("add", params->mode) == 0) {
628 		stat = rte_ethtool_net_vlan_rx_add_vid(
629 			params->port, params->vid
630 			);
631 		if (stat == 0)
632 			printf("VLAN vid %i added\n", params->vid);
633 
634 	} else if (strcasecmp("del", params->mode) == 0) {
635 		stat = rte_ethtool_net_vlan_rx_kill_vid(
636 			params->port, params->vid
637 			);
638 		if (stat == 0)
639 			printf("VLAN vid %i removed\n", params->vid);
640 	} else {
641 		/* Should not happen! */
642 		printf("Error: Bad mode %s\n", params->mode);
643 	}
644 	if (stat == -ENOTSUP)
645 		printf("Port %i: Operation not supported\n", params->port);
646 	else if (stat == -ENOSYS)
647 		printf("Port %i: VLAN filtering disabled\n", params->port);
648 	else if (stat != 0)
649 		printf("Port %i: Error changing VLAN setup (code %i)\n",
650 			params->port, -stat);
651 }
652 
653 
654 cmdline_parse_inst_t pcmd_quit = {
655 	.f = pcmd_quit_callback,
656 	.data = NULL,
657 	.help_str = "quit\n     Exit program",
658 	.tokens = {(void *)&pcmd_quit_token_cmd, NULL},
659 };
660 cmdline_parse_inst_t pcmd_drvinfo = {
661 	.f = pcmd_drvinfo_callback,
662 	.data = NULL,
663 	.help_str = "drvinfo\n     Print driver info",
664 	.tokens = {(void *)&pcmd_drvinfo_token_cmd, NULL},
665 };
666 cmdline_parse_inst_t pcmd_link = {
667 	.f = pcmd_link_callback,
668 	.data = NULL,
669 	.help_str = "link\n     Print port link states",
670 	.tokens = {(void *)&pcmd_link_token_cmd, NULL},
671 };
672 cmdline_parse_inst_t pcmd_regs = {
673 	.f = pcmd_regs_callback,
674 	.data = NULL,
675 	.help_str = "regs <port_id> <filename>\n"
676 		"     Dump port register(s) to file",
677 	.tokens = {
678 		(void *)&pcmd_regs_token_cmd,
679 		(void *)&pcmd_intstr_token_port,
680 		(void *)&pcmd_intstr_token_opt,
681 		NULL
682 	},
683 };
684 cmdline_parse_inst_t pcmd_eeprom = {
685 	.f = pcmd_eeprom_callback,
686 	.data = NULL,
687 	.help_str = "eeprom <port_id> <filename>\n    Dump EEPROM to file",
688 	.tokens = {
689 		(void *)&pcmd_eeprom_token_cmd,
690 		(void *)&pcmd_intstr_token_port,
691 		(void *)&pcmd_intstr_token_opt,
692 		NULL
693 	},
694 };
695 cmdline_parse_inst_t pcmd_pause_noopt = {
696 	.f = pcmd_pause_callback,
697 	.data = (void *)0x01,
698 	.help_str = "pause <port_id>\n     Print port pause state",
699 	.tokens = {
700 		(void *)&pcmd_pause_token_cmd,
701 		(void *)&pcmd_pause_token_port,
702 		NULL
703 	},
704 };
705 cmdline_parse_inst_t pcmd_pause = {
706 	.f = pcmd_pause_callback,
707 	.data = NULL,
708 	.help_str =
709 		"pause <port_id> <all|tx|rx|none>\n     Pause/unpause port",
710 	.tokens = {
711 		(void *)&pcmd_pause_token_cmd,
712 		(void *)&pcmd_pause_token_port,
713 		(void *)&pcmd_pause_token_opt,
714 		NULL
715 	},
716 };
717 cmdline_parse_inst_t pcmd_open = {
718 	.f = pcmd_open_callback,
719 	.data = NULL,
720 	.help_str = "open <port_id>\n     Open port",
721 	.tokens = {
722 		(void *)&pcmd_open_token_cmd,
723 		(void *)&pcmd_int_token_port,
724 		NULL
725 	},
726 };
727 cmdline_parse_inst_t pcmd_stop = {
728 	.f = pcmd_stop_callback,
729 	.data = NULL,
730 	.help_str = "stop <port_id>\n     Stop port",
731 	.tokens = {
732 		(void *)&pcmd_stop_token_cmd,
733 		(void *)&pcmd_int_token_port,
734 		NULL
735 	},
736 };
737 cmdline_parse_inst_t pcmd_rxmode = {
738 	.f = pcmd_rxmode_callback,
739 	.data = NULL,
740 	.help_str = "rxmode <port_id>\n     Toggle port Rx mode",
741 	.tokens = {
742 		(void *)&pcmd_rxmode_token_cmd,
743 		(void *)&pcmd_int_token_port,
744 		NULL
745 	},
746 };
747 cmdline_parse_inst_t pcmd_macaddr_get = {
748 	.f = pcmd_macaddr_callback,
749 	.data = NULL,
750 	.help_str = "macaddr <port_id>\n"
751 		"     Get MAC address",
752 	.tokens = {
753 		(void *)&pcmd_macaddr_token_cmd,
754 		(void *)&pcmd_intstr_token_port,
755 		NULL
756 	},
757 };
758 cmdline_parse_inst_t pcmd_macaddr = {
759 	.f = pcmd_macaddr_callback,
760 	.data = (void *)0x01,
761 	.help_str =
762 		"macaddr <port_id> <mac_addr>\n"
763 		"     Set MAC address",
764 	.tokens = {
765 		(void *)&pcmd_macaddr_token_cmd,
766 		(void *)&pcmd_intmac_token_port,
767 		(void *)&pcmd_intmac_token_mac,
768 		NULL
769 	},
770 };
771 cmdline_parse_inst_t pcmd_mtu = {
772 	.f = pcmd_mtu_callback,
773 	.data = NULL,
774 	.help_str = "mtu <port_id> <mtu_value>\n"
775 		"     Change MTU",
776 	.tokens = {
777 		(void *)&pcmd_mtu_token_cmd,
778 		(void *)&pcmd_intstr_token_port,
779 		(void *)&pcmd_intstr_token_opt,
780 		NULL
781 	},
782 };
783 cmdline_parse_inst_t pcmd_portstats = {
784 	.f = pcmd_portstats_callback,
785 	.data = NULL,
786 	.help_str = "portstats <port_id>\n"
787 		"     Print port eth statistics",
788 	.tokens = {
789 		(void *)&pcmd_portstats_token_cmd,
790 		(void *)&pcmd_int_token_port,
791 		NULL
792 	},
793 };
794 cmdline_parse_inst_t pcmd_ringparam = {
795 	.f = pcmd_ringparam_callback,
796 	.data = NULL,
797 	.help_str = "ringparam <port_id>\n"
798 		"     Print ring parameters",
799 	.tokens = {
800 		(void *)&pcmd_ringparam_token_cmd,
801 		(void *)&pcmd_intintint_token_port,
802 		NULL
803 	},
804 };
805 cmdline_parse_inst_t pcmd_ringparam_set = {
806 	.f = pcmd_ringparam_callback,
807 	.data = (void *)1,
808 	.help_str = "ringparam <port_id> <tx_param> <rx_param>\n"
809 		"     Set ring parameters",
810 	.tokens = {
811 		(void *)&pcmd_ringparam_token_cmd,
812 		(void *)&pcmd_intintint_token_port,
813 		(void *)&pcmd_intintint_token_tx,
814 		(void *)&pcmd_intintint_token_rx,
815 		NULL
816 	},
817 };
818 cmdline_parse_inst_t pcmd_validate = {
819 	.f = pcmd_validate_callback,
820 	.data = NULL,
821 	.help_str = "validate <mac_addr>\n"
822 		"     Check that MAC address is valid unicast address",
823 	.tokens = {
824 		(void *)&pcmd_validate_token_cmd,
825 		(void *)&pcmd_intmac_token_mac,
826 		NULL
827 	},
828 };
829 cmdline_parse_inst_t pcmd_vlan = {
830 	.f = pcmd_vlan_callback,
831 	.data = NULL,
832 	.help_str = "vlan <port_id> <add|del> <vlan_id>\n"
833 		"     Add/remove VLAN id",
834 	.tokens = {
835 		(void *)&pcmd_vlan_token_cmd,
836 		(void *)&pcmd_vlan_token_port,
837 		(void *)&pcmd_vlan_token_mode,
838 		(void *)&pcmd_vlan_token_vid,
839 		NULL
840 	},
841 };
842 
843 
844 cmdline_parse_ctx_t list_prompt_commands[] = {
845 	(cmdline_parse_inst_t *)&pcmd_drvinfo,
846 	(cmdline_parse_inst_t *)&pcmd_eeprom,
847 	(cmdline_parse_inst_t *)&pcmd_link,
848 	(cmdline_parse_inst_t *)&pcmd_macaddr_get,
849 	(cmdline_parse_inst_t *)&pcmd_macaddr,
850 	(cmdline_parse_inst_t *)&pcmd_mtu,
851 	(cmdline_parse_inst_t *)&pcmd_open,
852 	(cmdline_parse_inst_t *)&pcmd_pause_noopt,
853 	(cmdline_parse_inst_t *)&pcmd_pause,
854 	(cmdline_parse_inst_t *)&pcmd_portstats,
855 	(cmdline_parse_inst_t *)&pcmd_regs,
856 	(cmdline_parse_inst_t *)&pcmd_ringparam,
857 	(cmdline_parse_inst_t *)&pcmd_ringparam_set,
858 	(cmdline_parse_inst_t *)&pcmd_rxmode,
859 	(cmdline_parse_inst_t *)&pcmd_stop,
860 	(cmdline_parse_inst_t *)&pcmd_validate,
861 	(cmdline_parse_inst_t *)&pcmd_vlan,
862 	(cmdline_parse_inst_t *)&pcmd_quit,
863 	NULL
864 };
865 
866 
867 void ethapp_main(void)
868 {
869 	struct cmdline *ctx_cmdline;
870 
871 	ctx_cmdline = cmdline_stdin_new(list_prompt_commands, "EthApp> ");
872 	cmdline_interact(ctx_cmdline);
873 	cmdline_stdin_exit(ctx_cmdline);
874 }
875