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