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