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