2 * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <arpa/inet.h>
23 #include <sys/socket.h>
25 #include <netinet/in.h>
34 #include "command-line.h"
38 #include "dynamic-string.h"
53 VLOG_DEFINE_THIS_MODULE(dpctl
);
55 /* -s, --statistics: Print port statistics? */
56 static bool print_statistics
;
58 /* -m, --more: Output verbosity.
60 * So far only undocumented commands honor this option, so we don't document
61 * the option itself. */
64 static const struct command all_commands
[];
66 static void usage(void) NO_RETURN
;
67 static void parse_options(int argc
, char *argv
[]);
70 main(int argc
, char *argv
[])
72 set_program_name(argv
[0]);
73 parse_options(argc
, argv
);
74 signal(SIGPIPE
, SIG_IGN
);
75 run_command(argc
- optind
, argv
+ optind
, all_commands
);
80 parse_options(int argc
, char *argv
[])
83 OPT_DUMMY
= UCHAR_MAX
+ 1,
86 static struct option long_options
[] = {
87 {"statistics", no_argument
, NULL
, 's'},
88 {"more", no_argument
, NULL
, 'm'},
89 {"timeout", required_argument
, NULL
, 't'},
90 {"help", no_argument
, NULL
, 'h'},
91 {"version", no_argument
, NULL
, 'V'},
95 char *short_options
= long_options_to_short_options(long_options
);
98 unsigned long int timeout
;
101 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
108 print_statistics
= true;
116 timeout
= strtoul(optarg
, NULL
, 10);
118 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
129 ovs_print_version(0, 0);
147 printf("%s: Open vSwitch datapath management utility\n"
148 "usage: %s [OPTIONS] COMMAND [ARG...]\n"
149 " add-dp DP [IFACE...] add new datapath DP (with IFACEs)\n"
150 " del-dp DP delete local datapath DP\n"
151 " add-if DP IFACE... add each IFACE as a port on DP\n"
152 " set-if DP IFACE... reconfigure each IFACE within DP\n"
153 " del-if DP IFACE... delete each IFACE from DP\n"
154 " dump-dps display names of all datapaths\n"
155 " show show basic info on all datapaths\n"
156 " show DP... show basic info on each DP\n"
157 " dump-flows DP display flows in DP\n"
158 " del-flows DP delete all flows from DP\n"
159 "Each IFACE on add-dp, add-if, and set-if may be followed by\n"
160 "comma-separated options. See ovs-dpctl(8) for syntax, or the\n"
161 "Interface table in ovs-vswitchd.conf.db(5) for an options list.\n",
162 program_name
, program_name
);
164 printf("\nOther options:\n"
165 " -t, --timeout=SECS give up after SECS seconds\n"
166 " -h, --help display this help message\n"
167 " -V, --version display version information\n");
171 static void run(int retval
, const char *message
, ...)
174 static void run(int retval
, const char *message
, ...)
179 va_start(args
, message
);
180 ovs_fatal_valist(retval
, message
, args
);
184 static void do_add_if(int argc
, char *argv
[]);
186 static int if_up(const char *netdev_name
)
188 struct netdev
*netdev
;
191 retval
= netdev_open(netdev_name
, "system", &netdev
);
193 retval
= netdev_turn_flags_on(netdev
, NETDEV_UP
, true);
194 netdev_close(netdev
);
200 parsed_dpif_open(const char *arg_
, bool create
, struct dpif
**dpifp
)
205 dp_parse_name(arg_
, &name
, &type
);
208 result
= dpif_create(name
, type
, dpifp
);
210 result
= dpif_open(name
, type
, dpifp
);
219 do_add_dp(int argc OVS_UNUSED
, char *argv
[])
222 run(parsed_dpif_open(argv
[1], true, &dpif
), "add_dp");
225 do_add_if(argc
, argv
);
230 do_del_dp(int argc OVS_UNUSED
, char *argv
[])
233 run(parsed_dpif_open(argv
[1], false, &dpif
), "opening datapath");
234 run(dpif_delete(dpif
), "del_dp");
239 do_add_if(int argc OVS_UNUSED
, char *argv
[])
241 bool failure
= false;
245 run(parsed_dpif_open(argv
[1], false, &dpif
), "opening datapath");
246 for (i
= 2; i
< argc
; i
++) {
247 const char *name
, *type
;
248 char *save_ptr
= NULL
;
249 struct netdev
*netdev
= NULL
;
254 name
= strtok_r(argv
[i
], ",", &save_ptr
);
258 ovs_error(0, "%s is not a valid network device name", argv
[i
]);
264 while ((option
= strtok_r(NULL
, ",", &save_ptr
)) != NULL
) {
265 char *save_ptr_2
= NULL
;
268 key
= strtok_r(option
, "=", &save_ptr_2
);
269 value
= strtok_r(NULL
, "", &save_ptr_2
);
274 if (!strcmp(key
, "type")) {
276 } else if (!smap_add_once(&args
, key
, value
)) {
277 ovs_error(0, "duplicate \"%s\" option", key
);
281 error
= netdev_open(name
, type
, &netdev
);
283 ovs_error(error
, "%s: failed to open network device", name
);
287 error
= netdev_set_config(netdev
, &args
);
289 ovs_error(error
, "%s: failed to configure network device", name
);
293 error
= dpif_port_add(dpif
, netdev
, NULL
);
295 ovs_error(error
, "adding %s to %s failed", name
, argv
[1]);
302 netdev_close(netdev
);
314 do_set_if(int argc
, char *argv
[])
316 bool failure
= false;
320 run(parsed_dpif_open(argv
[1], false, &dpif
), "opening datapath");
321 for (i
= 2; i
< argc
; i
++) {
322 struct netdev
*netdev
= NULL
;
323 struct dpif_port dpif_port
;
324 char *save_ptr
= NULL
;
331 name
= strtok_r(argv
[i
], ",", &save_ptr
);
333 ovs_error(0, "%s is not a valid network device name", argv
[i
]);
338 /* Get the port's type from the datapath. */
339 error
= dpif_port_query_by_name(dpif
, name
, &dpif_port
);
341 ovs_error(error
, "%s: failed to query port in %s", name
, argv
[1]);
344 type
= xstrdup(dpif_port
.type
);
345 dpif_port_destroy(&dpif_port
);
347 /* Retrieve its existing configuration. */
348 error
= netdev_open(name
, type
, &netdev
);
350 ovs_error(error
, "%s: failed to open network device", name
);
355 error
= netdev_get_config(netdev
, &args
);
357 ovs_error(error
, "%s: failed to fetch configuration", name
);
361 /* Parse changes to configuration. */
362 while ((option
= strtok_r(NULL
, ",", &save_ptr
)) != NULL
) {
363 char *save_ptr_2
= NULL
;
366 key
= strtok_r(option
, "=", &save_ptr_2
);
367 value
= strtok_r(NULL
, "", &save_ptr_2
);
372 if (!strcmp(key
, "type")) {
373 if (strcmp(value
, type
)) {
374 ovs_error(0, "%s: can't change type from %s to %s",
378 } else if (value
[0] == '\0') {
379 smap_remove(&args
, key
);
381 smap_replace(&args
, key
, value
);
385 /* Update configuration. */
386 error
= netdev_set_config(netdev
, &args
);
389 ovs_error(error
, "%s: failed to configure network device", name
);
395 netdev_close(netdev
);
407 get_port_number(struct dpif
*dpif
, const char *name
, uint16_t *port
)
409 struct dpif_port dpif_port
;
411 if (!dpif_port_query_by_name(dpif
, name
, &dpif_port
)) {
412 *port
= dpif_port
.port_no
;
413 dpif_port_destroy(&dpif_port
);
416 ovs_error(0, "no port named %s", name
);
422 do_del_if(int argc OVS_UNUSED
, char *argv
[])
424 bool failure
= false;
428 run(parsed_dpif_open(argv
[1], false, &dpif
), "opening datapath");
429 for (i
= 2; i
< argc
; i
++) {
430 const char *name
= argv
[i
];
434 if (!name
[strspn(name
, "0123456789")]) {
436 } else if (!get_port_number(dpif
, name
, &port
)) {
441 error
= dpif_port_del(dpif
, port
);
443 ovs_error(error
, "deleting port %s from %s failed", name
, argv
[1]);
454 print_stat(const char *leader
, uint64_t value
)
456 fputs(leader
, stdout
);
457 if (value
!= UINT64_MAX
) {
458 printf("%"PRIu64
, value
);
465 print_human_size(uint64_t value
)
467 if (value
== UINT64_MAX
) {
469 } else if (value
>= 1024ULL * 1024 * 1024 * 1024) {
470 printf(" (%.1f TiB)", value
/ (1024.0 * 1024 * 1024 * 1024));
471 } else if (value
>= 1024ULL * 1024 * 1024) {
472 printf(" (%.1f GiB)", value
/ (1024.0 * 1024 * 1024));
473 } else if (value
>= 1024ULL * 1024) {
474 printf(" (%.1f MiB)", value
/ (1024.0 * 1024));
475 } else if (value
>= 1024) {
476 printf(" (%.1f KiB)", value
/ 1024.0);
481 show_dpif(struct dpif
*dpif
)
483 struct dpif_port_dump dump
;
484 struct dpif_port dpif_port
;
485 struct dpif_dp_stats stats
;
486 struct netdev
*netdev
;
488 printf("%s:\n", dpif_name(dpif
));
489 if (!dpif_get_dp_stats(dpif
, &stats
)) {
490 printf("\tlookups: hit:%"PRIu64
" missed:%"PRIu64
" lost:%"PRIu64
"\n"
491 "\tflows: %"PRIu64
"\n",
492 stats
.n_hit
, stats
.n_missed
, stats
.n_lost
, stats
.n_flows
);
494 DPIF_PORT_FOR_EACH (&dpif_port
, &dump
, dpif
) {
495 printf("\tport %u: %s", dpif_port
.port_no
, dpif_port
.name
);
497 if (strcmp(dpif_port
.type
, "system")) {
500 printf (" (%s", dpif_port
.type
);
502 error
= netdev_open(dpif_port
.name
, dpif_port
.type
, &netdev
);
507 error
= netdev_get_config(netdev
, &config
);
509 const struct smap_node
**nodes
;
512 nodes
= smap_sort(&config
);
513 for (i
= 0; i
< smap_count(&config
); i
++) {
514 const struct smap_node
*node
= nodes
[i
];
515 printf("%c %s=%s", i
? ',' : ':', node
->key
,
520 printf(", could not retrieve configuration (%s)",
523 smap_destroy(&config
);
525 netdev_close(netdev
);
527 printf(": open failed (%s)", strerror(error
));
533 if (print_statistics
) {
534 struct netdev_stats s
;
537 error
= netdev_open(dpif_port
.name
, dpif_port
.type
, &netdev
);
539 printf(", open failed (%s)", strerror(error
));
542 error
= netdev_get_stats(netdev
, &s
);
544 printf(", could not retrieve stats (%s)", strerror(error
));
548 netdev_close(netdev
);
549 print_stat("\t\tRX packets:", s
.rx_packets
);
550 print_stat(" errors:", s
.rx_errors
);
551 print_stat(" dropped:", s
.rx_dropped
);
552 print_stat(" overruns:", s
.rx_over_errors
);
553 print_stat(" frame:", s
.rx_frame_errors
);
556 print_stat("\t\tTX packets:", s
.tx_packets
);
557 print_stat(" errors:", s
.tx_errors
);
558 print_stat(" dropped:", s
.tx_dropped
);
559 print_stat(" aborted:", s
.tx_aborted_errors
);
560 print_stat(" carrier:", s
.tx_carrier_errors
);
563 print_stat("\t\tcollisions:", s
.collisions
);
566 print_stat("\t\tRX bytes:", s
.rx_bytes
);
567 print_human_size(s
.rx_bytes
);
568 print_stat(" TX bytes:", s
.tx_bytes
);
569 print_human_size(s
.tx_bytes
);
577 do_show(int argc
, char *argv
[])
579 bool failure
= false;
582 for (i
= 1; i
< argc
; i
++) {
583 const char *name
= argv
[i
];
587 error
= parsed_dpif_open(name
, false, &dpif
);
591 ovs_error(error
, "opening datapath %s failed", name
);
600 dp_enumerate_types(&types
);
601 SSET_FOR_EACH (type
, &types
) {
606 if (dp_enumerate_names(type
, &names
)) {
610 SSET_FOR_EACH (name
, &names
) {
614 error
= dpif_open(name
, type
, &dpif
);
618 ovs_error(error
, "opening datapath %s failed", name
);
622 sset_destroy(&names
);
624 sset_destroy(&types
);
632 do_dump_dps(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
634 struct sset dpif_names
, dpif_types
;
638 sset_init(&dpif_names
);
639 sset_init(&dpif_types
);
640 dp_enumerate_types(&dpif_types
);
642 SSET_FOR_EACH (type
, &dpif_types
) {
646 retval
= dp_enumerate_names(type
, &dpif_names
);
651 SSET_FOR_EACH (name
, &dpif_names
) {
653 if (!dpif_open(name
, type
, &dpif
)) {
654 printf("%s\n", dpif_name(dpif
));
660 sset_destroy(&dpif_names
);
661 sset_destroy(&dpif_types
);
668 do_dump_flows(int argc OVS_UNUSED
, char *argv
[])
670 const struct dpif_flow_stats
*stats
;
671 const struct nlattr
*actions
;
672 struct dpif_flow_dump dump
;
673 const struct nlattr
*key
;
679 run(parsed_dpif_open(argv
[1], false, &dpif
), "opening datapath");
682 dpif_flow_dump_start(&dump
, dpif
);
683 while (dpif_flow_dump_next(&dump
, &key
, &key_len
,
684 &actions
, &actions_len
, &stats
)) {
686 odp_flow_key_format(key
, key_len
, &ds
);
687 ds_put_cstr(&ds
, ", ");
688 dpif_flow_stats_format(stats
, &ds
);
689 ds_put_cstr(&ds
, ", actions:");
690 format_odp_actions(&ds
, actions
, actions_len
);
691 printf("%s\n", ds_cstr(&ds
));
693 dpif_flow_dump_done(&dump
);
699 do_del_flows(int argc OVS_UNUSED
, char *argv
[])
703 run(parsed_dpif_open(argv
[1], false, &dpif
), "opening datapath");
704 run(dpif_flow_flush(dpif
), "deleting all flows");
709 do_help(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
714 /* Undocumented commands for unit testing. */
717 do_parse_actions(int argc
, char *argv
[])
721 for (i
= 1; i
< argc
; i
++) {
722 struct ofpbuf actions
;
725 ofpbuf_init(&actions
, 0);
726 run(odp_actions_from_string(argv
[i
], NULL
, &actions
),
727 "odp_actions_from_string");
730 format_odp_actions(&s
, actions
.data
, actions
.size
);
734 ofpbuf_uninit(&actions
);
738 struct actions_for_flow
{
739 struct hmap_node hmap_node
;
741 struct ofpbuf actions
;
744 static struct actions_for_flow
*
745 get_actions_for_flow(struct hmap
*actions_per_flow
, const struct flow
*flow
)
747 uint32_t hash
= flow_hash(flow
, 0);
748 struct actions_for_flow
*af
;
750 HMAP_FOR_EACH_WITH_HASH (af
, hmap_node
, hash
, actions_per_flow
) {
751 if (flow_equal(&af
->flow
, flow
)) {
756 af
= xmalloc(sizeof *af
);
758 ofpbuf_init(&af
->actions
, 0);
759 hmap_insert(actions_per_flow
, &af
->hmap_node
, hash
);
764 compare_actions_for_flow(const void *a_
, const void *b_
)
766 struct actions_for_flow
*const *a
= a_
;
767 struct actions_for_flow
*const *b
= b_
;
769 return flow_compare_3way(&(*a
)->flow
, &(*b
)->flow
);
773 compare_output_actions(const void *a_
, const void *b_
)
775 const struct nlattr
*a
= a_
;
776 const struct nlattr
*b
= b_
;
777 uint32_t a_port
= nl_attr_get_u32(a
);
778 uint32_t b_port
= nl_attr_get_u32(b
);
780 return a_port
< b_port
? -1 : a_port
> b_port
;
784 sort_output_actions__(struct nlattr
*first
, struct nlattr
*end
)
786 size_t bytes
= (uint8_t *) end
- (uint8_t *) first
;
787 size_t n
= bytes
/ NL_A_U32_SIZE
;
789 assert(bytes
% NL_A_U32_SIZE
== 0);
790 qsort(first
, n
, NL_A_U32_SIZE
, compare_output_actions
);
794 sort_output_actions(struct nlattr
*actions
, size_t length
)
796 struct nlattr
*first_output
= NULL
;
800 NL_ATTR_FOR_EACH (a
, left
, actions
, length
) {
801 if (nl_attr_type(a
) == OVS_ACTION_ATTR_OUTPUT
) {
807 sort_output_actions__(first_output
, a
);
813 uint8_t *end
= (uint8_t *) actions
+ length
;
814 sort_output_actions__(first_output
, (struct nlattr
*) end
);
818 /* usage: "ovs-dpctl normalize-actions FLOW ACTIONS" where FLOW and ACTIONS
819 * have the syntax used by "ovs-dpctl dump-flows".
821 * This command prints ACTIONS in a format that shows what happens for each
822 * VLAN, independent of the order of the ACTIONS. For example, there is more
823 * than one way to output a packet on VLANs 9 and 11, but this command will
824 * print the same output for any form.
826 * The idea here generalizes beyond VLANs (e.g. to setting other fields) but
827 * so far the implementation only covers VLANs. */
829 do_normalize_actions(int argc
, char *argv
[])
831 struct simap port_names
;
832 struct ofpbuf keybuf
;
834 struct ofpbuf odp_actions
;
835 struct hmap actions_per_flow
;
836 struct actions_for_flow
**afs
;
837 struct actions_for_flow
*af
;
846 simap_init(&port_names
);
847 for (i
= 3; i
< argc
; i
++) {
852 if (sscanf(argv
[i
], "%15[^=]=%d%n", name
, &number
, &n
) > 0 && n
> 0) {
853 uintptr_t n
= number
;
854 simap_put(&port_names
, name
, n
);
856 ovs_fatal(0, "%s: expected NAME=NUMBER", argv
[i
]);
860 /* Parse flow key. */
861 ofpbuf_init(&keybuf
, 0);
862 run(odp_flow_key_from_string(argv
[1], &port_names
, &keybuf
),
863 "odp_flow_key_from_string");
866 odp_flow_key_format(keybuf
.data
, keybuf
.size
, &s
);
867 printf("input flow: %s\n", ds_cstr(&s
));
869 run(odp_flow_key_to_flow(keybuf
.data
, keybuf
.size
, &flow
),
870 "odp_flow_key_to_flow");
871 ofpbuf_uninit(&keybuf
);
874 ofpbuf_init(&odp_actions
, 0);
875 run(odp_actions_from_string(argv
[2], &port_names
, &odp_actions
),
876 "odp_actions_from_string");
880 format_odp_actions(&s
, odp_actions
.data
, odp_actions
.size
);
881 printf("input actions: %s\n", ds_cstr(&s
));
884 hmap_init(&actions_per_flow
);
885 NL_ATTR_FOR_EACH (a
, left
, odp_actions
.data
, odp_actions
.size
) {
886 if (nl_attr_type(a
) == OVS_ACTION_ATTR_POP_VLAN
) {
887 flow
.vlan_tci
= htons(0);
891 if (nl_attr_type(a
) == OVS_ACTION_ATTR_PUSH_VLAN
) {
892 const struct ovs_action_push_vlan
*push
;
894 push
= nl_attr_get_unspec(a
, sizeof *push
);
895 flow
.vlan_tci
= push
->vlan_tci
;
899 af
= get_actions_for_flow(&actions_per_flow
, &flow
);
900 nl_msg_put_unspec(&af
->actions
, nl_attr_type(a
),
901 nl_attr_get(a
), nl_attr_get_size(a
));
904 n_afs
= hmap_count(&actions_per_flow
);
905 afs
= xmalloc(n_afs
* sizeof *afs
);
907 HMAP_FOR_EACH (af
, hmap_node
, &actions_per_flow
) {
912 qsort(afs
, n_afs
, sizeof *afs
, compare_actions_for_flow
);
914 for (i
= 0; i
< n_afs
; i
++) {
915 const struct actions_for_flow
*af
= afs
[i
];
917 sort_output_actions(af
->actions
.data
, af
->actions
.size
);
919 if (af
->flow
.vlan_tci
!= htons(0)) {
920 printf("vlan(vid=%"PRIu16
",pcp=%d): ",
921 vlan_tci_to_vid(af
->flow
.vlan_tci
),
922 vlan_tci_to_pcp(af
->flow
.vlan_tci
));
928 format_odp_actions(&s
, af
->actions
.data
, af
->actions
.size
);
934 static const struct command all_commands
[] = {
935 { "add-dp", 1, INT_MAX
, do_add_dp
},
936 { "del-dp", 1, 1, do_del_dp
},
937 { "add-if", 2, INT_MAX
, do_add_if
},
938 { "del-if", 2, INT_MAX
, do_del_if
},
939 { "set-if", 2, INT_MAX
, do_set_if
},
940 { "dump-dps", 0, 0, do_dump_dps
},
941 { "show", 0, INT_MAX
, do_show
},
942 { "dump-flows", 1, 1, do_dump_flows
},
943 { "del-flows", 1, 1, do_del_flows
},
944 { "help", 0, INT_MAX
, do_help
},
946 /* Undocumented commands for testing. */
947 { "parse-actions", 1, INT_MAX
, do_parse_actions
},
948 { "normalize-actions", 2, INT_MAX
, do_normalize_actions
},
950 { NULL
, 0, 0, NULL
},