[7.4] b0301c538 Add vmod_h2 to control rapid_reset parameters per session
Dridi Boukelmoune
dridi.boukelmoune at gmail.com
Mon Oct 23 17:18:10 UTC 2023
commit b0301c5381373fbd8cf4d5299e27dffd1c70fbb2
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
diff --git a/include/tbl/params.h b/include/tbl/params.h
index 003f08d2a..c369bc9e7 100644
--- a/include/tbl/params.h
+++ b/include/tbl/params.h
@@ -1258,7 +1258,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 694e6c284..eab8cb0c2 100644
--- a/vmod/Makefile.am
+++ b/vmod/Makefile.am
@@ -24,6 +24,7 @@ vmod_LTLIBRARIES =
vmod_vcc_files =
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..fac5fd517
--- /dev/null
+++ b/vmod/automake_boilerplate_h2.am
@@ -0,0 +1,42 @@
+# Generated by vmodtool.py --boilerplate.
+
+vmod_h2_vcc ?= $(srcdir)/vmod_h2.vcc
+
+vmod_vcc_files += $(vmod_h2_vcc)
+
+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 += 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
+
+# A doc-change will not update mtime on the .h and .c files, so a
+# touch(1) is necessary to signal that vmodtool was in fact run.
+vcc_h2_if.c: $(VMODTOOL) $(srcdir)/vmod_h2.vcc
+ @PYTHON@ $(VMODTOOL) $(vmodtoolargs_h2) $(srcdir)/vmod_h2.vcc
+ touch vcc_h2_if.c
+
+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..28f821fe7
--- /dev/null
+++ b/vmod/vmod_h2.vcc
@@ -0,0 +1,93 @@
+#-
+# 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()
+$Restrict client
+
+Returns true when called on a session handled by the built-in HTTP2 transport.
+
+$Function DURATION rapid_reset([DURATION threshold])
+$Restrict client
+
+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])
+$Restrict client
+
+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])
+$Restrict client
+
+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()
+$Restrict client
+
+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