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