You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

120 lines
3.9 KiB

#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define BBR_SCALE 8
#define BBR_UNIT (1 << BBR_SCALE)
#define BW_SCALE 24
#define BW_UNIT (1 << BW_SCALE)
#define BBR_STARTUP_PACING_GAIN (BBR_UNIT * 277 / 100 + 1)
#define BBR_STARTUP_CWND_GAIN (BBR_UNIT * 2)
#define BBR_DRAIN_GAIN (BBR_UNIT * 1000 / 2885)
#define BBR_CWND_GAIN (BBR_UNIT * 2)
#define BBR_PROBE_RTT_CWND_GAIN (BBR_UNIT * 1 / 2)
#define BBR_CWND_MIN_TARGET 4
#define BBR_FULL_BW_THRESH (BBR_UNIT * 5 / 4)
#define BBR_FULL_BW_CNT 3
#define BBR_LOSS_THRESH (BBR_UNIT * 2 / 100)
#define BBR_BETA (BBR_UNIT * 30 / 100)
#define BBR_INFLIGHT_HEADROOM (BBR_UNIT * 15 / 100)
#define BBR_EXTRA_ACKED_GAIN BBR_UNIT
#define BBR_EXTRA_ACKED_WIN_RTTS 5
#define BBR_ACK_EPOCH_ACKED_RESET_THRESH (1U << 20)
#define BBR_EXTRA_ACKED_MAX_US (100 * 1000)
#define BBR_FULL_LOSS_CNT 6
#define BBR_BW_PROBE_MAX_ROUNDS 63
#define BBR_BW_PROBE_RAND_ROUNDS 2
#define BBR_BW_PROBE_BASE_US (2 * 1000000)
#define BBR_BW_PROBE_RAND_US (1 * 1000000)
#define BBR_PROBE_RTT_WIN_MS 5000
#define BBR_MIN_RTT_WIN_SEC 10
#define BBR_PROBE_RTT_MS 200
enum bbr_mode { BBR_STARTUP = 0, BBR_DRAIN = 1, BBR_PROBE_BW = 2, BBR_PROBE_RTT = 3 };
enum bbr_bw_probe_cyc { BBR_BW_PROBE_UP = 0, BBR_BW_PROBE_DOWN = 1, BBR_BW_PROBE_CRUISE = 2, BBR_BW_PROBE_REFILL = 3 };
enum bbr_ack_phase { BBR_ACKS_INIT = 0, BBR_ACKS_REFILLING, BBR_ACKS_PROBE_STARTING, BBR_ACKS_PROBE_FEEDBACK, BBR_ACKS_PROBE_STOPPING };
struct bbr_rate_sample {
uint32_t delivered;
uint32_t interval_us;
uint32_t rtt_us;
uint32_t acked_sacked;
uint32_t prior_delivered;
uint32_t tx_in_flight;
int lost;
int is_app_limited;
};
typedef void (*bbr_cwnd_update_fn)(void* ctx, uint32_t new_cwnd);
struct bbr {
uint32_t min_rtt_us;
uint32_t bw_lo;
uint32_t bw_hi[2];
uint32_t inflight_lo;
uint32_t inflight_hi;
uint32_t bw_latest;
uint32_t inflight_latest;
uint8_t mode;
uint8_t cycle_idx;
uint16_t pacing_gain;
uint16_t cwnd_gain;
uint32_t next_rtt_delivered;
uint8_t round_start : 1;
uint8_t full_bw_reached : 1;
uint8_t loss_in_round : 1;
uint8_t loss_in_cycle : 1;
uint8_t idle_restart : 1;
uint8_t try_fast_path : 1;
uint8_t has_seen_rtt : 1;
uint8_t initialized : 1;
uint32_t loss_round_delivered;
uint32_t bw_probe_up_cnt;
uint32_t bw_probe_up_acks;
uint8_t bw_probe_up_rounds;
uint8_t bw_probe_samples : 1;
uint8_t prev_probe_too_high: 1;
uint8_t stopped_risky_probe: 1;
uint8_t rounds_since_probe;
uint32_t probe_wait_us;
uint64_t cycle_mstamp_tb;
uint32_t probe_rtt_min_us;
uint64_t probe_rtt_min_stamp_tb;
uint64_t probe_rtt_done_stamp_tb;
uint8_t probe_rtt_round_done : 1;
uint16_t extra_acked[2];
uint32_t ack_epoch_acked;
uint64_t ack_epoch_mstamp_tb;
uint8_t extra_acked_win_idx : 1;
uint8_t extra_acked_win_rtts : 5;
uint32_t prior_cwnd;
uint8_t init_cwnd : 7;
uint8_t full_bw_cnt : 2;
uint8_t ack_phase : 3;
uint8_t loss_events_in_round : 4;
uint32_t delivered;
uint32_t full_bw;
uint64_t min_rtt_stamp_tb;
uint8_t loss_round_start : 1;
uint8_t full_bw_now : 1;
uint8_t pad_unused : 6;
uint8_t link_id; // local_link_id for debug logging
uint64_t now_tb; // 0 = real get_time_tb(); >0 = test-controlled time
bbr_cwnd_update_fn on_cwnd_update;
void* cwnd_update_ctx;
};
void bbr_init(struct bbr* bbr);
void bbr_main(struct bbr* bbr, const struct bbr_rate_sample* rs,
uint32_t* cwnd_out, uint32_t* pacing_rate_out,
uint32_t mss, uint32_t inflight_bytes, int is_cwnd_limited);
void bbr_note_loss(struct bbr* bbr);
void bbr_tx_start(struct bbr* bbr);
#ifdef __cplusplus
}
#endif