On 11/13/23 13:34, Mohammad Heib wrote:
> 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 <[email protected]>
> ---
With a couple of minor changes (see below) I applied this to the main
branch. Thanks, Mohammad!
Regards,
Dumitru
> NEWS | 4 +++
> controller/pinctrl.c | 43 ++++++++++++++++++++++++++++-
> northd/northd.c | 13 +++++++++
> ovn-nb.ovsschema | 9 ++++--
> ovn-nb.xml | 14 ++++++++++
> ovn-sb.ovsschema | 9 ++++--
> ovn-sb.xml | 6 ++++
> tests/ovn.at | 65 ++++++++++++++++++++++++++++++++++++++++++++
> 8 files changed, 158 insertions(+), 5 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 30f6edb28..e10fb79dd 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,5 +1,9 @@
> 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.
> - Disable OpenFlow inactivity probing between ovn-controller and OVS.
> OF connection is established over unix socket, which is a reliable
> connection method and doesn't require additional probing.
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index d88e951a6..cf48089b6 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_supports_ovn_owned;
> };
>
> static struct pinctrl pinctrl;
> @@ -2713,6 +2714,7 @@ struct dns_data {
> uint64_t *dps;
> size_t n_dps;
> struct smap records;
> + struct smap options;
> bool delete;
> };
>
> @@ -2741,6 +2743,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;
> @@ -2755,6 +2758,12 @@ sync_dns_cache(const struct sbrec_dns_table *dns_table)
> smap_clone(&dns_data->records, &sbrec_dns->records);
> }
>
> + if (pinctrl.dns_supports_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++) {
> @@ -2767,6 +2776,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);
> }
> @@ -2781,6 +2791,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);
> }
> @@ -2854,6 +2865,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(
> @@ -2867,6 +2880,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_refuse = false;
>
> /* Parse result field. */
> const struct mf_field *f;
> @@ -2966,6 +2980,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;
> @@ -2978,6 +2993,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);
I moved this out of the inner loop.
> break;
> }
> }
> @@ -3024,10 +3040,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_refuse = true;
> + }
> +
> destroy_lport_addresses(&ip_addrs);
> }
>
> - if (!ancount) {
> + if (!ancount && !send_refuse) {
> ofpbuf_uninit(&dns_answer);
> goto exit;
> }
> @@ -3062,6 +3090,10 @@ pinctrl_handle_dns_lookup(
>
> /* Set the answer RRs. */
> out_dns_header->ancount = htons(ancount);
> + if (send_refuse) {
> + /* set RCODE = 5 (server refuses). */
> + out_dns_header->hi_flag |= DNS_RCODE_SERVER_REFUSE;
> + }
> out_dns_header->arcount = 0;
>
> /* Copy the Query section. */
> @@ -3530,6 +3562,15 @@ pinctrl_update(const struct ovsdb_idl *idl, const char
> *br_int_name)
> notify_pinctrl_handler();
> }
>
> + bool dns_supports_ovn_owned =
> sbrec_server_has_dns_table_col_options(idl);
> + if (dns_supports_ovn_owned != pinctrl.dns_supports_ovn_owned) {
> + pinctrl.dns_supports_ovn_owned = dns_supports_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 f8b046d83..e93d0c8f8 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -17301,6 +17301,19 @@ sync_dns_entries(struct ovsdb_idl_txn *ovnsb_txn,
> free(dns_id);
> }
>
> + /* Copy DNS options to SB*/
> + struct smap options = SMAP_INITIALIZER(&options);
> + if (!smap_is_empty(&dns_info->sb_dns->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);
> + smap_destroy(&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
> <p><b>Example: </b> "4.0.0.10.in-addr.arpa" = "vm1.ovn.org"</p>
> </column>
>
> + <column name="options" key="ovn-owned">
> + If set to true, then the OVN will be the main responsible for
> + <code>DNS Records</code> within this Table.
> +
> + <p> A <code>DNS Table</code> with this option set to <code>true</code>
> + 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.</p>
I fixed up indentation here.
> + </column>
> +
> <column name="external_ids">
> See <em>External IDs</em> at the beginning of this document.
> </column>
> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
> index a512e00e5..72e230b75 100644
> --- a/ovn-sb.ovsschema
> +++ b/ovn-sb.ovsschema
> @@ -1,7 +1,7 @@
> {
> "name": "OVN_Southbound",
> - "version": "20.29.0",
> - "cksum": "3967183656 30959",
> + "version": "20.30.0",
> + "cksum": "2972392849 31172",
> "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 8d0bed94d..e581d6965 100644
> --- a/ovn-sb.xml
> +++ b/ovn-sb.xml
> @@ -4500,6 +4500,12 @@ tcp.flags = RST;
> in this column.
> </column>
>
> + <column name="options" key="ovn-owned">
> + This column indicates that all the <code>Domains</code> in this table
> + are owned by OVN, and all <code>DNS queries</code> for those domains
> + will be answered locally by either an IP address or
> + <code>DNS rejection</code>.
> +</column>
> <group title="Common Columns">
> <column name="external_ids">
> See <em>External IDs</em> at the beginning of this document.
> diff --git a/tests/ovn.at b/tests/ovn.at
> index b8c61f87f..543eca9d0 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -11281,6 +11281,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
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev