/* WARNING: This implementation is not necessarily the same *asthetcp_cubic.c.Thepurposeismainlyfortesting *thekernelBPFlogic. * *Highlights: *1.CONFIG_HZ.kconfigmapisused. *2.Inbictcp_update(),calculationischangedtouseusec *resolution(i.e.USEC_PER_JIFFY)insteadofusingjiffies. *Thus,usecs_to_jiffies()isnotusedinthebpf_cubic.c. *3.Inbitctcp_update()[undertcp_friendliness],theoriginal *"while(ca->ack_cnt>delta)"loopischangedtotheequivalent *"ca->ack_cnt/delta"operation.
*/
/* BIC TCP Parameters */ struct bpf_bictcp {
__u32 cnt; /* increase cwnd by 1 after ACKs */
__u32 last_max_cwnd; /* last maximum snd_cwnd */
__u32 last_cwnd; /* the last snd_cwnd */
__u32 last_time; /* time when updated last_cwnd */
__u32 bic_origin_point;/* origin point of bic function */
__u32 bic_K; /* time to origin point
from the beginning of the current epoch */
__u32 delay_min; /* min delay (usec) */
__u32 epoch_start; /* beginning of an epoch */
__u32 ack_cnt; /* number of acks */
__u32 tcp_cwnd; /* estimated tcp cwnd */
__u16 unused;
__u8 sample_cnt; /* number of samples to decide curr_rtt */
__u8 found; /* the exit point is found? */
__u32 round_start; /* beginning of each round */
__u32 end_seq; /* end_seq of the round */
__u32 last_ack; /* last time when the ACK spacing is close */
__u32 curr_rtt; /* the minimum rtt of current round */
};
#define BITS_PER_U64 (sizeof(__u64) * 8) staticint fls64(__u64 x)
{ int num = BITS_PER_U64 - 1;
if (x == 0) return0;
if (!(x & (~0ull << (BITS_PER_U64-32)))) {
num -= 32;
x <<= 32;
} if (!(x & (~0ull << (BITS_PER_U64-16)))) {
num -= 16;
x <<= 16;
} if (!(x & (~0ull << (BITS_PER_U64-8)))) {
num -= 8;
x <<= 8;
} if (!(x & (~0ull << (BITS_PER_U64-4)))) {
num -= 4;
x <<= 4;
} if (!(x & (~0ull << (BITS_PER_U64-2)))) {
num -= 2;
x <<= 2;
} if (!(x & (~0ull << (BITS_PER_U64-1))))
num -= 1;
/* calculate the cubic root of x using a table lookup followed by one *Newton-Raphsoniteration. *Avgerr~=0.195%
*/ static __u32 cubic_root(__u64 a)
{
__u32 x, b, shift;
if (a < 64) { /* a in [0..63] */ return ((__u32)v[(__u32)a] + 35) >> 6;
}
b = fls64(a);
b = ((b * 84) >> 8) - 1;
shift = (a >> (b * 3));
/* it is needed for verifier's bound check on v */ if (shift >= 64) return0;
x = ((__u32)(((__u32)v[shift] + 10) << b)) >> 6;
/* *Newton-Raphsoniteration *2 *x=(2*x+a/x)/3 *k+1kk
*/
x = (2 * x + (__u32)div64_u64(a, (__u64)x * (__u64)(x - 1)));
x = ((x * 341) >> 10); return x;
}
/* The CUBIC function can update ca->cnt at most once per jiffy. *Onallcwndreductionevents,ca->epoch_startissetto0, *whichwillforcearecalculationofca->cnt.
*/ if (ca->epoch_start && tcp_jiffies32 == ca->last_time) goto tcp_friendliness;
t = (__s32)(tcp_jiffies32 - ca->epoch_start) * USEC_PER_JIFFY;
t += ca->delay_min; /* change the unit from usec to bictcp_HZ */
t <<= BICTCP_HZ;
t /= USEC_PER_SEC;
if (t < ca->bic_K) /* t - K */
offs = ca->bic_K - t; else
offs = t - ca->bic_K;
/* Hystart ack train triggers if we get ack past *ca->delay_min/2. *PacingmighthavedelayedpacketsuptoRTT/2 *duringslowstart.
*/ if (sk->sk_pacing_status == SK_PACING_NONE)
threshold >>= 1;
bpf_cubic_acked_called = 1; /* Some calls are for duplicates without timestamps */ if (sample->rtt_us < 0) return;
/* Discard delay samples right after fast recovery */ if (ca->epoch_start && (__s32)(tcp_jiffies32 - ca->epoch_start) < HZ) return;
delay = sample->rtt_us; if (delay == 0)
delay = 1;
/* first time call or link delay decreases */ if (ca->delay_min == 0 || ca->delay_min > delay)
ca->delay_min = delay;
/* hystart triggers when cwnd is larger than some threshold */ if (!ca->found && tcp_in_slow_start(tp) && hystart &&
tp->snd_cwnd >= hystart_low_window)
hystart_update(sk, delay);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.