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