Re: [ovs-dev] [PATCH v2 ovn 3/3] northd: Add BFD support for ECMP route policy.
Thanks Lorenzo, Acked-by: Mark Michelson On 2/2/24 08:49, Lorenzo Bianconi wrote: Similar to OVN static routes, introduce the capability to link a BFD session for OVN reroute policies. Reported-at: https://issues.redhat.com/browse/FDP-234 Signed-off-by: Lorenzo Bianconi --- NEWS | 1 + northd/northd.c | 86 ++ ovn-nb.ovsschema | 9 +++- ovn-nb.xml| 7 +++ tests/ovn-nbctl.at| 6 +++ tests/ovn-northd.at | 20 +++- tests/system-ovn.at | 51 ++-- utilities/ovn-nbctl.8.xml | 8 utilities/ovn-nbctl.c | 97 ++- 9 files changed, 267 insertions(+), 18 deletions(-) diff --git a/NEWS b/NEWS index 6553bd078..d4227ac99 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,7 @@ Post v23.09.0 - Support selecting encapsulation IP based on the source/destination VIF's settting. See ovn-controller(8) 'external_ids:ovn-encap-ip' for more details. + - Introduce next-hop BFD availability check for OVN reroute policies. OVN v23.09.0 - 15 Sep 2023 -- diff --git a/northd/northd.c b/northd/northd.c index d2091d4bc..ae50e4ff9 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -10991,10 +10991,63 @@ get_outport_for_routing_policy_nexthop(struct ovn_datapath *od, return NULL; } +static struct ovs_mutex bfd_lock = OVS_MUTEX_INITIALIZER; + +static bool check_bfd_state( +const struct nbrec_logical_router_policy *rule, +const struct hmap *bfd_connections, +struct ovn_port *out_port, +const char *nexthop) +{ +struct in6_addr nexthop_v6; +bool is_nexthop_v6 = ipv6_parse(nexthop, _v6); +bool ret = true; + +for (size_t i = 0; i < rule->n_bfd_sessions; i++) { +/* Check if there is a BFD session associated to the reroute + * policy. */ +const struct nbrec_bfd *nb_bt = rule->bfd_sessions[i]; +struct in6_addr dst_ipv6; +bool is_dst_v6 = ipv6_parse(nb_bt->dst_ip, _ipv6); + +if (is_nexthop_v6 ^ is_dst_v6) { +continue; +} + +if ((is_nexthop_v6 && !ipv6_addr_equals(_v6, _ipv6)) || +strcmp(nb_bt->dst_ip, nexthop)) { +continue; +} + +if (strcmp(nb_bt->logical_port, out_port->key)) { +continue; +} + +struct bfd_entry *bfd_e = bfd_port_lookup(bfd_connections, + nb_bt->logical_port, + nb_bt->dst_ip); +ovs_mutex_lock(_lock); +if (bfd_e) { +bfd_e->ref = true; +} + +if (!strcmp(nb_bt->status, "admin_down")) { +nbrec_bfd_set_status(nb_bt, "down"); +} + +ret = strcmp(nb_bt->status, "down"); +ovs_mutex_unlock(_lock); +break; +} + +return ret; +} + static void build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od, const struct hmap *lr_ports, const struct nbrec_logical_router_policy *rule, + const struct hmap *bfd_connections, const struct ovsdb_idl_row *stage_hint) { struct ds match = DS_EMPTY_INITIALIZER; @@ -11019,6 +11072,11 @@ build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od, rule->priority, nexthop); return; } + +if (!check_bfd_state(rule, bfd_connections, out_port, nexthop)) { +return; +} + uint32_t pkt_mark = smap_get_uint(>options, "pkt_mark", 0); if (pkt_mark) { ds_put_format(, "pkt.mark = %u; ", pkt_mark); @@ -11060,6 +8,7 @@ static void build_ecmp_routing_policy_flows(struct hmap *lflows, struct ovn_datapath *od, const struct hmap *lr_ports, const struct nbrec_logical_router_policy *rule, +const struct hmap *bfd_connections, uint16_t ecmp_group_id) { ovs_assert(rule->n_nexthops > 1); @@ -11088,6 +11147,9 @@ build_ecmp_routing_policy_flows(struct hmap *lflows, struct ovn_datapath *od, struct ds match = DS_EMPTY_INITIALIZER; struct ds actions = DS_EMPTY_INITIALIZER; +size_t *valid_nexthops = xcalloc(rule->n_nexthops, sizeof *valid_nexthops); +size_t n_valid_nexthops = 0; + for (size_t i = 0; i < rule->n_nexthops; i++) { struct ovn_port *out_port = get_outport_for_routing_policy_nexthop( od, lr_ports, rule->priority, rule->nexthops[i]); @@ -11105,6 +11167,13 @@ build_ecmp_routing_policy_flows(struct hmap *lflows, struct ovn_datapath *od, goto cleanup; } +if (!check_bfd_state(rule, bfd_connections, out_port, +
[ovs-dev] [PATCH v2 ovn 3/3] northd: Add BFD support for ECMP route policy.
Similar to OVN static routes, introduce the capability to link a BFD session for OVN reroute policies. Reported-at: https://issues.redhat.com/browse/FDP-234 Signed-off-by: Lorenzo Bianconi --- NEWS | 1 + northd/northd.c | 86 ++ ovn-nb.ovsschema | 9 +++- ovn-nb.xml| 7 +++ tests/ovn-nbctl.at| 6 +++ tests/ovn-northd.at | 20 +++- tests/system-ovn.at | 51 ++-- utilities/ovn-nbctl.8.xml | 8 utilities/ovn-nbctl.c | 97 ++- 9 files changed, 267 insertions(+), 18 deletions(-) diff --git a/NEWS b/NEWS index 6553bd078..d4227ac99 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,7 @@ Post v23.09.0 - Support selecting encapsulation IP based on the source/destination VIF's settting. See ovn-controller(8) 'external_ids:ovn-encap-ip' for more details. + - Introduce next-hop BFD availability check for OVN reroute policies. OVN v23.09.0 - 15 Sep 2023 -- diff --git a/northd/northd.c b/northd/northd.c index d2091d4bc..ae50e4ff9 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -10991,10 +10991,63 @@ get_outport_for_routing_policy_nexthop(struct ovn_datapath *od, return NULL; } +static struct ovs_mutex bfd_lock = OVS_MUTEX_INITIALIZER; + +static bool check_bfd_state( +const struct nbrec_logical_router_policy *rule, +const struct hmap *bfd_connections, +struct ovn_port *out_port, +const char *nexthop) +{ +struct in6_addr nexthop_v6; +bool is_nexthop_v6 = ipv6_parse(nexthop, _v6); +bool ret = true; + +for (size_t i = 0; i < rule->n_bfd_sessions; i++) { +/* Check if there is a BFD session associated to the reroute + * policy. */ +const struct nbrec_bfd *nb_bt = rule->bfd_sessions[i]; +struct in6_addr dst_ipv6; +bool is_dst_v6 = ipv6_parse(nb_bt->dst_ip, _ipv6); + +if (is_nexthop_v6 ^ is_dst_v6) { +continue; +} + +if ((is_nexthop_v6 && !ipv6_addr_equals(_v6, _ipv6)) || +strcmp(nb_bt->dst_ip, nexthop)) { +continue; +} + +if (strcmp(nb_bt->logical_port, out_port->key)) { +continue; +} + +struct bfd_entry *bfd_e = bfd_port_lookup(bfd_connections, + nb_bt->logical_port, + nb_bt->dst_ip); +ovs_mutex_lock(_lock); +if (bfd_e) { +bfd_e->ref = true; +} + +if (!strcmp(nb_bt->status, "admin_down")) { +nbrec_bfd_set_status(nb_bt, "down"); +} + +ret = strcmp(nb_bt->status, "down"); +ovs_mutex_unlock(_lock); +break; +} + +return ret; +} + static void build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od, const struct hmap *lr_ports, const struct nbrec_logical_router_policy *rule, + const struct hmap *bfd_connections, const struct ovsdb_idl_row *stage_hint) { struct ds match = DS_EMPTY_INITIALIZER; @@ -11019,6 +11072,11 @@ build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od, rule->priority, nexthop); return; } + +if (!check_bfd_state(rule, bfd_connections, out_port, nexthop)) { +return; +} + uint32_t pkt_mark = smap_get_uint(>options, "pkt_mark", 0); if (pkt_mark) { ds_put_format(, "pkt.mark = %u; ", pkt_mark); @@ -11060,6 +8,7 @@ static void build_ecmp_routing_policy_flows(struct hmap *lflows, struct ovn_datapath *od, const struct hmap *lr_ports, const struct nbrec_logical_router_policy *rule, +const struct hmap *bfd_connections, uint16_t ecmp_group_id) { ovs_assert(rule->n_nexthops > 1); @@ -11088,6 +11147,9 @@ build_ecmp_routing_policy_flows(struct hmap *lflows, struct ovn_datapath *od, struct ds match = DS_EMPTY_INITIALIZER; struct ds actions = DS_EMPTY_INITIALIZER; +size_t *valid_nexthops = xcalloc(rule->n_nexthops, sizeof *valid_nexthops); +size_t n_valid_nexthops = 0; + for (size_t i = 0; i < rule->n_nexthops; i++) { struct ovn_port *out_port = get_outport_for_routing_policy_nexthop( od, lr_ports, rule->priority, rule->nexthops[i]); @@ -11105,6 +11167,13 @@ build_ecmp_routing_policy_flows(struct hmap *lflows, struct ovn_datapath *od, goto cleanup; } +if (!check_bfd_state(rule, bfd_connections, out_port, + rule->nexthops[i])) { +continue; +} + +valid_nexthops[n_valid_nexthops++] = i + 1; +