Commit 67f15d71 authored by rna's avatar rna

Refactor BBR to use maximum payload size.

parent a08fa1d6
Pipeline #2542 passed with stages
in 1 minute and 9 seconds
......@@ -4,11 +4,10 @@
#include "receiver.h"
#include <math.h>
prrtByteCount_t BBR_Inflight(BBR* bbr, double gain)
{
if (bbr->rtprop == Inf)
return InitialCwnd; /* no valid RTT samples yet */
return bbr->initial_cwnd; /* no valid RTT samples yet */
uint32_t quanta = 0;
uint32_t estimated_bdp = (uint32_t) round((((double)bbr->bw) * bbr->rtprop) / (1000 * 1000));
return (uint32_t)(gain * estimated_bdp + quanta);
......@@ -41,7 +40,7 @@ void BBR_CheckFullPipe(BBR* bbr, PrrtRateSample* rs)
{
if (bbr->filled_pipe || !bbr->round_start || rs->is_app_limited)
return; // no need to check for a full pipe now
if (bbr->bw >= bbr->full_bw * 1.25) { // BBR.BtlBw still growing?
if (bbr->bw >= bbr->full_bw * PROBE_GAIN) { // BBR.BtlBw still growing?
bbr->full_bw = bbr->bw; // record new baseline level
bbr->full_bw_count = 0;
return;
......@@ -58,14 +57,16 @@ bool BBR_IsNextCyclePhase(BBR* bbr, prrtByteCount_t bytes_lost, prrtByteCount_t
return is_full_length;
if (bbr->pacing_gain > 1)
return is_full_length && (bytes_lost > 0 || prior_inflight >= BBR_Inflight(bbr, bbr->pacing_gain));
return is_full_length || (prior_inflight <= BBR_Inflight(bbr, 1.0));
bool is_max_length = (PrrtClock_get_current_time_us() - bbr->cycle_stamp) > 4 * bbr->rtprop;
return is_max_length || (prior_inflight <= BBR_Inflight(bbr, 1.0));
}
void BBR_AdvanceCyclePhase(BBR* bbr)
{
bbr->cycle_stamp = PrrtClock_get_current_time_us();
bbr->cycle_index = (uint8_t )((bbr->cycle_index + 1) % BBRGainCycleLen);
float pacing_gain_cycle[BBRGainCycleLen] = {1.25, 0.75, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
float pacing_gain_cycle[BBRGainCycleLen] = {PROBE_GAIN, DRAIN_GAIN, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
bbr->pacing_gain = pacing_gain_cycle[bbr->cycle_index];
debug(DEBUG_BBR, "Advanced cycle with gain: %f", bbr->pacing_gain);
}
......@@ -135,7 +136,7 @@ void BBR_HandleProbeRTT(BBR *bbr, PrrtPacketTracking *tracking) {
tracking->app_limited = (tracking->delivered + tracking->pipe) ? : 1;
/* Ignore low rate samples during ProbeRTT: */
prrtTimestamp_t now = PrrtClock_get_current_time_us();
if (bbr->probe_rtt_done_stamp == 0 && tracking->pipe <= BBRMinPipeCwnd) {
if (bbr->probe_rtt_done_stamp == 0 && tracking->pipe <= bbr->min_pipe_cwnd) {
bbr->probe_rtt_done_stamp = now + ProbeRTTDuration;
bbr->probe_rtt_round_done = false;
bbr->next_round_delivered = tracking->delivered;
......@@ -183,13 +184,13 @@ void BBR_UpdateTargetCwnd(BBR* bbr)
void BBR_ModulateCwndForProbeRTT(BBR* bbr)
{
if (bbr->state == PROBE_RTT)
bbr->cwnd = MIN(bbr->cwnd, BBRMinPipeCwnd);
bbr->cwnd = MIN(bbr->cwnd, bbr->min_pipe_cwnd);
}
void BBR_ModulateCwndForRecovery(BBR* bbr, prrtByteCount_t bytes_lost, prrtByteCount_t pipe, prrtByteCount_t delivered)
{
if (bytes_lost > 0)
bbr->cwnd = MAX(bbr->cwnd - bytes_lost, SMSS);
bbr->cwnd = MAX(bbr->cwnd - bytes_lost, bbr->mps);
if (bbr->packet_conservation)
bbr->cwnd = MAX(bbr->cwnd, pipe + delivered);
}
......@@ -202,9 +203,9 @@ void BBR_SetCwnd(BBR* bbr, PrrtPacketTracking* packetTracking)
if (!bbr->packet_conservation) {
if (bbr->filled_pipe)
bbr->cwnd = MIN(bbr->cwnd + packetTracking->delivered, bbr->target_cwnd);
else if (bbr->cwnd < bbr->target_cwnd || packetTracking->delivered < InitialCwnd)
else if (bbr->cwnd < bbr->target_cwnd || packetTracking->delivered < bbr->initial_cwnd)
bbr->cwnd = bbr->cwnd + packetTracking->delivered;
bbr->cwnd = MAX(bbr->cwnd, BBRMinPipeCwnd);
bbr->cwnd = MAX(bbr->cwnd, bbr->min_pipe_cwnd);
}
BBR_ModulateCwndForProbeRTT(bbr);
debug(DEBUG_BBR, "New cwnd: %u, State: %u", bbr->cwnd, bbr->state);
......@@ -226,9 +227,9 @@ void BBR_SetPacingRate(BBR* bbr)
void BBR_SetSendQuantum(BBR* bbr) {
if(bbr->pacing_rate < 150000) { // 1.2Mbps = 0.15 MBps = 150000 Bps
bbr->send_quantum = 1 * SMSS;
bbr->send_quantum = 1 * bbr->mps;
} else if (bbr->pacing_rate < 3000000) { // 24 Mbps = 20 * 1.2Mbps = 3000000
bbr->send_quantum = 2 * SMSS;
bbr->send_quantum = 2 * bbr->mps;
} else {
bbr->send_quantum = MIN((prrtByteCount_t) round((double) bbr->pacing_rate / 1000), 64000);
}
......@@ -270,7 +271,7 @@ void BBR_OnRTOLoss(BBR *bbr) {
if(!bbr->is_loss_recovery) {
bbr->is_loss_recovery = true;
bbr->prior_cwnd = BBR_SaveCwnd(bbr);
bbr->cwnd = SMSS;
bbr->cwnd = bbr->mps;
}
check(pthread_mutex_unlock(&bbr->lock) == 0, "Unlock failed.");
return;
......@@ -291,7 +292,7 @@ void BBR_OnLossExit(BBR *bbr) {
PERROR("BBR_OnACK failed.")
}
BBR* BBR_Init(void)
BBR* BBR_Init(prrtByteCount_t maximum_payload_size)
{
BBR* bbr = calloc(1, sizeof(BBR));
check_mem(bbr);
......@@ -301,7 +302,9 @@ BBR* BBR_Init(void)
check(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == EXIT_SUCCESS, "Setting type failed.");
check(pthread_mutex_init(&bbr->lock, &attr) == 0, "lock init failed.");
bbr->mps = maximum_payload_size;
bbr->min_pipe_cwnd = 4 * maximum_payload_size;
bbr->initial_cwnd = 4 * maximum_payload_size;
bbr->has_seen_rtt = false;
bbr->btlBwFilter = WindowedFilter_Init(true);
bbr->rtprop = Inf;
......@@ -310,7 +313,7 @@ BBR* BBR_Init(void)
bbr->probe_rtt_round_done = false;
bbr->packet_conservation = false;
bbr->prior_cwnd = 0;
bbr->cwnd = InitialCwnd;
bbr->cwnd = bbr->initial_cwnd;
bbr->idle_restart = false;
bbr->is_loss_recovery = false;
......@@ -325,7 +328,7 @@ BBR* BBR_Init(void)
bbr->full_bw_count = 0;
//Init pacing rate
double nominal_bandwidth = InitialCwnd / (bbr->has_seen_rtt ? bbr->rtprop : 1000);
double nominal_bandwidth = bbr->initial_cwnd / (bbr->has_seen_rtt ? bbr->rtprop : 1000);
bbr->pacing_rate = bbr->pacing_gain * nominal_bandwidth;
BBR_EnterStartup(bbr);
......
......@@ -10,12 +10,11 @@
#include "types/rateSample.h"
#include "../util/windowedFilter.h"
#define SMSS 1500
#define PROBE_GAIN 1.25
#define DRAIN_GAIN 0.75
#define RTpropFilterLen 10000000 //10s
#define BBRHighGain ((((float)2885) / 1000) + 1)
#define InitialCwnd (10 * SMSS)
#define BBRGainCycleLen 8
#define BBRMinPipeCwnd (4 * SMSS)
#define ProbeRTTDuration 200000 //200ms
#define Inf UINT32_MAX
......@@ -29,6 +28,9 @@ enum bbr_state {
typedef struct bbr {
pthread_mutex_t lock;
prrtByteCount_t mps;
prrtByteCount_t min_pipe_cwnd;
prrtByteCount_t initial_cwnd;
prrtTimedelta_t rtprop;
prrtTimestamp_t rtprop_stamp;
prrtTimestamp_t probe_rtt_done_stamp;
......@@ -73,7 +75,7 @@ typedef struct bbr {
WindowedFilter* btlBwFilter;
} BBR;
BBR* BBR_Init(void);
BBR* BBR_Init(prrtByteCount_t maximum_payload_size);
void BBR_OnACK(BBR* bbr, PrrtChannelStateInformation* csi, PrrtRateSample* rs, PrrtPacketTracking* packetTracking, prrtTimedelta_t rtt);
void BBR_OnSpuriousLoss(BBR *bbr, PrrtPacketTracking *tracking);
void BBR_OnRTOLoss(BBR *bbr);
......
......@@ -98,7 +98,7 @@ bool update_and_generate_rate_sample(PrrtReceiver *recv, prrtSequenceNumber_t se
return result;
}
PrrtReceiver *PrrtReceiver_create(const char *host, uint16_t port, prrtByteCount_t mss) {
PrrtReceiver *PrrtReceiver_create(const char *host, uint16_t port, prrtByteCount_t maximum_payload_size) {
PrrtReceiver *recv = calloc(1, sizeof(PrrtReceiver));
check_mem(recv);
recv->host_name = strdup(host);
......@@ -130,7 +130,7 @@ PrrtReceiver *PrrtReceiver_create(const char *host, uint16_t port, prrtByteCount
check(0 == getaddrinfo(host, portstr, &hints, &info), "getaddrinfo");
recv->ai = info;
recv->bbr = BBR_Init();
recv->bbr = BBR_Init(maximum_payload_size);
pthread_mutexattr_t attr;
check(pthread_mutexattr_init(&attr) == EXIT_SUCCESS, "Mutex attr init failed.");
......
......@@ -28,7 +28,7 @@ typedef struct prrtReceiver {
PrrtPacketTracking *packetTracking;
} PrrtReceiver;
PrrtReceiver *PrrtReceiver_create(const char *host, uint16_t port, prrtByteCount_t mss);
PrrtReceiver *PrrtReceiver_create(const char *host, uint16_t port, prrtByteCount_t maximum_payload_size);
void PrrtReceiver_add_outstanding_packet_state(PrrtReceiver *recv, PrrtPacket *packet, prrtTimestamp_t sentTime);
prrtByteCount_t PrrtReceiver_get_pipe(PrrtReceiver *recv);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment