2 * Copyright (c) 2008-2017 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 <sys/types.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
23 #include <sys/socket.h>
30 #include "command-line.h"
36 #include "openvswitch/dynamic-string.h"
38 #include "openvswitch/match.h"
40 #include "netdev-dpdk.h"
43 #include "openvswitch/ofpbuf.h"
45 #include "openvswitch/shash.h"
52 #include "openvswitch/ofp-flow.h"
53 #include "openvswitch/ofp-port.h"
54 #include "openvswitch/vlog.h"
55 VLOG_DEFINE_THIS_MODULE(dpctl
);
57 typedef int dpctl_command_handler(int argc
, const char *argv
[],
58 struct dpctl_params
*);
59 struct dpctl_command
{
64 dpctl_command_handler
*handler
;
65 enum { DP_RO
, DP_RW
} mode
;
67 static const struct dpctl_command
*get_all_dpctl_commands(void);
68 static void dpctl_print(struct dpctl_params
*dpctl_p
, const char *fmt
, ...)
69 OVS_PRINTF_FORMAT(2, 3);
70 static void dpctl_error(struct dpctl_params
* dpctl_p
, int err_no
,
72 OVS_PRINTF_FORMAT(3, 4);
75 dpctl_puts(struct dpctl_params
*dpctl_p
, bool error
, const char *string
)
77 dpctl_p
->output(dpctl_p
->aux
, error
, string
);
81 dpctl_print(struct dpctl_params
*dpctl_p
, const char *fmt
, ...)
87 string
= xvasprintf(fmt
, args
);
90 dpctl_puts(dpctl_p
, false, string
);
95 dpctl_error(struct dpctl_params
* dpctl_p
, int err_no
, const char *fmt
, ...)
97 const char *subprogram_name
= get_subprogram_name();
98 struct ds ds
= DS_EMPTY_INITIALIZER
;
99 int save_errno
= errno
;
103 if (subprogram_name
[0]) {
104 ds_put_format(&ds
, "%s(%s): ", program_name
,subprogram_name
);
106 ds_put_format(&ds
, "%s: ", program_name
);
110 ds_put_format_valist(&ds
, fmt
, args
);
114 ds_put_format(&ds
, " (%s)", ovs_retval_to_string(err_no
));
116 ds_put_cstr(&ds
, "\n");
118 dpctl_puts(dpctl_p
, true, ds_cstr(&ds
));
125 static int dpctl_add_if(int argc
, const char *argv
[], struct dpctl_params
*);
128 if_up(struct netdev
*netdev
)
130 return netdev_turn_flags_on(netdev
, NETDEV_UP
, NULL
);
133 /* Retrieve the name of the datapath if exactly one exists. The caller
134 * is responsible for freeing the returned string. If a single datapath
135 * name cannot be determined, returns NULL. */
137 get_one_dp(struct dpctl_params
*dpctl_p
)
141 char *dp_name
= NULL
;
145 dp_enumerate_types(&types
);
146 SSET_FOR_EACH (type
, &types
) {
150 if (!dp_enumerate_names(type
, &names
)) {
151 count
+= sset_count(&names
);
152 if (!dp_name
&& count
== 1) {
153 dp_name
= xasprintf("%s@%s", type
, SSET_FIRST(&names
));
156 sset_destroy(&names
);
158 sset_destroy(&types
);
161 dpctl_error(dpctl_p
, 0, "no datapaths exist");
162 } else if (count
> 1) {
163 dpctl_error(dpctl_p
, 0, "multiple datapaths, specify one");
172 parsed_dpif_open(const char *arg_
, bool create
, struct dpif
**dpifp
)
177 dp_parse_name(arg_
, &name
, &type
);
180 result
= dpif_create(name
, type
, dpifp
);
182 result
= dpif_open(name
, type
, dpifp
);
190 /* Open a dpif with an optional name argument.
192 * The datapath name is not a mandatory parameter for this command. If
193 * it is not specified -- so 'argc' < 'max_args' -- we retrieve it from
194 * the current setup, assuming only one exists. On success stores the
195 * opened dpif in '*dpifp'. */
197 opt_dpif_open(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
,
198 uint8_t max_args
, struct dpif
**dpifp
)
201 char *dpname
= argc
>= max_args
? xstrdup(argv
[1]) : get_one_dp(dpctl_p
);
204 dpctl_error(dpctl_p
, error
, "datapath not found");
206 error
= parsed_dpif_open(dpname
, false, dpifp
);
209 dpctl_error(dpctl_p
, error
, "opening datapath");
216 dpctl_add_dp(int argc
, const char *argv
[],
217 struct dpctl_params
*dpctl_p
)
222 error
= parsed_dpif_open(argv
[1], true, &dpif
);
224 dpctl_error(dpctl_p
, error
, "add_dp");
229 error
= dpctl_add_if(argc
, argv
, dpctl_p
);
235 dpctl_del_dp(int argc OVS_UNUSED
, const char *argv
[],
236 struct dpctl_params
*dpctl_p
)
241 error
= parsed_dpif_open(argv
[1], false, &dpif
);
243 dpctl_error(dpctl_p
, error
, "opening datapath");
246 error
= dpif_delete(dpif
);
248 dpctl_error(dpctl_p
, error
, "del_dp");
256 dpctl_add_if(int argc OVS_UNUSED
, const char *argv
[],
257 struct dpctl_params
*dpctl_p
)
260 int i
, error
, lasterror
= 0;
262 error
= parsed_dpif_open(argv
[1], false, &dpif
);
264 dpctl_error(dpctl_p
, error
, "opening datapath");
267 for (i
= 2; i
< argc
; i
++) {
268 const char *name
, *type
;
269 char *save_ptr
= NULL
, *argcopy
;
270 struct netdev
*netdev
= NULL
;
272 odp_port_t port_no
= ODPP_NONE
;
275 argcopy
= xstrdup(argv
[i
]);
276 name
= strtok_r(argcopy
, ",", &save_ptr
);
280 dpctl_error(dpctl_p
, 0, "%s is not a valid network device name",
287 while ((option
= strtok_r(NULL
, ",", &save_ptr
)) != NULL
) {
288 char *save_ptr_2
= NULL
;
291 key
= strtok_r(option
, "=", &save_ptr_2
);
292 value
= strtok_r(NULL
, "", &save_ptr_2
);
297 if (!strcmp(key
, "type")) {
299 } else if (!strcmp(key
, "port_no")) {
300 port_no
= u32_to_odp(atoi(value
));
301 } else if (!smap_add_once(&args
, key
, value
)) {
302 dpctl_error(dpctl_p
, 0, "duplicate \"%s\" option", key
);
306 error
= netdev_open(name
, type
, &netdev
);
308 dpctl_error(dpctl_p
, error
, "%s: failed to open network device",
310 goto next_destroy_args
;
313 error
= netdev_set_config(netdev
, &args
, NULL
);
315 goto next_destroy_args
;
318 error
= dpif_port_add(dpif
, netdev
, &port_no
);
320 dpctl_error(dpctl_p
, error
, "adding %s to %s failed", name
,
322 goto next_destroy_args
;
325 error
= if_up(netdev
);
327 dpctl_error(dpctl_p
, error
, "%s: failed bringing interface up",
332 netdev_close(netdev
);
346 dpctl_set_if(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
349 int i
, error
, lasterror
= 0;
351 error
= parsed_dpif_open(argv
[1], false, &dpif
);
353 dpctl_error(dpctl_p
, error
, "opening datapath");
356 for (i
= 2; i
< argc
; i
++) {
357 struct netdev
*netdev
= NULL
;
358 struct dpif_port dpif_port
;
359 char *save_ptr
= NULL
;
369 argcopy
= xstrdup(argv
[i
]);
370 name
= strtok_r(argcopy
, ",", &save_ptr
);
372 dpctl_error(dpctl_p
, 0, "%s is not a valid network device name",
377 /* Get the port's type from the datapath. */
378 error
= dpif_port_query_by_name(dpif
, name
, &dpif_port
);
380 dpctl_error(dpctl_p
, error
, "%s: failed to query port in %s", name
,
384 type
= xstrdup(dpif_port
.type
);
385 port_no
= dpif_port
.port_no
;
386 dpif_port_destroy(&dpif_port
);
388 /* Retrieve its existing configuration. */
389 error
= netdev_open(name
, type
, &netdev
);
391 dpctl_error(dpctl_p
, error
, "%s: failed to open network device",
397 error
= netdev_get_config(netdev
, &args
);
399 dpctl_error(dpctl_p
, error
, "%s: failed to fetch configuration",
401 goto next_destroy_args
;
404 /* Parse changes to configuration. */
405 while ((option
= strtok_r(NULL
, ",", &save_ptr
)) != NULL
) {
406 char *save_ptr_2
= NULL
;
409 key
= strtok_r(option
, "=", &save_ptr_2
);
410 value
= strtok_r(NULL
, "", &save_ptr_2
);
415 if (!strcmp(key
, "type")) {
416 if (strcmp(value
, type
)) {
417 dpctl_error(dpctl_p
, 0,
418 "%s: can't change type from %s to %s",
421 goto next_destroy_args
;
423 } else if (!strcmp(key
, "port_no")) {
424 if (port_no
!= u32_to_odp(atoi(value
))) {
425 dpctl_error(dpctl_p
, 0, "%s: can't change port number from"
426 " %"PRIu32
" to %d", name
, port_no
, atoi(value
));
428 goto next_destroy_args
;
430 } else if (value
[0] == '\0') {
431 smap_remove(&args
, key
);
433 smap_replace(&args
, key
, value
);
437 /* Update configuration. */
439 error
= netdev_set_config(netdev
, &args
, &err_s
);
440 if (err_s
|| error
) {
441 dpctl_error(dpctl_p
, error
, "%s",
442 err_s
? err_s
: "Error updating configuration");
446 goto next_destroy_args
;
452 netdev_close(netdev
);
465 get_port_number(struct dpif
*dpif
, const char *name
, odp_port_t
*port
,
466 struct dpctl_params
*dpctl_p
)
468 struct dpif_port dpif_port
;
470 if (!dpif_port_query_by_name(dpif
, name
, &dpif_port
)) {
471 *port
= dpif_port
.port_no
;
472 dpif_port_destroy(&dpif_port
);
475 dpctl_error(dpctl_p
, 0, "no port named %s", name
);
481 dpctl_del_if(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
484 int i
, error
, lasterror
= 0;
486 error
= parsed_dpif_open(argv
[1], false, &dpif
);
488 dpctl_error(dpctl_p
, error
, "opening datapath");
491 for (i
= 2; i
< argc
; i
++) {
492 const char *name
= argv
[i
];
495 if (!name
[strspn(name
, "0123456789")]) {
496 port
= u32_to_odp(atoi(name
));
497 } else if (!get_port_number(dpif
, name
, &port
, dpctl_p
)) {
502 error
= dpif_port_del(dpif
, port
, false);
504 dpctl_error(dpctl_p
, error
, "deleting port %s from %s failed",
514 print_stat(struct dpctl_params
*dpctl_p
, const char *leader
, uint64_t value
)
516 dpctl_print(dpctl_p
, "%s", leader
);
517 if (value
!= UINT64_MAX
) {
518 dpctl_print(dpctl_p
, "%"PRIu64
, value
);
520 dpctl_print(dpctl_p
, "?");
525 print_human_size(struct dpctl_params
*dpctl_p
, uint64_t value
)
527 if (value
== UINT64_MAX
) {
529 } else if (value
>= 1024ULL * 1024 * 1024 * 1024) {
530 dpctl_print(dpctl_p
, " (%.1f TiB)",
531 value
/ (1024.0 * 1024 * 1024 * 1024));
532 } else if (value
>= 1024ULL * 1024 * 1024) {
533 dpctl_print(dpctl_p
, " (%.1f GiB)", value
/ (1024.0 * 1024 * 1024));
534 } else if (value
>= 1024ULL * 1024) {
535 dpctl_print(dpctl_p
, " (%.1f MiB)", value
/ (1024.0 * 1024));
536 } else if (value
>= 1024) {
537 dpctl_print(dpctl_p
, " (%.1f KiB)", value
/ 1024.0);
541 /* qsort comparison function. */
543 compare_port_nos(const void *a_
, const void *b_
)
545 const odp_port_t
*ap
= a_
;
546 const odp_port_t
*bp
= b_
;
547 uint32_t a
= odp_to_u32(*ap
);
548 uint32_t b
= odp_to_u32(*bp
);
550 return a
< b
? -1 : a
> b
;
554 show_dpif(struct dpif
*dpif
, struct dpctl_params
*dpctl_p
)
556 struct dpif_port_dump dump
;
557 struct dpif_port dpif_port
;
558 struct dpif_dp_stats stats
;
559 struct netdev
*netdev
;
561 dpctl_print(dpctl_p
, "%s:\n", dpif_name(dpif
));
562 if (!dpif_get_dp_stats(dpif
, &stats
)) {
563 dpctl_print(dpctl_p
, " lookups: hit:%"PRIu64
" missed:%"PRIu64
564 " lost:%"PRIu64
"\n flows: %"PRIu64
"\n",
565 stats
.n_hit
, stats
.n_missed
, stats
.n_lost
, stats
.n_flows
);
566 if (stats
.n_masks
!= UINT32_MAX
) {
567 uint64_t n_pkts
= stats
.n_hit
+ stats
.n_missed
;
568 double avg
= n_pkts
? (double) stats
.n_mask_hit
/ n_pkts
: 0.0;
570 dpctl_print(dpctl_p
, " masks: hit:%"PRIu64
" total:%"PRIu32
572 stats
.n_mask_hit
, stats
.n_masks
, avg
);
576 odp_port_t
*port_nos
= NULL
;
577 size_t allocated_port_nos
= 0, n_port_nos
= 0;
578 DPIF_PORT_FOR_EACH (&dpif_port
, &dump
, dpif
) {
579 if (n_port_nos
>= allocated_port_nos
) {
580 port_nos
= x2nrealloc(port_nos
, &allocated_port_nos
,
584 port_nos
[n_port_nos
] = dpif_port
.port_no
;
589 qsort(port_nos
, n_port_nos
, sizeof *port_nos
, compare_port_nos
);
592 for (int i
= 0; i
< n_port_nos
; i
++) {
593 if (dpif_port_query_by_number(dpif
, port_nos
[i
], &dpif_port
)) {
597 dpctl_print(dpctl_p
, " port %u: %s",
598 dpif_port
.port_no
, dpif_port
.name
);
600 if (strcmp(dpif_port
.type
, "system")) {
603 dpctl_print(dpctl_p
, " (%s", dpif_port
.type
);
605 error
= netdev_open(dpif_port
.name
, dpif_port
.type
, &netdev
);
610 error
= netdev_get_config(netdev
, &config
);
612 const struct smap_node
**nodes
= smap_sort(&config
);
613 for (size_t j
= 0; j
< smap_count(&config
); j
++) {
614 const struct smap_node
*node
= nodes
[j
];
615 dpctl_print(dpctl_p
, "%c %s=%s", j
? ',' : ':',
616 node
->key
, node
->value
);
620 dpctl_print(dpctl_p
, ", could not retrieve configuration "
621 "(%s)", ovs_strerror(error
));
623 smap_destroy(&config
);
625 netdev_close(netdev
);
627 dpctl_print(dpctl_p
, ": open failed (%s)",
628 ovs_strerror(error
));
630 dpctl_print(dpctl_p
, ")");
632 dpctl_print(dpctl_p
, "\n");
634 if (dpctl_p
->print_statistics
) {
635 struct netdev_stats s
;
638 error
= netdev_open(dpif_port
.name
, dpif_port
.type
, &netdev
);
640 dpctl_print(dpctl_p
, ", open failed (%s)",
641 ovs_strerror(error
));
642 dpif_port_destroy(&dpif_port
);
645 error
= netdev_get_stats(netdev
, &s
);
647 netdev_close(netdev
);
648 print_stat(dpctl_p
, " RX packets:", s
.rx_packets
);
649 print_stat(dpctl_p
, " errors:", s
.rx_errors
);
650 print_stat(dpctl_p
, " dropped:", s
.rx_dropped
);
651 print_stat(dpctl_p
, " overruns:", s
.rx_over_errors
);
652 print_stat(dpctl_p
, " frame:", s
.rx_frame_errors
);
653 dpctl_print(dpctl_p
, "\n");
655 print_stat(dpctl_p
, " TX packets:", s
.tx_packets
);
656 print_stat(dpctl_p
, " errors:", s
.tx_errors
);
657 print_stat(dpctl_p
, " dropped:", s
.tx_dropped
);
658 print_stat(dpctl_p
, " aborted:", s
.tx_aborted_errors
);
659 print_stat(dpctl_p
, " carrier:", s
.tx_carrier_errors
);
660 dpctl_print(dpctl_p
, "\n");
662 print_stat(dpctl_p
, " collisions:", s
.collisions
);
663 dpctl_print(dpctl_p
, "\n");
665 print_stat(dpctl_p
, " RX bytes:", s
.rx_bytes
);
666 print_human_size(dpctl_p
, s
.rx_bytes
);
667 print_stat(dpctl_p
, " TX bytes:", s
.tx_bytes
);
668 print_human_size(dpctl_p
, s
.tx_bytes
);
669 dpctl_print(dpctl_p
, "\n");
671 dpctl_print(dpctl_p
, ", could not retrieve stats (%s)",
672 ovs_strerror(error
));
675 dpif_port_destroy(&dpif_port
);
681 typedef void (*dps_for_each_cb
)(struct dpif
*, struct dpctl_params
*);
684 dps_for_each(struct dpctl_params
*dpctl_p
, dps_for_each_cb cb
)
686 struct sset dpif_names
= SSET_INITIALIZER(&dpif_names
),
687 dpif_types
= SSET_INITIALIZER(&dpif_types
);
688 int error
, openerror
= 0, enumerror
= 0;
689 const char *type
, *name
;
690 bool at_least_one
= false;
692 dp_enumerate_types(&dpif_types
);
694 SSET_FOR_EACH (type
, &dpif_types
) {
695 error
= dp_enumerate_names(type
, &dpif_names
);
700 SSET_FOR_EACH (name
, &dpif_names
) {
704 error
= dpif_open(name
, type
, &dpif
);
710 dpctl_error(dpctl_p
, error
, "opening datapath %s failed",
716 sset_destroy(&dpif_names
);
717 sset_destroy(&dpif_types
);
719 /* If there has been an error while opening a datapath it should be
720 * reported. Otherwise, we want to ignore the errors generated by
721 * dp_enumerate_names() if at least one datapath has been discovered,
722 * because they're not interesting for the user. This happens, for
723 * example, if OVS is using a userspace datapath and the kernel module
728 return at_least_one
? 0 : enumerror
;
733 dpctl_show(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
735 int error
, lasterror
= 0;
738 for (i
= 1; i
< argc
; i
++) {
739 const char *name
= argv
[i
];
742 error
= parsed_dpif_open(name
, false, &dpif
);
744 show_dpif(dpif
, dpctl_p
);
747 dpctl_error(dpctl_p
, error
, "opening datapath %s failed",
753 lasterror
= dps_for_each(dpctl_p
, show_dpif
);
760 dump_cb(struct dpif
*dpif
, struct dpctl_params
*dpctl_p
)
762 dpctl_print(dpctl_p
, "%s\n", dpif_name(dpif
));
766 dpctl_dump_dps(int argc OVS_UNUSED
, const char *argv
[] OVS_UNUSED
,
767 struct dpctl_params
*dpctl_p
)
769 return dps_for_each(dpctl_p
, dump_cb
);
773 format_dpif_flow(struct ds
*ds
, const struct dpif_flow
*f
, struct hmap
*ports
,
774 struct dpctl_params
*dpctl_p
)
776 if (dpctl_p
->verbosity
&& f
->ufid_present
) {
777 odp_format_ufid(&f
->ufid
, ds
);
778 ds_put_cstr(ds
, ", ");
780 odp_flow_format(f
->key
, f
->key_len
, f
->mask
, f
->mask_len
, ports
, ds
,
782 ds_put_cstr(ds
, ", ");
784 dpif_flow_stats_format(&f
->stats
, ds
);
785 if (dpctl_p
->verbosity
&& f
->attrs
.offloaded
) {
786 ds_put_cstr(ds
, ", offloaded:yes");
788 if (dpctl_p
->verbosity
&& f
->attrs
.dp_layer
) {
789 ds_put_format(ds
, ", dp:%s", f
->attrs
.dp_layer
);
791 ds_put_cstr(ds
, ", actions:");
792 format_odp_actions(ds
, f
->actions
, f
->actions_len
, ports
);
795 static char *supported_dump_types
[] = {
801 flow_passes_type_filter(const struct dpif_flow
*f
, char *type
)
803 if (!strcmp(type
, "offloaded")) {
804 return f
->attrs
.offloaded
;
810 dpctl_get_portno_names(struct dpif
*dpif
, const struct dpctl_params
*dpctl_p
)
812 if (dpctl_p
->names
) {
813 struct hmap
*portno_names
= xmalloc(sizeof *portno_names
);
814 hmap_init(portno_names
);
816 struct dpif_port_dump port_dump
;
817 struct dpif_port dpif_port
;
818 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, dpif
) {
819 odp_portno_names_set(portno_names
, dpif_port
.port_no
,
830 dpctl_free_portno_names(struct hmap
*portno_names
)
833 odp_portno_names_destroy(portno_names
);
834 hmap_destroy(portno_names
);
840 dpctl_dump_flows(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
847 struct flow flow_filter
;
848 struct flow_wildcards wc_filter
;
850 struct dpif_flow_dump_thread
*flow_dump_thread
;
851 struct dpif_flow_dump
*flow_dump
;
853 int pmd_id
= PMD_ID_NULL
;
857 while (argc
> 1 && lastargc
!= argc
) {
859 if (!strncmp(argv
[argc
- 1], "filter=", 7) && !filter
) {
860 filter
= xstrdup(argv
[--argc
] + 7);
861 } else if (!strncmp(argv
[argc
- 1], "type=", 5) && !type
) {
862 type
= xstrdup(argv
[--argc
] + 5);
866 error
= opt_dpif_open(argc
, argv
, dpctl_p
, 2, &dpif
);
871 struct hmap
*portno_names
= dpctl_get_portno_names(dpif
, dpctl_p
);
874 struct ofputil_port_map port_map
;
875 ofputil_port_map_init(&port_map
);
877 struct dpif_port_dump port_dump
;
878 struct dpif_port dpif_port
;
879 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, dpif
) {
880 ofputil_port_map_put(&port_map
,
881 u16_to_ofp(odp_to_u32(dpif_port
.port_no
)),
884 char *err
= parse_ofp_exact_flow(&flow_filter
, &wc_filter
, NULL
,
886 ofputil_port_map_destroy(&port_map
);
888 dpctl_error(dpctl_p
, 0, "Failed to parse filter (%s)", err
);
897 for (int i
= 0; i
< ARRAY_SIZE(supported_dump_types
); i
++) {
898 if (!strcmp(supported_dump_types
[i
], type
)) {
904 dpctl_error(dpctl_p
, error
, "Failed to parse type (%s)", type
);
909 /* Make sure that these values are different. PMD_ID_NULL means that the
910 * pmd is unspecified (e.g. because the datapath doesn't have different
911 * pmd threads), while NON_PMD_CORE_ID refers to every non pmd threads
912 * in the userspace datapath */
913 BUILD_ASSERT(PMD_ID_NULL
!= NON_PMD_CORE_ID
);
916 memset(&f
, 0, sizeof f
);
917 flow_dump
= dpif_flow_dump_create(dpif
, false, (type
? type
: "dpctl"));
918 flow_dump_thread
= dpif_flow_dump_thread_create(flow_dump
);
919 while (dpif_flow_dump_next(flow_dump_thread
, &f
, 1)) {
922 struct flow_wildcards wc
;
923 struct match match
, match_filter
;
924 struct minimatch minimatch
;
926 odp_flow_key_to_flow(f
.key
, f
.key_len
, &flow
);
927 odp_flow_key_to_mask(f
.mask
, f
.mask_len
, &wc
, &flow
);
928 match_init(&match
, &flow
, &wc
);
930 match_init(&match_filter
, &flow_filter
, &wc
);
931 match_init(&match_filter
, &match_filter
.flow
, &wc_filter
);
932 minimatch_init(&minimatch
, &match_filter
);
934 if (!minimatch_matches_flow(&minimatch
, &match
.flow
)) {
935 minimatch_destroy(&minimatch
);
938 minimatch_destroy(&minimatch
);
941 /* If 'pmd_id' is specified, overlapping flows could be dumped from
942 * different pmd threads. So, separates dumps from different pmds
943 * by printing a title line. */
944 if (pmd_id
!= f
.pmd_id
) {
945 if (f
.pmd_id
== NON_PMD_CORE_ID
) {
946 ds_put_format(&ds
, "flow-dump from non-dpdk interfaces:\n");
948 ds_put_format(&ds
, "flow-dump from pmd on cpu core: %d\n",
953 if (!type
|| flow_passes_type_filter(&f
, type
)) {
954 format_dpif_flow(&ds
, &f
, portno_names
, dpctl_p
);
955 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&ds
));
958 dpif_flow_dump_thread_destroy(flow_dump_thread
);
959 error
= dpif_flow_dump_destroy(flow_dump
);
962 dpctl_error(dpctl_p
, error
, "Failed to dump flows from datapath");
967 dpctl_free_portno_names(portno_names
);
976 dpctl_put_flow(int argc
, const char *argv
[], enum dpif_flow_put_flags flags
,
977 struct dpctl_params
*dpctl_p
)
979 const char *key_s
= argv
[argc
- 2];
980 const char *actions_s
= argv
[argc
- 1];
981 struct dpif_flow_stats stats
;
982 struct dpif_port dpif_port
;
983 struct dpif_port_dump port_dump
;
984 struct ofpbuf actions
;
990 struct simap port_names
;
993 error
= opt_dpif_open(argc
, argv
, dpctl_p
, 4, &dpif
);
998 ufid_present
= false;
999 n
= odp_ufid_from_string(key_s
, &ufid
);
1001 dpctl_error(dpctl_p
, -n
, "parsing flow ufid");
1005 ufid_present
= true;
1008 simap_init(&port_names
);
1009 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, dpif
) {
1010 simap_put(&port_names
, dpif_port
.name
, odp_to_u32(dpif_port
.port_no
));
1013 ofpbuf_init(&key
, 0);
1014 ofpbuf_init(&mask
, 0);
1015 error
= odp_flow_from_string(key_s
, &port_names
, &key
, &mask
);
1016 simap_destroy(&port_names
);
1018 dpctl_error(dpctl_p
, error
, "parsing flow key");
1019 goto out_freekeymask
;
1022 ofpbuf_init(&actions
, 0);
1023 error
= odp_actions_from_string(actions_s
, NULL
, &actions
);
1025 dpctl_error(dpctl_p
, error
, "parsing actions");
1026 goto out_freeactions
;
1029 /* The flow will be added on all pmds currently in the datapath. */
1030 error
= dpif_flow_put(dpif
, flags
,
1032 mask
.size
== 0 ? NULL
: mask
.data
,
1033 mask
.size
, actions
.data
,
1034 actions
.size
, ufid_present
? &ufid
: NULL
,
1036 dpctl_p
->print_statistics
? &stats
: NULL
);
1039 dpctl_error(dpctl_p
, error
, "updating flow table");
1040 goto out_freeactions
;
1043 if (dpctl_p
->print_statistics
) {
1047 dpif_flow_stats_format(&stats
, &s
);
1048 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1053 ofpbuf_uninit(&actions
);
1055 ofpbuf_uninit(&mask
);
1056 ofpbuf_uninit(&key
);
1062 dpctl_add_flow(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1064 return dpctl_put_flow(argc
, argv
, DPIF_FP_CREATE
, dpctl_p
);
1068 dpctl_mod_flow(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1070 enum dpif_flow_put_flags flags
;
1072 flags
= DPIF_FP_MODIFY
;
1073 if (dpctl_p
->may_create
) {
1074 flags
|= DPIF_FP_CREATE
;
1076 if (dpctl_p
->zero_statistics
) {
1077 flags
|= DPIF_FP_ZERO_STATS
;
1080 return dpctl_put_flow(argc
, argv
, flags
, dpctl_p
);
1084 dpctl_get_flow(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1086 const char *key_s
= argv
[argc
- 1];
1087 struct dpif_flow flow
;
1091 uint64_t stub
[DPIF_FLOW_BUFSIZE
/ 8];
1095 error
= opt_dpif_open(argc
, argv
, dpctl_p
, 3, &dpif
);
1100 ofpbuf_use_stub(&buf
, &stub
, sizeof stub
);
1102 struct hmap
*portno_names
= dpctl_get_portno_names(dpif
, dpctl_p
);
1104 n
= odp_ufid_from_string(key_s
, &ufid
);
1106 dpctl_error(dpctl_p
, -n
, "parsing flow ufid");
1110 /* In case of PMD will be returned flow from first PMD thread with match. */
1111 error
= dpif_flow_get(dpif
, NULL
, 0, &ufid
, PMD_ID_NULL
, &buf
, &flow
);
1113 dpctl_error(dpctl_p
, error
, "getting flow");
1118 format_dpif_flow(&ds
, &flow
, portno_names
, dpctl_p
);
1119 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&ds
));
1123 dpctl_free_portno_names(portno_names
);
1124 ofpbuf_uninit(&buf
);
1130 dpctl_del_flow(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1132 const char *key_s
= argv
[argc
- 1];
1133 struct dpif_flow_stats stats
;
1134 struct dpif_port dpif_port
;
1135 struct dpif_port_dump port_dump
;
1137 struct ofpbuf mask
; /* To be ignored. */
1141 struct simap port_names
;
1144 error
= opt_dpif_open(argc
, argv
, dpctl_p
, 3, &dpif
);
1149 ufid_present
= false;
1150 n
= odp_ufid_from_string(key_s
, &ufid
);
1152 dpctl_error(dpctl_p
, -n
, "parsing flow ufid");
1156 ufid_present
= true;
1159 simap_init(&port_names
);
1160 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, dpif
) {
1161 simap_put(&port_names
, dpif_port
.name
, odp_to_u32(dpif_port
.port_no
));
1164 ofpbuf_init(&key
, 0);
1165 ofpbuf_init(&mask
, 0);
1167 error
= odp_flow_from_string(key_s
, &port_names
, &key
, &mask
);
1169 dpctl_error(dpctl_p
, error
, "parsing flow key");
1173 /* The flow will be deleted from all pmds currently in the datapath. */
1174 error
= dpif_flow_del(dpif
, key
.data
, key
.size
,
1175 ufid_present
? &ufid
: NULL
, PMD_ID_NULL
,
1176 dpctl_p
->print_statistics
? &stats
: NULL
);
1179 dpctl_error(dpctl_p
, error
, "deleting flow");
1180 if (error
== ENOENT
&& !ufid_present
) {
1184 ds_put_format(&s
, "Perhaps you need to specify a UFID?");
1185 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1191 if (dpctl_p
->print_statistics
) {
1195 dpif_flow_stats_format(&stats
, &s
);
1196 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1201 ofpbuf_uninit(&mask
);
1202 ofpbuf_uninit(&key
);
1203 simap_destroy(&port_names
);
1209 dpctl_del_flows(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1213 int error
= opt_dpif_open(argc
, argv
, dpctl_p
, 2, &dpif
);
1218 error
= dpif_flow_flush(dpif
);
1220 dpctl_error(dpctl_p
, error
, "deleting all flows");
1227 dpctl_help(int argc OVS_UNUSED
, const char *argv
[] OVS_UNUSED
,
1228 struct dpctl_params
*dpctl_p
)
1230 if (dpctl_p
->usage
) {
1231 dpctl_p
->usage(dpctl_p
->aux
);
1238 dpctl_list_commands(int argc OVS_UNUSED
, const char *argv
[] OVS_UNUSED
,
1239 struct dpctl_params
*dpctl_p
)
1241 struct ds ds
= DS_EMPTY_INITIALIZER
;
1242 const struct dpctl_command
*commands
= get_all_dpctl_commands();
1244 ds_put_cstr(&ds
, "The available commands are:\n");
1245 for (; commands
->name
; commands
++) {
1246 const struct dpctl_command
*c
= commands
;
1248 ds_put_format(&ds
, " %s%-23s %s\n", dpctl_p
->is_appctl
? "dpctl/" : "",
1251 dpctl_puts(dpctl_p
, false, ds
.string
);
1259 dpctl_dump_conntrack(int argc
, const char *argv
[],
1260 struct dpctl_params
*dpctl_p
)
1262 struct ct_dpif_dump_state
*dump
;
1263 struct ct_dpif_entry cte
;
1264 uint16_t zone
, *pzone
= NULL
;
1269 if (argc
> 1 && ovs_scan(argv
[argc
- 1], "zone=%"SCNu16
, &zone
)) {
1274 error
= opt_dpif_open(argc
, argv
, dpctl_p
, 2, &dpif
);
1279 error
= ct_dpif_dump_start(dpif
, &dump
, pzone
, &tot_bkts
);
1281 dpctl_error(dpctl_p
, error
, "starting conntrack dump");
1286 while (!(error
= ct_dpif_dump_next(dump
, &cte
))) {
1287 struct ds s
= DS_EMPTY_INITIALIZER
;
1289 ct_dpif_format_entry(&cte
, &s
, dpctl_p
->verbosity
,
1290 dpctl_p
->print_statistics
);
1291 ct_dpif_entry_uninit(&cte
);
1293 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1297 /* Any CT entry was dumped with no issue. */
1300 dpctl_error(dpctl_p
, error
, "dumping conntrack entry");
1303 ct_dpif_dump_done(dump
);
1309 dpctl_flush_conntrack(int argc
, const char *argv
[],
1310 struct dpctl_params
*dpctl_p
)
1313 struct ct_dpif_tuple tuple
, *ptuple
= NULL
;
1314 struct ds ds
= DS_EMPTY_INITIALIZER
;
1315 uint16_t zone
, *pzone
= NULL
;
1318 bool got_dpif
= false;
1320 /* Parse datapath name. It is not a mandatory parameter for this command.
1321 * If it is not specified, we retrieve it from the current setup,
1322 * assuming only one exists. */
1324 error
= parsed_dpif_open(argv
[i
], false, &dpif
);
1328 } else if (argc
== 4) {
1329 dpctl_error(dpctl_p
, error
, "invalid datapath");
1334 name
= get_one_dp(dpctl_p
);
1338 error
= parsed_dpif_open(name
, false, &dpif
);
1341 dpctl_error(dpctl_p
, error
, "opening datapath");
1347 if (argc
> i
&& ovs_scan(argv
[i
], "zone=%"SCNu16
, &zone
)) {
1351 /* Report error if there are more than one unparsed argument. */
1353 ds_put_cstr(&ds
, "invalid zone");
1358 /* Parse ct tuple */
1359 if (argc
> i
&& ct_dpif_parse_tuple(&tuple
, argv
[i
], &ds
)) {
1363 /* Report error if there is an unparsed argument. */
1369 error
= ct_dpif_flush(dpif
, pzone
, ptuple
);
1374 ds_put_cstr(&ds
, "failed to flush conntrack");
1378 dpctl_error(dpctl_p
, error
, "%s", ds_cstr(&ds
));
1385 dpctl_ct_stats_show(int argc
, const char *argv
[],
1386 struct dpctl_params
*dpctl_p
)
1389 struct ct_dpif_dump_state
*dump
;
1390 struct ct_dpif_entry cte
;
1391 uint16_t zone
, *pzone
= NULL
;
1395 int proto_stats
[CT_STATS_MAX
];
1396 int tcp_conn_per_states
[CT_DPIF_TCPS_MAX_NUM
];
1399 bool verbose
= dpctl_p
->verbosity
;
1401 while (argc
> 1 && lastargc
!= argc
) {
1403 if (!strncmp(argv
[argc
- 1], "verbose", 7)) {
1404 /* Support "verbose" argument for backwards compatibility. */
1407 } else if (!strncmp(argv
[argc
- 1], "zone=", 5)) {
1408 if (ovs_scan(argv
[argc
- 1], "zone=%"SCNu16
, &zone
)) {
1415 error
= opt_dpif_open(argc
, argv
, dpctl_p
, 2, &dpif
);
1420 memset(proto_stats
, 0, sizeof(proto_stats
));
1421 memset(tcp_conn_per_states
, 0, sizeof(tcp_conn_per_states
));
1422 error
= ct_dpif_dump_start(dpif
, &dump
, pzone
, &tot_bkts
);
1424 dpctl_error(dpctl_p
, error
, "starting conntrack dump");
1430 while (!(error
= ct_dpif_dump_next(dump
, &cte
))) {
1431 ct_dpif_entry_uninit(&cte
);
1433 switch (cte
.tuple_orig
.ip_proto
) {
1435 proto_stats
[CT_STATS_ICMP
]++;
1437 case IPPROTO_ICMPV6
:
1438 proto_stats
[CT_STATS_ICMPV6
]++;
1441 proto_stats
[CT_STATS_TCP
]++;
1443 /* We keep two separate tcp states, but we print just one. The
1444 * Linux kernel connection tracker internally keeps only one state,
1445 * so 'state_orig' and 'state_reply', will be the same. */
1446 tcp_state
= MAX(cte
.protoinfo
.tcp
.state_orig
,
1447 cte
.protoinfo
.tcp
.state_reply
);
1448 tcp_state
= ct_dpif_coalesce_tcp_state(tcp_state
);
1449 tcp_conn_per_states
[tcp_state
]++;
1452 proto_stats
[CT_STATS_UDP
]++;
1455 proto_stats
[CT_STATS_SCTP
]++;
1457 case IPPROTO_UDPLITE
:
1458 proto_stats
[CT_STATS_UDPLITE
]++;
1461 proto_stats
[CT_STATS_DCCP
]++;
1464 proto_stats
[CT_STATS_IGMP
]++;
1467 proto_stats
[CT_STATS_OTHER
]++;
1472 /* All CT entries were dumped with no issue. */
1475 dpctl_error(dpctl_p
, error
, "dumping conntrack entry");
1476 /* Fall through to show any other info we collected. */
1479 dpctl_print(dpctl_p
, "Connections Stats:\n Total: %d\n", tot_conn
);
1480 if (proto_stats
[CT_STATS_TCP
]) {
1481 dpctl_print(dpctl_p
, " TCP: %d\n", proto_stats
[CT_STATS_TCP
]);
1483 dpctl_print(dpctl_p
, " Conn per TCP states:\n");
1484 for (int i
= 0; i
< CT_DPIF_TCPS_MAX_NUM
; i
++) {
1485 if (tcp_conn_per_states
[i
]) {
1486 struct ds s
= DS_EMPTY_INITIALIZER
;
1487 ct_dpif_format_tcp_stat(&s
, i
, tcp_conn_per_states
[i
]);
1488 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1494 if (proto_stats
[CT_STATS_UDP
]) {
1495 dpctl_print(dpctl_p
, " UDP: %d\n", proto_stats
[CT_STATS_UDP
]);
1497 if (proto_stats
[CT_STATS_UDPLITE
]) {
1498 dpctl_print(dpctl_p
, " UDPLITE: %d\n", proto_stats
[CT_STATS_UDPLITE
]);
1500 if (proto_stats
[CT_STATS_SCTP
]) {
1501 dpctl_print(dpctl_p
, " SCTP: %d\n", proto_stats
[CT_STATS_SCTP
]);
1503 if (proto_stats
[CT_STATS_ICMP
]) {
1504 dpctl_print(dpctl_p
, " ICMP: %d\n", proto_stats
[CT_STATS_ICMP
]);
1506 if (proto_stats
[CT_STATS_DCCP
]) {
1507 dpctl_print(dpctl_p
, " DCCP: %d\n", proto_stats
[CT_STATS_DCCP
]);
1509 if (proto_stats
[CT_STATS_IGMP
]) {
1510 dpctl_print(dpctl_p
, " IGMP: %d\n", proto_stats
[CT_STATS_IGMP
]);
1512 if (proto_stats
[CT_STATS_OTHER
]) {
1513 dpctl_print(dpctl_p
, " Other: %d\n", proto_stats
[CT_STATS_OTHER
]);
1516 ct_dpif_dump_done(dump
);
1521 #define CT_BKTS_GT "gt="
1523 dpctl_ct_bkts(int argc
, const char *argv
[],
1524 struct dpctl_params
*dpctl_p
)
1527 struct ct_dpif_dump_state
*dump
;
1528 struct ct_dpif_entry cte
;
1529 uint16_t gt
= 0; /* Threshold: display value when greater than gt. */
1530 uint16_t *pzone
= NULL
;
1534 if (argc
> 1 && !strncmp(argv
[argc
- 1], CT_BKTS_GT
, strlen(CT_BKTS_GT
))) {
1535 if (ovs_scan(argv
[argc
- 1], CT_BKTS_GT
"%"SCNu16
, >
)) {
1540 error
= opt_dpif_open(argc
, argv
, dpctl_p
, 2, &dpif
);
1545 error
= ct_dpif_dump_start(dpif
, &dump
, pzone
, &tot_bkts
);
1547 dpctl_error(dpctl_p
, error
, "starting conntrack dump");
1551 if (tot_bkts
== -1) {
1552 /* Command not available when called by kernel OvS. */
1553 dpctl_print(dpctl_p
,
1554 "Command is available for UserSpace ConnTracker only.\n");
1555 ct_dpif_dump_done(dump
);
1560 dpctl_print(dpctl_p
, "Total Buckets: %d\n", tot_bkts
);
1563 uint32_t *conn_per_bkts
= xzalloc(tot_bkts
* sizeof(uint32_t));
1565 while (!(error
= ct_dpif_dump_next(dump
, &cte
))) {
1566 ct_dpif_entry_uninit(&cte
);
1569 if (cte
.bkt
< tot_bkts
) {
1570 conn_per_bkts
[cte
.bkt
]++;
1572 dpctl_print(dpctl_p
, "Bucket nr out of range: %d >= %d\n",
1578 /* All CT entries were dumped with no issue. */
1581 dpctl_error(dpctl_p
, error
, "dumping conntrack entry");
1582 /* Fall through and display all the collected info. */
1585 dpctl_print(dpctl_p
, "Current Connections: %d\n", tot_conn
);
1586 dpctl_print(dpctl_p
, "\n");
1587 if (tot_bkts
&& tot_conn
) {
1588 dpctl_print(dpctl_p
, "+-----------+"
1589 "-----------------------------------------+\n");
1590 dpctl_print(dpctl_p
, "| Buckets |"
1591 " Connections per Buckets |\n");
1592 dpctl_print(dpctl_p
, "+-----------+"
1593 "-----------------------------------------+");
1594 #define NUM_BKTS_DIPLAYED_PER_ROW 8
1595 for (int i
= 0; i
< tot_bkts
; i
++) {
1596 if (i
% NUM_BKTS_DIPLAYED_PER_ROW
== 0) {
1597 dpctl_print(dpctl_p
, "\n %3d..%3d | ",
1598 i
, i
+ NUM_BKTS_DIPLAYED_PER_ROW
- 1);
1600 if (conn_per_bkts
[i
] > gt
) {
1601 dpctl_print(dpctl_p
, "%5d", conn_per_bkts
[i
]);
1603 dpctl_print(dpctl_p
, "%5s", ".");
1606 dpctl_print(dpctl_p
, "\n\n");
1609 ct_dpif_dump_done(dump
);
1611 free(conn_per_bkts
);
1616 dpctl_ct_set_maxconns(int argc
, const char *argv
[],
1617 struct dpctl_params
*dpctl_p
)
1620 int error
= opt_dpif_open(argc
, argv
, dpctl_p
, 3, &dpif
);
1623 if (ovs_scan(argv
[argc
- 1], "%"SCNu32
, &maxconns
)) {
1624 error
= ct_dpif_set_maxconns(dpif
, maxconns
);
1627 dpctl_print(dpctl_p
, "setting maxconns successful");
1629 dpctl_error(dpctl_p
, error
, "ct set maxconns failed");
1633 dpctl_error(dpctl_p
, error
, "maxconns missing or malformed");
1642 dpctl_ct_get_maxconns(int argc
, const char *argv
[],
1643 struct dpctl_params
*dpctl_p
)
1646 int error
= opt_dpif_open(argc
, argv
, dpctl_p
, 2, &dpif
);
1649 error
= ct_dpif_get_maxconns(dpif
, &maxconns
);
1652 dpctl_print(dpctl_p
, "%u\n", maxconns
);
1654 dpctl_error(dpctl_p
, error
, "maxconns could not be retrieved");
1663 dpctl_ct_get_nconns(int argc
, const char *argv
[],
1664 struct dpctl_params
*dpctl_p
)
1667 int error
= opt_dpif_open(argc
, argv
, dpctl_p
, 2, &dpif
);
1670 error
= ct_dpif_get_nconns(dpif
, &nconns
);
1673 dpctl_print(dpctl_p
, "%u\n", nconns
);
1675 dpctl_error(dpctl_p
, error
, "nconns could not be retrieved");
1683 /* Undocumented commands for unit testing. */
1686 dpctl_parse_actions(int argc
, const char *argv
[], struct dpctl_params
* dpctl_p
)
1690 for (i
= 1; i
< argc
; i
++) {
1691 struct ofpbuf actions
;
1694 ofpbuf_init(&actions
, 0);
1695 error
= odp_actions_from_string(argv
[i
], NULL
, &actions
);
1698 ofpbuf_uninit(&actions
);
1699 dpctl_error(dpctl_p
, error
, "odp_actions_from_string");
1704 format_odp_actions(&s
, actions
.data
, actions
.size
, NULL
);
1705 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1708 ofpbuf_uninit(&actions
);
1714 struct actions_for_flow
{
1715 struct hmap_node hmap_node
;
1717 struct ofpbuf actions
;
1720 static struct actions_for_flow
*
1721 get_actions_for_flow(struct hmap
*actions_per_flow
, const struct flow
*flow
)
1723 uint32_t hash
= flow_hash(flow
, 0);
1724 struct actions_for_flow
*af
;
1726 HMAP_FOR_EACH_WITH_HASH (af
, hmap_node
, hash
, actions_per_flow
) {
1727 if (flow_equal(&af
->flow
, flow
)) {
1732 af
= xmalloc(sizeof *af
);
1734 ofpbuf_init(&af
->actions
, 0);
1735 hmap_insert(actions_per_flow
, &af
->hmap_node
, hash
);
1740 compare_actions_for_flow(const void *a_
, const void *b_
)
1742 struct actions_for_flow
*const *a
= a_
;
1743 struct actions_for_flow
*const *b
= b_
;
1745 return flow_compare_3way(&(*a
)->flow
, &(*b
)->flow
);
1749 compare_output_actions(const void *a_
, const void *b_
)
1751 const struct nlattr
*a
= a_
;
1752 const struct nlattr
*b
= b_
;
1753 uint32_t a_port
= nl_attr_get_u32(a
);
1754 uint32_t b_port
= nl_attr_get_u32(b
);
1756 return a_port
< b_port
? -1 : a_port
> b_port
;
1760 sort_output_actions__(struct nlattr
*first
, struct nlattr
*end
)
1762 size_t bytes
= (uint8_t *) end
- (uint8_t *) first
;
1763 size_t n
= bytes
/ NL_A_U32_SIZE
;
1765 ovs_assert(bytes
% NL_A_U32_SIZE
== 0);
1766 qsort(first
, n
, NL_A_U32_SIZE
, compare_output_actions
);
1770 sort_output_actions(struct nlattr
*actions
, size_t length
)
1772 struct nlattr
*first_output
= NULL
;
1776 NL_ATTR_FOR_EACH (a
, left
, actions
, length
) {
1777 if (nl_attr_type(a
) == OVS_ACTION_ATTR_OUTPUT
) {
1778 if (!first_output
) {
1783 sort_output_actions__(first_output
, a
);
1784 first_output
= NULL
;
1789 uint8_t *end
= (uint8_t *) actions
+ length
;
1790 sort_output_actions__(first_output
,
1791 ALIGNED_CAST(struct nlattr
*, end
));
1795 /* usage: "ovs-dpctl normalize-actions FLOW ACTIONS" where FLOW and ACTIONS
1796 * have the syntax used by "ovs-dpctl dump-flows".
1798 * This command prints ACTIONS in a format that shows what happens for each
1799 * VLAN, independent of the order of the ACTIONS. For example, there is more
1800 * than one way to output a packet on VLANs 9 and 11, but this command will
1801 * print the same output for any form.
1803 * The idea here generalizes beyond VLANs (e.g. to setting other fields) but
1804 * so far the implementation only covers VLANs. */
1806 dpctl_normalize_actions(int argc
, const char *argv
[],
1807 struct dpctl_params
*dpctl_p
)
1809 struct simap port_names
;
1810 struct ofpbuf keybuf
;
1812 struct ofpbuf odp_actions
;
1813 struct hmap actions_per_flow
;
1814 struct actions_for_flow
**afs
;
1815 struct actions_for_flow
*af
;
1825 simap_init(&port_names
);
1826 for (i
= 3; i
< argc
; i
++) {
1830 if (ovs_scan(argv
[i
], "%15[^=]=%d", name
, &number
)) {
1831 uintptr_t n
= number
;
1832 simap_put(&port_names
, name
, n
);
1834 dpctl_error(dpctl_p
, 0, "%s: expected NAME=NUMBER", argv
[i
]);
1840 /* Parse flow key. */
1841 ofpbuf_init(&keybuf
, 0);
1842 error
= odp_flow_from_string(argv
[1], &port_names
, &keybuf
, NULL
);
1844 dpctl_error(dpctl_p
, error
, "odp_flow_key_from_string");
1845 goto out_freekeybuf
;
1849 odp_flow_format(keybuf
.data
, keybuf
.size
, NULL
, 0, NULL
,
1850 &s
, dpctl_p
->verbosity
);
1851 dpctl_print(dpctl_p
, "input flow: %s\n", ds_cstr(&s
));
1853 error
= odp_flow_key_to_flow(keybuf
.data
, keybuf
.size
, &flow
);
1855 dpctl_error(dpctl_p
, error
, "odp_flow_key_to_flow");
1856 goto out_freekeybuf
;
1859 /* Parse actions. */
1860 ofpbuf_init(&odp_actions
, 0);
1861 error
= odp_actions_from_string(argv
[2], &port_names
, &odp_actions
);
1863 dpctl_error(dpctl_p
, error
, "odp_actions_from_string");
1864 goto out_freeactions
;
1867 if (dpctl_p
->verbosity
) {
1869 format_odp_actions(&s
, odp_actions
.data
, odp_actions
.size
, NULL
);
1870 dpctl_print(dpctl_p
, "input actions: %s\n", ds_cstr(&s
));
1873 hmap_init(&actions_per_flow
);
1874 NL_ATTR_FOR_EACH (a
, left
, odp_actions
.data
, odp_actions
.size
) {
1875 const struct ovs_action_push_vlan
*push
;
1876 switch(nl_attr_type(a
)) {
1877 case OVS_ACTION_ATTR_POP_VLAN
:
1878 flow_pop_vlan(&flow
, NULL
);
1881 case OVS_ACTION_ATTR_PUSH_VLAN
:
1882 flow_push_vlan_uninit(&flow
, NULL
);
1883 push
= nl_attr_get_unspec(a
, sizeof *push
);
1884 flow
.vlans
[0].tpid
= push
->vlan_tpid
;
1885 flow
.vlans
[0].tci
= push
->vlan_tci
;
1889 af
= get_actions_for_flow(&actions_per_flow
, &flow
);
1890 nl_msg_put_unspec(&af
->actions
, nl_attr_type(a
),
1891 nl_attr_get(a
), nl_attr_get_size(a
));
1894 n_afs
= hmap_count(&actions_per_flow
);
1895 afs
= xmalloc(n_afs
* sizeof *afs
);
1897 HMAP_FOR_EACH (af
, hmap_node
, &actions_per_flow
) {
1901 ovs_assert(i
== n_afs
);
1902 hmap_destroy(&actions_per_flow
);
1904 qsort(afs
, n_afs
, sizeof *afs
, compare_actions_for_flow
);
1906 for (i
= 0; i
< n_afs
; i
++) {
1908 sort_output_actions(af
->actions
.data
, af
->actions
.size
);
1910 for (encaps
= 0; encaps
< FLOW_MAX_VLAN_HEADERS
; encaps
++) {
1911 union flow_vlan_hdr
*vlan
= &af
->flow
.vlans
[encaps
];
1912 if (vlan
->tci
!= htons(0)) {
1913 dpctl_print(dpctl_p
, "vlan(");
1914 if (vlan
->tpid
!= htons(ETH_TYPE_VLAN
)) {
1915 dpctl_print(dpctl_p
, "tpid=0x%04"PRIx16
",", vlan
->tpid
);
1917 dpctl_print(dpctl_p
, "vid=%"PRIu16
",pcp=%d): ",
1918 vlan_tci_to_vid(vlan
->tci
),
1919 vlan_tci_to_pcp(vlan
->tci
));
1922 dpctl_print(dpctl_p
, "no vlan: ");
1928 if (eth_type_mpls(af
->flow
.dl_type
)) {
1929 dpctl_print(dpctl_p
, "mpls(label=%"PRIu32
",tc=%d,ttl=%d): ",
1930 mpls_lse_to_label(af
->flow
.mpls_lse
[0]),
1931 mpls_lse_to_tc(af
->flow
.mpls_lse
[0]),
1932 mpls_lse_to_ttl(af
->flow
.mpls_lse
[0]));
1934 dpctl_print(dpctl_p
, "no mpls: ");
1938 format_odp_actions(&s
, af
->actions
.data
, af
->actions
.size
, NULL
);
1939 dpctl_puts(dpctl_p
, false, ds_cstr(&s
));
1941 ofpbuf_uninit(&af
->actions
);
1948 ofpbuf_uninit(&odp_actions
);
1950 ofpbuf_uninit(&keybuf
);
1952 simap_destroy(&port_names
);
1958 static const struct dpctl_command all_commands
[] = {
1959 { "add-dp", "dp [iface...]", 1, INT_MAX
, dpctl_add_dp
, DP_RW
},
1960 { "del-dp", "dp", 1, 1, dpctl_del_dp
, DP_RW
},
1961 { "add-if", "dp iface...", 2, INT_MAX
, dpctl_add_if
, DP_RW
},
1962 { "del-if", "dp iface...", 2, INT_MAX
, dpctl_del_if
, DP_RW
},
1963 { "set-if", "dp iface...", 2, INT_MAX
, dpctl_set_if
, DP_RW
},
1964 { "dump-dps", "", 0, 0, dpctl_dump_dps
, DP_RO
},
1965 { "show", "[dp...]", 0, INT_MAX
, dpctl_show
, DP_RO
},
1966 { "dump-flows", "[dp] [filter=..] [type=..]",
1967 0, 3, dpctl_dump_flows
, DP_RO
},
1968 { "add-flow", "[dp] flow actions", 2, 3, dpctl_add_flow
, DP_RW
},
1969 { "mod-flow", "[dp] flow actions", 2, 3, dpctl_mod_flow
, DP_RW
},
1970 { "get-flow", "[dp] ufid", 1, 2, dpctl_get_flow
, DP_RO
},
1971 { "del-flow", "[dp] flow", 1, 2, dpctl_del_flow
, DP_RW
},
1972 { "del-flows", "[dp]", 0, 1, dpctl_del_flows
, DP_RW
},
1973 { "dump-conntrack", "[dp] [zone=N]", 0, 2, dpctl_dump_conntrack
, DP_RO
},
1974 { "flush-conntrack", "[dp] [zone=N] [ct-tuple]", 0, 3,
1975 dpctl_flush_conntrack
, DP_RW
},
1976 { "ct-stats-show", "[dp] [zone=N]",
1977 0, 3, dpctl_ct_stats_show
, DP_RO
},
1978 { "ct-bkts", "[dp] [gt=N]", 0, 2, dpctl_ct_bkts
, DP_RO
},
1979 { "ct-set-maxconns", "[dp] maxconns", 1, 2, dpctl_ct_set_maxconns
, DP_RW
},
1980 { "ct-get-maxconns", "[dp]", 0, 1, dpctl_ct_get_maxconns
, DP_RO
},
1981 { "ct-get-nconns", "[dp]", 0, 1, dpctl_ct_get_nconns
, DP_RO
},
1982 { "help", "", 0, INT_MAX
, dpctl_help
, DP_RO
},
1983 { "list-commands", "", 0, INT_MAX
, dpctl_list_commands
, DP_RO
},
1985 /* Undocumented commands for testing. */
1986 { "parse-actions", "actions", 1, INT_MAX
, dpctl_parse_actions
, DP_RO
},
1987 { "normalize-actions", "actions",
1988 2, INT_MAX
, dpctl_normalize_actions
, DP_RO
},
1990 { NULL
, NULL
, 0, 0, NULL
, DP_RO
},
1993 static const struct dpctl_command
*get_all_dpctl_commands(void)
1995 return all_commands
;
1998 /* Runs the command designated by argv[0] within the command table specified by
1999 * 'commands', which must be terminated by a command whose 'name' member is a
2002 dpctl_run_command(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
2004 const struct dpctl_command
*p
;
2006 dpctl_error(dpctl_p
, 0, "missing command name; use --help for help");
2010 for (p
= all_commands
; p
->name
!= NULL
; p
++) {
2011 if (!strcmp(p
->name
, argv
[0])) {
2012 int n_arg
= argc
- 1;
2013 if (n_arg
< p
->min_args
) {
2014 dpctl_error(dpctl_p
, 0,
2015 "'%s' command requires at least %d arguments",
2016 p
->name
, p
->min_args
);
2018 } else if (n_arg
> p
->max_args
) {
2019 dpctl_error(dpctl_p
, 0,
2020 "'%s' command takes at most %d arguments",
2021 p
->name
, p
->max_args
);
2024 if (p
->mode
== DP_RW
&& dpctl_p
->read_only
) {
2025 dpctl_error(dpctl_p
, 0,
2026 "'%s' command does not work in read only mode",
2030 return p
->handler(argc
, argv
, dpctl_p
);
2035 dpctl_error(dpctl_p
, 0, "unknown command '%s'; use --help for help",
2041 dpctl_unixctl_print(void *userdata
, bool error OVS_UNUSED
, const char *msg
)
2043 struct ds
*ds
= userdata
;
2044 ds_put_cstr(ds
, msg
);
2048 dpctl_unixctl_handler(struct unixctl_conn
*conn
, int argc
, const char *argv
[],
2051 struct ds ds
= DS_EMPTY_INITIALIZER
;
2054 struct dpctl_params dpctl_p
= {
2056 .output
= dpctl_unixctl_print
,
2060 /* Parse options (like getopt). Unfortunately it does
2061 * not seem a good idea to call getopt_long() here, since it uses global
2063 bool set_names
= false;
2064 while (argc
> 1 && !error
) {
2065 const char *arg
= argv
[1];
2066 if (!strncmp(arg
, "--", 2)) {
2068 if (!strcmp(arg
, "--statistics")) {
2069 dpctl_p
.print_statistics
= true;
2070 } else if (!strcmp(arg
, "--clear")) {
2071 dpctl_p
.zero_statistics
= true;
2072 } else if (!strcmp(arg
, "--may-create")) {
2073 dpctl_p
.may_create
= true;
2074 } else if (!strcmp(arg
, "--more")) {
2075 dpctl_p
.verbosity
++;
2076 } else if (!strcmp(arg
, "--names")) {
2077 dpctl_p
.names
= true;
2079 } else if (!strcmp(arg
, "--no-names")) {
2080 dpctl_p
.names
= false;
2083 ds_put_format(&ds
, "Unrecognized option %s", argv
[1]);
2086 } else if (arg
[0] == '-' && arg
[1] != '\0') {
2087 /* Short option[s] */
2088 const char *opt
= &arg
[1];
2090 while (*opt
&& !error
) {
2093 dpctl_p
.verbosity
++;
2096 dpctl_p
.print_statistics
= true;
2099 ds_put_format(&ds
, "Unrecognized option -%c", *opt
);
2106 /* Doesn't start with -, not an option */
2117 dpctl_p
.names
= dpctl_p
.verbosity
> 0;
2119 VLOG_INFO("set_names=%d verbosity=%d names=%d", set_names
,
2120 dpctl_p
.verbosity
, dpctl_p
.names
);
2123 dpctl_command_handler
*handler
= (dpctl_command_handler
*) aux
;
2124 error
= handler(argc
, argv
, &dpctl_p
) != 0;
2128 unixctl_command_reply_error(conn
, ds_cstr(&ds
));
2130 unixctl_command_reply(conn
, ds_cstr(&ds
));
2137 dpctl_unixctl_register(void)
2139 const struct dpctl_command
*p
;
2141 for (p
= all_commands
; p
->name
!= NULL
; p
++) {
2142 if (strcmp(p
->name
, "help")) {
2143 char *cmd_name
= xasprintf("dpctl/%s", p
->name
);
2144 unixctl_command_register(cmd_name
,
2148 dpctl_unixctl_handler
,