[ovs-dev] [PATCH ovn 4/8] northd: introduce build_lrouter_in_dnat_flow routine
Lorenzo Bianconi
lorenzo.bianconi at redhat.com
Thu Feb 25 12:49:22 UTC 2021
Introduce build_lrouter_in_dnat_flow routine as a container for logical
router per nat configuration in build_lrouter_nat_defrag_and_lb
routine for S_ROUTER_IN_DNAT table.
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
---
northd/ovn-northd.c | 203 +++++++++++++++++++++++---------------------
1 file changed, 105 insertions(+), 98 deletions(-)
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index c5403ad30..b0f2ba953 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -11134,6 +11134,108 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od,
}
}
+static void
+build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od,
+ const struct nbrec_nat *nat, struct ds *match,
+ struct ds *actions, bool distributed,
+ ovs_be32 mask, bool is_v6)
+{
+ /* Ingress DNAT table: Packets enter the pipeline with destination
+ * IP address that needs to be DNATted from a external IP address
+ * to a logical IP address. */
+ if (!strcmp(nat->type, "dnat") || !strcmp(nat->type, "dnat_and_snat")) {
+ bool stateless = lrouter_nat_is_stateless(nat);
+
+ if (!od->l3dgw_port) {
+ /* Gateway router. */
+ /* Packet when it goes from the initiator to destination.
+ * We need to set flags.loopback because the router can
+ * send the packet back through the same interface. */
+ ds_clear(match);
+ ds_put_format(match, "ip && ip%s.dst == %s",
+ is_v6 ? "6" : "4", nat->external_ip);
+ ds_clear(actions);
+ if (nat->allowed_ext_ips || nat->exempted_ext_ips) {
+ lrouter_nat_add_ext_ip_match(od, lflows, match, nat,
+ is_v6, true, mask);
+ }
+
+ if (!lport_addresses_is_empty(&od->dnat_force_snat_addrs)) {
+ /* Indicate to the future tables that a DNAT has taken
+ * place and a force SNAT needs to be done in the
+ * Egress SNAT table. */
+ ds_put_format(actions, "flags.force_snat_for_dnat = 1; ");
+ }
+
+ if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
+ ds_put_format(actions, "flags.loopback = 1; "
+ "ip%s.dst=%s; next;",
+ is_v6 ? "6" : "4", nat->logical_ip);
+ } else {
+ ds_put_format(actions, "flags.loopback = 1; ct_dnat(%s",
+ nat->logical_ip);
+
+ if (nat->external_port_range[0]) {
+ ds_put_format(actions, ",%s", nat->external_port_range);
+ }
+ ds_put_format(actions, ");");
+ }
+
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, 100,
+ ds_cstr(match), ds_cstr(actions),
+ &nat->header_);
+ } else {
+ /* Distributed router. */
+
+ /* Traffic received on l3dgw_port is subject to NAT. */
+ ds_clear(match);
+ ds_put_format(match, "ip && ip%s.dst == %s && inport == %s",
+ is_v6 ? "6" : "4", nat->external_ip,
+ od->l3dgw_port->json_key);
+ if (!distributed && od->l3redirect_port) {
+ /* Flows for NAT rules that are centralized are only
+ * programmed on the gateway chassis. */
+ ds_put_format(match, " && is_chassis_resident(%s)",
+ od->l3redirect_port->json_key);
+ }
+ ds_clear(actions);
+ if (nat->allowed_ext_ips || nat->exempted_ext_ips) {
+ lrouter_nat_add_ext_ip_match(od, lflows, match, nat,
+ is_v6, true, mask);
+ }
+
+ if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
+ ds_put_format(actions, "ip%s.dst=%s; next;",
+ is_v6 ? "6" : "4", nat->logical_ip);
+ } else {
+ ds_put_format(actions, "ct_dnat(%s", nat->logical_ip);
+ if (nat->external_port_range[0]) {
+ ds_put_format(actions, ",%s", nat->external_port_range);
+ }
+ ds_put_format(actions, ");");
+ }
+
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, 100,
+ ds_cstr(match), ds_cstr(actions),
+ &nat->header_);
+ }
+ }
+
+ if (!od->l3dgw_port) {
+ /* For gateway router, re-circulate every packet through
+ * the DNAT zone. This helps with the following.
+ *
+ * Any packet that needs to be unDNATed in the reverse
+ * direction gets unDNATed. Ideally this could be done in
+ * the egress pipeline. But since the gateway router
+ * does not have any feature that depends on the source
+ * ip address being external IP address for IP routing,
+ * we can do it here, saving a future re-circulation. */
+ ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 50,
+ "ip", "flags.loopback = 1; ct_dnat;");
+ }
+}
+
/* NAT, Defrag and load balancing. */
static void
build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
@@ -11270,92 +11372,9 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
/* S_ROUTER_IN_UNSNAT */
build_lrouter_in_unsnat_flow(lflows, od, nat, match, actions, distributed,
is_v6);
-
- /* Ingress DNAT table: Packets enter the pipeline with destination
- * IP address that needs to be DNATted from a external IP address
- * to a logical IP address. */
- if (!strcmp(nat->type, "dnat")
- || !strcmp(nat->type, "dnat_and_snat")) {
- if (!od->l3dgw_port) {
- /* Gateway router. */
- /* Packet when it goes from the initiator to destination.
- * We need to set flags.loopback because the router can
- * send the packet back through the same interface. */
- ds_clear(match);
- ds_put_format(match, "ip && ip%s.dst == %s",
- is_v6 ? "6" : "4",
- nat->external_ip);
- ds_clear(actions);
- if (allowed_ext_ips || exempted_ext_ips) {
- lrouter_nat_add_ext_ip_match(od, lflows, match, nat,
- is_v6, true, mask);
- }
-
- if (dnat_force_snat_ip) {
- /* Indicate to the future tables that a DNAT has taken
- * place and a force SNAT needs to be done in the
- * Egress SNAT table. */
- ds_put_format(actions,
- "flags.force_snat_for_dnat = 1; ");
- }
-
- if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
- ds_put_format(actions, "flags.loopback = 1; "
- "ip%s.dst=%s; next;",
- is_v6 ? "6" : "4", nat->logical_ip);
- } else {
- ds_put_format(actions, "flags.loopback = 1; "
- "ct_dnat(%s", nat->logical_ip);
-
- if (nat->external_port_range[0]) {
- ds_put_format(actions, ",%s",
- nat->external_port_range);
- }
- ds_put_format(actions, ");");
- }
-
- ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, 100,
- ds_cstr(match), ds_cstr(actions),
- &nat->header_);
- } else {
- /* Distributed router. */
-
- /* Traffic received on l3dgw_port is subject to NAT. */
- ds_clear(match);
- ds_put_format(match, "ip && ip%s.dst == %s"
- " && inport == %s",
- is_v6 ? "6" : "4",
- nat->external_ip,
- od->l3dgw_port->json_key);
- if (!distributed && od->l3redirect_port) {
- /* Flows for NAT rules that are centralized are only
- * programmed on the gateway chassis. */
- ds_put_format(match, " && is_chassis_resident(%s)",
- od->l3redirect_port->json_key);
- }
- ds_clear(actions);
- if (allowed_ext_ips || exempted_ext_ips) {
- lrouter_nat_add_ext_ip_match(od, lflows, match, nat,
- is_v6, true, mask);
- }
-
- if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
- ds_put_format(actions, "ip%s.dst=%s; next;",
- is_v6 ? "6" : "4", nat->logical_ip);
- } else {
- ds_put_format(actions, "ct_dnat(%s", nat->logical_ip);
- if (nat->external_port_range[0]) {
- ds_put_format(actions, ",%s",
- nat->external_port_range);
- }
- ds_put_format(actions, ");");
- }
-
- ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, 100,
- ds_cstr(match), ds_cstr(actions),
- &nat->header_);
- }
- }
+ /* S_ROUTER_IN_DNAT */
+ build_lrouter_in_dnat_flow(lflows, od, nat, match, actions, distributed,
+ mask, is_v6);
/* ARP resolve for NAT IPs. */
if (od->l3dgw_port) {
@@ -11640,18 +11659,6 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
od->lb_force_snat_addrs.ipv6_addrs[0].addr_s, "lb");
}
}
-
- /* For gateway router, re-circulate every packet through
- * the DNAT zone. This helps with the following.
- *
- * Any packet that needs to be unDNATed in the reverse
- * direction gets unDNATed. Ideally this could be done in
- * the egress pipeline. But since the gateway router
- * does not have any feature that depends on the source
- * ip address being external IP address for IP routing,
- * we can do it here, saving a future re-circulation. */
- ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 50,
- "ip", "flags.loopback = 1; ct_dnat;");
}
/* Load balancing and packet defrag are only valid on
--
2.29.2
More information about the dev
mailing list