2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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>
21 #include <sys/socket.h>
23 #include <netinet/in.h>
29 #include "command-line.h"
35 #include "openvswitch/dynamic-string.h"
37 #include "openvswitch/match.h"
39 #include "netdev-dpdk.h"
42 #include "openvswitch/ofpbuf.h"
45 #include "openvswitch/shash.h"
52 #include "openvswitch/ofp-parse.h"
54 typedef int dpctl_command_handler(int argc
, const char *argv
[],
55 struct dpctl_params
*);
56 struct dpctl_command
{
61 dpctl_command_handler
*handler
;
62 enum { DP_RO
, DP_RW
} mode
;
64 static const struct dpctl_command
*get_all_dpctl_commands(void);
65 static void dpctl_print(struct dpctl_params
*dpctl_p
, const char *fmt
, ...)
66 OVS_PRINTF_FORMAT(2, 3);
67 static void dpctl_error(struct dpctl_params
* dpctl_p
, int err_no
,
69 OVS_PRINTF_FORMAT(3, 4);
72 dpctl_puts(struct dpctl_params
*dpctl_p
, bool error
, const char *string
)
74 dpctl_p
->output(dpctl_p
->aux
, error
, string
);
78 dpctl_print(struct dpctl_params
*dpctl_p
, const char *fmt
, ...)
84 string
= xvasprintf(fmt
, args
);
87 dpctl_puts(dpctl_p
, false, string
);
92 dpctl_error(struct dpctl_params
* dpctl_p
, int err_no
, const char *fmt
, ...)
94 const char *subprogram_name
= get_subprogram_name();
95 struct ds ds
= DS_EMPTY_INITIALIZER
;
96 int save_errno
= errno
;
100 if (subprogram_name
[0]) {
101 ds_put_format(&ds
, "%s(%s): ", program_name
,subprogram_name
);
103 ds_put_format(&ds
, "%s: ", program_name
);
107 ds_put_format_valist(&ds
, fmt
, args
);
111 ds_put_format(&ds
, " (%s)", ovs_retval_to_string(err_no
));
113 ds_put_cstr(&ds
, "\n");
115 dpctl_puts(dpctl_p
, true, ds_cstr(&ds
));
122 static int dpctl_add_if(int argc
, const char *argv
[], struct dpctl_params
*);
125 if_up(struct netdev
*netdev
)
127 return netdev_turn_flags_on(netdev
, NETDEV_UP
, NULL
);
130 /* Retrieve the name of the datapath if exactly one exists. The caller
131 * is responsible for freeing the returned string. If there is not one
132 * datapath, aborts with an error message. */
134 get_one_dp(struct dpctl_params
*dpctl_p
)
138 char *dp_name
= NULL
;
142 dp_enumerate_types(&types
);
143 SSET_FOR_EACH (type
, &types
) {
147 if (!dp_enumerate_names(type
, &names
)) {
148 count
+= sset_count(&names
);
149 if (!dp_name
&& count
== 1) {
150 dp_name
= xasprintf("%s@%s", type
, SSET_FIRST(&names
));
153 sset_destroy(&names
);
155 sset_destroy(&types
);
158 dpctl_error(dpctl_p
, 0, "no datapaths exist");
159 } else if (count
> 1) {
160 dpctl_error(dpctl_p
, 0, "multiple datapaths, specify one");
169 parsed_dpif_open(const char *arg_
, bool create
, struct dpif
**dpifp
)
174 dp_parse_name(arg_
, &name
, &type
);
177 result
= dpif_create(name
, type
, dpifp
);
179 result
= dpif_open(name
, type
, dpifp
);
188 dpctl_add_dp(int argc
, const char *argv
[],
189 struct dpctl_params
*dpctl_p
)
194 error
= parsed_dpif_open(argv
[1], true, &dpif
);
196 dpctl_error(dpctl_p
, error
, "add_dp");
201 error
= dpctl_add_if(argc
, argv
, dpctl_p
);
207 dpctl_del_dp(int argc OVS_UNUSED
, const char *argv
[],
208 struct dpctl_params
*dpctl_p
)
213 error
= parsed_dpif_open(argv
[1], false, &dpif
);
215 dpctl_error(dpctl_p
, error
, "opening datapath");
218 error
= dpif_delete(dpif
);
220 dpctl_error(dpctl_p
, error
, "del_dp");
228 dpctl_add_if(int argc OVS_UNUSED
, const char *argv
[],
229 struct dpctl_params
*dpctl_p
)
232 int i
, error
, lasterror
= 0;
234 error
= parsed_dpif_open(argv
[1], false, &dpif
);
236 dpctl_error(dpctl_p
, error
, "opening datapath");
239 for (i
= 2; i
< argc
; i
++) {
240 const char *name
, *type
;
241 char *save_ptr
= NULL
, *argcopy
;
242 struct netdev
*netdev
= NULL
;
244 odp_port_t port_no
= ODPP_NONE
;
247 argcopy
= xstrdup(argv
[i
]);
248 name
= strtok_r(argcopy
, ",", &save_ptr
);
252 dpctl_error(dpctl_p
, 0, "%s is not a valid network device name",
259 while ((option
= strtok_r(NULL
, ",", &save_ptr
)) != NULL
) {
260 char *save_ptr_2
= NULL
;
263 key
= strtok_r(option
, "=", &save_ptr_2
);
264 value
= strtok_r(NULL
, "", &save_ptr_2
);
269 if (!strcmp(key
, "type")) {
271 } else if (!strcmp(key
, "port_no")) {
272 port_no
= u32_to_odp(atoi(value
));
273 } else if (!smap_add_once(&args
, key
, value
)) {
274 dpctl_error(dpctl_p
, 0, "duplicate \"%s\" option", key
);
278 error
= netdev_open(name
, type
, &netdev
);
280 dpctl_error(dpctl_p
, error
, "%s: failed to open network device",
282 goto next_destroy_args
;
285 error
= netdev_set_config(netdev
, &args
, NULL
);
287 goto next_destroy_args
;
290 error
= dpif_port_add(dpif
, netdev
, &port_no
);
292 dpctl_error(dpctl_p
, error
, "adding %s to %s failed", name
,
294 goto next_destroy_args
;
297 error
= if_up(netdev
);
299 dpctl_error(dpctl_p
, error
, "%s: failed bringing interface up",
304 netdev_close(netdev
);
318 dpctl_set_if(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
321 int i
, error
, lasterror
= 0;
323 error
= parsed_dpif_open(argv
[1], false, &dpif
);
325 dpctl_error(dpctl_p
, error
, "opening datapath");
328 for (i
= 2; i
< argc
; i
++) {
329 struct netdev
*netdev
= NULL
;
330 struct dpif_port dpif_port
;
331 char *save_ptr
= NULL
;
340 argcopy
= xstrdup(argv
[i
]);
341 name
= strtok_r(argcopy
, ",", &save_ptr
);
343 dpctl_error(dpctl_p
, 0, "%s is not a valid network device name",
348 /* Get the port's type from the datapath. */
349 error
= dpif_port_query_by_name(dpif
, name
, &dpif_port
);
351 dpctl_error(dpctl_p
, error
, "%s: failed to query port in %s", name
,
355 type
= xstrdup(dpif_port
.type
);
356 port_no
= dpif_port
.port_no
;
357 dpif_port_destroy(&dpif_port
);
359 /* Retrieve its existing configuration. */
360 error
= netdev_open(name
, type
, &netdev
);
362 dpctl_error(dpctl_p
, error
, "%s: failed to open network device",
368 error
= netdev_get_config(netdev
, &args
);
370 dpctl_error(dpctl_p
, error
, "%s: failed to fetch configuration",
372 goto next_destroy_args
;
375 /* Parse changes to configuration. */
376 while ((option
= strtok_r(NULL
, ",", &save_ptr
)) != NULL
) {
377 char *save_ptr_2
= NULL
;
380 key
= strtok_r(option
, "=", &save_ptr_2
);
381 value
= strtok_r(NULL
, "", &save_ptr_2
);
386 if (!strcmp(key
, "type")) {
387 if (strcmp(value
, type
)) {
388 dpctl_error(dpctl_p
, 0,
389 "%s: can't change type from %s to %s",
392 goto next_destroy_args
;
394 } else if (!strcmp(key
, "port_no")) {
395 if (port_no
!= u32_to_odp(atoi(value
))) {
396 dpctl_error(dpctl_p
, 0, "%s: can't change port number from"
397 " %"PRIu32
" to %d", name
, port_no
, atoi(value
));
399 goto next_destroy_args
;
401 } else if (value
[0] == '\0') {
402 smap_remove(&args
, key
);
404 smap_replace(&args
, key
, value
);
408 /* Update configuration. */
410 error
= netdev_set_config(netdev
, &args
, &err_s
);
411 if (err_s
|| error
) {
412 dpctl_error(dpctl_p
, error
, "%s",
413 err_s
? err_s
: "Error updating configuration");
417 goto next_destroy_args
;
423 netdev_close(netdev
);
436 get_port_number(struct dpif
*dpif
, const char *name
, odp_port_t
*port
,
437 struct dpctl_params
*dpctl_p
)
439 struct dpif_port dpif_port
;
441 if (!dpif_port_query_by_name(dpif
, name
, &dpif_port
)) {
442 *port
= dpif_port
.port_no
;
443 dpif_port_destroy(&dpif_port
);
446 dpctl_error(dpctl_p
, 0, "no port named %s", name
);
452 dpctl_del_if(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
455 int i
, error
, lasterror
= 0;
457 error
= parsed_dpif_open(argv
[1], false, &dpif
);
459 dpctl_error(dpctl_p
, error
, "opening datapath");
462 for (i
= 2; i
< argc
; i
++) {
463 const char *name
= argv
[i
];
466 if (!name
[strspn(name
, "0123456789")]) {
467 port
= u32_to_odp(atoi(name
));
468 } else if (!get_port_number(dpif
, name
, &port
, dpctl_p
)) {
473 error
= dpif_port_del(dpif
, port
);
475 dpctl_error(dpctl_p
, error
, "deleting port %s from %s failed",
485 print_stat(struct dpctl_params
*dpctl_p
, const char *leader
, uint64_t value
)
487 dpctl_print(dpctl_p
, "%s", leader
);
488 if (value
!= UINT64_MAX
) {
489 dpctl_print(dpctl_p
, "%"PRIu64
, value
);
491 dpctl_print(dpctl_p
, "?");
496 print_human_size(struct dpctl_params
*dpctl_p
, uint64_t value
)
498 if (value
== UINT64_MAX
) {
500 } else if (value
>= 1024ULL * 1024 * 1024 * 1024) {
501 dpctl_print(dpctl_p
, " (%.1f TiB)",
502 value
/ (1024.0 * 1024 * 1024 * 1024));
503 } else if (value
>= 1024ULL * 1024 * 1024) {
504 dpctl_print(dpctl_p
, " (%.1f GiB)", value
/ (1024.0 * 1024 * 1024));
505 } else if (value
>= 1024ULL * 1024) {
506 dpctl_print(dpctl_p
, " (%.1f MiB)", value
/ (1024.0 * 1024));
507 } else if (value
>= 1024) {
508 dpctl_print(dpctl_p
, " (%.1f KiB)", value
/ 1024.0);
512 /* qsort comparison function. */
514 compare_port_nos(const void *a_
, const void *b_
)
516 const odp_port_t
*ap
= a_
;
517 const odp_port_t
*bp
= b_
;
518 uint32_t a
= odp_to_u32(*ap
);
519 uint32_t b
= odp_to_u32(*bp
);
521 return a
< b
? -1 : a
> b
;
525 show_dpif(struct dpif
*dpif
, struct dpctl_params
*dpctl_p
)
527 struct dpif_port_dump dump
;
528 struct dpif_port dpif_port
;
529 struct dpif_dp_stats stats
;
530 struct netdev
*netdev
;
532 dpctl_print(dpctl_p
, "%s:\n", dpif_name(dpif
));
533 if (!dpif_get_dp_stats(dpif
, &stats
)) {
534 dpctl_print(dpctl_p
, "\tlookups: hit:%"PRIu64
" missed:%"PRIu64
535 " lost:%"PRIu64
"\n\tflows: %"PRIu64
"\n",
536 stats
.n_hit
, stats
.n_missed
, stats
.n_lost
, stats
.n_flows
);
537 if (stats
.n_masks
!= UINT32_MAX
) {
538 uint64_t n_pkts
= stats
.n_hit
+ stats
.n_missed
;
539 double avg
= n_pkts
? (double) stats
.n_mask_hit
/ n_pkts
: 0.0;
541 dpctl_print(dpctl_p
, "\tmasks: hit:%"PRIu64
" total:%"PRIu32
543 stats
.n_mask_hit
, stats
.n_masks
, avg
);
547 odp_port_t
*port_nos
= NULL
;
548 size_t allocated_port_nos
= 0, n_port_nos
= 0;
549 DPIF_PORT_FOR_EACH (&dpif_port
, &dump
, dpif
) {
550 if (n_port_nos
>= allocated_port_nos
) {
551 port_nos
= x2nrealloc(port_nos
, &allocated_port_nos
,
555 port_nos
[n_port_nos
] = dpif_port
.port_no
;
559 qsort(port_nos
, n_port_nos
, sizeof *port_nos
, compare_port_nos
);
561 for (int i
= 0; i
< n_port_nos
; i
++) {
562 if (dpif_port_query_by_number(dpif
, port_nos
[i
], &dpif_port
)) {
566 dpctl_print(dpctl_p
, "\tport %u: %s",
567 dpif_port
.port_no
, dpif_port
.name
);
569 if (strcmp(dpif_port
.type
, "system")) {
572 dpctl_print(dpctl_p
, " (%s", dpif_port
.type
);
574 error
= netdev_open(dpif_port
.name
, dpif_port
.type
, &netdev
);
579 error
= netdev_get_config(netdev
, &config
);
581 const struct smap_node
**nodes
= smap_sort(&config
);
582 for (size_t j
= 0; j
< smap_count(&config
); j
++) {
583 const struct smap_node
*node
= nodes
[j
];
584 dpctl_print(dpctl_p
, "%c %s=%s", j
? ',' : ':',
585 node
->key
, node
->value
);
589 dpctl_print(dpctl_p
, ", could not retrieve configuration "
590 "(%s)", ovs_strerror(error
));
592 smap_destroy(&config
);
594 netdev_close(netdev
);
596 dpctl_print(dpctl_p
, ": open failed (%s)",
597 ovs_strerror(error
));
599 dpctl_print(dpctl_p
, ")");
601 dpctl_print(dpctl_p
, "\n");
603 if (dpctl_p
->print_statistics
) {
604 struct netdev_stats s
;
607 error
= netdev_open(dpif_port
.name
, dpif_port
.type
, &netdev
);
609 dpctl_print(dpctl_p
, ", open failed (%s)",
610 ovs_strerror(error
));
611 dpif_port_destroy(&dpif_port
);
614 error
= netdev_get_stats(netdev
, &s
);
616 netdev_close(netdev
);
617 print_stat(dpctl_p
, "\t\tRX packets:", s
.rx_packets
);
618 print_stat(dpctl_p
, " errors:", s
.rx_errors
);
619 print_stat(dpctl_p
, " dropped:", s
.rx_dropped
);
620 print_stat(dpctl_p
, " overruns:", s
.rx_over_errors
);
621 print_stat(dpctl_p
, " frame:", s
.rx_frame_errors
);
622 dpctl_print(dpctl_p
, "\n");
624 print_stat(dpctl_p
, "\t\tTX packets:", s
.tx_packets
);
625 print_stat(dpctl_p
, " errors:", s
.tx_errors
);
626 print_stat(dpctl_p
, " dropped:", s
.tx_dropped
);
627 print_stat(dpctl_p
, " aborted:", s
.tx_aborted_errors
);
628 print_stat(dpctl_p
, " carrier:", s
.tx_carrier_errors
);
629 dpctl_print(dpctl_p
, "\n");
631 print_stat(dpctl_p
, "\t\tcollisions:", s
.collisions
);
632 dpctl_print(dpctl_p
, "\n");
634 print_stat(dpctl_p
, "\t\tRX bytes:", s
.rx_bytes
);
635 print_human_size(dpctl_p
, s
.rx_bytes
);
636 print_stat(dpctl_p
, " TX bytes:", s
.tx_bytes
);
637 print_human_size(dpctl_p
, s
.tx_bytes
);
638 dpctl_print(dpctl_p
, "\n");
640 dpctl_print(dpctl_p
, ", could not retrieve stats (%s)",
641 ovs_strerror(error
));
644 dpif_port_destroy(&dpif_port
);
650 typedef void (*dps_for_each_cb
)(struct dpif
*, struct dpctl_params
*);
653 dps_for_each(struct dpctl_params
*dpctl_p
, dps_for_each_cb cb
)
655 struct sset dpif_names
= SSET_INITIALIZER(&dpif_names
),
656 dpif_types
= SSET_INITIALIZER(&dpif_types
);
657 int error
, openerror
= 0, enumerror
= 0;
658 const char *type
, *name
;
659 bool at_least_one
= false;
661 dp_enumerate_types(&dpif_types
);
663 SSET_FOR_EACH (type
, &dpif_types
) {
664 error
= dp_enumerate_names(type
, &dpif_names
);
669 SSET_FOR_EACH (name
, &dpif_names
) {
673 error
= dpif_open(name
, type
, &dpif
);
679 dpctl_error(dpctl_p
, error
, "opening datapath %s failed",
685 sset_destroy(&dpif_names
);
686 sset_destroy(&dpif_types
);
688 /* If there has been an error while opening a datapath it should be
689 * reported. Otherwise, we want to ignore the errors generated by
690 * dp_enumerate_names() if at least one datapath has been discovered,
691 * because they're not interesting for the user. This happens, for
692 * example, if OVS is using a userspace datapath and the kernel module
697 return at_least_one
? 0 : enumerror
;
702 dpctl_show(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
704 int error
, lasterror
= 0;
707 for (i
= 1; i
< argc
; i
++) {
708 const char *name
= argv
[i
];
711 error
= parsed_dpif_open(name
, false, &dpif
);
713 show_dpif(dpif
, dpctl_p
);
716 dpctl_error(dpctl_p
, error
, "opening datapath %s failed",
722 lasterror
= dps_for_each(dpctl_p
, show_dpif
);
729 dump_cb(struct dpif
*dpif
, struct dpctl_params
*dpctl_p
)
731 dpctl_print(dpctl_p
, "%s\n", dpif_name(dpif
));
735 dpctl_dump_dps(int argc OVS_UNUSED
, const char *argv
[] OVS_UNUSED
,
736 struct dpctl_params
*dpctl_p
)
738 return dps_for_each(dpctl_p
, dump_cb
);
742 format_dpif_flow(struct ds
*ds
, const struct dpif_flow
*f
, struct hmap
*ports
,
743 struct dpctl_params
*dpctl_p
)
745 if (dpctl_p
->verbosity
&& f
->ufid_present
) {
746 odp_format_ufid(&f
->ufid
, ds
);
747 ds_put_cstr(ds
, ", ");
749 odp_flow_format(f
->key
, f
->key_len
, f
->mask
, f
->mask_len
, ports
, ds
,
751 ds_put_cstr(ds
, ", ");
753 dpif_flow_stats_format(&f
->stats
, ds
);
754 ds_put_cstr(ds
, ", actions:");
755 format_odp_actions(ds
, f
->actions
, f
->actions_len
);
759 dpctl_dump_flows(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
766 struct flow flow_filter
;
767 struct flow_wildcards wc_filter
;
769 struct dpif_port_dump port_dump
;
770 struct dpif_port dpif_port
;
771 struct hmap portno_names
;
772 struct simap names_portno
;
774 struct dpif_flow_dump_thread
*flow_dump_thread
;
775 struct dpif_flow_dump
*flow_dump
;
777 int pmd_id
= PMD_ID_NULL
;
780 if (argc
> 1 && !strncmp(argv
[argc
- 1], "filter=", 7)) {
781 filter
= xstrdup(argv
[--argc
] + 7);
783 name
= (argc
== 2) ? xstrdup(argv
[1]) : get_one_dp(dpctl_p
);
789 error
= parsed_dpif_open(name
, false, &dpif
);
792 dpctl_error(dpctl_p
, error
, "opening datapath");
797 hmap_init(&portno_names
);
798 simap_init(&names_portno
);
799 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, dpif
) {
800 odp_portno_names_set(&portno_names
, dpif_port
.port_no
, dpif_port
.name
);
801 simap_put(&names_portno
, dpif_port
.name
,
802 odp_to_u32(dpif_port
.port_no
));
806 char *err
= parse_ofp_exact_flow(&flow_filter
, &wc_filter
, NULL
, filter
,
809 dpctl_error(dpctl_p
, 0, "Failed to parse filter (%s)", err
);
815 /* Make sure that these values are different. PMD_ID_NULL means that the
816 * pmd is unspecified (e.g. because the datapath doesn't have different
817 * pmd threads), while NON_PMD_CORE_ID refers to every non pmd threads
818 * in the userspace datapath */
819 BUILD_ASSERT(PMD_ID_NULL
!= NON_PMD_CORE_ID
);
822 flow_dump
= dpif_flow_dump_create(dpif
, false);
823 flow_dump_thread
= dpif_flow_dump_thread_create(flow_dump
);
824 while (dpif_flow_dump_next(flow_dump_thread
, &f
, 1)) {
827 struct flow_wildcards wc
;
828 struct match match
, match_filter
;
829 struct minimatch minimatch
;
831 odp_flow_key_to_flow(f
.key
, f
.key_len
, &flow
);
832 odp_flow_key_to_mask(f
.mask
, f
.mask_len
, &wc
, &flow
);
833 match_init(&match
, &flow
, &wc
);
835 match_init(&match_filter
, &flow_filter
, &wc
);
836 match_init(&match_filter
, &match_filter
.flow
, &wc_filter
);
837 minimatch_init(&minimatch
, &match_filter
);
839 if (!minimatch_matches_flow(&minimatch
, &match
.flow
)) {
840 minimatch_destroy(&minimatch
);
843 minimatch_destroy(&minimatch
);
846 /* If 'pmd_id' is specified, overlapping flows could be dumped from
847 * different pmd threads. So, separates dumps from different pmds
848 * by printing a title line. */
849 if (pmd_id
!= f
.pmd_id
) {
850 if (f
.pmd_id
== NON_PMD_CORE_ID
) {
851 ds_put_format(&ds
, "flow-dump from non-dpdk interfaces:\n");
853 ds_put_format(&ds
, "flow-dump from pmd on cpu core: %d\n",
858 format_dpif_flow(&ds
, &f
, &portno_names
, dpctl_p
);
859 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&ds
));
861 dpif_flow_dump_thread_destroy(flow_dump_thread
);
862 error
= dpif_flow_dump_destroy(flow_dump
);
865 dpctl_error(dpctl_p
, error
, "Failed to dump flows from datapath");
870 odp_portno_names_destroy(&portno_names
);
871 simap_destroy(&names_portno
);
872 hmap_destroy(&portno_names
);
879 /* Extracts the in_port from the parsed keys, and returns the reference
880 * to the 'struct netdev *' of the dpif port. On error, returns NULL.
881 * Users must call 'netdev_close()' after finish using the returned
883 static struct netdev
*
884 get_in_port_netdev_from_key(struct dpif
*dpif
, const struct ofpbuf
*key
)
886 const struct nlattr
*in_port_nla
;
887 struct netdev
*dev
= NULL
;
889 in_port_nla
= nl_attr_find(key
, 0, OVS_KEY_ATTR_IN_PORT
);
891 struct dpif_port dpif_port
;
895 port_no
= ODP_PORT_C(nl_attr_get_u32(in_port_nla
));
896 error
= dpif_port_query_by_number(dpif
, port_no
, &dpif_port
);
901 netdev_open(dpif_port
.name
, dpif_port
.type
, &dev
);
902 dpif_port_destroy(&dpif_port
);
910 dpctl_put_flow(int argc
, const char *argv
[], enum dpif_flow_put_flags flags
,
911 struct dpctl_params
*dpctl_p
)
913 const char *key_s
= argv
[argc
- 2];
914 const char *actions_s
= argv
[argc
- 1];
915 struct netdev
*in_port_netdev
= NULL
;
916 struct dpif_flow_stats stats
;
917 struct dpif_port dpif_port
;
918 struct dpif_port_dump port_dump
;
919 struct ofpbuf actions
;
926 struct simap port_names
;
929 dp_name
= argc
== 4 ? xstrdup(argv
[1]) : get_one_dp(dpctl_p
);
933 error
= parsed_dpif_open(dp_name
, false, &dpif
);
936 dpctl_error(dpctl_p
, error
, "opening datapath");
940 ufid_present
= false;
941 n
= odp_ufid_from_string(key_s
, &ufid
);
943 dpctl_error(dpctl_p
, -n
, "parsing flow ufid");
950 simap_init(&port_names
);
951 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, dpif
) {
952 simap_put(&port_names
, dpif_port
.name
, odp_to_u32(dpif_port
.port_no
));
955 ofpbuf_init(&key
, 0);
956 ofpbuf_init(&mask
, 0);
957 error
= odp_flow_from_string(key_s
, &port_names
, &key
, &mask
);
958 simap_destroy(&port_names
);
960 dpctl_error(dpctl_p
, error
, "parsing flow key");
961 goto out_freekeymask
;
964 ofpbuf_init(&actions
, 0);
965 error
= odp_actions_from_string(actions_s
, NULL
, &actions
);
967 dpctl_error(dpctl_p
, error
, "parsing actions");
968 goto out_freeactions
;
971 /* For DPDK interface, applies the operation to all pmd threads
972 * on the same numa node. */
973 in_port_netdev
= get_in_port_netdev_from_key(dpif
, &key
);
974 if (in_port_netdev
&& netdev_is_pmd(in_port_netdev
)) {
977 numa_id
= netdev_get_numa_id(in_port_netdev
);
978 if (ovs_numa_numa_id_is_valid(numa_id
)) {
979 struct ovs_numa_dump
*dump
= ovs_numa_dump_cores_on_numa(numa_id
);
980 struct ovs_numa_info
*iter
;
982 FOR_EACH_CORE_ON_NUMA (iter
, dump
) {
983 if (ovs_numa_core_is_pinned(iter
->core_id
)) {
984 error
= dpif_flow_put(dpif
, flags
,
986 mask
.size
== 0 ? NULL
: mask
.data
,
987 mask
.size
, actions
.data
,
988 actions
.size
, ufid_present
? &ufid
: NULL
,
989 iter
->core_id
, dpctl_p
->print_statistics
? &stats
: NULL
);
992 ovs_numa_dump_destroy(dump
);
997 error
= dpif_flow_put(dpif
, flags
,
999 mask
.size
== 0 ? NULL
: mask
.data
,
1000 mask
.size
, actions
.data
,
1001 actions
.size
, ufid_present
? &ufid
: NULL
,
1002 PMD_ID_NULL
, dpctl_p
->print_statistics
? &stats
: NULL
);
1005 dpctl_error(dpctl_p
, error
, "updating flow table");
1006 goto out_freeactions
;
1009 if (dpctl_p
->print_statistics
) {
1013 dpif_flow_stats_format(&stats
, &s
);
1014 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1019 ofpbuf_uninit(&actions
);
1021 ofpbuf_uninit(&mask
);
1022 ofpbuf_uninit(&key
);
1024 netdev_close(in_port_netdev
);
1029 dpctl_add_flow(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1031 return dpctl_put_flow(argc
, argv
, DPIF_FP_CREATE
, dpctl_p
);
1035 dpctl_mod_flow(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1037 enum dpif_flow_put_flags flags
;
1039 flags
= DPIF_FP_MODIFY
;
1040 if (dpctl_p
->may_create
) {
1041 flags
|= DPIF_FP_CREATE
;
1043 if (dpctl_p
->zero_statistics
) {
1044 flags
|= DPIF_FP_ZERO_STATS
;
1047 return dpctl_put_flow(argc
, argv
, flags
, dpctl_p
);
1051 dpctl_get_flow(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1053 const char *key_s
= argv
[argc
- 1];
1054 struct dpif_flow flow
;
1055 struct dpif_port dpif_port
;
1056 struct dpif_port_dump port_dump
;
1059 struct hmap portno_names
;
1062 uint64_t stub
[DPIF_FLOW_BUFSIZE
/ 8];
1066 dp_name
= argc
== 3 ? xstrdup(argv
[1]) : get_one_dp(dpctl_p
);
1070 error
= parsed_dpif_open(dp_name
, false, &dpif
);
1073 dpctl_error(dpctl_p
, error
, "opening datapath");
1077 ofpbuf_use_stub(&buf
, &stub
, sizeof stub
);
1078 hmap_init(&portno_names
);
1079 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, dpif
) {
1080 odp_portno_names_set(&portno_names
, dpif_port
.port_no
, dpif_port
.name
);
1083 n
= odp_ufid_from_string(key_s
, &ufid
);
1085 dpctl_error(dpctl_p
, -n
, "parsing flow ufid");
1089 /* In case of PMD will be returned flow from first PMD thread with match. */
1090 error
= dpif_flow_get(dpif
, NULL
, 0, &ufid
, PMD_ID_NULL
, &buf
, &flow
);
1092 dpctl_error(dpctl_p
, error
, "getting flow");
1097 format_dpif_flow(&ds
, &flow
, &portno_names
, dpctl_p
);
1098 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&ds
));
1102 odp_portno_names_destroy(&portno_names
);
1103 hmap_destroy(&portno_names
);
1104 ofpbuf_uninit(&buf
);
1110 dpctl_del_flow(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1112 const char *key_s
= argv
[argc
- 1];
1113 struct netdev
*in_port_netdev
= NULL
;
1114 struct dpif_flow_stats stats
;
1115 struct dpif_port dpif_port
;
1116 struct dpif_port_dump port_dump
;
1118 struct ofpbuf mask
; /* To be ignored. */
1123 struct simap port_names
;
1126 dp_name
= argc
== 3 ? xstrdup(argv
[1]) : get_one_dp(dpctl_p
);
1130 error
= parsed_dpif_open(dp_name
, false, &dpif
);
1133 dpctl_error(dpctl_p
, error
, "opening datapath");
1137 ufid_present
= false;
1138 n
= odp_ufid_from_string(key_s
, &ufid
);
1140 dpctl_error(dpctl_p
, -n
, "parsing flow ufid");
1144 ufid_present
= true;
1147 simap_init(&port_names
);
1148 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, dpif
) {
1149 simap_put(&port_names
, dpif_port
.name
, odp_to_u32(dpif_port
.port_no
));
1152 ofpbuf_init(&key
, 0);
1153 ofpbuf_init(&mask
, 0);
1155 error
= odp_flow_from_string(key_s
, &port_names
, &key
, &mask
);
1157 dpctl_error(dpctl_p
, error
, "parsing flow key");
1161 /* For DPDK interface, applies the operation to all pmd threads
1162 * on the same numa node. */
1163 in_port_netdev
= get_in_port_netdev_from_key(dpif
, &key
);
1164 if (in_port_netdev
&& netdev_is_pmd(in_port_netdev
)) {
1167 numa_id
= netdev_get_numa_id(in_port_netdev
);
1168 if (ovs_numa_numa_id_is_valid(numa_id
)) {
1169 struct ovs_numa_dump
*dump
= ovs_numa_dump_cores_on_numa(numa_id
);
1170 struct ovs_numa_info
*iter
;
1172 FOR_EACH_CORE_ON_NUMA (iter
, dump
) {
1173 if (ovs_numa_core_is_pinned(iter
->core_id
)) {
1174 error
= dpif_flow_del(dpif
, key
.data
,
1175 key
.size
, ufid_present
? &ufid
: NULL
,
1176 iter
->core_id
, dpctl_p
->print_statistics
? &stats
: NULL
);
1179 ovs_numa_dump_destroy(dump
);
1184 error
= dpif_flow_del(dpif
, key
.data
, key
.size
,
1185 ufid_present
? &ufid
: NULL
, PMD_ID_NULL
,
1186 dpctl_p
->print_statistics
? &stats
: NULL
);
1189 dpctl_error(dpctl_p
, error
, "deleting flow");
1190 if (error
== ENOENT
&& !ufid_present
) {
1194 ds_put_format(&s
, "Perhaps you need to specify a UFID?");
1195 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1201 if (dpctl_p
->print_statistics
) {
1205 dpif_flow_stats_format(&stats
, &s
);
1206 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1211 ofpbuf_uninit(&mask
);
1212 ofpbuf_uninit(&key
);
1213 simap_destroy(&port_names
);
1215 netdev_close(in_port_netdev
);
1220 dpctl_del_flows(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1226 name
= (argc
== 2) ? xstrdup(argv
[1]) : get_one_dp(dpctl_p
);
1230 error
= parsed_dpif_open(name
, false, &dpif
);
1233 dpctl_error(dpctl_p
, error
, "opening datapath");
1237 error
= dpif_flow_flush(dpif
);
1239 dpctl_error(dpctl_p
, error
, "deleting all flows");
1246 dpctl_help(int argc OVS_UNUSED
, const char *argv
[] OVS_UNUSED
,
1247 struct dpctl_params
*dpctl_p
)
1249 if (dpctl_p
->usage
) {
1250 dpctl_p
->usage(dpctl_p
->aux
);
1257 dpctl_list_commands(int argc OVS_UNUSED
, const char *argv
[] OVS_UNUSED
,
1258 struct dpctl_params
*dpctl_p
)
1260 struct ds ds
= DS_EMPTY_INITIALIZER
;
1261 const struct dpctl_command
*commands
= get_all_dpctl_commands();
1263 ds_put_cstr(&ds
, "The available commands are:\n");
1264 for (; commands
->name
; commands
++) {
1265 const struct dpctl_command
*c
= commands
;
1267 ds_put_format(&ds
, " %s%-23s %s\n", dpctl_p
->is_appctl
? "dpctl/" : "",
1270 dpctl_puts(dpctl_p
, false, ds
.string
);
1277 dpctl_dump_conntrack(int argc
, const char *argv
[],
1278 struct dpctl_params
*dpctl_p
)
1280 struct ct_dpif_dump_state
*dump
;
1281 struct ct_dpif_entry cte
;
1282 uint16_t zone
, *pzone
= NULL
;
1287 if (argc
> 1 && ovs_scan(argv
[argc
- 1], "zone=%"SCNu16
, &zone
)) {
1291 name
= (argc
== 2) ? xstrdup(argv
[1]) : get_one_dp(dpctl_p
);
1295 error
= parsed_dpif_open(name
, false, &dpif
);
1298 dpctl_error(dpctl_p
, error
, "opening datapath");
1302 error
= ct_dpif_dump_start(dpif
, &dump
, pzone
);
1304 dpctl_error(dpctl_p
, error
, "starting conntrack dump");
1309 while (!ct_dpif_dump_next(dump
, &cte
)) {
1310 struct ds s
= DS_EMPTY_INITIALIZER
;
1312 ct_dpif_format_entry(&cte
, &s
, dpctl_p
->verbosity
,
1313 dpctl_p
->print_statistics
);
1314 ct_dpif_entry_uninit(&cte
);
1316 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1319 ct_dpif_dump_done(dump
);
1325 dpctl_flush_conntrack(int argc
, const char *argv
[],
1326 struct dpctl_params
*dpctl_p
)
1329 uint16_t zone
, *pzone
= NULL
;
1333 if (argc
> 1 && ovs_scan(argv
[argc
- 1], "zone=%"SCNu16
, &zone
)) {
1337 name
= (argc
== 2) ? xstrdup(argv
[1]) : get_one_dp(dpctl_p
);
1341 error
= parsed_dpif_open(name
, false, &dpif
);
1344 dpctl_error(dpctl_p
, error
, "opening datapath");
1348 error
= ct_dpif_flush(dpif
, pzone
);
1354 /* Undocumented commands for unit testing. */
1357 dpctl_parse_actions(int argc
, const char *argv
[], struct dpctl_params
* dpctl_p
)
1361 for (i
= 1; i
< argc
; i
++) {
1362 struct ofpbuf actions
;
1365 ofpbuf_init(&actions
, 0);
1366 error
= odp_actions_from_string(argv
[i
], NULL
, &actions
);
1369 ofpbuf_uninit(&actions
);
1370 dpctl_error(dpctl_p
, error
, "odp_actions_from_string");
1375 format_odp_actions(&s
, actions
.data
, actions
.size
);
1376 dpctl_print(dpctl_p
, "%s\n", ds_cstr(&s
));
1379 ofpbuf_uninit(&actions
);
1385 struct actions_for_flow
{
1386 struct hmap_node hmap_node
;
1388 struct ofpbuf actions
;
1391 static struct actions_for_flow
*
1392 get_actions_for_flow(struct hmap
*actions_per_flow
, const struct flow
*flow
)
1394 uint32_t hash
= flow_hash(flow
, 0);
1395 struct actions_for_flow
*af
;
1397 HMAP_FOR_EACH_WITH_HASH (af
, hmap_node
, hash
, actions_per_flow
) {
1398 if (flow_equal(&af
->flow
, flow
)) {
1403 af
= xmalloc(sizeof *af
);
1405 ofpbuf_init(&af
->actions
, 0);
1406 hmap_insert(actions_per_flow
, &af
->hmap_node
, hash
);
1411 compare_actions_for_flow(const void *a_
, const void *b_
)
1413 struct actions_for_flow
*const *a
= a_
;
1414 struct actions_for_flow
*const *b
= b_
;
1416 return flow_compare_3way(&(*a
)->flow
, &(*b
)->flow
);
1420 compare_output_actions(const void *a_
, const void *b_
)
1422 const struct nlattr
*a
= a_
;
1423 const struct nlattr
*b
= b_
;
1424 uint32_t a_port
= nl_attr_get_u32(a
);
1425 uint32_t b_port
= nl_attr_get_u32(b
);
1427 return a_port
< b_port
? -1 : a_port
> b_port
;
1431 sort_output_actions__(struct nlattr
*first
, struct nlattr
*end
)
1433 size_t bytes
= (uint8_t *) end
- (uint8_t *) first
;
1434 size_t n
= bytes
/ NL_A_U32_SIZE
;
1436 ovs_assert(bytes
% NL_A_U32_SIZE
== 0);
1437 qsort(first
, n
, NL_A_U32_SIZE
, compare_output_actions
);
1441 sort_output_actions(struct nlattr
*actions
, size_t length
)
1443 struct nlattr
*first_output
= NULL
;
1447 NL_ATTR_FOR_EACH (a
, left
, actions
, length
) {
1448 if (nl_attr_type(a
) == OVS_ACTION_ATTR_OUTPUT
) {
1449 if (!first_output
) {
1454 sort_output_actions__(first_output
, a
);
1455 first_output
= NULL
;
1460 uint8_t *end
= (uint8_t *) actions
+ length
;
1461 sort_output_actions__(first_output
,
1462 ALIGNED_CAST(struct nlattr
*, end
));
1466 /* usage: "ovs-dpctl normalize-actions FLOW ACTIONS" where FLOW and ACTIONS
1467 * have the syntax used by "ovs-dpctl dump-flows".
1469 * This command prints ACTIONS in a format that shows what happens for each
1470 * VLAN, independent of the order of the ACTIONS. For example, there is more
1471 * than one way to output a packet on VLANs 9 and 11, but this command will
1472 * print the same output for any form.
1474 * The idea here generalizes beyond VLANs (e.g. to setting other fields) but
1475 * so far the implementation only covers VLANs. */
1477 dpctl_normalize_actions(int argc
, const char *argv
[],
1478 struct dpctl_params
*dpctl_p
)
1480 struct simap port_names
;
1481 struct ofpbuf keybuf
;
1483 struct ofpbuf odp_actions
;
1484 struct hmap actions_per_flow
;
1485 struct actions_for_flow
**afs
;
1486 struct actions_for_flow
*af
;
1495 simap_init(&port_names
);
1496 for (i
= 3; i
< argc
; i
++) {
1500 if (ovs_scan(argv
[i
], "%15[^=]=%d", name
, &number
)) {
1501 uintptr_t n
= number
;
1502 simap_put(&port_names
, name
, n
);
1504 dpctl_error(dpctl_p
, 0, "%s: expected NAME=NUMBER", argv
[i
]);
1510 /* Parse flow key. */
1511 ofpbuf_init(&keybuf
, 0);
1512 error
= odp_flow_from_string(argv
[1], &port_names
, &keybuf
, NULL
);
1514 dpctl_error(dpctl_p
, error
, "odp_flow_key_from_string");
1515 goto out_freekeybuf
;
1519 odp_flow_format(keybuf
.data
, keybuf
.size
, NULL
, 0, NULL
,
1520 &s
, dpctl_p
->verbosity
);
1521 dpctl_print(dpctl_p
, "input flow: %s\n", ds_cstr(&s
));
1523 error
= odp_flow_key_to_flow(keybuf
.data
, keybuf
.size
, &flow
);
1525 dpctl_error(dpctl_p
, error
, "odp_flow_key_to_flow");
1526 goto out_freekeybuf
;
1529 /* Parse actions. */
1530 ofpbuf_init(&odp_actions
, 0);
1531 error
= odp_actions_from_string(argv
[2], &port_names
, &odp_actions
);
1533 dpctl_error(dpctl_p
, error
, "odp_actions_from_string");
1534 goto out_freeactions
;
1537 if (dpctl_p
->verbosity
) {
1539 format_odp_actions(&s
, odp_actions
.data
, odp_actions
.size
);
1540 dpctl_print(dpctl_p
, "input actions: %s\n", ds_cstr(&s
));
1543 hmap_init(&actions_per_flow
);
1544 NL_ATTR_FOR_EACH (a
, left
, odp_actions
.data
, odp_actions
.size
) {
1545 const struct ovs_action_push_vlan
*push
;
1546 switch(nl_attr_type(a
)) {
1547 case OVS_ACTION_ATTR_POP_VLAN
:
1548 flow
.vlan_tci
= htons(0);
1551 case OVS_ACTION_ATTR_PUSH_VLAN
:
1552 push
= nl_attr_get_unspec(a
, sizeof *push
);
1553 flow
.vlan_tci
= push
->vlan_tci
;
1557 af
= get_actions_for_flow(&actions_per_flow
, &flow
);
1558 nl_msg_put_unspec(&af
->actions
, nl_attr_type(a
),
1559 nl_attr_get(a
), nl_attr_get_size(a
));
1562 n_afs
= hmap_count(&actions_per_flow
);
1563 afs
= xmalloc(n_afs
* sizeof *afs
);
1565 HMAP_FOR_EACH (af
, hmap_node
, &actions_per_flow
) {
1569 ovs_assert(i
== n_afs
);
1570 hmap_destroy(&actions_per_flow
);
1572 qsort(afs
, n_afs
, sizeof *afs
, compare_actions_for_flow
);
1574 for (i
= 0; i
< n_afs
; i
++) {
1575 struct actions_for_flow
*af
= afs
[i
];
1577 sort_output_actions(af
->actions
.data
, af
->actions
.size
);
1579 if (af
->flow
.vlan_tci
!= htons(0)) {
1580 dpctl_print(dpctl_p
, "vlan(vid=%"PRIu16
",pcp=%d): ",
1581 vlan_tci_to_vid(af
->flow
.vlan_tci
),
1582 vlan_tci_to_pcp(af
->flow
.vlan_tci
));
1584 dpctl_print(dpctl_p
, "no vlan: ");
1587 if (eth_type_mpls(af
->flow
.dl_type
)) {
1588 dpctl_print(dpctl_p
, "mpls(label=%"PRIu32
",tc=%d,ttl=%d): ",
1589 mpls_lse_to_label(af
->flow
.mpls_lse
[0]),
1590 mpls_lse_to_tc(af
->flow
.mpls_lse
[0]),
1591 mpls_lse_to_ttl(af
->flow
.mpls_lse
[0]));
1593 dpctl_print(dpctl_p
, "no mpls: ");
1597 format_odp_actions(&s
, af
->actions
.data
, af
->actions
.size
);
1598 dpctl_puts(dpctl_p
, false, ds_cstr(&s
));
1600 ofpbuf_uninit(&af
->actions
);
1607 ofpbuf_uninit(&odp_actions
);
1609 ofpbuf_uninit(&keybuf
);
1611 simap_destroy(&port_names
);
1617 static const struct dpctl_command all_commands
[] = {
1618 { "add-dp", "dp [iface...]", 1, INT_MAX
, dpctl_add_dp
, DP_RW
},
1619 { "del-dp", "dp", 1, 1, dpctl_del_dp
, DP_RW
},
1620 { "add-if", "dp iface...", 2, INT_MAX
, dpctl_add_if
, DP_RW
},
1621 { "del-if", "dp iface...", 2, INT_MAX
, dpctl_del_if
, DP_RW
},
1622 { "set-if", "dp iface...", 2, INT_MAX
, dpctl_set_if
, DP_RW
},
1623 { "dump-dps", "", 0, 0, dpctl_dump_dps
, DP_RO
},
1624 { "show", "[dp...]", 0, INT_MAX
, dpctl_show
, DP_RO
},
1625 { "dump-flows", "[dp]", 0, 2, dpctl_dump_flows
, DP_RO
},
1626 { "add-flow", "[dp] flow actions", 2, 3, dpctl_add_flow
, DP_RW
},
1627 { "mod-flow", "[dp] flow actions", 2, 3, dpctl_mod_flow
, DP_RW
},
1628 { "get-flow", "[dp] ufid", 1, 2, dpctl_get_flow
, DP_RO
},
1629 { "del-flow", "[dp] flow", 1, 2, dpctl_del_flow
, DP_RW
},
1630 { "del-flows", "[dp]", 0, 1, dpctl_del_flows
, DP_RW
},
1631 { "dump-conntrack", "[dp] [zone=N]", 0, 2, dpctl_dump_conntrack
, DP_RO
},
1632 { "flush-conntrack", "[dp] [zone=N]", 0, 2, dpctl_flush_conntrack
, DP_RW
},
1633 { "help", "", 0, INT_MAX
, dpctl_help
, DP_RO
},
1634 { "list-commands", "", 0, INT_MAX
, dpctl_list_commands
, DP_RO
},
1636 /* Undocumented commands for testing. */
1637 { "parse-actions", "actions", 1, INT_MAX
, dpctl_parse_actions
, DP_RO
},
1638 { "normalize-actions", "actions", 2, INT_MAX
, dpctl_normalize_actions
, DP_RO
},
1640 { NULL
, NULL
, 0, 0, NULL
, DP_RO
},
1643 static const struct dpctl_command
*get_all_dpctl_commands(void)
1645 return all_commands
;
1648 /* Runs the command designated by argv[0] within the command table specified by
1649 * 'commands', which must be terminated by a command whose 'name' member is a
1652 dpctl_run_command(int argc
, const char *argv
[], struct dpctl_params
*dpctl_p
)
1654 const struct dpctl_command
*p
;
1657 dpctl_error(dpctl_p
, 0, "missing command name; use --help for help");
1661 for (p
= all_commands
; p
->name
!= NULL
; p
++) {
1662 if (!strcmp(p
->name
, argv
[0])) {
1663 int n_arg
= argc
- 1;
1664 if (n_arg
< p
->min_args
) {
1665 dpctl_error(dpctl_p
, 0,
1666 "'%s' command requires at least %d arguments",
1667 p
->name
, p
->min_args
);
1669 } else if (n_arg
> p
->max_args
) {
1670 dpctl_error(dpctl_p
, 0,
1671 "'%s' command takes at most %d arguments",
1672 p
->name
, p
->max_args
);
1675 if (p
->mode
== DP_RW
&& dpctl_p
->read_only
) {
1676 dpctl_error(dpctl_p
, 0,
1677 "'%s' command does not work in read only mode",
1681 return p
->handler(argc
, argv
, dpctl_p
);
1686 dpctl_error(dpctl_p
, 0, "unknown command '%s'; use --help for help",
1692 dpctl_unixctl_print(void *userdata
, bool error OVS_UNUSED
, const char *msg
)
1694 struct ds
*ds
= userdata
;
1695 ds_put_cstr(ds
, msg
);
1699 dpctl_unixctl_handler(struct unixctl_conn
*conn
, int argc
, const char *argv
[],
1702 struct ds ds
= DS_EMPTY_INITIALIZER
;
1705 struct dpctl_params dpctl_p
= {
1707 .output
= dpctl_unixctl_print
,
1711 /* Parse options (like getopt). Unfortunately it does
1712 * not seem a good idea to call getopt_long() here, since it uses global
1714 while (argc
> 1 && !error
) {
1715 const char *arg
= argv
[1];
1716 if (!strncmp(arg
, "--", 2)) {
1718 if (!strcmp(arg
, "--statistics")) {
1719 dpctl_p
.print_statistics
= true;
1720 } else if (!strcmp(arg
, "--clear")) {
1721 dpctl_p
.zero_statistics
= true;
1722 } else if (!strcmp(arg
, "--may-create")) {
1723 dpctl_p
.may_create
= true;
1724 } else if (!strcmp(arg
, "--more")) {
1725 dpctl_p
.verbosity
++;
1727 ds_put_format(&ds
, "Unrecognized option %s", argv
[1]);
1730 } else if (arg
[0] == '-' && arg
[1] != '\0') {
1731 /* Short option[s] */
1732 const char *opt
= &arg
[1];
1734 while (*opt
&& !error
) {
1737 dpctl_p
.verbosity
++;
1740 dpctl_p
.print_statistics
= true;
1743 ds_put_format(&ds
, "Unrecognized option -%c", *opt
);
1750 /* Doesn't start with -, not an option */
1762 dpctl_command_handler
*handler
= (dpctl_command_handler
*) aux
;
1763 error
= handler(argc
, argv
, &dpctl_p
) != 0;
1767 unixctl_command_reply_error(conn
, ds_cstr(&ds
));
1769 unixctl_command_reply(conn
, ds_cstr(&ds
));
1776 dpctl_unixctl_register(void)
1778 const struct dpctl_command
*p
;
1780 for (p
= all_commands
; p
->name
!= NULL
; p
++) {
1781 if (strcmp(p
->name
, "help")) {
1782 char *cmd_name
= xasprintf("dpctl/%s", p
->name
);
1783 unixctl_command_register(cmd_name
,
1787 dpctl_unixctl_handler
,