Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_ratelimit.c
Show First 20 Lines • Show All 1,214 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
const struct tcp_hwrate_limit_table * | 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 bytes_per_sec, int flags, int *error) | ||||
{ | { | ||||
const struct tcp_hwrate_limit_table *rte; | const struct tcp_hwrate_limit_table *rte; | ||||
INP_WLOCK_ASSERT(tp->t_inpcb); | |||||
if (tp->t_inpcb->inp_snd_tag == NULL) { | if (tp->t_inpcb->inp_snd_tag == NULL) { | ||||
/* | /* | ||||
* We are setting up a rate for the first time. | * We are setting up a rate for the first time. | ||||
*/ | */ | ||||
if ((ifp->if_capenable & IFCAP_TXRTLMT) == 0) { | if ((ifp->if_capenable & IFCAP_TXRTLMT) == 0) { | ||||
/* Not supported by the egress */ | /* Not supported by the egress */ | ||||
if (error) | if (error) | ||||
*error = ENODEV; | *error = ENODEV; | ||||
Show All 14 Lines | #endif | ||||
} else { | } else { | ||||
/* | /* | ||||
* We are modifying a rate, wrong interface? | * We are modifying a rate, wrong interface? | ||||
*/ | */ | ||||
if (error) | if (error) | ||||
*error = EINVAL; | *error = EINVAL; | ||||
rte = NULL; | rte = NULL; | ||||
} | } | ||||
tp->t_pacing_rate = rte->rate; | |||||
*error = 0; | *error = 0; | ||||
return (rte); | return (rte); | ||||
} | } | ||||
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 bytes_per_sec, int flags, int *error) | ||||
{ | { | ||||
const struct tcp_hwrate_limit_table *nrte; | const struct tcp_hwrate_limit_table *nrte; | ||||
const struct tcp_rate_set *rs; | const struct tcp_rate_set *rs; | ||||
int is_indirect = 0; | int is_indirect = 0; | ||||
int err; | int err; | ||||
INP_WLOCK_ASSERT(tp->t_inpcb); | |||||
if ((tp->t_inpcb->inp_snd_tag == NULL) || | if ((tp->t_inpcb->inp_snd_tag == NULL) || | ||||
(crte == NULL)) { | (crte == NULL)) { | ||||
/* Wrong interface */ | /* Wrong interface */ | ||||
if (error) | if (error) | ||||
*error = EINVAL; | *error = EINVAL; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
rs = crte->ptbl; | rs = crte->ptbl; | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | re_rate: | ||||
err = in_pcbmodify_txrtlmt(tp->t_inpcb, nrte->rate); | err = in_pcbmodify_txrtlmt(tp->t_inpcb, nrte->rate); | ||||
if (err) { | if (err) { | ||||
if (error) | if (error) | ||||
*error = err; | *error = err; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if (error) | if (error) | ||||
*error = 0; | *error = 0; | ||||
tp->t_pacing_rate = nrte->rate; | |||||
return (nrte); | return (nrte); | ||||
} | } | ||||
void | void | ||||
tcp_rel_pacing_rate(const struct tcp_hwrate_limit_table *crte, struct tcpcb *tp) | tcp_rel_pacing_rate(const struct tcp_hwrate_limit_table *crte, struct tcpcb *tp) | ||||
{ | { | ||||
const struct tcp_rate_set *crs; | const struct tcp_rate_set *crs; | ||||
struct tcp_rate_set *rs; | struct tcp_rate_set *rs; | ||||
uint64_t pre; | uint64_t pre; | ||||
INP_WLOCK_ASSERT(tp->t_inpcb); | |||||
tp->t_pacing_rate = -1; | |||||
crs = crte->ptbl; | crs = crte->ptbl; | ||||
/* | /* | ||||
* Now we must break the const | * Now we must break the const | ||||
* in order to release our refcount. | * in order to release our refcount. | ||||
*/ | */ | ||||
rs = __DECONST(struct tcp_rate_set *, crs); | rs = __DECONST(struct tcp_rate_set *, crs); | ||||
pre = atomic_fetchadd_64(&rs->rs_flows_using, -1); | pre = atomic_fetchadd_64(&rs->rs_flows_using, -1); | ||||
if (pre == 1) { | if (pre == 1) { | ||||
▲ Show 20 Lines • Show All 149 Lines • Show Last 20 Lines |