mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 09:58:01 +00:00
ovs-router: Add JSON output for 'ovs/route/show' command.
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. An example json output would be: ovs-appctl --format json --pretty ovs/route/show [ { "dst": "::1", "local": false, "nexthops": [ { "dev": "lo"}], "prefix": 128, "prefsrc": "::1", "priority": 128, "user": false}, { "dst": "10.237.157.103", "local": true, "nexthops": [ { "dev": "eth1"}], "prefix": 32, "prefsrc": "10.237.157.103", "priority": 192, "user": false}, { "dst": "fe80::42:67ff:fe28:188", "local": true, "nexthops": [ { "dev": "docker0"}], "prefix": 128, "prefsrc": "fe80::42:67ff:fe28:188", "priority": 192, "user": false}, { "dst": "0.0.0.0", "local": false, "nexthops": [ { "dev": "eth0", "gateway": "192.168.121.1"}], "prefix": 0, "prefsrc": "192.168.121.203", "priority": 96, "user": false}] Reviewed-by: Roi Dayan <roid@nvidia.com> Signed-off-by: Dima Chumak <dchumak@nvidia.com> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
This commit is contained in:
parent
6fc5221742
commit
d000ff1cd5
2
NEWS
2
NEWS
@ -9,6 +9,8 @@ Post-v3.5.0
|
|||||||
- ovs-ctl:
|
- ovs-ctl:
|
||||||
* Added a new option, --oom-score=<score>, to set the daemons' Linux
|
* Added a new option, --oom-score=<score>, to set the daemons' Linux
|
||||||
Out-Of-Memory (OOM) killer score.
|
Out-Of-Memory (OOM) killer score.
|
||||||
|
- ovs-appctl:
|
||||||
|
* Added JSON output support to the 'ovs/route/show' command.
|
||||||
- SSL/TLS:
|
- SSL/TLS:
|
||||||
* Support for deprecated TLSv1 and TLSv1.1 protocols on OpenFlow and
|
* Support for deprecated TLSv1 and TLSv1.1 protocols on OpenFlow and
|
||||||
database connections is now removed.
|
database connections is now removed.
|
||||||
|
119
lib/ovs-router.c
119
lib/ovs-router.c
@ -36,6 +36,7 @@
|
|||||||
#include "dpif.h"
|
#include "dpif.h"
|
||||||
#include "fatal-signal.h"
|
#include "fatal-signal.h"
|
||||||
#include "openvswitch/dynamic-string.h"
|
#include "openvswitch/dynamic-string.h"
|
||||||
|
#include "openvswitch/json.h"
|
||||||
#include "netdev.h"
|
#include "netdev.h"
|
||||||
#include "packets.h"
|
#include "packets.h"
|
||||||
#include "seq.h"
|
#include "seq.h"
|
||||||
@ -509,44 +510,122 @@ ovs_router_del(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ovs_router_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
ovs_router_show_json(struct json **routes)
|
||||||
const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
|
{
|
||||||
|
int n_rules = classifier_count(&cls);
|
||||||
|
struct json **json_entries = NULL;
|
||||||
|
struct ovs_router_entry *rt;
|
||||||
|
struct ds ds;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (!n_rules) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_entries = xmalloc(n_rules * sizeof *json_entries);
|
||||||
|
ds_init(&ds);
|
||||||
|
|
||||||
|
CLS_FOR_EACH (rt, cr, &cls) {
|
||||||
|
bool user = rt->priority != rt->plen && !rt->local;
|
||||||
|
struct json *json = json_object_create();
|
||||||
|
struct json *nh = json_object_create();
|
||||||
|
uint8_t plen = rt->plen;
|
||||||
|
|
||||||
|
if (i >= n_rules) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(&rt->nw_addr)) {
|
||||||
|
plen -= 96;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, "prefix", json_integer_create(plen));
|
||||||
|
json_object_put_string(nh, "dev", rt->output_netdev);
|
||||||
|
|
||||||
|
ipv6_format_mapped(&rt->nw_addr, &ds);
|
||||||
|
json_object_put_string(json, "dst", ds_cstr_ro(&ds));
|
||||||
|
ds_clear(&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)) {
|
||||||
|
ipv6_format_mapped(&rt->gw, &ds);
|
||||||
|
json_object_put_string(nh, "gateway", ds_cstr_ro(&ds));
|
||||||
|
ds_clear(&ds);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_put(json, "nexthops", json_array_create_1(nh));
|
||||||
|
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;
|
struct ovs_router_entry *rt;
|
||||||
struct ds ds = DS_EMPTY_INITIALIZER;
|
|
||||||
|
|
||||||
ds_put_format(&ds, "Route Table:\n");
|
ds_put_format(ds, "Route Table:\n");
|
||||||
CLS_FOR_EACH(rt, cr, &cls) {
|
CLS_FOR_EACH (rt, cr, &cls) {
|
||||||
uint8_t plen;
|
uint8_t plen;
|
||||||
if (rt->priority == rt->plen || rt->local) {
|
if (rt->priority == rt->plen || rt->local) {
|
||||||
ds_put_format(&ds, "Cached: ");
|
ds_put_format(ds, "Cached: ");
|
||||||
} else {
|
} 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;
|
plen = rt->plen;
|
||||||
if (IN6_IS_ADDR_V4MAPPED(&rt->nw_addr)) {
|
if (IN6_IS_ADDR_V4MAPPED(&rt->nw_addr)) {
|
||||||
plen -= 96;
|
plen -= 96;
|
||||||
}
|
}
|
||||||
ds_put_format(&ds, "/%"PRIu8, plen);
|
ds_put_format(ds, "/%"PRIu8, plen);
|
||||||
if (rt->mark) {
|
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)) {
|
if (ipv6_addr_is_set(&rt->gw)) {
|
||||||
ds_put_format(&ds, " GW ");
|
ds_put_format(ds, " GW ");
|
||||||
ipv6_format_mapped(&rt->gw, &ds);
|
ipv6_format_mapped(&rt->gw, ds);
|
||||||
}
|
}
|
||||||
ds_put_format(&ds, " SRC ");
|
ds_put_format(ds, " SRC ");
|
||||||
ipv6_format_mapped(&rt->src_addr, &ds);
|
ipv6_format_mapped(&rt->src_addr, ds);
|
||||||
if (rt->local) {
|
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
|
static void
|
||||||
@ -619,7 +698,7 @@ ovs_router_init(void)
|
|||||||
fatal_signal_add_hook(ovs_router_flush_handler, NULL, NULL, true);
|
fatal_signal_add_hook(ovs_router_flush_handler, NULL, NULL, true);
|
||||||
classifier_init(&cls, NULL);
|
classifier_init(&cls, NULL);
|
||||||
unixctl_command_register("ovs/route/add",
|
unixctl_command_register("ovs/route/add",
|
||||||
"ip/plen output_netdev [gw] "
|
"ip/plen dev [gw] "
|
||||||
"[pkt_mark=mark] [src=src_ip]",
|
"[pkt_mark=mark] [src=src_ip]",
|
||||||
2, 5, ovs_router_add, NULL);
|
2, 5, ovs_router_add, NULL);
|
||||||
unixctl_command_register("ovs/route/show", "", 0, 0,
|
unixctl_command_register("ovs/route/show", "", 0, 0,
|
||||||
|
@ -28,6 +28,53 @@ 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: 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
|
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
|
||||||
|
[[
|
||||||
|
{
|
||||||
|
"dst": "2.2.2.0",
|
||||||
|
"local": true,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"dev": "br0"}],
|
||||||
|
"prefix": 24,
|
||||||
|
"prefsrc": "2.2.2.2",
|
||||||
|
"priority": 184,
|
||||||
|
"user": false},
|
||||||
|
{
|
||||||
|
"dst": "1.1.1.0",
|
||||||
|
"local": false,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"dev": "br0",
|
||||||
|
"gateway": "2.2.2.10"}],
|
||||||
|
"prefix": 24,
|
||||||
|
"prefsrc": "2.2.2.2",
|
||||||
|
"priority": 152,
|
||||||
|
"user": true},
|
||||||
|
{
|
||||||
|
"dst": "1.1.2.0",
|
||||||
|
"local": false,
|
||||||
|
"mark": 2,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"dev": "br0",
|
||||||
|
"gateway": "2.2.2.10"}],
|
||||||
|
"prefix": 24,
|
||||||
|
"prefsrc": "2.2.2.2",
|
||||||
|
"priority": 152,
|
||||||
|
"user": true},
|
||||||
|
{
|
||||||
|
"dst": "2.2.2.3",
|
||||||
|
"local": false,
|
||||||
|
"mark": 1,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"dev": "br0"}],
|
||||||
|
"prefix": 32,
|
||||||
|
"prefsrc": "2.2.2.2",
|
||||||
|
"priority": 160,
|
||||||
|
"user": true}]]
|
||||||
|
])
|
||||||
OVS_VSWITCHD_STOP
|
OVS_VSWITCHD_STOP
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user