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