Home | History | Annotate | Line # | Download | only in linux
      1  1.6  riastrad /*	$NetBSD: ratelimit.h,v 1.6 2022/04/09 23:44:25 riastradh Exp $	*/
      2  1.2  riastrad 
      3  1.2  riastrad /*-
      4  1.2  riastrad  * Copyright (c) 2013 The NetBSD Foundation, Inc.
      5  1.2  riastrad  * All rights reserved.
      6  1.2  riastrad  *
      7  1.2  riastrad  * This code is derived from software contributed to The NetBSD Foundation
      8  1.2  riastrad  * by Taylor R. Campbell.
      9  1.2  riastrad  *
     10  1.2  riastrad  * Redistribution and use in source and binary forms, with or without
     11  1.2  riastrad  * modification, are permitted provided that the following conditions
     12  1.2  riastrad  * are met:
     13  1.2  riastrad  * 1. Redistributions of source code must retain the above copyright
     14  1.2  riastrad  *    notice, this list of conditions and the following disclaimer.
     15  1.2  riastrad  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.2  riastrad  *    notice, this list of conditions and the following disclaimer in the
     17  1.2  riastrad  *    documentation and/or other materials provided with the distribution.
     18  1.2  riastrad  *
     19  1.2  riastrad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.2  riastrad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.2  riastrad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.2  riastrad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.2  riastrad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.2  riastrad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.2  riastrad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.2  riastrad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.2  riastrad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.2  riastrad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.2  riastrad  * POSSIBILITY OF SUCH DAMAGE.
     30  1.2  riastrad  */
     31  1.2  riastrad 
     32  1.2  riastrad #ifndef _LINUX_RATELIMIT_H_
     33  1.2  riastrad #define _LINUX_RATELIMIT_H_
     34  1.2  riastrad 
     35  1.3  riastrad #include <sys/atomic.h>
     36  1.3  riastrad #include <sys/stdbool.h>
     37  1.3  riastrad #include <sys/time.h>
     38  1.3  riastrad 
     39  1.4  riastrad #define	ratelimit_state	linux_ratelimit_state
     40  1.4  riastrad 
     41  1.4  riastrad struct ratelimit_state {
     42  1.5  riastrad 	volatile int		missed;
     43  1.5  riastrad 
     44  1.3  riastrad 	volatile unsigned	rl_lock;
     45  1.3  riastrad 	struct timeval		rl_lasttime;
     46  1.3  riastrad 	int			rl_curpps;
     47  1.3  riastrad 	unsigned		rl_maxpps;
     48  1.3  riastrad };
     49  1.3  riastrad 
     50  1.5  riastrad enum {
     51  1.5  riastrad 	RATELIMIT_MSG_ON_RELEASE,
     52  1.5  riastrad };
     53  1.5  riastrad 
     54  1.3  riastrad /*
     55  1.3  riastrad  * XXX Assumes hz=100 so this works in static initializers, and/or
     56  1.3  riastrad  * hopes the caller just uses DEFAULT_RATELIMIT_INTERVAL and doesn't
     57  1.3  riastrad  * mention hz.
     58  1.3  riastrad  */
     59  1.3  riastrad #define	DEFAULT_RATELIMIT_INTERVAL	(5*100)
     60  1.3  riastrad #define	DEFAULT_RATELIMIT_BURST		10
     61  1.3  riastrad 
     62  1.3  riastrad #define	DEFINE_RATELIMIT_STATE(n, i, b)					      \
     63  1.4  riastrad 	struct ratelimit_state n = {					      \
     64  1.5  riastrad 		.missed = 0,						      \
     65  1.3  riastrad 		.rl_lock = 0,						      \
     66  1.3  riastrad 		.rl_lasttime = { .tv_sec = 0, .tv_usec = 0 },		      \
     67  1.3  riastrad 		.rl_curpps = 0,						      \
     68  1.3  riastrad 		.rl_maxpps = (b)/((i)/100),				      \
     69  1.3  riastrad 	}
     70  1.3  riastrad 
     71  1.5  riastrad static inline void
     72  1.5  riastrad ratelimit_state_init(struct ratelimit_state *r, int interval, int burst)
     73  1.5  riastrad {
     74  1.5  riastrad 
     75  1.5  riastrad 	memset(r, 0, sizeof(*r));
     76  1.5  riastrad 	r->rl_maxpps = burst/(interval/hz);
     77  1.5  riastrad }
     78  1.5  riastrad 
     79  1.5  riastrad static inline void
     80  1.5  riastrad ratelimit_set_flags(struct ratelimit_state *r, unsigned long flags)
     81  1.5  riastrad {
     82  1.5  riastrad }
     83  1.5  riastrad 
     84  1.3  riastrad static inline bool
     85  1.4  riastrad __ratelimit(struct ratelimit_state *r)
     86  1.3  riastrad {
     87  1.3  riastrad 	int ok;
     88  1.3  riastrad 
     89  1.6  riastrad 	if (atomic_swap_uint(&r->rl_lock, 1)) {
     90  1.5  riastrad 		ok = false;
     91  1.5  riastrad 		goto out;
     92  1.5  riastrad 	}
     93  1.6  riastrad 	membar_acquire();
     94  1.3  riastrad 	ok = ppsratecheck(&r->rl_lasttime, &r->rl_curpps, r->rl_maxpps);
     95  1.6  riastrad 	atomic_store_release(&r->rl_lock, 0);
     96  1.3  riastrad 
     97  1.5  riastrad out:	if (!ok)
     98  1.5  riastrad 		atomic_store_relaxed(&r->missed, 1);
     99  1.3  riastrad 	return ok;
    100  1.3  riastrad }
    101  1.3  riastrad 
    102  1.2  riastrad #endif  /* _LINUX_RATELIMIT_H_ */
    103