Commit 37f5e170 authored by Andreas Schmidt's avatar Andreas Schmidt

Improve BBR.

* more parameters are visible
* function names follow the ietf draft
* slight fixes
parent f58b26e5
......@@ -150,6 +150,9 @@ cdef extern from "proto/socket.h":
uint32_t PrrtSocket_get_bbr_state(PrrtSocket *s)
uint64_t PrrtSocket_get_full_bw(PrrtSocket *s)
bint PrrtSocket_get_filled_pipe(PrrtSocket *s)
uint32_t PrrtSocket_get_cycle_index(PrrtSocket *s)
float PrrtSocket_get_pacing_gain(PrrtSocket *s)
bint PrrtSocket_get_app_limited(PrrtSocket *socket)
bint PrrtSocket_enable_thread_pinning(PrrtSocket *socket)
......
......@@ -4,7 +4,7 @@
#include "receiver.h"
uint32_t BBR_Inflight(BBR* bbr, float gain)
prrtByteCount_t BBR_Inflight(BBR* bbr, float gain)
{
if (bbr->rtprop == Inf)
return InitialCwnd; /* no valid RTT samples yet */
......@@ -20,10 +20,10 @@ void BBR_EnterStartup(BBR* bbr)
bbr->cwnd_gain = BBRHighGain;
}
void BBR_UpdateBtlBw(BBR* bbr, PrrtRateSample* rs, prrtByteCount_t packet_delivered, prrtByteCount_t delivered)
void BBR_UpdateBtlBw(BBR* bbr, PrrtRateSample* rs, PrrtPacketTracking* tracking)
{
if (packet_delivered >= bbr->next_round_delivered) {
bbr->next_round_delivered = delivered;
if (tracking->bytes_delivered >= bbr->next_round_delivered) {
bbr->next_round_delivered = tracking->delivered;
bbr->round_count++;
bbr->round_start = true;
} else {
......@@ -49,7 +49,7 @@ void BBR_CheckFullPipe(BBR* bbr, PrrtRateSample* rs)
bbr->filled_pipe = true;
}
bool BBR_IsNextCyclePhase(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtSequenceNumber_t prior_inflight)
bool BBR_IsNextCyclePhase(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtByteCount_t prior_inflight)
{
bool is_full_length = (PrrtClock_get_current_time_us() - bbr->cycle_stamp) > bbr->rtprop;
if (bbr->pacing_gain == 1)
......@@ -68,7 +68,7 @@ void BBR_AdvanceCyclePhase(BBR* bbr)
debug(DEBUG_BBR, "Advanced cycle with gain: %f", bbr->pacing_gain);
}
void BBR_CheckCyclePhase(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtSequenceNumber_t prior_inflight) {
void BBR_CheckCyclePhase(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtByteCount_t prior_inflight) {
if (bbr->state == PROBE_BW && BBR_IsNextCyclePhase(bbr, packets_lost, prior_inflight))
BBR_AdvanceCyclePhase(bbr);
}
......@@ -82,7 +82,7 @@ void BBR_EnterProbeBW(BBR* bbr)
BBR_AdvanceCyclePhase(bbr);
}
void BBR_CheckDrain(BBR* bbr, prrtSequenceNumber_t packets_in_flight)
void BBR_CheckDrain(BBR* bbr, prrtByteCount_t bytes_inflight)
{
if (bbr->state == STARTUP && bbr->filled_pipe) {
//Drain
......@@ -90,7 +90,7 @@ void BBR_CheckDrain(BBR* bbr, prrtSequenceNumber_t packets_in_flight)
bbr->pacing_gain = 1 / BBRHighGain; // pace slowly
bbr->cwnd_gain = BBRHighGain; // maintain cwnd
}
if (bbr->state == DRAIN && packets_in_flight <= BBR_Inflight(bbr, 1.0))
if (bbr->state == DRAIN && bytes_inflight <= BBR_Inflight(bbr, 1.0))
BBR_EnterProbeBW(bbr); // we estimate queue is drained
}
......@@ -115,49 +115,63 @@ void BBR_RestoreCwnd(BBR* bbr)
bbr->cwnd = bbr->cwnd > bbr->prior_cwnd ? bbr->cwnd : bbr->prior_cwnd;
}
void BBR_UpdateRTprop(BBR* bbr, prrtTimedelta_t rtt, prrtByteCount_t delivered, prrtSequenceNumber_t packets_in_flight)
void BBR_UpdateRTprop(BBR* bbr, prrtTimedelta_t rtt)
{
bbr->rtprop_expired = PrrtClock_get_current_time_us() > (bbr->rtprop_stamp + RTpropFilterLen);
if (rtt >= 0 && (rtt <= bbr->rtprop || bbr->rtprop_expired)) {
bbr->rtprop = rtt;
bbr->rtprop_stamp = PrrtClock_get_current_time_us();
}
}
void BBR_EnterProbeRTT(BBR *bbr) {
bbr->state = PROBE_RTT;
bbr->pacing_gain = 1;
bbr->cwnd_gain = 1;
}
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) {
bbr->probe_rtt_done_stamp = now + ProbeRTTDuration;
bbr->probe_rtt_round_done = false;
bbr->next_round_delivered = tracking->delivered;
} else if (bbr->probe_rtt_done_stamp != 0) {
if (bbr->round_start)
bbr->probe_rtt_round_done = true;
if (bbr->probe_rtt_round_done && (now > bbr->probe_rtt_done_stamp)) {
bbr->rtprop_stamp = now;
BBR_RestoreCwnd(bbr);
BBR_ExitProbeRTT(bbr);
}
}
}
void BBR_CheckProbeRTT(BBR *bbr, PrrtPacketTracking *tracking) {
if (bbr->state != PROBE_RTT && bbr->rtprop_expired && !bbr->idle_restart) {
bbr->state = PROBE_RTT;
bbr->pacing_gain = 1;
bbr->cwnd_gain = 1;
BBR_EnterProbeRTT(bbr);
BBR_SaveCwnd(bbr);
bbr->probe_rtt_done_stamp = 0;
}
if (bbr->state == PROBE_RTT) {
/* Ignore low rate samples during ProbeRTT: */
prrtTimestamp_t now = PrrtClock_get_current_time_us();
if (bbr->probe_rtt_done_stamp == 0 && packets_in_flight <= BBRMinPipeCwnd) {
bbr->probe_rtt_done_stamp = now + ProbeRTTDuration;
bbr->probe_rtt_round_done = false;
bbr->next_round_delivered = delivered;
} else if (bbr->probe_rtt_done_stamp != 0) {
if (bbr->round_start)
bbr->probe_rtt_round_done = true;
if (bbr->probe_rtt_round_done && (now > bbr->probe_rtt_done_stamp)) {
bbr->rtprop_stamp = now;
BBR_RestoreCwnd(bbr);
BBR_ExitProbeRTT(bbr);
}
}
BBR_HandleProbeRTT(bbr, tracking);
}
bbr->idle_restart = false;
}
void BBR_UpdateModel(BBR* bbr, PrrtChannelStateInformation* csi, PrrtRateSample* rs, PrrtPacketTracking* packetTracking)
void BBR_UpdateModelAndState(BBR *bbr, PrrtChannelStateInformation *csi, PrrtRateSample *rs,
PrrtPacketTracking *packetTracking)
{
BBR_UpdateBtlBw(bbr, rs, packetTracking->bytes_delivered, packetTracking->delivered);
BBR_UpdateBtlBw(bbr, rs, packetTracking);
BBR_CheckCyclePhase(bbr, packetTracking->packets_lost, packetTracking->prior_inflight);
BBR_CheckFullPipe(bbr, rs);
BBR_CheckDrain(bbr, packetTracking->packets_lost);
BBR_UpdateRTprop(bbr, PrrtChannelStateInformation_get_rtprop(csi), packetTracking->delivered, packetTracking->packets_in_flight);
BBR_CheckDrain(bbr, packetTracking->pipe);
BBR_UpdateRTprop(bbr, PrrtChannelStateInformation_get_rtprop(csi));
BBR_CheckProbeRTT(bbr, packetTracking);
}
void BBR_UpdateTargetCwnd(BBR* bbr)
......@@ -211,7 +225,7 @@ void BBR_SetPacingRate(BBR* bbr)
void BBR_OnACK(BBR* bbr, PrrtChannelStateInformation* csi, PrrtRateSample* rs, PrrtPacketTracking* packetTracking)
{
BBR_UpdateModel(bbr, csi, rs, packetTracking);
BBR_UpdateModelAndState(bbr, csi, rs, packetTracking);
BBR_SetPacingRate(bbr);
......@@ -223,8 +237,7 @@ BBR* BBR_Init(void)
BBR* bbr = calloc(1, sizeof(BBR));
check_mem(bbr);
bbr->btlBwFilter = WindowedFilter_Init(true);
//bbr->rtprop = SRTT ? SRTT : Inf;
bbr->rtprop = UINT32_MAX;
bbr->rtprop = Inf;
bbr->rtprop_stamp = PrrtClock_get_current_time_us();
bbr->probe_rtt_done_stamp = 0;
bbr->probe_rtt_round_done = false;
......@@ -283,6 +296,14 @@ uint32_t BBR_getState(BBR* bbr) {
return bbr->state;
}
uint32_t BBR_getCycleIndex(BBR* bbr) {
return bbr->cycle_index;
}
float BBR_getPacingGain(BBR* bbr) {
return bbr->pacing_gain;
}
bool BBR_getFilledPipe(BBR* bbr) {
return bbr->filled_pipe;
}
......
......@@ -10,16 +10,14 @@
#include "types/rateSample.h"
#include "../util/windowedFilter.h"
#define BtlBwFilterLen 10
#define MTU 1500
#define RTpropFilterLen 10000000 //10s
#define BBRHighGain ((2885 / 1000) + 1)
#define ProbeRTTInterval 10
#define InitialCwnd 10
#define InitialCwnd (10 * MTU)
#define BBRGainCycleLen 8
#define BBRMinPipeCwnd 4
//#define BBRMinPipeCwnd 200
#define BBRMinPipeCwnd (4 * MTU)
#define ProbeRTTDuration 200000 //200ms
#define Inf 0 //TODO: What is Inf
#define Inf UINT32_MAX
enum bbr_state {
STARTUP,
......@@ -80,6 +78,8 @@ uint32_t BBR_getCwnd(BBR* bbr);
prrtDeliveryRate_t BBR_getBtlBw(BBR* bbr);
uint32_t BBR_getState(BBR* bbr);
uint64_t BBR_getFullBw(BBR* bbr);
float BBR_getPacingGain(BBR* bbr);
uint32_t BBR_getCycleIndex(BBR* bbr);
bool BBR_getFilledPipe(BBR* bbr);
uint32_t BBR_getRTProp(BBR* bbr);
......
......@@ -185,7 +185,7 @@ bool PrrtReceiver_updateAndGenerateRateSample(PrrtReceiver *recv, prrtSequenceNu
recv->packetTracking->packets_delivered++;
recv->packetTracking->packets_in_flight = (prrtSequenceNumber_t) (PrrtInFlightPacketStore_get_queue_size(recv->dataInflightPacketStore) + PrrtInFlightPacketStore_get_queue_size(recv->redundancyInflightPacketStore));
recv->packetTracking->prior_inflight = recv->packetTracking->packets_in_flight;
recv->packetTracking->prior_inflight = recv->packetTracking->pipe;
if(recv->rateSample != NULL && result) {
BBR_OnACK(recv->bbr, recv->csi, recv->rateSample, recv->packetTracking);
}
......
......@@ -614,6 +614,13 @@ uint64_t PrrtSocket_get_full_bw(PrrtSocket *s) {
return BBR_getFullBw(s->receiver->bbr);
}
float PrrtSocket_get_pacing_gain(PrrtSocket *s) {
return BBR_getPacingGain(s->receiver->bbr);
}
uint32_t PrrtSocket_get_cycle_index(PrrtSocket *s) {
return BBR_getCycleIndex(s->receiver->bbr);
}
bool PrrtSocket_get_app_limited(PrrtSocket *s) {
return PrrtChannelStateInformation_get_app_limited(s->receiver->csi);
......
......@@ -138,5 +138,8 @@ uint64_t PrrtSocket_get_full_bw(PrrtSocket *s);
bool PrrtSocket_get_filled_pipe(PrrtSocket *s);
uint32_t PrrtSocket_get_bbr_state(PrrtSocket *s);
bool PrrtSocket_get_app_limited(PrrtSocket *s);
uint32_t PrrtSocket_get_cycle_index(PrrtSocket *s);
float PrrtSocket_get_pacing_gain(PrrtSocket *s);
#endif // PRRT_SOCKET_H
......@@ -11,7 +11,7 @@ typedef struct packetTracking {
prrtByteCount_t app_limited;
prrtByteCount_t bytes_delivered;
prrtSequenceNumber_t packets_lost;
prrtSequenceNumber_t prior_inflight;
prrtByteCount_t prior_inflight;
prrtSequenceNumber_t packets_in_flight;
prrtSequenceNumber_t packets_delivered;
} PrrtPacketTracking;
......
......@@ -13,7 +13,7 @@ typedef struct prrtRateSample {
prrtByteCount_t delivered;
bool is_app_limited;
prrtDeliveryRate_t delivery_rate; // Bps
prrtDeliveryRate_t delivery_rate; // bps
} PrrtRateSample;
#endif //PRRT_RATESAMPLE_H
......@@ -204,12 +204,25 @@ cdef class PrrtSocket:
raise Exception("Not a sender.")
return cprrt.PrrtSocket_get_filled_pipe(self._c_socket)
property bbr_full_bw:
def __get__(self):
if not self.isSender:
raise Exception("Not a sender.")
return cprrt.PrrtSocket_get_full_bw(self._c_socket)
property bbr_cycle_index:
def __get__(self):
if not self.isSender:
raise Exception("Not a sender.")
return cprrt.PrrtSocket_get_cycle_index(self._c_socket)
property bbr_pacing_gain:
def __get__(self):
if not self.isSender:
raise Exception("Not a sender.")
return cprrt.PrrtSocket_get_pacing_gain(self._c_socket)
property app_limited:
def __get__(self):
if not self.isSender:
......
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