Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137935700
D50796.id157609.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D50796.id157609.diff
View Options
diff --git a/share/man/man9/counter.9 b/share/man/man9/counter.9
--- a/share/man/man9/counter.9
+++ b/share/man/man9/counter.9
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 11, 2021
+.Dd June 19, 2025
.Dt COUNTER 9
.Os
.Sh NAME
@@ -49,8 +49,14 @@
.Fn counter_u64_fetch "counter_u64_t c"
.Ft void
.Fn counter_u64_zero "counter_u64_t c"
+.Ft struct counter_rate *
+.Fn counter_rate_alloc "int flags" "int period"
.Ft int64_t
.Fn counter_ratecheck "struct counter_rate *cr" "int64_t limit"
+.Ft uint64_t
+.Fn counter_rate_get "struct counter_rate *cr"
+.Ft void
+.Fn counter_rate_free "struct counter_rate *cr"
.Fn COUNTER_U64_SYSINIT "counter_u64_t c"
.Fn COUNTER_U64_DEFINE_EARLY "counter_u64_t c"
.In sys/sysctl.h
@@ -133,6 +139,13 @@
Clear the counter
.Fa c
and set it to zero.
+.It Fn counter_rate_alloc flags period
+Allocate a new struct counter_rate.
+.Fa flags
+is passed to
+.Xr malloc 9 .
+.Fa period
+is the time over which the rate is checked.
.It Fn counter_ratecheck cr limit
The function is a multiprocessor-friendly version of
.Fn ppsratecheck
@@ -140,11 +153,17 @@
.Nm
internally.
Returns non-negative value if the rate is not yet reached during the current
-second, and a negative value otherwise.
-If the limit was reached on previous second, but was just reset back to zero,
-then
+period, and a negative value otherwise.
+If the limit was reached during the previous period, but was just reset back
+to zero, then
.Fn counter_ratecheck
returns number of events since previous reset.
+.It Fn counter_rate_get cr
+The number of hits to this check within the current period.
+.It Fn counter_rate_free cr
+Free the
+.Fa cr
+counter.
.It Fn COUNTER_U64_SYSINIT c
Define a
.Xr SYSINIT 9
diff --git a/sys/kern/subr_counter.c b/sys/kern/subr_counter.c
--- a/sys/kern/subr_counter.c
+++ b/sys/kern/subr_counter.c
@@ -40,6 +40,8 @@
#define IN_SUBR_COUNTER_C
#include <sys/counter.h>
+static MALLOC_DEFINE(M_COUNTER_RATE, "counter_rate", "counter rate allocations");
+
void
counter_u64_zero(counter_u64_t c)
{
@@ -114,6 +116,57 @@
return (0);
}
+/*
+ * counter(9) based rate checking.
+ */
+struct counter_rate {
+ counter_u64_t cr_rate; /* Events since last second */
+ volatile int cr_lock; /* Lock to clean the struct */
+ int cr_ticks; /* Ticks on last clean */
+ int cr_over; /* Over limit since cr_ticks? */
+ int cr_period; /* Allow cr_rate per cr_period seconds. */
+};
+
+struct counter_rate *
+counter_rate_alloc(int flags, int period)
+{
+ struct counter_rate *new;
+
+ new = malloc(sizeof(struct counter_rate), M_COUNTER_RATE,
+ flags | M_ZERO);
+ if (new == NULL)
+ return (NULL);
+
+ new->cr_rate = counter_u64_alloc(flags);
+ if (new->cr_rate == NULL) {
+ free(new, M_COUNTER_RATE);
+ return (NULL);
+ }
+ new->cr_ticks = ticks;
+ new->cr_period = period;
+
+ return (new);
+}
+
+void
+counter_rate_free(struct counter_rate *rate)
+{
+ if (rate == NULL)
+ return;
+
+ counter_u64_free(rate->cr_rate);
+ free(rate, M_COUNTER_RATE);
+}
+
+uint64_t
+counter_rate_get(struct counter_rate *cr)
+{
+ if (cr->cr_ticks < (tick - (hz * cr->cr_period)))
+ return (0);
+
+ return (counter_u64_fetch(cr->cr_rate));
+}
+
/*
* MP-friendly version of ppsratecheck().
*
@@ -132,7 +185,7 @@
val = cr->cr_over;
now = ticks;
- if ((u_int)(now - cr->cr_ticks) >= hz) {
+ if ((u_int)(now - cr->cr_ticks) >= (hz * cr->cr_period)) {
/*
* Time to clear the structure, we are in the next second.
* First try unlocked read, and then proceed with atomic.
@@ -143,7 +196,7 @@
* Check if other thread has just went through the
* reset sequence before us.
*/
- if ((u_int)(now - cr->cr_ticks) >= hz) {
+ if ((u_int)(now - cr->cr_ticks) >= (hz * cr->cr_period)) {
val = counter_u64_fetch(cr->cr_rate);
counter_u64_zero(cr->cr_rate);
cr->cr_over = 0;
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -1090,7 +1090,7 @@
* the 'final' error, but it doesn't make sense to solve the printing
* delay with more complex code.
*/
-VNET_DEFINE_STATIC(struct counter_rate, icmp_rates[BANDLIM_MAX]);
+VNET_DEFINE_STATIC(struct counter_rate *, icmp_rates[BANDLIM_MAX]);
#define V_icmp_rates VNET(icmp_rates)
static const char *icmp_rate_descrs[BANDLIM_MAX] = {
@@ -1158,8 +1158,7 @@
{
for (int i = 0; i < BANDLIM_MAX; i++) {
- V_icmp_rates[i].cr_rate = counter_u64_alloc(M_WAITOK);
- V_icmp_rates[i].cr_ticks = ticks;
+ V_icmp_rates[i] = counter_rate_alloc(M_WAITOK, 1);
icmplim_new_jitter(i);
}
}
@@ -1172,7 +1171,7 @@
{
for (int i = 0; i < BANDLIM_MAX; i++)
- counter_u64_free(V_icmp_rates[i].cr_rate);
+ counter_rate_free(V_icmp_rates[i]);
}
VNET_SYSUNINIT(icmp_bandlimit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
icmp_bandlimit_uninit, NULL);
@@ -1189,7 +1188,7 @@
KASSERT(which >= 0 && which < BANDLIM_MAX,
("%s: which %d", __func__, which));
- pps = counter_ratecheck(&V_icmp_rates[which], V_icmplim +
+ pps = counter_ratecheck(V_icmp_rates[which], V_icmplim +
V_icmplim_curr_jitter[which]);
if (pps > 0) {
if (V_icmplim_output)
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -2844,7 +2844,7 @@
}
-VNET_DEFINE_STATIC(struct counter_rate, icmp6_rates[RATELIM_MAX]);
+VNET_DEFINE_STATIC(struct counter_rate *, icmp6_rates[RATELIM_MAX]);
#define V_icmp6_rates VNET(icmp6_rates)
static void
@@ -2852,8 +2852,7 @@
{
for (int i = 0; i < RATELIM_MAX; i++) {
- V_icmp6_rates[i].cr_rate = counter_u64_alloc(M_WAITOK);
- V_icmp6_rates[i].cr_ticks = ticks;
+ V_icmp6_rates[i] = counter_rate_alloc(M_WAITOK, 1);
icmp6lim_new_jitter(i);
}
}
@@ -2866,7 +2865,7 @@
{
for (int i = 0; i < RATELIM_MAX; i++)
- counter_u64_free(V_icmp6_rates[i].cr_rate);
+ counter_rate_free(V_icmp6_rates[i]);
}
VNET_SYSUNINIT(icmp6_ratelimit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
icmp6_ratelimit_uninit, NULL);
@@ -2916,7 +2915,7 @@
break;
};
- pps = counter_ratecheck(&V_icmp6_rates[which], V_icmp6errppslim +
+ pps = counter_ratecheck(V_icmp6_rates[which], V_icmp6errppslim +
V_icmp6lim_curr_jitter[which]);
if (pps > 0) {
if (V_icmp6lim_output)
diff --git a/sys/sys/counter.h b/sys/sys/counter.h
--- a/sys/sys/counter.h
+++ b/sys/sys/counter.h
@@ -60,17 +60,12 @@
counter_u64_zero((a)[_i]); \
} while (0)
-/*
- * counter(9) based rate checking.
- */
-struct counter_rate {
- counter_u64_t cr_rate; /* Events since last second */
- volatile int cr_lock; /* Lock to clean the struct */
- int cr_ticks; /* Ticks on last clean */
- int cr_over; /* Over limit since cr_ticks? */
-};
+struct counter_rate;
+struct counter_rate *counter_rate_alloc(int flags, int period);
+void counter_rate_free(struct counter_rate *);
int64_t counter_ratecheck(struct counter_rate *, int64_t);
+uint64_t counter_rate_get(struct counter_rate *);
#define COUNTER_U64_SYSINIT(c) \
SYSINIT(c##_counter_sysinit, SI_SUB_COUNTER, \
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 28, 10:39 AM (13 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26251011
Default Alt Text
D50796.id157609.diff (6 KB)
Attached To
Mode
D50796: counter(9): rate limit periods may be more than 1 second
Attached
Detach File
Event Timeline
Log In to Comment