From patchwork Fri Feb 2 13:49:35 2024
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Lorenzo Bianconi
+ Reference to row if the route policy has associated + some BFD sessions. +
+Marks the packet with the value specified when the router policy diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 7f37d7716..b15b5cfd3 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -2189,6 +2189,12 @@ AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.2.0/24" allow pkt_mark AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.1.0/24" allow]) AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24" drop]) AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip6.src == 2002::/64" drop]) +AT_CHECK([ovn-nbctl --bfd lr-policy-add lr0 103 "ip4.src == 1.2.3.0/24" reroute 192.168.1.1], [1], [], + [ovn-nbctl: out lrp not found for 192.168.1.1 nexthop +]) +AT_CHECK([ovn-nbctl --bfd lr-policy-add lr0 103 "ip4.src == 1.2.3.0/24" drop], [1], [], + [ovn-nbctl: BFD is valid only with reroute action. +]) dnl Incomplete option set. AT_CHECK([ovn-nbctl lr-policy-add lr0 200 "ip4.src == 1.1.4.0/24" reroute 192.168.0.10 foo], [1], [], diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 67e81ddba..5407bd381 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -3624,7 +3624,7 @@ AT_KEYWORDS([northd-bfd]) ovn_start check ovn-nbctl --wait=sb lr-add r0 -for i in $(seq 1 7); do +for i in $(seq 1 9); do check ovn-nbctl --wait=sb lrp-add r0 r0-sw$i 00:00:00:00:00:0$i 192.168.$i.1/24 check ovn-nbctl --wait=sb ls-add sw$i check ovn-nbctl --wait=sb lsp-add sw$i sw$i-r0 @@ -3688,6 +3688,24 @@ bfd2_uuid=$(fetch_column bfd _uuid logical_port=r0-sw2) check ovn-sbctl set bfd $bfd2_uuid status=up wait_column up nb:bfd status logical_port=r0-sw2 +# Create reroute policies associated with BFD sessions +check ovn-nbctl lr-route-del r0 +check ovn-nbctl --bfd lr-policy-add r0 100 "ip4.src == 1.2.3.0/24" reroute 192.168.8.2 +wait_column down bfd status logical_port=r0-sw8 + +bfd_route_policy_uuid=$(fetch_column nb:bfd _uuid logical_port=r0-sw8) +AT_CHECK([ovn-nbctl list logical_router_policy | grep -q $bfd_route_policy_uuid]) + +check ovn-nbctl lr-policy-del r0 +check ovn-nbctl --bfd lr-policy-add r0 100 "ip4.src == 2.3.4.0/24" reroute 192.168.9.2,192.168.9.3,192.168.9.4 + +wait_column down bfd status dst_ip=192.168.9.2 +wait_column down bfd status dst_ip=192.168.9.3 +wait_column down bfd status dst_ip=192.168.9.4 + +bfd_route_policy_uuid=$(fetch_column nb:bfd _uuid logical_port=r0-sw9) +AT_CHECK([ovn-nbctl list logical_router_policy | sed s/,//g | grep -q "$bfd_route_policy_uuid"]) + AT_CLEANUP ]) diff --git a/tests/system-ovn.at b/tests/system-ovn.at index 9ecb29cdb..8e3acd57e 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -6837,6 +6837,15 @@ OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 |grep lr_in_ip_routing |grep 'ip4.dst == check ovn-nbctl clear logical_router_static_route $route_uuid bfd wait_column "admin_down" nb:bfd status logical_port=rp-public OVS_WAIT_UNTIL([ip netns exec server bfdd-control status | grep -qi state=Down]) + +check ovn-nbctl --bfd lr-policy-add R1 100 "ip4.src == 200.0.0.0/8" reroute 172.16.1.50 +wait_column "up" nb:bfd status logical_port=rp-public +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 |grep lr_in_policy |grep 'ip4.src == 200.0.0.0/8' |grep -q 172.16.1.50]) + +check ovn-nbctl lr-policy-del R1 +wait_column "admin_down" nb:bfd status logical_port=rp-public +OVS_WAIT_UNTIL([ip netns exec server bfdd-control status | grep -qi state=Down]) + NS_CHECK_EXEC([server], [tcpdump -nni s1 udp port 3784 -Q in > bfd.pcap &]) sleep 5 kill $(pidof tcpdump) @@ -6844,25 +6853,57 @@ AT_CHECK([grep -qi bfd bfd.pcap],[1]) # restart the connection check ovn-nbctl set logical_router_static_route $route_uuid bfd=$uuid +check ovn-nbctl --bfd lr-policy-add R1 100 "ip4.src == 200.0.0.0/8" reroute 172.16.1.50 wait_column "up" nb:bfd status logical_port=rp-public +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 |grep lr_in_ip_routing |grep 'ip4.dst == 100.0.0.0/8' |grep -q 172.16.1.50]) +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 |grep lr_in_policy |grep 'ip4.src == 200.0.0.0/8' |grep -q 172.16.1.50]) + +# stop bfd endpoint +NS_CHECK_EXEC([server], [bfdd-control stop], [0], [dnl +stopping +]) +wait_column "down" nb:bfd status logical_port=rp-public +OVS_WAIT_UNTIL([test "$(ovn-sbctl dump-flows R1 |grep lr_in_ip_routing |grep 'ip4.dst == 100.0.0.0/8' |grep 172.16.1.50)" = ""]) +OVS_WAIT_UNTIL([test "$(ovn-sbctl dump-flows R1 |grep lr_in_policy |grep 'ip4.src == 200.0.0.0/8' |grep 172.16.1.50)" = ""]) + # switch to gw router configuration check ovn-nbctl clear logical_router_static_route $route_uuid bfd -wait_column "admin_down" nb:bfd status logical_port=rp-public -OVS_WAIT_UNTIL([ip netns exec server bfdd-control status | grep -qi state=Down]) +check ovn-nbctl lr-policy-del R1 check ovn-nbctl clear logical_router_port rp-public gateway_chassis check ovn-nbctl set logical_router R1 options:chassis=hv1 check ovn-nbctl set logical_router_static_route $route_uuid bfd=$uuid + +# restart bfdd +NS_CHECK_EXEC([server], [bfdd-beacon --listen=172.16.1.50], [0]) +NS_CHECK_EXEC([server], [bfdd-control allow 172.16.1.1], [0], [dnl +Allowing connections from 172.16.1.1 +]) + wait_column "up" nb:bfd status logical_port=rp-public +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 |grep lr_in_ip_routing |grep 'ip4.dst == 100.0.0.0/8' |grep -q 172.16.1.50]) + +check ovn-nbctl clear logical_router_static_route $route_uuid bfd +wait_column "admin_down" nb:bfd status logical_port=rp-public +OVS_WAIT_UNTIL([ip netns exec server bfdd-control status | grep -qi state=Down]) +ovn-nbctl destroy bfd $uuid +check_row_count bfd 0 + +# create reroute route policy +check ovn-nbctl --bfd lr-policy-add R1 100 "ip4.src == 210.0.0.0/8" reroute 172.16.1.50 +wait_column "up" nb:bfd status logical_port=rp-public +OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 |grep lr_in_policy |grep 'ip4.src == 210.0.0.0/8' |grep -q 172.16.1.50]) + +check ovn-nbctl lr-policy-del R1 +wait_column "admin_down" nb:bfd status logical_port=rp-public +OVS_WAIT_UNTIL([ip netns exec server bfdd-control status | grep -qi state=Down]) +uuid=$(fetch_column nb:bfd _uuid logical_port="rp-public") # stop bfd endpoint NS_CHECK_EXEC([server], [bfdd-control stop], [0], [dnl stopping ]) -wait_column "down" nb:bfd status logical_port=rp-public -OVS_WAIT_UNTIL([test "$(ovn-sbctl dump-flows R1 |grep lr_in_ip_routing |grep 'ip4.dst == 100.0.0.0/8' |grep 172.16.1.50)" = ""]) - # remove bfd entry ovn-nbctl destroy bfd $uuid check_row_count bfd 0 diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml index 6f74bd557..5aa01f2f8 100644 --- a/utilities/ovn-nbctl.8.xml +++ b/utilities/ovn-nbctl.8.xml @@ -1119,6 +1119,14 @@ duplicated routing policy results in error.
+
+ --bfd
option is used to link a BFD session to the
+ OVN reroute policy. OVN will look for an already running BFD
+ session using next-hop as lookup key in the BFD table.
+ If the lookup fails, a new entry in the BFD table will be created
+ using the nexthop as dst_ip.
+
The following example shows a policy to lr1, which will drop packets
from192.168.100.0/24
.
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index 0586eccdb..5db1fc136 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -4014,14 +4014,26 @@ normalize_addr_str(const char *orig_addr)
return ret;
}
+static bool
+ip_in_lrp_networks(const struct nbrec_logical_router_port *lrp,
+ const char *ip_s);
+
static void
nbctl_pre_lr_policy_add(struct ctl_context *ctx)
{
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_name);
+ ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_ports);
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_col_policies);
+ 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_policy_col_priority);
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_match);
+
+ ovsdb_idl_add_column(ctx->idl, &nbrec_bfd_col_dst_ip);
+ ovsdb_idl_add_column(ctx->idl, &nbrec_bfd_col_logical_port);
}
static void
@@ -4158,6 +4170,81 @@ nbctl_lr_policy_add(struct ctl_context *ctx)
nbrec_logical_router_update_policies_addvalue(lr, policy);
+ struct shash_node *bfd = shash_find(&ctx->options, "--bfd");
+ const struct nbrec_bfd **bfd_sessions = NULL;
+
+ if (bfd) {
+ if (!reroute) {
+ ctl_error(ctx, "BFD is valid only with reroute action.");
+ goto free_nexthops;
+ }
+
+ bfd_sessions = xcalloc(n_nexthops, sizeof *bfd_sessions);
+ size_t j, n_bfd_sessions = 0;
+
+ for (i = 0; i < n_nexthops; i++) {
+ for (j = 0; j < lr->n_ports; j++) {
+ if (ip_in_lrp_networks(lr->ports[j], nexthops[i])) {
+ break;
+ }
+ }
+
+ if (j == lr->n_ports) {
+ ctl_error(ctx, "out lrp not found for %s nexthop",
+ nexthops[i]);
+ goto free_nexthops;
+ }
+
+ struct in6_addr nexthop_v6;
+ bool is_nexthop_v6 = ipv6_parse(nexthops[i], &nexthop_v6);
+ const struct nbrec_bfd *iter, *nb_bt = NULL;
+
+ NBREC_BFD_FOR_EACH (iter, ctx->idl) {
+ struct in6_addr dst_ipv6;
+ bool is_dst_v6 = ipv6_parse(iter->dst_ip, &dst_ipv6);
+
+ if (is_nexthop_v6 ^ is_dst_v6) {
+ continue;
+ }
+
+ /* match endpoint ip. */
+ if ((is_nexthop_v6 &&
+ !ipv6_addr_equals(&nexthop_v6, &dst_ipv6)) ||
+ strcmp(iter->dst_ip, nexthops[i])) {
+ continue;
+ }
+
+ /* match outport. */
+ if (strcmp(iter->logical_port, lr->ports[j]->name)) {
+ continue;
+ }
+
+ nb_bt = iter;
+ break;
+ }
+
+ /* Create the BFD session if it does not already exist. */
+ if (!nb_bt) {
+ nb_bt = nbrec_bfd_insert(ctx->txn);
+ nbrec_bfd_set_dst_ip(nb_bt, nexthops[i]);
+ nbrec_bfd_set_logical_port(nb_bt, lr->ports[j]->name);
+ }
+
+ for (j = 0; j < n_bfd_sessions; j++) {
+ if (bfd_sessions[j] == nb_bt) {
+ break;
+ }
+ }
+ if (j == n_bfd_sessions) {
+ bfd_sessions[n_bfd_sessions++] = nb_bt;
+ }
+ }
+ nbrec_logical_router_policy_set_bfd_sessions(
+ policy, (struct nbrec_bfd **) bfd_sessions, n_bfd_sessions);
+ }
+
+free_nexthops:
+ free(bfd_sessions);
for (i = 0; i < n_nexthops; i++) {
free(nexthops[i]);
}
@@ -4282,8 +4369,11 @@ print_routing_policy(const struct nbrec_logical_router_policy *policy,
policy->match, policy->action);
}
- if (!smap_is_empty(&policy->options)) {
+ if (!smap_is_empty(&policy->options) || policy->n_bfd_sessions) {
ds_put_format(s, "%15s", "");
+ if (policy->n_bfd_sessions) {
+ ds_put_cstr(s, "bfd,");
+ }
struct smap_node *node;
SMAP_FOR_EACH (node, &policy->options) {
ds_put_format(s, "%s=%s,", node->key, node->value);
@@ -4305,6 +4395,8 @@ nbctl_pre_lr_policy_list(struct ctl_context *ctx)
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_nexthops);
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_action);
ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_options);
+ ovsdb_idl_add_column(ctx->idl,
+ &nbrec_logical_router_policy_col_bfd_sessions);
}
static void
@@ -7900,7 +7992,8 @@ static const struct ctl_command_syntax nbctl_commands[] = {
/* Policy commands */
{ "lr-policy-add", 4, INT_MAX,
"ROUTER PRIORITY MATCH ACTION [NEXTHOP] [OPTIONS - KEY=VALUE ...]",
- nbctl_pre_lr_policy_add, nbctl_lr_policy_add, NULL, "--may-exist", RW },
+ nbctl_pre_lr_policy_add, nbctl_lr_policy_add, NULL, "--may-exist,--bfd?",
+ RW },
{ "lr-policy-del", 1, 3, "ROUTER [{PRIORITY | UUID} [MATCH]]",
nbctl_pre_lr_policy_del, nbctl_lr_policy_del, NULL, "--if-exists", RW },
{ "lr-policy-list", 1, 1, "ROUTER", nbctl_pre_lr_policy_list,