From: Dima Chumak <dchu...@nvidia.com> The 'ovs/route/show' command now supports machine-readable JSON output in addition to the plain-text output for humans. An example would be:
ovs-appctl --format json --pretty ovs/route/show [ { "is_local": false, "nw_addr": "::1", "output_netdev": "lo", "plen": 128, "priority": 128, "src_addr": "::1"}, { "is_local": true, "nw_addr": "10.237.157.103", "output_netdev": "eth1", "plen": 128, "priority": 192, "src_addr": "10.237.157.103"}, { "is_local": true, "nw_addr": "fe80::42:67ff:fe28:188", "output_netdev": "docker0", "plen": 128, "priority": 192, "src_addr": "fe80::42:67ff:fe28:188"}, { "gw": "192.168.121.1", "is_local": false, "nw_addr": "0.0.0.0", "output_netdev": "eth0", "plen": 96, "priority": 96, "src_addr": "192.168.121.203"}] Signed-off-by: Dima Chumak <dchu...@nvidia.com> Reviewed-by: Roi Dayan <r...@nvidia.com> --- lib/ovs-router.c | 103 ++++++++++++++++++++++++++++++++++++-------- tests/ovs-router.at | 35 +++++++++++++++ 2 files changed, 119 insertions(+), 19 deletions(-) diff --git a/lib/ovs-router.c b/lib/ovs-router.c index d955a3a543b8..eb04edece9cb 100644 --- a/lib/ovs-router.c +++ b/lib/ovs-router.c @@ -36,6 +36,7 @@ #include "dpif.h" #include "fatal-signal.h" #include "openvswitch/dynamic-string.h" +#include "openvswitch/json.h" #include "netdev.h" #include "packets.h" #include "seq.h" @@ -509,44 +510,108 @@ 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) +ovs_router_show_json(struct json **routes) { + struct json **json_entries = NULL; struct ovs_router_entry *rt; - struct ds ds = DS_EMPTY_INITIALIZER; + int i = 0; - ds_put_format(&ds, "Route Table:\n"); - CLS_FOR_EACH(rt, cr, &cls) { + if (!cls.n_rules) { + goto out; + } + + json_entries = xmalloc(cls.n_rules * sizeof *json_entries); + + CLS_FOR_EACH (rt, cr, &cls) { + struct json *json = json_object_create(); + struct ds ds; + + json_object_put(json, "is_local", json_boolean_create(rt->local)); + json_object_put(json, "priority", json_integer_create(rt->priority)); + json_object_put(json, "plen", json_integer_create(rt->plen)); + json_object_put_string(json, "output_netdev", rt->output_netdev); + + ds_init(&ds); + ipv6_format_mapped(&rt->nw_addr, &ds); + json_object_put_string(json, "nw_addr", ds_cstr_ro(&ds)); + ds_destroy(&ds); + + ds_init(&ds); + ipv6_format_mapped(&rt->src_addr, &ds); + json_object_put_string(json, "src_addr", ds_cstr_ro(&ds)); + ds_destroy(&ds); + + if (rt->mark) { + json_object_put(json, "mark", json_integer_create(rt->mark)); + } + + if (ipv6_addr_is_set(&rt->gw)) { + ds_init(&ds); + ipv6_format_mapped(&rt->gw, &ds); + json_object_put_string(json, "gw", ds_cstr_ro(&ds)); + ds_destroy(&ds); + } + + json_entries[i++] = json; + } + +out: + *routes = json_array_create(json_entries, i); +} + +static void +ovs_router_show_text(struct ds *ds) +{ + struct ovs_router_entry *rt; + + ds_put_format(ds, "Route Table:\n"); + CLS_FOR_EACH (rt, cr, &cls) { uint8_t plen; if (rt->priority == rt->plen || rt->local) { - ds_put_format(&ds, "Cached: "); + ds_put_format(ds, "Cached: "); } else { - ds_put_format(&ds, "User: "); + ds_put_format(ds, "User: "); } - ipv6_format_mapped(&rt->nw_addr, &ds); + ipv6_format_mapped(&rt->nw_addr, ds); plen = rt->plen; if (IN6_IS_ADDR_V4MAPPED(&rt->nw_addr)) { plen -= 96; } - ds_put_format(&ds, "/%"PRIu8, plen); + ds_put_format(ds, "/%"PRIu8, plen); if (rt->mark) { - ds_put_format(&ds, " MARK %"PRIu32, rt->mark); + ds_put_format(ds, " MARK %"PRIu32, rt->mark); } - ds_put_format(&ds, " dev %s", rt->output_netdev); + ds_put_format(ds, " dev %s", rt->output_netdev); if (ipv6_addr_is_set(&rt->gw)) { - ds_put_format(&ds, " GW "); - ipv6_format_mapped(&rt->gw, &ds); + ds_put_format(ds, " GW "); + ipv6_format_mapped(&rt->gw, ds); } - ds_put_format(&ds, " SRC "); - ipv6_format_mapped(&rt->src_addr, &ds); + ds_put_format(ds, " SRC "); + ipv6_format_mapped(&rt->src_addr, ds); if (rt->local) { - ds_put_format(&ds, " local"); + ds_put_format(ds, " local"); } - ds_put_format(&ds, "\n"); + ds_put_format(ds, "\n"); + } +} + +static void +ovs_router_show(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) +{ + if (unixctl_command_get_output_format(conn) == UNIXCTL_OUTPUT_FMT_JSON) { + struct json *routes; + + ovs_router_show_json(&routes); + unixctl_command_reply_json(conn, routes); + } else { + struct ds ds = DS_EMPTY_INITIALIZER; + + ovs_router_show_text(&ds); + unixctl_command_reply(conn, ds_cstr(&ds)); + ds_destroy(&ds); } - unixctl_command_reply(conn, ds_cstr(&ds)); - ds_destroy(&ds); } static void diff --git a/tests/ovs-router.at b/tests/ovs-router.at index b3314b3dff0d..13a38eb55055 100644 --- a/tests/ovs-router.at +++ b/tests/ovs-router.at @@ -28,6 +28,41 @@ User: 1.1.1.0/24 dev br0 GW 2.2.2.10 SRC 2.2.2.2 User: 1.1.2.0/24 MARK 2 dev br0 GW 2.2.2.10 SRC 2.2.2.2 User: 2.2.2.3/32 MARK 1 dev br0 SRC 2.2.2.2 ]) +AT_CHECK([ovs-appctl --format=json --pretty ovs/route/show], [0], [dnl +[[ + { + "is_local": true, + "nw_addr": "2.2.2.0", + "output_netdev": "br0", + "plen": 120, + "priority": 184, + "src_addr": "2.2.2.2"}, + { + "gw": "2.2.2.10", + "is_local": false, + "nw_addr": "1.1.1.0", + "output_netdev": "br0", + "plen": 120, + "priority": 152, + "src_addr": "2.2.2.2"}, + { + "gw": "2.2.2.10", + "is_local": false, + "mark": 2, + "nw_addr": "1.1.2.0", + "output_netdev": "br0", + "plen": 120, + "priority": 152, + "src_addr": "2.2.2.2"}, + { + "is_local": false, + "mark": 1, + "nw_addr": "2.2.2.3", + "output_netdev": "br0", + "plen": 128, + "priority": 160, + "src_addr": "2.2.2.2"}]] +]) OVS_VSWITCHD_STOP AT_CLEANUP -- 2.21.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev