Merge ~fnordahl/ubuntu/+source/ovn:bug/1857026-focal into ~ubuntu-server-dev/ubuntu/+source/ovn:ubuntu/focal
- Git
- lp:~fnordahl/ubuntu/+source/ovn
- bug/1857026-focal
- Merge into ubuntu/focal
Proposed by
Frode Nordahl
Status: | Merged |
---|---|
Merged at revision: | 1272554ada5e7ecfcc9b090d696d7b092779bdb6 |
Proposed branch: | ~fnordahl/ubuntu/+source/ovn:bug/1857026-focal |
Merge into: | ~ubuntu-server-dev/ubuntu/+source/ovn:ubuntu/focal |
Diff against target: |
803 lines (+775/-0) 4 files modified
debian/changelog (+8/-0) debian/patches/lp-1857026-0001-DNS-Make-DNS-lookups-case-insensitive.patch (+274/-0) debian/patches/lp-1857026-0002-controller-Add-support-for-PTR-DNS-requests.patch (+491/-0) debian/patches/series (+2/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Page | Pending | ||
Review via email: mp+413737@code.launchpad.net |
Commit message
Description of the change
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
1 | diff --git a/debian/changelog b/debian/changelog |
2 | index c0af91d..2094609 100644 |
3 | --- a/debian/changelog |
4 | +++ b/debian/changelog |
5 | @@ -1,3 +1,11 @@ |
6 | +ovn (20.03.2-0ubuntu0.20.04.3) focal; urgency=medium |
7 | + |
8 | + * Add support for PTR DNS requests (LP: #1857026) |
9 | + - d/p/lp-1857026-0001-DNS-Make-DNS-lookups-case-insensitive.patch |
10 | + - d/p/lp-1857026-0002-controller-Add-support-for-PTR-DNS-requests.patch |
11 | + |
12 | + -- Frode Nordahl <frode.nordahl@canonical.com> Thu, 06 Jan 2022 10:00:00 +0100 |
13 | + |
14 | ovn (20.03.2-0ubuntu0.20.04.2) focal; urgency=medium |
15 | |
16 | * Add RBAC rules for IGMP_Group table (LP: #1914988): |
17 | diff --git a/debian/patches/lp-1857026-0001-DNS-Make-DNS-lookups-case-insensitive.patch b/debian/patches/lp-1857026-0001-DNS-Make-DNS-lookups-case-insensitive.patch |
18 | new file mode 100644 |
19 | index 0000000..bfb394a |
20 | --- /dev/null |
21 | +++ b/debian/patches/lp-1857026-0001-DNS-Make-DNS-lookups-case-insensitive.patch |
22 | @@ -0,0 +1,274 @@ |
23 | +Origin: backport, https://github.com/ovn-org/ovn/commit/9287f425e8bc5781728b2ff1c60413d3c39c33a8 |
24 | +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/ovn/+bug/1857026 |
25 | +Last-Update: 2022-01-06 |
26 | + |
27 | +From 815d4c04992d994bcd75b3d642fe6cc694ec99b3 Mon Sep 17 00:00:00 2001 |
28 | +From: Mark Michelson <mmichels@redhat.com> |
29 | +Date: Mon, 20 Apr 2020 09:25:09 -0400 |
30 | +Subject: [PATCH 1/2] DNS: Make DNS lookups case insensitive. |
31 | + |
32 | +From RFC 1035 Section 2.3.3: |
33 | + |
34 | +"For all parts of the DNS that are part of the official protocol, all |
35 | +comparisons between character strings (e.g., labels, domain names, etc.) |
36 | +are done in a case-insensitive manner." |
37 | + |
38 | +OVN was using case-sensitive lookups and therefore was not complying. |
39 | +This change makes lookups case insensitive by storing lowercase record |
40 | +names in the southbound database and converting incoming query names to |
41 | +lowercase. |
42 | + |
43 | +Signed-off-by: Mark Michelson <mmichels@redhat.com> |
44 | +Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1819069 |
45 | +Reported-by: Jianlin Shi <jishi@redhat.com> |
46 | +Acked-by: Numan Siddique <numans@ovn.org> |
47 | +(cherry picked from commit 9287f425e8bc5781728b2ff1c60413d3c39c33a8) |
48 | +--- |
49 | + controller/pinctrl.c | 7 ++++- |
50 | + lib/ovn-util.c | 15 +++++++++++ |
51 | + lib/ovn-util.h | 5 ++++ |
52 | + northd/ovn-northd.c | 15 ++++++++++- |
53 | + ovn-sb.xml | 3 ++- |
54 | + tests/ovn.at | 61 ++++++++++++++++++++++++++++++++------------ |
55 | + 6 files changed, 87 insertions(+), 19 deletions(-) |
56 | + |
57 | +diff --git a/controller/pinctrl.c b/controller/pinctrl.c |
58 | +index 5822f03ef..4879dcc45 100644 |
59 | +--- a/controller/pinctrl.c |
60 | ++++ b/controller/pinctrl.c |
61 | +@@ -1767,7 +1767,12 @@ pinctrl_handle_dns_lookup( |
62 | + struct dns_data *d = iter->data; |
63 | + for (size_t i = 0; i < d->n_dps; i++) { |
64 | + if (d->dps[i] == dp_key) { |
65 | +- answer_ips = smap_get(&d->records, ds_cstr(&query_name)); |
66 | ++ /* DNS records in SBDB are stored in lowercase. Convert to |
67 | ++ * lowercase to perform case insensitive lookup |
68 | ++ */ |
69 | ++ char *query_name_lower = str_tolower(ds_cstr(&query_name)); |
70 | ++ answer_ips = smap_get(&d->records, query_name_lower); |
71 | ++ free(query_name_lower); |
72 | + if (answer_ips) { |
73 | + break; |
74 | + } |
75 | +diff --git a/lib/ovn-util.c b/lib/ovn-util.c |
76 | +index 514e2489f..1b30c2e9a 100644 |
77 | +--- a/lib/ovn-util.c |
78 | ++++ b/lib/ovn-util.c |
79 | +@@ -21,6 +21,7 @@ |
80 | + #include "openvswitch/ofp-parse.h" |
81 | + #include "ovn-nb-idl.h" |
82 | + #include "ovn-sb-idl.h" |
83 | ++#include <ctype.h> |
84 | + |
85 | + VLOG_DEFINE_THIS_MODULE(ovn_util); |
86 | + |
87 | +@@ -550,3 +551,17 @@ ip46_equals(const struct v46_ip *addr1, const struct v46_ip *addr2) |
88 | + (addr1->family == AF_INET ? addr1->ipv4 == addr2->ipv4 : |
89 | + IN6_ARE_ADDR_EQUAL(&addr1->ipv6, &addr2->ipv6))); |
90 | + } |
91 | ++ |
92 | ++char * |
93 | ++str_tolower(const char *orig) |
94 | ++{ |
95 | ++ char *copy = xmalloc(strlen(orig) + 1); |
96 | ++ char *p = copy; |
97 | ++ |
98 | ++ while (*orig) { |
99 | ++ *p++ = tolower(*orig++); |
100 | ++ } |
101 | ++ *p = '\0'; |
102 | ++ |
103 | ++ return copy; |
104 | ++} |
105 | +diff --git a/lib/ovn-util.h b/lib/ovn-util.h |
106 | +index 11238f61c..4076e8b9a 100644 |
107 | +--- a/lib/ovn-util.h |
108 | ++++ b/lib/ovn-util.h |
109 | +@@ -124,4 +124,9 @@ struct v46_ip { |
110 | + bool ip46_parse_cidr(const char *str, struct v46_ip *prefix, |
111 | + unsigned int *plen); |
112 | + bool ip46_equals(const struct v46_ip *addr1, const struct v46_ip *addr2); |
113 | ++ |
114 | ++/* Returns a lowercase copy of orig. |
115 | ++ * Caller must free the returned string. |
116 | ++ */ |
117 | ++char *str_tolower(const char *orig); |
118 | + #endif |
119 | +diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c |
120 | +index 9cc2c04bb..4ced1b48f 100644 |
121 | +--- a/northd/ovn-northd.c |
122 | ++++ b/northd/ovn-northd.c |
123 | +@@ -10634,7 +10634,20 @@ sync_dns_entries(struct northd_context *ctx, struct hmap *datapaths) |
124 | + dns_info->sb_dns, |
125 | + (struct sbrec_datapath_binding **)dns_info->sbs, |
126 | + dns_info->n_sbs); |
127 | +- sbrec_dns_set_records(dns_info->sb_dns, &dns_info->nb_dns->records); |
128 | ++ |
129 | ++ /* DNS lookups are case-insensitive. Convert records to lowercase so |
130 | ++ * we can do consistent lookups when DNS requests arrive |
131 | ++ */ |
132 | ++ struct smap lower_records = SMAP_INITIALIZER(&lower_records); |
133 | ++ struct smap_node *node; |
134 | ++ SMAP_FOR_EACH (node, &dns_info->nb_dns->records) { |
135 | ++ smap_add_nocopy(&lower_records, xstrdup(node->key), |
136 | ++ str_tolower(node->value)); |
137 | ++ } |
138 | ++ |
139 | ++ sbrec_dns_set_records(dns_info->sb_dns, &lower_records); |
140 | ++ |
141 | ++ smap_destroy(&lower_records); |
142 | + free(dns_info->sbs); |
143 | + free(dns_info); |
144 | + } |
145 | +diff --git a/ovn-sb.xml b/ovn-sb.xml |
146 | +index 2703e6d0c..64c33d2df 100644 |
147 | +--- a/ovn-sb.xml |
148 | ++++ b/ovn-sb.xml |
149 | +@@ -3581,7 +3581,8 @@ tcp.flags = RST; |
150 | + <column name="records"> |
151 | + Key-value pair of DNS records with <code>DNS query name</code> as the key |
152 | + and a string of IP address(es) separated by comma or space as the |
153 | +- value. |
154 | ++ value. ovn-northd stores the DNS query name in all lowercase in order to |
155 | ++ facilitate case-insensitive lookups. |
156 | + |
157 | + <p><b>Example: </b> "vm1.ovn.org" = "10.0.0.4 aef0::4"</p> |
158 | + </column> |
159 | +diff --git a/tests/ovn.at b/tests/ovn.at |
160 | +index 4d9ee1256..b6eff4349 100644 |
161 | +--- a/tests/ovn.at |
162 | ++++ b/tests/ovn.at |
163 | +@@ -8317,6 +8317,12 @@ set_dns_params() { |
164 | + # IPv4 address - 10.0.0.4 |
165 | + expected_dns_answer=${query_name}00010001${ttl}00040a000004 |
166 | + ;; |
167 | ++ VM1) |
168 | ++ # VM1.OVN.ORG |
169 | ++ query_name=03564d31034f564e034f524700 |
170 | ++ # IPv4 address - 10.0.0.4 |
171 | ++ expected_dns_answer=${query_name}00010001${ttl}00040a000004 |
172 | ++ ;; |
173 | + vm2) |
174 | + # vm2.ovn.org |
175 | + query_name=03766d32036f766e036f726700 |
176 | +@@ -8479,6 +8485,29 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
177 | + rm -f 1.expected |
178 | + rm -f 2.expected |
179 | + |
180 | ++# Try vm1 again but an all-caps query name |
181 | ++ |
182 | ++set_dns_params VM1 |
183 | ++src_ip=`ip_to_hex 10 0 0 6` |
184 | ++dst_ip=`ip_to_hex 10 0 0 1` |
185 | ++dns_reply=1 |
186 | ++test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data |
187 | ++ |
188 | ++# NXT_RESUMEs should be 3. |
189 | ++OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
190 | ++ |
191 | ++$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets |
192 | ++cat 2.expected | cut -c -48 > expout |
193 | ++AT_CHECK([cat 2.packets | cut -c -48], [0], [expout]) |
194 | ++# Skipping the IPv4 checksum. |
195 | ++cat 2.expected | cut -c 53- > expout |
196 | ++AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout]) |
197 | ++ |
198 | ++reset_pcap_file hv1-vif1 hv1/vif1 |
199 | ++reset_pcap_file hv1-vif2 hv1/vif2 |
200 | ++rm -f 1.expected |
201 | ++rm -f 2.expected |
202 | ++ |
203 | + # Clear the query name options for ls1-lp2 |
204 | + ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org |
205 | + |
206 | +@@ -8488,8 +8517,8 @@ dst_ip=`ip_to_hex 10 0 0 1` |
207 | + dns_reply=0 |
208 | + test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply $dns_req_data |
209 | + |
210 | +-# NXT_RESUMEs should be 3. |
211 | +-OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
212 | ++# NXT_RESUMEs should be 4. |
213 | ++OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
214 | + |
215 | + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets |
216 | + AT_CHECK([cat 1.packets], [0], []) |
217 | +@@ -8510,8 +8539,8 @@ dst_ip=`ip_to_hex 10 0 0 1` |
218 | + dns_reply=0 |
219 | + test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data |
220 | + |
221 | +-# NXT_RESUMEs should be 3 only. |
222 | +-OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
223 | ++# NXT_RESUMEs should be 4 only. |
224 | ++OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
225 | + |
226 | + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets |
227 | + AT_CHECK([cat 2.packets], [0], []) |
228 | +@@ -8531,8 +8560,8 @@ dst_ip=`ip_to_hex 10 0 0 1` |
229 | + dns_reply=1 |
230 | + test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data |
231 | + |
232 | +-# NXT_RESUMEs should be 4. |
233 | +-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
234 | ++# NXT_RESUMEs should be 5. |
235 | ++OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
236 | + |
237 | + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets |
238 | + cat 2.expected | cut -c -48 > expout |
239 | +@@ -8553,8 +8582,8 @@ dst_ip=`ip_to_hex 10 0 0 1` |
240 | + dns_reply=1 |
241 | + test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data |
242 | + |
243 | +-# NXT_RESUMEs should be 5. |
244 | +-OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
245 | ++# NXT_RESUMEs should be 6. |
246 | ++OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
247 | + |
248 | + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets |
249 | + cat 2.expected | cut -c -48 > expout |
250 | +@@ -8575,8 +8604,8 @@ dst_ip=`ip_to_hex 10 0 0 1` |
251 | + dns_reply=0 |
252 | + test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data |
253 | + |
254 | +-# NXT_RESUMEs should be 6. |
255 | +-OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
256 | ++# NXT_RESUMEs should be 7. |
257 | ++OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
258 | + |
259 | + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets |
260 | + AT_CHECK([cat 2.packets], [0], []) |
261 | +@@ -8593,8 +8622,8 @@ dst_ip=`ip_to_hex 10 0 0 1` |
262 | + dns_reply=0 |
263 | + test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data |
264 | + |
265 | +-# NXT_RESUMEs should be 7. |
266 | +-OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
267 | ++# NXT_RESUMEs should be 8. |
268 | ++OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
269 | + |
270 | + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets |
271 | + AT_CHECK([cat 2.packets], [0], []) |
272 | +@@ -8613,8 +8642,8 @@ dst_ip=`ip_to_hex 10 0 0 1` |
273 | + dns_reply=1 |
274 | + test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data |
275 | + |
276 | +-# NXT_RESUMEs should be 8. |
277 | +-OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
278 | ++# NXT_RESUMEs should be 9. |
279 | ++OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
280 | + |
281 | + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets |
282 | + cat 1.expected | cut -c -48 > expout |
283 | +@@ -8635,8 +8664,8 @@ dst_ip=aef00000000000000000000000000001 |
284 | + dns_reply=1 |
285 | + test_dns6 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data |
286 | + |
287 | +-# NXT_RESUMEs should be 9. |
288 | +-OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
289 | ++# NXT_RESUMEs should be 10 |
290 | ++OVS_WAIT_UNTIL([test 10 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
291 | + |
292 | + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets |
293 | + # Skipping the UDP checksum. |
294 | +-- |
295 | +2.33.1 |
296 | + |
297 | diff --git a/debian/patches/lp-1857026-0002-controller-Add-support-for-PTR-DNS-requests.patch b/debian/patches/lp-1857026-0002-controller-Add-support-for-PTR-DNS-requests.patch |
298 | new file mode 100644 |
299 | index 0000000..4386c6c |
300 | --- /dev/null |
301 | +++ b/debian/patches/lp-1857026-0002-controller-Add-support-for-PTR-DNS-requests.patch |
302 | @@ -0,0 +1,491 @@ |
303 | +Origin: backport, https://github.com/ovn-org/ovn/commit/82a4e44e308171cb545211eb2534475ef16a4c0e |
304 | +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/ovn/+bug/1857026 |
305 | +Last-Update: 2022-01-06 |
306 | + |
307 | +From e612a270f789af616e98cc204eee42b8b114de41 Mon Sep 17 00:00:00 2001 |
308 | +From: Vladislav Odintsov <odivlad@gmail.com> |
309 | +Date: Fri, 19 Feb 2021 11:57:59 +0300 |
310 | +Subject: [PATCH 2/2] controller: Add support for PTR DNS requests. |
311 | + |
312 | +The native OVN DNS support doesn't yet support for PTR DNS requests. |
313 | +This patch adds the support for it. If suppose there is a dns record |
314 | +as - "vm1.ovn.org"="10.0.0.4", then a normal DNS request will query for |
315 | +"vm1.ovn.org" and the reply will be the IP address - 10.0.0.4. |
316 | +PTR DNS request helps in getting the domain name of the IP address. |
317 | +For the above example, the PTR DNS request will have a query name as |
318 | +- "4.0.0.10.in-addr.arpa". And the response will have "vm1.ovn.org". |
319 | +In order to support this feature, this patch expects the CMS to define |
320 | +an another entry in the DNS record as - "4.0.0.10.in-addr.arpa"="vm1.ovn.org". |
321 | + |
322 | +This makes the job of ovn-controller easier to support this feature. |
323 | + |
324 | +Submitted-at: https://github.com/ovn-org/ovn/pull/74 |
325 | +Signed-off-by: Vladislav Odintsov <odivlad@gmail.com> |
326 | +Signed-off-by: Numan Siddique <numans@ovn.org> |
327 | +(cherry picked from commit 82a4e44e308171cb545211eb2534475ef16a4c0e) |
328 | +--- |
329 | + controller/pinctrl.c | 181 +++++++++++++++++++++++++++++++------------ |
330 | + lib/ovn-l7.h | 8 ++ |
331 | + ovn-nb.xml | 6 ++ |
332 | + tests/ovn.at | 83 +++++++++++++++++++- |
333 | + 4 files changed, 228 insertions(+), 50 deletions(-) |
334 | + |
335 | +diff --git a/controller/pinctrl.c b/controller/pinctrl.c |
336 | +index 4879dcc45..c505077e0 100644 |
337 | +--- a/controller/pinctrl.c |
338 | ++++ b/controller/pinctrl.c |
339 | +@@ -1658,6 +1658,106 @@ destroy_dns_cache(void) |
340 | + } |
341 | + } |
342 | + |
343 | ++/* Populates dns_answer struct with base data. |
344 | ++ * Copy the answer section |
345 | ++ * Format of the answer section is |
346 | ++ * - NAME -> The domain name |
347 | ++ * - TYPE -> 2 octets containing one of the RR type codes |
348 | ++ * - CLASS -> 2 octets which specify the class of the data |
349 | ++ * in the RDATA field. |
350 | ++ * - TTL -> 32 bit unsigned int specifying the time |
351 | ++ * interval (in secs) that the resource record |
352 | ++ * may be cached before it should be discarded. |
353 | ++ * - RDLENGTH -> 16 bit integer specifying the length of the |
354 | ++ * RDATA field. |
355 | ++ * - RDATA -> a variable length string of octets that |
356 | ++ * describes the resource. |
357 | ++ */ |
358 | ++static void |
359 | ++dns_build_base_answer( |
360 | ++ struct ofpbuf *dns_answer, const uint8_t *in_queryname, |
361 | ++ uint16_t query_length, int query_type) |
362 | ++{ |
363 | ++ ofpbuf_put(dns_answer, in_queryname, query_length); |
364 | ++ put_be16(dns_answer, htons(query_type)); |
365 | ++ put_be16(dns_answer, htons(DNS_CLASS_IN)); |
366 | ++ put_be32(dns_answer, htonl(DNS_DEFAULT_RR_TTL)); |
367 | ++} |
368 | ++ |
369 | ++/* Populates dns_answer struct with a TYPE A answer. */ |
370 | ++static void |
371 | ++dns_build_a_answer( |
372 | ++ struct ofpbuf *dns_answer, const uint8_t *in_queryname, |
373 | ++ uint16_t query_length, const ovs_be32 addr) |
374 | ++{ |
375 | ++ dns_build_base_answer(dns_answer, in_queryname, query_length, |
376 | ++ DNS_QUERY_TYPE_A); |
377 | ++ put_be16(dns_answer, htons(sizeof(ovs_be32))); |
378 | ++ put_be32(dns_answer, addr); |
379 | ++} |
380 | ++ |
381 | ++/* Populates dns_answer struct with a TYPE AAAA answer. */ |
382 | ++static void |
383 | ++dns_build_aaaa_answer( |
384 | ++ struct ofpbuf *dns_answer, const uint8_t *in_queryname, |
385 | ++ uint16_t query_length, const struct in6_addr *addr) |
386 | ++{ |
387 | ++ dns_build_base_answer(dns_answer, in_queryname, query_length, |
388 | ++ DNS_QUERY_TYPE_AAAA); |
389 | ++ put_be16(dns_answer, htons(sizeof(*addr))); |
390 | ++ ofpbuf_put(dns_answer, addr, sizeof(*addr)); |
391 | ++} |
392 | ++ |
393 | ++/* Populates dns_answer struct with a TYPE PTR answer. */ |
394 | ++static void |
395 | ++dns_build_ptr_answer( |
396 | ++ struct ofpbuf *dns_answer, const uint8_t *in_queryname, |
397 | ++ uint16_t query_length, const char *answer_data) |
398 | ++{ |
399 | ++ char *encoded_answer; |
400 | ++ uint16_t encoded_answer_length; |
401 | ++ |
402 | ++ dns_build_base_answer(dns_answer, in_queryname, query_length, |
403 | ++ DNS_QUERY_TYPE_PTR); |
404 | ++ |
405 | ++ /* Initialize string 2 chars longer than real answer: |
406 | ++ * first label length and terminating zero-length label. |
407 | ++ * If the answer_data is - vm1tst.ovn.org, it will be encoded as |
408 | ++ * - 0010 (Total length which is 16) |
409 | ++ * - 06766d31747374 (vm1tst) |
410 | ++ * - 036f766e (ovn) |
411 | ++ * - 036f7267 (org |
412 | ++ * - 00 (zero length field) */ |
413 | ++ encoded_answer_length = strlen(answer_data) + 2; |
414 | ++ encoded_answer = (char *)xzalloc(encoded_answer_length); |
415 | ++ |
416 | ++ put_be16(dns_answer, htons(encoded_answer_length)); |
417 | ++ uint8_t label_len_index = 0; |
418 | ++ uint16_t label_len = 0; |
419 | ++ char *encoded_answer_ptr = (char *)encoded_answer + 1; |
420 | ++ while (*answer_data) { |
421 | ++ if (*answer_data == '.') { |
422 | ++ /* Label has ended. Update the length of the label. */ |
423 | ++ encoded_answer[label_len_index] = label_len; |
424 | ++ label_len_index += (label_len + 1); |
425 | ++ label_len = 0; /* Init to 0 for the next label. */ |
426 | ++ } else { |
427 | ++ *encoded_answer_ptr = *answer_data; |
428 | ++ label_len++; |
429 | ++ } |
430 | ++ encoded_answer_ptr++; |
431 | ++ answer_data++; |
432 | ++ } |
433 | ++ |
434 | ++ /* This is required for the last label if it doesn't end with '.' */ |
435 | ++ if (label_len) { |
436 | ++ encoded_answer[label_len_index] = label_len; |
437 | ++ } |
438 | ++ |
439 | ++ ofpbuf_put(dns_answer, encoded_answer, encoded_answer_length); |
440 | ++ free(encoded_answer); |
441 | ++} |
442 | ++ |
443 | + /* Called with in the pinctrl_handler thread context. */ |
444 | + static void |
445 | + pinctrl_handle_dns_lookup( |
446 | +@@ -1753,15 +1853,16 @@ pinctrl_handle_dns_lookup( |
447 | + } |
448 | + |
449 | + uint16_t query_type = ntohs(*ALIGNED_CAST(const ovs_be16 *, in_dns_data)); |
450 | +- /* Supported query types - A, AAAA and ANY */ |
451 | ++ /* Supported query types - A, AAAA, ANY and PTR */ |
452 | + if (!(query_type == DNS_QUERY_TYPE_A || query_type == DNS_QUERY_TYPE_AAAA |
453 | +- || query_type == DNS_QUERY_TYPE_ANY)) { |
454 | ++ || query_type == DNS_QUERY_TYPE_ANY |
455 | ++ || query_type == DNS_QUERY_TYPE_PTR)) { |
456 | + ds_destroy(&query_name); |
457 | + goto exit; |
458 | + } |
459 | + |
460 | + uint64_t dp_key = ntohll(pin->flow_metadata.flow.metadata); |
461 | +- const char *answer_ips = NULL; |
462 | ++ const char *answer_data = NULL; |
463 | + struct shash_node *iter; |
464 | + SHASH_FOR_EACH (iter, &dns_cache) { |
465 | + struct dns_data *d = iter->data; |
466 | +@@ -1771,76 +1872,58 @@ pinctrl_handle_dns_lookup( |
467 | + * lowercase to perform case insensitive lookup |
468 | + */ |
469 | + char *query_name_lower = str_tolower(ds_cstr(&query_name)); |
470 | +- answer_ips = smap_get(&d->records, query_name_lower); |
471 | ++ answer_data = smap_get(&d->records, query_name_lower); |
472 | + free(query_name_lower); |
473 | +- if (answer_ips) { |
474 | ++ if (answer_data) { |
475 | + break; |
476 | + } |
477 | + } |
478 | + } |
479 | + |
480 | +- if (answer_ips) { |
481 | ++ if (answer_data) { |
482 | + break; |
483 | + } |
484 | + } |
485 | + |
486 | + ds_destroy(&query_name); |
487 | +- if (!answer_ips) { |
488 | ++ if (!answer_data) { |
489 | + goto exit; |
490 | + } |
491 | + |
492 | +- struct lport_addresses ip_addrs; |
493 | +- if (!extract_ip_addresses(answer_ips, &ip_addrs)) { |
494 | +- goto exit; |
495 | +- } |
496 | + |
497 | + uint16_t ancount = 0; |
498 | + uint64_t dns_ans_stub[128 / 8]; |
499 | + struct ofpbuf dns_answer = OFPBUF_STUB_INITIALIZER(dns_ans_stub); |
500 | + |
501 | +- if (query_type == DNS_QUERY_TYPE_A || query_type == DNS_QUERY_TYPE_ANY) { |
502 | +- for (size_t i = 0; i < ip_addrs.n_ipv4_addrs; i++) { |
503 | +- /* Copy the answer section */ |
504 | +- /* Format of the answer section is |
505 | +- * - NAME -> The domain name |
506 | +- * - TYPE -> 2 octets containing one of the RR type codes |
507 | +- * - CLASS -> 2 octets which specify the class of the data |
508 | +- * in the RDATA field. |
509 | +- * - TTL -> 32 bit unsigned int specifying the time |
510 | +- * interval (in secs) that the resource record |
511 | +- * may be cached before it should be discarded. |
512 | +- * - RDLENGTH -> 16 bit integer specifying the length of the |
513 | +- * RDATA field. |
514 | +- * - RDATA -> a variable length string of octets that |
515 | +- * describes the resource. In our case it will |
516 | +- * be IP address of the domain name. |
517 | +- */ |
518 | +- ofpbuf_put(&dns_answer, in_queryname, idx); |
519 | +- put_be16(&dns_answer, htons(DNS_QUERY_TYPE_A)); |
520 | +- put_be16(&dns_answer, htons(DNS_CLASS_IN)); |
521 | +- put_be32(&dns_answer, htonl(DNS_DEFAULT_RR_TTL)); |
522 | +- put_be16(&dns_answer, htons(sizeof(ovs_be32))); |
523 | +- put_be32(&dns_answer, ip_addrs.ipv4_addrs[i].addr); |
524 | +- ancount++; |
525 | ++ if (query_type == DNS_QUERY_TYPE_PTR) { |
526 | ++ dns_build_ptr_answer(&dns_answer, in_queryname, idx, answer_data); |
527 | ++ ancount++; |
528 | ++ } else { |
529 | ++ struct lport_addresses ip_addrs; |
530 | ++ if (!extract_ip_addresses(answer_data, &ip_addrs)) { |
531 | ++ goto exit; |
532 | ++ } |
533 | ++ |
534 | ++ if (query_type == DNS_QUERY_TYPE_A || |
535 | ++ query_type == DNS_QUERY_TYPE_ANY) { |
536 | ++ for (size_t i = 0; i < ip_addrs.n_ipv4_addrs; i++) { |
537 | ++ dns_build_a_answer(&dns_answer, in_queryname, idx, |
538 | ++ ip_addrs.ipv4_addrs[i].addr); |
539 | ++ ancount++; |
540 | ++ } |
541 | + } |
542 | +- } |
543 | + |
544 | +- if (query_type == DNS_QUERY_TYPE_AAAA || |
545 | +- query_type == DNS_QUERY_TYPE_ANY) { |
546 | +- for (size_t i = 0; i < ip_addrs.n_ipv6_addrs; i++) { |
547 | +- ofpbuf_put(&dns_answer, in_queryname, idx); |
548 | +- put_be16(&dns_answer, htons(DNS_QUERY_TYPE_AAAA)); |
549 | +- put_be16(&dns_answer, htons(DNS_CLASS_IN)); |
550 | +- put_be32(&dns_answer, htonl(DNS_DEFAULT_RR_TTL)); |
551 | +- const struct in6_addr *ip6 = &ip_addrs.ipv6_addrs[i].addr; |
552 | +- put_be16(&dns_answer, htons(sizeof *ip6)); |
553 | +- ofpbuf_put(&dns_answer, ip6, sizeof *ip6); |
554 | +- ancount++; |
555 | ++ if (query_type == DNS_QUERY_TYPE_AAAA || |
556 | ++ query_type == DNS_QUERY_TYPE_ANY) { |
557 | ++ for (size_t i = 0; i < ip_addrs.n_ipv6_addrs; i++) { |
558 | ++ dns_build_aaaa_answer(&dns_answer, in_queryname, idx, |
559 | ++ &ip_addrs.ipv6_addrs[i].addr); |
560 | ++ ancount++; |
561 | ++ } |
562 | + } |
563 | ++ destroy_lport_addresses(&ip_addrs); |
564 | + } |
565 | + |
566 | +- destroy_lport_addresses(&ip_addrs); |
567 | +- |
568 | + if (!ancount) { |
569 | + ofpbuf_uninit(&dns_answer); |
570 | + goto exit; |
571 | +diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h |
572 | +index 507949c28..899162866 100644 |
573 | +--- a/lib/ovn-l7.h |
574 | ++++ b/lib/ovn-l7.h |
575 | +@@ -26,6 +26,14 @@ |
576 | + #include "hash.h" |
577 | + #include "ovn/logical-fields.h" |
578 | + |
579 | ++#define DNS_QUERY_TYPE_A 0x01 |
580 | ++#define DNS_QUERY_TYPE_AAAA 0x1c |
581 | ++#define DNS_QUERY_TYPE_ANY 0xff |
582 | ++#define DNS_QUERY_TYPE_PTR 0x0c |
583 | ++ |
584 | ++#define DNS_CLASS_IN 0x01 |
585 | ++#define DNS_DEFAULT_RR_TTL 3600 |
586 | ++ |
587 | + /* Generic options map which is used to store dhcpv4 opts and dhcpv6 opts. */ |
588 | + struct gen_opts_map { |
589 | + struct hmap_node hmap_node; |
590 | +diff --git a/ovn-nb.xml b/ovn-nb.xml |
591 | +index f30cc9ee9..a57e7498f 100644 |
592 | +--- a/ovn-nb.xml |
593 | ++++ b/ovn-nb.xml |
594 | +@@ -3188,7 +3188,13 @@ |
595 | + Key-value pair of DNS records with <code>DNS query name</code> as the key |
596 | + and value as a string of IP address(es) separated by comma or space. |
597 | + |
598 | ++ For PTR requests, the key-value pair can be |
599 | ++ <code>Reverse IPv4 address.in-addr.arpa</code> and the value |
600 | ++ <code>DNS domain name</code>. For IPv6 addresses, the key |
601 | ++ has to be <code>Reverse IPv6 address.ip6.arpa</code>. |
602 | ++ |
603 | + <p><b>Example: </b> "vm1.ovn.org" = "10.0.0.4 aef0::4"</p> |
604 | ++ <p><b>Example: </b> "4.0.0.10.in-addr.arpa" = "vm1.ovn.org"</p> |
605 | + </column> |
606 | + |
607 | + <column name="external_ids"> |
608 | +diff --git a/tests/ovn.at b/tests/ovn.at |
609 | +index b6eff4349..87d0bd4fc 100644 |
610 | +--- a/tests/ovn.at |
611 | ++++ b/tests/ovn.at |
612 | +@@ -8256,10 +8256,13 @@ ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4" |
613 | + |
614 | + DNS1=`ovn-nbctl create DNS records={}` |
615 | + DNS2=`ovn-nbctl create DNS records={}` |
616 | ++DNS3=`ovn-nbctl create DNS records={}` |
617 | + |
618 | + ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4" |
619 | + ovn-nbctl set DNS $DNS1 records:vm2.ovn.org="10.0.0.6 20.0.0.4" |
620 | + ovn-nbctl set DNS $DNS2 records:vm3.ovn.org="40.0.0.4" |
621 | ++ovn-nbctl set DNS $DNS3 records:4.0.0.10.in-addr.arpa="vm1.ovn.org" |
622 | ++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" |
623 | + |
624 | + ovn-nbctl set Logical_switch ls1 dns_records="$DNS1" |
625 | + |
626 | +@@ -8365,6 +8368,21 @@ set_dns_params() { |
627 | + vm1_incomplete) |
628 | + # set type to none |
629 | + type='' |
630 | ++ ;; |
631 | ++ vm1_ipv4_ptr) |
632 | ++ # 4.0.0.10.in-addr.arpa |
633 | ++ query_name=01340130013002313007696e2d61646472046172706100 |
634 | ++ type=000c |
635 | ++ # vm1.ovn.org |
636 | ++ expected_dns_answer=${query_name}${type}0001${ttl}000d03766d31036f766e036f726700 |
637 | ++ ;; |
638 | ++ vm1_ipv6_ptr) |
639 | ++ # 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 |
640 | ++ query_name=0134013001300130013001300130013001300130013001300130013001300130013001300130013001300130013001300130013001300130013001660165016103697036046172706100 |
641 | ++ type=000c |
642 | ++ # vm1.ovn.org |
643 | ++ expected_dns_answer=${query_name}${type}0001${ttl}000d03766d31036f766e036f726700 |
644 | ++ ;; |
645 | + esac |
646 | + # TTL - 3600 |
647 | + local dns_req_header=010201200001000000000000 |
648 | +@@ -8464,6 +8482,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
649 | + rm -f 1.expected |
650 | + rm -f 2.expected |
651 | + |
652 | ++ |
653 | + set_dns_params vm1 |
654 | + src_ip=`ip_to_hex 10 0 0 6` |
655 | + dst_ip=`ip_to_hex 10 0 0 1` |
656 | +@@ -8485,8 +8504,8 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
657 | + rm -f 1.expected |
658 | + rm -f 2.expected |
659 | + |
660 | +-# Try vm1 again but an all-caps query name |
661 | + |
662 | ++# Try vm1 again but an all-caps query name |
663 | + set_dns_params VM1 |
664 | + src_ip=`ip_to_hex 10 0 0 6` |
665 | + dst_ip=`ip_to_hex 10 0 0 1` |
666 | +@@ -8508,6 +8527,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
667 | + rm -f 1.expected |
668 | + rm -f 2.expected |
669 | + |
670 | ++ |
671 | + # Clear the query name options for ls1-lp2 |
672 | + ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org |
673 | + |
674 | +@@ -8528,6 +8548,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
675 | + rm -f 1.expected |
676 | + rm -f 2.expected |
677 | + |
678 | ++ |
679 | + # Clear the query name for ls1-lp1 |
680 | + # Since ls1 has no query names configued, |
681 | + # ovn-northd should not add the DNS flows. |
682 | +@@ -8550,6 +8571,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
683 | + rm -f 1.expected |
684 | + rm -f 2.expected |
685 | + |
686 | ++ |
687 | + # Test IPv6 (AAAA records) using IPv4 packet. |
688 | + # Add back the DNS options for ls1-lp1. |
689 | + ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4" |
690 | +@@ -8575,6 +8597,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
691 | + rm -f 1.expected |
692 | + rm -f 2.expected |
693 | + |
694 | ++ |
695 | + # Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet. |
696 | + set_dns_params vm1_ipv4_v6 |
697 | + src_ip=`ip_to_hex 10 0 0 6` |
698 | +@@ -8597,6 +8620,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
699 | + rm -f 1.expected |
700 | + rm -f 2.expected |
701 | + |
702 | ++ |
703 | + # Invalid type. |
704 | + set_dns_params vm1_invalid_type |
705 | + src_ip=`ip_to_hex 10 0 0 6` |
706 | +@@ -8615,6 +8639,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
707 | + rm -f 1.expected |
708 | + rm -f 2.expected |
709 | + |
710 | ++ |
711 | + # Incomplete DNS packet. |
712 | + set_dns_params vm1_incomplete |
713 | + src_ip=`ip_to_hex 10 0 0 6` |
714 | +@@ -8633,6 +8658,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
715 | + rm -f 1.expected |
716 | + rm -f 2.expected |
717 | + |
718 | ++ |
719 | + # Add one more DNS record to the ls1. |
720 | + ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2" |
721 | + |
722 | +@@ -8657,6 +8683,7 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
723 | + rm -f 1.expected |
724 | + rm -f 2.expected |
725 | + |
726 | ++ |
727 | + # Try DNS query over IPv6 |
728 | + set_dns_params vm1 |
729 | + src_ip=aef00000000000000000000000000004 |
730 | +@@ -8677,6 +8704,60 @@ reset_pcap_file hv1-vif2 hv1/vif2 |
731 | + rm -f 1.expected |
732 | + rm -f 2.expected |
733 | + |
734 | ++ |
735 | ++# Add one more DNS record to the ls1. |
736 | ++ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2 $DNS3" |
737 | ++echo "*************************" |
738 | ++ovn-sbctl list DNS |
739 | ++echo "*************************" |
740 | ++ovn-nbctl list DNS |
741 | ++echo "*************************" |
742 | ++ |
743 | ++# Test PTR record for IPv4 address using IPv4 packet. |
744 | ++set_dns_params vm1_ipv4_ptr |
745 | ++src_ip=`ip_to_hex 10 0 0 4` |
746 | ++dst_ip=`ip_to_hex 10 0 0 1` |
747 | ++dns_reply=1 |
748 | ++test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data |
749 | ++ |
750 | ++# NXT_RESUMEs should be 11. |
751 | ++OVS_WAIT_UNTIL([test 11 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
752 | ++ |
753 | ++$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets |
754 | ++cat 1.expected | cut -c -48 > expout |
755 | ++AT_CHECK([cat 1.packets | cut -c -48], [0], [expout]) |
756 | ++# Skipping the IPv4 checksum. |
757 | ++cat 1.expected | cut -c 53- > expout |
758 | ++AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout]) |
759 | ++ |
760 | ++reset_pcap_file hv1-vif1 hv1/vif1 |
761 | ++reset_pcap_file hv1-vif2 hv1/vif2 |
762 | ++rm -f 1.expected |
763 | ++rm -f 2.expected |
764 | ++ |
765 | ++ |
766 | ++# Test PTR record for IPv6 address using IPv4 packet. |
767 | ++set_dns_params vm1_ipv6_ptr |
768 | ++src_ip=`ip_to_hex 10 0 0 4` |
769 | ++dst_ip=`ip_to_hex 10 0 0 1` |
770 | ++dns_reply=1 |
771 | ++test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data |
772 | ++ |
773 | ++# NXT_RESUMEs should be 12. |
774 | ++OVS_WAIT_UNTIL([test 12 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) |
775 | ++ |
776 | ++$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets |
777 | ++cat 1.expected | cut -c -48 > expout |
778 | ++AT_CHECK([cat 1.packets | cut -c -48], [0], [expout]) |
779 | ++# Skipping the IPv4 checksum. |
780 | ++cat 1.expected | cut -c 53- > expout |
781 | ++AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout]) |
782 | ++ |
783 | ++reset_pcap_file hv1-vif1 hv1/vif1 |
784 | ++reset_pcap_file hv1-vif2 hv1/vif2 |
785 | ++rm -f 1.expected |
786 | ++rm -f 2.expected |
787 | ++ |
788 | + OVN_CLEANUP([hv1]) |
789 | + |
790 | + AT_CLEANUP |
791 | +-- |
792 | +2.33.1 |
793 | + |
794 | diff --git a/debian/patches/series b/debian/patches/series |
795 | index fbe5db9..ba80c08 100644 |
796 | --- a/debian/patches/series |
797 | +++ b/debian/patches/series |
798 | @@ -4,3 +4,5 @@ lp-1914988-tests-Use-ovn_start-in-tests-ovn-controller.at.patch |
799 | lp-1914988-tests-Make-certificate-generation-extendable.patch |
800 | lp-1914988-tests-Test-with-SSL-and-RBAC-for-controller-by-defau.patch |
801 | lp-1943266-physical-do-not-forward-traffic-from-localport-to-a-.patch |
802 | +lp-1857026-0001-DNS-Make-DNS-lookups-case-insensitive.patch |
803 | +lp-1857026-0002-controller-Add-support-for-PTR-DNS-requests.patch |
Package building in https:/ /launchpad. net/~fnordahl/ +archive/ ubuntu/ lp1857026