[ovs-dev] [PATCH v2 ovn 4/4] northd: introduce lrouter_check_nat_entry routine
Lorenzo Bianconi
lorenzo.bianconi at redhat.com
Mon Mar 8 14:00:29 UTC 2021
Introduce lrouter_check_nat_entry routine to check logical router
per nat configuration and allow nat entry processing.
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
---
northd/ovn-northd.c | 180 ++++++++++++++++++++++++--------------------
1 file changed, 97 insertions(+), 83 deletions(-)
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index fb097c76e..5af91bed5 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -11441,6 +11441,96 @@ build_lrouter_ingress_flow(struct hmap *lflows, struct ovn_datapath *od,
}
}
+static int
+lrouter_check_nat_entry(struct ovn_datapath *od, const struct nbrec_nat *nat,
+ ovs_be32 *mask, bool *is_v6, int *cidr_bits,
+ struct eth_addr *mac, bool *distributed)
+{
+ struct in6_addr ipv6, mask_v6, v6_exact = IN6ADDR_EXACT_INIT;
+ ovs_be32 ip;
+
+ if (nat->allowed_ext_ips && nat->exempted_ext_ips) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+ VLOG_WARN_RL(&rl, "NAT rule: "UUID_FMT" not applied, since "
+ "both allowed and exempt external ips set",
+ UUID_ARGS(&(nat->header_.uuid)));
+ return -EINVAL;
+ }
+
+ char *error = ip_parse_masked(nat->external_ip, &ip, mask);
+ *is_v6 = false;
+
+ if (error || *mask != OVS_BE32_MAX) {
+ free(error);
+ error = ipv6_parse_masked(nat->external_ip, &ipv6, &mask_v6);
+ if (error || memcmp(&mask_v6, &v6_exact, sizeof(mask_v6))) {
+ /* Invalid for both IPv4 and IPv6 */
+ static struct vlog_rate_limit rl =
+ VLOG_RATE_LIMIT_INIT(5, 1);
+ VLOG_WARN_RL(&rl, "bad external ip %s for nat",
+ nat->external_ip);
+ free(error);
+ return -EINVAL;
+ }
+ /* It was an invalid IPv4 address, but valid IPv6.
+ * Treat the rest of the handling of this NAT rule
+ * as IPv6. */
+ *is_v6 = true;
+ }
+
+ /* Check the validity of nat->logical_ip. 'logical_ip' can
+ * be a subnet when the type is "snat". */
+ if (*is_v6) {
+ error = ipv6_parse_masked(nat->logical_ip, &ipv6, &mask_v6);
+ *cidr_bits = ipv6_count_cidr_bits(&mask_v6);
+ } else {
+ error = ip_parse_masked(nat->logical_ip, &ip, mask);
+ *cidr_bits = ip_count_cidr_bits(*mask);
+ }
+ if (!strcmp(nat->type, "snat")) {
+ if (error) {
+ /* Invalid for both IPv4 and IPv6 */
+ static struct vlog_rate_limit rl =
+ VLOG_RATE_LIMIT_INIT(5, 1);
+ VLOG_WARN_RL(&rl, "bad ip network or ip %s for snat "
+ "in router "UUID_FMT"",
+ nat->logical_ip, UUID_ARGS(&od->key));
+ free(error);
+ return -EINVAL;
+ }
+ } else {
+ if (error || (*is_v6 == false && *mask != OVS_BE32_MAX)
+ || (*is_v6 && memcmp(&mask_v6, &v6_exact,
+ sizeof mask_v6))) {
+ /* Invalid for both IPv4 and IPv6 */
+ static struct vlog_rate_limit rl =
+ VLOG_RATE_LIMIT_INIT(5, 1);
+ VLOG_WARN_RL(&rl, "bad ip %s for dnat in router "
+ ""UUID_FMT"", nat->logical_ip, UUID_ARGS(&od->key));
+ free(error);
+ return -EINVAL;
+ }
+ }
+
+ /* For distributed router NAT, determine whether this NAT rule
+ * satisfies the conditions for distributed NAT processing. */
+ *distributed = false;
+ if (od->l3dgw_port && !strcmp(nat->type, "dnat_and_snat") &&
+ nat->logical_port && nat->external_mac) {
+ if (eth_addr_from_string(nat->external_mac, mac)) {
+ *distributed = true;
+ } else {
+ static struct vlog_rate_limit rl =
+ VLOG_RATE_LIMIT_INIT(5, 1);
+ VLOG_WARN_RL(&rl, "bad mac %s for dnat in router "
+ ""UUID_FMT"", nat->external_mac, UUID_ARGS(&od->key));
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
/* NAT, Defrag and load balancing. */
static void
build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
@@ -11482,91 +11572,15 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
!lport_addresses_is_empty(&od->lb_force_snat_addrs);
for (int i = 0; i < od->nbr->n_nat; i++) {
- const struct nbrec_nat *nat;
-
- nat = od->nbr->nat[i];
-
- ovs_be32 ip, mask;
- struct in6_addr ipv6, mask_v6, v6_exact = IN6ADDR_EXACT_INIT;
- bool is_v6 = false;
-
- if (nat->allowed_ext_ips && nat->exempted_ext_ips) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
- VLOG_WARN_RL(&rl, "NAT rule: "UUID_FMT" not applied, since "
- "both allowed and exempt external ips set",
- UUID_ARGS(&(nat->header_.uuid)));
- continue;
- }
-
- char *error = ip_parse_masked(nat->external_ip, &ip, &mask);
- if (error || mask != OVS_BE32_MAX) {
- free(error);
- error = ipv6_parse_masked(nat->external_ip, &ipv6, &mask_v6);
- if (error || memcmp(&mask_v6, &v6_exact, sizeof(mask_v6))) {
- /* Invalid for both IPv4 and IPv6 */
- static struct vlog_rate_limit rl =
- VLOG_RATE_LIMIT_INIT(5, 1);
- VLOG_WARN_RL(&rl, "bad external ip %s for nat",
- nat->external_ip);
- free(error);
- continue;
- }
- /* It was an invalid IPv4 address, but valid IPv6.
- * Treat the rest of the handling of this NAT rule
- * as IPv6. */
- is_v6 = true;
- }
-
- /* Check the validity of nat->logical_ip. 'logical_ip' can
- * be a subnet when the type is "snat". */
+ const struct nbrec_nat *nat = nat = od->nbr->nat[i];
+ struct eth_addr mac = eth_addr_broadcast;
+ bool is_v6, distributed;
+ ovs_be32 mask;
int cidr_bits;
- if (is_v6) {
- error = ipv6_parse_masked(nat->logical_ip, &ipv6, &mask_v6);
- cidr_bits = ipv6_count_cidr_bits(&mask_v6);
- } else {
- error = ip_parse_masked(nat->logical_ip, &ip, &mask);
- cidr_bits = ip_count_cidr_bits(mask);
- }
- if (!strcmp(nat->type, "snat")) {
- if (error) {
- /* Invalid for both IPv4 and IPv6 */
- static struct vlog_rate_limit rl =
- VLOG_RATE_LIMIT_INIT(5, 1);
- VLOG_WARN_RL(&rl, "bad ip network or ip %s for snat "
- "in router "UUID_FMT"",
- nat->logical_ip, UUID_ARGS(&od->key));
- free(error);
- continue;
- }
- } else {
- if (error || (!is_v6 && mask != OVS_BE32_MAX)
- || (is_v6 && memcmp(&mask_v6, &v6_exact,
- sizeof mask_v6))) {
- /* Invalid for both IPv4 and IPv6 */
- static struct vlog_rate_limit rl =
- VLOG_RATE_LIMIT_INIT(5, 1);
- VLOG_WARN_RL(&rl, "bad ip %s for dnat in router "
- ""UUID_FMT"", nat->logical_ip, UUID_ARGS(&od->key));
- free(error);
- continue;
- }
- }
- /* For distributed router NAT, determine whether this NAT rule
- * satisfies the conditions for distributed NAT processing. */
- bool distributed = false;
- struct eth_addr mac = eth_addr_broadcast;
- if (od->l3dgw_port && !strcmp(nat->type, "dnat_and_snat") &&
- nat->logical_port && nat->external_mac) {
- if (eth_addr_from_string(nat->external_mac, &mac)) {
- distributed = true;
- } else {
- static struct vlog_rate_limit rl =
- VLOG_RATE_LIMIT_INIT(5, 1);
- VLOG_WARN_RL(&rl, "bad mac %s for dnat in router "
- ""UUID_FMT"", nat->external_mac, UUID_ARGS(&od->key));
- continue;
- }
+ if (lrouter_check_nat_entry(od, nat, &mask, &is_v6, &cidr_bits,
+ &mac, &distributed) < 0) {
+ continue;
}
/* S_ROUTER_IN_UNSNAT */
--
2.29.2
More information about the dev
mailing list