From patchwork Sun Oct 1 19:27:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mohammad Heib X-Patchwork-Id: 1841810 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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=hcMWyCPi; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RzDcW65zZz1yng for ; Mon, 2 Oct 2023 06:27:23 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 3B36C60ED6; Sun, 1 Oct 2023 19:27:21 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 3B36C60ED6 Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=hcMWyCPi X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zlrBHOPWhjLG; Sun, 1 Oct 2023 19:27:19 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id D52C560B0E; Sun, 1 Oct 2023 19:27:18 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org D52C560B0E Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id B59F3C0039; Sun, 1 Oct 2023 19:27:18 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0217BC0032 for ; Sun, 1 Oct 2023 19:27:17 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id C8D5760B0E for ; Sun, 1 Oct 2023 19:27:16 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org C8D5760B0E X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id gTkPyOgWWwXo for ; Sun, 1 Oct 2023 19:27:14 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id 98A4E605B5 for ; Sun, 1 Oct 2023 19:27:14 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 98A4E605B5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1696188433; 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; bh=P77AT449ZS84Pti4t3k5j1tvPWpmFm08QxZZKsNZEKc=; b=hcMWyCPi9pS4Y+g05zkW8BR6b4IrUU0Hp3lBuvWzQCx2rePdoDjTthUPhqnfY2N4W1TvMg TwUCBF6qB0QvgeBcFcg2Uca89v3i4bBcqCWzeO28b7rea6qvDSA/YqbTjuDRS+RE0Wt0tS E9gxgCof7jA+h3gO7sIxku7O9mAnG7c= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-92-itfftKDFNXyhWTtghQCgcw-1; Sun, 01 Oct 2023 15:27:09 -0400 X-MC-Unique: itfftKDFNXyhWTtghQCgcw-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6E3AE101A53B for ; Sun, 1 Oct 2023 19:27:09 +0000 (UTC) Received: from mheiblap.localdomain.com (unknown [10.47.238.13]) by smtp.corp.redhat.com (Postfix) with ESMTP id 62432492B16; Sun, 1 Oct 2023 19:27:08 +0000 (UTC) From: Mohammad Heib To: dev@openvswitch.org Date: Sun, 1 Oct 2023 22:27:04 +0300 Message-Id: <20231001192704.3107450-1-mheib@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.9 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn] DNS: allow defining records that owned by OVN only 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" Currently OVN allows users to create DNS records and define domains within these records. These domains can be associated with IPV4 or IPv6 or both, when the user creates a domain with both IPv4 and IPv6 ovn will answer each query for this domain immediately and everything works as expected. But if the user only creates a domain with only IPv4 or IPv6 this will cause the DNS queries respond take longer than the usual since OVN will forward query and user will keep waiting for an answer until someone else replies for this query or timeout occur. The above behavior is a bit problematic if the user knows that this domain is only configured in OVN we should not forward queries for this domain to the outside. This patch adds an option:ovn-owned for the DNS table that can be set to "true" when creating a DNS. When setting this option to "true" all the domains within this table will be treated as local domains only, and queries for domains within this table that don't have an accurate IP will be refused immediately to save the time of waiting for timeout. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1946662 Signed-off-by: Mohammad Heib --- NEWS | 5 ++++ controller/pinctrl.c | 47 ++++++++++++++++++++++++++++++-- northd/northd.c | 11 ++++++++ ovn-nb.ovsschema | 9 ++++-- ovn-nb.xml | 14 ++++++++++ ovn-sb.ovsschema | 9 ++++-- ovn-sb.xml | 6 ++++ tests/ovn.at | 65 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 160 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 425dfe0a8..465649430 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ Post v23.09.0 ------------- + - DNS now have an "options" column for configuration of extra options. + - A new DNS option "ovn-owned" has been added to allow defining domains + that are owned only by ovn, queries for that domain will not be processed + externally. + OVN v23.09.0 - 15 Sep 2023 -------------------------- diff --git a/controller/pinctrl.c b/controller/pinctrl.c index ff5a3444c..e1e558595 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -179,6 +179,7 @@ struct pinctrl { struct latch pinctrl_thread_exit; bool mac_binding_can_timestamp; bool fdb_can_timestamp; + bool dns_can_ovn_owned; }; static struct pinctrl pinctrl; @@ -2709,6 +2710,7 @@ struct dns_data { uint64_t *dps; size_t n_dps; struct smap records; + struct smap options; bool delete; }; @@ -2737,6 +2739,7 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) if (!dns_data) { dns_data = xmalloc(sizeof *dns_data); smap_init(&dns_data->records); + smap_init(&dns_data->options); shash_add(&dns_cache, dns_id, dns_data); dns_data->n_dps = 0; dns_data->dps = NULL; @@ -2751,6 +2754,12 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) smap_clone(&dns_data->records, &sbrec_dns->records); } + if (pinctrl.dns_can_ovn_owned + && !smap_equal(&dns_data->options, &sbrec_dns->options)) { + smap_destroy(&dns_data->options); + smap_clone(&dns_data->options, &sbrec_dns->options); + } + dns_data->n_dps = sbrec_dns->n_datapaths; dns_data->dps = xcalloc(dns_data->n_dps, sizeof(uint64_t)); for (size_t i = 0; i < sbrec_dns->n_datapaths; i++) { @@ -2763,6 +2772,7 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table) if (d->delete) { shash_delete(&dns_cache, iter); smap_destroy(&d->records); + smap_destroy(&d->options); free(d->dps); free(d); } @@ -2777,6 +2787,7 @@ destroy_dns_cache(void) struct dns_data *d = iter->data; shash_delete(&dns_cache, iter); smap_destroy(&d->records); + smap_destroy(&d->options); free(d->dps); free(d); } @@ -2850,6 +2861,8 @@ dns_build_ptr_answer( free(encoded); } +#define DNS_RCODE_SERVER_REFUSE 0x5 + /* Called with in the pinctrl_handler thread context. */ static void pinctrl_handle_dns_lookup( @@ -2863,6 +2876,7 @@ pinctrl_handle_dns_lookup( enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version); struct dp_packet *pkt_out_ptr = NULL; uint32_t success = 0; + bool send_query_rejection = false; /* Parse result field. */ const struct mf_field *f; @@ -2962,6 +2976,7 @@ pinctrl_handle_dns_lookup( uint64_t dp_key = ntohll(pin->flow_metadata.flow.metadata); const char *answer_data = NULL; + bool ovn_owned = false; struct shash_node *iter; SHASH_FOR_EACH (iter, &dns_cache) { struct dns_data *d = iter->data; @@ -2974,6 +2989,7 @@ pinctrl_handle_dns_lookup( answer_data = smap_get(&d->records, query_name_lower); free(query_name_lower); if (answer_data) { + ovn_owned = smap_get_bool(&d->options, "ovn-owned", false); break; } } @@ -3020,10 +3036,22 @@ pinctrl_handle_dns_lookup( ancount++; } } + + /* DNS is configured with a record for this domain with + * an IPv4/IPV6 only, so instead of ignoring this A/AAAA query, + * we can reply with RCODE = 5 (server refuses) and that + * will speed up the DNS process by not letting the customer + * wait for a timeout. + */ + if (ovn_owned && (query_type == DNS_QUERY_TYPE_AAAA || + query_type == DNS_QUERY_TYPE_A) && !ancount) { + send_query_rejection = true; + } + destroy_lport_addresses(&ip_addrs); } - if (!ancount) { + if (!ancount && !send_query_rejection) { ofpbuf_uninit(&dns_answer); goto exit; } @@ -3058,13 +3086,19 @@ pinctrl_handle_dns_lookup( /* Set the answer RRs. */ out_dns_header->ancount = htons(ancount); + if (send_query_rejection) { + /* set RCODE = 5 (server refuses). */ + out_dns_header->hi_flag |= DNS_RCODE_SERVER_REFUSE; + } out_dns_header->arcount = 0; /* Copy the Query section. */ dp_packet_put(&pkt_out, dp_packet_data(pkt_in), dp_packet_size(pkt_in)); /* Copy the answer sections. */ - dp_packet_put(&pkt_out, dns_answer.data, dns_answer.size); + if (!send_query_rejection) { + dp_packet_put(&pkt_out, dns_answer.data, dns_answer.size); + } ofpbuf_uninit(&dns_answer); out_udp->udp_len = htons(new_l4_size); @@ -3521,6 +3555,15 @@ pinctrl_update(const struct ovsdb_idl *idl, const char *br_int_name) notify_pinctrl_handler(); } + bool dns_can_ovn_owned = sbrec_server_has_dns_table_col_options(idl); + if (dns_can_ovn_owned != pinctrl.dns_can_ovn_owned) { + pinctrl.dns_can_ovn_owned = dns_can_ovn_owned; + + /* Notify pinctrl_handler that fdb timestamp column + * availability has changed. */ + notify_pinctrl_handler(); + } + ovs_mutex_unlock(&pinctrl_mutex); } diff --git a/northd/northd.c b/northd/northd.c index 528027d07..70a2922f2 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -17196,6 +17196,17 @@ sync_dns_entries(struct ovsdb_idl_txn *ovnsb_txn, free(dns_id); } + + /* Copy DNS options to SB*/ + struct smap options; + smap_clone(&options, &dns_info->sb_dns->options); + + bool ovn_owned = smap_get_bool(&dns_info->nb_dns->options, + "ovn-owned", false); + smap_replace(&options, "ovn-owned", + ovn_owned? "true" : "false"); + sbrec_dns_set_options(dns_info->sb_dns, &options); + /* Set the datapaths and records. If nothing has changed, then * this will be a no-op. */ diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema index e103360ec..b2e0993e0 100644 --- a/ovn-nb.ovsschema +++ b/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "7.1.0", - "cksum": "217362582 33949", + "version": "7.2.0", + "cksum": "1069338687 34162", "tables": { "NB_Global": { "columns": { @@ -560,6 +560,11 @@ "value": "string", "min": 0, "max": "unlimited"}}, + "options": { + "type": {"key": "string", + "value": "string", + "min": 0, + "max": "unlimited"}}, "external_ids": {"type": {"key": "string", "value": "string", "min": 0, diff --git a/ovn-nb.xml b/ovn-nb.xml index 1de0c3041..4aa8107a5 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -4542,6 +4542,20 @@ or

Example: "4.0.0.10.in-addr.arpa" = "vm1.ovn.org"

+ + If set to true, then the OVN will be the main responsible for + DNS Records within this Table. + +

A DNS Table with this option set to true + can be created for domains that the user needs to configure + locally and don't care about IPv6 only interested in IPv4 or + vice versa. + + This will let ovn send IPv4 DNS reply and reject/ignore IPv6 + queries to save the waiting for a timeout on those uninteresting + queries.

+
+ See External IDs at the beginning of this document. diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index 7b20aa21b..b5a16d231 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "20.27.4", - "cksum": "3194181501 30531", + "version": "20.28.0", + "cksum": "160983021 30744", "tables": { "SB_Global": { "columns": { @@ -363,6 +363,11 @@ "refTable": "Datapath_Binding"}, "min": 1, "max": "unlimited"}}, + "options": { + "type": {"key": "string", + "value": "string", + "min": 0, + "max": "unlimited"}}, "external_ids": {"type": {"key": "string", "value": "string", "min": 0, diff --git a/ovn-sb.xml b/ovn-sb.xml index 46aedf973..55fcf59b2 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -4500,6 +4500,12 @@ tcp.flags = RST; in this column. + + This column indicates that all the Domains in this table + are owned by OVN, and all DNS queries for those domains + will be answered locally by either an IP address or + DNS rejection. + See External IDs at the beginning of this document. diff --git a/tests/ovn.at b/tests/ovn.at index dfe535f36..88357fd33 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -11302,6 +11302,71 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected +# send AAAA query for a server known domain that don't have +# any IPV6 address associated with this domain, and expected +# server refused DNS reply to save the sender time of waiting for timeout. +AS_BOX([Test IPv6 (AAAA records) NO timeout.]) +# Add back the DNS options for ls1-lp1 without ipv6. +check ovn-nbctl remove DNS $DNS1 records vm1.ovn.org +check ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4" +check ovn-nbctl --wait=hv set DNS $DNS1 options:ovn-owned=true +ovn-sbctl list DNS > dns6 +AT_CAPTURE_FILE([dns6]) +ovn-sbctl dump-flows > sbflows6 +AT_CAPTURE_FILE([sbflows6]) + +set_dns_params vm1_ipv6_only +src_ip=`ip_to_hex 10 0 0 6` +dst_ip=`ip_to_hex 10 0 0 1` +dns_reply=1 +test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data + +# NXT_RESUMEs should be 13. +OVS_WAIT_UNTIL([test 13 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets +# dns hdr with server refuse RCODE +echo "01028125" > expout +#only check for the DNS HDR flags since we are not getting any DNS answer +AT_CHECK([cat 2.packets | cut -c -92 | cut -c 85-], [0], [expout]) + +reset_pcap_file hv1-vif1 hv1/vif1 +reset_pcap_file hv1-vif2 hv1/vif2 +rm -f 1.expected +rm -f 2.expected + +# send A query for a server known domain that don't have +# any IPv4 address associated with this domain, and expected +# server refused DNS reply to save the sender time of waiting for timeout. +AS_BOX([Test IPv4 (A records) NO timeout.]) +# Add back the DNS options for ls1-lp1 without ipv4. +check ovn-nbctl remove DNS $DNS1 records vm1.ovn.org +check ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="aef0::4" +check ovn-nbctl --wait=hv set DNS $DNS1 options:ovn-owned=true +ovn-sbctl list DNS > dns7 +AT_CAPTURE_FILE([dns7]) +ovn-sbctl dump-flows > sbflows7 +AT_CAPTURE_FILE([sbflows7]) + +set_dns_params vm1 +src_ip=`ip_to_hex 10 0 0 6` +dst_ip=`ip_to_hex 10 0 0 1` +dns_reply=1 +test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data + +# NXT_RESUMEs should be 14. +OVS_WAIT_UNTIL([test 14 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets +# dns hdr with server refuse RCODE +echo "01028125" > expout +#only check for the DNS HDR flags since we are not getting any DNS answer +AT_CHECK([cat 2.packets | cut -c -92 | cut -c 85-], [0], [expout]) + +reset_pcap_file hv1-vif1 hv1/vif1 +reset_pcap_file hv1-vif2 hv1/vif2 +rm -f 1.expected +rm -f 2.expected OVN_CLEANUP([hv1]) AT_CLEANUP