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