From patchwork Fri Oct 20 09:39:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakob Meng X-Patchwork-Id: 1852403 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=F6WdjfWb; 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 4SBfhN6QVMz23jM for ; Fri, 20 Oct 2023 20:40:20 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 9686342E36; Fri, 20 Oct 2023 09:40:18 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 9686342E36 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=F6WdjfWb 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 oSOjoectcAIv; Fri, 20 Oct 2023 09:40:15 +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 53A074188D; Fri, 20 Oct 2023 09:40:14 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 53A074188D Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3637BC0039; Fri, 20 Oct 2023 09:40:14 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 134D3C0039 for ; Fri, 20 Oct 2023 09:40:13 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id D3AB182347 for ; Fri, 20 Oct 2023 09:40:12 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org D3AB182347 Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=F6WdjfWb X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PQQlkjC4I7HH for ; Fri, 20 Oct 2023 09:40:09 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id 79518822B7 for ; Fri, 20 Oct 2023 09:40:09 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 79518822B7 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1697794808; 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; bh=WxsjyyFAZqNroVHEXL/ptA2BTt53tpVHaDWcTHUlElI=; b=F6WdjfWbRODZyqG+lN8u++1PPVJoTK8x/gT8K2yfz+TGgG/uKyA21E8o8ZYIM/2fewHhD+ uYpoF1K3RP/66UVClzvrIW+R7gJGHujQzltjNkik/TjSoOv8zkz1csslFjelfUJL166Aq1 MORWTDhpzSExt12CL3TWe2XvSf+IreI= 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-577-lsYG_FR4PXqbuaQKu_-pSw-1; Fri, 20 Oct 2023 05:40:05 -0400 X-MC-Unique: lsYG_FR4PXqbuaQKu_-pSw-1 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-32dceab634dso327760f8f.2 for ; Fri, 20 Oct 2023 02:40:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697794804; x=1698399604; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=WxsjyyFAZqNroVHEXL/ptA2BTt53tpVHaDWcTHUlElI=; b=tM8clDQkRhy5+Vc+TUuYvPEwXmzEkBXOdeH1iFaHy2iGIezt6OV7Sn7Dv2tPkSVBal DErI+uMrIqSHqWmTQ63eXMpJCyi8CVVcykwKBtBPEb9/6lixucPP/MkFAUq8JWwRQ3oP miPuyatbdMH+6KGs+gvvDVd/+fkZKHVGS7pbExI6i3Sow95Nf/6x/GvgAi38/7QwowLh oZZiTPixUrBL//5rzBLvzIh6bhcVCf2VHGQfHnijCS6VzTMswz9g4eCUrFep45mxW3oj 9jDPSKG7383JWk0KBSZYDfUxUJZV8nt5lH8S/ivaha35P1D2DVnHT1/Nik4aku48skpl 15TQ== X-Gm-Message-State: AOJu0YwJS2H9TPW3bkON5Tl6ziihxiOHaQizdrZGCsq6xzyIeufaolYY oAa8Y+5jIAP1Ez+gwzB+z8G16yPT6hQv9ljJKzvrh6QUq4c0yMWItBDhXUtAiba5Kg71wcgwfUs nqP2k3+rAzKZ+HjcCIIrXAF/g03pwNhVEosn3dJP5x0OSis6KnltyaOkndBxh40t0Ke0= X-Received: by 2002:a5d:534b:0:b0:32d:8410:f526 with SMTP id t11-20020a5d534b000000b0032d8410f526mr810453wrv.13.1697794803211; Fri, 20 Oct 2023 02:40:03 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFYp293RlNCQ2lsUTqYr6FR3yjmRIfJfMCdKY5m7tWYYQjeXhx8F8EsizWR+mV8RezGb2iouQ== X-Received: by 2002:a5d:534b:0:b0:32d:8410:f526 with SMTP id t11-20020a5d534b000000b0032d8410f526mr810418wrv.13.1697794801692; Fri, 20 Oct 2023 02:40:01 -0700 (PDT) Received: from positronik4lide.redhat.com ([87.122.57.185]) by smtp.gmail.com with ESMTPSA id z10-20020adff74a000000b003231ca246b6sm1281388wrp.95.2023.10.20.02.40.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Oct 2023 02:40:01 -0700 (PDT) From: jmeng@redhat.com To: dev@openvswitch.org Date: Fri, 20 Oct 2023 11:39:54 +0200 Message-Id: <20231020093954.1410995-1-jmeng@redhat.com> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC] 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 | 18 ++- lib/cfm.c | 13 +- lib/command-line.c | 35 ++++++ lib/command-line.h | 10 ++ lib/coverage.c | 11 +- lib/dpctl.c | 139 ++++++++++++--------- lib/dpctl.h | 4 + lib/dpdk.c | 15 ++- lib/dpif-netdev-perf.c | 1 + lib/dpif-netdev-perf.h | 1 + lib/dpif-netdev.c | 102 +++++++++------- lib/dpif-netlink.c | 10 +- lib/dpif.c | 4 +- lib/lacp.c | 15 ++- lib/memory.c | 5 +- lib/netdev-dpdk.c | 16 ++- lib/netdev-dummy.c | 32 +++-- lib/netdev-native-tnl.c | 6 +- lib/netdev-native-tnl.h | 4 +- lib/netdev-vport.c | 7 +- 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 | 24 ++-- lib/timeval.c | 17 +-- lib/tnl-neigh-cache.c | 35 ++++-- lib/tnl-ports.c | 6 +- lib/unixctl.c | 211 +++++++++++++++++++++----------- lib/unixctl.h | 11 +- lib/vlog.c | 46 ++++--- ofproto/bond.c | 46 ++++--- ofproto/ofproto-dpif-trace.c | 10 +- ofproto/ofproto-dpif-upcall.c | 87 +++++++++---- ofproto/ofproto-dpif.c | 216 ++++++++++++++++++++++++++------- ofproto/ofproto.c | 48 ++++---- ofproto/tunnel.c | 4 +- ovsdb/file.c | 10 +- ovsdb/ovsdb-client.c | 48 +++++--- ovsdb/ovsdb-server.c | 124 ++++++++++++++----- ovsdb/ovsdb.c | 6 +- ovsdb/raft.c | 36 ++++-- 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 | 49 +++++--- vswitchd/bridge.c | 41 ++++--- vswitchd/ovs-vswitchd.c | 5 +- 59 files changed, 1303 insertions(+), 591 deletions(-) -- 2.39.2 diff --git a/lib/bfd.c b/lib/bfd.c index 9698576d0..2e8d171bf 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); } @@ -912,7 +917,7 @@ bfd_set_netdev(struct bfd *bfd, const struct netdev *netdev) ovs_mutex_unlock(&mutex); } - + /* Updates the forwarding flag. If override is not configured and * the forwarding flag value changes, increments the flap count. * @@ -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..c9a310ef4 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; }; @@ -126,7 +127,7 @@ dpctl_error(struct dpctl_params* dpctl_p, int err_no, const char *fmt, ...) errno = save_errno; } - + static int dpctl_add_if(int argc, const char *argv[], struct dpctl_params *); static int @@ -1667,7 +1668,7 @@ dpctl_list_commands(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, return 0; } - + static int dpctl_dump_conntrack(int argc, const char *argv[], @@ -2070,7 +2071,7 @@ dpctl_ct_bkts(int argc, const char *argv[], free(conn_per_bkts); return error; } - + static int dpctl_ct_set_maxconns(int argc, const char *argv[], struct dpctl_params *dpctl_p) @@ -2988,71 +2989,95 @@ out: return error; } - + 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) @@ -3101,7 +3126,7 @@ dpctl_run_command(int argc, const char *argv[], struct dpctl_params *dpctl_p) argv[0]); return EINVAL; } - + static void dpctl_unixctl_print(void *userdata, bool error OVS_UNUSED, const char *msg) { @@ -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..4922c5a10 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -151,7 +151,7 @@ static struct odp_support dp_netdev_support = { .ct_orig_tuple6 = true, }; - + /* Simple non-wildcarding single-priority classifier. */ /* Time in microseconds between successive optimizations of the dpcls @@ -695,7 +695,7 @@ get_dp_netdev(const struct dpif *dpif) { return dpif_netdev_cast(dpif)->dp; } - + enum pmd_info_type { PMD_INFO_SHOW_STATS, /* Show how cpu cycles are spent. */ PMD_INFO_CLEAR_STATS, /* Set the cycles count to 0. */ @@ -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; @@ -1612,7 +1623,7 @@ dpif_netdev_bond_show(struct unixctl_conn *conn, int argc, ds_destroy(&reply); } - + static int dpif_netdev_init(void) { @@ -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; } @@ -5208,7 +5219,7 @@ dpif_netdev_queue_to_priority(const struct dpif *dpif OVS_UNUSED, return 0; } - + /* Creates and returns a new 'struct dp_netdev_actions', whose actions are * a copy of the 'size' bytes of 'actions' input parameters. */ struct dp_netdev_actions * @@ -5236,7 +5247,7 @@ dp_netdev_actions_free(struct dp_netdev_actions *actions) { free(actions); } - + static void dp_netdev_rxq_set_cycles(struct dp_netdev_rxq *rx, enum rxq_cycles_counter_type type, @@ -7190,7 +7201,7 @@ dp_netdev_disable_upcall(struct dp_netdev *dp) fat_rwlock_wrlock(&dp->upcall_rwlock); } - + /* Meters */ static void dpif_netdev_meter_get_features(const struct dpif * dpif OVS_UNUSED, @@ -7510,7 +7521,7 @@ dpif_netdev_meter_del(struct dpif *dpif, return error; } - + static void dpif_netdev_disable_upcall(struct dpif *dpif) OVS_NO_THREAD_SAFETY_ANALYSIS @@ -7918,7 +7929,7 @@ dp_netdev_del_bond_tx_from_pmd(struct dp_netdev_pmd_thread *pmd, } ovs_mutex_unlock(&pmd->bond_mutex); } - + static char * dpif_netdev_get_datapath_version(void) { @@ -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,9 +9942,10 @@ 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. */ static void diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 9194971d3..a4809b447 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. */ @@ -4045,7 +4047,7 @@ dpif_netlink_ct_timeout_policy_dump_done(struct dpif *dpif OVS_UNUSED, } #endif - + /* Meters */ /* Set of supported meter flags */ @@ -4516,7 +4518,7 @@ dpif_netlink_cache_set_size(struct dpif *dpif_, uint32_t level, uint32_t size) return error; } - + const struct dpif_class dpif_netlink_class = { "system", false, /* cleanup_required */ @@ -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/dpif.c b/lib/dpif.c index d07241f1e..40579288b 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1715,7 +1715,7 @@ dpif_queue_to_priority(const struct dpif *dpif, uint32_t queue_id, log_operation(dpif, "queue_to_priority", error); return error; } - + void dpif_init(struct dpif *dpif, const struct dpif_class *dpif_class, const char *name, @@ -1747,7 +1747,7 @@ dpif_uninit(struct dpif *dpif, bool close) free(base_name); free(full_name); } - + static void log_operation(const struct dpif *dpif, const char *operation, int error) { diff --git a/lib/lacp.c b/lib/lacp.c index 3252f17eb..ac8d7d7ce 100644 --- a/lib/lacp.c +++ b/lib/lacp.c @@ -83,7 +83,7 @@ struct lacp_pdu { uint8_t z3[64]; /* Combination of several fields. Always 0. */ }; BUILD_ASSERT_DECL(LACP_PDU_LEN == sizeof(struct lacp_pdu)); - + /* Implementation. */ enum pdu_subtype { @@ -218,17 +218,18 @@ parse_lacp_packet(const struct dp_packet *p, enum pdu_subtype *subtype) return NULL; } } - + /* LACP Protocol Implementation. */ /* Initializes the lacp module. */ 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 @@ -667,7 +668,7 @@ lacp_wait(struct lacp *lacp) OVS_EXCLUDED(mutex) } lacp_unlock(); } - + /* Static Helpers. */ /* Updates the attached status of all members controlled by 'lacp' and sets its @@ -925,7 +926,7 @@ info_tx_equal(struct lacp_info *a, struct lacp_info *b) && a->sys_priority == b->sys_priority && eth_addr_equals(a->sys_id, b->sys_id); } - + static struct lacp * lacp_find(const char *name) OVS_REQUIRES(mutex) { @@ -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..f3e08f695 100644 --- a/lib/netdev-dummy.c +++ b/lib/netdev-dummy.c @@ -1693,7 +1693,7 @@ static const struct netdev_flow_api netdev_offload_dummy = { .init_flow_api = netdev_dummy_offloads_init_flow_api, }; - + /* Helper functions. */ static void @@ -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..598aefa68 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -1178,10 +1178,12 @@ netdev_geneve_build_header(const struct netdev *netdev, return 0; } - + 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..1c0c1fb5e 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -380,7 +380,7 @@ netdev_vport_wait(const struct netdev_class *netdev_class OVS_UNUSED) poll_immediate_wake(); } } - + /* Code specific to tunnel types. */ static ovs_be64 @@ -1089,7 +1089,7 @@ get_tunnel_config(const struct netdev *dev, struct smap *args) return 0; } - + /* Code specific to patch ports. */ /* If 'netdev' is a patch port, returns the name of its peer as a malloc()'d @@ -1219,7 +1219,7 @@ netdev_vport_get_pt_mode(const struct netdev *netdev) } - + #ifdef __linux__ static int netdev_vport_get_ifindex(const struct netdev *netdev_) @@ -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..99e55229d 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); } } @@ -1030,7 +1032,7 @@ stp_port_disable_change_detection(struct stp_port *p) { p->change_detection_enabled = false; } - + static void stp_transmit_config(struct stp_port *p) OVS_REQUIRES(mutex) { @@ -1594,7 +1596,7 @@ stp_send_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) p->stp->send_bpdu(pkt, stp_port_no(p), p->stp->aux); p->tx_count++; } - + /* Unixctl. */ static struct stp * @@ -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..94493c076 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -677,7 +677,7 @@ log_poll_interval(long long int last_wakeup) coverage_log(); } } - + /* CPU usage tracking. */ struct cpu_usage { @@ -758,15 +758,16 @@ get_cpu_usage(void) { return get_cpu_tracker()->cpu_usage; } - + /* Unixctl interface. */ /* "time/stop" stops the monotonic time returned by e.g. time_msec() from * 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..89f10f2b7 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" @@ -35,10 +34,11 @@ VLOG_DEFINE_THIS_MODULE(unixctl); COVERAGE_DEFINE(unixctl_received); 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 @@ -439,7 +492,7 @@ unixctl_server_get_path(const struct unixctl_server *server) { return server ? server->path : NULL; } - + /* On POSIX based systems, connects to a unixctl server socket. 'path' should * be the name of a unixctl server socket. If it does not start with '/', it * will be prefixed with the rundir (e.g. /usr/local/var/run/openvswitch). @@ -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..de811221a 100644 --- a/ofproto/bond.c +++ b/ofproto/bond.c @@ -227,7 +227,7 @@ bond_mode_to_string(enum bond_mode balance) { OVS_NOT_REACHED(); } - + /* Creates and returns a new bond whose configuration is initially taken from * 's'. * @@ -776,7 +776,7 @@ bond_wait(struct bond *bond) * schedule and bond_rebalance() gets called afterward, so we'd just be * waking up for no purpose. */ } - + /* MAC learning table interaction. */ static bool @@ -840,7 +840,7 @@ bond_compose_learning_packet(struct bond *bond, const struct eth_addr eth_src, ovs_rwlock_unlock(&rwlock); return packet; } - + static bool bond_is_falling_back_to_ab(const struct bond *bond) @@ -1002,7 +1002,7 @@ bond_choose_output_member(struct bond *bond, const struct flow *flow, return aux; } - + /* Recirculation. */ static void bond_entry_account(struct bond_entry *entry, uint64_t rule_tx_bytes) @@ -1120,7 +1120,7 @@ bond_get_recirc_id_and_hash_basis(struct bond *bond, uint32_t *recirc_id, } ovs_rwlock_unlock(&rwlock); } - + /* Rebalancing. */ static bool @@ -1439,7 +1439,7 @@ bond_rebalance(struct bond *bond) done: ovs_rwlock_unlock(&rwlock); } - + /* Bonding unixctl user interface functions. */ static struct bond * @@ -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,29 +1838,36 @@ 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 bond_entry_reset(struct bond *bond) { 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..386279fa1 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); } } @@ -772,7 +795,7 @@ udpif_use_ufid(struct udpif *udpif) return enable && udpif->backer->rt_support.ufid; } - + static unsigned long udpif_get_n_flows(struct udpif *udpif) { @@ -1077,7 +1100,7 @@ udpif_revalidator(void *arg) return NULL; } - + static enum upcall_type classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata, struct user_action_cookie *cookie) @@ -3064,10 +3087,12 @@ dp_purge_cb(void *aux, unsigned pmd_id) } udpif_resume_revalidators(udpif); } - + 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..0f2089480 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" @@ -260,7 +261,7 @@ ofproto_dpif_send_async_msg(struct ofproto_dpif *ofproto, /* Wakes up main thread for packet-in I/O. */ seq_change(ofproto->ams_seq); } - + /* Factory functions. */ static void @@ -321,7 +322,7 @@ del(const char *type, const char *name) } return error; } - + static const char * port_open_type(const char *datapath_type, const char *port_type) { @@ -662,7 +663,7 @@ type_wait(const char *type) dpif_wait(backer->dpif); } - + /* Basic life-cycle. */ static int add_internal_flows(struct ofproto_dpif *); @@ -2556,7 +2557,7 @@ aa_vlan_get_queue_size(struct ofproto *ofproto OVS_UNUSED) return aa_get_vlan_queue_size(); } - + /* Spanning Tree. */ /* Called while rstp_mutex is held. */ @@ -3063,7 +3064,7 @@ get_rstp_port_status(struct ofport *ofport_, &s->rx_count, &s->error_count, &s->uptime); } - + static int set_queues(struct ofport *ofport_, const struct ofproto_port_queue *qdscp, size_t n_qdscp) @@ -3084,7 +3085,7 @@ set_queues(struct ofport *ofport_, const struct ofproto_port_queue *qdscp, return 0; } - + /* Bundles. */ /* Expires all MAC learning entries associated with 'bundle' and forces its @@ -3635,7 +3636,7 @@ bundle_wait(struct ofbundle *bundle) bond_wait(bundle->bond); } } - + /* Mirrors. */ static int @@ -3769,7 +3770,7 @@ set_mcast_snooping_port(struct ofproto *ofproto_, void *aux, return 0; } - + /* Ports. */ struct ofport_dpif * @@ -4183,7 +4184,7 @@ port_is_lacp_current(const struct ofport *ofport_) ? lacp_member_is_current(ofport->bundle->lacp, ofport) : -1); } - + /* If 'rule' is an OpenFlow rule, that has expired according to OpenFlow rules, * then delete it entirely. */ static void @@ -5304,7 +5305,7 @@ group_dpif_lookup(struct ofproto_dpif *ofproto, uint32_t group_id, version, take_ref); return ofgroup ? group_dpif_cast(ofgroup) : NULL; } - + /* Sends 'packet' out 'ofport'. If 'port' is a tunnel and that tunnel type * supports a notion of an OAM flag, sets it if 'oam' is true. * May modify 'packet'. @@ -5324,7 +5325,7 @@ ofproto_dpif_send_packet(const struct ofport_dpif *ofport, bool oam, ovs_mutex_unlock(&ofproto->stats_mutex); return error; } - + /* Return the version string of the datapath that backs up * this 'ofproto'. */ @@ -5776,7 +5777,7 @@ nxt_resume(struct ofproto *ofproto_, return error; } - + /* NetFlow. */ static int @@ -5808,7 +5809,7 @@ get_netflow_ids(const struct ofproto *ofproto_, dpif_get_netflow_ids(ofproto->backer->dpif, engine_type, engine_id); } - + struct ofproto_dpif * ofproto_dpif_lookup_by_name(const char *name) { @@ -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,34 +6702,44 @@ 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); } - + static odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port) { diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index e78c80d11..7f98bdf22 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1026,7 +1026,7 @@ ofproto_ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone_id) } - + /* Spanning Tree Protocol (STP) configuration. */ /* Configures STP on 'ofproto' using the settings defined in 's'. If @@ -1201,7 +1201,7 @@ ofproto_port_get_rstp_status(struct ofproto *ofproto, ofp_port_t ofp_port, ofproto->ofproto_class->get_rstp_port_status(ofport, s); return 0; } - + /* Queue DSCP configuration. */ /* Registers meta-data associated with the 'n_qdscp' Qualities of Service @@ -1228,7 +1228,7 @@ ofproto_port_set_queues(struct ofproto *ofproto, ofp_port_t ofp_port, ? ofproto->ofproto_class->set_queues(ofport, queues, n_queues) : EOPNOTSUPP); } - + /* LLDP configuration. */ void ofproto_port_set_lldp(struct ofproto *ofproto, @@ -1432,7 +1432,7 @@ ofproto_port_get_lacp_stats(const struct ofport *port, return error; } - + /* Bundles. */ /* Registers a "bundle" associated with client data pointer 'aux' in 'ofproto'. @@ -1463,7 +1463,7 @@ ofproto_bundle_unregister(struct ofproto *ofproto, void *aux) return ofproto_bundle_register(ofproto, aux, NULL); } - + /* Registers a mirror associated with client data pointer 'aux' in 'ofproto'. * If 'aux' is already registered then this function updates its configuration * to 's'. Otherwise, this function registers a new mirror. */ @@ -1525,7 +1525,7 @@ ofproto_is_mirror_output_bundle(const struct ofproto *ofproto, void *aux) ? ofproto->ofproto_class->is_mirror_output_bundle(ofproto, aux) : false); } - + /* Configuration of OpenFlow tables. */ /* Returns the number of OpenFlow tables in 'ofproto'. */ @@ -1587,7 +1587,7 @@ ofproto_configure_table(struct ofproto *ofproto, int table_id, evict_rules_from_table(table); ovs_mutex_unlock(&ofproto_mutex); } - + bool ofproto_has_snoops(const struct ofproto *ofproto) { @@ -2379,7 +2379,7 @@ ofproto_flush_flows(struct ofproto *ofproto) ofproto_flush__(ofproto, false); connmgr_flushed(ofproto->connmgr); } - + static void reinit_ports(struct ofproto *p) { @@ -3001,7 +3001,7 @@ update_mtu_ofproto(struct ofproto *p) } } } - + static void ofproto_rule_destroy__(struct rule *rule) OVS_NO_THREAD_SAFETY_ANALYSIS @@ -3275,7 +3275,7 @@ rule_is_readonly(const struct rule *rule) const struct oftable *table = &rule->ofproto->tables[rule->table_id]; return (table->flags & OFTABLE_READONLY) != 0; } - + static uint32_t hash_learned_cookie(ovs_be64 cookie_, uint8_t table_id) { @@ -3390,7 +3390,7 @@ learned_cookies_flush(struct ofproto *ofproto, struct ovs_list *dead_cookies) } minimatch_destroy(&match); } - + static enum ofperr handle_echo_request(struct ofconn *ofconn, const struct ofp_header *oh) { @@ -5342,7 +5342,7 @@ add_flow_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm, return error; } - + /* OFPFC_MODIFY and OFPFC_MODIFY_STRICT. */ /* Create a new rule. Note that the rule is NOT inserted into a any data @@ -6037,7 +6037,7 @@ modify_flow_start_strict(struct ofproto *ofproto, struct ofproto_flow_mod *ofm) return error; } - + /* OFPFC_DELETE implementation. */ static void @@ -6316,7 +6316,7 @@ ofproto_rule_reduce_timeouts(struct rule *rule, reduce_timeout(hard_timeout, &rule->hard_timeout); ovs_mutex_unlock(&rule->mutex); } - + static enum ofperr handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh) OVS_EXCLUDED(ofproto_mutex) @@ -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) { @@ -8940,7 +8940,7 @@ handle_openflow(struct ofconn *ofconn, const struct ovs_list *msgs) ofconn_send_error(ofconn, msg->data, error); } } - + static uint64_t pick_datapath_id(const struct ofproto *ofproto) { @@ -8969,7 +8969,7 @@ pick_fallback_dpid(void) eth_addr_nicira_random(&ea); return eth_addr_to_uint64(ea); } - + /* Table overflow policy. */ /* Chooses and updates 'rulep' with a rule to evict from 'table'. Sets 'rulep' @@ -9010,7 +9010,7 @@ choose_rule_to_evict(struct oftable *table, struct rule **rulep) return false; } - + /* Eviction groups. */ /* Returns the priority to use for an eviction_group that contains 'n_rules' @@ -9215,7 +9215,7 @@ eviction_group_add_rule(struct rule *rule) eviction_group_resized(table, evg); } } - + /* oftables. */ /* Initializes 'table'. */ @@ -9434,7 +9434,7 @@ ofproto_rule_remove__(struct ofproto *ofproto, struct rule *rule) rule->state = RULE_REMOVED; } - + /* unixctl commands. */ struct ofproto * @@ -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..63bdb267a 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 * @@ -395,7 +397,7 @@ error: *dstp = NULL; return error; } - + static bool ovsdb_file_change_cb(const struct ovsdb_row *old, const struct ovsdb_row *new, @@ -463,7 +465,7 @@ ovsdb_file_txn_annotate(struct json *json, const char *comment) json_object_put(json, "_date", json_integer_create(time_wall_msec())); return json; } - + static void ovsdb_file_txn_init(struct ovsdb_file_txn *ftxn) { @@ -550,7 +552,7 @@ ovsdb_file_txn_add_row(struct ovsdb_file_txn *ftxn, json_object_put(ftxn->table_json, uuid, row); } } - + static struct ovsdb * ovsdb_file_read__(const char *filename, bool rw, struct ovsdb_schema *new_schema) diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index 7249805ba..f0fd32ae2 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -477,7 +477,7 @@ usage(void) " -V, --version display version information\n"); exit(EXIT_SUCCESS); } - + static void check_txn(int error, struct jsonrpc_msg **reply_) { @@ -733,7 +733,7 @@ should_stay_connected(const char *server, const char *database, return true; } - + static void do_list_dbs(struct jsonrpc *rpc, const char *database OVS_UNUSED, int argc OVS_UNUSED, char *argv[] OVS_UNUSED) @@ -934,7 +934,7 @@ do_query(struct jsonrpc *rpc OVS_UNUSED, const char *database OVS_UNUSED, /* Print the result. */ print_and_free_json(result); } - + /* "monitor" command. */ struct monitored_table { @@ -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; @@ -2195,7 +2202,7 @@ do_help(struct jsonrpc *rpc OVS_UNUSED, const char *database OVS_UNUSED, usage(); } - + /* "lock" command. */ struct ovsdb_client_lock_req { @@ -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..5c8574184 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_; @@ -2180,7 +2240,7 @@ usage(void) " -V, --version display version information\n"); exit(EXIT_SUCCESS); } - + static struct json * sset_to_json(const struct sset *sset) { diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c index f67b836d7..d7f5b64b5 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 @@ -429,7 +431,7 @@ ovsdb_schema_persist_ephemeral_columns(struct ovsdb_schema *schema, filename, n, schema->name, example_column, example_table); } } - + static void ovsdb_set_ref_table(const struct shash *tables, struct ovsdb_base_type *base) diff --git a/ovsdb/raft.c b/ovsdb/raft.c index 8effd9ad1..80aff0cc9 100644 --- a/ovsdb/raft.c +++ b/ovsdb/raft.c @@ -2488,7 +2488,7 @@ raft_find_command_by_eid(struct raft *raft, const struct uuid *eid) } return NULL; } - + #define RAFT_RPC(ENUM, NAME) \ static void raft_handle_##NAME(struct raft *, const struct raft_##NAME *); RAFT_RPC_TYPES @@ -4523,7 +4523,7 @@ raft_handle_rpc(struct raft *raft, const union raft_rpc *rpc) OVS_NOT_REACHED(); } } - + static bool raft_rpc_is_heartbeat(const union raft_rpc *rpc) { @@ -4533,7 +4533,7 @@ raft_rpc_is_heartbeat(const union raft_rpc *rpc) && !strcmp(rpc->common.comment, "heartbeat")); } - + static bool raft_send_to_conn_at(struct raft *raft, const union raft_rpc *rpc, struct raft_conn *conn, int line_number) @@ -4585,7 +4585,7 @@ raft_send_at(struct raft *raft, const union raft_rpc *rpc, int line_number) return raft_send_to_conn_at(raft, rpc, conn, line_number); } - + static struct raft * raft_lookup_by_name(const char *name) { @@ -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..49625588b 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; @@ -544,7 +545,7 @@ run(int retval, const char *message, ...) ovs_fatal_valist(retval, message, args); } } - + /* Generic commands. */ static int @@ -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(); @@ -3424,7 +3435,7 @@ ofctl_list_commands(struct ovs_cmdl_context *ctx OVS_UNUSED) { ovs_cmdl_print_commands(get_all_commands()); } - + /* replace-flows and diff-flows commands. */ struct flow_tables { @@ -4181,7 +4192,7 @@ ofctl_meter_features(struct ovs_cmdl_context *ctx) ofctl_meter_request__(ctx->argv[1], NULL, OFPUTIL_METER_FEATURES); } - + /* Undocumented commands for unit testing. */ static void diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index e9110c1d8..4747d7479 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -421,7 +421,7 @@ if_notifier_changed(struct if_notifier *notifier OVS_UNUSED) seq_wait(ifaces_changed, last_ifaces_changed); return changed; } - + /* Public functions. */ /* Initializes the bridge module, configuring it to obtain its configuration @@ -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(); @@ -3054,7 +3057,7 @@ refresh_controller_status(void) ofproto_free_ofproto_controller_info(&info); } } - + /* Update interface and mirror statistics if necessary. */ static void run_stats_update(void) @@ -3416,7 +3419,7 @@ bridge_get_memory_usage(struct simap *usage) ovsdb_idl_get_memory_usage(idl, usage); } - + /* QoS unixctl user interface functions. */ struct qos_unixctl_show_cbdata { @@ -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); @@ -3552,7 +3557,7 @@ qos_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, smap_destroy(&smap); ds_destroy(&ds); } - + /* Bridge reconfiguration functions. */ static void bridge_create(const struct ovsrec_bridge *br_cfg) @@ -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) { @@ -4355,7 +4364,7 @@ bridge_aa_refresh_queued(struct bridge *br) free(list); } - + /* Port functions. */ static struct port * @@ -4617,7 +4626,7 @@ port_is_synthetic(const struct port *port) { return ovsdb_idl_row_is_synthetic(&port->cfg->header_); } - + /* Interface functions. */ static bool @@ -4985,7 +4994,7 @@ iface_pick_ofport(const struct ovsrec_interface *cfg) ? requested_ofport : iface_validate_ofport__(cfg->n_ofport, cfg->ofport)); } - + /* Port mirroring. */ static struct mirror * @@ -5179,7 +5188,7 @@ mirror_configure(struct mirror *m) return true; } - + static void mirror_refresh_stats(struct mirror *m) { 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,