Skip to content

Commit f64e9ce

Browse files
committed
+fold acl flag: remove subnets and fold adjacent entries
Function: With the fold acl flag enabled (default: disabled, keeping the existing behavior), ACLs are optimized in that subnets contained in other entries are skipped (e.g. if 1.2.3.0/24 is part of the ACL, an entry for 1.2.3.128/25 will not be added) and adjacent entries get folded (e.g. if both 1.2.3.0/25 and 1.2.3.128/25 are added, they will be folded to 1.2.3.0/24). Skip and fold operations on VCL entries are output as warnings during VCL compilation as entries from the VCL are processed in order. Logging under the VCL_acl tag can change with this parameter enabled: Matches on skipped subnet entries are now logged as matches on the respective supernet entry. Matches on folded entries are logged with a shorter netmask which might not be contained in the original ACL as defined in VCL. Such log entries are marked by "fixed: folded". Negated ACL entries are excluded from folds. Implementation: The sort functions are changed such that the previous semantics are preserved: negative return values signify "a < b", positive return values signify "a > b". But additionally the values -2/2 and -3/3 are introduced (and given enums) to signify "contained in supernet" and "directly adjacent to". This allows for mostly unchanged code with vcc_acl_fold disabled. For the "subnet contained in supernet" case, all contained subnets are removed. By sort order, caontained subnets are always to be found left of supernets. For the "fold adjacent" case, the netmask of the entry with the smaller network number is decreased by one and the other entry removed. Because changing the netmask might affect sort order, we reinsert the changed entry.
1 parent 1abecec commit f64e9ce

File tree

4 files changed

+306
-26
lines changed

4 files changed

+306
-26
lines changed

bin/varnishtest/tests/c00005.vtc

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,170 @@ varnish v1 -errvcl {Non-zero bits in masked part} {
162162
if (client.ip ~ acl1) {}
163163
}
164164
}
165+
166+
# this is both an OK test for pedantic and fold
167+
varnish v1 -vcl {
168+
import std;
169+
170+
backend dummy None;
171+
172+
acl acl1 +log +pedantic +fold {
173+
# bad notation (confusing)
174+
"1.2.3.0"/24;
175+
"1.2.3.64"/26;
176+
177+
# all contained in 1.3.0.0/21 and 1.4.4.0/22
178+
"1.4.4.0"/22;
179+
"1.3.4.0"/23;
180+
"1.3.5.0"/26;
181+
"1.3.6.0"/25;
182+
"1.3.6.128"/25;
183+
"1.3.0.0"/21;
184+
"1.4.7";
185+
"1.4.6.0"/24;
186+
187+
# right,left adjacent
188+
"2.3.2.0"/23;
189+
"2.3.0.0"/23;
190+
# left,right adjacent
191+
"2.3.4.0"/23;
192+
"2.3.6.0"/23;
193+
194+
# 12/14 folded, not 10
195+
"2.10.0.0"/15;
196+
"2.12.0.0"/15;
197+
"2.14.0.0"/15;
198+
199+
# 226/227 folded, not 225
200+
"2.225.0.0"/16;
201+
"2.226.0.0"/16;
202+
"2.227.0.0"/16;
203+
204+
# phks test case
205+
"10.0.0.0"/23;
206+
"10.0.2.0"/23;
207+
208+
"10.1.0.0"/24;
209+
"10.1.1.0"/24;
210+
211+
"10.2.0.0"/25;
212+
"10.2.0.128"/25;
213+
}
214+
215+
sub vcl_recv {
216+
return (synth(200));
217+
}
218+
sub t {
219+
if (std.ip(req.http.ip) ~ acl1) { }
220+
}
221+
sub vcl_synth {
222+
# variables would be nice, but not in core (yet?)
223+
set req.http.ip = "1.2.3.0"; call t;
224+
set req.http.ip = "1.2.3.63"; call t;
225+
set req.http.ip = "1.2.3.64"; call t;
226+
227+
set req.http.ip = "1.3.4.255"; call t;
228+
set req.http.ip = "1.3.5.0"; call t;
229+
set req.http.ip = "1.3.5.255"; call t;
230+
set req.http.ip = "1.3.6.0"; call t;
231+
set req.http.ip = "1.3.6.140"; call t;
232+
set req.http.ip = "1.3.7.255"; call t;
233+
234+
set req.http.ip = "1.4.5.255"; call t;
235+
set req.http.ip = "1.4.6.64"; call t;
236+
set req.http.ip = "1.4.7.64"; call t;
237+
238+
set req.http.ip = "2.3.0.0"; call t;
239+
set req.http.ip = "2.3.5.255"; call t;
240+
241+
set req.http.ip = "2.2.255.255";call t;
242+
set req.http.ip = "2.3.8.0"; call t;
243+
244+
set req.http.ip = "2.9.1.1"; call t;
245+
set req.http.ip = "2.10.1.1"; call t;
246+
set req.http.ip = "2.12.0.0"; call t;
247+
set req.http.ip = "2.15.255.255";call t;
248+
set req.http.ip = "2.16.1.1"; call t;
249+
250+
set req.http.ip = "2.224.1.1"; call t;
251+
set req.http.ip = "2.225.1.1"; call t;
252+
set req.http.ip = "2.226.1.1"; call t;
253+
set req.http.ip = "2.227.1.1"; call t;
254+
255+
set req.http.ip = "10.0.3.255"; call t;
256+
set req.http.ip = "10.1.1.255"; call t;
257+
set req.http.ip = "10.2.0.255"; call t;
258+
}
259+
}
260+
261+
logexpect l1 -v v1 -g raw {
262+
expect * 1009 ReqHeader {^\Qip: 1.2.3.0\E$}
263+
expect 0 = VCL_acl {^\QMATCH acl1 "1.2.3.0"/24\E$}
264+
expect 1 = ReqHeader {^\Qip: 1.2.3.63\E$}
265+
expect 0 = VCL_acl {^\QMATCH acl1 "1.2.3.0"/24\E$}
266+
expect 1 = ReqHeader {^\Qip: 1.2.3.64\E$}
267+
expect 0 = VCL_acl {^\QMATCH acl1 "1.2.3.0"/24\E$}
268+
269+
expect 1 = ReqHeader {^\Qip: 1.3.4.255\E$}
270+
expect 0 = VCL_acl {^\QMATCH acl1 "1.3.0.0"/21\E$}
271+
expect 1 = ReqHeader {^\Qip: 1.3.5.0\E$}
272+
expect 0 = VCL_acl {^\QMATCH acl1 "1.3.0.0"/21\E$}
273+
expect 1 = ReqHeader {^\Qip: 1.3.5.255\E$}
274+
expect 0 = VCL_acl {^\QMATCH acl1 "1.3.0.0"/21\E$}
275+
expect 1 = ReqHeader {^\Qip: 1.3.6.0\E$}
276+
expect 0 = VCL_acl {^\QMATCH acl1 "1.3.0.0"/21\E$}
277+
expect 1 = ReqHeader {^\Qip: 1.3.6.140\E$}
278+
expect 0 = VCL_acl {^\QMATCH acl1 "1.3.0.0"/21\E$}
279+
expect 1 = ReqHeader {^\Qip: 1.3.7.255\E$}
280+
expect 0 = VCL_acl {^\QMATCH acl1 "1.3.0.0"/21\E$}
281+
282+
expect 1 = ReqHeader {^\Qip: 1.4.5.255\E$}
283+
expect 0 = VCL_acl {^\QMATCH acl1 "1.4.4.0"/22\E$}
284+
expect 1 = ReqHeader {^\Qip: 1.4.6.64\E$}
285+
expect 0 = VCL_acl {^\QMATCH acl1 "1.4.4.0"/22\E$}
286+
expect 1 = ReqHeader {^\Qip: 1.4.7.64\E$}
287+
expect 0 = VCL_acl {^\QMATCH acl1 "1.4.4.0"/22\E$}
288+
289+
expect 1 = ReqHeader {^\Qip: 2.3.0.0\E$}
290+
expect 0 = VCL_acl {^\QMATCH acl1 "2.3.0.0"/21 fixed: folded\E}
291+
expect 1 = ReqHeader {^\Qip: 2.3.5.255\E$}
292+
expect 0 = VCL_acl {^\QMATCH acl1 "2.3.0.0"/21 fixed: folded\E}
293+
expect 1 = ReqHeader {^\Qip: 2.2.255.255\E$$}
294+
expect 0 = VCL_acl {^\QNO_MATCH acl1\E$}
295+
expect 1 = ReqHeader {^\Qip: 2.3.8.0\E$}
296+
expect 0 = VCL_acl {^\QNO_MATCH acl1\E$}
297+
298+
expect 1 = ReqHeader {^\Qip: 2.9.1.1\E$}
299+
expect 0 = VCL_acl {^\QNO_MATCH acl1\E$}
300+
expect 1 = ReqHeader {^\Qip: 2.10.1.1\E$}
301+
expect 0 = VCL_acl {^\QMATCH acl1 "2.10.0.0"/15\E$}
302+
expect 1 = ReqHeader {^\Qip: 2.12.0.0\E$}
303+
expect 0 = VCL_acl {^\QMATCH acl1 "2.12.0.0"/14 fixed: folded\E}
304+
expect 1 = ReqHeader {^\Qip: 2.15.255.255\E$}
305+
expect 0 = VCL_acl {^\QMATCH acl1 "2.12.0.0"/14 fixed: folded\E}
306+
expect 1 = ReqHeader {^\Qip: 2.16.1.1\E$}
307+
expect 0 = VCL_acl {^\QNO_MATCH acl1\E}
308+
309+
expect 1 = ReqHeader {^\Qip: 2.224.1.1\E$}
310+
expect 0 = VCL_acl {^\QNO_MATCH acl1\E$}
311+
expect 1 = ReqHeader {^\Qip: 2.225.1.1\E$}
312+
expect 0 = VCL_acl {^\QMATCH acl1 "2.225.0.0"/16\E$}
313+
expect 1 = ReqHeader {^\Qip: 2.226.1.1\E$}
314+
expect 0 = VCL_acl {^\QMATCH acl1 "2.226.0.0"/15 fixed: folded\E}
315+
expect 1 = ReqHeader {^\Qip: 2.227.1.1\E$}
316+
expect 0 = VCL_acl {^\QMATCH acl1 "2.226.0.0"/15 fixed: folded\E}
317+
318+
expect 1 = ReqHeader {^\Qip: 10.0.3.255\E$}
319+
expect 0 = VCL_acl {^\QMATCH acl1 "10.0.0.0"/22 fixed: folded\E}
320+
expect 1 = ReqHeader {^\Qip: 10.1.1.255\E$}
321+
expect 0 = VCL_acl {^\QMATCH acl1 "10.1.0.0"/23 fixed: folded\E}
322+
expect 1 = ReqHeader {^\Qip: 10.2.0.255\E$}
323+
expect 0 = VCL_acl {^\QMATCH acl1 "10.2.0.0"/24 fixed: folded\E}
324+
} -start
325+
326+
client c1 {
327+
txreq
328+
rxresp
329+
} -run
330+
331+
logexpect l1 -wait

doc/sphinx/reference/vcl.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,27 @@ individually:
299299
However, if the name resolves to both IPv4 and IPv6 you will still
300300
get an error.
301301

302+
* `+fold` - Fold ACL supernets and adjacent networks.
303+
304+
With this parameter set to on, ACLs are optimized in that subnets
305+
contained in other entries are skipped (e.g. if 1.2.3.0/24 is part
306+
of the ACL, an entry for 1.2.3.128/25 will not be added) and
307+
adjacent entries get folded (e.g. if both 1.2.3.0/25 and
308+
1.2.3.128/25 are added, they will be folded to 1.2.3.0/24).
309+
310+
Skip and fold operations on VCL entries are output as warnings
311+
during VCL compilation as entries from the VCL are processed in
312+
order.
313+
314+
Logging under the ``VCL_acl`` tag can change with this parameter
315+
enabled: Matches on skipped subnet entries are now logged as matches
316+
on the respective supernet entry. Matches on folded entries are
317+
logged with a shorter netmask which might not be contained in the
318+
original ACL as defined in VCL. Such log entries are marked by
319+
``fixed: folded``.
320+
321+
Negated ACL entries are never folded.
322+
302323
VCL objects
303324
-----------
304325

include/tbl/vsl_tags.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,19 @@ SLTM(Fetch_Body, 0, "Body fetched from backend",
264264
SLTM(VCL_acl, 0, "VCL ACL check results",
265265
"ACLs with the `+log` flag emits this record with the result.\n\n"
266266
"The format is::\n\n"
267-
"\t%s %s [%s [fixed: %s]]\n"
268-
"\t| | | |\n"
269-
"\t| | | +- Fixed entry (see acl +pedantic flag)\n"
270-
"\t| | +------------ Matching entry (only for MATCH)\n"
271-
"\t| +---------------- Name of the ACL\n"
272-
"\t+-------------------- MATCH or NO_MATCH\n"
273-
"\n"
274-
"MATCH denotes an ACL match\n"
275-
"NO_MATCH denotes that a checked ACL has not matched\n"
267+
"\t%s [%s [%s [fixed: %s]]]\n"
268+
"\t| | | |\n"
269+
"\t| | | +- Fix info (see below)\n"
270+
"\t| | +------------ Matching entry (only for MATCH)\n"
271+
"\t| +---------------- Name of the ACL for MATCH or NO_MATCH\n"
272+
"\t+-------------------- MATCH, NO_MATCH or NO_FAM\n"
273+
"\n"
274+
"* Fix info: either contains network/mask for non-canonical entries "
275+
"(see acl +pedantic flag) or ``folded`` for entries "
276+
"which were the result of a fold operation (see acl +fold flag).\n"
277+
"* ``MATCH`` denotes an ACL match\n"
278+
"* ``NO_MATCH`` denotes that a checked ACL has not matched\n"
279+
"* ``NO_FAM`` denotes a missing address family and should not occur.\n"
276280
"\n"
277281
)
278282

0 commit comments

Comments
 (0)