Global replace of Nicira Networks.
[sliver-openvswitch.git] / utilities / ovs-dpctl.c
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
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 <assert.h>
20 #include <errno.h>
21 #include <getopt.h>
22 #include <inttypes.h>
23 #include <sys/socket.h>
24 #include <net/if.h>
25 #include <netinet/in.h>
26 #include <signal.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include <sys/time.h>
33
34 #include "command-line.h"
35 #include "compiler.h"
36 #include "dirs.h"
37 #include "dpif.h"
38 #include "dynamic-string.h"
39 #include "flow.h"
40 #include "netdev.h"
41 #include "netlink.h"
42 #include "odp-util.h"
43 #include "ofpbuf.h"
44 #include "packets.h"
45 #include "shash.h"
46 #include "sset.h"
47 #include "timeval.h"
48 #include "util.h"
49 #include "vlog.h"
50
51 VLOG_DEFINE_THIS_MODULE(dpctl);
52
53 /* -s, --statistics: Print port statistics? */
54 static bool print_statistics;
55
56 /* -m, --more: Output verbosity.
57  *
58  * So far only undocumented commands honor this option, so we don't document
59  * the option itself. */
60 static int verbosity;
61
62 static const struct command all_commands[];
63
64 static void usage(void) NO_RETURN;
65 static void parse_options(int argc, char *argv[]);
66
67 int
68 main(int argc, char *argv[])
69 {
70     set_program_name(argv[0]);
71     parse_options(argc, argv);
72     signal(SIGPIPE, SIG_IGN);
73     run_command(argc - optind, argv + optind, all_commands);
74     return 0;
75 }
76
77 static void
78 parse_options(int argc, char *argv[])
79 {
80     enum {
81         OPT_DUMMY = UCHAR_MAX + 1,
82         VLOG_OPTION_ENUMS
83     };
84     static struct option long_options[] = {
85         {"statistics", no_argument, NULL, 's'},
86         {"more", no_argument, NULL, 'm'},
87         {"timeout", required_argument, NULL, 't'},
88         {"help", no_argument, NULL, 'h'},
89         {"version", no_argument, NULL, 'V'},
90         VLOG_LONG_OPTIONS,
91         {NULL, 0, NULL, 0},
92     };
93     char *short_options = long_options_to_short_options(long_options);
94
95     for (;;) {
96         unsigned long int timeout;
97         int c;
98
99         c = getopt_long(argc, argv, short_options, long_options, NULL);
100         if (c == -1) {
101             break;
102         }
103
104         switch (c) {
105         case 's':
106             print_statistics = true;
107             break;
108
109         case 'm':
110             verbosity++;
111             break;
112
113         case 't':
114             timeout = strtoul(optarg, NULL, 10);
115             if (timeout <= 0) {
116                 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
117                           optarg);
118             } else {
119                 time_alarm(timeout);
120             }
121             break;
122
123         case 'h':
124             usage();
125
126         case 'V':
127             ovs_print_version(0, 0);
128             exit(EXIT_SUCCESS);
129
130         VLOG_OPTION_HANDLERS
131
132         case '?':
133             exit(EXIT_FAILURE);
134
135         default:
136             abort();
137         }
138     }
139     free(short_options);
140 }
141
142 static void
143 usage(void)
144 {
145     printf("%s: Open vSwitch datapath management utility\n"
146            "usage: %s [OPTIONS] COMMAND [ARG...]\n"
147            "  add-dp DP [IFACE...]     add new datapath DP (with IFACEs)\n"
148            "  del-dp DP                delete local datapath DP\n"
149            "  add-if DP IFACE...       add each IFACE as a port on DP\n"
150            "  set-if DP IFACE...       reconfigure each IFACE within DP\n"
151            "  del-if DP IFACE...       delete each IFACE from DP\n"
152            "  dump-dps                 display names of all datapaths\n"
153            "  show                     show basic info on all datapaths\n"
154            "  show DP...               show basic info on each DP\n"
155            "  dump-flows DP            display flows in DP\n"
156            "  del-flows DP             delete all flows from DP\n"
157            "Each IFACE on add-dp, add-if, and set-if may be followed by\n"
158            "comma-separated options.  See ovs-dpctl(8) for syntax, or the\n"
159            "Interface table in ovs-vswitchd.conf.db(5) for an options list.\n",
160            program_name, program_name);
161     vlog_usage();
162     printf("\nOther options:\n"
163            "  -t, --timeout=SECS          give up after SECS seconds\n"
164            "  -h, --help                  display this help message\n"
165            "  -V, --version               display version information\n");
166     exit(EXIT_SUCCESS);
167 }
168
169 static void run(int retval, const char *message, ...)
170     PRINTF_FORMAT(2, 3);
171
172 static void run(int retval, const char *message, ...)
173 {
174     if (retval) {
175         va_list args;
176
177         va_start(args, message);
178         ovs_fatal_valist(retval, message, args);
179     }
180 }
181 \f
182 static void do_add_if(int argc, char *argv[]);
183
184 static int if_up(const char *netdev_name)
185 {
186     struct netdev *netdev;
187     int retval;
188
189     retval = netdev_open(netdev_name, "system", &netdev);
190     if (!retval) {
191         retval = netdev_turn_flags_on(netdev, NETDEV_UP, true);
192         netdev_close(netdev);
193     }
194     return retval;
195 }
196
197 static int
198 parsed_dpif_open(const char *arg_, bool create, struct dpif **dpifp)
199 {
200     int result;
201     char *name, *type;
202
203     dp_parse_name(arg_, &name, &type);
204
205     if (create) {
206         result = dpif_create(name, type, dpifp);
207     } else {
208         result = dpif_open(name, type, dpifp);
209     }
210
211     free(name);
212     free(type);
213     return result;
214 }
215
216 static void
217 do_add_dp(int argc OVS_UNUSED, char *argv[])
218 {
219     struct dpif *dpif;
220     run(parsed_dpif_open(argv[1], true, &dpif), "add_dp");
221     dpif_close(dpif);
222     if (argc > 2) {
223         do_add_if(argc, argv);
224     }
225 }
226
227 static void
228 do_del_dp(int argc OVS_UNUSED, char *argv[])
229 {
230     struct dpif *dpif;
231     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
232     run(dpif_delete(dpif), "del_dp");
233     dpif_close(dpif);
234 }
235
236 static void
237 do_add_if(int argc OVS_UNUSED, char *argv[])
238 {
239     bool failure = false;
240     struct dpif *dpif;
241     int i;
242
243     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
244     for (i = 2; i < argc; i++) {
245         const char *name, *type;
246         char *save_ptr = NULL;
247         struct netdev *netdev = NULL;
248         struct shash args;
249         char *option;
250         int error;
251
252         name = strtok_r(argv[i], ",", &save_ptr);
253         type = "system";
254
255         if (!name) {
256             ovs_error(0, "%s is not a valid network device name", argv[i]);
257             failure = true;
258             continue;
259         }
260
261         shash_init(&args);
262         while ((option = strtok_r(NULL, ",", &save_ptr)) != NULL) {
263             char *save_ptr_2 = NULL;
264             char *key, *value;
265
266             key = strtok_r(option, "=", &save_ptr_2);
267             value = strtok_r(NULL, "", &save_ptr_2);
268             if (!value) {
269                 value = "";
270             }
271
272             if (!strcmp(key, "type")) {
273                 type = value;
274             } else if (!shash_add_once(&args, key, value)) {
275                 ovs_error(0, "duplicate \"%s\" option", key);
276             }
277         }
278
279         error = netdev_open(name, type, &netdev);
280         if (error) {
281             ovs_error(error, "%s: failed to open network device", name);
282             goto next;
283         }
284
285         error = netdev_set_config(netdev, &args);
286         if (error) {
287             ovs_error(error, "%s: failed to configure network device", name);
288             goto next;
289         }
290
291         error = dpif_port_add(dpif, netdev, NULL);
292         if (error) {
293             ovs_error(error, "adding %s to %s failed", name, argv[1]);
294             goto next;
295         }
296
297         error = if_up(name);
298
299 next:
300         netdev_close(netdev);
301         if (error) {
302             failure = true;
303         }
304     }
305     dpif_close(dpif);
306     if (failure) {
307         exit(EXIT_FAILURE);
308     }
309 }
310
311 static void
312 do_set_if(int argc, char *argv[])
313 {
314     bool failure = false;
315     struct dpif *dpif;
316     int i;
317
318     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
319     for (i = 2; i < argc; i++) {
320         struct netdev *netdev = NULL;
321         struct dpif_port dpif_port;
322         char *save_ptr = NULL;
323         char *type = NULL;
324         const char *name;
325         struct shash args;
326         char *option;
327         int error;
328
329         name = strtok_r(argv[i], ",", &save_ptr);
330         if (!name) {
331             ovs_error(0, "%s is not a valid network device name", argv[i]);
332             failure = true;
333             continue;
334         }
335
336         /* Get the port's type from the datapath. */
337         error = dpif_port_query_by_name(dpif, name, &dpif_port);
338         if (error) {
339             ovs_error(error, "%s: failed to query port in %s", name, argv[1]);
340             goto next;
341         }
342         type = xstrdup(dpif_port.type);
343         dpif_port_destroy(&dpif_port);
344
345         /* Retrieve its existing configuration. */
346         error = netdev_open(name, type, &netdev);
347         if (error) {
348             ovs_error(error, "%s: failed to open network device", name);
349             goto next;
350         }
351
352         shash_init(&args);
353         error = netdev_get_config(netdev, &args);
354         if (error) {
355             ovs_error(error, "%s: failed to fetch configuration", name);
356             goto next;
357         }
358
359         /* Parse changes to configuration. */
360         while ((option = strtok_r(NULL, ",", &save_ptr)) != NULL) {
361             char *save_ptr_2 = NULL;
362             char *key, *value;
363
364             key = strtok_r(option, "=", &save_ptr_2);
365             value = strtok_r(NULL, "", &save_ptr_2);
366             if (!value) {
367                 value = "";
368             }
369
370             if (!strcmp(key, "type")) {
371                 if (strcmp(value, type)) {
372                     ovs_error(0, "%s: can't change type from %s to %s",
373                               name, type, value);
374                     failure = true;
375                 }
376             } else if (value[0] == '\0') {
377                 free(shash_find_and_delete(&args, key));
378             } else {
379                 free(shash_replace(&args, key, xstrdup(value)));
380             }
381         }
382
383         /* Update configuration. */
384         error = netdev_set_config(netdev, &args);
385         smap_destroy(&args);
386         if (error) {
387             ovs_error(error, "%s: failed to configure network device", name);
388             goto next;
389         }
390
391 next:
392         free(type);
393         netdev_close(netdev);
394         if (error) {
395             failure = true;
396         }
397     }
398     dpif_close(dpif);
399     if (failure) {
400         exit(EXIT_FAILURE);
401     }
402 }
403
404 static bool
405 get_port_number(struct dpif *dpif, const char *name, uint16_t *port)
406 {
407     struct dpif_port dpif_port;
408
409     if (!dpif_port_query_by_name(dpif, name, &dpif_port)) {
410         *port = dpif_port.port_no;
411         dpif_port_destroy(&dpif_port);
412         return true;
413     } else {
414         ovs_error(0, "no port named %s", name);
415         return false;
416     }
417 }
418
419 static void
420 do_del_if(int argc OVS_UNUSED, char *argv[])
421 {
422     bool failure = false;
423     struct dpif *dpif;
424     int i;
425
426     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
427     for (i = 2; i < argc; i++) {
428         const char *name = argv[i];
429         uint16_t port;
430         int error;
431
432         if (!name[strspn(name, "0123456789")]) {
433             port = atoi(name);
434         } else if (!get_port_number(dpif, name, &port)) {
435             failure = true;
436             continue;
437         }
438
439         error = dpif_port_del(dpif, port);
440         if (error) {
441             ovs_error(error, "deleting port %s from %s failed", name, argv[1]);
442             failure = true;
443         }
444     }
445     dpif_close(dpif);
446     if (failure) {
447         exit(EXIT_FAILURE);
448     }
449 }
450
451 static void
452 print_stat(const char *leader, uint64_t value)
453 {
454     fputs(leader, stdout);
455     if (value != UINT64_MAX) {
456         printf("%"PRIu64, value);
457     } else {
458         putchar('?');
459     }
460 }
461
462 static void
463 print_human_size(uint64_t value)
464 {
465     if (value == UINT64_MAX) {
466         /* Nothing to do. */
467     } else if (value >= 1024ULL * 1024 * 1024 * 1024) {
468         printf(" (%.1f TiB)", value / (1024.0 * 1024 * 1024 * 1024));
469     } else if (value >= 1024ULL * 1024 * 1024) {
470         printf(" (%.1f GiB)", value / (1024.0 * 1024 * 1024));
471     } else if (value >= 1024ULL * 1024) {
472         printf(" (%.1f MiB)", value / (1024.0 * 1024));
473     } else if (value >= 1024) {
474         printf(" (%.1f KiB)", value / 1024.0);
475     }
476 }
477
478 static void
479 show_dpif(struct dpif *dpif)
480 {
481     struct dpif_port_dump dump;
482     struct dpif_port dpif_port;
483     struct dpif_dp_stats stats;
484     struct netdev *netdev;
485
486     printf("%s:\n", dpif_name(dpif));
487     if (!dpif_get_dp_stats(dpif, &stats)) {
488         printf("\tlookups: hit:%"PRIu64" missed:%"PRIu64" lost:%"PRIu64"\n"
489                "\tflows: %"PRIu64"\n",
490                stats.n_hit, stats.n_missed, stats.n_lost, stats.n_flows);
491     }
492     DPIF_PORT_FOR_EACH (&dpif_port, &dump, dpif) {
493         printf("\tport %u: %s", dpif_port.port_no, dpif_port.name);
494
495         if (strcmp(dpif_port.type, "system")) {
496             int error;
497
498             printf (" (%s", dpif_port.type);
499
500             error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
501             if (!error) {
502                 struct shash config;
503
504                 shash_init(&config);
505                 error = netdev_get_config(netdev, &config);
506                 if (!error) {
507                     const struct shash_node **nodes;
508                     size_t i;
509
510                     nodes = shash_sort(&config);
511                     for (i = 0; i < shash_count(&config); i++) {
512                         const struct shash_node *node = nodes[i];
513                         printf("%c %s=%s", i ? ',' : ':',
514                                node->name, (char *) node->data);
515                     }
516                     free(nodes);
517                 } else {
518                     printf(", could not retrieve configuration (%s)",
519                            strerror(error));
520                 }
521                 shash_destroy_free_data(&config);
522
523                 netdev_close(netdev);
524             } else {
525                 printf(": open failed (%s)", strerror(error));
526             }
527             putchar(')');
528         }
529         putchar('\n');
530
531         if (print_statistics) {
532             struct netdev_stats s;
533             int error;
534
535             error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
536             if (error) {
537                 printf(", open failed (%s)", strerror(error));
538                 continue;
539             }
540             error = netdev_get_stats(netdev, &s);
541             if (error) {
542                 printf(", could not retrieve stats (%s)", strerror(error));
543                 continue;
544             }
545
546             netdev_close(netdev);
547             print_stat("\t\tRX packets:", s.rx_packets);
548             print_stat(" errors:", s.rx_errors);
549             print_stat(" dropped:", s.rx_dropped);
550             print_stat(" overruns:", s.rx_over_errors);
551             print_stat(" frame:", s.rx_frame_errors);
552             printf("\n");
553
554             print_stat("\t\tTX packets:", s.tx_packets);
555             print_stat(" errors:", s.tx_errors);
556             print_stat(" dropped:", s.tx_dropped);
557             print_stat(" aborted:", s.tx_aborted_errors);
558             print_stat(" carrier:", s.tx_carrier_errors);
559             printf("\n");
560
561             print_stat("\t\tcollisions:", s.collisions);
562             printf("\n");
563
564             print_stat("\t\tRX bytes:", s.rx_bytes);
565             print_human_size(s.rx_bytes);
566             print_stat("  TX bytes:", s.tx_bytes);
567             print_human_size(s.tx_bytes);
568             printf("\n");
569         }
570     }
571     dpif_close(dpif);
572 }
573
574 static void
575 do_show(int argc, char *argv[])
576 {
577     bool failure = false;
578     if (argc > 1) {
579         int i;
580         for (i = 1; i < argc; i++) {
581             const char *name = argv[i];
582             struct dpif *dpif;
583             int error;
584
585             error = parsed_dpif_open(name, false, &dpif);
586             if (!error) {
587                 show_dpif(dpif);
588             } else {
589                 ovs_error(error, "opening datapath %s failed", name);
590                 failure = true;
591             }
592         }
593     } else {
594         struct sset types;
595         const char *type;
596
597         sset_init(&types);
598         dp_enumerate_types(&types);
599         SSET_FOR_EACH (type, &types) {
600             struct sset names;
601             const char *name;
602
603             sset_init(&names);
604             if (dp_enumerate_names(type, &names)) {
605                 failure = true;
606                 continue;
607             }
608             SSET_FOR_EACH (name, &names) {
609                 struct dpif *dpif;
610                 int error;
611
612                 error = dpif_open(name, type, &dpif);
613                 if (!error) {
614                     show_dpif(dpif);
615                 } else {
616                     ovs_error(error, "opening datapath %s failed", name);
617                     failure = true;
618                 }
619             }
620             sset_destroy(&names);
621         }
622         sset_destroy(&types);
623     }
624     if (failure) {
625         exit(EXIT_FAILURE);
626     }
627 }
628
629 static void
630 do_dump_dps(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
631 {
632     struct sset dpif_names, dpif_types;
633     const char *type;
634     int error = 0;
635
636     sset_init(&dpif_names);
637     sset_init(&dpif_types);
638     dp_enumerate_types(&dpif_types);
639
640     SSET_FOR_EACH (type, &dpif_types) {
641         const char *name;
642         int retval;
643
644         retval = dp_enumerate_names(type, &dpif_names);
645         if (retval) {
646             error = retval;
647         }
648
649         SSET_FOR_EACH (name, &dpif_names) {
650             struct dpif *dpif;
651             if (!dpif_open(name, type, &dpif)) {
652                 printf("%s\n", dpif_name(dpif));
653                 dpif_close(dpif);
654             }
655         }
656     }
657
658     sset_destroy(&dpif_names);
659     sset_destroy(&dpif_types);
660     if (error) {
661         exit(EXIT_FAILURE);
662     }
663 }
664
665 static void
666 do_dump_flows(int argc OVS_UNUSED, char *argv[])
667 {
668     const struct dpif_flow_stats *stats;
669     const struct nlattr *actions;
670     struct dpif_flow_dump dump;
671     const struct nlattr *key;
672     size_t actions_len;
673     struct dpif *dpif;
674     size_t key_len;
675     struct ds ds;
676
677     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
678
679     ds_init(&ds);
680     dpif_flow_dump_start(&dump, dpif);
681     while (dpif_flow_dump_next(&dump, &key, &key_len,
682                                &actions, &actions_len, &stats)) {
683         ds_clear(&ds);
684         odp_flow_key_format(key, key_len, &ds);
685         ds_put_cstr(&ds, ", ");
686         dpif_flow_stats_format(stats, &ds);
687         ds_put_cstr(&ds, ", actions:");
688         format_odp_actions(&ds, actions, actions_len);
689         printf("%s\n", ds_cstr(&ds));
690     }
691     dpif_flow_dump_done(&dump);
692     ds_destroy(&ds);
693     dpif_close(dpif);
694 }
695
696 static void
697 do_del_flows(int argc OVS_UNUSED, char *argv[])
698 {
699     struct dpif *dpif;
700
701     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
702     run(dpif_flow_flush(dpif), "deleting all flows");
703     dpif_close(dpif);
704 }
705
706 static void
707 do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
708 {
709     usage();
710 }
711 \f
712 /* Undocumented commands for unit testing. */
713
714 static void
715 do_parse_actions(int argc, char *argv[])
716 {
717     int i;
718
719     for (i = 1; i < argc; i++) {
720         struct ofpbuf actions;
721         struct ds s;
722
723         ofpbuf_init(&actions, 0);
724         run(odp_actions_from_string(argv[i], NULL, &actions),
725             "odp_actions_from_string");
726
727         ds_init(&s);
728         format_odp_actions(&s, actions.data, actions.size);
729         puts(ds_cstr(&s));
730         ds_destroy(&s);
731
732         ofpbuf_uninit(&actions);
733     }
734 }
735
736 struct actions_for_flow {
737     struct hmap_node hmap_node;
738     struct flow flow;
739     struct ofpbuf actions;
740 };
741
742 static struct actions_for_flow *
743 get_actions_for_flow(struct hmap *actions_per_flow, const struct flow *flow)
744 {
745     uint32_t hash = flow_hash(flow, 0);
746     struct actions_for_flow *af;
747
748     HMAP_FOR_EACH_WITH_HASH (af, hmap_node, hash, actions_per_flow) {
749         if (flow_equal(&af->flow, flow)) {
750             return af;
751         }
752     }
753
754     af = xmalloc(sizeof *af);
755     af->flow = *flow;
756     ofpbuf_init(&af->actions, 0);
757     hmap_insert(actions_per_flow, &af->hmap_node, hash);
758     return af;
759 }
760
761 static int
762 compare_actions_for_flow(const void *a_, const void *b_)
763 {
764     struct actions_for_flow *const *a = a_;
765     struct actions_for_flow *const *b = b_;
766
767     return flow_compare_3way(&(*a)->flow, &(*b)->flow);
768 }
769
770 static int
771 compare_output_actions(const void *a_, const void *b_)
772 {
773     const struct nlattr *a = a_;
774     const struct nlattr *b = b_;
775     uint32_t a_port = nl_attr_get_u32(a);
776     uint32_t b_port = nl_attr_get_u32(b);
777
778     return a_port < b_port ? -1 : a_port > b_port;
779 }
780
781 static void
782 sort_output_actions__(struct nlattr *first, struct nlattr *end)
783 {
784     size_t bytes = (uint8_t *) end - (uint8_t *) first;
785     size_t n = bytes / NL_A_U32_SIZE;
786
787     assert(bytes % NL_A_U32_SIZE == 0);
788     qsort(first, n, NL_A_U32_SIZE, compare_output_actions);
789 }
790
791 static void
792 sort_output_actions(struct nlattr *actions, size_t length)
793 {
794     struct nlattr *first_output = NULL;
795     struct nlattr *a;
796     int left;
797
798     NL_ATTR_FOR_EACH (a, left, actions, length) {
799         if (nl_attr_type(a) == OVS_ACTION_ATTR_OUTPUT) {
800             if (!first_output) {
801                 first_output = a;
802             }
803         } else {
804             if (first_output) {
805                 sort_output_actions__(first_output, a);
806                 first_output = NULL;
807             }
808         }
809     }
810     if (first_output) {
811         uint8_t *end = (uint8_t *) actions + length;
812         sort_output_actions__(first_output, (struct nlattr *) end);
813     }
814 }
815
816 /* usage: "ovs-dpctl normalize-actions FLOW ACTIONS" where FLOW and ACTIONS
817  * have the syntax used by "ovs-dpctl dump-flows".
818  *
819  * This command prints ACTIONS in a format that shows what happens for each
820  * VLAN, independent of the order of the ACTIONS.  For example, there is more
821  * than one way to output a packet on VLANs 9 and 11, but this command will
822  * print the same output for any form.
823  *
824  * The idea here generalizes beyond VLANs (e.g. to setting other fields) but
825  * so far the implementation only covers VLANs. */
826 static void
827 do_normalize_actions(int argc, char *argv[])
828 {
829     struct shash port_names;
830     struct ofpbuf keybuf;
831     struct flow flow;
832     struct ofpbuf odp_actions;
833     struct hmap actions_per_flow;
834     struct actions_for_flow **afs;
835     struct actions_for_flow *af;
836     struct nlattr *a;
837     size_t n_afs;
838     struct ds s;
839     int left;
840     int i;
841
842     ds_init(&s);
843
844     shash_init(&port_names);
845     for (i = 3; i < argc; i++) {
846         char name[16];
847         int number;
848         int n = -1;
849
850         if (sscanf(argv[i], "%15[^=]=%d%n", name, &number, &n) > 0 && n > 0) {
851             uintptr_t n = number;
852             shash_add(&port_names, name, (void *) n);
853         } else {
854             ovs_fatal(0, "%s: expected NAME=NUMBER", argv[i]);
855         }
856     }
857
858     /* Parse flow key. */
859     ofpbuf_init(&keybuf, 0);
860     run(odp_flow_key_from_string(argv[1], &port_names, &keybuf),
861         "odp_flow_key_from_string");
862
863     ds_clear(&s);
864     odp_flow_key_format(keybuf.data, keybuf.size, &s);
865     printf("input flow: %s\n", ds_cstr(&s));
866
867     run(odp_flow_key_to_flow(keybuf.data, keybuf.size, &flow),
868         "odp_flow_key_to_flow");
869     ofpbuf_uninit(&keybuf);
870
871     /* Parse actions. */
872     ofpbuf_init(&odp_actions, 0);
873     run(odp_actions_from_string(argv[2], &port_names, &odp_actions),
874         "odp_actions_from_string");
875
876     if (verbosity) {
877         ds_clear(&s);
878         format_odp_actions(&s, odp_actions.data, odp_actions.size);
879         printf("input actions: %s\n", ds_cstr(&s));
880     }
881
882     hmap_init(&actions_per_flow);
883     NL_ATTR_FOR_EACH (a, left, odp_actions.data, odp_actions.size) {
884         if (nl_attr_type(a) == OVS_ACTION_ATTR_POP_VLAN) {
885             flow.vlan_tci = htons(0);
886             continue;
887         }
888
889         if (nl_attr_type(a) == OVS_ACTION_ATTR_PUSH_VLAN) {
890             const struct ovs_action_push_vlan *push;
891
892             push = nl_attr_get_unspec(a, sizeof *push);
893             flow.vlan_tci = push->vlan_tci;
894             continue;
895         }
896
897         af = get_actions_for_flow(&actions_per_flow, &flow);
898         nl_msg_put_unspec(&af->actions, nl_attr_type(a),
899                           nl_attr_get(a), nl_attr_get_size(a));
900     }
901
902     n_afs = hmap_count(&actions_per_flow);
903     afs = xmalloc(n_afs * sizeof *afs);
904     i = 0;
905     HMAP_FOR_EACH (af, hmap_node, &actions_per_flow) {
906         afs[i++] = af;
907     }
908     assert(i == n_afs);
909
910     qsort(afs, n_afs, sizeof *afs, compare_actions_for_flow);
911
912     for (i = 0; i < n_afs; i++) {
913         const struct actions_for_flow *af = afs[i];
914
915         sort_output_actions(af->actions.data, af->actions.size);
916
917         if (af->flow.vlan_tci != htons(0)) {
918             printf("vlan(vid=%"PRIu16",pcp=%d): ",
919                    vlan_tci_to_vid(af->flow.vlan_tci),
920                    vlan_tci_to_pcp(af->flow.vlan_tci));
921         } else {
922             printf("no vlan: ");
923         }
924
925         ds_clear(&s);
926         format_odp_actions(&s, af->actions.data, af->actions.size);
927         puts(ds_cstr(&s));
928     }
929     ds_destroy(&s);
930 }
931
932 static const struct command all_commands[] = {
933     { "add-dp", 1, INT_MAX, do_add_dp },
934     { "del-dp", 1, 1, do_del_dp },
935     { "add-if", 2, INT_MAX, do_add_if },
936     { "del-if", 2, INT_MAX, do_del_if },
937     { "set-if", 2, INT_MAX, do_set_if },
938     { "dump-dps", 0, 0, do_dump_dps },
939     { "show", 0, INT_MAX, do_show },
940     { "dump-flows", 1, 1, do_dump_flows },
941     { "del-flows", 1, 1, do_del_flows },
942     { "help", 0, INT_MAX, do_help },
943
944     /* Undocumented commands for testing. */
945     { "parse-actions", 1, INT_MAX, do_parse_actions },
946     { "normalize-actions", 2, INT_MAX, do_normalize_actions },
947
948     { NULL, 0, 0, NULL },
949 };