[6.0] cfba2637e Add vmod_h2 to control rapid_reset parameters per session

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Wed Oct 18 16:40:08 UTC 2023


commit cfba2637e10f3b23db9fa301bb353fb74f207b01
Author: Dag Haavi Finstad <daghf at varnish-software.com>
Date:   Wed Oct 18 15:17:27 2023 +0200

    Add vmod_h2 to control rapid_reset parameters per session
    
    Backport of 2cfb561ed46a2db1e6c2ef9f88cbb8eebb792f25 and 1a406e3f9a085f9d9321242c94a99080eb2be525
    
    Conflicts:
            bin/varnishtest/vmods.h
            configure.ac
            lib/Makefile.am

diff --git a/bin/varnishtest/vmods.h b/bin/varnishtest/vmods.h
index 06ab9b80c..81c12cbdb 100644
--- a/bin/varnishtest/vmods.h
+++ b/bin/varnishtest/vmods.h
@@ -35,3 +35,4 @@ VTC_VMOD(vtc)
 VTC_VMOD(blob)
 VTC_VMOD(unix)
 VTC_VMOD(proxy)
+VTC_VMOD(h2)
diff --git a/bin/varnishtest/vmodtests/h2/b00000.vtc b/bin/varnishtest/vmodtests/h2/b00000.vtc
new file mode 100644
index 000000000..aedb6aad8
--- /dev/null
+++ b/bin/varnishtest/vmodtests/h2/b00000.vtc
@@ -0,0 +1,90 @@
+varnishtest "VMOD h2 basics"
+
+varnish v1 -arg "-p feature=+http2" -vcl {
+	import h2;
+
+	backend proforma none;
+
+	sub vcl_recv {
+		return(synth(200));
+	}
+
+	sub vcl_synth {
+		set resp.http.http2-is = h2.is();
+		set resp.body = "";
+		return (deliver);
+	}
+} -start
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.status == 200
+	expect resp.http.http2-is == false
+} -start
+
+client c2 {
+	stream 7 {
+		txreq
+		rxresp
+		expect resp.status == 200
+		expect resp.http.http2-is == true
+	} -run
+} -start
+
+client c1 -wait
+client c2 -wait
+
+# coverage
+varnish v1 -vcl {
+	import h2;
+
+	backend proforma none;
+
+	sub vcl_recv {
+		return(synth(200));
+	}
+
+	sub vcl_synth {
+		set resp.http.rapid-reset-o = h2.rapid_reset(10ms);
+		set resp.http.rapid-reset-n = h2.rapid_reset();
+		set resp.http.rapid-reset-limit-o = h2.rapid_reset_limit(10);
+		set resp.http.rapid-reset-limit-n = h2.rapid_reset_limit();
+		set resp.http.rapid-reset-period-o = h2.rapid_reset_period(10s);
+		set resp.http.rapid-reset-period-n = h2.rapid_reset_period();
+		set resp.http.rapid-reset-budget = h2.rapid_reset_budget();
+		set resp.body = "";
+		return (deliver);
+	}
+}
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.status == 200
+	expect resp.http.rapid-reset-o == -1.000
+	expect resp.http.rapid-reset-n == -1.000
+	expect resp.http.rapid-reset-limit-o == -1
+	expect resp.http.rapid-reset-limit-n == -1
+	expect resp.http.rapid-reset-period-o == -1.000
+	expect resp.http.rapid-reset-period-n == -1.000
+	expect resp.http.rapid-reset-budget == -1.000
+} -start
+
+client c2 {
+	stream 7 {
+		txreq
+		rxresp
+		expect resp.status == 200
+		expect resp.http.rapid-reset-o == 1.000
+		expect resp.http.rapid-reset-n == 0.010
+		expect resp.http.rapid-reset-limit-o == 100
+		expect resp.http.rapid-reset-limit-n == 10
+		expect resp.http.rapid-reset-period-o == 60.000
+		expect resp.http.rapid-reset-period-n == 10.000
+		expect resp.http.rapid-reset-budget == 10.000
+	} -run
+} -start
+
+client c1 -wait
+client c2 -wait
diff --git a/configure.ac b/configure.ac
index b5e8b45ab..d7c7c33ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -784,6 +784,7 @@ AC_CONFIG_FILES([
     lib/libvmod_blob/Makefile
     lib/libvmod_unix/Makefile
     lib/libvmod_proxy/Makefile
+    lib/libvmod_h2/Makefile
     man/Makefile
     varnishapi.pc
     varnishapi-uninstalled.pc
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 907ee4a5e..986abf890 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -12,4 +12,5 @@ SUBDIRS = \
 	libvmod_vtc \
 	libvmod_blob \
 	libvmod_unix \
-	libvmod_proxy
+	libvmod_proxy \
+	libvmod_h2
diff --git a/lib/libvmod_h2/Makefile.am b/lib/libvmod_h2/Makefile.am
new file mode 100644
index 000000000..5013d1de1
--- /dev/null
+++ b/lib/libvmod_h2/Makefile.am
@@ -0,0 +1,3 @@
+
+libvmod_h2_la_SOURCES = vmod_h2.c
+include $(srcdir)/automake_boilerplate.am
diff --git a/lib/libvmod_h2/automake_boilerplate.am b/lib/libvmod_h2/automake_boilerplate.am
new file mode 100644
index 000000000..cf7dc7b1b
--- /dev/null
+++ b/lib/libvmod_h2/automake_boilerplate.am
@@ -0,0 +1,37 @@
+
+# Boilerplate generated by vmodtool.py - changes will be overwritten
+
+AM_LDFLAGS  = $(AM_LT_LDFLAGS)
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/bin/varnishd \
+	-I$(top_builddir)/include
+
+vmoddir = $(pkglibdir)/vmods
+vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py
+vmodtoolargs = --strict --boilerplate
+
+vmod_LTLIBRARIES = libvmod_h2.la
+
+libvmod_h2_la_CFLAGS =
+
+libvmod_h2_la_LDFLAGS = \
+	$(AM_LDFLAGS) \
+	$(VMOD_LDFLAGS)
+
+nodist_libvmod_h2_la_SOURCES = vcc_if.c vcc_if.h
+
+$(libvmod_h2_la_OBJECTS): vcc_if.h
+
+vcc_if.h vmod_h2.rst vmod_h2.man.rst: vcc_if.c
+
+vcc_if.c: $(vmodtool) $(srcdir)/vmod.vcc
+	@PYTHON@ $(vmodtool) $(vmodtoolargs) $(srcdir)/vmod.vcc
+
+EXTRA_DIST = vmod.vcc automake_boilerplate.am
+
+CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h \
+	$(builddir)/vmod_h2.rst \
+	$(builddir)/vmod_h2.man.rst
+
diff --git a/lib/libvmod_h2/vmod.vcc b/lib/libvmod_h2/vmod.vcc
new file mode 100644
index 000000000..65702aaf6
--- /dev/null
+++ b/lib/libvmod_h2/vmod.vcc
@@ -0,0 +1,88 @@
+#-
+# Copyright 2023 UPLEX - Nils Goroll Systemoptimierung
+# All rights reserved.
+#
+# Author: Nils Goroll <nils.goroll at uplex.de>
+#
+# 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.
+
+$ABI strict
+$Module h2 3 "Module to control the built-in HTTP2 transport"
+
+DESCRIPTION
+===========
+
+This VMOD contains functions to control the HTTP2 transport built into
+Varnish-Cache.
+
+$Function BOOL is()
+
+Returns true when called on a session handled by the built-in HTTP2 transport.
+
+$Function DURATION rapid_reset([DURATION threshold])
+
+Get and optionally set the ``h2_rapid_reset`` parameter (See
+:ref:`varnishd(1)`) for this HTTP2 session only.
+
+Returns -1 when used outside the HTTP2 transport. Otherwise returns
+the previous value.
+
+If the call leads to a change in the rate limit parameters, the
+current budget as retuned by
+`h2.rapid_reset_budget()` is reset.
+
+$Function INT rapid_reset_limit([INT number])
+
+Get and optionally set the ``h2_rapid_reset_limit`` parameter (See
+:ref:`varnishd(1)`) for this HTTP2 session only.
+
+Returns -1 when used outside the HTTP2 transport. Otherwise returns
+the previous value.
+
+If the call leads to a change in the rate limit parameters, the
+current budget as retuned by
+`h2.rapid_reset_budget()` is reset.
+
+$Function DURATION rapid_reset_period([DURATION duration])
+
+Get and optionally set the ``h2_rapid_reset_period`` parameter (See
+:ref:`varnishd(1)`) for this HTTP2 session only.
+
+Returns -1 when used outside the HTTP2 transport. Otherwise returns
+the previous value.
+
+If the call leads to a change in the rate limit parameters, the
+current budget as retuned by
+`h2.rapid_reset_budget()` is reset.
+
+$Function REAL rapid_reset_budget()
+
+Return how many RST frames classified as "rapid" the client is still
+allowed to send before the session is going to be closed.
+
+SEE ALSO
+========
+
+* :ref:`varnishd(1)`
+* :ref:`vsl(7)`
diff --git a/lib/libvmod_h2/vmod_h2.c b/lib/libvmod_h2/vmod_h2.c
new file mode 100644
index 000000000..2153e979e
--- /dev/null
+++ b/lib/libvmod_h2/vmod_h2.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright 2023 UPLEX - Nils Goroll Systemoptimierung
+ * All rights reserved.
+ *
+ * Author: Nils Goroll <nils.goroll at uplex.de>
+ *
+ * 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 "cache/cache_varnishd.h"
+
+#include "vcc_if.h"
+
+#include "cache/cache_transport.h"
+#include "http2/cache_http2.h"
+
+static struct h2_sess *
+h2get(VRT_CTX)
+{
+	struct h2_sess *h2;
+	uintptr_t *up;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); // $Restrict client
+	if (ctx->req->transport != &H2_transport)
+		return (NULL);
+	AZ(SES_Get_proto_priv(ctx->req->sp, &up));
+	CAST_OBJ_NOTNULL(h2, (void *)*up, H2_SESS_MAGIC);
+	return (h2);
+}
+VCL_BOOL
+vmod_is(VRT_CTX)
+{
+	struct h2_sess *h2 = h2get(ctx);
+
+	return (h2 != NULL);
+}
+
+#define GETSET(type, name, argname) \
+type							\
+vmod_ ## name(VRT_CTX, struct vmod_##name##_arg *args)	\
+{							\
+	struct h2_sess *h2 = h2get(ctx);		\
+	type r;						\
+							\
+	if (h2 == NULL)					\
+		return (-1);				\
+							\
+	if (! args->valid_ ## argname)			\
+		return (h2->name);			\
+	if (h2->name == args->argname)			\
+		return (h2->name);			\
+							\
+	Lck_Lock(&h2->sess->mtx);			\
+	r = h2->name;					\
+	if (h2->name != args->argname) {		\
+		h2->name = args->argname;		\
+		h2->rst_budget = h2->rapid_reset_limit;	\
+		h2->last_rst = ctx->now;		\
+	}						\
+	Lck_Unlock(&h2->sess->mtx);			\
+	return (r);					\
+}
+
+GETSET(VCL_DURATION, rapid_reset, threshold)
+GETSET(VCL_INT, rapid_reset_limit, number)
+GETSET(VCL_DURATION, rapid_reset_period, duration)
+
+VCL_REAL
+vmod_rapid_reset_budget(VRT_CTX)
+{
+	struct h2_sess *h2 = h2get(ctx);
+
+	if (h2 == NULL)
+		return (-1);
+
+	return (h2->rst_budget);
+}
diff --git a/man/Makefile.am b/man/Makefile.am
index 0e35dc5bf..1c2714872 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -21,7 +21,8 @@ dist_man_MANS = \
 	vmod_vtc.3 \
 	vmod_blob.3 \
 	vmod_unix.3 \
-	vmod_proxy.3
+	vmod_proxy.3 \
+	vmod_h2.3
 
 CLEANFILES = $(dist_man_MANS)
 
@@ -109,4 +110,7 @@ vmod_unix.3: $(top_builddir)/lib/libvmod_unix/vmod_unix.man.rst
 vmod_proxy.3: $(top_builddir)/lib/libvmod_proxy/vmod_proxy.man.rst
 	${RST2MAN} $(RST2ANY_FLAGS) $? $@
 
+vmod_h2.3: $(top_builddir)/lib/libvmod_h2/vmod_h2.man.rst
+	${RST2MAN} $(RST2ANY_FLAGS) $? $@
+
 .NOPATH: $(dist_man_MANS)


More information about the varnish-commit mailing list