@@ -8810,7 +8810,13 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
is_v6 ? "6" : "4", nat->logical_ip);
} else {
ds_put_format(&actions, "flags.loopback = 1; "
- "ct_dnat(%s);", nat->logical_ip);
+ "ct_dnat(%s", nat->logical_ip);
+
+ if (strlen(nat->external_port_range)) {
+ 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,
@@ -8838,8 +8844,12 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
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);
+ ds_put_format(&actions, "ct_dnat(%s", nat->logical_ip);
+ if (strlen(nat->external_port_range)) {
+ 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,
@@ -8938,8 +8948,14 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_put_format(&actions, "ip%s.src=%s; next;",
is_v6 ? "6" : "4", nat->external_ip);
} else {
- ds_put_format(&actions, "ct_snat(%s);",
+ ds_put_format(&actions, "ct_snat(%s",
nat->external_ip);
+
+ if (strlen(nat->external_port_range)) {
+ ds_put_format(&actions, ",%s",
+ nat->external_port_range);
+ }
+ ds_put_format(&actions, ");");
}
/* The priority here is calculated such that the
@@ -8976,8 +8992,13 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_put_format(&actions, "ip%s.src=%s; next;",
is_v6 ? "6" : "4", nat->external_ip);
} else {
- ds_put_format(&actions, "ct_snat(%s);",
+ ds_put_format(&actions, "ct_snat(%s",
nat->external_ip);
+ if (strlen(nat->external_port_range)) {
+ ds_put_format(&actions, ",%s",
+ nat->external_port_range);
+ }
+ ds_put_format(&actions, ");");
}
/* The priority here is calculated such that the
@@ -1074,6 +1074,70 @@ AT_CHECK([ovn-sbctl dump-flows R1 | grep ip6.src=| wc -l], [0], [2
AT_CLEANUP
+AT_SETUP([ovn -- check portrange dnat, snat and dnat_and_snat rules])
+ovn_start
+
+ovn-sbctl chassis-add gw1 geneve 127.0.0.1
+
+ovn-nbctl lr-add R1
+ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
+
+ovn-nbctl ls-add S1
+ovn-nbctl lsp-add S1 S1-R1
+ovn-nbctl lsp-set-type S1-R1 router
+ovn-nbctl lsp-set-addresses S1-R1 router
+ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
+
+ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1
+
+uuid=`ovn-sbctl --columns=_uuid --bare find Port_Binding logical_port=cr-R1-S1`
+echo "CR-LRP UUID is: " $uuid
+
+# IPV4
+ovn-nbctl --portrange lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 1-3000
+
+OVS_WAIT_UNTIL([test 2 = `ovn-sbctl dump-flows R1 | grep lr_in_unsnat | \
+wc -l`])
+
+AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_snat | grep 3000 | wc -l], [0], [1
+])
+
+AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_dnat | grep 3000 | wc -l], [0], [1
+])
+
+
+ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1
+
+ovn-nbctl --portrange lr-nat-add R1 snat 172.16.1.1 50.0.0.11 1-3000
+
+OVS_WAIT_UNTIL([test 2 = `ovn-sbctl dump-flows R1 | grep lr_in_unsnat | \
+wc -l`])
+
+AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_snat | grep 3000 | wc -l], [0], [1
+])
+
+AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_dnat | grep 3000 | wc -l], [0], [0
+])
+
+ovn-nbctl lr-nat-del R1 snat 172.16.1.1
+
+ovn-nbctl --portrange --stateless lr-nat-add R1 dnat_and_snat 172.16.1.2 50.0.0.12 1-3000
+ovn-sbctl dump-flows R1
+
+OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows R1 | grep lr_in_unsnat | \
+wc -l`])
+
+AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_snat | grep 3000 | grep 172.16.1.2 | wc -l], [0], [0
+])
+
+AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_dnat | grep 3000 | grep 172.16.1.2 | wc -l], [0], [0
+])
+
+
+ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1
+
+AT_CLEANUP
+
AT_SETUP([ovn -- check Load balancer health check and Service Monitor sync])
AT_SKIP_IF([test $HAVE_PYTHON = no])
ovn_start