On Tue, Sep 15, 2026 at 11:06 AM Dumitru Ceara via dev < [email protected]> wrote:
> OVN's native DNS responder answered every A/AAAA/ANY/PTR query with a > hardcoded resource-record TTL of 3600 seconds. In dynamic environments > caching a DNS response for 1h is probably not desirable, in any case > it's better if the TTL is operator configurable. > > Add a per-row "options:ttl" key on the NB DNS table. ovn-northd > validates the value in sync_dns_entries() and, like the existing > "ovn-owned" option, propagates it to the SB DNS table. ovn-controller > reads the option back and uses it when building DNS replies for > that record. > > The default remains 3600 seconds. > > Reported-at: https://redhat.atlassian.net/browse/FDP-2956 > Assisted-by: Qwen3.8-27B-FP8, opencode > Signed-off-by: Dumitru Ceara <[email protected]> > --- NEWS | 2 + > controller/ovn-dns.c | 7 ++- > controller/ovn-dns.h | 2 +- > controller/pinctrl.c | 27 +++++---- > lib/ovn-l7.h | 1 + > northd/northd.c | 22 +++++++ > ovn-nb.xml | 14 +++++ > ovn-sb.xml | 9 +++ > tests/ovn-northd.at | 60 +++++++++++++++++++ > tests/ovn.at | 138 +++++++++++++++++++++++++++++++++++++++++++ > 10 files changed, 268 insertions(+), 14 deletions(-) > > diff --git a/NEWS b/NEWS > index aadf6416d2..f1c56dd147 100644 > --- a/NEWS > +++ b/NEWS > @@ -1,5 +1,7 @@ > Post v26.09.0 > -------------- > + - Added a new "options:ttl" key on the NB DNS table to make the TTL of > + DNS replies from OVN's native DNS resolver configurable per row. > - Removed implementations of the commit_ecmp_nh, chk_ecmp_nh, and > chk_ecmp_nh_mac actions from the code. > - Mark tunnel ports as transient (other_config:transient=true) when the > diff --git a/controller/ovn-dns.c b/controller/ovn-dns.c > index bfeef5a747..416f399d78 100644 > --- a/controller/ovn-dns.c > +++ b/controller/ovn-dns.c > @@ -22,6 +22,7 @@ > #include "openvswitch/vlog.h" > > /* OVN includes. */ > +#include "lib/ovn-l7.h" > #include "lib/ovn-sb-idl.h" > #include "ovn-dns.h" > > @@ -112,12 +113,14 @@ ovn_dns_update_cache(const struct sbrec_dns_table > *dns_table) > } > > const char * > -ovn_dns_lookup(const char *query_name, uint64_t dp_key, bool *ovn_owned) > +ovn_dns_lookup(const char *query_name, uint64_t dp_key, bool *ovn_owned, > + uint32_t *ttl) > { > const char *answer_data = NULL; > struct dns_data *dns_data; > > *ovn_owned = false; > + *ttl = DNS_DEFAULT_RR_TTL; > > CMAP_FOR_EACH (dns_data, cmap_node, &dns_cache_) { > for (size_t i = 0; i < dns_data->n_dps; i++) { > @@ -131,6 +134,8 @@ ovn_dns_lookup(const char *query_name, uint64_t > dp_key, bool *ovn_owned) > if (answer_data) { > *ovn_owned = smap_get_bool(&dns_data->options, > "ovn-owned", > false); > + *ttl = smap_get_uint(&dns_data->options, "ttl", > + DNS_DEFAULT_RR_TTL); > break; > } > } > diff --git a/controller/ovn-dns.h b/controller/ovn-dns.h > index 8eca6ad0eb..6c86ccc858 100644 > --- a/controller/ovn-dns.h > +++ b/controller/ovn-dns.h > @@ -24,6 +24,6 @@ void ovn_dns_cache_destroy(void); > void ovn_dns_sync_cache(const struct sbrec_dns_table *); > void ovn_dns_update_cache(const struct sbrec_dns_table *); > const char *ovn_dns_lookup(const char *query_name, uint64_t dp_key, > - bool *ovn_owned); > + bool *ovn_owned, uint32_t *ttl); > > #endif /* OVN_DNS_H */ > diff --git a/controller/pinctrl.c b/controller/pinctrl.c > index 333dcedb6e..e100912510 100644 > --- a/controller/pinctrl.c > +++ b/controller/pinctrl.c > @@ -3394,22 +3394,22 @@ put_be32(struct ofpbuf *buf, ovs_be32 x) > static void > dns_build_base_answer( > struct ofpbuf *dns_answer, const uint8_t *in_queryname, > - uint16_t query_length, int query_type) > + uint16_t query_length, int query_type, uint32_t ttl) > { > ofpbuf_put(dns_answer, in_queryname, query_length); > put_be16(dns_answer, htons(query_type)); > put_be16(dns_answer, htons(DNS_CLASS_IN)); > - put_be32(dns_answer, htonl(DNS_DEFAULT_RR_TTL)); > + put_be32(dns_answer, htonl(ttl)); > } > > /* Populates dns_answer struct with a TYPE A answer. */ > static void > dns_build_a_answer( > struct ofpbuf *dns_answer, const uint8_t *in_queryname, > - uint16_t query_length, const ovs_be32 addr) > + uint16_t query_length, const ovs_be32 addr, uint32_t ttl) > { > dns_build_base_answer(dns_answer, in_queryname, query_length, > - DNS_QUERY_TYPE_A); > + DNS_QUERY_TYPE_A, ttl); > put_be16(dns_answer, htons(sizeof(ovs_be32))); > put_be32(dns_answer, addr); > } > @@ -3418,10 +3418,10 @@ dns_build_a_answer( > static void > dns_build_aaaa_answer( > struct ofpbuf *dns_answer, const uint8_t *in_queryname, > - uint16_t query_length, const struct in6_addr *addr) > + uint16_t query_length, const struct in6_addr *addr, uint32_t ttl) > { > dns_build_base_answer(dns_answer, in_queryname, query_length, > - DNS_QUERY_TYPE_AAAA); > + DNS_QUERY_TYPE_AAAA, ttl); > put_be16(dns_answer, htons(sizeof(*addr))); > ofpbuf_put(dns_answer, addr, sizeof(*addr)); > } > @@ -3430,10 +3430,10 @@ dns_build_aaaa_answer( > static void > dns_build_ptr_answer( > struct ofpbuf *dns_answer, const uint8_t *in_queryname, > - uint16_t query_length, const char *answer_data) > + uint16_t query_length, const char *answer_data, uint32_t ttl) > { > dns_build_base_answer(dns_answer, in_queryname, query_length, > - DNS_QUERY_TYPE_PTR); > + DNS_QUERY_TYPE_PTR, ttl); > > size_t encoded_len = 0; > char *encoded = encode_fqdn_string(answer_data, &encoded_len); > @@ -3586,8 +3586,9 @@ pinctrl_handle_dns_lookup( > > uint64_t dp_key = ntohll(pin->flow_metadata.flow.metadata); > bool ovn_owned = false; > + uint32_t ttl = DNS_DEFAULT_RR_TTL; > const char *answer_data = ovn_dns_lookup(ds_cstr(&query_name), dp_key, > - &ovn_owned); > + &ovn_owned, &ttl); > ds_destroy(&query_name); > if (!answer_data) { > COVERAGE_INC(dns_cache_miss); > @@ -3601,7 +3602,8 @@ pinctrl_handle_dns_lookup( > struct ofpbuf dns_answer = OFPBUF_STUB_INITIALIZER(dns_ans_stub); > > if (query_type == DNS_QUERY_TYPE_PTR) { > - dns_build_ptr_answer(&dns_answer, in_queryname, idx, answer_data); > + dns_build_ptr_answer(&dns_answer, in_queryname, idx, answer_data, > + ttl); > ancount++; > } else { > struct lport_addresses ip_addrs; > @@ -3617,7 +3619,7 @@ pinctrl_handle_dns_lookup( > query_type == DNS_QUERY_TYPE_ANY) { > for (size_t i = 0; i < ip_addrs.n_ipv4_addrs; i++) { > ovs_be32 addr = ip_addrs.ipv4_addrs[ipv4_order[i]].addr; > - dns_build_a_answer(&dns_answer, in_queryname, idx, addr); > + dns_build_a_answer(&dns_answer, in_queryname, idx, addr, > ttl); > ancount++; > } > } > @@ -3627,7 +3629,8 @@ pinctrl_handle_dns_lookup( > for (size_t i = 0; i < ip_addrs.n_ipv6_addrs; i++) { > struct in6_addr *addr = > &ip_addrs.ipv6_addrs[ipv6_order[i]].addr; > - dns_build_aaaa_answer(&dns_answer, in_queryname, idx, > addr); > + dns_build_aaaa_answer(&dns_answer, in_queryname, idx, > addr, > + ttl); > ancount++; > } > } > diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h > index 5f52e1791f..58b8a4a1c3 100644 > --- a/lib/ovn-l7.h > +++ b/lib/ovn-l7.h > @@ -52,6 +52,7 @@ BUILD_ASSERT_DECL(BFD_PACKET_LEN == sizeof(struct > bfd_msg)); > > #define DNS_CLASS_IN 0x01 > #define DNS_DEFAULT_RR_TTL 3600 > +#define DNS_MAX_RR_TTL 2147483647U /* 2^31-1, per RFC 2181. */ > > /* Generic options map which is used to store dhcpv4 opts and dhcpv6 > opts. */ > struct gen_opts_map { > diff --git a/northd/northd.c b/northd/northd.c > index 1c9e5d0703..a0b90646f0 100644 > --- a/northd/northd.c > +++ b/northd/northd.c > @@ -21618,6 +21618,28 @@ sync_dns_entries(struct ovsdb_idl_txn *ovnsb_txn, > "ovn-owned", false); > smap_replace(&options, "ovn-owned", > ovn_owned? "true" : "false"); > + > + /* Sync the per-row TTL option to SB. Only values in the range > + * 0..DNS_MAX_RR_TTL are valid. > + */ > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); > + const char *ttl = smap_get(&dns_info->nb_dns->options, "ttl"); > + if (ttl) { > + unsigned int ttl_val; > + if (str_to_uint(ttl, 10, &ttl_val) && ttl_val <= > DNS_MAX_RR_TTL) { > + smap_replace(&options, "ttl", ttl); > + } else { > + VLOG_WARN_RL(&rl, "Ignoring invalid \"options:ttl\" %s " > + "(expected 0-%"PRIu32") for DNS record " > + UUID_FMT, ttl, DNS_MAX_RR_TTL, > + > UUID_ARGS(&dns_info->nb_dns->header_.uuid)); > + smap_remove(&options, "ttl"); > + } > + } else { > + /* Remove any stale value so the default TTL is used. */ > + smap_remove(&options, "ttl"); > + } > + > sbrec_dns_set_options(dns_info->sb_dns, &options); > smap_destroy(&options); > > diff --git a/ovn-nb.xml b/ovn-nb.xml > index 57b81d4b44..078bd60687 100644 > --- a/ovn-nb.xml > +++ b/ovn-nb.xml > @@ -6464,6 +6464,20 @@ or > </p> > </column> > > + <column name="options" key="ttl"> > + The time-to-live (in seconds) set in the TTL field of DNS replies > + generated by OVN for the records in this row. > + > + <p> > + The default is <code>3600</code> seconds. Set this to a smaller > + value in dynamic environments (e.g. VM fail-over) so that > + clients do not cache stale records for long. Valid values are 0 > + to 2147483647 <(214)%20748-3647> (inclusive). An invalid or > out-of-range value is > + rejected with a warning by ovn-northd and the default of 3600 > + seconds is used instead. > + </p> > + </column> > + > <column name="external_ids"> > See <em>External IDs</em> at the beginning of this document. > </column> > diff --git a/ovn-sb.xml b/ovn-sb.xml > index 808694fe0a..2096fc3e3c 100644 > --- a/ovn-sb.xml > +++ b/ovn-sb.xml > @@ -5015,6 +5015,15 @@ tcp.flags = RST; > will be answered locally by either an IP address or > <code>DNS rejection</code>. > </column> > + > + <column name="options" key="ttl"> > + The time-to-live (in seconds) set in the TTL field of DNS replies > for > + the records in this row. This is synced automatically by ovn-northd > + from the corresponding > + <ref table="DNS" column="options" key="ttl" db="OVN_Northbound"/> > + option and should not be set directly. > + </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-northd.at b/tests/ovn-northd.at > index af231fb871..7d9bd68541 100644 > --- a/tests/ovn-northd.at > +++ b/tests/ovn-northd.at > @@ -12354,6 +12354,66 @@ wait_row_count sb:DNS 0 > AT_CLEANUP > ]) > > +OVN_FOR_EACH_NORTHD_NO_HV([ > +AT_SETUP([DNS options:ttl synchronization to SB]) > +ovn_start > + > +check ovn-nbctl ls-add sw0 > +dns_uuid=$(ovn-nbctl create DNS records={}) > +check ovn-nbctl set DNS $dns_uuid records:vm1.ovn.org="10.0.0.4" > +check ovn-nbctl set Logical_Switch sw0 dns_records="$dns_uuid" > +check ovn-nbctl --wait=sb sync > + > +wait_row_count sb:DNS 1 > +sb_dns_uuid=$(fetch_column sb:DNS _uuid) > + > +# Without "options:ttl", the key is not present in SB. > +AT_CHECK([test -z "$(ovn-sbctl --if-exists get DNS $sb_dns_uuid > options:ttl)"]) > + > +# Valid values are synced to SB, including the boundary values 0 and the > +# RFC 2181 maximum of 2147483647 <(214)%20748-3647>. > +check ovn-nbctl --wait=sb set DNS $dns_uuid options:ttl=30 > +AT_CHECK([ovn-sbctl get DNS $sb_dns_uuid options:ttl], [0], [dnl > +"30" > +]) > + > +check ovn-nbctl --wait=sb set DNS $dns_uuid options:ttl=0 > +AT_CHECK([ovn-sbctl get DNS $sb_dns_uuid options:ttl], [0], [dnl > +"0" > +]) > + > +check ovn-nbctl --wait=sb set DNS $dns_uuid options:ttl=2147483647 > <(214)%20748-3647> > +AT_CHECK([ovn-sbctl get DNS $sb_dns_uuid options:ttl], [0], [dnl > +"2147483647 <(214)%20748-3647>" > +]) > + > +# Invalid values are rejected and the key is removed from SB. > +check ovn-nbctl --wait=sb set DNS $dns_uuid options:ttl=garbage > +AT_CHECK([test -z "$(ovn-sbctl --if-exists get DNS $sb_dns_uuid > options:ttl)"]) > + > +check ovn-nbctl --wait=sb set DNS $dns_uuid options:ttl=-5 > +AT_CHECK([test -z "$(ovn-sbctl --if-exists get DNS $sb_dns_uuid > options:ttl)"]) > + > +# A value above the 2^31-1 cap is out of range and rejected. > +check ovn-nbctl --wait=sb set DNS $dns_uuid options:ttl=2147483648 > <(214)%20748-3648> > +AT_CHECK([test -z "$(ovn-sbctl --if-exists get DNS $sb_dns_uuid > options:ttl)"]) > + > +# A value that overflows the 32-bit unsigned range is rejected as well. > +check ovn-nbctl --wait=sb set DNS $dns_uuid options:ttl=99999999999 > +AT_CHECK([test -z "$(ovn-sbctl --if-exists get DNS $sb_dns_uuid > options:ttl)"]) > + > +# Removing the option clears any previously synced value. > +check ovn-nbctl --wait=sb set DNS $dns_uuid options:ttl=30 > +AT_CHECK([ovn-sbctl get DNS $sb_dns_uuid options:ttl], [0], [dnl > +"30" > +]) > +check ovn-nbctl --wait=sb remove DNS $dns_uuid options ttl > +AT_CHECK([test -z "$(ovn-sbctl --if-exists get DNS $sb_dns_uuid > options:ttl)"]) > + > +OVN_CLEANUP_NORTHD > +AT_CLEANUP > +]) > + > OVN_FOR_EACH_NORTHD_NO_HV([ > AT_SETUP([ACL/Meter incremental processing - no northd recompute]) > ovn_start > diff --git a/tests/ovn.at b/tests/ovn.at > index 8acfecb7bc..7f823de1da 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -12677,6 +12677,144 @@ OVN_CLEANUP([hv1]) > AT_CLEANUP > ]) > > +OVN_FOR_EACH_NORTHD([ > +AT_SETUP([dns lookup : configurable TTL]) > +CHECK_SCAPY > +ovn_start > + > +check ovn-nbctl ls-add ls \ > + -- lsp-add ls lsp \ > + -- lsp-set-addresses lsp "00:00:00:00:00:01 10.0.0.1" > + > +d=$(ovn-nbctl create DNS records={}) > +check ovn-nbctl set DNS $d records:foo.ovn.org="10.0.0.42 aef0::42" > +check ovn-nbctl set DNS $d records:42.0.0.10.in-addr.arpa="foo.ovn.org" > +check ovn-nbctl set Logical_switch ls dns_records="$d" > + > +net_add n1 > +sim_add hv1 > + > +as hv1 > +ovs-vsctl add-br br-phys > +ovn_attach n1 br-phys 192.168.0.1 > +check ovs-vsctl add-port br-int hv1-vif1 -- \ > + set interface hv1-vif1 external-ids:iface-id=lsp \ > + options:tx_pcap=hv1/vif1-tx.pcap \ > + options:rxq_pcap=hv1/vif1-rx.pcap > + > +OVN_POPULATE_ARP > +wait_for_ports_up > +check ovn-nbctl --wait=hv sync > + > +dns_req_a=$(fmt_pkt "Ether(dst='00:00:00:00:00:02', > src='00:00:00:00:00:01') / \ > + IP(dst='10.0.0.254', src='10.0.0.1') / \ > + UDP(sport=42424, dport=53) / \ > + DNS(rd=1, qd=DNSQR(qname='foo.ovn.org', qtype='A'))") > +dns_req_aaaa=$(fmt_pkt "Ether(dst='00:00:00:00:00:02', > src='00:00:00:00:00:01') / \ > + IP(dst='10.0.0.254', src='10.0.0.1') / \ > + UDP(sport=42424, dport=53) / \ > + DNS(rd=1, qd=DNSQR(qname='foo.ovn.org', > qtype='AAAA'))") > +dns_req_ptr=$(fmt_pkt "Ether(dst='00:00:00:00:00:02', > src='00:00:00:00:00:01') / \ > + IP(dst='10.0.0.254', src='10.0.0.1') / \ > + UDP(sport=42424, dport=53) / \ > + DNS(rd=1, qd=DNSQR(qname='42.0.0.10.in-addr.arpa', > qtype='PTR'))") > +dns_req_any=$(fmt_pkt "Ether(dst='00:00:00:00:00:02', > src='00:00:00:00:00:01') / \ > + IP(dst='10.0.0.254', src='10.0.0.1') / \ > + UDP(sport=42424, dport=53) / \ > + DNS(rd=1, qd=DNSQR(qname='foo.ovn.org', > qtype='ALL'))") > + > +# Without "options:ttl", the reply uses the default TTL of 3600. > +dns_reply=$(fmt_pkt "Ether(dst='00:00:00:00:00:01', > src='00:00:00:00:00:02') / \ > + IP(dst='10.0.0.1', src='10.0.0.254') / \ > + UDP(sport=53, dport=42424, chksum=0) / \ > + DNS(qr=1, qd=DNSQR(qname='foo.ovn.org', qtype='A'), > \ > + an=DNSRR(rrname='foo.ovn.org', type='A', > ttl=3600, \ > + rdata='10.0.0.42'))") > +echo ${dns_reply} > expected > +as hv1 reset_pcap_file hv1-vif1 hv1/vif1 > +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 ${dns_req_a} > +OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv1/vif1-tx.pcap], [expected]) > + > +# options:ttl=30 is applied to the A, AAAA and PTR replies alike. > +check ovn-nbctl --wait=hv set DNS $d options:ttl=30 > + > +dns_reply=$(fmt_pkt "Ether(dst='00:00:00:00:00:01', > src='00:00:00:00:00:02') / \ > + IP(dst='10.0.0.1', src='10.0.0.254') / \ > + UDP(sport=53, dport=42424, chksum=0) / \ > + DNS(qr=1, qd=DNSQR(qname='foo.ovn.org', qtype='A'), > \ > + an=DNSRR(rrname='foo.ovn.org', type='A', > ttl=30, \ > + rdata='10.0.0.42'))") > +echo ${dns_reply} > expected > +as hv1 reset_pcap_file hv1-vif1 hv1/vif1 > +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 ${dns_req_a} > +OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv1/vif1-tx.pcap], [expected]) > + > +dns_reply=$(fmt_pkt "Ether(dst='00:00:00:00:00:01', > src='00:00:00:00:00:02') / \ > + IP(dst='10.0.0.1', src='10.0.0.254') / \ > + UDP(sport=53, dport=42424, chksum=0) / \ > + DNS(qr=1, qd=DNSQR(qname='foo.ovn.org', > qtype='AAAA'), \ > + an=DNSRR(rrname='foo.ovn.org', type='AAAA', > ttl=30, \ > + rdata='aef0::42'))") > +echo ${dns_reply} > expected > +as hv1 reset_pcap_file hv1-vif1 hv1/vif1 > +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 ${dns_req_aaaa} > +OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv1/vif1-tx.pcap], [expected]) > + > +dns_reply=$(fmt_pkt "Ether(dst='00:00:00:00:00:01', > src='00:00:00:00:00:02') / \ > + IP(dst='10.0.0.1', src='10.0.0.254') / \ > + UDP(sport=53, dport=42424, chksum=0) / \ > + DNS(qr=1, qd=DNSQR(qname='42.0.0.10.in-addr.arpa', > qtype='PTR'), \ > + an=DNSRR(rrname='42.0.0.10.in-addr.arpa', > type='PTR', \ > + ttl=30, rdata='foo.ovn.org'))") > +echo ${dns_reply} > expected > +as hv1 reset_pcap_file hv1-vif1 hv1/vif1 > +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 ${dns_req_ptr} > +OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv1/vif1-tx.pcap], [expected]) > + > +# The ANY reply carries the A and AAAA RRs, each with the per-row TTL. > +dns_reply=$(fmt_pkt "Ether(dst='00:00:00:00:00:01', > src='00:00:00:00:00:02') / \ > + IP(dst='10.0.0.1', src='10.0.0.254') / \ > + UDP(sport=53, dport=42424, chksum=0) / \ > + DNS(qr=1, qd=DNSQR(qname='foo.ovn.org', > qtype='ALL'), \ > + an=[[DNSRR(rrname='foo.ovn.org', type='A', \ > + ttl=30, rdata='10.0.0.42'), \ > + DNSRR(rrname='foo.ovn.org', type='AAAA', \ > + ttl=30, rdata='aef0::42')]])") > +echo ${dns_reply} > expected > +as hv1 reset_pcap_file hv1-vif1 hv1/vif1 > +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 ${dns_req_any} > +OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv1/vif1-tx.pcap], [expected]) > + > +# Removing the option restores the default TTL of 3600. > +check ovn-nbctl --wait=hv remove DNS $d options ttl > +dns_reply=$(fmt_pkt "Ether(dst='00:00:00:00:00:01', > src='00:00:00:00:00:02') / \ > + IP(dst='10.0.0.1', src='10.0.0.254') / \ > + UDP(sport=53, dport=42424, chksum=0) / \ > + DNS(qr=1, qd=DNSQR(qname='foo.ovn.org', qtype='A'), > \ > + an=DNSRR(rrname='foo.ovn.org', type='A', > ttl=3600, \ > + rdata='10.0.0.42'))") > +echo ${dns_reply} > expected > +as hv1 reset_pcap_file hv1-vif1 hv1/vif1 > +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 ${dns_req_a} > +OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv1/vif1-tx.pcap], [expected]) > + > +# options:ttl=0 is honored (a reply TTL of 0). > +check ovn-nbctl --wait=hv set DNS $d options:ttl=0 > +dns_reply=$(fmt_pkt "Ether(dst='00:00:00:00:00:01', > src='00:00:00:00:00:02') / \ > + IP(dst='10.0.0.1', src='10.0.0.254') / \ > + UDP(sport=53, dport=42424, chksum=0) / \ > + DNS(qr=1, qd=DNSQR(qname='foo.ovn.org', qtype='A'), > \ > + an=DNSRR(rrname='foo.ovn.org', type='A', ttl=0, > \ > + rdata='10.0.0.42'))") > +echo ${dns_reply} > expected > +as hv1 reset_pcap_file hv1-vif1 hv1/vif1 > +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 ${dns_req_a} > +OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv1/vif1-tx.pcap], [expected]) > + > +OVN_CLEANUP([hv1]) > +AT_CLEANUP > +]) > + > OVN_FOR_EACH_NORTHD([ > AT_SETUP([4 HV, 1 LS, 1 LR, packet test with HA distributed router > gateway port]) > ovn_start > -- > 2.55.0 > > _______________________________________________ > dev mailing list > [email protected] > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > Looks good to me, thanks. Acked-by: Ales Musil <[email protected]> _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
