From patchwork Tue Jun 30 21:42:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1320134 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=whitealder.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=ZiGJHrla; dkim-atps=neutral Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49xHrT0q2zz9sPF for ; Wed, 1 Jul 2020 07:42:17 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 9268188211; Tue, 30 Jun 2020 21:42:15 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TL0A49AudlgA; Tue, 30 Jun 2020 21:42:14 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 5961787742; Tue, 30 Jun 2020 21:42:14 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 4D0CAC0865; Tue, 30 Jun 2020 21:42:14 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 9E25BC016E for ; Tue, 30 Jun 2020 21:42:12 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 8B97E864EA for ; Tue, 30 Jun 2020 21:42:12 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id b1vM7cY-ae7Z for ; Tue, 30 Jun 2020 21:42:11 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) by fraxinus.osuosl.org (Postfix) with ESMTPS id BAA2986216 for ; Tue, 30 Jun 2020 21:42:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1593553330; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ndEO67jowHGTAHAMQPXn0uOV8kYXkiJxX2fh3PdFqGM=; b=ZiGJHrlaY51dUuNSJVXdM5c90bsF0XybvkS9gVXALU5H+47vWkOLNqCl90jC4usX7iMrgf uJJ2lXDLM1sD2hcp4gEovBEM7Rv5EJsnM0/V2+OTzTzwkt4XFsQ+fva68+gzBnkDKh7IJf 1nUZjxlUcyFN1JaR+R8aQ9wtL4iwA60= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-465-q8d_gZe-MpGrDB7C6S5Xeg-1; Tue, 30 Jun 2020 17:42:07 -0400 X-MC-Unique: q8d_gZe-MpGrDB7C6S5Xeg-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A0B16107ACCD; Tue, 30 Jun 2020 21:42:06 +0000 (UTC) Received: from dceara.remote.csb (ovpn-112-145.ams2.redhat.com [10.36.112.145]) by smtp.corp.redhat.com (Postfix) with ESMTP id B408D9CFF1; Tue, 30 Jun 2020 21:42:05 +0000 (UTC) From: Dumitru Ceara To: dev@openvswitch.org Date: Tue, 30 Jun 2020 23:42:03 +0200 Message-Id: <20200630214201.26800.53920.stgit@dceara.remote.csb> In-Reply-To: <20200630214107.26800.21305.stgit@dceara.remote.csb> References: <20200630214107.26800.21305.stgit@dceara.remote.csb> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=dceara@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: hzhou@ovn.org Subject: [ovs-dev] [PATCH v2 ovn 4/5] ovn-northd: Refactor NAT address parsing. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Store NAT entries pointers in ovn_datapath and pre-parse the external IP addresses. This simplifies the code and makes it easier to reuse the parsed external IP and solicited-node address without reparsing. Signed-off-by: Dumitru Ceara --- northd/ovn-northd.c | 115 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 30 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index fde9198..51ef532 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -608,6 +608,9 @@ struct ovn_datapath { * the "redirect-chassis". */ struct ovn_port *l3redirect_port; + /* NAT entries configured on the router. */ + struct ovn_nat *nat_entries; + struct ovn_port **localnet_ports; size_t n_localnet_ports; @@ -620,6 +623,65 @@ struct ovn_datapath { struct hmap nb_pgs; }; +/* Contains a NAT entry with the external addresses pre-parsed. */ +struct ovn_nat { + const struct nbrec_nat *nb; + struct lport_addresses ext_addrs; +}; + +/* Returns true if a 'nat_entry' is valid, i.e.: + * - parsing was successful. + * - the string yielded exactly one IPv4 address or exactly one IPv6 address. + */ +static bool nat_entry_is_valid(const struct ovn_nat *nat_entry) +{ + const struct lport_addresses *ext_addrs = &nat_entry->ext_addrs; + + return (ext_addrs->n_ipv4_addrs == 1 && ext_addrs->n_ipv6_addrs == 0) || + (ext_addrs->n_ipv4_addrs == 0 && ext_addrs->n_ipv6_addrs == 1); +} + +static bool nat_entry_is_v6(const struct ovn_nat *nat_entry) +{ + return nat_entry->ext_addrs.n_ipv6_addrs > 0; +} + +static void init_nat_entries(struct ovn_datapath *od) +{ + if (!od->nbr || od->nbr->n_nat == 0) { + return; + } + + od->nat_entries = xmalloc(od->nbr->n_nat * sizeof *od->nat_entries); + + for (size_t i = 0; i < od->nbr->n_nat; i++) { + const struct nbrec_nat *nat = od->nbr->nat[i]; + struct ovn_nat *nat_entry = &od->nat_entries[i]; + + nat_entry->nb = nat; + if (!extract_ip_addresses(nat->external_ip, + &nat_entry->ext_addrs) || + !nat_entry_is_valid(nat_entry)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + + VLOG_WARN_RL(&rl, + "Bad ip address %s in nat configuration " + "for router %s", nat->external_ip, od->nbr->name); + } + } +} + +static void destroy_nat_entries(struct ovn_datapath *od) +{ + if (!od->nbr) { + return; + } + + for (size_t i = 0; i < od->nbr->n_nat; i++) { + destroy_lport_addresses(&od->nat_entries[i].ext_addrs); + } +} + /* A group of logical router datapaths which are connected - either * directly or indirectly. * Each logical router can belong to only one group. */ @@ -677,6 +739,8 @@ ovn_datapath_destroy(struct hmap *datapaths, struct ovn_datapath *od) ovn_destroy_tnlids(&od->port_tnlids); bitmap_free(od->ipam_info.allocated_ipv4s); free(od->router_ports); + destroy_nat_entries(od); + free(od->nat_entries); free(od->localnet_ports); ovn_ls_port_group_destroy(&od->nb_pgs); destroy_mcast_info_for_datapath(od); @@ -1105,6 +1169,7 @@ join_datapaths(struct northd_context *ctx, struct hmap *datapaths, ovs_list_push_back(nb_only, &od->list); } init_mcast_info_for_datapath(od); + init_nat_entries(od); ovs_list_push_back(lr_list, &od->lr_list); } } @@ -8454,30 +8519,24 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, snat_ips[n_snat_ips++] = snat_ip; } - for (int i = 0; i < op->od->nbr->n_nat; i++) { - const struct nbrec_nat *nat; - - nat = op->od->nbr->nat[i]; + for (size_t i = 0; i < op->od->nbr->n_nat; i++) { + struct ovn_nat *nat_entry = &op->od->nat_entries[i]; + const struct nbrec_nat *nat = nat_entry->nb; - ovs_be32 ip; - struct in6_addr ipv6; - bool is_v6 = false; - if (!ip_parse(nat->external_ip, &ip) || !ip) { - if (!ipv6_parse(nat->external_ip, &ipv6)) { - static struct vlog_rate_limit rl = - VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "bad ip address %s in nat configuration " - "for router %s", nat->external_ip, op->key); - continue; - } - is_v6 = true; + /* Skip entries we failed to parse. */ + if (!nat_entry_is_valid(nat_entry)) { + continue; } if (!strcmp(nat->type, "snat")) { - if (is_v6) { + if (nat_entry_is_v6(nat_entry)) { + struct in6_addr *ipv6 = + &nat_entry->ext_addrs.ipv6_addrs[0].addr; + snat_ips[n_snat_ips].family = AF_INET6; - snat_ips[n_snat_ips++].ipv6 = ipv6; + snat_ips[n_snat_ips++].ipv6 = *ipv6; } else { + ovs_be32 ip = nat_entry->ext_addrs.ipv4_addrs[0].addr; snat_ips[n_snat_ips].family = AF_INET; snat_ips[n_snat_ips++].ipv4 = ip; } @@ -8520,22 +8579,18 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, } } } - if (is_v6) { - /* For ND solicitations, we need to listen for both the - * unicast IPv6 address and its all-nodes multicast address, - * but always respond with the unicast IPv6 address. */ - char sn_addr_s[INET6_ADDRSTRLEN + 1]; - struct in6_addr sn_addr; - in6_addr_solicited_node(&sn_addr, &ipv6); - ipv6_string_mapped(sn_addr_s, &sn_addr); + struct lport_addresses *ext_addrs = &nat_entry->ext_addrs; + if (nat_entry_is_v6(nat_entry)) { build_lrouter_nd_flow(op->od, op, "nd_na", - nat->external_ip, sn_addr_s, - mac_s, &match, 90, - lflows, &nat->header_); + ext_addrs->ipv6_addrs[0].addr_s, + ext_addrs->ipv6_addrs[0].sn_addr_s, + mac_s, &match, 90, + lflows, &nat->header_); } else { build_lrouter_arp_flow(op->od, op, - nat->external_ip, mac_s, &match, 90, + ext_addrs->ipv4_addrs[0].addr_s, + mac_s, &match, 90, lflows, &nat->header_); } }