[master] 7b64147e9 Add debug.sweep_acl() for ACL testing

Poul-Henning Kamp phk at FreeBSD.org
Tue Mar 23 10:16:05 UTC 2021


commit 7b64147e9cdb77361f3b53a58f5a30fdd3813779
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Mar 23 10:11:35 2021 +0000

    Add debug.sweep_acl() for ACL testing

diff --git a/vmod/automake_boilerplate_debug.am b/vmod/automake_boilerplate_debug.am
index 88f89a403..5617c04c9 100644
--- a/vmod/automake_boilerplate_debug.am
+++ b/vmod/automake_boilerplate_debug.am
@@ -4,6 +4,7 @@ vmod_LTLIBRARIES += libvmod_debug.la
 
 libvmod_debug_la_SOURCES = \
 	vmod_debug.c \
+	vmod_debug_acl.c \
 	vmod_debug_dyn.c \
 	vmod_debug_obj.c
 
diff --git a/vmod/vmod_debug.c b/vmod/vmod_debug.c
index 8f123c276..a203af31b 100644
--- a/vmod/vmod_debug.c
+++ b/vmod/vmod_debug.c
@@ -665,17 +665,6 @@ xyzzy_vcl_discard_delay(VRT_CTX, struct vmod_priv *priv, VCL_DURATION delay)
 	priv_vcl->vcl_discard_delay = delay;
 }
 
-VCL_BOOL v_matchproto_(td_debug_match_acl)
-xyzzy_match_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip)
-{
-
-	CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
-	AN(acl);
-	assert(VSA_Sane(ip));
-
-	return (VRT_acl_match(ctx, acl, ip));
-}
-
 VCL_VOID v_matchproto_(td_debug_test_probe)
 xyzzy_test_probe(VRT_CTX, VCL_PROBE probe, VCL_PROBE same)
 {
diff --git a/vmod/vmod_debug.vcc b/vmod/vmod_debug.vcc
index c15079630..cdafcc4d3 100644
--- a/vmod/vmod_debug.vcc
+++ b/vmod/vmod_debug.vcc
@@ -178,6 +178,22 @@ $Function BOOL match_acl(ACL acl, IP ip)
 
 Perform an IP match against a named ACL.
 
+$Function BLOB sweep_acl(ACL acl, IP ip0, IP ip1, INT step = 1)
+
+Sweep `acl` through IP#s `ip0` ... `ip1` and return a hash-signature
+of the results.
+
+VSL_Debug lines will be emitted for every 64 addresses (you probably want:
+`-p vsl_mask=+Debug,-VCL_acl`
+
+Only the lower 64 bits of IPv4 addresses are stepped.
+
+$Function DURATION time_acl(ACL acl, IP ip0, IP ip1, INT step = 1, INT rounds = 1000)
+
+Time `rounds` sweeps from `ip0` to `ip1` through `acl`.
+
+Consider: `-p vsl_mask=-VCL_acl`
+
 $Function VOID test_probe(PROBE probe, PROBE same = 0)
 
 Only here to make sure probe definitions are passed properly.
diff --git a/vmod/vmod_debug_acl.c b/vmod/vmod_debug_acl.c
new file mode 100644
index 000000000..cb5fd3424
--- /dev/null
+++ b/vmod/vmod_debug_acl.c
@@ -0,0 +1,250 @@
+/*-
+ * Copyright (c) 2012-2019 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+// #include "vdef.h"
+//#include "vas.h"
+#include "cache/cache.h"
+#include "vend.h"
+#include "vsa.h"
+#include "vsb.h"
+#include "vsha256.h"
+#include "vtcp.h"
+#include "vtim.h"
+#include "vcc_debug_if.h"
+
+VCL_BOOL v_matchproto_(td_debug_match_acl)
+xyzzy_match_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip)
+{
+
+	CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
+	AN(acl);
+	assert(VSA_Sane(ip));
+
+	return (VRT_acl_match(ctx, acl, ip));
+}
+
+/*
+ * The code below is more intimate with VSA than anything is supposed to.
+ */
+
+struct acl_sweep {
+	int			family;
+	const uint8_t		*ip0_p;
+	const uint8_t		*ip1_p;
+	struct suckaddr		*probe;
+	uint8_t			*probe_p;
+	VCL_INT			step;
+	uint64_t		reset;
+	uint64_t		this;
+	uint64_t		count;
+};
+
+static void
+reset_sweep(struct acl_sweep *asw)
+{
+	asw->this = asw->reset;
+}
+
+static int
+setup_sweep(VRT_CTX, struct acl_sweep *asw, VCL_IP ip0, VCL_IP ip1,
+    VCL_INT step)
+{
+	int fam0, fam1;
+	const uint8_t *ptr;
+
+	AN(asw);
+	memset(asw, 0, sizeof *asw);
+
+	AN(ip0);
+	AN(ip1);
+	fam0 = VSA_GetPtr(ip0, &asw->ip0_p);
+	fam1 = VSA_GetPtr(ip1, &asw->ip1_p);
+	if (fam0 != fam1) {
+		VRT_fail(ctx, "IPs have different families (0x%x vs 0x%x)",
+		    fam0, fam1);
+		return (-1);
+	}
+
+	asw->family = fam0;
+	if (asw->family == PF_INET) {
+		if (memcmp(asw->ip0_p, asw->ip1_p, 4) > 0) {
+			VRT_fail(ctx, "Sweep: ipv4.end < ipv4.start");
+			return (-1);
+		}
+		asw->reset = vbe32dec(asw->ip0_p);
+	} else {
+		if (memcmp(asw->ip0_p, asw->ip1_p, 16) > 0) {
+			VRT_fail(ctx, "Sweep: ipv6.end < ipv6.start");
+			return (-1);
+		}
+		asw->reset = vbe64dec(asw->ip0_p + 8);
+	}
+	asw->this = asw->reset;
+
+	asw->probe = VSA_Clone(ip0);
+	(void)VSA_GetPtr(asw->probe, &ptr);
+	asw->probe_p = TRUST_ME(ptr);
+
+	asw->step = step;
+
+	return (0);
+}
+
+static void
+cleanup_sweep(struct acl_sweep *asw)
+{
+	free(asw->probe);
+	memset(asw, 0, sizeof *asw);
+}
+
+static int
+step_sweep(struct acl_sweep *asw)
+{
+
+	AN(asw);
+	asw->count++;
+	asw->this += asw->step;
+	if (asw->family == PF_INET) {
+		vbe32enc(asw->probe_p, asw->this);
+		return (memcmp(asw->probe_p, asw->ip1_p, 4));
+	} else {
+		vbe64enc(asw->probe_p + 8, asw->this);
+		return (memcmp(asw->probe_p, asw->ip1_p, 16));
+	}
+}
+
+
+VCL_BLOB
+xyzzy_sweep_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip0, VCL_IP ip1, VCL_INT step)
+{
+	struct acl_sweep asw[1];
+	int i, j;
+	struct vsb *vsb;
+	char abuf[VTCP_ADDRBUFSIZE];
+	char pbuf[VTCP_PORTBUFSIZE];
+	unsigned char digest[VSHA256_DIGEST_LENGTH];
+	struct VSHA256Context vsha[1];
+	struct vrt_blob *b;
+	ssize_t sz;
+
+	vsb = VSB_new_auto();
+	AN(vsb);
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	AN(acl);
+	AN(ip0);
+	AN(ip1);
+	assert(step > 0);
+	if (setup_sweep(ctx, asw, ip0, ip1, step))
+		return(NULL);
+	VSHA256_Init(vsha);
+	for (j = 0; ; j++) {
+		if ((j & 0x3f) == 0x00) {
+			VTCP_name(asw->probe, abuf, sizeof abuf,
+			    pbuf, sizeof pbuf);
+			VSB_printf(vsb, "Sweep: %-15s", abuf);
+		}
+		i = VRT_acl_match(ctx, acl, asw->probe);
+		assert(0 <= i && i <= 1);
+		VSB_putc(vsb, "-X"[i]);
+		if ((j & 0x3f) == 0x3f) {
+			AZ(VSB_finish(vsb));
+			VSLb(ctx->vsl, SLT_Debug, "%s", VSB_data(vsb));
+			sz =VSB_len(vsb);
+			assert (sz > 0);
+			VSHA256_Update(vsha, VSB_data(vsb), sz);
+			VSB_clear(vsb);
+		}
+		if (step_sweep(asw) > 0)
+			break;
+	}
+	if (VSB_len(vsb)) {
+		AZ(VSB_finish(vsb));
+		VSLb(ctx->vsl, SLT_Debug, "%s", VSB_data(vsb));
+		sz =VSB_len(vsb);
+		assert (sz > 0);
+		VSHA256_Update(vsha, VSB_data(vsb), sz);
+		VSB_clear(vsb);
+	}
+	VSB_destroy(&vsb);
+
+	VSHA256_Final(digest, vsha);
+	b = WS_Alloc(ctx->ws, sizeof *b + sizeof digest);
+	if (b != NULL) {
+		memcpy(b + 1, digest, sizeof digest);
+		b->blob = b + 1;
+		b->len = sizeof digest;
+	}
+	cleanup_sweep(asw);
+	return (b);
+}
+
+VCL_DURATION
+xyzzy_time_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip0, VCL_IP ip1,
+    VCL_INT step, VCL_INT turnus)
+{
+	struct acl_sweep asw[1];
+	vtim_mono t0, t1;
+	VCL_INT cnt;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	AN(acl);
+	AN(ip0);
+	AN(ip1);
+	assert(step > 0);
+	assert(turnus > 0);
+
+	if (setup_sweep(ctx, asw, ip0, ip1, step))
+		return(-1);
+	do {
+		(void)VRT_acl_match(ctx, acl, asw->probe);
+	} while (step_sweep(asw) <= 0);
+	asw->count = 0;
+	t0 = VTIM_mono();
+	for (cnt = 0; cnt < turnus; cnt++) {
+		reset_sweep(asw);
+		do {
+			(void)VRT_acl_match(ctx, acl, asw->probe);
+		} while (step_sweep(asw) <= 0);
+	}
+	t1 = VTIM_mono();
+	VSLb(ctx->vsl, SLT_Debug,
+	    "Timed ACL: %.9f -> %.9f = %.9f %.9f/round, %.9f/IP %jd IPs",
+	    t0, t1, t1 - t0, (t1-t0) / turnus, (t1-t0) / asw->count, asw->count);
+	return ((t1 - t0) / asw->count);
+}


More information about the varnish-commit mailing list