diff --git a/sys/netinet/tcp_ratelimit.h b/sys/netinet/tcp_ratelimit.h --- a/sys/netinet/tcp_ratelimit.h +++ b/sys/netinet/tcp_ratelimit.h @@ -36,6 +36,9 @@ struct m_snd_tag; +#define RL_MIN_DIVISOR 50 +#define RL_DEFAULT_DIVISOR 1000 + /* Flags on an individual rate */ #define HDWRPACE_INITED 0x0001 #define HDWRPACE_TAGPRESENT 0x0002 @@ -121,6 +124,14 @@ void tcp_rel_pacing_rate(const struct tcp_hwrate_limit_table *crte, struct tcpcb *tp); + +uint32_t +tcp_get_pacing_burst_size_w_divisor(struct tcpcb *tp, uint64_t bw, uint32_t segsiz, int can_use_1mss, + const struct tcp_hwrate_limit_table *te, int *err, int divisor); + +void +tcp_rl_log_enobuf(const struct tcp_hwrate_limit_table *rte); + #else static inline const struct tcp_hwrate_limit_table * tcp_set_pacing_rate(struct tcpcb *tp, struct ifnet *ifp, @@ -160,8 +171,56 @@ return (0); } +static inline uint32_t +tcp_get_pacing_burst_size_w_divisor(struct tcpcb *tp, uint64_t bw, uint32_t segsiz, int can_use_1mss, + const struct tcp_hwrate_limit_table *te, int *err, int divisor) +{ + /* + * We use the google formula to calculate the + * TSO size. I.E. + * bw < 24Meg + * tso = 2mss + * else + * tso = min(bw/(div=1000), 64k) + * + * Note for these calculations we ignore the + * packet overhead (enet hdr, ip hdr and tcp hdr). + * We only get the google formula when we have + * divisor = 1000, which is the default for now. + */ + uint64_t bytes; + uint32_t new_tso, min_tso_segs; + + /* It can't be zero */ + if ((divisor == 0) || + (divisor < RL_MIN_DIVISOR)) { + bytes = bw / RL_DEFAULT_DIVISOR; + } else + bytes = bw / divisor; + /* We can't ever send more than 65k in a TSO */ + if (bytes > 0xffff) { + bytes = 0xffff; + } + /* Round up */ + new_tso = (bytes + segsiz - 1) / segsiz; + if (can_use_1mss) + min_tso_segs = 1; + else + min_tso_segs = 2; + if (new_tso < min_tso_segs) + new_tso = min_tso_segs; + new_tso *= segsiz; + return (new_tso); +} + +/* Do nothing if RATELIMIT is not defined */ +static void +tcp_rl_log_enobuf(const struct tcp_hwrate_limit_table *rte) +{ +} #endif + /* * Given a b/w and a segsiz, and optional hardware * rate limit, return the ideal size to burst @@ -170,13 +229,15 @@ * limit, if not it will bottom out at 2mss (think * delayed ack). */ -uint32_t +static inline uint32_t tcp_get_pacing_burst_size(struct tcpcb *tp, uint64_t bw, uint32_t segsiz, int can_use_1mss, - const struct tcp_hwrate_limit_table *te, int *err); - + const struct tcp_hwrate_limit_table *te, int *err) +{ -void -tcp_rl_log_enobuf(const struct tcp_hwrate_limit_table *rte); + return (tcp_get_pacing_burst_size_w_divisor(tp, bw, segsiz, + can_use_1mss, + te, err, 0)); +} #endif #endif diff --git a/sys/netinet/tcp_ratelimit.c b/sys/netinet/tcp_ratelimit.c --- a/sys/netinet/tcp_ratelimit.c +++ b/sys/netinet/tcp_ratelimit.c @@ -255,6 +255,10 @@ static uint32_t rs_hw_floor_mss = 16; static uint32_t num_of_waits_allowed = 1; /* How many time blocks are we willing to wait */ +static uint32_t mss_divisor = RL_DEFAULT_DIVISOR; +static uint32_t even_num_segs = 1; +static uint32_t even_threshold = 4; + SYSCTL_NODE(_net_inet_tcp, OID_AUTO, rl, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "TCP Ratelimit stats"); SYSCTL_UINT(_net_inet_tcp_rl, OID_AUTO, alive, CTLFLAG_RW, @@ -277,6 +281,15 @@ &rs_hw_floor_mss, 16, "Number of mss that are a minum for hardware pacing?"); +SYSCTL_INT(_net_inet_tcp_rl, OID_AUTO, divisor, CTLFLAG_RW, + &mss_divisor, RL_DEFAULT_DIVISOR, + "The value divided into bytes per second to help establish mss size"); +SYSCTL_INT(_net_inet_tcp_rl, OID_AUTO, even, CTLFLAG_RW, + &even_num_segs, 1, + "Do we round mss size up to an even number of segments for delayed ack"); +SYSCTL_INT(_net_inet_tcp_rl, OID_AUTO, eventhresh, CTLFLAG_RW, + &even_threshold, 4, + "At what number of mss do we start rounding up to an even number of mss?"); static void rl_add_syctl_entries(struct sysctl_oid *rl_sysctl_root, struct tcp_rate_set *rs) @@ -1583,8 +1596,8 @@ } uint32_t -tcp_get_pacing_burst_size (struct tcpcb *tp, uint64_t bw, uint32_t segsiz, int can_use_1mss, - const struct tcp_hwrate_limit_table *te, int *err) +tcp_get_pacing_burst_size_w_divisor(struct tcpcb *tp, uint64_t bw, uint32_t segsiz, int can_use_1mss, + const struct tcp_hwrate_limit_table *te, int *err, int divisor) { /* * We use the google formula to calculate the @@ -1592,20 +1605,35 @@ * bw < 24Meg * tso = 2mss * else - * tso = min(bw/1000, 64k) + * tso = min(bw/(div=1000), 64k) * * Note for these calculations we ignore the * packet overhead (enet hdr, ip hdr and tcp hdr). + * We only get the google formula when we have + * divisor = 1000, which is the default for now. */ uint64_t lentim, res, bytes; uint32_t new_tso, min_tso_segs; - bytes = bw / 1000; - if (bytes > (64 * 1000)) - bytes = 64 * 1000; + /* It can't be zero */ + if ((divisor == 0) || + (divisor < RL_MIN_DIVISOR)) { + if (mss_divisor) + bytes = bw / mss_divisor; + else + bytes = bw / 1000; + } else + bytes = bw / divisor; + /* We can't ever send more than 65k in a TSO */ + if (bytes > 0xffff) { + bytes = 0xffff; + } /* Round up */ new_tso = (bytes + segsiz - 1) / segsiz; - if (can_use_1mss && (bw < ONE_POINT_TWO_MEG)) + /* Are we enforcing even boundaries? */ + if (even_num_segs && (new_tso & 1) && (new_tso > even_threshold)) + new_tso++; + if (can_use_1mss) min_tso_segs = 1; else min_tso_segs = 2;