2
0
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:
Dima Chumak 2025-05-05 11:46:53 +03:00 committed by Eelco Chaudron
parent 6fc5221742
commit d000ff1cd5
3 changed files with 148 additions and 20 deletions

2
NEWS
View File

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

View File

@ -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,

View File

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