diff mbox series

[ovs-dev,v3,31/33] northd: Support active-active bgp redirects.

Message ID 19f4f1a0b12520fa32b039482c2937d86f4dde70.1732630355.git.felix.huettner@stackit.cloud
State Changes Requested
Headers show
Series OVN Fabric integration | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success

Commit Message

Felix Huettner Nov. 26, 2024, 2:38 p.m. UTC
add support for routing-protocol-redirects in combination with
active-active routing.

Signed-off-by: Felix Huettner <felix.huettner@stackit.cloud>
---
 northd/northd.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++--
 ovn-nb.xml      |  4 ++++
 tests/ovn.at    | 40 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 92 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/northd/northd.c b/northd/northd.c
index 5ed2720d8..ff665d187 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -2309,6 +2309,7 @@  join_logical_ports_lrp(struct hmap *ports,
 
 struct active_active_port {
     const struct nbrec_logical_switch_port *nbsp;
+    const struct nbrec_logical_switch_port *routing_protocol_redirect;
     const struct nbrec_logical_router_port *nbrp;
     struct ovn_datapath *switch_dp;
     struct ovn_datapath *router_dp;
@@ -2376,6 +2377,7 @@  join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table,
     ovs_list_init(both);
 
     struct shash active_active_ports = SHASH_INITIALIZER(&active_active_ports);
+    struct shash aa_redirect_targets = SHASH_INITIALIZER(&aa_redirect_targets);
 
     const struct sbrec_port_binding *sb;
     SBREC_PORT_BINDING_TABLE_FOR_EACH (sb, sbrec_pb_table) {
@@ -2404,6 +2406,12 @@  join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table,
                 aap->nbrp = nbrp;
                 aap->router_dp = od;
                 shash_add(&active_active_ports, nbrp->name, aap);
+
+                const char *redirect_port_name = smap_get(&nbrp->options,
+                                              "routing-protocol-redirect");
+                if (redirect_port_name) {
+                    shash_add(&aa_redirect_targets, redirect_port_name, aap);
+                }
                 continue;
             }
 
@@ -2434,6 +2442,12 @@  join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table,
                 aap->switch_dp = od;
                 continue;
             }
+            struct active_active_port *aap =
+                shash_find_data(&aa_redirect_targets, nbsp->name);
+            if (aap) {
+                aap->routing_protocol_redirect = nbsp;
+                continue;
+            }
             join_logical_ports_lsp(ports, nb_only, both, od, nbsp,
                                    nbsp->name, queue_id_bitmap,
                                    tag_alloc_table);
@@ -2517,6 +2531,8 @@  join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table,
     SHASH_FOR_EACH (aa_snode, &active_active_ports) {
         const struct active_active_port *aap = aa_snode->data;
         const struct nbrec_logical_switch_port *nbsp = aap->nbsp;
+        const struct nbrec_logical_switch_port *nbsp_rpr =
+            aap->routing_protocol_redirect;
         const struct nbrec_logical_router_port *nbrp = aap->nbrp;
         ovs_assert(nbrp);
         ovs_assert(aap->router_dp);
@@ -2609,6 +2625,18 @@  join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table,
                 lsp->aa_chassis_name = xstrdup(chassis->name);
                 lrp->aa_chassis_index = j;
                 lsp->aa_chassis_index = j;
+
+                if (nbsp_rpr) {
+                    char *lsp_rpr_name = xasprintf("%s-%s-%"PRIuSIZE,
+                                                     nbsp_rpr->name,
+                                                     chassis->name, j);
+                    join_logical_ports_lsp(ports, nb_only, both,
+                                           aap->switch_dp, nbsp_rpr,
+                                           lsp_rpr_name, queue_id_bitmap,
+                                           tag_alloc_table);
+                    free(lsp_rpr_name);
+                }
+
             }
             free(networks.network_name);
             free(networks.addresses);
@@ -2672,6 +2700,7 @@  join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table,
         ipam_add_port_addresses(op->od, op);
     }
 
+    shash_destroy(&aa_redirect_targets);
     shash_destroy_free_data(&active_active_ports);
 }
 
@@ -14332,6 +14361,20 @@  build_arp_resolve_flows_for_lrp(struct ovn_port *op,
     }
 }
 
+static char*
+ovn_port_get_redirect_port_name(struct ovn_port *op) {
+    const char *rpr = smap_get(&op->nbrp->options,
+                               "routing-protocol-redirect");
+    if (!rpr) {
+        return NULL;
+    }
+    if (op->is_active_active) {
+        return xasprintf("%s-%s-%"PRIuSIZE, rpr,
+                         op->aa_chassis_name, op->aa_chassis_index);
+    }
+    return xstrdup(rpr);
+}
+
 static void
 build_routing_protocols_redirect_rule__(
         const char *s_addr, const char *redirect_port_name, int protocol_port,
@@ -14465,8 +14508,7 @@  build_lrouter_routing_protocol_redirect(
     /* Proceed only for LRPs that have 'routing-protocol-redirect' option set.
      * Value of this option is the name of LSP to which the routing protocol
      * traffic will be redirected. */
-    const char *redirect_port_name = smap_get(&op->nbrp->options,
-                                              "routing-protocol-redirect");
+    char *redirect_port_name = ovn_port_get_redirect_port_name(op);
     if (!redirect_port_name) {
         return;
     }
@@ -14482,6 +14524,7 @@  build_lrouter_routing_protocol_redirect(
                           "Switch Port. Routing protocol redirecting won't be "
                           "configured.",
                           op->key);
+        free(redirect_port_name);
         return;
     }
     if (lsp_in_peer->od != op->peer->od) {
@@ -14492,6 +14535,7 @@  build_lrouter_routing_protocol_redirect(
                           "option. Routing protocol redirecting won't be "
                           "configured.",
                           op->key, redirect_port_name);
+        free(redirect_port_name);
         return;
     }
 
@@ -14503,6 +14547,7 @@  build_lrouter_routing_protocol_redirect(
                           "were set via 'routing-protocols' options. This "
                           "configuration has no effect.",
                           op->key);
+        free(redirect_port_name);
         return;
     }
 
@@ -14550,6 +14595,7 @@  build_lrouter_routing_protocol_redirect(
                   ds_cstr(match),
                   REGBIT_PORT_SEC_DROP " = 1; next;",
                   lflow_ref);
+    free(redirect_port_name);
 }
 
 /* This function adds ARP resolve flows related to a LSP. */
diff --git a/ovn-nb.xml b/ovn-nb.xml
index da8cdbe08..ed425f45e 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -3790,6 +3790,10 @@  or
 
           The MAC and IP configuration of this LRP in the northbound database
           is ignored.
+
+          In case the option <ref column="options"
+          key="routing-protocol-redirect"/> is set the target LSP will also be
+          duplicated per LRP/LSP combination.
         </p>
         <p>
           The LRP must be connected via its LSP to an external network.
diff --git a/tests/ovn.at b/tests/ovn.at
index eb38189d5..ecdb50816 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -39636,6 +39636,27 @@  check ovn-nbctl lsp-add phys phys1 \
         -- lsp-set-type phys1 localnet \
         -- lsp-set-options phys1 network_name=phys
 
+# routing-protocol redirection
+check ovn-nbctl set logical_router_port internet-phys \
+          options:routing-protocol-redirect=bgp-redirect \
+          options:routing-protocols=BGP,BFD
+check ovn-nbctl lsp-add phys bgp-redirect
+
+as hv1 ovs-vsctl add-port br-int bgp-redirect-0 -- \
+        set Interface bgp-redirect-0 external-ids:iface-id=bgp-redirect-hv1-0 \
+                              options:tx_pcap=hv1/bgp-redirect-0-tx.pcap \
+                              options:rxq_pcap=hv1/bgp-redirect-0-rx.pcap
+as hv1 ovs-vsctl add-port br-int bgp-redirect-1 -- \
+        set Interface bgp-redirect-1 external-ids:iface-id=bgp-redirect-hv1-1 \
+                              options:tx_pcap=hv1/bgp-redirect-1-tx.pcap \
+                              options:rxq_pcap=hv1/bgp-redirect-1-rx.pcap
+as hv2 ovs-vsctl add-port br-int bgp-redirect-0 -- \
+        set Interface bgp-redirect-0 external-ids:iface-id=bgp-redirect-hv2-0 \
+                              options:tx_pcap=hv2/bgp-redirect-0-tx.pcap \
+                              options:rxq_pcap=hv2/bgp-redirect-0-rx.pcap
+
+# now all setup is done
+
 check ovn-nbctl --wait=hv sync
 wait_for_ports_up
 OVN_POPULATE_ARP
@@ -39719,6 +39740,25 @@  packet=$(fmt_pkt "Ether(dst='00:cc:cc:cc:cc:20', src='00:02:01:00:00:01')/ \
                     cut -c 1-68)
 OVN_CHECK_PACKETS_CONTAIN_PARTS([hv2/br-phys_hv2-1-tx.pcap], ["$packet"])
 
+# bgp packet to the active-active router ports are forwarded to the respective
+# bgp redirect LSP
+outside_to_bgp() {
+  local hv=$1 if=$2 redirindex=$3 mac=$4 ip=$5
+  packet=$(fmt_pkt "Ether(dst='$mac', src='00:aa:bb:cc:dd:ee')/ \
+                    IP(dst='$ip', src='1.1.1.1')/ \
+                    TCP(dport=179)")
+  as hv$hv ovs-appctl netdev-dummy/receive $if $packet
+  local filename="hv$hv-bgp-redirect-$redirindex-tx.expected"
+  rm -f $filename
+  echo $packet > $filename
+  OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv$hv/bgp-redirect-$redirindex-tx.pcap],
+                                     [$filename])
+}
+
+outside_to_bgp 1 br-phys_hv1-1 0 00:01:01:00:00:01 192.168.10.10
+outside_to_bgp 1 br-phys2_hv1-2 1 00:01:02:00:00:01 192.168.11.10
+outside_to_bgp 2 br-phys_hv2-1 0 00:02:01:00:00:01 192.168.20.10
+
 OVN_CLEANUP([hv1],[hv2
 /Couldn't parse MAC binding/d])
 AT_CLEANUP