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