Re: [ovs-dev] [PATCH v2 ovn 3/3] northd: Add BFD support for ECMP route policy.

2024-02-02 Thread Mark Michelson

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.

2024-02-02 Thread Lorenzo Bianconi
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;
+