diff options
-rw-r--r-- | NEWS | 11 | ||||
-rw-r--r-- | configure.ac | 14 | ||||
-rw-r--r-- | src/.gitignore | 1 | ||||
-rw-r--r-- | src/Makefile.am | 31 | ||||
-rw-r--r-- | src/getla.c | 11 | ||||
-rw-r--r-- | src/sleep.c | 8 | ||||
-rw-r--r-- | src/tbf.c | 30 | ||||
-rw-r--r-- | src/tbf.h | 38 | ||||
-rw-r--r-- | src/time.c | 23 | ||||
-rw-r--r-- | src/vmod_tbf.vcc | 47 | ||||
-rw-r--r-- | tests/.gitignore | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 31 | ||||
-rw-r--r-- | tests/test00.vti (renamed from tests/test00.vtc) | 6 | ||||
-rw-r--r-- | tests/test02.vti (renamed from tests/test02.vtc) | 6 |
14 files changed, 183 insertions, 76 deletions
@@ -1,21 +1,26 @@ -vmod-tbf -- history of user-visible changes. 2013-10-19 -Copyright (C) 2013 Sergey Poznyakoff +vmod-tbf -- history of user-visible changes. 2014-10-31 +Copyright (C) 2013-2014 Sergey Poznyakoff See the end of file for copying conditions. Please send vmod-tbf bug reports to <gray@gnu.org> +Version 1.0.90 (git) + +Support for VCL 4.0 + + Version 1.0, 2013-10-19 Initial release ========================================================================= Copyright information: -Copyright (C) 2013 Sergey Poznyakoff +Copyright (C) 2013-2014 Sergey Poznyakoff Permission is granted to anyone to make or distribute verbatim copies of this document as received, in any medium, provided that the copyright notice and this permission notice are preserved, thus giving the recipient permission to redistribute in turn. diff --git a/configure.ac b/configure.ac index 6af8fd6..70fd78d 100644 --- a/configure.ac +++ b/configure.ac @@ -11,13 +11,13 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with vmod-tbf. If not, see <http://www.gnu.org/licenses/>. AC_PREREQ(2.69) -AC_INIT([vmod-tbf], 1.0, [gray@gnu.org]) +AC_INIT([vmod-tbf], 1.0.90, [gray@gnu.org]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR(src/vmod_tbf.vcc) AM_CONFIG_HEADER(config.h) AC_CANONICAL_SYSTEM @@ -64,15 +64,23 @@ fi case "$VARNISHSRC" in /*) ;; *) AC_MSG_ERROR([varnish source path must be absolute pathname]) esac VARNISHSRC=`cd $VARNISHSRC && pwd` +VARNISHVERSION= AC_CHECK_FILE([$VARNISHSRC/include/varnishapi.h], - [], - [AC_MSG_FAILURE(["$VARNISHSRC" is not a Varnish source directory])]) + [VARNISHVERSION=3], + [AC_CHECK_FILE([$VARNISHSRC/include/vapi/vsm.h], + [VARNISHVERSION=4], + [AC_MSG_FAILURE(["$VARNISHSRC" is not a Varnish source directory])]) ]) +AC_SUBST([VARNISHVERSION],$VARNISHVERSION) + +AC_DEFINE_UNQUOTED([VARNISHVERSION],$VARNISHVERSION,[Varnish major version number]) +AM_CONDITIONAL([VARNISH3],[test $VARNISHVERSION -eq 3]) +AM_CONDITIONAL([VARNISH4],[test $VARNISHVERSION -eq 4]) # Check that varnishtest is built in the varnish source directory AC_CHECK_FILE([$VARNISHSRC/bin/varnishtest/varnishtest], [], [AC_MSG_FAILURE([cannot find "$VARNISHSRC/bin/varnishtest/varnishtest". Please build your varnish source directory])] ) diff --git a/src/.gitignore b/src/.gitignore index 7f6e438..ce7aef0 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1,3 @@ vcc_if.c vcc_if.h +*.rst diff --git a/src/Makefile.am b/src/Makefile.am index 727d33b..f4e3bec 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,34 +13,53 @@ # # You should have received a copy of the GNU General Public License # along with vmod-tbf. If not, see <http://www.gnu.org/licenses/>. AM_CPPFLAGS=\ -I$(VARNISHSRC)/include\ + -I$(VARNISHSRC)/bin/varnishd\ -I$(VARNISHSRC)\ -DLOCALSTATEDIR=\"$(localstatedir)\" dist_man_MANS=vmod-tbf.3 vmod_tbf.3 vmoddir = $(VMODDIR) vmod_LTLIBRARIES = libvmod_tbf.la libvmod_tbf_la_LDFLAGS=-module -export-dynamic -avoid-version libvmod_tbf_la_LIBADD= libvmod_tbf_la_SOURCES = \ + tbf.c\ + tbf.h\ getla.c\ sleep.c\ - time.c\ - tbf.c\ + time.c +nodist_libvmod_tbf_la_SOURCES = \ vcc_if.c vcc_if.h -BUILT_SOURCES = vcc_if.c vcc_if.h +tbf.lo: vcc_if.h + +CLEANFILES = vcc_if.c vcc_if.h *.rst + +if VARNISH4 + vmodtool = $(VARNISHSRC)/lib/libvcc/vmodtool.py + vmodtoolargs = --strict + vccfile = $(top_srcdir)/src/vmod_tbf.vcc +else + vmodtool = $(VARNISHSRC)/lib/libvmod_std/vmod.py + vmodtoolargs = + vccfile = vmod_tbf.vcc3 + +vmod_tbf.vcc3: $(top_srcdir)/src/vmod_tbf.vcc + CLEANFILES += vmod_tbf.vcc3 +endif -vcc_if.c vcc_if.h: $(VARNISHSRC)/lib/libvmod_std/vmod.py $(top_srcdir)/src/vmod_tbf.vcc - @PYTHON@ $(VARNISHSRC)/lib/libvmod_std/vmod.py $(top_srcdir)/src/vmod_tbf.vcc +.vcc.vcc3: + sed -n '/^\$$/{s///;s/\(Module *[^ ][^ ]*\).*/\1/;p}' $< > $@ +vcc_if.c vcc_if.h: $(vmodtool) $(vccfile) + @PYTHON@ $(vmodtool) $(vmodtoolargs) $(vccfile) EXTRA_DIST = \ vmod_tbf.vcc -CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h diff --git a/src/getla.c b/src/getla.c index c735956..51791c4 100644 --- a/src/getla.c +++ b/src/getla.c @@ -12,21 +12,16 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with vmod-tbf. If not, see <http://www.gnu.org/licenses/>. */ #define _BSD_SOURCE -#include <config.h> -#include <stdlib.h> -#include <stdio.h> -#include <syslog.h> +#include "tbf.h" #if defined(HAVE_SYSINFO) && defined(HAVE_SYS_SYSINFO_H) # include <sys/sysinfo.h> #endif -#include "vrt.h" -#include "vcc_if.h" static double sys_getla(int what) { #if defined(HAVE_GETLOADAVG) double loadavg[3]; @@ -47,14 +42,14 @@ sys_getla(int what) #else syslog(LOG_DAEMON|LOG_CRIT, "tbf.getla is not implemented"); return 0.0; #endif } -double -vmod_getla(struct sess *sp, int what) +VCL_REAL +vmod_getla(MOD_CTX ctx, VCL_INT what) { switch (what) { case 1: what = 0; break; case 5: diff --git a/src/sleep.c b/src/sleep.c index 70c4337..9242475 100644 --- a/src/sleep.c +++ b/src/sleep.c @@ -11,20 +11,18 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with vmod-tbf. If not, see <http://www.gnu.org/licenses/>. */ -#include <config.h> +#include "tbf.h" #include <errno.h> #include <time.h> -#include "vrt.h" -#include "vcc_if.h" -void -vmod_sleep(struct sess *sp, double t) +VCL_VOID +vmod_sleep(MOD_CTX ctx, VCL_REAL t) { struct timespec ts, ret; ts.tv_sec = t; ts.tv_nsec = (t - ts.tv_sec) * 1e9; @@ -11,23 +11,18 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with vmod-tbf. If not, see <http://www.gnu.org/licenses/>. */ -#include <config.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdbool.h> +#include "tbf.h" #include <syslog.h> #include <inttypes.h> #include <sys/stat.h> +#include <sys/time.h> #include <db.h> -#include "vrt.h" -#include "vcc_if.h" -#include "bin/varnishd/cache.h" static int debug_level; static void debugprt(const char *fmt, ...) { @@ -348,24 +343,24 @@ tbf_init(struct vmod_priv *priv, const struct VCL_conf *vclconf) { VTAILQ_INIT(&keylock_head); VTAILQ_INIT(&keylock_avail); } void -vmod_open(struct sess *sp, const char *dir, const char *params) +vmod_open(MOD_CTX ctx, const char *dir, const char *params) { if (db) { syslog(LOG_DAEMON|LOG_ERR, "tbf.open called twice"); return; } tbf_set_db_dir(dir); tbf_open_safe(params); } void -vmod_close(struct sess *sp) +vmod_close(MOD_CTX ctx) { pthread_mutex_lock(&mutex); if (db) { debug(1, ("closing database %s", dbname)); db->close(db, 0); db = NULL; @@ -374,13 +369,13 @@ vmod_close(struct sess *sp) tbf_disabled = 0; } pthread_mutex_unlock(&mutex); } void -vmod_sync(struct sess *sp) +vmod_sync(MOD_CTX ctx) { if (db) { debug(1, ("synchronizing database")); db->sync(db, 0); } } @@ -407,13 +402,13 @@ vmod_sync(struct sess *sp) struct tbf_bucket { uint64_t timestamp; /* microseconds since epoch */ size_t tokens; /* tokens available */ }; int -tbf_proc(struct sess *sp, DB *db, const char *key, int cost, +tbf_proc(MOD_CTX ctx, DB *db, const char *key, int cost, unsigned long interval, int burst_size) { DBT keydat, content; struct timeval tv; uint64_t now; uint64_t elapsed; @@ -496,14 +491,15 @@ tbf_proc(struct sess *sp, DB *db, const char *key, int cost, autosync_count = 0; } return res; } -unsigned -vmod_rate(struct sess *sp, const char *key, int cost, double t, int burst_size) +VCL_BOOL +vmod_rate(MOD_CTX ctx, VCL_STRING key, VCL_INT cost, VCL_REAL t, + VCL_INT burst_size) { unsigned long interval = t * USEC_PER_SEC; int rc; debug(2, ("entering rate(%s,%d,%g,%d)", key, cost, t, burst_size)); @@ -524,26 +520,26 @@ vmod_rate(struct sess *sp, const char *key, int cost, double t, int burst_size) if (db) { struct keylock *kp; kp = keylock_find_safe(key); debug(2, ("found key %s, ref %u", key, kp->refcnt)); AZ(pthread_mutex_lock(&kp->mutex)); - rc = tbf_proc(sp, db, key, cost, interval, burst_size); + rc = tbf_proc(ctx, db, key, cost, interval, burst_size); if (--kp->refcnt == 0) keylock_remove_safe(kp); AZ(pthread_mutex_unlock(&kp->mutex)); } else rc = false; return rc; } #define ISWS(c) ((c)==' '||(c)=='\t') -unsigned -vmod_check(struct sess *sp, const char *key, const char *spec) +VCL_BOOL +vmod_check(MOD_CTX ctx, VCL_STRING key, VCL_STRING spec) { double t, v, n; char *p; #define SKIPWS(init) for (init; *spec && ISWS(*spec); spec++) int burst; @@ -598,8 +594,8 @@ vmod_check(struct sess *sp, const char *key, const char *spec) SKIPWS(++spec); if (*spec) syslog(LOG_DAEMON|LOG_WARNING, "garbage after rate spec: %s", spec); - return vmod_rate(sp, key, 1, n/v, v/n+1); + return vmod_rate(ctx, key, 1, n/v, v/n+1); } diff --git a/src/tbf.h b/src/tbf.h new file mode 100644 index 0000000..3c7a118 --- /dev/null +++ b/src/tbf.h @@ -0,0 +1,38 @@ +/* This file is part of vmod-tbf + Copyright (C) 2013-2014 Sergey Poznyakoff + + Vmod-tbf is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + Vmod-tbf is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with vmod-tbf. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <syslog.h> +#include "vrt.h" +#include "vcc_if.h" +#include "pthread.h" +#if VARNISHVERSION == 3 +# include "bin/varnishd/cache.h" +# define VCL_VOID void +# define VCL_INT int +# define VCL_REAL double +# define VCL_BOOL unsigned +# define VCL_STRING const char * +# define MOD_CTX struct sess * +# define WSPTR(s) ((s)->wrk->ws) +#else +# include "bin/varnishd/cache/cache.h" +# define MOD_CTX const struct vrt_ctx * +# define WSPTR(s) ((s)->ws) +#endif @@ -11,39 +11,34 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with vmod-tbf. If not, see <http://www.gnu.org/licenses/>. */ -#include <config.h> -#include <stdlib.h> -#include <stdio.h> +#include "tbf.h" #include <time.h> -#include "vrt.h" -#include "vcc_if.h" -#include "bin/varnishd/cache.h" -int -vmod_systime(struct sess *sp) +VCL_INT +vmod_systime(MOD_CTX ctx) { return time(NULL); } -const char * -vmod_strftime(struct sess *sp, const char *format, int timestamp) +VCL_STRING +vmod_strftime(MOD_CTX ctx, VCL_STRING format, VCL_INT timestamp) { time_t ts = (time_t) timestamp; size_t u, n; char *p; - u = WS_Reserve(sp->wrk->ws, 0); - p = sp->wrk->ws->f; + u = WS_Reserve(WSPTR(ctx), 0); + p = WSPTR(ctx)->f; n = strftime(p, u, format, gmtime(&ts)); if (n == 0) { - WS_Release(sp->wrk->ws, 0); + WS_Release(WSPTR(ctx), 0); return NULL; } - WS_Release(sp->wrk->ws, n + 1); + WS_Release(WSPTR(ctx), n + 1); return p; } diff --git a/src/vmod_tbf.vcc b/src/vmod_tbf.vcc index 3634807..b27093b 100644 --- a/src/vmod_tbf.vcc +++ b/src/vmod_tbf.vcc @@ -1,11 +1,36 @@ -Module tbf -Init tbf_init -Function VOID open(STRING, STRING) -Function VOID close() -Function VOID sync() -Function BOOL rate(STRING, INT, DURATION, INT) -Function BOOL check(STRING, STRING) -Function REAL getla(INT) -Function INT systime() -Function STRING strftime(STRING, INT) -Function VOID sleep(DURATION) +# This file is part of vmod-tbf +# Copyright (C) 2013 Sergey Poznyakoff +# +# Vmod-tbf is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Vmod-tbf is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with vmod-tbf. If not, see <http://www.gnu.org/licenses/>. + +$Module tbf 3 Token Bucket Filtering for Varnish + +COLOPHON +======== +This document provides a short description of the **vmod-tbf** module. +For a detailed documentation, please see vmod-tbf(3) manual page. + +DESCRIPTION +=========== + +$Init tbf_init +$Function VOID open(STRING, STRING) +$Function VOID close() +$Function VOID sync() +$Function BOOL rate(STRING, INT, DURATION, INT) +$Function BOOL check(STRING, STRING) +$Function REAL getla(INT) +$Function INT systime() +$Function STRING strftime(STRING, INT) +$Function VOID sleep(DURATION) diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..6f6760a --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,2 @@ +test00.vtc +test02.vtc diff --git a/tests/Makefile.am b/tests/Makefile.am index 4790115..0f90aa7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,19 +1,40 @@ +VMOD_VTC = \ + test01.vtc\ + test03.vtc\ + time00.vtc + +VMOD_VTI = \ + test00.vti\ + test02.vti + +BUILT_TESTS = $(VMOD_VTI:.vti=.vtc) + VMOD_TESTS = \ - test00.vtc\ + test00.vti\ test01.vtc\ - test02.vtc\ + test02.vti\ test03.vtc\ time00.vtc -EXTRA_DIST=$(VMOD_TESTS) +.vti.vtc: + sed 's/^#VARNISH$(VARNISHVERSION)#//' $< > $@ + +EXTRA_DIST=$(VMOD_VTC) $(VMOD_VTI) +CLEANFILES=$(BUILT_TESTS) + distclean-local: rm -fr tbf -check: - cd $(abs_srcdir); \ +check: $(BUILT_TESTS) for t in $(VMOD_TESTS); do \ + n=$${t%%.vti}; \ + if [ $$n != $$t ]; then \ + t=$(abs_builddir)/$${n}.vtc;\ + else \ + t=$(abs_srcdir)/$$t;\ + fi; \ $(VARNISHSRC)/bin/varnishtest/varnishtest \ -Dvarnishd=$(VARNISHSRC)/bin/varnishd/varnishd \ -Dvmod_topsrc=$(abs_top_srcdir) \ -Dvmod_topbuild=$(abs_top_builddir) $$t; \ done diff --git a/tests/test00.vtc b/tests/test00.vti index f69f5ed..05084c7 100644 --- a/tests/test00.vtc +++ b/tests/test00.vti @@ -12,15 +12,17 @@ varnish v1 -vcl+backend { } sub vcl_fini { tbf.close(); } sub vcl_recv { if (!tbf.rate("url:"+req.url, 1, 20 s, 5)) { - error 420 "Overlimit"; +#VARNISH3# error 420 "Overlimit"; +#VARNISH4# return (synth(420, "Overlimit")); } - return (lookup); +#VARNISH3# return (lookup); +#VARNISH4# return (hash); } } -start client c1 { txreq -url "/" rxresp diff --git a/tests/test02.vtc b/tests/test02.vti index 8df6730..1b5e6b3 100644 --- a/tests/test02.vtc +++ b/tests/test02.vti @@ -12,15 +12,17 @@ varnish v1 -vcl+backend { } sub vcl_fini { tbf.close(); } sub vcl_recv { if (!tbf.check("url:"+req.url, "4 req/s")) { - error 420 "Overlimit"; +#VARNISH3# error 420 "Overlimit"; +#VARNISH4# return (synth(420, "Overlimit")); } - return (lookup); +#VARNISH3# return (lookup); +#VARNISH4# return (hash); } } -start client c1 { txreq -url "/" rxresp |