odp-util: New function odp_actions_from_string().
[sliver-openvswitch.git] / utilities / ovs-dpctl.c
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18 #include <arpa/inet.h>
19 #include <errno.h>
20 #include <getopt.h>
21 #include <inttypes.h>
22 #include <sys/socket.h>
23 #include <net/if.h>
24 #include <netinet/in.h>
25 #include <signal.h>
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <sys/time.h>
32
33 #include "command-line.h"
34 #include "compiler.h"
35 #include "dirs.h"
36 #include "dpif.h"
37 #include "dynamic-string.h"
38 #include "netdev.h"
39 #include "odp-util.h"
40 #include "ofpbuf.h"
41 #include "shash.h"
42 #include "sset.h"
43 #include "timeval.h"
44 #include "util.h"
45 #include "vlog.h"
46
47 VLOG_DEFINE_THIS_MODULE(dpctl);
48
49 /* -s, --statistics: Print port statistics? */
50 static bool print_statistics;
51
52 static const struct command all_commands[];
53
54 static void usage(void) NO_RETURN;
55 static void parse_options(int argc, char *argv[]);
56
57 int
58 main(int argc, char *argv[])
59 {
60     set_program_name(argv[0]);
61     parse_options(argc, argv);
62     signal(SIGPIPE, SIG_IGN);
63     run_command(argc - optind, argv + optind, all_commands);
64     return 0;
65 }
66
67 static void
68 parse_options(int argc, char *argv[])
69 {
70     enum {
71         OPT_DUMMY = UCHAR_MAX + 1,
72         VLOG_OPTION_ENUMS
73     };
74     static struct option long_options[] = {
75         {"statistics", no_argument, NULL, 's'},
76         {"timeout", required_argument, NULL, 't'},
77         {"help", no_argument, NULL, 'h'},
78         {"version", no_argument, NULL, 'V'},
79         VLOG_LONG_OPTIONS,
80         {NULL, 0, NULL, 0},
81     };
82     char *short_options = long_options_to_short_options(long_options);
83
84     for (;;) {
85         unsigned long int timeout;
86         int c;
87
88         c = getopt_long(argc, argv, short_options, long_options, NULL);
89         if (c == -1) {
90             break;
91         }
92
93         switch (c) {
94         case 's':
95             print_statistics = true;
96             break;
97
98         case 't':
99             timeout = strtoul(optarg, NULL, 10);
100             if (timeout <= 0) {
101                 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
102                           optarg);
103             } else {
104                 time_alarm(timeout);
105             }
106             break;
107
108         case 'h':
109             usage();
110
111         case 'V':
112             ovs_print_version(0, 0);
113             exit(EXIT_SUCCESS);
114
115         VLOG_OPTION_HANDLERS
116
117         case '?':
118             exit(EXIT_FAILURE);
119
120         default:
121             abort();
122         }
123     }
124     free(short_options);
125 }
126
127 static void
128 usage(void)
129 {
130     printf("%s: Open vSwitch datapath management utility\n"
131            "usage: %s [OPTIONS] COMMAND [ARG...]\n"
132            "  add-dp DP [IFACE...]     add new datapath DP (with IFACEs)\n"
133            "  del-dp DP                delete local datapath DP\n"
134            "  add-if DP IFACE...       add each IFACE as a port on DP\n"
135            "  set-if DP IFACE...       reconfigure each IFACE within DP\n"
136            "  del-if DP IFACE...       delete each IFACE from DP\n"
137            "  dump-dps                 display names of all datapaths\n"
138            "  show                     show basic info on all datapaths\n"
139            "  show DP...               show basic info on each DP\n"
140            "  dump-flows DP            display flows in DP\n"
141            "  del-flows DP             delete all flows from DP\n"
142            "Each IFACE on add-dp, add-if, and set-if may be followed by\n"
143            "comma-separated options.  See ovs-dpctl(8) for syntax, or the\n"
144            "Interface table in ovs-vswitchd.conf.db(5) for an options list.\n",
145            program_name, program_name);
146     vlog_usage();
147     printf("\nOther options:\n"
148            "  -t, --timeout=SECS          give up after SECS seconds\n"
149            "  -h, --help                  display this help message\n"
150            "  -V, --version               display version information\n");
151     exit(EXIT_SUCCESS);
152 }
153
154 static void run(int retval, const char *message, ...)
155     PRINTF_FORMAT(2, 3);
156
157 static void run(int retval, const char *message, ...)
158 {
159     if (retval) {
160         va_list args;
161
162         va_start(args, message);
163         ovs_fatal_valist(retval, message, args);
164     }
165 }
166 \f
167 static void do_add_if(int argc, char *argv[]);
168
169 static int if_up(const char *netdev_name)
170 {
171     struct netdev *netdev;
172     int retval;
173
174     retval = netdev_open(netdev_name, "system", &netdev);
175     if (!retval) {
176         retval = netdev_turn_flags_on(netdev, NETDEV_UP, true);
177         netdev_close(netdev);
178     }
179     return retval;
180 }
181
182 static int
183 parsed_dpif_open(const char *arg_, bool create, struct dpif **dpifp)
184 {
185     int result;
186     char *name, *type;
187
188     dp_parse_name(arg_, &name, &type);
189
190     if (create) {
191         result = dpif_create(name, type, dpifp);
192     } else {
193         result = dpif_open(name, type, dpifp);
194     }
195
196     free(name);
197     free(type);
198     return result;
199 }
200
201 static void
202 do_add_dp(int argc OVS_UNUSED, char *argv[])
203 {
204     struct dpif *dpif;
205     run(parsed_dpif_open(argv[1], true, &dpif), "add_dp");
206     dpif_close(dpif);
207     if (argc > 2) {
208         do_add_if(argc, argv);
209     }
210 }
211
212 static void
213 do_del_dp(int argc OVS_UNUSED, char *argv[])
214 {
215     struct dpif *dpif;
216     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
217     run(dpif_delete(dpif), "del_dp");
218     dpif_close(dpif);
219 }
220
221 static void
222 do_add_if(int argc OVS_UNUSED, char *argv[])
223 {
224     bool failure = false;
225     struct dpif *dpif;
226     int i;
227
228     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
229     for (i = 2; i < argc; i++) {
230         const char *name, *type;
231         char *save_ptr = NULL;
232         struct netdev *netdev = NULL;
233         struct shash args;
234         char *option;
235         int error;
236
237         name = strtok_r(argv[i], ",", &save_ptr);
238         type = "system";
239
240         if (!name) {
241             ovs_error(0, "%s is not a valid network device name", argv[i]);
242             failure = true;
243             continue;
244         }
245
246         shash_init(&args);
247         while ((option = strtok_r(NULL, ",", &save_ptr)) != NULL) {
248             char *save_ptr_2 = NULL;
249             char *key, *value;
250
251             key = strtok_r(option, "=", &save_ptr_2);
252             value = strtok_r(NULL, "", &save_ptr_2);
253             if (!value) {
254                 value = "";
255             }
256
257             if (!strcmp(key, "type")) {
258                 type = value;
259             } else if (!shash_add_once(&args, key, value)) {
260                 ovs_error(0, "duplicate \"%s\" option", key);
261             }
262         }
263
264         error = netdev_open(name, type, &netdev);
265         if (error) {
266             ovs_error(error, "%s: failed to open network device", name);
267             goto next;
268         }
269
270         error = netdev_set_config(netdev, &args);
271         if (error) {
272             ovs_error(error, "%s: failed to configure network device", name);
273             goto next;
274         }
275
276         error = dpif_port_add(dpif, netdev, NULL);
277         if (error) {
278             ovs_error(error, "adding %s to %s failed", name, argv[1]);
279             goto next;
280         }
281
282         error = if_up(name);
283
284 next:
285         netdev_close(netdev);
286         if (error) {
287             failure = true;
288         }
289     }
290     dpif_close(dpif);
291     if (failure) {
292         exit(EXIT_FAILURE);
293     }
294 }
295
296 static void
297 do_set_if(int argc, char *argv[])
298 {
299     bool failure = false;
300     struct dpif *dpif;
301     int i;
302
303     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
304     for (i = 2; i < argc; i++) {
305         struct netdev *netdev = NULL;
306         struct dpif_port dpif_port;
307         char *save_ptr = NULL;
308         char *type = NULL;
309         const char *name;
310         struct shash args;
311         char *option;
312         int error;
313
314         name = strtok_r(argv[i], ",", &save_ptr);
315         if (!name) {
316             ovs_error(0, "%s is not a valid network device name", argv[i]);
317             failure = true;
318             continue;
319         }
320
321         /* Get the port's type from the datapath. */
322         error = dpif_port_query_by_name(dpif, name, &dpif_port);
323         if (error) {
324             ovs_error(error, "%s: failed to query port in %s", name, argv[1]);
325             goto next;
326         }
327         type = xstrdup(dpif_port.type);
328         dpif_port_destroy(&dpif_port);
329
330         /* Retrieve its existing configuration. */
331         error = netdev_open(name, type, &netdev);
332         if (error) {
333             ovs_error(error, "%s: failed to open network device", name);
334             goto next;
335         }
336
337         shash_init(&args);
338         error = netdev_get_config(netdev, &args);
339         if (error) {
340             ovs_error(error, "%s: failed to fetch configuration", name);
341             goto next;
342         }
343
344         /* Parse changes to configuration. */
345         while ((option = strtok_r(NULL, ",", &save_ptr)) != NULL) {
346             char *save_ptr_2 = NULL;
347             char *key, *value;
348
349             key = strtok_r(option, "=", &save_ptr_2);
350             value = strtok_r(NULL, "", &save_ptr_2);
351             if (!value) {
352                 value = "";
353             }
354
355             if (!strcmp(key, "type")) {
356                 if (strcmp(value, type)) {
357                     ovs_error(0, "%s: can't change type from %s to %s",
358                               name, type, value);
359                     failure = true;
360                 }
361             } else if (value[0] == '\0') {
362                 free(shash_find_and_delete(&args, key));
363             } else {
364                 free(shash_replace(&args, key, xstrdup(value)));
365             }
366         }
367
368         /* Update configuration. */
369         error = netdev_set_config(netdev, &args);
370         smap_destroy(&args);
371         if (error) {
372             ovs_error(error, "%s: failed to configure network device", name);
373             goto next;
374         }
375
376 next:
377         free(type);
378         netdev_close(netdev);
379         if (error) {
380             failure = true;
381         }
382     }
383     dpif_close(dpif);
384     if (failure) {
385         exit(EXIT_FAILURE);
386     }
387 }
388
389 static bool
390 get_port_number(struct dpif *dpif, const char *name, uint16_t *port)
391 {
392     struct dpif_port dpif_port;
393
394     if (!dpif_port_query_by_name(dpif, name, &dpif_port)) {
395         *port = dpif_port.port_no;
396         dpif_port_destroy(&dpif_port);
397         return true;
398     } else {
399         ovs_error(0, "no port named %s", name);
400         return false;
401     }
402 }
403
404 static void
405 do_del_if(int argc OVS_UNUSED, char *argv[])
406 {
407     bool failure = false;
408     struct dpif *dpif;
409     int i;
410
411     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
412     for (i = 2; i < argc; i++) {
413         const char *name = argv[i];
414         uint16_t port;
415         int error;
416
417         if (!name[strspn(name, "0123456789")]) {
418             port = atoi(name);
419         } else if (!get_port_number(dpif, name, &port)) {
420             failure = true;
421             continue;
422         }
423
424         error = dpif_port_del(dpif, port);
425         if (error) {
426             ovs_error(error, "deleting port %s from %s failed", name, argv[1]);
427             failure = true;
428         }
429     }
430     dpif_close(dpif);
431     if (failure) {
432         exit(EXIT_FAILURE);
433     }
434 }
435
436 static void
437 print_stat(const char *leader, uint64_t value)
438 {
439     fputs(leader, stdout);
440     if (value != UINT64_MAX) {
441         printf("%"PRIu64, value);
442     } else {
443         putchar('?');
444     }
445 }
446
447 static void
448 print_human_size(uint64_t value)
449 {
450     if (value == UINT64_MAX) {
451         /* Nothing to do. */
452     } else if (value >= 1024ULL * 1024 * 1024 * 1024) {
453         printf(" (%.1f TiB)", value / (1024.0 * 1024 * 1024 * 1024));
454     } else if (value >= 1024ULL * 1024 * 1024) {
455         printf(" (%.1f GiB)", value / (1024.0 * 1024 * 1024));
456     } else if (value >= 1024ULL * 1024) {
457         printf(" (%.1f MiB)", value / (1024.0 * 1024));
458     } else if (value >= 1024) {
459         printf(" (%.1f KiB)", value / 1024.0);
460     }
461 }
462
463 static void
464 show_dpif(struct dpif *dpif)
465 {
466     struct dpif_port_dump dump;
467     struct dpif_port dpif_port;
468     struct dpif_dp_stats stats;
469     struct netdev *netdev;
470
471     printf("%s:\n", dpif_name(dpif));
472     if (!dpif_get_dp_stats(dpif, &stats)) {
473         printf("\tlookups: hit:%"PRIu64" missed:%"PRIu64" lost:%"PRIu64"\n"
474                "\tflows: %"PRIu64"\n",
475                stats.n_hit, stats.n_missed, stats.n_lost, stats.n_flows);
476     }
477     DPIF_PORT_FOR_EACH (&dpif_port, &dump, dpif) {
478         printf("\tport %u: %s", dpif_port.port_no, dpif_port.name);
479
480         if (strcmp(dpif_port.type, "system")) {
481             int error;
482
483             printf (" (%s", dpif_port.type);
484
485             error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
486             if (!error) {
487                 struct shash config;
488
489                 shash_init(&config);
490                 error = netdev_get_config(netdev, &config);
491                 if (!error) {
492                     const struct shash_node **nodes;
493                     size_t i;
494
495                     nodes = shash_sort(&config);
496                     for (i = 0; i < shash_count(&config); i++) {
497                         const struct shash_node *node = nodes[i];
498                         printf("%c %s=%s", i ? ',' : ':',
499                                node->name, (char *) node->data);
500                     }
501                     free(nodes);
502                 } else {
503                     printf(", could not retrieve configuration (%s)",
504                            strerror(error));
505                 }
506                 shash_destroy_free_data(&config);
507
508                 netdev_close(netdev);
509             } else {
510                 printf(": open failed (%s)", strerror(error));
511             }
512             putchar(')');
513         }
514         putchar('\n');
515
516         if (print_statistics) {
517             struct netdev_stats s;
518             int error;
519
520             error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
521             if (error) {
522                 printf(", open failed (%s)", strerror(error));
523                 continue;
524             }
525             error = netdev_get_stats(netdev, &s);
526             if (error) {
527                 printf(", could not retrieve stats (%s)", strerror(error));
528                 continue;
529             }
530
531             netdev_close(netdev);
532             print_stat("\t\tRX packets:", s.rx_packets);
533             print_stat(" errors:", s.rx_errors);
534             print_stat(" dropped:", s.rx_dropped);
535             print_stat(" overruns:", s.rx_over_errors);
536             print_stat(" frame:", s.rx_frame_errors);
537             printf("\n");
538
539             print_stat("\t\tTX packets:", s.tx_packets);
540             print_stat(" errors:", s.tx_errors);
541             print_stat(" dropped:", s.tx_dropped);
542             print_stat(" aborted:", s.tx_aborted_errors);
543             print_stat(" carrier:", s.tx_carrier_errors);
544             printf("\n");
545
546             print_stat("\t\tcollisions:", s.collisions);
547             printf("\n");
548
549             print_stat("\t\tRX bytes:", s.rx_bytes);
550             print_human_size(s.rx_bytes);
551             print_stat("  TX bytes:", s.tx_bytes);
552             print_human_size(s.tx_bytes);
553             printf("\n");
554         }
555     }
556     dpif_close(dpif);
557 }
558
559 static void
560 do_show(int argc, char *argv[])
561 {
562     bool failure = false;
563     if (argc > 1) {
564         int i;
565         for (i = 1; i < argc; i++) {
566             const char *name = argv[i];
567             struct dpif *dpif;
568             int error;
569
570             error = parsed_dpif_open(name, false, &dpif);
571             if (!error) {
572                 show_dpif(dpif);
573             } else {
574                 ovs_error(error, "opening datapath %s failed", name);
575                 failure = true;
576             }
577         }
578     } else {
579         struct sset types;
580         const char *type;
581
582         sset_init(&types);
583         dp_enumerate_types(&types);
584         SSET_FOR_EACH (type, &types) {
585             struct sset names;
586             const char *name;
587
588             sset_init(&names);
589             if (dp_enumerate_names(type, &names)) {
590                 failure = true;
591                 continue;
592             }
593             SSET_FOR_EACH (name, &names) {
594                 struct dpif *dpif;
595                 int error;
596
597                 error = dpif_open(name, type, &dpif);
598                 if (!error) {
599                     show_dpif(dpif);
600                 } else {
601                     ovs_error(error, "opening datapath %s failed", name);
602                     failure = true;
603                 }
604             }
605             sset_destroy(&names);
606         }
607         sset_destroy(&types);
608     }
609     if (failure) {
610         exit(EXIT_FAILURE);
611     }
612 }
613
614 static void
615 do_dump_dps(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
616 {
617     struct sset dpif_names, dpif_types;
618     const char *type;
619     int error = 0;
620
621     sset_init(&dpif_names);
622     sset_init(&dpif_types);
623     dp_enumerate_types(&dpif_types);
624
625     SSET_FOR_EACH (type, &dpif_types) {
626         const char *name;
627         int retval;
628
629         retval = dp_enumerate_names(type, &dpif_names);
630         if (retval) {
631             error = retval;
632         }
633
634         SSET_FOR_EACH (name, &dpif_names) {
635             struct dpif *dpif;
636             if (!dpif_open(name, type, &dpif)) {
637                 printf("%s\n", dpif_name(dpif));
638                 dpif_close(dpif);
639             }
640         }
641     }
642
643     sset_destroy(&dpif_names);
644     sset_destroy(&dpif_types);
645     if (error) {
646         exit(EXIT_FAILURE);
647     }
648 }
649
650 static void
651 do_dump_flows(int argc OVS_UNUSED, char *argv[])
652 {
653     const struct dpif_flow_stats *stats;
654     const struct nlattr *actions;
655     struct dpif_flow_dump dump;
656     const struct nlattr *key;
657     size_t actions_len;
658     struct dpif *dpif;
659     size_t key_len;
660     struct ds ds;
661
662     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
663
664     ds_init(&ds);
665     dpif_flow_dump_start(&dump, dpif);
666     while (dpif_flow_dump_next(&dump, &key, &key_len,
667                                &actions, &actions_len, &stats)) {
668         ds_clear(&ds);
669         odp_flow_key_format(key, key_len, &ds);
670         ds_put_cstr(&ds, ", ");
671         dpif_flow_stats_format(stats, &ds);
672         ds_put_cstr(&ds, ", actions:");
673         format_odp_actions(&ds, actions, actions_len);
674         printf("%s\n", ds_cstr(&ds));
675     }
676     dpif_flow_dump_done(&dump);
677     ds_destroy(&ds);
678     dpif_close(dpif);
679 }
680
681 static void
682 do_del_flows(int argc OVS_UNUSED, char *argv[])
683 {
684     struct dpif *dpif;
685
686     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
687     run(dpif_flow_flush(dpif), "deleting all flows");
688     dpif_close(dpif);
689 }
690
691 static void
692 do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
693 {
694     usage();
695 }
696 \f
697 /* Undocumented commands for unit testing. */
698
699 static void
700 do_parse_actions(int argc, char *argv[])
701 {
702     int i;
703
704     for (i = 1; i < argc; i++) {
705         struct ofpbuf actions;
706         struct ds s;
707
708         ofpbuf_init(&actions, 0);
709         run(odp_actions_from_string(argv[i], NULL, &actions),
710             "odp_actions_from_string");
711
712         ds_init(&s);
713         format_odp_actions(&s, actions.data, actions.size);
714         puts(ds_cstr(&s));
715         ds_destroy(&s);
716
717         ofpbuf_uninit(&actions);
718     }
719 }
720
721 static const struct command all_commands[] = {
722     { "add-dp", 1, INT_MAX, do_add_dp },
723     { "del-dp", 1, 1, do_del_dp },
724     { "add-if", 2, INT_MAX, do_add_if },
725     { "del-if", 2, INT_MAX, do_del_if },
726     { "set-if", 2, INT_MAX, do_set_if },
727     { "dump-dps", 0, 0, do_dump_dps },
728     { "show", 0, INT_MAX, do_show },
729     { "dump-flows", 1, 1, do_dump_flows },
730     { "del-flows", 1, 1, do_del_flows },
731     { "help", 0, INT_MAX, do_help },
732
733     /* Undocumented commands for testing. */
734     { "parse-actions", 1, INT_MAX, do_parse_actions },
735
736     { NULL, 0, 0, NULL },
737 };