[7.3] c9f0a4483 Add vmod_h2 to control rapid_reset parameters per session

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Tue Oct 24 15:08:13 UTC 2023


commit c9f0a4483a459d42aaaa39b14ec6e2b834efa275
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Mon Oct 16 16:07:05 2023 +0200

    Add vmod_h2 to control rapid_reset parameters per session
    
    Conflicts:
            vmod/automake_boilerplate_h2.am
            vmod/vmod_h2.vcc

diff --git a/include/tbl/params.h b/include/tbl/params.h
index 679d29894..1a9fe78ad 100644
--- a/include/tbl/params.h
+++ b/include/tbl/params.h
@@ -1244,7 +1244,9 @@ PARAM_SIMPLE(
 )
 
 #define H2_RR_INFO \
-	"Changes to this parameter affect the default for new HTTP2 sessions"
+	"Changes to this parameter affect the default for new HTTP2 " \
+	"sessions. vmod_h2(3) can be used to adjust it from VCL."
+
 PARAM_SIMPLE(
 	/* name */	h2_rapid_reset,
 	/* typ */	timeout,
diff --git a/vmod/Makefile.am b/vmod/Makefile.am
index 29ffcf6bd..da6eaaeff 100644
--- a/vmod/Makefile.am
+++ b/vmod/Makefile.am
@@ -20,6 +20,7 @@ AM_CPPFLAGS = \
 vmod_LTLIBRARIES =
 
 include $(srcdir)/automake_boilerplate_blob.am
+include $(srcdir)/automake_boilerplate_h2.am
 include $(srcdir)/automake_boilerplate_cookie.am
 include $(srcdir)/automake_boilerplate_debug.am
 include $(srcdir)/automake_boilerplate_directors.am
diff --git a/vmod/automake_boilerplate_h2.am b/vmod/automake_boilerplate_h2.am
new file mode 100644
index 000000000..905014e23
--- /dev/null
+++ b/vmod/automake_boilerplate_h2.am
@@ -0,0 +1,35 @@
+# Generated by vmodtool.py --boilerplate.
+
+vmod_LTLIBRARIES += libvmod_h2.la
+
+libvmod_h2_la_SOURCES = \
+	vmod_h2.c
+
+libvmod_h2_la_CFLAGS =
+
+vmodtoolargs_h2 ?= --strict --boilerplate -o vcc_h2_if
+vmod_h2_symbols_regex ?= Vmod_h2_Data
+
+libvmod_h2_la_LDFLAGS = \
+	-export-symbols-regex $(vmod_h2_symbols_regex) \
+	$(AM_LDFLAGS) \
+	$(VMOD_LDFLAGS)
+
+nodist_libvmod_h2_la_SOURCES = vcc_h2_if.c vcc_h2_if.h
+
+EXTRA_libvmod_h2_la_DEPENDENCIES = $(nodist_libvmod_h2_la_SOURCES)
+
+EXTRA_DIST += $(srcdir)/vmod_h2.vcc automake_boilerplate_h2.am
+
+$(libvmod_h2_la_OBJECTS): vcc_h2_if.h
+
+vcc_h2_if.h vmod_h2.rst vmod_h2.man.rst: vcc_h2_if.c
+
+vcc_h2_if.c: $(vmodtool) $(srcdir)/vmod_h2.vcc
+	@PYTHON@ $(vmodtool) $(vmodtoolargs_h2) $(srcdir)/vmod_h2.vcc
+
+clean-local: clean-vmod-h2
+
+clean-vmod-h2:
+	rm -f $(nodist_libvmod_h2_la_SOURCES)
+	rm -f vmod_h2.rst vmod_h2.man.rst
diff --git a/vmod/tests/h2_b00000.vtc b/vmod/tests/h2_b00000.vtc
new file mode 100644
index 000000000..e6754fc84
--- /dev/null
+++ b/vmod/tests/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(100);
+		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 == 0
+		expect resp.http.rapid-reset-limit-n == 100
+		expect resp.http.rapid-reset-period-o == 60.000
+		expect resp.http.rapid-reset-period-n == 10.000
+		expect resp.http.rapid-reset-budget == 100.000
+	} -run
+} -start
+
+client c1 -wait
+client c2 -wait
diff --git a/vmod/vmod_h2.c b/vmod/vmod_h2.c
new file mode 100644
index 000000000..bded788f4
--- /dev/null
+++ b/vmod/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_h2_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 != &HTTP2_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 VARGS(name) *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/vmod/vmod_h2.vcc b/vmod/vmod_h2.vcc
new file mode 100644
index 000000000..cd7529c9f
--- /dev/null
+++ b/vmod/vmod_h2.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)`


More information about the varnish-commit mailing list