diff mbox series

[ovs-dev,RFC] Add global option to output JSON from ovs-appctl cmds.

Message ID 20231020093954.1410995-1-jmeng@redhat.com
State Superseded, archived
Headers show
Series [ovs-dev,RFC] Add global option to output JSON from ovs-appctl cmds. | expand

Checks

Context Check Description
ovsrobot/apply-robot fail apply and check: fail
ovsrobot/intel-ovs-compilation fail test: fail

Commit Message

Jakob Meng Oct. 20, 2023, 9:39 a.m. UTC
From: Jakob Meng <code@jakobmeng.de>

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 <code@jakobmeng.de>
---
 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

Comments

0-day Robot Oct. 20, 2023, 9:56 a.m. UTC | #1
Bleep bloop.  Greetings Jakob Meng, I am a robot and I have tried out your patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


git-am:
error: patch failed: lib/bfd.c:912
error: lib/bfd.c: patch does not apply
error: patch failed: lib/dpctl.c:126
error: lib/dpctl.c: patch does not apply
error: patch failed: lib/dpif-netdev.c:151
error: lib/dpif-netdev.c: patch does not apply
error: patch failed: lib/dpif-netlink.c:4045
error: lib/dpif-netlink.c: patch does not apply
error: patch failed: lib/dpif.c:1715
error: lib/dpif.c: patch does not apply
error: patch failed: lib/lacp.c:83
error: lib/lacp.c: patch does not apply
error: patch failed: lib/netdev-dummy.c:1693
error: lib/netdev-dummy.c: patch does not apply
error: patch failed: lib/netdev-native-tnl.c:1178
error: lib/netdev-native-tnl.c: patch does not apply
error: patch failed: lib/netdev-vport.c:380
error: lib/netdev-vport.c: patch does not apply
error: patch failed: lib/stp.c:1030
error: lib/stp.c: patch does not apply
error: patch failed: lib/timeval.c:677
error: lib/timeval.c: patch does not apply
error: patch failed: lib/unixctl.c:35
error: lib/unixctl.c: patch does not apply
error: patch failed: ofproto/bond.c:227
error: ofproto/bond.c: patch does not apply
error: patch failed: ofproto/ofproto-dpif-upcall.c:772
error: ofproto/ofproto-dpif-upcall.c: patch does not apply
error: patch failed: ofproto/ofproto-dpif.c:260
error: ofproto/ofproto-dpif.c: patch does not apply
error: patch failed: ofproto/ofproto.c:1026
error: ofproto/ofproto.c: patch does not apply
error: patch failed: ovsdb/file.c:395
error: ovsdb/file.c: patch does not apply
error: patch failed: ovsdb/ovsdb-client.c:477
error: ovsdb/ovsdb-client.c: patch does not apply
error: patch failed: ovsdb/ovsdb-server.c:2180
error: ovsdb/ovsdb-server.c: patch does not apply
error: patch failed: ovsdb/ovsdb.c:429
error: ovsdb/ovsdb.c: patch does not apply
error: patch failed: ovsdb/raft.c:2488
error: ovsdb/raft.c: patch does not apply
error: patch failed: utilities/ovs-ofctl.c:544
error: utilities/ovs-ofctl.c: patch does not apply
error: patch failed: vswitchd/bridge.c:421
error: vswitchd/bridge.c: patch does not apply
error: Did you hand edit your patch?
It does not apply to blobs recorded in its index.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Add global option to output JSON from ovs-appctl cmds.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".


Patch skipped due to previous failure.

Please check this out.  If you feel there has been an error, please email aconole@redhat.com

Thanks,
0-day Robot
Jakob Meng Oct. 20, 2023, 10:44 a.m. UTC | #2
Superseeded by:

https://patchwork.ozlabs.org/project/openvswitch/patch/20231020104320.1417664-2-jmeng@redhat.com/
Eelco Chaudron Oct. 20, 2023, 11:45 a.m. UTC | #3
On 20 Oct 2023, at 11:39, jmeng@redhat.com wrote:

> From: Jakob Meng <code@jakobmeng.de>
>
> 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.

Thanks for sending out this patch. I like this way more than the other one, as I prefer consistency over smaller code changes.

>
> 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.

I think we should be backward compatible, i.e., and older clients should work forcing text output. Not sure if possible, but we should add a test case for this.

> 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.

My suggestion for this is to break out this patch into multiple ones.
For example, the first patch only changing the callback/register functions. The second patch containing the infrastructure changes, and the third (individual) patch containing the actual changes for the json supported command, like ‘dpif/show’.


> 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).

I was thinking of having it nicely formatted, but then I woke up at night crying about trying to maintain consistency among commands/additions. So after this nightmare, I think just printing in the compact form would be good enough and add some examples to the documentation on using jq.

So in other words, the output of the command should look like it was piped through ‘jq --compact-output’

>
> Wdyt?

I personally think this is the right approach compared to the per-command one, and I would suggest splitting up this patch and sending it as a non-RFC.

Also, this patch does not apply, so I only added some comments on things I spotted from looking at the diff (no in-depth review).

>
> [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 <code@jakobmeng.de>
> ---
>  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(-)
>
> 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;

Returning NULL might cause a problem in the json_string_create() below, how about returning “text” as this is the default value?

> +    }
> +}
> +
> +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 <openvswitch/list.h>
>
>  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;

Any reason why this is int, and not ‘enum ovs_output_fmt’, as here you only store a single output format?

>      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;
>  }
> -
> +

I think these odd add/deletes are causing the merge problems.

>  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 <size>", 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 <size>", 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 <stdbool.h>
>
>  #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 */

Be more explicit, or remove the comment, i.e. “Add dpif name to json.”

> +    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

Would it make sense to do 1 << 0, 1 << 1 here also to indicate we are using bits? So next time someone does not add 3?

> +
> +
>  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=<cleared>, requested_rx_queues=1, requested_tx_queues=<cleared>)
>  ])
>
> +AT_CHECK([ovs-appctl --format json dpif/show | sed 's/\(tx_queues": "\)[[0-9]]*"/\1<cleared>"/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": "<cleared>",
> +              "requested_rx_queues": "1",
> +              "requested_tx_queues": "<cleared>"},
> +            "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

I think we should add a test case for a non-Json-supported command to return an error when requesting json.
>
> 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");

Do we need to free this somewhere?

> +    }
> +    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"

Can we make the two help texts the same?

+  -f, --format=FMT   Output format. One of: 'json', or 'text'\n\
+                     ('text', by 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=<port> packet=<hex data> 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,
> --
> 2.39.2
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
diff mbox series

Patch

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 <openvswitch/list.h>

 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 <size>", 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 <size>", 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 <stdbool.h>

 #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=<cleared>, requested_rx_queues=1, requested_tx_queues=<cleared>)
 ])

+AT_CHECK([ovs-appctl --format json dpif/show | sed 's/\(tx_queues": "\)[[0-9]]*"/\1<cleared>"/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": "<cleared>",
+              "requested_rx_queues": "1",
+              "requested_tx_queues": "<cleared>"},
+            "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=<port> packet=<hex data> 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,