Keep FIP traffic distributed and do not centralize it even if the
CMS sets redirect-type option to bridged for distributed gateway port.
Tested-by: Jianlin Shi <[email protected]>
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2007120
Signed-off-by: Lorenzo Bianconi <[email protected]>
---
Changes since v1:
- add unit-test
- fix typos
---
northd/northd.c | 29 +++++++++++++++++++++++++++++
northd/northd.h | 2 ++
northd/ovn-northd.8.xml | 17 +++++++++++++++++
tests/ovn-northd.at | 37 +++++++++++++++++++++++++++++++++++++
4 files changed, 85 insertions(+)
diff --git a/northd/northd.c b/northd/northd.c
index 84440a47f..a60467963 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -2616,6 +2616,13 @@ join_logical_ports(struct northd_input *input_data,
op->od = od;
ovs_list_push_back(&od->port_list, &op->dp_node);
+ if (!od->redirect_bridged) {
+ const char *redirect_type =
+ smap_get(&nbrp->options, "redirect-type");
+ od->redirect_bridged =
+ redirect_type && !strcasecmp(redirect_type, "bridged");
+ }
+
if (op->nbrp->ha_chassis_group ||
op->nbrp->n_gateway_chassis) {
/* Additional "derived" ovn_port crp represents the
@@ -13731,6 +13738,28 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath
*od, struct hmap *lflows,
100, ds_cstr(match),
ds_cstr(actions),
&nat->header_);
+ if (od->redirect_bridged && distributed) {
+ ds_clear(match);
+ ds_put_format(
+ match,
+ "outport == %s && ip%s.src == %s "
+ "&& is_chassis_resident(\"%s\")",
+ od->l3dgw_ports[0]->json_key,
+ is_v6 ? "6" : "4", nat->logical_ip,
+ nat->logical_port);
+ ds_clear(actions);
+ if (is_v6) {
+ ds_put_cstr(actions,
+ "get_nd(outport, " REG_NEXT_HOP_IPV6 "); next;");
+ } else {
+ ds_put_cstr(actions,
+ "get_arp(outport, " REG_NEXT_HOP_IPV4 "); next;");
+ }
+ ovn_lflow_add_with_hint(lflows, od,
+ S_ROUTER_IN_ARP_RESOLVE, 90,
+ ds_cstr(match), ds_cstr(actions),
+ &nat->header_);
+ }
sset_add(&nat_entries, nat->external_ip);
}
}
diff --git a/northd/northd.h b/northd/northd.h
index aa9a3ae6e..60601803f 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -229,6 +229,8 @@ struct ovn_datapath {
size_t n_nat_entries;
bool has_distributed_nat;
+ /* router datapath has a logical port with redirect-type set to bridged. */
+ bool redirect_bridged;
/* Set of nat external ips on the router. */
struct sset external_ips;
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index d9e9a7345..009a380bd 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -4053,6 +4053,23 @@ outport = <var>P</var>
</p>
</li>
+ <li>
+ <p>
+ If the router datapath runs a port with <code>redirect-type</code>
+ set to <code>bridged</code>, for each distributed NAT rule with IP
+ <var>A</var> in the
+ <ref column="logical_ip" table="NAT" db="OVN_Northbound"/> column
+ and logical port <var>P</var> in the
+ <ref column="logical_port" table="NAT" db="OVN_Northbound"/> column
+ of <ref table="NAT" db="OVN_Northbound"/> table, a priority-90 flow
+ with the match <code>outport == <var>Q</var> && ip.src ===
+ <var>A</var> && is_chassis_resident(<var>P</var>)</code>,
+ where <code>Q</code> is the distributed logical router port and
+ action <code>get_arp(outport, reg0); next;</code> for IPv4 and
+ <code>get_nd(outport, xxreg0); next;</code> for IPv6.
+ </p>
+ </li>
+
<li>
<p>
Traffic with IP destination an address owned by the router should be
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 093e01c6d..a210fc575 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -7861,3 +7861,40 @@ check_column "" sb:load_balancer datapaths name=lb0
AT_CLEANUP
])
+
+AT_SETUP([check fip flows with redirect-type bridged])
+AT_KEYWORDS([fip-redirect-type-bridged])
+ovn_start
+
+ovn-nbctl lr-add R1
+ovn-nbctl lrp-add R1 R1-S0 02:ac:10:01:00:01 10.0.0.1/24 1000::a/64
+ovn-nbctl lrp-add R1 R1-PUB 02:ac:20:01:01:01 172.16.0.1/24 3000::a/64
+ovn-nbctl lrp-set-gateway-chassis R1-PUB hv1 20
+
+ovn-nbctl ls-add S0
+ovn-nbctl lsp-add S0 S0-R1
+ovn-nbctl lsp-set-type S0-R1 router
+ovn-nbctl lsp-set-addresses S0-R1 02:ac:10:01:00:01
+ovn-nbctl lsp-set-options S0-R1 router-port=R1-S0
+ovn-nbctl lsp-add S0 S0-P0
+ovn-nbctl lsp-set-addresses S0-P0 "50:54:00:00:00:03 10.0.0.3 1000::3"
+
+ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.0.110 10.0.0.3 S0-P0
30:54:00:00:00:03
+ovn-nbctl lr-nat-add R1 dnat_and_snat 3000::c 1000::3 S0-P0 40:54:00:00:00:03
+
+ovn-sbctl dump-flows R1 > R1flows
+AT_CAPTURE_FILE([R1flows])
+AT_CHECK([grep "lr_in_arp_resolve" R1flows | grep priority=90 | sort], [0],
[dnl
+])
+
+ovn-nbctl --wait=sb set logical_router_port R1-PUB
options:redirect-type=bridged
+ovn-sbctl dump-flows R1 > R1flows
+AT_CAPTURE_FILE([R1flows])
+
+AT_CHECK([grep "lr_in_arp_resolve" R1flows | grep priority=90 | sort], [0],
[dnl
+ table=15(lr_in_arp_resolve ), priority=90 , match=(outport == "R1-PUB" && ip4.src ==
10.0.0.3 && is_chassis_resident("S0-P0")), action=(get_arp(outport, reg0); next;)
+ table=15(lr_in_arp_resolve ), priority=90 , match=(outport == "R1-PUB" && ip6.src ==
1000::3 && is_chassis_resident("S0-P0")), action=(get_nd(outport, xxreg0); next;)
+])
+
+AT_CLEANUP
+])