@@ -229,6 +229,7 @@ done
AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr1], [0], [dnl
IPv4 Routes
+Route Table global:
10.11.1.0/24 169.254.0.1 dst-ip
10.11.2.0/24 169.254.100.2 dst-ip (learned)
10.22.1.0/24 169.254.0.2 src-ip
@@ -247,6 +248,7 @@ ovn_as az1 ovn-nbctl set nb_global . options:ic-route-learn=false
OVS_WAIT_WHILE([ovn_as az1 ovn-nbctl lr-route-list lr1 | grep learned])
AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr1], [0], [dnl
IPv4 Routes
+Route Table global:
10.11.1.0/24 169.254.0.1 dst-ip
10.22.1.0/24 169.254.0.2 src-ip
])
@@ -262,6 +264,7 @@ ovn_as az1 ovn-nbctl set nb_global . options:ic-route-adv=false
OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned])
AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
IPv4 Routes
+Route Table global:
10.11.2.0/24 169.254.0.1 dst-ip
10.22.2.0/24 169.254.0.2 src-ip
])
@@ -280,6 +283,7 @@ done
# Default route should NOT get advertised or learned, by default.
AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
IPv4 Routes
+Route Table global:
10.11.1.0/24 169.254.100.1 dst-ip (learned)
10.11.2.0/24 169.254.0.1 dst-ip
10.22.2.0/24 169.254.0.2 src-ip
@@ -1515,6 +1515,7 @@ AT_CHECK([ovn-nbctl --ecmp --policy=src-ip lr-route-add lr0 20.0.0.0/24 11.0.0.1
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
10.0.0.0/24 11.0.0.1 dst-ip
10.0.1.0/24 11.0.1.1 dst-ip lp0
20.0.0.0/24 discard dst-ip
@@ -1527,6 +1528,7 @@ IPv4 Routes
AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24 11.0.0.1 lp1])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
10.0.0.0/24 11.0.0.1 dst-ip lp1
10.0.1.0/24 11.0.1.1 dst-ip lp0
20.0.0.0/24 discard dst-ip
@@ -1556,6 +1558,7 @@ AT_CHECK([ovn-nbctl --policy=src-ip lr-route-del lr0 9.16.1.0/24])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
10.0.0.0/24 11.0.0.1 dst-ip lp1
10.0.0.0/24 11.0.0.2 src-ip
0.0.0.0/0 192.168.0.1 dst-ip
@@ -1566,6 +1569,7 @@ AT_CHECK([ovn-nbctl --policy=dst-ip lr-route-del lr0 10.0.0.0/24])
AT_CHECK([ovn-nbctl --policy=src-ip lr-route-del lr0 10.0.0.0/24])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
0.0.0.0/0 192.168.0.1 dst-ip
])
@@ -1575,6 +1579,7 @@ AT_CHECK([ovn-nbctl --policy=src-ip lr-route-add lr0 10.0.0.0/24 11.0.0.2])
AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.0.0/24])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
0.0.0.0/0 192.168.0.1 dst-ip
])
@@ -1590,6 +1595,7 @@ AT_CHECK([ovn-nbctl --ecmp lr-route-add lr0 10.0.0.0/24 11.0.0.3])
AT_CHECK([ovn-nbctl --ecmp lr-route-add lr0 10.0.0.0/24 11.0.0.4 lp0])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
10.0.0.0/24 11.0.0.1 dst-ip ecmp
10.0.0.0/24 11.0.0.2 dst-ip ecmp
10.0.0.0/24 11.0.0.3 dst-ip ecmp
@@ -1604,6 +1610,7 @@ dnl Delete ecmp routes
AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.0.0/24 11.0.0.1])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
10.0.0.0/24 11.0.0.2 dst-ip ecmp
10.0.0.0/24 11.0.0.3 dst-ip ecmp
10.0.0.0/24 11.0.0.4 dst-ip lp0 ecmp
@@ -1611,12 +1618,14 @@ IPv4 Routes
AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.0.0/24 11.0.0.2])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
10.0.0.0/24 11.0.0.3 dst-ip ecmp
10.0.0.0/24 11.0.0.4 dst-ip lp0 ecmp
])
AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.0.0/24 11.0.0.4 lp0])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
10.0.0.0/24 11.0.0.3 dst-ip
])
AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.0.0/24 11.0.0.3])
@@ -1630,6 +1639,7 @@ AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv6 Routes
+Route Table global:
2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0
2001:db8:1::/64 2001:db8:0:f103::1 dst-ip
::/0 2001:db8:0:f101::1 dst-ip
@@ -1639,6 +1649,7 @@ AT_CHECK([ovn-nbctl lr-route-del lr0 2001:0db8:0::/64])
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv6 Routes
+Route Table global:
2001:db8:1::/64 2001:db8:0:f103::1 dst-ip
::/0 2001:db8:0:f101::1 dst-ip
])
@@ -1666,11 +1677,13 @@ AT_CHECK([ovn-nbctl --may-exist --ecmp-symmetric-reply lr-route-add lr0 2003:0db
AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
IPv4 Routes
+Route Table global:
10.0.0.0/24 11.0.0.1 dst-ip
10.0.1.0/24 11.0.1.1 dst-ip lp0
0.0.0.0/0 192.168.0.1 dst-ip
IPv6 Routes
+Route Table global:
2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0
2001:db8:1::/64 2001:db8:0:f103::1 dst-ip ecmp
2001:db8:1::/64 2001:db8:0:f103::2 dst-ip ecmp
@@ -1685,7 +1698,157 @@ AT_CHECK([ovn-nbctl lrp-add lr0 lr0-p0 00:00:01:01:02:03 192.168.10.1/24])
bfd_uuid=$(ovn-nbctl create bfd logical_port=lr0-p0 dst_ip=100.0.0.50 status=down min_tx=250 min_rx=250 detect_mult=10)
AT_CHECK([ovn-nbctl lr-route-add lr0 100.0.0.0/24 192.168.0.1])
route_uuid=$(fetch_column nb:logical_router_static_route _uuid ip_prefix="100.0.0.0/24")
-AT_CHECK([ovn-nbctl set logical_router_static_route $route_uuid bfd=$bfd_uuid])])
+AT_CHECK([ovn-nbctl set logical_router_static_route $route_uuid bfd=$bfd_uuid])
+
+check ovn-nbctl lr-route-del lr0
+AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
+])
+
+dnl Check IPv4 routes in route table
+check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 0.0.0.0/0 192.168.0.1
+check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 10.0.1.1/24 11.0.1.1 lp0
+check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 10.0.0.1/24 11.0.0.1
+AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
+IPv4 Routes
+Route Table rtb-1:
+ 10.0.0.0/24 11.0.0.1 dst-ip
+ 10.0.1.0/24 11.0.1.1 dst-ip lp0
+ 0.0.0.0/0 192.168.0.1 dst-ip
+])
+
+check ovn-nbctl lr-route-del lr0
+AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
+])
+
+dnl Check IPv6 routes in route table
+check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 0:0:0:0:0:0:0:0/0 2001:0db8:0:f101::1
+check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 2001:0db8:0::/64 2001:0db8:0:f102::1 lp0
+check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1
+
+AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
+IPv6 Routes
+Route Table rtb-1:
+ 2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0
+ 2001:db8:1::/64 2001:db8:0:f103::1 dst-ip
+ ::/0 2001:db8:0:f101::1 dst-ip
+])
+
+dnl Check IPv4 and IPv6 routes in route table
+check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 0.0.0.0/0 192.168.0.1
+check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 10.0.1.1/24 11.0.1.1 lp0
+check ovn-nbctl --route-table=rtb-1 lr-route-add lr0 10.0.0.1/24 11.0.0.1
+
+AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
+IPv4 Routes
+Route Table rtb-1:
+ 10.0.0.0/24 11.0.0.1 dst-ip
+ 10.0.1.0/24 11.0.1.1 dst-ip lp0
+ 0.0.0.0/0 192.168.0.1 dst-ip
+
+IPv6 Routes
+Route Table rtb-1:
+ 2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0
+ 2001:db8:1::/64 2001:db8:0:f103::1 dst-ip
+ ::/0 2001:db8:0:f101::1 dst-ip
+])
+
+# Add routes in another route table
+check ovn-nbctl --route-table=rtb-2 lr-route-add lr0 0.0.0.0/0 192.168.0.1
+check ovn-nbctl --route-table=rtb-2 lr-route-add lr0 10.0.1.1/24 11.0.1.1 lp0
+check ovn-nbctl --route-table=rtb-2 lr-route-add lr0 10.0.0.1/24 11.0.0.1
+check ovn-nbctl --route-table=rtb-2 lr-route-add lr0 0:0:0:0:0:0:0:0/0 2001:0db8:0:f101::1
+check ovn-nbctl --route-table=rtb-2 lr-route-add lr0 2001:0db8:0::/64 2001:0db8:0:f102::1 lp0
+check ovn-nbctl --route-table=rtb-2 lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1
+
+AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
+IPv4 Routes
+Route Table rtb-1:
+ 10.0.0.0/24 11.0.0.1 dst-ip
+ 10.0.1.0/24 11.0.1.1 dst-ip lp0
+ 0.0.0.0/0 192.168.0.1 dst-ip
+
+Route Table rtb-2:
+ 10.0.0.0/24 11.0.0.1 dst-ip
+ 10.0.1.0/24 11.0.1.1 dst-ip lp0
+ 0.0.0.0/0 192.168.0.1 dst-ip
+
+IPv6 Routes
+Route Table rtb-1:
+ 2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0
+ 2001:db8:1::/64 2001:db8:0:f103::1 dst-ip
+ ::/0 2001:db8:0:f101::1 dst-ip
+
+Route Table rtb-2:
+ 2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0
+ 2001:db8:1::/64 2001:db8:0:f103::1 dst-ip
+ ::/0 2001:db8:0:f101::1 dst-ip
+])
+
+# Add routes to global route table
+check ovn-nbctl lr-route-add lr0 0.0.0.0/0 192.168.0.1
+check ovn-nbctl lr-route-add lr0 10.0.1.1/24 11.0.1.1 lp0
+check ovn-nbctl lr-route-add lr0 10.0.0.1/24 11.0.0.1
+check ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0 2001:0db8:0:f101::1
+check ovn-nbctl lr-route-add lr0 2001:0db8:0::/64 2001:0db8:0:f102::1 lp0
+check check ovn-nbctl lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1
+
+AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
+IPv4 Routes
+Route Table global:
+ 10.0.0.0/24 11.0.0.1 dst-ip
+ 10.0.1.0/24 11.0.1.1 dst-ip lp0
+ 0.0.0.0/0 192.168.0.1 dst-ip
+
+Route Table rtb-1:
+ 10.0.0.0/24 11.0.0.1 dst-ip
+ 10.0.1.0/24 11.0.1.1 dst-ip lp0
+ 0.0.0.0/0 192.168.0.1 dst-ip
+
+Route Table rtb-2:
+ 10.0.0.0/24 11.0.0.1 dst-ip
+ 10.0.1.0/24 11.0.1.1 dst-ip lp0
+ 0.0.0.0/0 192.168.0.1 dst-ip
+
+IPv6 Routes
+Route Table global:
+ 2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0
+ 2001:db8:1::/64 2001:db8:0:f103::1 dst-ip
+ ::/0 2001:db8:0:f101::1 dst-ip
+
+Route Table rtb-1:
+ 2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0
+ 2001:db8:1::/64 2001:db8:0:f103::1 dst-ip
+ ::/0 2001:db8:0:f101::1 dst-ip
+
+Route Table rtb-2:
+ 2001:db8::/64 2001:db8:0:f102::1 dst-ip lp0
+ 2001:db8:1::/64 2001:db8:0:f103::1 dst-ip
+ ::/0 2001:db8:0:f101::1 dst-ip
+])
+check ovn-nbctl lr-route-del lr0
+
+# ECMP route in route table
+check ovn-nbctl --route-table=rtb1 lr-route-add lr0 0.0.0.0/0 192.168.0.1
+check ovn-nbctl --ecmp --route-table=rtb1 lr-route-add lr0 0.0.0.0/0 192.168.0.2
+
+# Negative route table case: same prefix
+AT_CHECK([ovn-nbctl --route-table=rtb1 lr-route-add lr0 0.0.0.0/0 192.168.0.1], [1], [], [dnl
+ovn-nbctl: duplicate prefix: 0.0.0.0/0 (policy: dst-ip). Use option --ecmp to allow this for ECMP routing.
+])
+
+# Negative route table case: same prefix & nexthop with ecmp
+AT_CHECK([ovn-nbctl --ecmp --route-table=rtb1 lr-route-add lr0 0.0.0.0/0 192.168.0.2], [1], [], [dnl
+ovn-nbctl: duplicate nexthop for the same ECMP route
+])
+
+# Add routes to global route table
+check ovn-nbctl lrp-add lr0 lrp0 00:00:00:00:00:01 1.1.1.1/24
+check ovn-nbctl lrp-set-options lrp0 route_table=rtb1
+AT_CHECK([ovn-nbctl get logical-router-port lrp0 options:route_table], [0], [dnl
+rtb1
+])
+check `ovn-nbctl show lr0 | grep lrp0 -A3 | grep route_table=rtb1`
+])
dnl ---------------------------------------------------------------------
@@ -329,6 +329,8 @@ Logical router port commands:\n\
add logical port PORT on ROUTER\n\
lrp-set-gateway-chassis PORT CHASSIS [PRIORITY]\n\
set gateway chassis for port PORT\n\
+ lrp-set-options PORT KEY=VALUE [KEY=VALUE]...\n\
+ set router port options\n\
lrp-del-gateway-chassis PORT CHASSIS\n\
delete gateway chassis from port PORT\n\
lrp-get-gateway-chassis PORT\n\
@@ -351,10 +353,15 @@ Logical router port commands:\n\
('overlay' or 'bridged')\n\
\n\
Route commands:\n\
- [--policy=POLICY] [--ecmp] [--ecmp-symmetric-reply] lr-route-add ROUTER \n\
- PREFIX NEXTHOP [PORT]\n\
+ [--policy=POLICY]\n\
+ [--ecmp]\n\
+ [--ecmp-symmetric-reply]\n\
+ [--route-table=ROUTE_TABLE]\n\
+ lr-route-add ROUTER PREFIX NEXTHOP [PORT]\n\
add a route to ROUTER\n\
- [--policy=POLICY] lr-route-del ROUTER [PREFIX [NEXTHOP [PORT]]]\n\
+ [--policy=POLICY]\n\
+ [--route-table=ROUTE_TABLE]\n\
+ lr-route-del ROUTER [PREFIX [NEXTHOP [PORT]]]\n\
remove routes from ROUTER\n\
lr-route-list ROUTER print routes for ROUTER\n\
\n\
@@ -743,6 +750,11 @@ print_lr(const struct nbrec_logical_router *lr, struct ds *s)
ds_put_cstr(s, "]\n");
}
+ const char *route_table = smap_get(&lrp->options, "route_table");
+ if (route_table) {
+ ds_put_format(s, " route-table: %s\n", route_table);
+ }
+
if (lrp->n_gateway_chassis) {
const struct nbrec_gateway_chassis **gcs;
@@ -860,6 +872,7 @@ nbctl_pre_show(struct ctl_context *ctx)
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name);
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_mac);
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_networks);
+ ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_options);
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_gateway_chassis);
ovsdb_idl_add_column(ctx->idl, &nbrec_gateway_chassis_col_chassis_name);
@@ -3998,11 +4011,19 @@ nbctl_lr_policy_list(struct ctl_context *ctx)
static struct nbrec_logical_router_static_route *
nbctl_lr_get_route(const struct nbrec_logical_router *lr, char *prefix,
- char *next_hop, bool is_src_route, bool ecmp)
+ char *next_hop, bool is_src_route, bool ecmp,
+ char *route_table)
{
for (int i = 0; i < lr->n_static_routes; i++) {
struct nbrec_logical_router_static_route *route = lr->static_routes[i];
+ /* Strict compare for route_table.
+ * If route_table was not specified,
+ * lookup for routes with empty route_table value. */
+ if (strcmp(route->route_table, route_table ? route_table : "")) {
+ continue;
+ }
+
/* Compare route policy. */
char *nb_policy = route->policy;
bool nb_is_src_route = false;
@@ -4056,6 +4077,8 @@ nbctl_pre_lr_route_add(struct ctl_context *ctx)
&nbrec_logical_router_static_route_col_bfd);
ovsdb_idl_add_column(ctx->idl,
&nbrec_logical_router_static_route_col_options);
+ ovsdb_idl_add_column(ctx->idl,
+ &nbrec_logical_router_static_route_col_route_table);
}
static void
@@ -4081,6 +4104,7 @@ nbctl_lr_route_add(struct ctl_context *ctx)
}
}
+ char *route_table = shash_find_data(&ctx->options, "--route-table");
bool v6_prefix = false;
prefix = normalize_ipv4_prefix_str(ctx->argv[2]);
if (!prefix) {
@@ -4135,7 +4159,8 @@ nbctl_lr_route_add(struct ctl_context *ctx)
bool ecmp = shash_find(&ctx->options, "--ecmp") != NULL ||
ecmp_symmetric_reply;
struct nbrec_logical_router_static_route *route =
- nbctl_lr_get_route(lr, prefix, next_hop, is_src_route, ecmp);
+ nbctl_lr_get_route(lr, prefix, next_hop, is_src_route, ecmp,
+ route_table);
/* Validations for nexthop = "discard" */
if (is_discard_route) {
@@ -4199,7 +4224,8 @@ nbctl_lr_route_add(struct ctl_context *ctx)
}
struct nbrec_logical_router_static_route *discard_route =
- nbctl_lr_get_route(lr, prefix, "discard", is_src_route, true);
+ nbctl_lr_get_route(lr, prefix, "discard", is_src_route, true,
+ route_table);
if (discard_route) {
ctl_error(ctx, "discard nexthop for the same ECMP route exists.");
goto cleanup;
@@ -4214,6 +4240,9 @@ nbctl_lr_route_add(struct ctl_context *ctx)
if (policy) {
nbrec_logical_router_static_route_set_policy(route, policy);
}
+ if (route_table) {
+ nbrec_logical_router_static_route_set_route_table(route, route_table);
+ }
if (ecmp_symmetric_reply) {
const struct smap options = SMAP_CONST1(&options,
@@ -4268,6 +4297,7 @@ nbctl_lr_route_del(struct ctl_context *ctx)
return;
}
+ const char *route_table = shash_find_data(&ctx->options, "--route-table");
const char *policy = shash_find_data(&ctx->options, "--policy");
bool is_src_route = false;
if (policy) {
@@ -4358,6 +4388,14 @@ nbctl_lr_route_del(struct ctl_context *ctx)
}
}
+ /* Strict compare for route_table.
+ * If route_table was not specified,
+ * lookup for routes with empty route_table value. */
+ if (strcmp(lr->static_routes[i]->route_table,
+ route_table ? route_table : "")) {
+ continue;
+ }
+
/* Compare output_port, if specified. */
if (output_port) {
char *rt_output_port = lr->static_routes[i]->output_port;
@@ -5081,6 +5119,41 @@ nbctl_pre_lrp_del_gateway_chassis(struct ctl_context *ctx)
ovsdb_idl_add_column(ctx->idl, &nbrec_gateway_chassis_col_chassis_name);
}
+static void
+nbctl_pre_lrp_options(struct ctl_context *ctx)
+{
+ ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_name);
+ ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_port_col_options);
+}
+
+static void
+nbctl_lrp_set_options(struct ctl_context *ctx)
+{
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_router_port *lrp = NULL;
+ size_t i;
+ struct smap options = SMAP_INITIALIZER(&options);
+
+ char *error = lrp_by_name_or_uuid(ctx, id, true, &lrp);
+ if (error) {
+ ctx->error = error;
+ return;
+ }
+ for (i = 2; i < ctx->argc; i++) {
+ char *key, *value;
+ value = xstrdup(ctx->argv[i]);
+ key = strsep(&value, "=");
+ if (value) {
+ smap_add(&options, key, value);
+ }
+ free(key);
+ }
+
+ nbrec_logical_router_port_set_options(lrp, &options);
+
+ smap_destroy(&options);
+}
+
/* Removes logical router port 'lrp->gateway_chassis[idx]'. */
static void
remove_gc(const struct nbrec_logical_router_port *lrp, size_t idx)
@@ -5857,6 +5930,7 @@ route_cmp_details(const struct nbrec_logical_router_static_route *r1,
}
return r1->output_port ? 1 : -1;
}
+
struct ipv4_route {
int priority;
ovs_be32 addr;
@@ -5866,6 +5940,11 @@ struct ipv4_route {
static int
__ipv4_route_cmp(const struct ipv4_route *r1, const struct ipv4_route *r2)
{
+ int rtb_cmp = strcmp(r1->route->route_table,
+ r2->route->route_table);
+ if (rtb_cmp) {
+ return rtb_cmp;
+ }
if (r1->priority != r2->priority) {
return r1->priority > r2->priority ? -1 : 1;
}
@@ -5897,6 +5976,11 @@ struct ipv6_route {
static int
__ipv6_route_cmp(const struct ipv6_route *r1, const struct ipv6_route *r2)
{
+ int rtb_cmp = strcmp(r1->route->route_table,
+ r2->route->route_table);
+ if (rtb_cmp) {
+ return rtb_cmp;
+ }
if (r1->priority != r2->priority) {
return r1->priority > r2->priority ? -1 : 1;
}
@@ -5978,6 +6062,8 @@ nbctl_pre_lr_route_list(struct ctl_context *ctx)
&nbrec_logical_router_static_route_col_options);
ovsdb_idl_add_column(ctx->idl,
&nbrec_logical_router_static_route_col_bfd);
+ ovsdb_idl_add_column(ctx->idl,
+ &nbrec_logical_router_static_route_col_route_table);
}
static void
@@ -6041,6 +6127,7 @@ nbctl_lr_route_list(struct ctl_context *ctx)
if (n_ipv4_routes) {
ds_put_cstr(&ctx->output, "IPv4 Routes\n");
}
+ const struct nbrec_logical_router_static_route *route;
for (int i = 0; i < n_ipv4_routes; i++) {
bool ecmp = false;
if (i < n_ipv4_routes - 1 &&
@@ -6051,6 +6138,15 @@ nbctl_lr_route_list(struct ctl_context *ctx)
&ipv4_routes[i - 1])) {
ecmp = true;
}
+
+ route = ipv4_routes[i].route;
+ if (!i || (i > 0 && strcmp(route->route_table,
+ ipv4_routes[i - 1].route->route_table))) {
+ ds_put_format(&ctx->output, "%sRoute Table %s:\n", i ? "\n" : "",
+ strlen(route->route_table) ? route->route_table
+ : "global");
+ }
+
print_route(ipv4_routes[i].route, &ctx->output, ecmp);
}
@@ -6068,6 +6164,15 @@ nbctl_lr_route_list(struct ctl_context *ctx)
&ipv6_routes[i - 1])) {
ecmp = true;
}
+
+ route = ipv6_routes[i].route;
+ if (!i || (i > 0 && strcmp(route->route_table,
+ ipv6_routes[i - 1].route->route_table))) {
+ ds_put_format(&ctx->output, "%sRoute Table %s:\n", i ? "\n" : "",
+ strlen(route->route_table) ? route->route_table
+ : "global");
+ }
+
print_route(ipv6_routes[i].route, &ctx->output, ecmp);
}
@@ -6886,6 +6991,8 @@ static const struct ctl_command_syntax nbctl_commands[] = {
"PORT CHASSIS [PRIORITY]",
nbctl_pre_lrp_set_gateway_chassis, nbctl_lrp_set_gateway_chassis,
NULL, "--may-exist", RW },
+ { "lrp-set-options", 1, INT_MAX, "PORT KEY=VALUE [KEY=VALUE]...",
+ nbctl_pre_lrp_options, nbctl_lrp_set_options, NULL, "", RW },
{ "lrp-del-gateway-chassis", 2, 2, "PORT CHASSIS",
nbctl_pre_lrp_del_gateway_chassis, nbctl_lrp_del_gateway_chassis,
NULL, "", RW },
@@ -6909,10 +7016,11 @@ static const struct ctl_command_syntax nbctl_commands[] = {
/* logical router route commands. */
{ "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]",
nbctl_pre_lr_route_add, nbctl_lr_route_add, NULL,
- "--may-exist,--ecmp,--ecmp-symmetric-reply,--policy=,--bfd?", RW },
+ "--may-exist,--ecmp,--ecmp-symmetric-reply,--policy=,--route-table=,--bfd?",
+ RW },
{ "lr-route-del", 1, 4, "ROUTER [PREFIX [NEXTHOP [PORT]]]",
nbctl_pre_lr_route_del, nbctl_lr_route_del, NULL,
- "--if-exists,--policy=", RW },
+ "--if-exists,--policy=,--route-table=", RW },
{ "lr-route-list", 1, 1, "ROUTER", nbctl_pre_lr_route_list,
nbctl_lr_route_list, NULL, "", RO },
Signed-off-by: Vladislav Odintsov <odivlad@gmail.com> --- tests/ovn-ic.at | 4 + tests/ovn-nbctl.at | 165 +++++++++++++++++++++++++++++++++++++++++- utilities/ovn-nbctl.c | 124 +++++++++++++++++++++++++++++-- 3 files changed, 284 insertions(+), 9 deletions(-)