From: Dima Chumak <[email protected]>
The 'ovs/route/show' command now supports machine-readable JSON output
in addition to the plain-text output for humans.
Align the keys to match ip route output so also update the command
help output from mask to mask.
An example json output would be:
ovs-appctl --format json --pretty ovs/route/show
[
{
"dev": "lo",
"dst": "::1",
"local": false,
"mask": 128,
"prefsrc": "::1",
"priority": 128,
"user": false},
{
"dev": "eth1",
"dst": "10.237.157.103",
"local": true,
"mask": 128,
"prefsrc": "10.237.157.103",
"priority": 192,
"user": false},
{
"dev": "docker0",
"dst": "fe80::42:67ff:fe28:188",
"local": true,
"mask": 128,
"prefsrc": "fe80::42:67ff:fe28:188",
"priority": 192,
"user": false},
{
"dev": "eth0",
"dst": "0.0.0.0",
"gw": "192.168.121.1",
"local": false,
"mask": 96,
"prefsrc": "192.168.121.203",
"priority": 96,
"user": false}]
Signed-off-by: Dima Chumak <[email protected]>
Reviewed-by: Roi Dayan <[email protected]>
---
Notes:
v3
- Update ovs-router.at test.
- Update example output in the commit msg.
v2
- Don't prefix boolean with "is_". Use key "local" instead of "is_local".
- Add "user" key.
- Use ds_clear() in the loop and ds_destroy() outside the loop to avoid
repeated malloc/free.
- Align json keys to ip route command output.
lib/ovs-router.c | 113 +++++++++++++++++++++++++++++++++++---------
tests/ovs-router.at | 41 +++++++++++++++-
2 files changed, 131 insertions(+), 23 deletions(-)
diff --git a/lib/ovs-router.c b/lib/ovs-router.c
index d955a3a543b8..11827bf3c72b 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"
@@ -429,7 +430,7 @@ ovs_router_add(struct unixctl_conn *conn, int argc,
is_ipv6 = true;
} else {
unixctl_command_reply_error(conn,
- "Invalid 'ip/plen' parameter");
+ "Invalid 'ip/mask' parameter");
return;
}
@@ -509,44 +510,112 @@ 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;
+ struct ds ds;
+ 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) {
+ bool user = rt->priority != rt->plen && !rt->local;
+ struct json *json = json_object_create();
+
+ json_object_put(json, "user", json_boolean_create(user));
+ json_object_put(json, "local", json_boolean_create(rt->local));
+ json_object_put(json, "priority", json_integer_create(rt->priority));
+ json_object_put(json, "mask", json_integer_create(rt->plen));
+ json_object_put_string(json, "dev", rt->output_netdev);
+
+ ds_init(&ds);
+ ipv6_format_mapped(&rt->nw_addr, &ds);
+ json_object_put_string(json, "dst", ds_cstr_ro(&ds));
+ ds_clear(&ds);
+
+ ds_init(&ds);
+ ipv6_format_mapped(&rt->src_addr, &ds);
+ json_object_put_string(json, "prefsrc", ds_cstr_ro(&ds));
+ ds_clear(&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_clear(&ds);
+ }
+
+ json_entries[i++] = json;
+ }
+
+ ds_destroy(&ds);
+
+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
@@ -619,12 +688,12 @@ ovs_router_init(void)
fatal_signal_add_hook(ovs_router_flush_handler, NULL, NULL, true);
classifier_init(&cls, NULL);
unixctl_command_register("ovs/route/add",
- "ip/plen output_netdev [gw] "
+ "ip/mask dev [gw] "
"[pkt_mark=mark] [src=src_ip]",
2, 5, ovs_router_add, NULL);
unixctl_command_register("ovs/route/show", "", 0, 0,
ovs_router_show, NULL);
- unixctl_command_register("ovs/route/del", "ip/plen "
+ unixctl_command_register("ovs/route/del", "ip/mask "
"[pkt_mark=mark]", 1, 2, ovs_router_del,
NULL);
unixctl_command_register("ovs/route/lookup", "ip_addr "
diff --git a/tests/ovs-router.at b/tests/ovs-router.at
index b3314b3dff0d..6f2378666e7e 100644
--- a/tests/ovs-router.at
+++ b/tests/ovs-router.at
@@ -16,7 +16,7 @@ Error while inserting route.
ovs-appctl: ovs-vswitchd: server returned an error
])
AT_CHECK([ovs-appctl ovs/route/add 1.1.foo.bar/24 br0 2.2.2.10], [2], [], [dnl
-Invalid 'ip/plen' parameter
+Invalid 'ip/mask' parameter
ovs-appctl: ovs-vswitchd: server returned an error
])
AT_CHECK([ovs-appctl ovs/route/add 2.2.2.4/24 br0 pkt_mark=baz], [2], [], [dnl
@@ -28,6 +28,45 @@ 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
+[[
+ {
+ "dev": "br0",
+ "dst": "2.2.2.0",
+ "local": true,
+ "mask": 120,
+ "prefsrc": "2.2.2.2",
+ "priority": 184,
+ "user": false},
+ {
+ "dev": "br0",
+ "dst": "1.1.1.0",
+ "gw": "2.2.2.10",
+ "local": false,
+ "mask": 120,
+ "prefsrc": "2.2.2.2",
+ "priority": 152,
+ "user": true},
+ {
+ "dev": "br0",
+ "dst": "1.1.2.0",
+ "gw": "2.2.2.10",
+ "local": false,
+ "mark": 2,
+ "mask": 120,
+ "prefsrc": "2.2.2.2",
+ "priority": 152,
+ "user": true},
+ {
+ "dev": "br0",
+ "dst": "2.2.2.3",
+ "local": false,
+ "mark": 1,
+ "mask": 128,
+ "prefsrc": "2.2.2.2",
+ "priority": 160,
+ "user": true}]]
+])
OVS_VSWITCHD_STOP
AT_CLEANUP
--
2.21.0
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev