Merge ~fnordahl/ubuntu/+source/ovn:bug/1857026-hirsute into ~ubuntu-server-dev/ubuntu/+source/ovn:ubuntu/hirsute

Proposed by Frode Nordahl
Status: Merged
Merged at revision: 33d2dee39ed672aa04061714cb3b665bbf0d19da
Proposed branch: ~fnordahl/ubuntu/+source/ovn:bug/1857026-hirsute
Merge into: ~ubuntu-server-dev/ubuntu/+source/ovn:ubuntu/hirsute
Diff against target: 512 lines (+490/-0)
3 files modified
debian/changelog (+7/-0)
debian/patches/lp-1857026-controller-Add-support-for-PTR-DNS-requests.patch (+482/-0)
debian/patches/series (+1/-0)
Reviewer Review Type Date Requested Status
James Page Pending
Review via email: mp+413736@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Frode Nordahl (fnordahl) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 18f4a10..085a9c6 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,10 @@
6+ovn (20.12.0-0ubuntu3~cloud1) focal-wallaby; urgency=medium
7+
8+ * Add support for PTR DNS requests (LP: #1857026)
9+ - d/p/lp-1857026-controller-Add-support-for-PTR-DNS-requests.patch
10+
11+ -- Frode Nordahl <frode.nordahl@canonical.com> Fri, 25 Feb 2022 10:03:00 +0100
12+
13 ovn (20.12.0-0ubuntu3) hirsute; urgency=medium
14
15 * Add RBAC rules for IGMP_Group table (LP: #1914988):
16diff --git a/debian/patches/lp-1857026-controller-Add-support-for-PTR-DNS-requests.patch b/debian/patches/lp-1857026-controller-Add-support-for-PTR-DNS-requests.patch
17new file mode 100644
18index 0000000..244e836
19--- /dev/null
20+++ b/debian/patches/lp-1857026-controller-Add-support-for-PTR-DNS-requests.patch
21@@ -0,0 +1,482 @@
22+Origin: backport, https://github.com/ovn-org/ovn/commit/82a4e44e308171cb545211eb2534475ef16a4c0e
23+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/ovn/+bug/1857026
24+Last-Update: 2022-01-06
25+
26+From 3adbef871f64523b18e75c19dab0aabc435b30e9 Mon Sep 17 00:00:00 2001
27+From: Vladislav Odintsov <odivlad@gmail.com>
28+Date: Fri, 19 Feb 2021 11:57:59 +0300
29+Subject: [PATCH] controller: Add support for PTR DNS requests.
30+
31+The native OVN DNS support doesn't yet support for PTR DNS requests.
32+This patch adds the support for it. If suppose there is a dns record
33+as - "vm1.ovn.org"="10.0.0.4", then a normal DNS request will query for
34+"vm1.ovn.org" and the reply will be the IP address - 10.0.0.4.
35+PTR DNS request helps in getting the domain name of the IP address.
36+For the above example, the PTR DNS request will have a query name as
37+- "4.0.0.10.in-addr.arpa". And the response will have "vm1.ovn.org".
38+In order to support this feature, this patch expects the CMS to define
39+an another entry in the DNS record as - "4.0.0.10.in-addr.arpa"="vm1.ovn.org".
40+
41+This makes the job of ovn-controller easier to support this feature.
42+
43+Submitted-at: https://github.com/ovn-org/ovn/pull/74
44+Signed-off-by: Vladislav Odintsov <odivlad@gmail.com>
45+Signed-off-by: Numan Siddique <numans@ovn.org>
46+(cherry picked from commit 82a4e44e308171cb545211eb2534475ef16a4c0e)
47+
48+Index: ovn-20.12.0/controller/pinctrl.c
49+===================================================================
50+--- ovn-20.12.0.orig/controller/pinctrl.c
51++++ ovn-20.12.0/controller/pinctrl.c
52+@@ -2545,6 +2545,106 @@ destroy_dns_cache(void)
53+ }
54+ }
55+
56++/* Populates dns_answer struct with base data.
57++ * Copy the answer section
58++ * Format of the answer section is
59++ * - NAME -> The domain name
60++ * - TYPE -> 2 octets containing one of the RR type codes
61++ * - CLASS -> 2 octets which specify the class of the data
62++ * in the RDATA field.
63++ * - TTL -> 32 bit unsigned int specifying the time
64++ * interval (in secs) that the resource record
65++ * may be cached before it should be discarded.
66++ * - RDLENGTH -> 16 bit integer specifying the length of the
67++ * RDATA field.
68++ * - RDATA -> a variable length string of octets that
69++ * describes the resource.
70++ */
71++static void
72++dns_build_base_answer(
73++ struct ofpbuf *dns_answer, const uint8_t *in_queryname,
74++ uint16_t query_length, int query_type)
75++{
76++ ofpbuf_put(dns_answer, in_queryname, query_length);
77++ put_be16(dns_answer, htons(query_type));
78++ put_be16(dns_answer, htons(DNS_CLASS_IN));
79++ put_be32(dns_answer, htonl(DNS_DEFAULT_RR_TTL));
80++}
81++
82++/* Populates dns_answer struct with a TYPE A answer. */
83++static void
84++dns_build_a_answer(
85++ struct ofpbuf *dns_answer, const uint8_t *in_queryname,
86++ uint16_t query_length, const ovs_be32 addr)
87++{
88++ dns_build_base_answer(dns_answer, in_queryname, query_length,
89++ DNS_QUERY_TYPE_A);
90++ put_be16(dns_answer, htons(sizeof(ovs_be32)));
91++ put_be32(dns_answer, addr);
92++}
93++
94++/* Populates dns_answer struct with a TYPE AAAA answer. */
95++static void
96++dns_build_aaaa_answer(
97++ struct ofpbuf *dns_answer, const uint8_t *in_queryname,
98++ uint16_t query_length, const struct in6_addr *addr)
99++{
100++ dns_build_base_answer(dns_answer, in_queryname, query_length,
101++ DNS_QUERY_TYPE_AAAA);
102++ put_be16(dns_answer, htons(sizeof(*addr)));
103++ ofpbuf_put(dns_answer, addr, sizeof(*addr));
104++}
105++
106++/* Populates dns_answer struct with a TYPE PTR answer. */
107++static void
108++dns_build_ptr_answer(
109++ struct ofpbuf *dns_answer, const uint8_t *in_queryname,
110++ uint16_t query_length, const char *answer_data)
111++{
112++ char *encoded_answer;
113++ uint16_t encoded_answer_length;
114++
115++ dns_build_base_answer(dns_answer, in_queryname, query_length,
116++ DNS_QUERY_TYPE_PTR);
117++
118++ /* Initialize string 2 chars longer than real answer:
119++ * first label length and terminating zero-length label.
120++ * If the answer_data is - vm1tst.ovn.org, it will be encoded as
121++ * - 0010 (Total length which is 16)
122++ * - 06766d31747374 (vm1tst)
123++ * - 036f766e (ovn)
124++ * - 036f7267 (org
125++ * - 00 (zero length field) */
126++ encoded_answer_length = strlen(answer_data) + 2;
127++ encoded_answer = (char *)xzalloc(encoded_answer_length);
128++
129++ put_be16(dns_answer, htons(encoded_answer_length));
130++ uint8_t label_len_index = 0;
131++ uint16_t label_len = 0;
132++ char *encoded_answer_ptr = (char *)encoded_answer + 1;
133++ while (*answer_data) {
134++ if (*answer_data == '.') {
135++ /* Label has ended. Update the length of the label. */
136++ encoded_answer[label_len_index] = label_len;
137++ label_len_index += (label_len + 1);
138++ label_len = 0; /* Init to 0 for the next label. */
139++ } else {
140++ *encoded_answer_ptr = *answer_data;
141++ label_len++;
142++ }
143++ encoded_answer_ptr++;
144++ answer_data++;
145++ }
146++
147++ /* This is required for the last label if it doesn't end with '.' */
148++ if (label_len) {
149++ encoded_answer[label_len_index] = label_len;
150++ }
151++
152++ ofpbuf_put(dns_answer, encoded_answer, encoded_answer_length);
153++ free(encoded_answer);
154++}
155++
156+ /* Called with in the pinctrl_handler thread context. */
157+ static void
158+ pinctrl_handle_dns_lookup(
159+@@ -2640,15 +2740,16 @@ pinctrl_handle_dns_lookup(
160+ }
161+
162+ uint16_t query_type = ntohs(*ALIGNED_CAST(const ovs_be16 *, in_dns_data));
163+- /* Supported query types - A, AAAA and ANY */
164++ /* Supported query types - A, AAAA, ANY and PTR */
165+ if (!(query_type == DNS_QUERY_TYPE_A || query_type == DNS_QUERY_TYPE_AAAA
166+- || query_type == DNS_QUERY_TYPE_ANY)) {
167++ || query_type == DNS_QUERY_TYPE_ANY
168++ || query_type == DNS_QUERY_TYPE_PTR)) {
169+ ds_destroy(&query_name);
170+ goto exit;
171+ }
172+
173+ uint64_t dp_key = ntohll(pin->flow_metadata.flow.metadata);
174+- const char *answer_ips = NULL;
175++ const char *answer_data = NULL;
176+ struct shash_node *iter;
177+ SHASH_FOR_EACH (iter, &dns_cache) {
178+ struct dns_data *d = iter->data;
179+@@ -2658,76 +2759,58 @@ pinctrl_handle_dns_lookup(
180+ * lowercase to perform case insensitive lookup
181+ */
182+ char *query_name_lower = str_tolower(ds_cstr(&query_name));
183+- answer_ips = smap_get(&d->records, query_name_lower);
184++ answer_data = smap_get(&d->records, query_name_lower);
185+ free(query_name_lower);
186+- if (answer_ips) {
187++ if (answer_data) {
188+ break;
189+ }
190+ }
191+ }
192+
193+- if (answer_ips) {
194++ if (answer_data) {
195+ break;
196+ }
197+ }
198+
199+ ds_destroy(&query_name);
200+- if (!answer_ips) {
201++ if (!answer_data) {
202+ goto exit;
203+ }
204+
205+- struct lport_addresses ip_addrs;
206+- if (!extract_ip_addresses(answer_ips, &ip_addrs)) {
207+- goto exit;
208+- }
209+
210+ uint16_t ancount = 0;
211+ uint64_t dns_ans_stub[128 / 8];
212+ struct ofpbuf dns_answer = OFPBUF_STUB_INITIALIZER(dns_ans_stub);
213+
214+- if (query_type == DNS_QUERY_TYPE_A || query_type == DNS_QUERY_TYPE_ANY) {
215+- for (size_t i = 0; i < ip_addrs.n_ipv4_addrs; i++) {
216+- /* Copy the answer section */
217+- /* Format of the answer section is
218+- * - NAME -> The domain name
219+- * - TYPE -> 2 octets containing one of the RR type codes
220+- * - CLASS -> 2 octets which specify the class of the data
221+- * in the RDATA field.
222+- * - TTL -> 32 bit unsigned int specifying the time
223+- * interval (in secs) that the resource record
224+- * may be cached before it should be discarded.
225+- * - RDLENGTH -> 16 bit integer specifying the length of the
226+- * RDATA field.
227+- * - RDATA -> a variable length string of octets that
228+- * describes the resource. In our case it will
229+- * be IP address of the domain name.
230+- */
231+- ofpbuf_put(&dns_answer, in_queryname, idx);
232+- put_be16(&dns_answer, htons(DNS_QUERY_TYPE_A));
233+- put_be16(&dns_answer, htons(DNS_CLASS_IN));
234+- put_be32(&dns_answer, htonl(DNS_DEFAULT_RR_TTL));
235+- put_be16(&dns_answer, htons(sizeof(ovs_be32)));
236+- put_be32(&dns_answer, ip_addrs.ipv4_addrs[i].addr);
237+- ancount++;
238++ if (query_type == DNS_QUERY_TYPE_PTR) {
239++ dns_build_ptr_answer(&dns_answer, in_queryname, idx, answer_data);
240++ ancount++;
241++ } else {
242++ struct lport_addresses ip_addrs;
243++ if (!extract_ip_addresses(answer_data, &ip_addrs)) {
244++ goto exit;
245++ }
246++
247++ if (query_type == DNS_QUERY_TYPE_A ||
248++ query_type == DNS_QUERY_TYPE_ANY) {
249++ for (size_t i = 0; i < ip_addrs.n_ipv4_addrs; i++) {
250++ dns_build_a_answer(&dns_answer, in_queryname, idx,
251++ ip_addrs.ipv4_addrs[i].addr);
252++ ancount++;
253++ }
254+ }
255+- }
256+
257+- if (query_type == DNS_QUERY_TYPE_AAAA ||
258+- query_type == DNS_QUERY_TYPE_ANY) {
259+- for (size_t i = 0; i < ip_addrs.n_ipv6_addrs; i++) {
260+- ofpbuf_put(&dns_answer, in_queryname, idx);
261+- put_be16(&dns_answer, htons(DNS_QUERY_TYPE_AAAA));
262+- put_be16(&dns_answer, htons(DNS_CLASS_IN));
263+- put_be32(&dns_answer, htonl(DNS_DEFAULT_RR_TTL));
264+- const struct in6_addr *ip6 = &ip_addrs.ipv6_addrs[i].addr;
265+- put_be16(&dns_answer, htons(sizeof *ip6));
266+- ofpbuf_put(&dns_answer, ip6, sizeof *ip6);
267+- ancount++;
268++ if (query_type == DNS_QUERY_TYPE_AAAA ||
269++ query_type == DNS_QUERY_TYPE_ANY) {
270++ for (size_t i = 0; i < ip_addrs.n_ipv6_addrs; i++) {
271++ dns_build_aaaa_answer(&dns_answer, in_queryname, idx,
272++ &ip_addrs.ipv6_addrs[i].addr);
273++ ancount++;
274++ }
275+ }
276++ destroy_lport_addresses(&ip_addrs);
277+ }
278+
279+- destroy_lport_addresses(&ip_addrs);
280+-
281+ if (!ancount) {
282+ ofpbuf_uninit(&dns_answer);
283+ goto exit;
284+Index: ovn-20.12.0/lib/ovn-l7.h
285+===================================================================
286+--- ovn-20.12.0.orig/lib/ovn-l7.h
287++++ ovn-20.12.0/lib/ovn-l7.h
288+@@ -26,6 +26,14 @@
289+ #include "hash.h"
290+ #include "ovn/logical-fields.h"
291+
292++#define DNS_QUERY_TYPE_A 0x01
293++#define DNS_QUERY_TYPE_AAAA 0x1c
294++#define DNS_QUERY_TYPE_ANY 0xff
295++#define DNS_QUERY_TYPE_PTR 0x0c
296++
297++#define DNS_CLASS_IN 0x01
298++#define DNS_DEFAULT_RR_TTL 3600
299++
300+ /* Generic options map which is used to store dhcpv4 opts and dhcpv6 opts. */
301+ struct gen_opts_map {
302+ struct hmap_node hmap_node;
303+Index: ovn-20.12.0/ovn-nb.xml
304+===================================================================
305+--- ovn-20.12.0.orig/ovn-nb.xml
306++++ ovn-20.12.0/ovn-nb.xml
307+@@ -3549,7 +3549,13 @@
308+ Key-value pair of DNS records with <code>DNS query name</code> as the key
309+ and value as a string of IP address(es) separated by comma or space.
310+
311++ For PTR requests, the key-value pair can be
312++ <code>Reverse IPv4 address.in-addr.arpa</code> and the value
313++ <code>DNS domain name</code>. For IPv6 addresses, the key
314++ has to be <code>Reverse IPv6 address.ip6.arpa</code>.
315++
316+ <p><b>Example: </b> "vm1.ovn.org" = "10.0.0.4 aef0::4"</p>
317++ <p><b>Example: </b> "4.0.0.10.in-addr.arpa" = "vm1.ovn.org"</p>
318+ </column>
319+
320+ <column name="external_ids">
321+Index: ovn-20.12.0/tests/ovn.at
322+===================================================================
323+--- ovn-20.12.0.orig/tests/ovn.at
324++++ ovn-20.12.0/tests/ovn.at
325+@@ -9349,10 +9349,13 @@ ovn-nbctl lsp-set-port-security ls1-lp2
326+
327+ DNS1=`ovn-nbctl create DNS records={}`
328+ DNS2=`ovn-nbctl create DNS records={}`
329++DNS3=`ovn-nbctl create DNS records={}`
330+
331+ ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4"
332+ ovn-nbctl set DNS $DNS1 records:vm2.ovn.org="10.0.0.6 20.0.0.4"
333+ ovn-nbctl set DNS $DNS2 records:vm3.ovn.org="40.0.0.4"
334++ovn-nbctl set DNS $DNS3 records:4.0.0.10.in-addr.arpa="vm1.ovn.org"
335++ovn-nbctl set DNS $DNS3 records:4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.f.e.a.ip6.arpa="vm1.ovn.org"
336+
337+ ovn-nbctl set Logical_switch ls1 dns_records="$DNS1"
338+
339+@@ -9454,6 +9457,21 @@ set_dns_params() {
340+ vm1_incomplete)
341+ # set type to none
342+ type=''
343++ ;;
344++ vm1_ipv4_ptr)
345++ # 4.0.0.10.in-addr.arpa
346++ query_name=01340130013002313007696e2d61646472046172706100
347++ type=000c
348++ # vm1.ovn.org
349++ expected_dns_answer=${query_name}${type}0001${ttl}000d03766d31036f766e036f726700
350++ ;;
351++ vm1_ipv6_ptr)
352++ # 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.f.e.a.ip6.arpa
353++ query_name=0134013001300130013001300130013001300130013001300130013001300130013001300130013001300130013001300130013001300130013001660165016103697036046172706100
354++ type=000c
355++ # vm1.ovn.org
356++ expected_dns_answer=${query_name}${type}0001${ttl}000d03766d31036f766e036f726700
357++ ;;
358+ esac
359+ # TTL - 3600
360+ local dns_req_header=010201200001000000000000
361+@@ -9553,6 +9571,7 @@ reset_pcap_file hv1-vif2 hv1/vif2
362+ rm -f 1.expected
363+ rm -f 2.expected
364+
365++
366+ set_dns_params vm1
367+ src_ip=`ip_to_hex 10 0 0 6`
368+ dst_ip=`ip_to_hex 10 0 0 1`
369+@@ -9574,8 +9593,8 @@ reset_pcap_file hv1-vif2 hv1/vif2
370+ rm -f 1.expected
371+ rm -f 2.expected
372+
373+-# Try vm1 again but an all-caps query name
374+
375++# Try vm1 again but an all-caps query name
376+ set_dns_params VM1
377+ src_ip=`ip_to_hex 10 0 0 6`
378+ dst_ip=`ip_to_hex 10 0 0 1`
379+@@ -9597,6 +9616,7 @@ reset_pcap_file hv1-vif2 hv1/vif2
380+ rm -f 1.expected
381+ rm -f 2.expected
382+
383++
384+ # Clear the query name options for ls1-lp2
385+ ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org
386+
387+@@ -9617,6 +9637,7 @@ reset_pcap_file hv1-vif2 hv1/vif2
388+ rm -f 1.expected
389+ rm -f 2.expected
390+
391++
392+ # Clear the query name for ls1-lp1
393+ # Since ls1 has no query names configued,
394+ # ovn-northd should not add the DNS flows.
395+@@ -9639,6 +9660,7 @@ reset_pcap_file hv1-vif2 hv1/vif2
396+ rm -f 1.expected
397+ rm -f 2.expected
398+
399++
400+ # Test IPv6 (AAAA records) using IPv4 packet.
401+ # Add back the DNS options for ls1-lp1.
402+ ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4"
403+@@ -9664,6 +9686,7 @@ reset_pcap_file hv1-vif2 hv1/vif2
404+ rm -f 1.expected
405+ rm -f 2.expected
406+
407++
408+ # Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet.
409+ set_dns_params vm1_ipv4_v6
410+ src_ip=`ip_to_hex 10 0 0 6`
411+@@ -9686,6 +9709,7 @@ reset_pcap_file hv1-vif2 hv1/vif2
412+ rm -f 1.expected
413+ rm -f 2.expected
414+
415++
416+ # Invalid type.
417+ set_dns_params vm1_invalid_type
418+ src_ip=`ip_to_hex 10 0 0 6`
419+@@ -9704,6 +9728,7 @@ reset_pcap_file hv1-vif2 hv1/vif2
420+ rm -f 1.expected
421+ rm -f 2.expected
422+
423++
424+ # Incomplete DNS packet.
425+ set_dns_params vm1_incomplete
426+ src_ip=`ip_to_hex 10 0 0 6`
427+@@ -9722,6 +9747,7 @@ reset_pcap_file hv1-vif2 hv1/vif2
428+ rm -f 1.expected
429+ rm -f 2.expected
430+
431++
432+ # Add one more DNS record to the ls1.
433+ ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2"
434+
435+@@ -9746,6 +9772,7 @@ reset_pcap_file hv1-vif2 hv1/vif2
436+ rm -f 1.expected
437+ rm -f 2.expected
438+
439++
440+ # Try DNS query over IPv6
441+ set_dns_params vm1
442+ src_ip=aef00000000000000000000000000004
443+@@ -9763,6 +9790,60 @@ AT_CHECK([cat 1.packets | cut -c 1-120,1
444+
445+ reset_pcap_file hv1-vif1 hv1/vif1
446+ reset_pcap_file hv1-vif2 hv1/vif2
447++rm -f 1.expected
448++rm -f 2.expected
449++
450++
451++# Add one more DNS record to the ls1.
452++ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2 $DNS3"
453++echo "*************************"
454++ovn-sbctl list DNS
455++echo "*************************"
456++ovn-nbctl list DNS
457++echo "*************************"
458++
459++# Test PTR record for IPv4 address using IPv4 packet.
460++set_dns_params vm1_ipv4_ptr
461++src_ip=`ip_to_hex 10 0 0 4`
462++dst_ip=`ip_to_hex 10 0 0 1`
463++dns_reply=1
464++test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
465++
466++# NXT_RESUMEs should be 11.
467++OVS_WAIT_UNTIL([test 11 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
468++
469++$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
470++cat 1.expected | cut -c -48 > expout
471++AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
472++# Skipping the IPv4 checksum.
473++cat 1.expected | cut -c 53- > expout
474++AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
475++
476++reset_pcap_file hv1-vif1 hv1/vif1
477++reset_pcap_file hv1-vif2 hv1/vif2
478++rm -f 1.expected
479++rm -f 2.expected
480++
481++
482++# Test PTR record for IPv6 address using IPv4 packet.
483++set_dns_params vm1_ipv6_ptr
484++src_ip=`ip_to_hex 10 0 0 4`
485++dst_ip=`ip_to_hex 10 0 0 1`
486++dns_reply=1
487++test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
488++
489++# NXT_RESUMEs should be 12.
490++OVS_WAIT_UNTIL([test 12 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
491++
492++$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
493++cat 1.expected | cut -c -48 > expout
494++AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
495++# Skipping the IPv4 checksum.
496++cat 1.expected | cut -c 53- > expout
497++AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
498++
499++reset_pcap_file hv1-vif1 hv1/vif1
500++reset_pcap_file hv1-vif2 hv1/vif2
501+ rm -f 1.expected
502+ rm -f 2.expected
503+
504diff --git a/debian/patches/series b/debian/patches/series
505index 495c2d2..e6ab792 100644
506--- a/debian/patches/series
507+++ b/debian/patches/series
508@@ -10,3 +10,4 @@ lp-1914988-tests-Make-certificate-generation-extendable.patch
509 lp-1914988-tests-Test-with-SSL-and-RBAC-for-controller-by-defau.patch
510 lp-1943266-pinctrl-Don-t-send-gARPs-for-localports.patch
511 lp-1943266-physical-do-not-forward-traffic-from-localport-to-a-.patch
512+lp-1857026-controller-Add-support-for-PTR-DNS-requests.patch

Subscribers

People subscribed via source and target branches