Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_ratelimit.h
Show All 30 Lines | |||||
/** | /** | ||||
* Author: Randall Stewart <rrs@netflix.com> | * Author: Randall Stewart <rrs@netflix.com> | ||||
*/ | */ | ||||
#ifndef __tcp_ratelimit_h__ | #ifndef __tcp_ratelimit_h__ | ||||
#define __tcp_ratelimit_h__ | #define __tcp_ratelimit_h__ | ||||
struct m_snd_tag; | struct m_snd_tag; | ||||
#define RL_MIN_DIVISOR 50 | |||||
#define RL_DEFAULT_DIVISOR 1000 | |||||
/* Flags on an individual rate */ | /* Flags on an individual rate */ | ||||
#define HDWRPACE_INITED 0x0001 | #define HDWRPACE_INITED 0x0001 | ||||
#define HDWRPACE_TAGPRESENT 0x0002 | #define HDWRPACE_TAGPRESENT 0x0002 | ||||
#define HDWRPACE_IFPDEPARTED 0x0004 | #define HDWRPACE_IFPDEPARTED 0x0004 | ||||
struct tcp_hwrate_limit_table { | struct tcp_hwrate_limit_table { | ||||
const struct tcp_rate_set *ptbl; /* Pointer to parent table */ | const struct tcp_rate_set *ptbl; /* Pointer to parent table */ | ||||
struct m_snd_tag *tag; /* Send tag if needed (chelsio) */ | struct m_snd_tag *tag; /* Send tag if needed (chelsio) */ | ||||
long rate; /* Rate we get in Bytes per second (Bps) */ | long rate; /* Rate we get in Bytes per second (Bps) */ | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | |||||
const struct tcp_hwrate_limit_table * | const struct tcp_hwrate_limit_table * | ||||
tcp_chg_pacing_rate(const struct tcp_hwrate_limit_table *crte, | tcp_chg_pacing_rate(const struct tcp_hwrate_limit_table *crte, | ||||
struct tcpcb *tp, struct ifnet *ifp, | struct tcpcb *tp, struct ifnet *ifp, | ||||
uint64_t bytes_per_sec, int flags, int *error, uint64_t *lower_rate); | uint64_t bytes_per_sec, int flags, int *error, uint64_t *lower_rate); | ||||
void | void | ||||
tcp_rel_pacing_rate(const struct tcp_hwrate_limit_table *crte, | tcp_rel_pacing_rate(const struct tcp_hwrate_limit_table *crte, | ||||
struct tcpcb *tp); | 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 | #else | ||||
static inline const struct tcp_hwrate_limit_table * | static inline const struct tcp_hwrate_limit_table * | ||||
tcp_set_pacing_rate(struct tcpcb *tp, struct ifnet *ifp, | tcp_set_pacing_rate(struct tcpcb *tp, struct ifnet *ifp, | ||||
uint64_t bytes_per_sec, int flags, int *error, uint64_t *lower_rate) | uint64_t bytes_per_sec, int flags, int *error, uint64_t *lower_rate) | ||||
{ | { | ||||
if (error) | if (error) | ||||
*error = EOPNOTSUPP; | *error = EOPNOTSUPP; | ||||
return (NULL); | return (NULL); | ||||
Show All 23 Lines | |||||
} | } | ||||
static uint64_t inline | static uint64_t inline | ||||
tcp_hw_highest_rate_ifp(struct ifnet *ifp, struct inpcb *inp) | tcp_hw_highest_rate_ifp(struct ifnet *ifp, struct inpcb *inp) | ||||
{ | { | ||||
return (0); | 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 | #endif | ||||
/* | /* | ||||
* Given a b/w and a segsiz, and optional hardware | * Given a b/w and a segsiz, and optional hardware | ||||
* rate limit, return the ideal size to burst | * rate limit, return the ideal size to burst | ||||
* out at once. Note the parameter can_use_1mss | * out at once. Note the parameter can_use_1mss | ||||
* dictates if the transport will tolerate a 1mss | * dictates if the transport will tolerate a 1mss | ||||
* limit, if not it will bottom out at 2mss (think | * limit, if not it will bottom out at 2mss (think | ||||
* delayed ack). | * 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, | 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) | ||||
{ | |||||
return (tcp_get_pacing_burst_size_w_divisor(tp, bw, segsiz, | |||||
void | can_use_1mss, | ||||
tcp_rl_log_enobuf(const struct tcp_hwrate_limit_table *rte); | te, err, 0)); | ||||
} | |||||
#endif | #endif | ||||
#endif | #endif |