aboutsummaryrefslogtreecommitdiff
path: root/sys/net/altq/altq_subr.c
diff options
context:
space:
mode:
authorPatrick Kelsey <pkelsey@FreeBSD.org>2018-08-22 19:38:48 +0000
committerPatrick Kelsey <pkelsey@FreeBSD.org>2018-08-22 19:38:48 +0000
commit249cc75fd14eac511a102b657646f98229c9dcc3 (patch)
tree3e80c0ad9bcf7e59a8ad3c979d54e2d4249a6d99 /sys/net/altq/altq_subr.c
parentfe2bf351fe0095c8ca716ac9f085ced51a243a2e (diff)
downloadsrc-249cc75fd14eac511a102b657646f98229c9dcc3.tar.gz
src-249cc75fd14eac511a102b657646f98229c9dcc3.zip
Extended pf(4) ioctl interface and pfctl(8) to allow bandwidths of
2^32 bps or greater to be used. Prior to this, bandwidth parameters would simply wrap at the 2^32 boundary. The computations in the HFSC scheduler and token bucket regulator have been modified to operate correctly up to at least 100 Gbps. No other algorithms have been examined or modified for correct operation above 2^32 bps (some may have existing computation resolution or overflow issues at rates below that threshold). pfctl(8) will now limit non-HFSC bandwidth parameters to 2^32 - 1 before passing them to the kernel. The extensions to the pf(4) ioctl interface have been made in a backwards-compatible way by versioning affected data structures, supporting all versions in the kernel, and implementing macros that will cause existing code that consumes that interface to use version 0 without source modifications. If version 0 consumers of the interface are used against a new kernel that has had bandwidth parameters of 2^32 or greater configured by updated tools, such bandwidth parameters will be reported as 2^32 - 1 bps by those old consumers. All in-tree consumers of the pf(4) interface have been updated. To update out-of-tree consumers to the latest version of the interface, define PFIOC_USE_LATEST ahead of any includes and use the code of pfctl(8) as a guide for the ioctls of interest. PR: 211730 Reviewed by: jmallett, kp, loos MFC after: 2 weeks Relnotes: yes Sponsored by: RG Nets Differential Revision: https://reviews.freebsd.org/D16782
Notes
Notes: svn path=/head/; revision=338209
Diffstat (limited to 'sys/net/altq/altq_subr.c')
-rw-r--r--sys/net/altq/altq_subr.c58
1 files changed, 24 insertions, 34 deletions
diff --git a/sys/net/altq/altq_subr.c b/sys/net/altq/altq_subr.c
index 356f79f84b9a..bce83efcd3a7 100644
--- a/sys/net/altq/altq_subr.c
+++ b/sys/net/altq/altq_subr.c
@@ -292,12 +292,12 @@ altq_assert(file, line, failedexpr)
/*
* internal representation of token bucket parameters
- * rate: byte_per_unittime << 32
- * (((bits_per_sec) / 8) << 32) / machclk_freq
- * depth: byte << 32
+ * rate: (byte_per_unittime << TBR_SHIFT) / machclk_freq
+ * (((bits_per_sec) / 8) << TBR_SHIFT) / machclk_freq
+ * depth: byte << TBR_SHIFT
*
*/
-#define TBR_SHIFT 32
+#define TBR_SHIFT 29
#define TBR_SCALE(x) ((int64_t)(x) << TBR_SHIFT)
#define TBR_UNSCALE(x) ((x) >> TBR_SHIFT)
@@ -394,7 +394,20 @@ tbr_set(ifq, profile)
if (tbr->tbr_rate > 0)
tbr->tbr_filluptime = tbr->tbr_depth / tbr->tbr_rate;
else
- tbr->tbr_filluptime = 0xffffffffffffffffLL;
+ tbr->tbr_filluptime = LLONG_MAX;
+ /*
+ * The longest time between tbr_dequeue() calls will be about 1
+ * system tick, as the callout that drives it is scheduled once per
+ * tick. The refill-time detection logic in tbr_dequeue() can only
+ * properly detect the passage of up to LLONG_MAX machclk ticks.
+ * Therefore, in order for this logic to function properly in the
+ * extreme case, the maximum value of tbr_filluptime should be
+ * LLONG_MAX less one system tick's worth of machclk ticks less
+ * some additional slop factor (here one more system tick's worth
+ * of machclk ticks).
+ */
+ if (tbr->tbr_filluptime > (LLONG_MAX - 2 * machclk_per_tick))
+ tbr->tbr_filluptime = LLONG_MAX - 2 * machclk_per_tick;
tbr->tbr_token = tbr->tbr_depth;
tbr->tbr_last = read_machclk();
tbr->tbr_lastop = ALTDQ_REMOVE;
@@ -456,29 +469,6 @@ tbr_timeout(arg)
}
/*
- * get token bucket regulator profile
- */
-int
-tbr_get(ifq, profile)
- struct ifaltq *ifq;
- struct tb_profile *profile;
-{
- struct tb_regulator *tbr;
-
- IFQ_LOCK(ifq);
- if ((tbr = ifq->altq_tbr) == NULL) {
- profile->rate = 0;
- profile->depth = 0;
- } else {
- profile->rate =
- (u_int)TBR_UNSCALE(tbr->tbr_rate * 8 * machclk_freq);
- profile->depth = (u_int)TBR_UNSCALE(tbr->tbr_depth);
- }
- IFQ_UNLOCK(ifq);
- return (0);
-}
-
-/*
* attach a discipline to the interface. if one already exists, it is
* overridden.
* Locking is done in the discipline specific attach functions. Basically
@@ -733,34 +723,34 @@ altq_remove_queue(struct pf_altq *a)
* copyout operations, also it is not yet clear which lock to use.
*/
int
-altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes, int version)
{
int error = 0;
switch (a->scheduler) {
#ifdef ALTQ_CBQ
case ALTQT_CBQ:
- error = cbq_getqstats(a, ubuf, nbytes);
+ error = cbq_getqstats(a, ubuf, nbytes, version);
break;
#endif
#ifdef ALTQ_PRIQ
case ALTQT_PRIQ:
- error = priq_getqstats(a, ubuf, nbytes);
+ error = priq_getqstats(a, ubuf, nbytes, version);
break;
#endif
#ifdef ALTQ_HFSC
case ALTQT_HFSC:
- error = hfsc_getqstats(a, ubuf, nbytes);
+ error = hfsc_getqstats(a, ubuf, nbytes, version);
break;
#endif
#ifdef ALTQ_FAIRQ
case ALTQT_FAIRQ:
- error = fairq_getqstats(a, ubuf, nbytes);
+ error = fairq_getqstats(a, ubuf, nbytes, version);
break;
#endif
#ifdef ALTQ_CODEL
case ALTQT_CODEL:
- error = codel_getqstats(a, ubuf, nbytes);
+ error = codel_getqstats(a, ubuf, nbytes, version);
break;
#endif
default: