From patchwork Fri Oct 20 10:43:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakob Meng X-Patchwork-Id: 1852441 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=LBFcoeLG; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SBh5d6hb3z23jM for ; Fri, 20 Oct 2023 21:43:49 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 055874ECF4; Fri, 20 Oct 2023 10:43:48 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 055874ECF4 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=LBFcoeLG X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3tfQwBRj0O_9; Fri, 20 Oct 2023 10:43:44 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id BDB994ECF0; Fri, 20 Oct 2023 10:43:43 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org BDB994ECF0 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 97738C0039; Fri, 20 Oct 2023 10:43:43 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 29A79C0039 for ; Fri, 20 Oct 2023 10:43:42 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 4CFB470436 for ; Fri, 20 Oct 2023 10:43:40 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 4CFB470436 Authentication-Results: smtp3.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=LBFcoeLG X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id FLk88-CCwIo8 for ; Fri, 20 Oct 2023 10:43:37 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id AE308704CF for ; Fri, 20 Oct 2023 10:43:36 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org AE308704CF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1697798615; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xCIZfk6Z2sva+G6iE3jvUoPAUgPHalcuM52dtaZRkhI=; b=LBFcoeLGWCHkaxBfV293z/lQ8s5rmfi1foseKgR/ZF1ELhrqcDccIN2R1bydeLwxZzaeSo O9gApxLv/lzz084fR73DZBfcpTfmN+11Tuw+C/GkNq27XvScf9ALqUbTL1FGdJZybWLvJL fDu9yXeSYqinB1QyUde+nrkJrYgRkS4= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-424-7HmkVYvvNICH6dCEIBQkvA-1; Fri, 20 Oct 2023 06:43:32 -0400 X-MC-Unique: 7HmkVYvvNICH6dCEIBQkvA-1 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-32d9602824dso308616f8f.2 for ; Fri, 20 Oct 2023 03:43:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697798611; x=1698403411; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xCIZfk6Z2sva+G6iE3jvUoPAUgPHalcuM52dtaZRkhI=; b=sfCXDpkQ3dWGyGRZyBagUgYH0vXLi1HMTaXKU4YtTQZS59MkDREB+vDVUNmxvwjHFM NVTTLfGLBjAN0KbzJ9dpJTBHArQFLpbdN0v4xny6mr4+/6FGx6eS8n7Ci3OOJdZ2KZsN HWzYW9PX45eXBoqNCp/XLpCOh9psT19z9L0jJV+KGt1VgoQnexag/JU4d0MGHsHh8ngJ RAngBc7hXaGodqO36I3U3TluNpQJwy/2sEcXCDJi3Gw1iLKaytwZdJw1VITPGUhXVVFd 3neaPB2vGOh6hcHd+DI15QDRlU4hEDlurTpGaQ3il+4NXyrNDFkU0Xqj2aHMEz27bcgN Ai6w== X-Gm-Message-State: AOJu0Yyk7x9q2nD7tg+QBhtZ5PfXP29NyivQkijEVmOw0uj7LqGC2fvO NKoNkdUdakCCsEsGuT81r3Y8IFBfX17Mp74iCKB8FXUrxmRAypW5Am2oElcIJ57e+jLZfKdIYm1 sGD8AffhWmpyffyHj/moR0qGp70QkuWdLKx4LGQ+XjYi2PixPTk0/tmq5JAqzotZBTUI= X-Received: by 2002:adf:fe48:0:b0:32d:9fc9:d14c with SMTP id m8-20020adffe48000000b0032d9fc9d14cmr1041701wrs.47.1697798610834; Fri, 20 Oct 2023 03:43:30 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEPROxu5QTOjR2QFMpqXZu/aQ5XX0646+iwPGF3FpStc0IVKefRUvFqFkbYuY2+bFxWSXbKXQ== X-Received: by 2002:adf:fe48:0:b0:32d:9fc9:d14c with SMTP id m8-20020adffe48000000b0032d9fc9d14cmr1041658wrs.47.1697798609601; Fri, 20 Oct 2023 03:43:29 -0700 (PDT) Received: from positronik4lide.redhat.com ([87.122.57.185]) by smtp.gmail.com with ESMTPSA id p7-20020a5d4587000000b0032db430fb9bsm1400519wrq.68.2023.10.20.03.43.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Oct 2023 03:43:28 -0700 (PDT) From: jmeng@redhat.com To: dev@openvswitch.org Date: Fri, 20 Oct 2023 12:43:20 +0200 Message-Id: <20231020104320.1417664-2-jmeng@redhat.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231020104320.1417664-1-jmeng@redhat.com> References: <20231020104320.1417664-1-jmeng@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC v2 1/1] Add global option to output JSON from ovs-appctl cmds. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Jakob Meng This patch follows an alternative approach to RFC [0]. For monitoring systems such as Prometheus it would be beneficial if OVS and OVS-DPDK would expose statistics in a machine-readable format. Several approaches like UNIX socket, OVSDB queries and JSON output from ovs-xxx tools have been proposed [1],[2]. This proof of concept describes one way how ovs-xxx tools could output JSON in addition to plain-text for humans. In the previous approach JSON output was implemented as a separate option for each command such as 'dpif/show'. This patch adds a global option '-f,--format' instead. An example call would be 'ovs-appctl --format json dpif/show' as shown in tests/pmd.at. By default, the output format is plain-text as before. In the previous patch the option was called '-o|--output' instead of '-f,--format'. But ovs-appctl already has a short option '-o' which prints the available ovs-appctl options ('--option'). The new option name '-f,--format' is in line with ovsdb-client where it controls output formatting, too. unixctl_command_register() in lib/unixctl.* gained a new int arg 'output_fmts' with which commands have to announce their support for output formats. All commands have been updated accordingly which is why so many files had to be changed. Most announce OVS_OUTPUT_FMT_TEXT only except for 'dpif/show' in ofproto/ofproto-dpif.c which also supports OVS_OUTPUT_FMT_JSON. The JSON-RPC API in lib/unixctl.c has been changed to transport the requested output format besides command and args. Previously, the command was copied to the 'method' parameter in JSON-RPC while the args were copied to the 'params' parameter. Without any other means to transport parameters via JSON-RPC left, the meaning of 'method' and 'params' had to be changed: 'method' will now always be 'execute/v1' to ensure (in)compatibility between (mis)matching client and server. The JSON-RPC 1.0 spec which is currently implemented, defines 'params' as a JSON array. The first parameter will now be the command, the second one the output format and the rest will be command args. Function type unixctl_cb_func in lib/unixctl.h has gained a new arg 'enum ovs_output_fmt fmt'. The output format which is passed via unix socket to ovs-vswitchd will be converted into a value of type 'enum ovs_output_fmt' in lib/unixctl.c and then passed to said 'fmt' arg of the choosen command handler. When a requested output format is not supported by a command, then process_command() in lib/unixctl.c will return an error. This is an advantage over the previous approach [0] where each command would have to parse the output format option and handle requests for unsupported output formats on its own. A disadvantage to the previous approach is that the JSON-RPC API for the socket communication had to be changed and all commands had to be updated to announce their output format support. However, this is a one-time change only: Whenever JSON output is to be implemend for another command, OVS_OUTPUT_FMT_TEXT|OVS_OUTPUT_FMT_JSON would have to be added to the unixctl_command_register() call and the command handler would have to readout the fmt arg. The question whether JSON output should be pretty printed and sorted remains. In most cases it would be unnecessary because machines consume the output or humans could use jq for pretty printing. However, it would make tests more readable (for humans) without having to use jq (which would require us to introduce a dependency on jq). Wdyt? [0] https://patchwork.ozlabs.org/project/openvswitch/patch/20231020092205.710399-2-jmeng@redhat.com/ [1] https://bugzilla.redhat.com/show_bug.cgi?id=1824861#c7 [2] https://patchwork.ozlabs.org/project/openvswitch/patch/20230831131122.284913-1-rjarry@redhat.com/ Reported-at: https://bugzilla.redhat.com/1824861 Signed-off-by: Jakob Meng --- lib/bfd.c | 16 ++- lib/cfm.c | 13 ++- lib/command-line.c | 35 ++++++ lib/command-line.h | 10 ++ lib/coverage.c | 11 +- lib/dpctl.c | 129 ++++++++++++-------- lib/dpctl.h | 4 + lib/dpdk.c | 15 ++- lib/dpif-netdev-perf.c | 1 + lib/dpif-netdev-perf.h | 1 + lib/dpif-netdev.c | 84 +++++++------ lib/dpif-netlink.c | 6 +- lib/lacp.c | 7 +- lib/memory.c | 5 +- lib/netdev-dpdk.c | 16 ++- lib/netdev-dummy.c | 30 +++-- lib/netdev-native-tnl.c | 4 +- lib/netdev-native-tnl.h | 4 +- lib/netdev-vport.c | 1 + lib/odp-execute.c | 10 +- lib/ovs-lldp.c | 16 ++- lib/ovs-router.c | 26 +++-- lib/rstp.c | 22 ++-- lib/stopwatch.c | 10 +- lib/stp.c | 20 ++-- lib/timeval.c | 13 ++- lib/tnl-neigh-cache.c | 35 +++--- lib/tnl-ports.c | 6 +- lib/unixctl.c | 207 ++++++++++++++++++++++----------- lib/unixctl.h | 11 +- lib/vlog.c | 46 +++++--- ofproto/bond.c | 32 +++-- ofproto/ofproto-dpif-trace.c | 10 +- ofproto/ofproto-dpif-upcall.c | 81 +++++++++---- ofproto/ofproto-dpif.c | 188 +++++++++++++++++++++++++----- ofproto/ofproto.c | 10 +- ofproto/tunnel.c | 4 +- ovsdb/file.c | 4 +- ovsdb/ovsdb-client.c | 40 ++++--- ovsdb/ovsdb-server.c | 122 ++++++++++++++----- ovsdb/ovsdb.c | 4 +- ovsdb/raft.c | 28 +++-- python/ovs/unixctl/__init__.py | 15 ++- python/ovs/unixctl/client.py | 6 +- python/ovs/unixctl/server.py | 63 ++++++---- python/ovs/util.py | 7 ++ python/ovs/vlog.py | 12 +- tests/appctl.py | 7 +- tests/pmd.at | 29 +++++ tests/test-netflow.c | 4 +- tests/test-sflow.c | 4 +- tests/test-unixctl.c | 33 ++++-- tests/test-unixctl.py | 25 ++-- utilities/ovs-appctl.c | 65 ++++++++--- utilities/ovs-dpctl.c | 12 ++ utilities/ovs-ofctl.c | 43 ++++--- vswitchd/bridge.c | 25 ++-- vswitchd/ovs-vswitchd.c | 5 +- 58 files changed, 1202 insertions(+), 490 deletions(-) -- 2.39.2 diff --git a/lib/bfd.c b/lib/bfd.c index 9698576d0..05d150878 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -267,9 +267,13 @@ static void bfd_status_changed(struct bfd *) OVS_REQUIRES(mutex); static void bfd_forwarding_if_rx_update(struct bfd *) OVS_REQUIRES(mutex); static void bfd_unixctl_show(struct unixctl_conn *, int argc, - const char *argv[], void *aux OVS_UNUSED); + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED); static void bfd_unixctl_set_forwarding_override(struct unixctl_conn *, int argc, const char *argv[], + enum ovs_output_fmt fmt + OVS_UNUSED, void *aux OVS_UNUSED); static void log_msg(enum vlog_level, const struct msg *, const char *message, const struct bfd *) OVS_REQUIRES(mutex); @@ -339,9 +343,10 @@ void bfd_init(void) { unixctl_command_register("bfd/show", "[interface]", 0, 1, - bfd_unixctl_show, NULL); + OVS_OUTPUT_FMT_TEXT, bfd_unixctl_show, NULL); unixctl_command_register("bfd/set-forwarding", "[interface] normal|false|true", 1, 2, + OVS_OUTPUT_FMT_TEXT, bfd_unixctl_set_forwarding_override, NULL); } @@ -1311,7 +1316,8 @@ bfd_put_details(struct ds *ds, const struct bfd *bfd) OVS_REQUIRES(mutex) static void bfd_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[], - void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) + OVS_EXCLUDED(mutex) { struct ds ds = DS_EMPTY_INITIALIZER; struct bfd *bfd; @@ -1340,7 +1346,9 @@ out: static void bfd_unixctl_set_forwarding_override(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) { const char *forward_str = argv[argc - 1]; diff --git a/lib/cfm.c b/lib/cfm.c index c3742f3de..4f1598983 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -327,10 +327,12 @@ lookup_remote_mp(const struct cfm *cfm, uint64_t mpid) OVS_REQUIRES(mutex) void cfm_init(void) { - unixctl_command_register("cfm/show", "[interface]", 0, 1, cfm_unixctl_show, + unixctl_command_register("cfm/show", "[interface]", 0, 1, + OVS_OUTPUT_FMT_TEXT, cfm_unixctl_show, NULL); unixctl_command_register("cfm/set-fault", "[interface] normal|false|true", - 1, 2, cfm_unixctl_set_fault, NULL); + 1, 2, OVS_OUTPUT_FMT_TEXT, cfm_unixctl_set_fault, + NULL); } /* Records the status change and changes the global connectivity seq. */ @@ -1061,7 +1063,8 @@ cfm_print_details(struct ds *ds, struct cfm *cfm) OVS_REQUIRES(mutex) static void cfm_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[], - void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) + OVS_EXCLUDED(mutex) { struct ds ds = DS_EMPTY_INITIALIZER; struct cfm *cfm; @@ -1088,7 +1091,9 @@ out: static void cfm_unixctl_set_fault(struct unixctl_conn *conn, int argc, const char *argv[], - void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) + OVS_EXCLUDED(mutex) { const char *fault_str = argv[argc - 1]; int fault_override; diff --git a/lib/command-line.c b/lib/command-line.c index 967f4f5d5..742be570f 100644 --- a/lib/command-line.c +++ b/lib/command-line.c @@ -24,6 +24,7 @@ #include "ovs-thread.h" #include "util.h" #include "openvswitch/vlog.h" +#include "openvswitch/json.h" VLOG_DEFINE_THIS_MODULE(command_line); @@ -53,6 +54,40 @@ ovs_cmdl_long_options_to_short_options(const struct option options[]) return xstrdup(short_options); } +const char * +ovs_output_fmt_to_string(enum ovs_output_fmt fmt) +{ + switch (fmt) { + case OVS_OUTPUT_FMT_TEXT: + return "text"; + + case OVS_OUTPUT_FMT_JSON: + return "json"; + + default: + return NULL; + } +} + +struct json * +ovs_output_fmt_to_json(enum ovs_output_fmt fmt) +{ + return json_string_create(ovs_output_fmt_to_string(fmt)); +} + +bool +ovs_output_fmt_from_string(const char *string, enum ovs_output_fmt *fmt) +{ + if (!strcmp(string, "text")) { + *fmt = OVS_OUTPUT_FMT_TEXT; + } else if (!strcmp(string, "json")) { + *fmt = OVS_OUTPUT_FMT_JSON; + } else { + return false; + } + return true; +} + static char * OVS_WARN_UNUSED_RESULT build_short_options(const struct option *long_options) { diff --git a/lib/command-line.h b/lib/command-line.h index fc2a2690f..494274cec 100644 --- a/lib/command-line.h +++ b/lib/command-line.h @@ -20,6 +20,7 @@ /* Utilities for command-line parsing. */ #include "compiler.h" +#include struct option; @@ -46,6 +47,15 @@ struct ovs_cmdl_command { char *ovs_cmdl_long_options_to_short_options(const struct option *options); +enum ovs_output_fmt { + OVS_OUTPUT_FMT_TEXT = 1 << 0, + OVS_OUTPUT_FMT_JSON = 1 << 1 +}; + +const char *ovs_output_fmt_to_string(enum ovs_output_fmt); +struct json *ovs_output_fmt_to_json(enum ovs_output_fmt); +bool ovs_output_fmt_from_string(const char *, enum ovs_output_fmt *); + struct ovs_cmdl_parsed_option { const struct option *o; char *arg; diff --git a/lib/coverage.c b/lib/coverage.c index a95b6aa25..f32550fc3 100644 --- a/lib/coverage.c +++ b/lib/coverage.c @@ -61,7 +61,9 @@ coverage_counter_register(struct coverage_counter* counter) static void coverage_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct svec lines; char *reply; @@ -76,7 +78,9 @@ coverage_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, static void coverage_unixctl_read_counter(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { unsigned long long count; char *reply; @@ -96,9 +100,10 @@ coverage_unixctl_read_counter(struct unixctl_conn *conn, int argc OVS_UNUSED, void coverage_init(void) { - unixctl_command_register("coverage/show", "", 0, 0, + unixctl_command_register("coverage/show", "", 0, 0, OVS_OUTPUT_FMT_TEXT, coverage_unixctl_show, NULL); unixctl_command_register("coverage/read-counter", "COUNTER", 1, 1, + OVS_OUTPUT_FMT_TEXT, coverage_unixctl_read_counter, NULL); } diff --git a/lib/dpctl.c b/lib/dpctl.c index cd12625a1..2de6daad1 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -66,6 +66,7 @@ struct dpctl_command { const char *usage; int min_args; int max_args; + int output_fmts; dpctl_command_handler *handler; enum { DP_RO, DP_RW} mode; }; @@ -2990,69 +2991,93 @@ out: } static const struct dpctl_command all_commands[] = { - { "add-dp", "dp [iface...]", 1, INT_MAX, dpctl_add_dp, DP_RW }, - { "del-dp", "dp", 1, 1, dpctl_del_dp, DP_RW }, - { "add-if", "dp iface...", 2, INT_MAX, dpctl_add_if, DP_RW }, - { "del-if", "dp iface...", 2, INT_MAX, dpctl_del_if, DP_RW }, - { "set-if", "dp iface...", 2, INT_MAX, dpctl_set_if, DP_RW }, - { "dump-dps", "", 0, 0, dpctl_dump_dps, DP_RO }, - { "show", "[-s] [dp...]", 0, INT_MAX, dpctl_show, DP_RO }, + { "add-dp", "dp [iface...]", 1, INT_MAX, OVS_OUTPUT_FMT_TEXT, + dpctl_add_dp, DP_RW }, + { "del-dp", "dp", 1, 1, OVS_OUTPUT_FMT_TEXT, dpctl_del_dp, DP_RW }, + { "add-if", "dp iface...", 2, INT_MAX, OVS_OUTPUT_FMT_TEXT, dpctl_add_if, + DP_RW }, + { "del-if", "dp iface...", 2, INT_MAX, OVS_OUTPUT_FMT_TEXT, dpctl_del_if, + DP_RW }, + { "set-if", "dp iface...", 2, INT_MAX, OVS_OUTPUT_FMT_TEXT, dpctl_set_if, + DP_RW }, + { "dump-dps", "", 0, 0, OVS_OUTPUT_FMT_TEXT, dpctl_dump_dps, DP_RO }, + { "show", "[-s] [dp...]", 0, INT_MAX, OVS_OUTPUT_FMT_TEXT, dpctl_show, + DP_RO }, { "dump-flows", "[-m] [--names] [dp] [filter=..] [type=..] [pmd=..]", - 0, 6, dpctl_dump_flows, DP_RO }, - { "add-flow", "[dp] flow actions", 2, 3, dpctl_add_flow, DP_RW }, - { "mod-flow", "[dp] flow actions", 2, 3, dpctl_mod_flow, DP_RW }, - { "get-flow", "[dp] ufid", 1, 2, dpctl_get_flow, DP_RO }, - { "del-flow", "[dp] flow", 1, 2, dpctl_del_flow, DP_RW }, - { "add-flows", "[dp] file", 1, 2, dpctl_process_flows, DP_RW }, - { "mod-flows", "[dp] file", 1, 2, dpctl_process_flows, DP_RW }, - { "del-flows", "[dp] [file]", 0, 2, dpctl_del_flows, DP_RW }, + 0, 6, OVS_OUTPUT_FMT_TEXT, dpctl_dump_flows, DP_RO }, + { "add-flow", "[dp] flow actions", 2, 3, OVS_OUTPUT_FMT_TEXT, + dpctl_add_flow, DP_RW }, + { "mod-flow", "[dp] flow actions", 2, 3, OVS_OUTPUT_FMT_TEXT, + dpctl_mod_flow, DP_RW }, + { "get-flow", "[dp] ufid", 1, 2, OVS_OUTPUT_FMT_TEXT, dpctl_get_flow, + DP_RO }, + { "del-flow", "[dp] flow", 1, 2, OVS_OUTPUT_FMT_TEXT, dpctl_del_flow, + DP_RW }, + { "add-flows", "[dp] file", 1, 2, OVS_OUTPUT_FMT_TEXT, + dpctl_process_flows, DP_RW }, + { "mod-flows", "[dp] file", 1, 2, OVS_OUTPUT_FMT_TEXT, + dpctl_process_flows, DP_RW }, + { "del-flows", "[dp] [file]", 0, 2, OVS_OUTPUT_FMT_TEXT, dpctl_del_flows, + DP_RW }, { "offload-stats-show", "[dp]", - 0, 1, dpctl_offload_stats_show, DP_RO }, + 0, 1, OVS_OUTPUT_FMT_TEXT, dpctl_offload_stats_show, DP_RO }, { "dump-conntrack", "[-m] [-s] [dp] [zone=N]", - 0, 4, dpctl_dump_conntrack, DP_RO }, + 0, 4, OVS_OUTPUT_FMT_TEXT, dpctl_dump_conntrack, DP_RO }, { "dump-conntrack-exp", "[dp] [zone=N]", - 0, 2, dpctl_dump_conntrack_exp, DP_RO }, + 0, 2, OVS_OUTPUT_FMT_TEXT, dpctl_dump_conntrack_exp, DP_RO }, { "flush-conntrack", "[dp] [zone=N] [ct-orig-tuple] [ct-reply-tuple]", - 0, 4, dpctl_flush_conntrack, DP_RW }, - { "cache-get-size", "[dp]", 0, 1, dpctl_cache_get_size, DP_RO }, - { "cache-set-size", "dp cache ", 3, 3, dpctl_cache_set_size, DP_RW }, + 0, 4, OVS_OUTPUT_FMT_TEXT, dpctl_flush_conntrack, DP_RW }, + { "cache-get-size", "[dp]", 0, 1, OVS_OUTPUT_FMT_TEXT, + dpctl_cache_get_size, DP_RO }, + { "cache-set-size", "dp cache ", 3, 3, OVS_OUTPUT_FMT_TEXT, + dpctl_cache_set_size, DP_RW }, { "ct-stats-show", "[dp] [zone=N]", - 0, 3, dpctl_ct_stats_show, DP_RO }, - { "ct-bkts", "[dp] [gt=N]", 0, 2, dpctl_ct_bkts, DP_RO }, - { "ct-set-maxconns", "[dp] maxconns", 1, 2, dpctl_ct_set_maxconns, - DP_RW }, - { "ct-get-maxconns", "[dp]", 0, 1, dpctl_ct_get_maxconns, DP_RO }, - { "ct-get-nconns", "[dp]", 0, 1, dpctl_ct_get_nconns, DP_RO }, - { "ct-enable-tcp-seq-chk", "[dp]", 0, 1, dpctl_ct_enable_tcp_seq_chk, - DP_RW }, - { "ct-disable-tcp-seq-chk", "[dp]", 0, 1, dpctl_ct_disable_tcp_seq_chk, - DP_RW }, - { "ct-get-tcp-seq-chk", "[dp]", 0, 1, dpctl_ct_get_tcp_seq_chk, DP_RO }, + 0, 3, OVS_OUTPUT_FMT_TEXT, dpctl_ct_stats_show, DP_RO }, + { "ct-bkts", "[dp] [gt=N]", 0, 2, OVS_OUTPUT_FMT_TEXT, dpctl_ct_bkts, + DP_RO }, + { "ct-set-maxconns", "[dp] maxconns", 1, 2, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_set_maxconns, DP_RW }, + { "ct-get-maxconns", "[dp]", 0, 1, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_get_maxconns, DP_RO }, + { "ct-get-nconns", "[dp]", 0, 1, OVS_OUTPUT_FMT_TEXT, dpctl_ct_get_nconns, + DP_RO }, + { "ct-enable-tcp-seq-chk", "[dp]", 0, 1, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_enable_tcp_seq_chk, DP_RW }, + { "ct-disable-tcp-seq-chk", "[dp]", 0, 1, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_disable_tcp_seq_chk, DP_RW }, + { "ct-get-tcp-seq-chk", "[dp]", 0, 1, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_get_tcp_seq_chk, DP_RO }, { "ct-set-limits", "[dp] [default=L] [zone=N,limit=L]...", 1, INT_MAX, - dpctl_ct_set_limits, DP_RO }, - { "ct-del-limits", "[dp] zone=N1[,N2]...", 1, 2, dpctl_ct_del_limits, - DP_RO }, - { "ct-get-limits", "[dp] [zone=N1[,N2]...]", 0, 2, dpctl_ct_get_limits, - DP_RO }, - { "ct-get-sweep-interval", "[dp]", 0, 1, dpctl_ct_get_sweep, DP_RO }, - { "ct-set-sweep-interval", "[dp] ms", 1, 2, dpctl_ct_set_sweep, DP_RW }, - { "ipf-set-enabled", "[dp] v4|v6", 1, 2, dpctl_ipf_set_enabled, DP_RW }, - { "ipf-set-disabled", "[dp] v4|v6", 1, 2, dpctl_ipf_set_disabled, DP_RW }, + OVS_OUTPUT_FMT_TEXT, dpctl_ct_set_limits, DP_RO }, + { "ct-del-limits", "[dp] zone=N1[,N2]...", 1, 2, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_del_limits, DP_RO }, + { "ct-get-limits", "[dp] [zone=N1[,N2]...]", 0, 2, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_get_limits, DP_RO }, + { "ct-get-sweep-interval", "[dp]", 0, 1, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_get_sweep, DP_RO }, + { "ct-set-sweep-interval", "[dp] ms", 1, 2, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_set_sweep, DP_RW }, + { "ipf-set-enabled", "[dp] v4|v6", 1, 2, OVS_OUTPUT_FMT_TEXT, + dpctl_ipf_set_enabled, DP_RW }, + { "ipf-set-disabled", "[dp] v4|v6", 1, 2, OVS_OUTPUT_FMT_TEXT, + dpctl_ipf_set_disabled, DP_RW }, { "ipf-set-min-frag", "[dp] v4|v6 minfragment", 2, 3, - dpctl_ipf_set_min_frag, DP_RW }, + OVS_OUTPUT_FMT_TEXT, dpctl_ipf_set_min_frag, DP_RW }, { "ipf-set-max-nfrags", "[dp] maxfrags", 1, 2, - dpctl_ipf_set_max_nfrags, DP_RW }, - { "ipf-get-status", "[dp]", 0, 1, dpctl_ct_ipf_get_status, - DP_RO }, - { "help", "", 0, INT_MAX, dpctl_help, DP_RO }, - { "list-commands", "", 0, INT_MAX, dpctl_list_commands, DP_RO }, + OVS_OUTPUT_FMT_TEXT, dpctl_ipf_set_max_nfrags, DP_RW }, + { "ipf-get-status", "[dp]", 0, 1, OVS_OUTPUT_FMT_TEXT, + dpctl_ct_ipf_get_status, DP_RO }, + { "help", "", 0, INT_MAX, OVS_OUTPUT_FMT_TEXT, dpctl_help, DP_RO }, + { "list-commands", "", 0, INT_MAX, OVS_OUTPUT_FMT_TEXT, + dpctl_list_commands, DP_RO }, /* Undocumented commands for testing. */ - { "parse-actions", "actions", 1, INT_MAX, dpctl_parse_actions, DP_RO }, + { "parse-actions", "actions", 1, INT_MAX, OVS_OUTPUT_FMT_TEXT, + dpctl_parse_actions, DP_RO }, { "normalize-actions", "actions", - 2, INT_MAX, dpctl_normalize_actions, DP_RO }, + 2, INT_MAX, OVS_OUTPUT_FMT_TEXT, dpctl_normalize_actions, DP_RO }, - { NULL, NULL, 0, 0, NULL, DP_RO }, + { NULL, NULL, 0, 0, 0, NULL, DP_RO }, }; static const struct dpctl_command *get_all_dpctl_commands(void) @@ -3111,7 +3136,7 @@ dpctl_unixctl_print(void *userdata, bool error OVS_UNUSED, const char *msg) static void dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[], - void *aux) + enum ovs_output_fmt fmt, void *aux) { struct ds ds = DS_EMPTY_INITIALIZER; bool error = false; @@ -3120,6 +3145,7 @@ dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[], .is_appctl = true, .output = dpctl_unixctl_print, .aux = &ds, + .format = fmt, }; /* Parse options (like getopt). Unfortunately it does @@ -3208,6 +3234,7 @@ dpctl_unixctl_register(void) p->usage, p->min_args, p->max_args, + p->output_fmts, dpctl_unixctl_handler, p->handler); free(cmd_name); diff --git a/lib/dpctl.h b/lib/dpctl.h index 9d0052152..d174815e7 100644 --- a/lib/dpctl.h +++ b/lib/dpctl.h @@ -19,6 +19,7 @@ #include #include "compiler.h" +#include "command-line.h" struct dpctl_params { /* True if it is called by ovs-appctl command. */ @@ -42,6 +43,9 @@ struct dpctl_params { /* --names: Use port names in output? */ bool names; + /* --format: Output format? */ + enum ovs_output_fmt format; + /* Callback for printing. This function is called from dpctl_run_command() * to output data. The 'aux' parameter is set to the 'aux' * member. The 'error' parameter is true if 'string' is an error diff --git a/lib/dpdk.c b/lib/dpdk.c index d76d53f8f..4e71a8234 100644 --- a/lib/dpdk.c +++ b/lib/dpdk.c @@ -213,7 +213,8 @@ static cookie_io_functions_t dpdk_log_func = { static void dpdk_unixctl_mem_stream(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux) { void (*callback)(FILE *) = aux; char *response = NULL; @@ -260,6 +261,7 @@ dpdk_parse_log_level(const char *s) static void dpdk_unixctl_log_set(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { int i; @@ -427,14 +429,15 @@ dpdk_init__(const struct smap *ovs_other_config) } } - unixctl_command_register("dpdk/lcore-list", "", 0, 0, - dpdk_unixctl_mem_stream, rte_lcore_dump); - unixctl_command_register("dpdk/log-list", "", 0, 0, + unixctl_command_register("dpdk/lcore-list", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + dpdk_unixctl_mem_stream, rte_lcore_dump); + unixctl_command_register("dpdk/log-list", "", 0, 0, OVS_OUTPUT_FMT_TEXT, dpdk_unixctl_mem_stream, rte_log_dump); unixctl_command_register("dpdk/log-set", "{level | pattern:level}", 0, - INT_MAX, dpdk_unixctl_log_set, NULL); + INT_MAX, OVS_OUTPUT_FMT_TEXT, + dpdk_unixctl_log_set, NULL); unixctl_command_register("dpdk/get-malloc-stats", "", 0, 0, - dpdk_unixctl_mem_stream, + OVS_OUTPUT_FMT_TEXT, dpdk_unixctl_mem_stream, malloc_dump_stats_wrapper); /* We are called from the main thread here */ diff --git a/lib/dpif-netdev-perf.c b/lib/dpif-netdev-perf.c index 79ea5e3be..23e735ef0 100644 --- a/lib/dpif-netdev-perf.c +++ b/lib/dpif-netdev-perf.c @@ -706,6 +706,7 @@ pmd_perf_log_susp_iteration_neighborhood(struct pmd_perf_stats *s) void pmd_perf_log_set_cmd(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { unsigned int it_before, it_after, us_thr, q_thr; diff --git a/lib/dpif-netdev-perf.h b/lib/dpif-netdev-perf.h index 84beced15..1e5cddbac 100644 --- a/lib/dpif-netdev-perf.h +++ b/lib/dpif-netdev-perf.h @@ -432,6 +432,7 @@ void pmd_perf_format_ms_history(struct ds *str, struct pmd_perf_stats *s, int n_ms); void pmd_perf_log_set_cmd(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED); #ifdef __cplusplus diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 157694bcf..43beb1311 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1010,6 +1010,7 @@ sorted_poll_thread_list(struct dp_netdev *dp, static void dpif_netdev_subtable_lookup_get(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds reply = DS_EMPTY_INITIALIZER; @@ -1021,7 +1022,9 @@ dpif_netdev_subtable_lookup_get(struct unixctl_conn *conn, int argc OVS_UNUSED, static void dpif_netdev_subtable_lookup_set(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { /* This function requires 2 parameters (argv[1] and argv[2]) to execute. * argv[1] is subtable name @@ -1101,7 +1104,9 @@ dpif_netdev_subtable_lookup_set(struct unixctl_conn *conn, int argc OVS_UNUSED, static void dpif_netdev_impl_get(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds reply = DS_EMPTY_INITIALIZER; struct shash_node *node; @@ -1125,7 +1130,8 @@ dpif_netdev_impl_get(struct unixctl_conn *conn, int argc OVS_UNUSED, static void dpif_netdev_impl_set(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { /* This function requires just one parameter, the DPIF name. */ const char *dpif_name = argv[1]; @@ -1187,6 +1193,7 @@ dpif_netdev_impl_set(struct unixctl_conn *conn, int argc OVS_UNUSED, static void dpif_miniflow_extract_impl_get(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds reply = DS_EMPTY_INITIALIZER; @@ -1211,7 +1218,9 @@ dpif_miniflow_extract_impl_get(struct unixctl_conn *conn, int argc OVS_UNUSED, static void dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { /* This command takes some optional and mandatory arguments. The function * here first parses all of the options, saving results in local variables. @@ -1400,7 +1409,9 @@ error: static void dpif_netdev_pmd_rebalance(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds reply = DS_EMPTY_INITIALIZER; struct dp_netdev *dp = NULL; @@ -1430,7 +1441,7 @@ dpif_netdev_pmd_rebalance(struct unixctl_conn *conn, int argc, static void dpif_netdev_pmd_info(struct unixctl_conn *conn, int argc, const char *argv[], - void *aux) + enum ovs_output_fmt fmt OVS_UNUSED, void *aux) { struct ds reply = DS_EMPTY_INITIALIZER; struct dp_netdev_pmd_thread **pmd_list; @@ -1529,9 +1540,8 @@ dpif_netdev_pmd_info(struct unixctl_conn *conn, int argc, const char *argv[], } static void -pmd_perf_show_cmd(struct unixctl_conn *conn, int argc, - const char *argv[], - void *aux OVS_UNUSED) +pmd_perf_show_cmd(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt, void *aux OVS_UNUSED) { struct pmd_perf_params par; long int it_hist = 0, ms_hist = 0; @@ -1567,12 +1577,13 @@ pmd_perf_show_cmd(struct unixctl_conn *conn, int argc, par.iter_hist_len = it_hist; par.ms_hist_len = ms_hist; par.command_type = PMD_INFO_PERF_SHOW; - dpif_netdev_pmd_info(conn, argc, argv, &par); + dpif_netdev_pmd_info(conn, argc, argv, fmt, &par); } static void -dpif_netdev_bond_show(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) +dpif_netdev_bond_show(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds reply = DS_EMPTY_INITIALIZER; struct dp_netdev *dp = NULL; @@ -1622,60 +1633,60 @@ dpif_netdev_init(void) sleep_aux = PMD_INFO_SLEEP_SHOW; unixctl_command_register("dpif-netdev/pmd-stats-show", "[-pmd core] [dp]", - 0, 3, dpif_netdev_pmd_info, + 0, 3, OVS_OUTPUT_FMT_TEXT, dpif_netdev_pmd_info, (void *)&show_aux); unixctl_command_register("dpif-netdev/pmd-stats-clear", "[-pmd core] [dp]", - 0, 3, dpif_netdev_pmd_info, + 0, 3, OVS_OUTPUT_FMT_TEXT, dpif_netdev_pmd_info, (void *)&clear_aux); unixctl_command_register("dpif-netdev/pmd-rxq-show", "[-pmd core] " "[-secs secs] [dp]", - 0, 5, dpif_netdev_pmd_info, + 0, 5, OVS_OUTPUT_FMT_TEXT, dpif_netdev_pmd_info, (void *)&poll_aux); unixctl_command_register("dpif-netdev/pmd-sleep-show", "[dp]", - 0, 1, dpif_netdev_pmd_info, + 0, 1, OVS_OUTPUT_FMT_TEXT, dpif_netdev_pmd_info, (void *)&sleep_aux); unixctl_command_register("dpif-netdev/pmd-perf-show", "[-nh] [-it iter-history-len]" " [-ms ms-history-len]" " [-pmd core] [dp]", - 0, 8, pmd_perf_show_cmd, + 0, 8, OVS_OUTPUT_FMT_TEXT, pmd_perf_show_cmd, NULL); unixctl_command_register("dpif-netdev/pmd-rxq-rebalance", "[dp]", - 0, 1, dpif_netdev_pmd_rebalance, - NULL); + 0, 1, OVS_OUTPUT_FMT_TEXT, + dpif_netdev_pmd_rebalance, NULL); unixctl_command_register("dpif-netdev/pmd-perf-log-set", "on|off [-b before] [-a after] [-e|-ne] " "[-us usec] [-q qlen]", - 0, 10, pmd_perf_log_set_cmd, + 0, 10, OVS_OUTPUT_FMT_TEXT, pmd_perf_log_set_cmd, NULL); unixctl_command_register("dpif-netdev/bond-show", "[dp]", - 0, 1, dpif_netdev_bond_show, + 0, 1, OVS_OUTPUT_FMT_TEXT, dpif_netdev_bond_show, NULL); unixctl_command_register("dpif-netdev/subtable-lookup-prio-set", "[lookup_func] [prio]", - 2, 2, dpif_netdev_subtable_lookup_set, - NULL); + 2, 2, OVS_OUTPUT_FMT_TEXT, + dpif_netdev_subtable_lookup_set, NULL); unixctl_command_register("dpif-netdev/subtable-lookup-info-get", "", - 0, 0, dpif_netdev_subtable_lookup_get, - NULL); + 0, 0, OVS_OUTPUT_FMT_TEXT, + dpif_netdev_subtable_lookup_get, NULL); unixctl_command_register("dpif-netdev/subtable-lookup-prio-get", NULL, - 0, 0, dpif_netdev_subtable_lookup_get, - NULL); + 0, 0, OVS_OUTPUT_FMT_TEXT, + dpif_netdev_subtable_lookup_get, NULL); unixctl_command_register("dpif-netdev/dpif-impl-set", "dpif_implementation_name", - 1, 1, dpif_netdev_impl_set, + 1, 1, OVS_OUTPUT_FMT_TEXT, dpif_netdev_impl_set, NULL); unixctl_command_register("dpif-netdev/dpif-impl-get", "", - 0, 0, dpif_netdev_impl_get, + 0, 0, OVS_OUTPUT_FMT_TEXT, dpif_netdev_impl_get, NULL); unixctl_command_register("dpif-netdev/miniflow-parser-set", "[-pmd core] miniflow_implementation_name" " [study_pkt_cnt]", - 1, 5, dpif_miniflow_extract_impl_set, - NULL); + 1, 5, OVS_OUTPUT_FMT_TEXT, + dpif_miniflow_extract_impl_set, NULL); unixctl_command_register("dpif-netdev/miniflow-parser-get", "", - 0, 0, dpif_miniflow_extract_impl_get, - NULL); + 0, 0, OVS_OUTPUT_FMT_TEXT, + dpif_miniflow_extract_impl_get, NULL); return 0; } @@ -9833,7 +9844,9 @@ const struct dpif_class dpif_netdev_class = { static void dpif_dummy_change_port_number(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct dp_netdev_port *port; struct dp_netdev *dp; @@ -9929,7 +9942,8 @@ dpif_dummy_register(enum dummy_level level) unixctl_command_register("dpif-dummy/change-port-number", "dp port new-number", - 3, 3, dpif_dummy_change_port_number, NULL); + 3, 3, OVS_OUTPUT_FMT_TEXT, + dpif_dummy_change_port_number, NULL); } /* Datapath Classifier. */ diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 9194971d3..1b0771c4c 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -124,7 +124,9 @@ dpif_netlink_set_features(struct dpif *dpif_, uint32_t new_features); static void dpif_netlink_unixctl_dispatch_mode(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux); struct dpif_netlink_flow { /* Generic Netlink header. */ @@ -4651,6 +4653,7 @@ dpif_netlink_init(void) ovs_tunnels_out_of_tree = dpif_netlink_rtnl_probe_oot_tunnels(); unixctl_command_register("dpif-netlink/dispatch-mode", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, dpif_netlink_unixctl_dispatch_mode, NULL); ovsthread_once_done(&once); @@ -5304,6 +5307,7 @@ static void dpif_netlink_unixctl_dispatch_mode(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds reply = DS_EMPTY_INITIALIZER; diff --git a/lib/lacp.c b/lib/lacp.c index 3252f17eb..9923efb72 100644 --- a/lib/lacp.c +++ b/lib/lacp.c @@ -225,10 +225,11 @@ parse_lacp_packet(const struct dp_packet *p, enum pdu_subtype *subtype) void lacp_init(void) { - unixctl_command_register("lacp/show", "[port]", 0, 1, + unixctl_command_register("lacp/show", "[port]", 0, 1, OVS_OUTPUT_FMT_TEXT, lacp_unixctl_show, NULL); unixctl_command_register("lacp/show-stats", "[port]", 0, 1, - lacp_unixctl_show_stats, NULL); + OVS_OUTPUT_FMT_TEXT, lacp_unixctl_show_stats, + NULL); } static void @@ -1114,6 +1115,7 @@ lacp_print_stats(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex) static void lacp_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -1144,6 +1146,7 @@ static void lacp_unixctl_show_stats(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) { struct ds ds = DS_EMPTY_INITIALIZER; diff --git a/lib/memory.c b/lib/memory.c index da97476c6..cd6950aa3 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -160,7 +160,8 @@ memory_report(const struct simap *usage) static void memory_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { conns = xrealloc(conns, (n_conns + 1) * sizeof *conns); conns[n_conns++] = conn; @@ -173,7 +174,7 @@ memory_init(void) if (!inited) { inited = true; - unixctl_command_register("memory/show", "", 0, 0, + unixctl_command_register("memory/show", "", 0, 0, OVS_OUTPUT_FMT_TEXT, memory_unixctl_show, NULL); next_check = time_boot_msec() + MEMORY_CHECK_INTERVAL; diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index 55700250d..bd3ca4cc8 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -4217,7 +4217,9 @@ netdev_dpdk_set_admin_state__(struct netdev_dpdk *dev, bool admin_state) static void netdev_dpdk_set_admin_state(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { bool up; @@ -4262,7 +4264,9 @@ netdev_dpdk_set_admin_state(struct unixctl_conn *conn, int argc, static void netdev_dpdk_detach(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds used_interfaces = DS_EMPTY_INITIALIZER; struct rte_eth_dev_info dev_info; @@ -4329,6 +4333,7 @@ error: static void netdev_dpdk_get_mempool_info(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { size_t size; @@ -4841,19 +4846,22 @@ netdev_dpdk_class_init(void) ovs_thread_create("dpdk_watchdog", dpdk_watchdog, NULL); unixctl_command_register("netdev-dpdk/set-admin-state", "[netdev] up|down", 1, 2, + OVS_OUTPUT_FMT_TEXT, netdev_dpdk_set_admin_state, NULL); unixctl_command_register("netdev-dpdk/detach", "pci address of device", 1, 1, + OVS_OUTPUT_FMT_TEXT, netdev_dpdk_detach, NULL); unixctl_command_register("netdev-dpdk/get-mempool-info", - "[netdev]", 0, 1, + "[netdev]", 0, 1, OVS_OUTPUT_FMT_TEXT, netdev_dpdk_get_mempool_info, NULL); ret = rte_eth_dev_callback_register(RTE_ETH_ALL, RTE_ETH_EVENT_INTR_RESET, - dpdk_eth_event_callback, NULL); + dpdk_eth_event_callback, + NULL); if (ret != 0) { VLOG_ERR("Ethernet device callback register error: %s", rte_strerror(-ret)); diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c index 1a54add87..37484d234 100644 --- a/lib/netdev-dummy.c +++ b/lib/netdev-dummy.c @@ -1848,7 +1848,8 @@ netdev_dummy_queue_packet(struct netdev_dummy *dummy, struct dp_packet *packet, static void netdev_dummy_receive(struct unixctl_conn *conn, - int argc, const char *argv[], void *aux OVS_UNUSED) + int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct netdev_dummy *dummy_dev; struct netdev *netdev; @@ -1931,7 +1932,9 @@ netdev_dummy_set_admin_state__(struct netdev_dummy *dev, bool admin_state) static void netdev_dummy_set_admin_state(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { bool up; @@ -1997,7 +2000,9 @@ display_conn_state__(struct ds *s, const char *name, static void netdev_dummy_conn_state(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { enum dummy_netdev_conn_state state = CONN_STATE_UNKNOWN; struct ds s; @@ -2039,7 +2044,9 @@ netdev_dummy_conn_state(struct unixctl_conn *conn, int argc, static void netdev_dummy_ip4addr(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct netdev *netdev = netdev_from_name(argv[1]); @@ -2064,7 +2071,8 @@ netdev_dummy_ip4addr(struct unixctl_conn *conn, int argc OVS_UNUSED, static void netdev_dummy_ip6addr(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct netdev *netdev = netdev_from_name(argv[1]); @@ -2116,18 +2124,20 @@ netdev_dummy_register(enum dummy_level level) { unixctl_command_register("netdev-dummy/receive", "name [--qid queue_id] packet|flow [--len packet_len]", - 2, INT_MAX, netdev_dummy_receive, NULL); + 2, INT_MAX, OVS_OUTPUT_FMT_TEXT, + netdev_dummy_receive, NULL); unixctl_command_register("netdev-dummy/set-admin-state", - "[netdev] up|down", 1, 2, + "[netdev] up|down", 1, 2, OVS_OUTPUT_FMT_TEXT, netdev_dummy_set_admin_state, NULL); unixctl_command_register("netdev-dummy/conn-state", - "[netdev]", 0, 1, + "[netdev]", 0, 1, OVS_OUTPUT_FMT_TEXT, netdev_dummy_conn_state, NULL); unixctl_command_register("netdev-dummy/ip4addr", "[netdev] ipaddr/mask-prefix-len", 2, 2, - netdev_dummy_ip4addr, NULL); + OVS_OUTPUT_FMT_TEXT, netdev_dummy_ip4addr, + NULL); unixctl_command_register("netdev-dummy/ip6addr", - "[netdev] ip6addr", 2, 2, + "[netdev] ip6addr", 2, 2, OVS_OUTPUT_FMT_TEXT, netdev_dummy_ip6addr, NULL); if (level == DUMMY_OVERRIDE_ALL) { diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index a0682c70f..95fb56333 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -1181,7 +1181,9 @@ netdev_geneve_build_header(const struct netdev *netdev, void netdev_tnl_egress_port_range(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { int val1, val2; diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h index eb55dd041..e5d067d97 100644 --- a/lib/netdev-native-tnl.h +++ b/lib/netdev-native-tnl.h @@ -142,5 +142,7 @@ netdev_tnl_push_ip_header(struct dp_packet *packet, const void *header, int size, int *ip_tot_size, ovs_be32 ipv6_label); void netdev_tnl_egress_port_range(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED); + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED); #endif diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 60caa02fb..1acd0e5bf 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -1389,6 +1389,7 @@ netdev_vport_tunnel_register(void) } unixctl_command_register("tnl/egress_port_range", "min max", 0, 2, + OVS_OUTPUT_FMT_TEXT, netdev_tnl_egress_port_range, NULL); ovsthread_once_done(&once); diff --git a/lib/odp-execute.c b/lib/odp-execute.c index eb03b57c4..230bd26a8 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -916,7 +916,8 @@ odp_actions_impl_set(const char *name) static void action_impl_set(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds reply = DS_EMPTY_INITIALIZER; @@ -936,7 +937,8 @@ action_impl_set(struct unixctl_conn *conn, int argc OVS_UNUSED, static void action_impl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds reply = DS_EMPTY_INITIALIZER; @@ -949,10 +951,10 @@ static void odp_execute_unixctl_init(void) { unixctl_command_register("odp-execute/action-impl-set", "name", - 1, 1, action_impl_set, + 1, 1, OVS_OUTPUT_FMT_TEXT, action_impl_set, NULL); unixctl_command_register("odp-execute/action-impl-show", "", - 0, 0, action_impl_show, + 0, 0, OVS_OUTPUT_FMT_TEXT, action_impl_show, NULL); } diff --git a/lib/ovs-lldp.c b/lib/ovs-lldp.c index 2d13e971e..8dbc037a5 100644 --- a/lib/ovs-lldp.c +++ b/lib/ovs-lldp.c @@ -326,7 +326,8 @@ aa_print_isid_status(struct ds *ds, struct lldp *lldp) OVS_REQUIRES(mutex) static void aa_unixctl_status(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) { struct lldp *lldp; @@ -345,7 +346,8 @@ aa_unixctl_status(struct unixctl_conn *conn, int argc OVS_UNUSED, static void aa_unixctl_show_isid(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) { struct lldp *lldp; @@ -364,7 +366,8 @@ aa_unixctl_show_isid(struct unixctl_conn *conn, int argc OVS_UNUSED, static void aa_unixctl_statistics(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) OVS_EXCLUDED(mutex) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -644,11 +647,12 @@ void lldp_init(void) { unixctl_command_register("autoattach/status", "[bridge]", 0, 1, - aa_unixctl_status, NULL); + OVS_OUTPUT_FMT_TEXT, aa_unixctl_status, NULL); unixctl_command_register("autoattach/show-isid", "[bridge]", 0, 1, - aa_unixctl_show_isid, NULL); + OVS_OUTPUT_FMT_TEXT, aa_unixctl_show_isid, NULL); unixctl_command_register("autoattach/statistics", "[bridge]", 0, 1, - aa_unixctl_statistics, NULL); + OVS_OUTPUT_FMT_TEXT, aa_unixctl_statistics, + NULL); } /* Returns true if 'lldp' should process packets from 'flow'. Sets diff --git a/lib/ovs-router.c b/lib/ovs-router.c index 7c04bb0e6..993bc452e 100644 --- a/lib/ovs-router.c +++ b/lib/ovs-router.c @@ -389,8 +389,8 @@ scan_ipv4_route(const char *s, ovs_be32 *addr, unsigned int *plen) } static void -ovs_router_add(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) +ovs_router_add(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct in6_addr src6 = in6addr_any; struct in6_addr gw6 = in6addr_any; @@ -463,7 +463,8 @@ ovs_router_add(struct unixctl_conn *conn, int argc, static void ovs_router_del(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct in6_addr ip6; uint32_t mark = 0; @@ -494,7 +495,8 @@ ovs_router_del(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovs_router_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ovs_router_entry *rt; struct ds ds = DS_EMPTY_INITIALIZER; @@ -534,8 +536,9 @@ ovs_router_show(struct unixctl_conn *conn, int argc OVS_UNUSED, } static void -ovs_router_lookup_cmd(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) +ovs_router_lookup_cmd(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct in6_addr gw, src = in6addr_any; char iface[IFNAMSIZ]; @@ -605,14 +608,15 @@ ovs_router_init(void) unixctl_command_register("ovs/route/add", "ip/plen output_bridge [gw] " "[pkt_mark=mark] [src=src_ip]", - 2, 5, ovs_router_add, NULL); + 2, 5, OVS_OUTPUT_FMT_TEXT, ovs_router_add, + NULL); unixctl_command_register("ovs/route/show", "", 0, 0, - ovs_router_show, NULL); + OVS_OUTPUT_FMT_TEXT, ovs_router_show, NULL); unixctl_command_register("ovs/route/del", "ip/plen " - "[pkt_mark=mark]", 1, 2, ovs_router_del, - NULL); + "[pkt_mark=mark]", 1, 2, OVS_OUTPUT_FMT_TEXT, + ovs_router_del, NULL); unixctl_command_register("ovs/route/lookup", "ip_addr " - "[pkt_mark=mark]", 1, 2, + "[pkt_mark=mark]", 1, 2, OVS_OUTPUT_FMT_TEXT, ovs_router_lookup_cmd, NULL); ovsthread_once_done(&once); } diff --git a/lib/rstp.c b/lib/rstp.c index 2f01966f7..0f5a0e91d 100644 --- a/lib/rstp.c +++ b/lib/rstp.c @@ -129,9 +129,11 @@ static struct rstp_port *rstp_get_root_port__(const struct rstp *rstp) static rstp_identifier rstp_get_root_id__(const struct rstp *rstp) OVS_REQUIRES(rstp_mutex); static void rstp_unixctl_tcn(struct unixctl_conn *, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux); static void rstp_unixctl_show(struct unixctl_conn *, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux); const char * rstp_state_name(enum rstp_state state) @@ -248,10 +250,10 @@ void rstp_init(void) OVS_EXCLUDED(rstp_mutex) { - unixctl_command_register("rstp/tcn", "[bridge]", 0, 1, rstp_unixctl_tcn, - NULL); - unixctl_command_register("rstp/show", "[bridge]", 0, 1, rstp_unixctl_show, - NULL); + unixctl_command_register("rstp/tcn", "[bridge]", 0, 1, + OVS_OUTPUT_FMT_TEXT, rstp_unixctl_tcn, NULL); + unixctl_command_register("rstp/show", "[bridge]", 0, 1, + OVS_OUTPUT_FMT_TEXT, rstp_unixctl_show, NULL); } /* Creates and returns a new RSTP instance that initially has no ports. */ @@ -1550,8 +1552,8 @@ rstp_find(const char *name) } static void -rstp_unixctl_tcn(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) +rstp_unixctl_tcn(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) OVS_EXCLUDED(rstp_mutex) { ovs_mutex_lock(&rstp_mutex); @@ -1651,8 +1653,8 @@ rstp_print_details(struct ds *ds, const struct rstp *rstp) } static void -rstp_unixctl_show(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) +rstp_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) OVS_EXCLUDED(rstp_mutex) { struct ds ds = DS_EMPTY_INITIALIZER; diff --git a/lib/stopwatch.c b/lib/stopwatch.c index ec567603b..70fcc2979 100644 --- a/lib/stopwatch.c +++ b/lib/stopwatch.c @@ -314,7 +314,8 @@ stopwatch_show_protected(int argc, const char *argv[], struct ds *s) static void stopwatch_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds s = DS_EMPTY_INITIALIZER; bool success; @@ -351,7 +352,8 @@ stopwatch_packet_write(struct stopwatch_packet *pkt) static void stopwatch_reset(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct stopwatch_packet *pkt = stopwatch_packet_create(OP_RESET); if (argc > 1) { @@ -488,9 +490,9 @@ static void do_init_stopwatch(void) { unixctl_command_register("stopwatch/show", "[NAME]", 0, 1, - stopwatch_show, NULL); + OVS_OUTPUT_FMT_TEXT, stopwatch_show, NULL); unixctl_command_register("stopwatch/reset", "[NAME]", 0, 1, - stopwatch_reset, NULL); + OVS_OUTPUT_FMT_TEXT, stopwatch_reset, NULL); guarded_list_init(&stopwatch_commands); latch_init(&stopwatch_latch); stopwatch_thread_id = ovs_thread_create( diff --git a/lib/stp.c b/lib/stp.c index f37337992..0d1b6b053 100644 --- a/lib/stp.c +++ b/lib/stp.c @@ -233,9 +233,11 @@ static bool stp_timer_expired(struct stp_timer *, int elapsed, int timeout); static void stp_send_bpdu(struct stp_port *, const void *, size_t) OVS_REQUIRES(mutex); static void stp_unixctl_tcn(struct unixctl_conn *, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux); static void stp_unixctl_show(struct unixctl_conn *, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux); void stp_init(void) @@ -249,10 +251,10 @@ stp_init(void) * the call back function, but for now this is what we have. */ ovs_mutex_init_recursive(&mutex); - unixctl_command_register("stp/tcn", "[bridge]", 0, 1, stp_unixctl_tcn, - NULL); + unixctl_command_register("stp/tcn", "[bridge]", 0, 1, + OVS_OUTPUT_FMT_TEXT, stp_unixctl_tcn, NULL); unixctl_command_register("stp/show", "[bridge]", 0, 1, - stp_unixctl_show, NULL); + OVS_OUTPUT_FMT_TEXT, stp_unixctl_show, NULL); ovsthread_once_done(&once); } } @@ -1611,8 +1613,8 @@ stp_find(const char *name) OVS_REQUIRES(mutex) } static void -stp_unixctl_tcn(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) +stp_unixctl_tcn(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { ovs_mutex_lock(&mutex); if (argc > 1) { @@ -1702,8 +1704,8 @@ stp_print_details(struct ds *ds, const struct stp *stp) } static void -stp_unixctl_show(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) +stp_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; diff --git a/lib/timeval.c b/lib/timeval.c index 193c7bab1..5efe9da20 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -765,8 +765,9 @@ get_cpu_usage(void) * advancing, except due to later calls to "time/warp". */ static void timeval_stop_cb(struct unixctl_conn *conn, - int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, - void *aux OVS_UNUSED) + int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { ovs_mutex_lock(&monotonic_clock.mutex); atomic_store_relaxed(&monotonic_clock.slow_path, true); @@ -789,7 +790,8 @@ timeval_stop_cb(struct unixctl_conn *conn, * Does not affect wall clock readings. */ static void timeval_warp_cb(struct unixctl_conn *conn, - int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED) + int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { long long int total_warp = argc > 2 ? atoll(argv[1]) : 0; long long int msecs = argc > 2 ? atoll(argv[2]) : atoll(argv[1]); @@ -818,9 +820,10 @@ void timeval_dummy_register(void) { timewarp_enabled = true; - unixctl_command_register("time/stop", "", 0, 0, timeval_stop_cb, NULL); + unixctl_command_register("time/stop", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + timeval_stop_cb, NULL); unixctl_command_register("time/warp", "[large_msecs] msecs", 1, 2, - timeval_warp_cb, NULL); + OVS_OUTPUT_FMT_TEXT, timeval_warp_cb, NULL); } diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c index bdff1debc..b8aeee29a 100644 --- a/lib/tnl-neigh-cache.c +++ b/lib/tnl-neigh-cache.c @@ -273,7 +273,9 @@ tnl_neigh_flush(const char br_name[IFNAMSIZ]) static void tnl_neigh_cache_flush(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct tnl_neigh_entry *neigh; bool changed = false; @@ -291,8 +293,9 @@ tnl_neigh_cache_flush(struct unixctl_conn *conn, int argc OVS_UNUSED, } static void -tnl_neigh_cache_aging(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) +tnl_neigh_cache_aging(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { long long int new_exp, curr_exp; struct tnl_neigh_entry *neigh; @@ -348,7 +351,8 @@ lookup_any(const char *host_name, struct in6_addr *address) static void tnl_neigh_cache_add(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { const char *br_name = argv[1]; struct eth_addr mac; @@ -370,7 +374,9 @@ tnl_neigh_cache_add(struct unixctl_conn *conn, int argc OVS_UNUSED, static void tnl_neigh_cache_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; struct tnl_neigh_entry *neigh; @@ -404,20 +410,23 @@ void tnl_neigh_cache_init(void) { atomic_init(&neigh_aging, NEIGH_ENTRY_DEFAULT_IDLE_TIME_MS); - unixctl_command_register("tnl/arp/show", "", 0, 0, + unixctl_command_register("tnl/arp/show", "", 0, 0, OVS_OUTPUT_FMT_TEXT, tnl_neigh_cache_show, NULL); unixctl_command_register("tnl/arp/set", "BRIDGE IP MAC", 3, 3, - tnl_neigh_cache_add, NULL); + OVS_OUTPUT_FMT_TEXT, tnl_neigh_cache_add, NULL); unixctl_command_register("tnl/arp/flush", "", 0, 0, - tnl_neigh_cache_flush, NULL); + OVS_OUTPUT_FMT_TEXT, tnl_neigh_cache_flush, + NULL); unixctl_command_register("tnl/arp/aging", "[SECS]", 0, 1, - tnl_neigh_cache_aging, NULL); + OVS_OUTPUT_FMT_TEXT, tnl_neigh_cache_aging, + NULL); unixctl_command_register("tnl/neigh/show", "", 0, 0, - tnl_neigh_cache_show, NULL); + OVS_OUTPUT_FMT_TEXT, tnl_neigh_cache_show, NULL); unixctl_command_register("tnl/neigh/set", "BRIDGE IP MAC", 3, 3, - tnl_neigh_cache_add, NULL); - unixctl_command_register("tnl/neigh/flush", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, tnl_neigh_cache_add, NULL); + unixctl_command_register("tnl/neigh/flush", "", 0, 0, OVS_OUTPUT_FMT_TEXT, tnl_neigh_cache_flush, NULL); unixctl_command_register("tnl/neigh/aging", "[SECS]", 0, 1, - tnl_neigh_cache_aging, NULL); + OVS_OUTPUT_FMT_TEXT, tnl_neigh_cache_aging, + NULL); } diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c index f16409a0b..9e3d7064a 100644 --- a/lib/tnl-ports.c +++ b/lib/tnl-ports.c @@ -354,7 +354,8 @@ tnl_port_show_v(struct ds *ds) static void tnl_port_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; struct tnl_port *p; @@ -523,5 +524,6 @@ tnl_port_map_init(void) classifier_init(&cls, flow_segment_u64s); ovs_list_init(&addr_list); ovs_list_init(&port_list); - unixctl_command_register("tnl/ports/show", "-v", 0, 1, tnl_port_show, NULL); + unixctl_command_register("tnl/ports/show", "-v", 0, 1, + OVS_OUTPUT_FMT_TEXT, tnl_port_show, NULL); } diff --git a/lib/unixctl.c b/lib/unixctl.c index 103357ee9..1a66cd0c8 100644 --- a/lib/unixctl.c +++ b/lib/unixctl.c @@ -21,7 +21,6 @@ #include "coverage.h" #include "dirs.h" #include "openvswitch/dynamic-string.h" -#include "openvswitch/json.h" #include "jsonrpc.h" #include "openvswitch/list.h" #include "openvswitch/poll-loop.h" @@ -39,6 +38,7 @@ COVERAGE_DEFINE(unixctl_replied); struct unixctl_command { const char *usage; int min_args, max_args; + int output_fmts; unixctl_cb_func *cb; void *aux; }; @@ -65,15 +65,16 @@ static struct shash commands = SHASH_INITIALIZER(&commands); static void unixctl_list_commands(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; - const struct shash_node **nodes = shash_sort(&commands); - size_t i; + const struct shash_node **nodes = shash_sort(&commands); ds_put_cstr(&ds, "The available commands are:\n"); - for (i = 0; i < shash_count(&commands); i++) { + for (size_t i = 0; i < shash_count(&commands); i++) { const struct shash_node *node = nodes[i]; const struct unixctl_command *command = node->data; @@ -89,7 +90,9 @@ unixctl_list_commands(struct unixctl_conn *conn, int argc OVS_UNUSED, static void unixctl_version(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { unixctl_command_reply(conn, ovs_get_program_version()); } @@ -107,7 +110,7 @@ unixctl_version(struct unixctl_conn *conn, int argc OVS_UNUSED, * made eventually to avoid blocking that connection. */ void unixctl_command_register(const char *name, const char *usage, - int min_args, int max_args, + int min_args, int max_args, int output_fmts, unixctl_cb_func *cb, void *aux) { struct unixctl_command *command; @@ -123,41 +126,48 @@ unixctl_command_register(const char *name, const char *usage, command->usage = usage; command->min_args = min_args; command->max_args = max_args; + command->output_fmts = output_fmts; command->cb = cb; command->aux = aux; shash_add(&commands, name, command); } -static void -unixctl_command_reply__(struct unixctl_conn *conn, - bool success, const char *body) +static struct json * +json_string_create__(const char *body) { - struct json *body_json; - struct jsonrpc_msg *reply; - - COVERAGE_INC(unixctl_replied); - ovs_assert(conn->request_id); - if (!body) { body = ""; } if (body[0] && body[strlen(body) - 1] != '\n') { - body_json = json_string_create_nocopy(xasprintf("%s\n", body)); + return json_string_create_nocopy(xasprintf("%s\n", body)); } else { - body_json = json_string_create(body); + return json_string_create(body); } +} + +/* Takes ownership of 'body'. */ +static void +unixctl_command_reply__(struct unixctl_conn *conn, + bool success, struct json *body) +{ + struct jsonrpc_msg *reply; + + COVERAGE_INC(unixctl_replied); + ovs_assert(conn->request_id); if (success) { - reply = jsonrpc_create_reply(body_json, conn->request_id); + reply = jsonrpc_create_reply(body, conn->request_id); } else { - reply = jsonrpc_create_error(body_json, conn->request_id); + reply = jsonrpc_create_error(body, conn->request_id); } if (VLOG_IS_DBG_ENABLED()) { char *id = json_to_string(conn->request_id, 0); + char *msg = json_to_string(body, 0); VLOG_DBG("replying with %s, id=%s: \"%s\"", - success ? "success" : "error", id, body); + success ? "success" : "error", id, msg); + free(msg); free(id); } @@ -170,22 +180,34 @@ unixctl_command_reply__(struct unixctl_conn *conn, /* Replies to the active unixctl connection 'conn'. 'result' is sent to the * client indicating the command was processed successfully. Only one call to - * unixctl_command_reply() or unixctl_command_reply_error() may be made per - * request. */ + * unixctl_command_reply(), unixctl_command_reply_error() or + * unixctl_command_reply_json() may be made per request. */ void unixctl_command_reply(struct unixctl_conn *conn, const char *result) { - unixctl_command_reply__(conn, true, result); + unixctl_command_reply__(conn, true, json_string_create__(result)); } /* Replies to the active unixctl connection 'conn'. 'error' is sent to the - * client indicating an error occurred processing the command. Only one call to - * unixctl_command_reply() or unixctl_command_reply_error() may be made per - * request. */ + * client indicating an error occurred processing the command. Only one call + * to unixctl_command_reply(), unixctl_command_reply_error() or + * unixctl_command_reply_json() may be made per request. */ void unixctl_command_reply_error(struct unixctl_conn *conn, const char *error) { - unixctl_command_reply__(conn, false, error); + unixctl_command_reply__(conn, false, json_string_create__(error)); +} + +/* Replies to the active unixctl connection 'conn'. 'result' is sent to the + * client indicating the command was processed successfully. Only one call to + * unixctl_command_reply(), unixctl_command_reply_error() or + * unixctl_command_reply_json() may be made per request. + * + * Takes ownership of 'body'. */ +void +unixctl_command_reply_json(struct unixctl_conn *conn, struct json *body) +{ + unixctl_command_reply__(conn, true, body); } /* Creates a unixctl server listening on 'path', which for POSIX may be: @@ -247,9 +269,10 @@ unixctl_server_create(const char *path, struct unixctl_server **serverp) return error; } - unixctl_command_register("list-commands", "", 0, 0, unixctl_list_commands, - NULL); - unixctl_command_register("version", "", 0, 0, unixctl_version, NULL); + unixctl_command_register("list-commands", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + unixctl_list_commands, NULL); + unixctl_command_register("version", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + unixctl_version, NULL); struct unixctl_server *server = xmalloc(sizeof *server); server->listener = listener; @@ -266,6 +289,9 @@ process_command(struct unixctl_conn *conn, struct jsonrpc_msg *request) struct unixctl_command *command; struct json_array *params; + const char *method; + enum ovs_output_fmt fmt; + struct svec argv = SVEC_EMPTY_INITIALIZER; COVERAGE_INC(unixctl_received); conn->request_id = json_clone(request->id); @@ -279,45 +305,72 @@ process_command(struct unixctl_conn *conn, struct jsonrpc_msg *request) free(id_s); } + if (strcmp(request->method, "execute/v1")) { + error = xasprintf("JSON-RPC API mismatch: Unexpected command \"%s\".", + request->method); + goto error; + } + params = json_array(request->params); - command = shash_find_data(&commands, request->method); + if (params->n < 2) { + error = xasprintf("JSON-RPC API mismatch: Unexpected # of params:"\ + " %"PRIuSIZE, params->n); + goto error; + } + + for (size_t i = 0; i < params->n; i++) { + if (params->elems[i]->type != JSON_STRING) { + error = xasprintf("command has non-string argument: %s", + json_to_string(params->elems[i], 0)); + goto error; + } + } + + method = json_string(params->elems[0]); + if (!ovs_output_fmt_from_string(json_string(params->elems[1]), &fmt)) { + error = xasprintf("invalid output format: %s", + json_string(params->elems[1])); + goto error; + } + + command = shash_find_data(&commands, method); if (!command) { error = xasprintf("\"%s\" is not a valid command (use " "\"list-commands\" to see a list of valid commands)", - request->method); - } else if (params->n < command->min_args) { + method); + goto error; + } else if ((params->n - 2) < command->min_args) { error = xasprintf("\"%s\" command requires at least %d arguments", - request->method, command->min_args); - } else if (params->n > command->max_args) { + method, command->min_args); + goto error; + } else if ((params->n - 2) > command->max_args) { error = xasprintf("\"%s\" command takes at most %d arguments", - request->method, command->max_args); - } else { - struct svec argv = SVEC_EMPTY_INITIALIZER; - int i; - - svec_add(&argv, request->method); - for (i = 0; i < params->n; i++) { - if (params->elems[i]->type != JSON_STRING) { - error = xasprintf("\"%s\" command has non-string argument", - request->method); - break; - } - svec_add(&argv, json_string(params->elems[i])); - } - svec_terminate(&argv); - - if (!error) { - command->cb(conn, argv.n, (const char **) argv.names, - command->aux); - } - - svec_destroy(&argv); + method, command->max_args); + goto error; + } else if ((!command->output_fmts && fmt != OVS_OUTPUT_FMT_TEXT) || + (command->output_fmts && !(fmt & command->output_fmts))) + { + error = xasprintf("\"%s\" command does not support output format"\ + " \"%s\" %d %d", method, + ovs_output_fmt_to_string(fmt), command->output_fmts, + fmt); + goto error; } - if (error) { - unixctl_command_reply_error(conn, error); - free(error); + svec_add(&argv, method); + for (size_t i = 2; i < params->n; i++) { + svec_add(&argv, json_string(params->elems[i])); } + svec_terminate(&argv); + + command->cb(conn, argv.n, (const char **) argv.names, fmt, command->aux); + + svec_destroy(&argv); + + return; +error: + unixctl_command_reply_error(conn, error); + free(error); } static int @@ -483,7 +536,8 @@ unixctl_client_create(const char *path, struct jsonrpc **client) * '*err' if not NULL. */ int unixctl_client_transact(struct jsonrpc *client, const char *command, int argc, - char *argv[], char **result, char **err) + char *argv[], enum ovs_output_fmt fmt, + char **result, char **err) { struct jsonrpc_msg *request, *reply; struct json **json_args, *params; @@ -492,12 +546,19 @@ unixctl_client_transact(struct jsonrpc *client, const char *command, int argc, *result = NULL; *err = NULL; - json_args = xmalloc(argc * sizeof *json_args); + json_args = xmalloc((argc + 2) * sizeof *json_args); + json_args[0] = json_string_create(command); + json_args[1] = ovs_output_fmt_to_json(fmt); for (i = 0; i < argc; i++) { - json_args[i] = json_string_create(argv[i]); + json_args[i + 2] = json_string_create(argv[i]); } - params = json_array_create(json_args, argc); - request = jsonrpc_create_request(command, params, NULL); + + params = json_array_create(json_args, argc + 2); + + /* Use a versioned command to ensure that both server and client + * use the same JSON-RPC API. + */ + request = jsonrpc_create_request("execute/v1", params, NULL); error = jsonrpc_transact_block(client, request, &reply); if (error) { @@ -518,6 +579,20 @@ unixctl_client_transact(struct jsonrpc *client, const char *command, int argc, } else if (reply->result) { if (reply->result->type == JSON_STRING) { *result = xstrdup(json_string(reply->result)); + } else if (reply->result->type == JSON_OBJECT || + reply->result->type == JSON_ARRAY) { + /* TODO: How about other result types? */ + + /* TODO: Do we really want to prettyfy and sort the output? + * The benefit for users is probably minimal because they could + * simply use jq to format the output if needed. Since JSON output + * is meant to be consumed by machines, this pretty-printing is + * probably unnecessary in most cases. + * However, it might have its use in our unit tests because it + * allows us to make readable checks without having to introduce a + * dependency on jq. + */ + *result = json_to_string(reply->result, JSSF_PRETTY | JSSF_SORT); } else { VLOG_WARN("%s: unexpected result type in JSON rpc reply: %s", jsonrpc_get_name(client), diff --git a/lib/unixctl.h b/lib/unixctl.h index 4562dbc49..4b8193d9d 100644 --- a/lib/unixctl.h +++ b/lib/unixctl.h @@ -17,6 +17,9 @@ #ifndef UNIXCTL_H #define UNIXCTL_H 1 +#include "openvswitch/json.h" +#include "command-line.h" + #ifdef __cplusplus extern "C" { #endif @@ -36,17 +39,21 @@ int unixctl_client_create(const char *path, struct jsonrpc **client); int unixctl_client_transact(struct jsonrpc *client, const char *command, int argc, char *argv[], + enum ovs_output_fmt fmt, char **result, char **error); /* Command registration. */ struct unixctl_conn; typedef void unixctl_cb_func(struct unixctl_conn *, - int argc, const char *argv[], void *aux); + int argc, const char *argv[], + enum ovs_output_fmt fmt, void *aux); void unixctl_command_register(const char *name, const char *usage, - int min_args, int max_args, + int min_args, int max_args, int output_fmts, unixctl_cb_func *cb, void *aux); void unixctl_command_reply_error(struct unixctl_conn *, const char *error); void unixctl_command_reply(struct unixctl_conn *, const char *body); +void unixctl_command_reply_json(struct unixctl_conn *, + struct json *body); #ifdef __cplusplus } diff --git a/lib/vlog.c b/lib/vlog.c index b2653142f..a8ab97b1b 100644 --- a/lib/vlog.c +++ b/lib/vlog.c @@ -689,6 +689,7 @@ vlog_facility_exists(const char* facility, int *value) static void vlog_unixctl_set(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { int i; @@ -710,7 +711,8 @@ vlog_unixctl_set(struct unixctl_conn *conn, int argc, const char *argv[], static void vlog_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { char *msg = vlog_get_levels(); unixctl_command_reply(conn, msg); @@ -719,7 +721,9 @@ vlog_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED, static void vlog_unixctl_list_pattern(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { char *msg; @@ -730,7 +734,9 @@ vlog_unixctl_list_pattern(struct unixctl_conn *conn, int argc OVS_UNUSED, static void vlog_unixctl_reopen(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { bool has_log_file; @@ -752,7 +758,9 @@ vlog_unixctl_reopen(struct unixctl_conn *conn, int argc OVS_UNUSED, static void vlog_unixctl_close(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { ovs_mutex_lock(&log_file_mutex); if (log_fd >= 0) { @@ -811,14 +819,18 @@ set_rate_limits(struct unixctl_conn *conn, int argc, static void vlog_enable_rate_limit(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { set_rate_limits(conn, argc, argv, true); } static void vlog_disable_rate_limit(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { set_rate_limits(conn, argc, argv, false); } @@ -860,20 +872,24 @@ vlog_init(void) free(s); } - unixctl_command_register( - "vlog/set", "{spec | PATTERN:destination:pattern}", - 0, INT_MAX, vlog_unixctl_set, NULL); - unixctl_command_register("vlog/list", "", 0, 0, vlog_unixctl_list, - NULL); + unixctl_command_register("vlog/set", + "{spec | PATTERN:destination:pattern}", + 0, INT_MAX, OVS_OUTPUT_FMT_TEXT, + vlog_unixctl_set, NULL); + unixctl_command_register("vlog/list", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + vlog_unixctl_list, NULL); unixctl_command_register("vlog/list-pattern", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, vlog_unixctl_list_pattern, NULL); unixctl_command_register("vlog/enable-rate-limit", "[module]...", - 0, INT_MAX, vlog_enable_rate_limit, NULL); + 0, INT_MAX, OVS_OUTPUT_FMT_TEXT, + vlog_enable_rate_limit, NULL); unixctl_command_register("vlog/disable-rate-limit", "[module]...", - 0, INT_MAX, vlog_disable_rate_limit, NULL); - unixctl_command_register("vlog/reopen", "", 0, 0, + 0, INT_MAX, OVS_OUTPUT_FMT_TEXT, + vlog_disable_rate_limit, NULL); + unixctl_command_register("vlog/reopen", "", 0, 0, OVS_OUTPUT_FMT_TEXT, vlog_unixctl_reopen, NULL); - unixctl_command_register("vlog/close", "", 0, 0, + unixctl_command_register("vlog/close", "", 0, 0, OVS_OUTPUT_FMT_TEXT, vlog_unixctl_close, NULL); ovs_rwlock_rdlock(&pattern_rwlock); diff --git a/ofproto/bond.c b/ofproto/bond.c index cfdf44f85..fcab5f932 100644 --- a/ofproto/bond.c +++ b/ofproto/bond.c @@ -1472,6 +1472,7 @@ bond_lookup_member(struct bond *bond, const char *member_name) static void bond_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -1617,6 +1618,7 @@ bond_print_details(struct ds *ds, const struct bond *bond) static void bond_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -1648,6 +1650,7 @@ out: static void bond_unixctl_migrate(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { const char *bond_s = argv[1]; @@ -1701,6 +1704,7 @@ out: static void bond_unixctl_set_active_member(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { const char *bond_s = argv[1]; @@ -1773,6 +1777,7 @@ out: static void bond_unixctl_enable_member(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { enable_member(conn, argv, true); @@ -1781,6 +1786,7 @@ bond_unixctl_enable_member(struct unixctl_conn *conn, static void bond_unixctl_disable_member(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { enable_member(conn, argv, false); @@ -1788,6 +1794,7 @@ bond_unixctl_disable_member(struct unixctl_conn *conn, static void bond_unixctl_hash(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { const char *mac_s = argv[1]; @@ -1831,27 +1838,34 @@ bond_unixctl_hash(struct unixctl_conn *conn, int argc, const char *argv[], void bond_init(void) { - unixctl_command_register("bond/list", "", 0, 0, bond_unixctl_list, NULL); - unixctl_command_register("bond/show", "[port]", 0, 1, bond_unixctl_show, - NULL); + unixctl_command_register("bond/list", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + bond_unixctl_list, NULL); + unixctl_command_register("bond/show", "[port]", 0, 1, OVS_OUTPUT_FMT_TEXT, + bond_unixctl_show, NULL); unixctl_command_register("bond/migrate", "port hash member", 3, 3, - bond_unixctl_migrate, NULL); + OVS_OUTPUT_FMT_TEXT, bond_unixctl_migrate, NULL); unixctl_command_register("bond/set-active-member", "port member", 2, 2, + OVS_OUTPUT_FMT_TEXT, bond_unixctl_set_active_member, NULL); unixctl_command_register("bond/enable-member", "port member", 2, 2, - bond_unixctl_enable_member, NULL); + OVS_OUTPUT_FMT_TEXT, bond_unixctl_enable_member, + NULL); unixctl_command_register("bond/disable-member", "port member", 2, 2, - bond_unixctl_disable_member, NULL); + OVS_OUTPUT_FMT_TEXT, bond_unixctl_disable_member, + NULL); unixctl_command_register("bond/hash", "mac [vlan] [basis]", 1, 3, - bond_unixctl_hash, NULL); + OVS_OUTPUT_FMT_TEXT, bond_unixctl_hash, NULL); /* Backward-compatibility command names. */ unixctl_command_register("bond/set-active-slave", NULL, 2, 2, + OVS_OUTPUT_FMT_TEXT, bond_unixctl_set_active_member, NULL); unixctl_command_register("bond/enable-slave", NULL, 2, 2, - bond_unixctl_enable_member, NULL); + OVS_OUTPUT_FMT_TEXT, bond_unixctl_enable_member, + NULL); unixctl_command_register("bond/disable-slave", NULL, 2, 2, - bond_unixctl_disable_member, NULL); + OVS_OUTPUT_FMT_TEXT, bond_unixctl_disable_member, + NULL); } static void diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c index 527e2f17e..da31ff55b 100644 --- a/ofproto/ofproto-dpif-trace.c +++ b/ofproto/ofproto-dpif-trace.c @@ -471,6 +471,7 @@ free_ct_states(struct ovs_list *ct_states) static void ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ofproto_dpif *ofproto; @@ -500,7 +501,9 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], static void ofproto_unixctl_trace_actions(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { enum ofputil_protocol usable_protocols; struct ofproto_dpif *ofproto; @@ -870,12 +873,13 @@ ofproto_dpif_trace_init(void) unixctl_command_register( "ofproto/trace", "{[dp_name] odp_flow | bridge br_flow} [OPTIONS...] " - "[-generate|packet]", 1, INT_MAX, ofproto_unixctl_trace, NULL); + "[-generate|packet]", 1, INT_MAX, OVS_OUTPUT_FMT_TEXT, + ofproto_unixctl_trace, NULL); unixctl_command_register( "ofproto/trace-packet-out", "[-consistent] {[dp_name] odp_flow | bridge br_flow} [OPTIONS...] " "[-generate|packet] actions", - 2, INT_MAX, ofproto_unixctl_trace_actions, NULL); + 2, INT_MAX, OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_trace_actions, NULL); } void diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index cde03abc6..b5e38fd13 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -354,25 +354,38 @@ static void revalidator_pause(struct revalidator *); static void revalidator_sweep(struct revalidator *); static void revalidator_purge(struct revalidator *); static void upcall_unixctl_show(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt, + void *aux); static void upcall_unixctl_disable_megaflows(struct unixctl_conn *, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt, + void *aux); static void upcall_unixctl_enable_megaflows(struct unixctl_conn *, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt, + void *aux); static void upcall_unixctl_disable_ufid(struct unixctl_conn *, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt, void *aux); static void upcall_unixctl_enable_ufid(struct unixctl_conn *, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt, void *aux); static void upcall_unixctl_set_flow_limit(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt, void *aux); static void upcall_unixctl_dump_wait(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux); + const char *argv[], + enum ovs_output_fmt fmt, void *aux); static void upcall_unixctl_purge(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux); + const char *argv[], enum ovs_output_fmt fmt, + void *aux); static void upcall_unixctl_pause(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux); + const char *argv[], enum ovs_output_fmt fmt, + void *aux); static void upcall_unixctl_resume(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux); + const char *argv[], enum ovs_output_fmt fmt, + void *aux); static struct udpif_key *ukey_create_from_upcall(struct upcall *, struct flow_wildcards *); @@ -430,26 +443,36 @@ udpif_init(void) { static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; if (ovsthread_once_start(&once)) { - unixctl_command_register("upcall/show", "", 0, 0, upcall_unixctl_show, + unixctl_command_register("upcall/show", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + upcall_unixctl_show, NULL); unixctl_command_register("upcall/disable-megaflows", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, upcall_unixctl_disable_megaflows, NULL); unixctl_command_register("upcall/enable-megaflows", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, upcall_unixctl_enable_megaflows, NULL); unixctl_command_register("upcall/disable-ufid", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, upcall_unixctl_disable_ufid, NULL); unixctl_command_register("upcall/enable-ufid", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, upcall_unixctl_enable_ufid, NULL); unixctl_command_register("upcall/set-flow-limit", "flow-limit-number", - 1, 1, upcall_unixctl_set_flow_limit, NULL); + 1, 1, OVS_OUTPUT_FMT_TEXT, + upcall_unixctl_set_flow_limit, NULL); unixctl_command_register("revalidator/wait", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, upcall_unixctl_dump_wait, NULL); unixctl_command_register("revalidator/purge", "", 0, 0, - upcall_unixctl_purge, NULL); + OVS_OUTPUT_FMT_TEXT, upcall_unixctl_purge, + NULL); unixctl_command_register("revalidator/pause", NULL, 0, 0, - upcall_unixctl_pause, NULL); + OVS_OUTPUT_FMT_TEXT, upcall_unixctl_pause, + NULL); unixctl_command_register("revalidator/resume", NULL, 0, 0, - upcall_unixctl_resume, NULL); + OVS_OUTPUT_FMT_TEXT, upcall_unixctl_resume, + NULL); ovsthread_once_done(&once); } } @@ -3067,7 +3090,9 @@ dp_purge_cb(void *aux, unsigned pmd_id) static void upcall_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; uint64_t n_offloaded_flows; @@ -3121,6 +3146,7 @@ static void upcall_unixctl_disable_megaflows(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { atomic_store_relaxed(&enable_megaflows, false); @@ -3136,6 +3162,7 @@ static void upcall_unixctl_enable_megaflows(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { atomic_store_relaxed(&enable_megaflows, true); @@ -3149,7 +3176,9 @@ upcall_unixctl_enable_megaflows(struct unixctl_conn *conn, * documented in the man page. */ static void upcall_unixctl_disable_ufid(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { atomic_store_relaxed(&enable_ufid, false); unixctl_command_reply(conn, "Datapath dumping tersely using UFID disabled"); @@ -3161,7 +3190,9 @@ upcall_unixctl_disable_ufid(struct unixctl_conn *conn, int argc OVS_UNUSED, * in the man page. */ static void upcall_unixctl_enable_ufid(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { atomic_store_relaxed(&enable_ufid, true); unixctl_command_reply(conn, "Datapath dumping tersely using UFID enabled " @@ -3176,6 +3207,7 @@ static void upcall_unixctl_set_flow_limit(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -3194,6 +3226,7 @@ static void upcall_unixctl_dump_wait(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { if (ovs_list_is_singleton(&all_udpifs)) { @@ -3212,7 +3245,9 @@ upcall_unixctl_dump_wait(struct unixctl_conn *conn, static void upcall_unixctl_purge(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct udpif *udpif; @@ -3228,7 +3263,9 @@ upcall_unixctl_purge(struct unixctl_conn *conn, int argc OVS_UNUSED, static void upcall_unixctl_pause(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct udpif *udpif; @@ -3240,7 +3277,9 @@ upcall_unixctl_pause(struct unixctl_conn *conn, int argc OVS_UNUSED, static void upcall_unixctl_resume(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct udpif *udpif; diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index ba5706f6a..01f12d967 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -20,6 +20,7 @@ #include "bond.h" #include "bundle.h" #include "byte-order.h" +#include "command-line.h" #include "connectivity.h" #include "connmgr.h" #include "coverage.h" @@ -5832,7 +5833,9 @@ ofproto_dpif_lookup_by_uuid(const struct uuid *uuid) static void ofproto_unixctl_fdb_flush(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ofproto_dpif *ofproto; @@ -5859,7 +5862,9 @@ ofproto_unixctl_fdb_flush(struct unixctl_conn *conn, int argc, static void ofproto_unixctl_mcast_snooping_flush(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ofproto_dpif *ofproto; @@ -5897,7 +5902,9 @@ ofbundle_get_a_port(const struct ofbundle *bundle) static void ofproto_unixctl_fdb_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; const struct ofproto_dpif *ofproto; @@ -5933,7 +5940,9 @@ ofproto_unixctl_fdb_show(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ofproto_unixctl_fdb_add(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { const struct ofproto_dpif *ofproto; const struct mac_entry *mac_entry; @@ -5998,7 +6007,9 @@ ofproto_unixctl_fdb_add(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ofproto_unixctl_fdb_delete(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { const struct ofproto_dpif *ofproto; const char *br_name = argv[1]; @@ -6024,7 +6035,9 @@ ofproto_unixctl_fdb_delete(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ofproto_unixctl_fdb_stats_clear(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ofproto_dpif *ofproto; @@ -6051,7 +6064,9 @@ ofproto_unixctl_fdb_stats_clear(struct unixctl_conn *conn, int argc, static void ofproto_unixctl_fdb_stats_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; const struct ofproto_dpif *ofproto; @@ -6092,6 +6107,7 @@ static void ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -6164,6 +6180,7 @@ get_ofprotos(struct shash *ofproto_shash) static void ofproto_unixctl_dpif_dump_dps(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -6344,8 +6361,103 @@ done: return changed; } +static struct json * +dpif_show_backer_json(const struct dpif_backer *backer) +{ + struct json *json_backer = json_object_create(); + + /* name */ + json_object_put_string(json_backer, "name", dpif_name(backer->dpif)); + + /* stats */ + struct dpif_dp_stats dp_stats; + dpif_get_dp_stats(backer->dpif, &dp_stats); + struct json *json_dp_stats = json_object_create(); + json_object_put_format(json_dp_stats, "n_hit", "%"PRIu64, dp_stats.n_hit); + json_object_put_format(json_dp_stats, "n_missed", "%"PRIu64, + dp_stats.n_missed); + json_object_put(json_backer, "stats", json_dp_stats); + + /* ofprotos */ + struct json *json_ofprotos = json_array_create_empty(); + struct shash ofproto_shash; + shash_init(&ofproto_shash); + const struct shash_node **ofprotos = get_ofprotos(&ofproto_shash); + for (size_t i = 0; i < shash_count(&ofproto_shash); i++) { + struct ofproto_dpif *ofproto = ofprotos[i]->data; + + if (ofproto->backer != backer) { + continue; + } + + struct json *json_ofproto = json_object_create(); + + /* ofproto name */ + json_object_put_string(json_ofproto, "name", ofproto->up.name); + + /* ofproto ports */ + struct json *json_ofproto_ports = json_array_create_empty(); + const struct shash_node **ports; + ports = shash_sort(&ofproto->up.port_by_name); + for (size_t j = 0; j < shash_count(&ofproto->up.port_by_name); j++) { + const struct shash_node *port = ports[j]; + struct ofport *ofport = port->data; + + struct json * json_ofproto_port = json_object_create(); + /* ofproto port netdev name */ + json_object_put_string(json_ofproto_port, "netdev_name", + netdev_get_name(ofport->netdev)); + /* ofproto port ofp port */ + json_object_put_format(json_ofproto_port, "ofp_port", "%u", + ofport->ofp_port); + + /* ofproto port odp port */ + odp_port_t odp_port = ofp_port_to_odp_port(ofproto, + ofport->ofp_port); + if (odp_port != ODPP_NONE) { + json_object_put_format(json_ofproto_port, "odp_port", + "%"PRIu32, odp_port); + } else { + json_object_put_string(json_ofproto_port, "odp_port", "none"); + } + + /* ofproto port netdev type */ + json_object_put_string(json_ofproto_port, "netdev_type", + netdev_get_type(ofport->netdev)); + + /* ofproto port config */ + struct json *json_port_config = json_object_create(); + struct smap config; + smap_init(&config); + if (!netdev_get_config(ofport->netdev, &config)) { + struct smap_node *node; + + SMAP_FOR_EACH (node, &config) { + json_object_put_string(json_port_config, node->key, + node->value); + } + } + smap_destroy(&config); + json_object_put(json_ofproto_port, "netdev_config", + json_port_config); + + json_array_add(json_ofproto_ports, json_ofproto_port); + } /* ofproto port */ + + free(ports); + json_object_put(json_ofproto, "ports", json_ofproto_ports); + + json_array_add(json_ofprotos, json_ofproto); + } /* ofproto */ + shash_destroy(&ofproto_shash); + free(ofprotos); + + json_object_put(json_backer, "ofprotos", json_ofprotos); + return json_backer; +} + static void -dpif_show_backer(const struct dpif_backer *backer, struct ds *ds) +dpif_show_backer_text(const struct dpif_backer *backer, struct ds *ds) { const struct shash_node **ofprotos; struct dpif_dp_stats dp_stats; @@ -6410,25 +6522,35 @@ dpif_show_backer(const struct dpif_backer *backer, struct ds *ds) static void ofproto_unixctl_dpif_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; - const struct shash_node **backers; - int i; - backers = shash_sort(&all_dpif_backers); - for (i = 0; i < shash_count(&all_dpif_backers); i++) { - dpif_show_backer(backers[i]->data, &ds); - } - free(backers); + if (fmt == OVS_OUTPUT_FMT_JSON) { + struct json *backers = json_array_create_empty(); + const struct shash_node *backer; + SHASH_FOR_EACH (backer, &all_dpif_backers) { + json_array_add(backers, dpif_show_backer_json(backer->data)); + } + unixctl_command_reply_json(conn, backers); + } else { + const struct shash_node **backers = shash_sort(&all_dpif_backers); + for (int i = 0; i < shash_count(&all_dpif_backers); i++) { + dpif_show_backer_text(backers[i]->data, &ds); + } + free(backers); - unixctl_command_reply(conn, ds_cstr(&ds)); - ds_destroy(&ds); + unixctl_command_reply(conn, ds_cstr(&ds)); + ds_destroy(&ds); + } } static void ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { const struct ofproto_dpif *ofproto; @@ -6523,6 +6645,7 @@ ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn, static void ofproto_unixctl_dpif_show_dp_features(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -6542,6 +6665,7 @@ ofproto_unixctl_dpif_show_dp_features(struct unixctl_conn *conn, static void ofproto_unixctl_dpif_set_dp_features(struct unixctl_conn *conn, int argc, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; @@ -6578,31 +6702,41 @@ ofproto_unixctl_init(void) registered = true; unixctl_command_register("fdb/add", "bridge port vlan mac", 4, 4, - ofproto_unixctl_fdb_add, NULL); + OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_fdb_add, + NULL); unixctl_command_register("fdb/del", "bridge vlan mac", 3, 3, - ofproto_unixctl_fdb_delete, NULL); + OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_fdb_delete, + NULL); unixctl_command_register("fdb/flush", "[bridge]", 0, 1, - ofproto_unixctl_fdb_flush, NULL); - unixctl_command_register("fdb/show", "bridge", 1, 1, + OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_fdb_flush, + NULL); + unixctl_command_register("fdb/show", "bridge", 1, 1, OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_fdb_show, NULL); unixctl_command_register("fdb/stats-clear", "[bridge]", 0, 1, + OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_fdb_stats_clear, NULL); unixctl_command_register("fdb/stats-show", "bridge", 1, 1, + OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_fdb_stats_show, NULL); unixctl_command_register("mdb/flush", "[bridge]", 0, 1, + OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_mcast_snooping_flush, NULL); - unixctl_command_register("mdb/show", "bridge", 1, 1, + unixctl_command_register("mdb/show", "bridge", 1, 1, OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_mcast_snooping_show, NULL); - unixctl_command_register("dpif/dump-dps", "", 0, 0, + unixctl_command_register("dpif/dump-dps", "", 0, 0, OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_dpif_dump_dps, NULL); - unixctl_command_register("dpif/show", "", 0, 0, ofproto_unixctl_dpif_show, - NULL); + unixctl_command_register("dpif/show", "", 0, 0, + OVS_OUTPUT_FMT_TEXT | OVS_OUTPUT_FMT_JSON, + ofproto_unixctl_dpif_show, NULL); unixctl_command_register("dpif/show-dp-features", "bridge", 1, 1, + OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_dpif_show_dp_features, NULL); unixctl_command_register("dpif/dump-flows", "[-m] [--names | --no-names] bridge", 1, INT_MAX, + OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_dpif_dump_flows, NULL); - unixctl_command_register("dpif/set-dp-features", "bridge", 1, 3 , + unixctl_command_register("dpif/set-dp-features", "bridge", 1, 3, + OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_dpif_set_dp_features, NULL); } diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index e78c80d11..3eb880f84 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -6366,7 +6366,7 @@ handle_flow_mod__(struct ofproto *ofproto, const struct ofputil_flow_mod *fm, error = ofproto_flow_mod_start(ofproto, &ofm); if (!error) { ofproto_bump_tables_version(ofproto); - error = ofproto_flow_mod_finish(ofproto, &ofm, req); + error = ofproto_flow_mod_finish(ofproto, &ofm, req); ofmonitor_flush(ofproto->connmgr); } ovs_mutex_unlock(&ofproto_mutex); @@ -8437,7 +8437,7 @@ do_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags) /* Send error referring to the original message. */ ofconn_send_error(ofconn, be->msg, error); error = OFPERR_OFPBFC_MSG_FAILED; - + /* 2. Revert. Undo all the changes made above. */ LIST_FOR_EACH_REVERSE_CONTINUE(be, node, &bundle->msg_list) { if (be->type == OFPTYPE_FLOW_MOD) { @@ -9453,7 +9453,9 @@ ofproto_lookup(const char *name) static void ofproto_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ofproto *ofproto; struct ds results; @@ -9475,7 +9477,7 @@ ofproto_unixctl_init(void) } registered = true; - unixctl_command_register("ofproto/list", "", 0, 0, + unixctl_command_register("ofproto/list", "", 0, 0, OVS_OUTPUT_FMT_TEXT, ofproto_unixctl_list, NULL); } diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index 3455ed233..a17414833 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -141,7 +141,7 @@ ofproto_tunnel_init(void) if (ovsthread_once_start(&once)) { fat_rwlock_init(&rwlock); unixctl_command_register("ofproto/list-tunnels", "", 0, 0, - tnl_unixctl_list, NULL); + OVS_OUTPUT_FMT_TEXT, tnl_unixctl_list, NULL); ovsthread_once_done(&once); } } @@ -756,7 +756,7 @@ tnl_port_build_header(const struct ofport_dpif *ofport, static void tnl_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, - void *aux OVS_UNUSED) + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct ds reply = DS_EMPTY_INITIALIZER; diff --git a/ovsdb/file.c b/ovsdb/file.c index 8bd1d4af3..9b60785e2 100644 --- a/ovsdb/file.c +++ b/ovsdb/file.c @@ -62,6 +62,7 @@ static bool use_column_diff = true; static void ovsdb_file_column_diff_enable(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *arg OVS_UNUSED) { use_column_diff = true; @@ -76,7 +77,8 @@ ovsdb_file_column_diff_disable(void) } use_column_diff = false; unixctl_command_register("ovsdb/file/column-diff-enable", "", - 0, 0, ovsdb_file_column_diff_enable, NULL); + 0, 0, OVS_OUTPUT_FMT_TEXT, + ovsdb_file_column_diff_enable, NULL); } static struct ovsdb_error * diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index 7249805ba..50de20ee1 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -1253,7 +1253,8 @@ parse_monitor_columns(char *arg, const char *server, const char *database, static void ovsdb_client_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *exiting_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *exiting_) { bool *exiting = exiting_; *exiting = true; @@ -1262,7 +1263,8 @@ ovsdb_client_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_client_block(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *blocked_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *blocked_) { bool *blocked = blocked_; @@ -1276,7 +1278,8 @@ ovsdb_client_block(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_client_unblock(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *blocked_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *blocked_) { bool *blocked = blocked_; @@ -1290,7 +1293,8 @@ ovsdb_client_unblock(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_client_cond_change(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *rpc_) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *rpc_) { struct jsonrpc *rpc = rpc_; struct json *monitor_cond_update_requests = json_object_create(); @@ -1404,13 +1408,16 @@ do_monitor__(struct jsonrpc *rpc, const char *database, ovs_fatal(error, "failed to create unixctl server"); } - unixctl_command_register("exit", "", 0, 0, + unixctl_command_register("exit", "", 0, 0, OVS_OUTPUT_FMT_TEXT, ovsdb_client_exit, &exiting); unixctl_command_register("ovsdb-client/block", "", 0, 0, - ovsdb_client_block, &blocked); + OVS_OUTPUT_FMT_TEXT, ovsdb_client_block, + &blocked); unixctl_command_register("ovsdb-client/unblock", "", 0, 0, - ovsdb_client_unblock, &blocked); + OVS_OUTPUT_FMT_TEXT, ovsdb_client_unblock, + &blocked); unixctl_command_register("ovsdb-client/cond_change", "TABLE COND", 2, 2, + OVS_OUTPUT_FMT_TEXT, ovsdb_client_cond_change, rpc); } else { unixctl = NULL; @@ -2244,7 +2251,9 @@ create_lock_request(struct ovsdb_client_lock_req *lock_req) static void ovsdb_client_lock(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *lock_req_) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *lock_req_) { struct ovsdb_client_lock_req *lock_req = lock_req_; lock_req_init(lock_req, "lock", argv[1]); @@ -2253,7 +2262,9 @@ ovsdb_client_lock(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_client_unlock(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *lock_req_) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *lock_req_) { struct ovsdb_client_lock_req *lock_req = lock_req_; lock_req_init(lock_req, "unlock", argv[1]); @@ -2262,7 +2273,8 @@ ovsdb_client_unlock(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_client_steal(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *lock_req_) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *lock_req_) { struct ovsdb_client_lock_req *lock_req = lock_req_; lock_req_init(lock_req, "steal", argv[1]); @@ -2292,13 +2304,13 @@ do_lock(struct jsonrpc *rpc, const char *method, const char *lock) ovs_fatal(error, "failed to create unixctl server"); } - unixctl_command_register("unlock", "LOCK", 1, 1, + unixctl_command_register("unlock", "LOCK", 1, 1, OVS_OUTPUT_FMT_TEXT, ovsdb_client_unlock, &lock_req); - unixctl_command_register("steal", "LOCK", 1, 1, + unixctl_command_register("steal", "LOCK", 1, 1, OVS_OUTPUT_FMT_TEXT, ovsdb_client_steal, &lock_req); - unixctl_command_register("lock", "LOCK", 1, 1, + unixctl_command_register("lock", "LOCK", 1, 1, OVS_OUTPUT_FMT_TEXT, ovsdb_client_lock, &lock_req); - unixctl_command_register("exit", "", 0, 0, + unixctl_command_register("exit", "", 0, 0, OVS_OUTPUT_FMT_TEXT, ovsdb_client_exit, &exiting); } else { unixctl = NULL; diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c index 4d29043f4..e3b7abaf9 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -431,70 +431,94 @@ main(int argc, char *argv[]) VLOG_INFO("%s (Open vSwitch) %s", program_name, VERSION); } - unixctl_command_register("exit", "", 0, 0, ovsdb_server_exit, &exiting); + unixctl_command_register("exit", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + ovsdb_server_exit, &exiting); unixctl_command_register("ovsdb-server/compact", "", 0, 1, - ovsdb_server_compact, &all_dbs); + OVS_OUTPUT_FMT_TEXT, ovsdb_server_compact, + &all_dbs); unixctl_command_register("ovsdb-server/memory-trim-on-compaction", - "on|off", 1, 1, + "on|off", 1, 1, OVS_OUTPUT_FMT_TEXT, ovsdb_server_memory_trim_on_compaction, NULL); unixctl_command_register("ovsdb-server/reconnect", "", 0, 0, - ovsdb_server_reconnect, jsonrpc); + OVS_OUTPUT_FMT_TEXT, ovsdb_server_reconnect, + jsonrpc); unixctl_command_register("ovsdb-server/add-remote", "REMOTE", 1, 1, - ovsdb_server_add_remote, &server_config); + OVS_OUTPUT_FMT_TEXT, ovsdb_server_add_remote, + &server_config); unixctl_command_register("ovsdb-server/remove-remote", "REMOTE", 1, 1, - ovsdb_server_remove_remote, &server_config); + OVS_OUTPUT_FMT_TEXT, ovsdb_server_remove_remote, + &server_config); unixctl_command_register("ovsdb-server/list-remotes", "", 0, 0, - ovsdb_server_list_remotes, &remotes); + OVS_OUTPUT_FMT_TEXT, ovsdb_server_list_remotes, + &remotes); unixctl_command_register("ovsdb-server/add-db", "DB", 1, 1, - ovsdb_server_add_database, &server_config); + OVS_OUTPUT_FMT_TEXT, ovsdb_server_add_database, + &server_config); unixctl_command_register("ovsdb-server/remove-db", "DB", 1, 1, - ovsdb_server_remove_database, &server_config); + OVS_OUTPUT_FMT_TEXT, ovsdb_server_remove_database, + &server_config); unixctl_command_register("ovsdb-server/list-dbs", "", 0, 0, - ovsdb_server_list_databases, &all_dbs); + OVS_OUTPUT_FMT_TEXT, ovsdb_server_list_databases, + &all_dbs); unixctl_command_register("ovsdb-server/tlog-set", "DB:TABLE on|off", - 2, 2, ovsdb_server_tlog_set, &all_dbs); + 2, 2, OVS_OUTPUT_FMT_TEXT, ovsdb_server_tlog_set, + &all_dbs); unixctl_command_register("ovsdb-server/tlog-list", "", - 0, 0, ovsdb_server_tlog_list, &all_dbs); + 0, 0, OVS_OUTPUT_FMT_TEXT, + ovsdb_server_tlog_list, &all_dbs); unixctl_command_register("ovsdb-server/perf-counters-show", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, ovsdb_server_perf_counters_show, NULL); unixctl_command_register("ovsdb-server/perf-counters-clear", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, ovsdb_server_perf_counters_clear, NULL); unixctl_command_register("ovsdb-server/set-active-ovsdb-server", "", 1, 1, + OVS_OUTPUT_FMT_TEXT, ovsdb_server_set_active_ovsdb_server, &server_config); unixctl_command_register("ovsdb-server/get-active-ovsdb-server", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, ovsdb_server_get_active_ovsdb_server, &server_config); unixctl_command_register("ovsdb-server/connect-active-ovsdb-server", "", - 0, 0, ovsdb_server_connect_active_ovsdb_server, + 0, 0, OVS_OUTPUT_FMT_TEXT, + ovsdb_server_connect_active_ovsdb_server, &server_config); unixctl_command_register("ovsdb-server/disconnect-active-ovsdb-server", "", - 0, 0, ovsdb_server_disconnect_active_ovsdb_server, + 0, 0, OVS_OUTPUT_FMT_TEXT, + ovsdb_server_disconnect_active_ovsdb_server, &server_config); unixctl_command_register( "ovsdb-server/set-active-ovsdb-server-probe-interval", "", 1, 1, + OVS_OUTPUT_FMT_TEXT, ovsdb_server_set_active_ovsdb_server_probe_interval, &server_config); unixctl_command_register( "ovsdb-server/set-relay-source-probe-interval", "", 1, 1, + OVS_OUTPUT_FMT_TEXT, ovsdb_server_set_relay_source_interval, &server_config); unixctl_command_register("ovsdb-server/set-sync-exclude-tables", "", - 0, 1, ovsdb_server_set_sync_exclude_tables, + 0, 1, OVS_OUTPUT_FMT_TEXT, + ovsdb_server_set_sync_exclude_tables, &server_config); unixctl_command_register("ovsdb-server/get-sync-exclude-tables", "", - 0, 0, ovsdb_server_get_sync_exclude_tables, + 0, 0, OVS_OUTPUT_FMT_TEXT, + ovsdb_server_get_sync_exclude_tables, NULL); unixctl_command_register("ovsdb-server/sync-status", "", - 0, 0, ovsdb_server_get_sync_status, + 0, 0, OVS_OUTPUT_FMT_TEXT, + ovsdb_server_get_sync_status, &server_config); unixctl_command_register("ovsdb-server/get-db-storage-status", "DB", 1, 1, + OVS_OUTPUT_FMT_TEXT, ovsdb_server_get_db_storage_status, &server_config); /* Simulate the behavior of OVS release prior to version 2.5 that * does not support the monitor_cond method. */ unixctl_command_register("ovsdb-server/disable-monitor-cond", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, ovsdb_server_disable_monitor_cond, jsonrpc); if (is_backup) { @@ -1404,6 +1428,7 @@ report_error_if_changed(char *error, char **last_errorp) static void ovsdb_server_set_active_ovsdb_server(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *config_) { struct server_config *config = config_; @@ -1421,6 +1446,7 @@ static void ovsdb_server_get_active_ovsdb_server(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *config_ ) { struct server_config *config = config_; @@ -1432,6 +1458,7 @@ static void ovsdb_server_connect_active_ovsdb_server(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *config_) { struct server_config *config = config_; @@ -1457,6 +1484,7 @@ static void ovsdb_server_disconnect_active_ovsdb_server(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *config_) { struct server_config *config = config_; @@ -1469,9 +1497,11 @@ ovsdb_server_disconnect_active_ovsdb_server(struct unixctl_conn *conn, static void ovsdb_server_set_active_ovsdb_server_probe_interval(struct unixctl_conn *conn, - int argc OVS_UNUSED, - const char *argv[], - void *config_) + int argc OVS_UNUSED, + const char *argv[], + enum ovs_output_fmt fmt + OVS_UNUSED, + void *config_) { struct server_config *config = config_; @@ -1493,6 +1523,7 @@ static void ovsdb_server_set_relay_source_interval(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *config_) { struct server_config *config = config_; @@ -1513,6 +1544,7 @@ static void ovsdb_server_set_sync_exclude_tables(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *config_) { struct server_config *config = config_; @@ -1539,6 +1571,7 @@ static void ovsdb_server_get_sync_exclude_tables(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *arg_ OVS_UNUSED) { char *reply = get_excluded_tables(); @@ -1549,6 +1582,7 @@ ovsdb_server_get_sync_exclude_tables(struct unixctl_conn *conn, static void ovsdb_server_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *exiting_) { bool *exiting = exiting_; @@ -1559,6 +1593,7 @@ ovsdb_server_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_server_perf_counters_show(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *arg_ OVS_UNUSED) { char *s = perf_counters_to_string(); @@ -1570,6 +1605,7 @@ ovsdb_server_perf_counters_show(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_server_perf_counters_clear(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *arg_ OVS_UNUSED) { perf_counters_clear(); @@ -1583,6 +1619,7 @@ static void ovsdb_server_disable_monitor_cond(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *jsonrpc_) { struct ovsdb_jsonrpc_server *jsonrpc = jsonrpc_; @@ -1595,7 +1632,8 @@ ovsdb_server_disable_monitor_cond(struct unixctl_conn *conn, static void ovsdb_server_compact(struct unixctl_conn *conn, int argc, - const char *argv[], void *dbs_) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *dbs_) { const char *db_name = argc < 2 ? NULL : argv[1]; struct shash *all_dbs = dbs_; @@ -1658,6 +1696,7 @@ static void ovsdb_server_memory_trim_on_compaction(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *arg OVS_UNUSED) { bool old_trim_memory = trim_memory; @@ -1689,7 +1728,9 @@ ovsdb_server_memory_trim_on_compaction(struct unixctl_conn *conn, * connections and reconnect. */ static void ovsdb_server_reconnect(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *jsonrpc_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *jsonrpc_) { struct ovsdb_jsonrpc_server *jsonrpc = jsonrpc_; ovsdb_jsonrpc_server_reconnect( @@ -1701,7 +1742,9 @@ ovsdb_server_reconnect(struct unixctl_conn *conn, int argc OVS_UNUSED, * ovsdb-server services. */ static void ovsdb_server_add_remote(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *config_) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *config_) { struct server_config *config = config_; const char *remote = argv[1]; @@ -1730,7 +1773,9 @@ ovsdb_server_add_remote(struct unixctl_conn *conn, int argc OVS_UNUSED, * that ovsdb-server services. */ static void ovsdb_server_remove_remote(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *config_) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *config_) { struct server_config *config = config_; struct sset_node *node; @@ -1748,7 +1793,9 @@ ovsdb_server_remove_remote(struct unixctl_conn *conn, int argc OVS_UNUSED, /* "ovsdb-server/list-remotes": outputs a list of configured rmeotes. */ static void ovsdb_server_list_remotes(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *remotes_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *remotes_) { struct sset *remotes = remotes_; const char **list, **p; @@ -1770,7 +1817,9 @@ ovsdb_server_list_remotes(struct unixctl_conn *conn, int argc OVS_UNUSED, /* "ovsdb-server/add-db DB": adds the DB to ovsdb-server. */ static void ovsdb_server_add_database(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *config_) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *config_) { struct server_config *config = config_; const char *filename = argv[1]; @@ -1812,7 +1861,9 @@ remove_db(struct server_config *config, struct shash_node *node, char *comment) static void ovsdb_server_remove_database(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *config_) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *config_) { struct server_config *config = config_; struct shash_node *node; @@ -1834,7 +1885,9 @@ ovsdb_server_remove_database(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_server_list_databases(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *all_dbs_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *all_dbs_) { struct shash *all_dbs = all_dbs_; const struct shash_node **nodes; @@ -1859,7 +1912,9 @@ ovsdb_server_list_databases(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_server_tlog_set(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *all_dbs_) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *all_dbs_) { struct shash *all_dbs = all_dbs_; const char *name_ = argv[1]; @@ -1905,7 +1960,9 @@ out: static void ovsdb_server_tlog_list(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *all_dbs_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *all_dbs_) { const struct shash_node **db_nodes; struct ds s = DS_EMPTY_INITIALIZER; @@ -1940,7 +1997,9 @@ ovsdb_server_tlog_list(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ovsdb_server_get_sync_status(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *config_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *config_) { struct server_config *config = config_; bool is_backup = *config->is_backup; @@ -1960,6 +2019,7 @@ static void ovsdb_server_get_db_storage_status(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *config_) { struct server_config *config = config_; diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c index f67b836d7..28914fdb0 100644 --- a/ovsdb/ovsdb.c +++ b/ovsdb/ovsdb.c @@ -186,6 +186,7 @@ static bool use_no_data_conversion = true; static void ovsdb_no_data_conversion_enable(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *arg OVS_UNUSED) { use_no_data_conversion = true; @@ -200,7 +201,8 @@ ovsdb_no_data_conversion_disable(void) } use_no_data_conversion = false; unixctl_command_register("ovsdb/file/no-data-conversion-enable", "", - 0, 0, ovsdb_no_data_conversion_enable, NULL); + 0, 0, OVS_OUTPUT_FMT_TEXT, + ovsdb_no_data_conversion_enable, NULL); } /* Returns true if the database storage allows conversion records without diff --git a/ovsdb/raft.c b/ovsdb/raft.c index 8effd9ad1..a7d6e5a09 100644 --- a/ovsdb/raft.c +++ b/ovsdb/raft.c @@ -4603,6 +4603,7 @@ raft_lookup_by_name(const char *name) static void raft_unixctl_cid(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct raft *raft = raft_lookup_by_name(argv[1]); @@ -4620,6 +4621,7 @@ raft_unixctl_cid(struct unixctl_conn *conn, static void raft_unixctl_sid(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct raft *raft = raft_lookup_by_name(argv[1]); @@ -4651,6 +4653,7 @@ raft_put_sid(const char *title, const struct uuid *sid, static void raft_unixctl_status(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { struct raft *raft = raft_lookup_by_name(argv[1]); @@ -4809,7 +4812,8 @@ raft_unixctl_leave__(struct unixctl_conn *conn, struct raft *raft) static void raft_unixctl_leave(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct raft *raft = raft_lookup_by_name(argv[1]); if (!raft) { @@ -4845,7 +4849,8 @@ raft_lookup_server_best_match(struct raft *raft, const char *id) static void raft_unixctl_kick(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { const char *cluster_name = argv[1]; const char *server_name = argv[2]; @@ -4918,6 +4923,7 @@ raft_log_election_timer(struct raft *raft) static void raft_unixctl_change_election_timer(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { const char *cluster_name = argv[1]; @@ -4972,6 +4978,7 @@ raft_unixctl_change_election_timer(struct unixctl_conn *conn, static void raft_unixctl_set_backlog_threshold(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { const char *cluster_name = argv[1]; @@ -5008,6 +5015,7 @@ raft_unixctl_set_backlog_threshold(struct unixctl_conn *conn, static void raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED, int argc OVS_UNUSED, const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { const char *test = argv[1]; @@ -5062,22 +5070,24 @@ raft_init(void) if (!ovsthread_once_start(&once)) { return; } - unixctl_command_register("cluster/cid", "DB", 1, 1, + unixctl_command_register("cluster/cid", "DB", 1, 1, OVS_OUTPUT_FMT_TEXT, raft_unixctl_cid, NULL); - unixctl_command_register("cluster/sid", "DB", 1, 1, + unixctl_command_register("cluster/sid", "DB", 1, 1, OVS_OUTPUT_FMT_TEXT, raft_unixctl_sid, NULL); - unixctl_command_register("cluster/status", "DB", 1, 1, + unixctl_command_register("cluster/status", "DB", 1, 1, OVS_OUTPUT_FMT_TEXT, raft_unixctl_status, NULL); - unixctl_command_register("cluster/leave", "DB", 1, 1, + unixctl_command_register("cluster/leave", "DB", 1, 1, OVS_OUTPUT_FMT_TEXT, raft_unixctl_leave, NULL); unixctl_command_register("cluster/kick", "DB SERVER", 2, 2, - raft_unixctl_kick, NULL); + OVS_OUTPUT_FMT_TEXT, raft_unixctl_kick, NULL); unixctl_command_register("cluster/change-election-timer", "DB TIME", 2, 2, + OVS_OUTPUT_FMT_TEXT, raft_unixctl_change_election_timer, NULL); unixctl_command_register("cluster/set-backlog-threshold", - "DB N_MSGS N_BYTES", 3, 3, + "DB N_MSGS N_BYTES", 3, 3, OVS_OUTPUT_FMT_TEXT, raft_unixctl_set_backlog_threshold, NULL); unixctl_command_register("cluster/failure-test", "FAILURE SCENARIO", 1, 1, - raft_unixctl_failure_test, NULL); + OVS_OUTPUT_FMT_TEXT, raft_unixctl_failure_test, + NULL); ovsthread_once_done(&once); } diff --git a/python/ovs/unixctl/__init__.py b/python/ovs/unixctl/__init__.py index 8ee312943..b432bffa9 100644 --- a/python/ovs/unixctl/__init__.py +++ b/python/ovs/unixctl/__init__.py @@ -20,15 +20,16 @@ commands = {} class _UnixctlCommand(object): - def __init__(self, usage, min_args, max_args, callback, aux): + def __init__(self, usage, min_args, max_args, fmt, callback, aux): self.usage = usage self.min_args = min_args self.max_args = max_args + self.fmt = fmt self.callback = callback self.aux = aux -def _unixctl_help(conn, unused_argv, unused_aux): +def _unixctl_help(conn, unused_argv, unused_fmt, unused_aux): reply = "The available commands are:\n" command_names = sorted(commands.keys()) for name in command_names: @@ -42,7 +43,7 @@ def _unixctl_help(conn, unused_argv, unused_aux): conn.reply(reply) -def command_register(name, usage, min_args, max_args, callback, aux): +def command_register(name, usage, min_args, max_args, fmt, callback, aux): """ Registers a command with the given 'name' to be exposed by the UnixctlServer. 'usage' describes the arguments to the command; it is used only for presentation to the user in "help" output. @@ -60,11 +61,12 @@ def command_register(name, usage, min_args, max_args, callback, aux): assert isinstance(usage, str) assert isinstance(min_args, int) assert isinstance(max_args, int) + assert isinstance(fmt, ovs.util.OutputFormat) assert callable(callback) if name not in commands: - commands[name] = _UnixctlCommand(usage, min_args, max_args, callback, - aux) + commands[name] = _UnixctlCommand(usage, min_args, max_args, fmt, + callback, aux) def socket_name_from_target(target): @@ -85,4 +87,5 @@ def socket_name_from_target(target): return 0, "%s/%s.%d.ctl" % (ovs.dirs.RUNDIR, target, pid) -command_register("help", "", 0, 0, _unixctl_help, None) +command_register( + "help", "", 0, 0, ovs.util.OutputFormat.TEXT, _unixctl_help, None) diff --git a/python/ovs/unixctl/client.py b/python/ovs/unixctl/client.py index 8283f99bb..f2980c230 100644 --- a/python/ovs/unixctl/client.py +++ b/python/ovs/unixctl/client.py @@ -26,13 +26,15 @@ class UnixctlClient(object): assert isinstance(conn, ovs.jsonrpc.Connection) self._conn = conn - def transact(self, command, argv): + def transact(self, command, argv, fmt): assert isinstance(command, str) assert isinstance(argv, list) for arg in argv: assert isinstance(arg, str) + assert isinstance(fmt, ovs.util.OutputFormat) - request = ovs.jsonrpc.Message.create_request(command, argv) + request = ovs.jsonrpc.Message.create_request( + "execute/v1", [command, fmt.name.lower()] + argv) error, reply = self._conn.transact_block(request) if error: diff --git a/python/ovs/unixctl/server.py b/python/ovs/unixctl/server.py index 5f9b3e739..0a4f71d7d 100644 --- a/python/ovs/unixctl/server.py +++ b/python/ovs/unixctl/server.py @@ -104,33 +104,46 @@ class UnixctlConnection(object): self._request_id = request.id - error = None - params = request.params - method = request.method - command = ovs.unixctl.commands.get(method) - if command is None: - error = '"%s" is not a valid command' % method - elif len(params) < command.min_args: - error = '"%s" command requires at least %d arguments' \ - % (method, command.min_args) - elif len(params) > command.max_args: - error = '"%s" command takes at most %d arguments' \ - % (method, command.max_args) - else: - for param in params: + try: + if request.method != "execute/v1": + raise ValueError( + "JSON-RPC API mismatch: Unexpected command '%s'." + % request.method) + + if len(request.params) < 2: + raise ValueError( + "JSON-RPC API mismatch: Unexpected # of params: %d" + % len(params)) + + for param in request.params: if not isinstance(param, str): - error = '"%s" command has non-string argument' % method - break + raise ValueError( + "command has non-string argument: %s" % param) - if error is None: - unicode_params = [str(p) for p in params] - command.callback(self, unicode_params, command.aux) + method = request.params[0] + fmt = ovs.util.OutputFormat[request.params[1].upper()] + params = request.params[2:] - if error: - self.reply_error(error) + command = ovs.unixctl.commands.get(method) + if command is None: + raise ValueError('"%s" is not a valid command' % method) + elif len(params) < command.min_args: + raise ValueError( + '"%s" command requires at least %d arguments' + % (method, command.min_args)) + elif len(params) > command.max_args: + raise ValueError( + '"%s" command takes at most %d arguments' + % (method, command.max_args)) + + unicode_params = [str(p) for p in params] + command.callback(self, unicode_params, fmt, command.aux) + except Exception as e: + self.reply_error(str(e)) -def _unixctl_version(conn, unused_argv, version): + +def _unixctl_version(conn, unused_argv, unused_fmt, version): assert isinstance(conn, UnixctlConnection) version = "%s (Open vSwitch) %s" % (ovs.util.PROGRAM_NAME, version) conn.reply(version) @@ -207,12 +220,14 @@ class UnixctlServer(object): % path) return error, None - ovs.unixctl.command_register("version", "", 0, 0, _unixctl_version, + ovs.unixctl.command_register("version", "", 0, 0, + ovs.util.OutputFormat.TEXT, + _unixctl_version, version) return 0, UnixctlServer(listener) - +# TODO: What is this? A copy of UnixctlClient from client.py? class UnixctlClient(object): def __init__(self, conn): assert isinstance(conn, ovs.jsonrpc.Connection) diff --git a/python/ovs/util.py b/python/ovs/util.py index 3dba022f8..dce4452c1 100644 --- a/python/ovs/util.py +++ b/python/ovs/util.py @@ -15,11 +15,18 @@ import os import os.path import sys +import enum PROGRAM_NAME = os.path.basename(sys.argv[0]) EOF = -1 +@enum.unique +class OutputFormat(enum.IntFlag): + TEXT = 1 + JSON = 2 + + def abs_file_name(dir_, file_name): """If 'file_name' starts with '/', returns a copy of 'file_name'. Otherwise, returns an absolute path to 'file_name' considering it relative diff --git a/python/ovs/vlog.py b/python/ovs/vlog.py index 61f5928db..ba8701040 100644 --- a/python/ovs/vlog.py +++ b/python/ovs/vlog.py @@ -237,8 +237,10 @@ class Vlog(object): logger.disabled = True ovs.unixctl.command_register("vlog/reopen", "", 0, 0, + ovs.util.OutputFormat.TEXT, Vlog._unixctl_vlog_reopen, None) ovs.unixctl.command_register("vlog/close", "", 0, 0, + ovs.util.OutputFormat.TEXT, Vlog._unixctl_vlog_close, None) try: # Windows limitation on Python 2, sys.maxsize is a long number @@ -248,8 +250,10 @@ class Vlog(object): except AttributeError: maxsize_int = sys.maxsize ovs.unixctl.command_register("vlog/set", "spec", 1, maxsize_int, + ovs.util.OutputFormat.TEXT, Vlog._unixctl_vlog_set, None) ovs.unixctl.command_register("vlog/list", "", 0, 0, + ovs.util.OutputFormat.TEXT, Vlog._unixctl_vlog_list, None) @staticmethod @@ -406,7 +410,7 @@ class Vlog(object): Vlog.__file_handler.close() @staticmethod - def _unixctl_vlog_reopen(conn, unused_argv, unused_aux): + def _unixctl_vlog_reopen(conn, unused_argv, unused_fmt, unused_aux): if Vlog.__log_file: Vlog.reopen_log_file() conn.reply(None) @@ -414,7 +418,7 @@ class Vlog(object): conn.reply("Logging to file not configured") @staticmethod - def _unixctl_vlog_close(conn, unused_argv, unused_aux): + def _unixctl_vlog_close(conn, unused_argv, unused_fmt, unused_aux): if Vlog.__log_file: if sys.platform != 'win32': logger = logging.getLogger("file") @@ -424,7 +428,7 @@ class Vlog(object): conn.reply(None) @staticmethod - def _unixctl_vlog_set(conn, argv, unused_aux): + def _unixctl_vlog_set(conn, argv, unused_fmt, unused_aux): for arg in argv: msg = Vlog.set_levels_from_string(arg) if msg: @@ -433,7 +437,7 @@ class Vlog(object): conn.reply(None) @staticmethod - def _unixctl_vlog_list(conn, unused_argv, unused_aux): + def _unixctl_vlog_list(conn, unused_argv, unused_fmt, unused_aux): conn.reply(Vlog.get_levels()) diff --git a/tests/appctl.py b/tests/appctl.py index b85b364fa..42f96b2a3 100644 --- a/tests/appctl.py +++ b/tests/appctl.py @@ -49,6 +49,10 @@ def main(): help="Arguments to the command.") parser.add_argument("-T", "--timeout", metavar="SECS", help="wait at most SECS seconds for a response") + parser.add_argument("-f", "--format", metavar="FMT", + help="Output format.", default="text", + choices=[fmt.name.lower() + for fmt in ovs.util.OutputFormat]) args = parser.parse_args() signal_alarm(int(args.timeout) if args.timeout else None) @@ -56,7 +60,8 @@ def main(): ovs.vlog.Vlog.init() target = args.target client = connect_to_target(target) - err_no, error, result = client.transact(args.command, args.argv) + err_no, error, result = client.transact( + args.command, args.argv, ovs.util.OutputFormat[args.format.upper()]) client.close() if err_no: diff --git a/tests/pmd.at b/tests/pmd.at index 7bdaca9e7..4d90fa2a4 100644 --- a/tests/pmd.at +++ b/tests/pmd.at @@ -100,6 +100,35 @@ dummy@ovs-dummy: hit:0 missed:0 p0 1/1: (dummy-pmd: configured_rx_queues=1, configured_tx_queues=, requested_rx_queues=1, requested_tx_queues=) ]) +AT_CHECK([ovs-appctl --format json dpif/show | sed 's/\(tx_queues": "\)[[0-9]]*"/\1"/g'], [0], [dnl +[[ + { + "name": "dummy@ovs-dummy", + "ofprotos": [ + { + "name": "br0", + "ports": [ + { + "netdev_config": { + }, + "netdev_name": "br0", + "netdev_type": "dummy-internal", + "odp_port": "100", + "ofp_port": "65534"}, + { + "netdev_config": { + "configured_rx_queues": "1", + "configured_tx_queues": "", + "requested_rx_queues": "1", + "requested_tx_queues": ""}, + "netdev_name": "p0", + "netdev_type": "dummy-pmd", + "odp_port": "1", + "ofp_port": "1"}]}], + "stats": { + "n_hit": "0", + "n_missed": "0"}}]]]) + OVS_VSWITCHD_STOP AT_CLEANUP diff --git a/tests/test-netflow.c b/tests/test-netflow.c index 7f89cfcae..b808cb9fd 100644 --- a/tests/test-netflow.c +++ b/tests/test-netflow.c @@ -201,7 +201,8 @@ test_netflow_main(int argc, char *argv[]) if (error) { ovs_fatal(error, "failed to create unixctl server"); } - unixctl_command_register("exit", "", 0, 0, test_netflow_exit, &exiting); + unixctl_command_register("exit", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + test_netflow_exit, &exiting); daemonize_complete(); @@ -294,6 +295,7 @@ usage(void) static void test_netflow_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *exiting_) { bool *exiting = exiting_; diff --git a/tests/test-sflow.c b/tests/test-sflow.c index 3c617bdd1..82ef66178 100644 --- a/tests/test-sflow.c +++ b/tests/test-sflow.c @@ -715,7 +715,8 @@ test_sflow_main(int argc, char *argv[]) if (error) { ovs_fatal(error, "failed to create unixctl server"); } - unixctl_command_register("exit", "", 0, 0, test_sflow_exit, &exiting); + unixctl_command_register("exit", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + test_sflow_exit, &exiting); daemonize_complete(); @@ -804,6 +805,7 @@ usage(void) static void test_sflow_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *exiting_) { bool *exiting = exiting_; diff --git a/tests/test-unixctl.c b/tests/test-unixctl.c index 9e8982789..e344a8203 100644 --- a/tests/test-unixctl.c +++ b/tests/test-unixctl.c @@ -33,7 +33,9 @@ OVS_NO_RETURN static void usage(void); static void test_unixctl_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *exiting_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *exiting_) { bool *exiting = exiting_; *exiting = true; @@ -42,21 +44,26 @@ test_unixctl_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, static void test_unixctl_echo(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { unixctl_command_reply(conn, argv[1]); } static void test_unixctl_echo_error(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { unixctl_command_reply_error(conn, argv[1]); } static void test_unixctl_log(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *aux OVS_UNUSED) { VLOG_INFO("%s", argv[1]); unixctl_command_reply(conn, NULL); @@ -64,7 +71,9 @@ test_unixctl_log(struct unixctl_conn *conn, int argc OVS_UNUSED, static void test_unixctl_block(struct unixctl_conn *conn OVS_UNUSED, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { VLOG_INFO("%s", argv[1]); unixctl_command_reply(conn, NULL); @@ -88,12 +97,16 @@ test_unixctl_main(int argc, char *argv[]) if (retval) { exit(EXIT_FAILURE); } - unixctl_command_register("exit", "", 0, 0, test_unixctl_exit, &exiting); - unixctl_command_register("echo", "ARG", 1, 1, test_unixctl_echo, NULL); - unixctl_command_register("echo_error", "ARG", 1, 1, + unixctl_command_register("exit", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + test_unixctl_exit, &exiting); + unixctl_command_register("echo", "ARG", 1, 1, OVS_OUTPUT_FMT_TEXT, + test_unixctl_echo, NULL); + unixctl_command_register("echo_error", "ARG", 1, 1, OVS_OUTPUT_FMT_TEXT, test_unixctl_echo_error, NULL); - unixctl_command_register("log", "ARG", 1, 1, test_unixctl_log, NULL); - unixctl_command_register("block", "", 0, 0, test_unixctl_block, NULL); + unixctl_command_register("log", "ARG", 1, 1, OVS_OUTPUT_FMT_TEXT, + test_unixctl_log, NULL); + unixctl_command_register("block", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + test_unixctl_block, NULL); daemonize_complete(); VLOG_INFO("Entering run loop."); diff --git a/tests/test-unixctl.py b/tests/test-unixctl.py index 4fa27b09f..b5fe12eb7 100644 --- a/tests/test-unixctl.py +++ b/tests/test-unixctl.py @@ -17,12 +17,13 @@ import argparse import ovs.daemon import ovs.unixctl import ovs.unixctl.server +import ovs.util vlog = ovs.vlog.Vlog("test-unixctl") exiting = False -def unixctl_exit(conn, unused_argv, aux): +def unixctl_exit(conn, unused_argv, unused_fmt, aux): assert aux == "aux_exit" global exiting @@ -30,22 +31,22 @@ def unixctl_exit(conn, unused_argv, aux): conn.reply(None) -def unixctl_echo(conn, argv, aux): +def unixctl_echo(conn, argv, unused_fmt, aux): assert aux == "aux_echo" conn.reply(str(argv)) -def unixctl_echo_error(conn, argv, aux): +def unixctl_echo_error(conn, argv, unused_fmt, aux): assert aux == "aux_echo_error" conn.reply_error(str(argv)) -def unixctl_log(conn, argv, unused_aux): +def unixctl_log(conn, argv, unused_fmt, unused_aux): vlog.info(str(argv[0])) conn.reply(None) -def unixctl_block(conn, unused_argv, unused_aux): +def unixctl_block(conn, unused_argv, unused_fmt, unused_aux): pass @@ -66,13 +67,19 @@ def main(): ovs.util.ovs_fatal(error, "could not create unixctl server at %s" % args.unixctl, vlog) - ovs.unixctl.command_register("exit", "", 0, 0, unixctl_exit, "aux_exit") - ovs.unixctl.command_register("echo", "[arg ...]", 1, 2, unixctl_echo, + ovs.unixctl.command_register("exit", "", 0, 0, ovs.util.OutputFormat.TEXT, + unixctl_exit, "aux_exit") + ovs.unixctl.command_register("echo", "[arg ...]", 1, 2, + ovs.util.OutputFormat.TEXT, unixctl_echo, "aux_echo") - ovs.unixctl.command_register("log", "[arg ...]", 1, 2, unixctl_log, None) + ovs.unixctl.command_register("log", "[arg ...]", 1, 2, + ovs.util.OutputFormat.TEXT, unixctl_log, + None) ovs.unixctl.command_register("echo_error", "[arg ...]", 1, 2, + ovs.util.OutputFormat.TEXT, unixctl_echo_error, "aux_echo_error") - ovs.unixctl.command_register("block", "", 0, 0, unixctl_block, None) + ovs.unixctl.command_register("block", "", 0, 0, ovs.util.OutputFormat.TEXT, + unixctl_block, None) ovs.daemon.daemonize_complete() vlog.info("Entering run loop.") diff --git a/utilities/ovs-appctl.c b/utilities/ovs-appctl.c index ba0c172e6..3a70408e5 100644 --- a/utilities/ovs-appctl.c +++ b/utilities/ovs-appctl.c @@ -34,7 +34,14 @@ #include "openvswitch/vlog.h" static void usage(void); -static const char *parse_command_line(int argc, char *argv[]); +struct cmdl_args { + enum ovs_output_fmt format; + char *target; +}; + +static struct cmdl_args *cmdl_args_create(void); +static void cmdl_args_destroy(struct cmdl_args *); +static struct cmdl_args *parse_command_line(int argc, char *argv[]); static struct jsonrpc *connect_to_target(const char *target); int @@ -43,30 +50,30 @@ main(int argc, char *argv[]) char *cmd_result, *cmd_error; struct jsonrpc *client; char *cmd, **cmd_argv; - const char *target; + struct cmdl_args *args; int cmd_argc; int error; set_program_name(argv[0]); /* Parse command line and connect to target. */ - target = parse_command_line(argc, argv); - client = connect_to_target(target); + args = parse_command_line(argc, argv); + client = connect_to_target(args->target); /* Transact request and process reply. */ cmd = argv[optind++]; cmd_argc = argc - optind; cmd_argv = cmd_argc ? argv + optind : NULL; error = unixctl_client_transact(client, cmd, cmd_argc, cmd_argv, - &cmd_result, &cmd_error); + args->format, &cmd_result, &cmd_error); if (error) { - ovs_fatal(error, "%s: transaction error", target); + ovs_fatal(error, "%s: transaction error", args->target); } if (cmd_error) { jsonrpc_close(client); fputs(cmd_error, stderr); - ovs_error(0, "%s: server returned an error", target); + ovs_error(0, "%s: server returned an error", args->target); exit(2); } else if (cmd_result) { fputs(cmd_result, stdout); @@ -74,6 +81,7 @@ main(int argc, char *argv[]) OVS_NOT_REACHED(); } + cmdl_args_destroy(args); jsonrpc_close(client); free(cmd_result); free(cmd_error); @@ -101,13 +109,34 @@ Common commands:\n\ vlog/reopen Make the program reopen its log file\n\ Other options:\n\ --timeout=SECS wait at most SECS seconds for a response\n\ + -f, --format=FMT Output format. One of: 'json', or 'text'\n\ + ('text', by default)\n\ -h, --help Print this helpful information\n\ -V, --version Display ovs-appctl version information\n", program_name, program_name); exit(EXIT_SUCCESS); } -static const char * +static struct cmdl_args * +cmdl_args_create(void) { + struct cmdl_args *args = xmalloc(sizeof *args); + + args->format = OVS_OUTPUT_FMT_TEXT; + args->target = NULL; + + return args; +} + +static void +cmdl_args_destroy(struct cmdl_args *args) { + if (args->target) { + free(args->target); + } + + free(args); +} + +static struct cmdl_args * parse_command_line(int argc, char *argv[]) { enum { @@ -117,6 +146,7 @@ parse_command_line(int argc, char *argv[]) static const struct option long_options[] = { {"target", required_argument, NULL, 't'}, {"execute", no_argument, NULL, 'e'}, + {"format", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"option", no_argument, NULL, 'o'}, {"version", no_argument, NULL, 'V'}, @@ -126,11 +156,11 @@ parse_command_line(int argc, char *argv[]) }; char *short_options_ = ovs_cmdl_long_options_to_short_options(long_options); char *short_options = xasprintf("+%s", short_options_); - const char *target; + + struct cmdl_args *args = cmdl_args_create(); int e_options; unsigned int timeout = 0; - target = NULL; e_options = 0; for (;;) { int option; @@ -141,10 +171,10 @@ parse_command_line(int argc, char *argv[]) } switch (option) { case 't': - if (target) { + if (args->target) { ovs_fatal(0, "-t or --target may be specified only once"); } - target = optarg; + args->target = xstrdup(optarg); break; case 'e': @@ -157,6 +187,12 @@ parse_command_line(int argc, char *argv[]) } break; + case 'f': + if (!ovs_output_fmt_from_string(optarg, &args->format)) { + ovs_fatal(0, "value %s on -f or --format is invalid", optarg); + } + break; + case 'h': usage(); break; @@ -194,7 +230,10 @@ parse_command_line(int argc, char *argv[]) "(use --help for help)"); } - return target ? target : "ovs-vswitchd"; + if (!args->target) { + args->target = xstrdup("ovs-vswitchd"); + } + return args; } static struct jsonrpc * diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c index 56d7a942b..1b4f9db17 100644 --- a/utilities/ovs-dpctl.c +++ b/utilities/ovs-dpctl.c @@ -91,6 +91,7 @@ parse_options(int argc, char *argv[]) {"names", no_argument, NULL, OPT_NAMES}, {"no-names", no_argument, NULL, OPT_NO_NAMES}, {"timeout", required_argument, NULL, 't'}, + {"format", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"option", no_argument, NULL, 'o'}, {"version", no_argument, NULL, 'V'}, @@ -101,6 +102,7 @@ parse_options(int argc, char *argv[]) bool set_names = false; unsigned int timeout = 0; + enum ovs_output_fmt fmt = OVS_OUTPUT_FMT_TEXT; for (;;) { int c; @@ -141,6 +143,12 @@ parse_options(int argc, char *argv[]) set_names = true; break; + case 'f': + if (!ovs_output_fmt_from_string(optarg, &fmt)) { + ovs_fatal(0, "value %s on -f or --format is invalid", optarg); + } + break; + case 't': if (!str_to_uint(optarg, 10, &timeout) || !timeout) { ovs_fatal(0, "value %s on -t or --timeout is invalid", optarg); @@ -174,6 +182,8 @@ parse_options(int argc, char *argv[]) if (!set_names) { dpctl_p.names = dpctl_p.verbosity > 0; } + + dpctl_p.format = fmt; } static void @@ -228,6 +238,8 @@ usage(void *userdata OVS_UNUSED) " --clear reset existing stats to zero\n" "\nOther options:\n" " -t, --timeout=SECS give up after SECS seconds\n" + " -f, --format=FMT Output format.\n" + " One of: 'json', 'text' (default)\n" " -h, --help display this help message\n" " -V, --version display version information\n"); exit(EXIT_SUCCESS); diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 24d0941cf..4bf398492 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -524,7 +524,8 @@ usage(void) static void ofctl_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *exiting_) + const char *argv[] OVS_UNUSED, enum ovs_output_fmt fmt OVS_UNUSED, + void *exiting_) { bool *exiting = exiting_; *exiting = true; @@ -1935,7 +1936,8 @@ openflow_from_hex(const char *hex, struct ofpbuf **msgp) static void ofctl_send(struct unixctl_conn *conn, int argc, - const char *argv[], void *vconn_) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *vconn_) { struct vconn *vconn = vconn_; struct ds reply; @@ -1981,7 +1983,8 @@ ofctl_send(struct unixctl_conn *conn, int argc, static void unixctl_packet_out(struct unixctl_conn *conn, int OVS_UNUSED argc, - const char *argv[], void *vconn_) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *vconn_) { struct vconn *vconn = vconn_; enum ofputil_protocol protocol @@ -2042,7 +2045,8 @@ struct barrier_aux { static void ofctl_barrier(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *aux_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, void *aux_) { struct barrier_aux *aux = aux_; struct ofpbuf *msg; @@ -2065,7 +2069,8 @@ ofctl_barrier(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ofctl_set_output_file(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { int fd; @@ -2083,7 +2088,9 @@ ofctl_set_output_file(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ofctl_block(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *blocked_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *blocked_) { bool *blocked = blocked_; @@ -2097,7 +2104,9 @@ ofctl_block(struct unixctl_conn *conn, int argc OVS_UNUSED, static void ofctl_unblock(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *blocked_) + const char *argv[] OVS_UNUSED, + enum ovs_output_fmt fmt OVS_UNUSED, + void *blocked_) { bool *blocked = blocked_; @@ -2132,19 +2141,21 @@ monitor_vconn(struct vconn *vconn, bool reply_to_echo_requests, if (error) { ovs_fatal(error, "failed to create unixctl server"); } - unixctl_command_register("exit", "", 0, 0, ofctl_exit, &exiting); + unixctl_command_register("exit", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + ofctl_exit, &exiting); unixctl_command_register("ofctl/send", "OFMSG...", 1, INT_MAX, - ofctl_send, vconn); + OVS_OUTPUT_FMT_TEXT, ofctl_send, vconn); unixctl_command_register("ofctl/packet-out", "\"in_port= packet= actions=...\"", 1, 1, - unixctl_packet_out, vconn); - unixctl_command_register("ofctl/barrier", "", 0, 0, + OVS_OUTPUT_FMT_TEXT, unixctl_packet_out, vconn); + unixctl_command_register("ofctl/barrier", "", 0, 0, OVS_OUTPUT_FMT_TEXT, ofctl_barrier, &barrier_aux); unixctl_command_register("ofctl/set-output-file", "FILE", 1, 1, - ofctl_set_output_file, NULL); - - unixctl_command_register("ofctl/block", "", 0, 0, ofctl_block, &blocked); - unixctl_command_register("ofctl/unblock", "", 0, 0, ofctl_unblock, - &blocked); + OVS_OUTPUT_FMT_TEXT, ofctl_set_output_file, + NULL); + unixctl_command_register("ofctl/block", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + ofctl_block, &blocked); + unixctl_command_register("ofctl/unblock", "", 0, 0, OVS_OUTPUT_FMT_TEXT, + ofctl_unblock, &blocked); daemonize_complete(); diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index e9110c1d8..fda873ac9 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -513,13 +513,16 @@ bridge_init(const char *remote) /* Register unixctl commands. */ unixctl_command_register("qos/show-types", "interface", 1, 1, - qos_unixctl_show_types, NULL); + OVS_OUTPUT_FMT_TEXT, qos_unixctl_show_types, + NULL); unixctl_command_register("qos/show", "interface", 1, 1, - qos_unixctl_show, NULL); + OVS_OUTPUT_FMT_TEXT, qos_unixctl_show, NULL); unixctl_command_register("bridge/dump-flows", "[--offload-stats] bridge", - 1, 2, bridge_unixctl_dump_flows, NULL); + 1, 2, OVS_OUTPUT_FMT_TEXT, + bridge_unixctl_dump_flows, NULL); unixctl_command_register("bridge/reconnect", "[bridge]", 0, 1, - bridge_unixctl_reconnect, NULL); + OVS_OUTPUT_FMT_TEXT, bridge_unixctl_reconnect, + NULL); lacp_init(); bond_init(); cfm_init(); @@ -3466,7 +3469,8 @@ qos_unixctl_show_queue(unsigned int queue_id, static void qos_unixctl_show_types(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; struct sset types = SSET_INITIALIZER(&types); @@ -3504,7 +3508,8 @@ qos_unixctl_show_types(struct unixctl_conn *conn, int argc OVS_UNUSED, static void qos_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; struct smap smap = SMAP_INITIALIZER(&smap); @@ -3624,7 +3629,9 @@ bridge_lookup(const char *name) * stack, including those normally hidden. */ static void bridge_unixctl_dump_flows(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct bridge *br; struct ds results; @@ -3654,7 +3661,9 @@ bridge_unixctl_dump_flows(struct unixctl_conn *conn, int argc, * drop their controller connections and reconnect. */ static void bridge_unixctl_reconnect(struct unixctl_conn *conn, int argc, - const char *argv[], void *aux OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, + void *aux OVS_UNUSED) { struct bridge *br; if (argc > 1) { diff --git a/vswitchd/ovs-vswitchd.c b/vswitchd/ovs-vswitchd.c index 273af9f5d..74b755778 100644 --- a/vswitchd/ovs-vswitchd.c +++ b/vswitchd/ovs-vswitchd.c @@ -111,7 +111,7 @@ main(int argc, char *argv[]) exit(EXIT_FAILURE); } unixctl_command_register("exit", "[--cleanup]", 0, 1, - ovs_vswitchd_exit, NULL); + OVS_OUTPUT_FMT_TEXT, ovs_vswitchd_exit, NULL); bridge_init(remote); free(remote); @@ -308,7 +308,8 @@ usage(void) static void ovs_vswitchd_exit(struct unixctl_conn *conn, int argc, - const char *argv[], void *args OVS_UNUSED) + const char *argv[], + enum ovs_output_fmt fmt OVS_UNUSED, void *args OVS_UNUSED) { exit_args.n_conns++; exit_args.conns = xrealloc(exit_args.conns,