Loading prrt/proto/CMakeLists.txt +2 −1 Original line number Diff line number Diff line add_library(PRRT ../defines.h block.c block.h bbr.c bbr.h channelStateInformation.c channelStateInformation.h clock.c clock.h codingParams.c codingParams.h Loading @@ -20,6 +21,6 @@ add_library(PRRT ../defines.h types/packetTimeout.c types/packetTimeout.h types/lossStatistics.c types/lossStatistics.h types/packet.c types/packet.h vdmcode/block_code.c vdmcode/block_code.h) vdmcode/block_code.c vdmcode/block_code.h types/packetTracking.c types/packetTracking.h types/rateSample.c types/rateSample.h) target_link_libraries(PRRT rt) prrt/proto/bbr.c 0 → 100644 +280 −0 Original line number Diff line number Diff line #include "bbr.h" #include "../util/dbg.h" #include "../util/common.h" #include "receiver.h" uint32_t BBR_Inflight(BBR* bbr, float gain) { if (bbr->rtprop == Inf) return InitialCwnd; /* no valid RTT samples yet */ uint32_t quanta = 3 * bbr->send_quantum; uint32_t estimated_bdp = bbr->bw * bbr->rtprop; return (uint32_t)(gain * estimated_bdp + quanta); } void BBR_EnterStartup(BBR* bbr) { bbr->state = STARTUP; bbr->pacing_gain = BBRHighGain; bbr->cwnd_gain = BBRHighGain; } void BBR_UpdateBtlBw(BBR* bbr, PrrtRateSample* rs, prrtByteCount_t packet_delivered, prrtByteCount_t delivered) { if (packet_delivered >= bbr->next_round_delivered) { bbr->next_round_delivered = delivered; bbr->round_count++; bbr->round_start = true; } else { bbr->round_start = false; } if ((rs->delivery_rate >= bbr->bw || !rs->is_app_limited) && rs->delivery_rate != 0) { bbr->bw = (uint32_t)WindowedFilter_push(bbr->btlBwFilter, (uint32_t)rs->delivery_rate); debug(DEBUG_BBR, "Current BtlBw: %u, RS delivery rate: %u", bbr->bw, (uint32_t)rs->delivery_rate); } } 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? bbr->full_bw = bbr->bw; // record new baseline level bbr->full_bw_count = 0; return; } bbr->full_bw_count++; // another round w/o much growth if (bbr->full_bw_count >= 3) bbr->filled_pipe = true; } bool BBR_IsNextCyclePhase(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtSequenceNumber_t prior_inflight) { bool is_full_length = (PrrtClock_get_current_time_us() - bbr->cycle_stamp) > bbr->rtprop; if (bbr->pacing_gain == 1) return is_full_length; if (bbr->pacing_gain > 1) return is_full_length && (packets_lost > 0 || prior_inflight >= BBR_Inflight(bbr, bbr->pacing_gain)); return is_full_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}; bbr->pacing_gain = pacing_gain_cycle[bbr->cycle_index]; debug(DEBUG_BBR, "Advanced cycle with gain: %f", bbr->pacing_gain); } void BBR_CheckCyclePhase(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtSequenceNumber_t prior_inflight) { if (bbr->state == PROBE_BW && BBR_IsNextCyclePhase(bbr, packets_lost, prior_inflight)) BBR_AdvanceCyclePhase(bbr); } void BBR_EnterProbeBW(BBR* bbr) { bbr->state = PROBE_BW; bbr->pacing_gain = 1; bbr->cwnd_gain = 2; bbr->cycle_index = (uint8_t)(BBRGainCycleLen - 1 - (random() % 7)); BBR_AdvanceCyclePhase(bbr); } void BBR_CheckDrain(BBR* bbr, prrtSequenceNumber_t packets_in_flight) { if (bbr->state == STARTUP && bbr->filled_pipe) { //Drain bbr->state = DRAIN; 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)) BBR_EnterProbeBW(bbr); // we estimate queue is drained } void BBR_ExitProbeRTT(BBR* bbr) { if (bbr->filled_pipe) BBR_EnterProbeBW(bbr); else BBR_EnterStartup(bbr); } uint32_t BBR_SaveCwnd(BBR* bbr) { //if (!InLossRecovery() && bbr->state != PROBE_RTT) if (bbr->state != PROBE_RTT) return bbr->cwnd; return MAX(bbr->prior_cwnd ,bbr->cwnd); } 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) { 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(); } if (bbr->state != PROBE_RTT && bbr->rtprop_expired && !bbr->idle_restart) { bbr->state = PROBE_RTT; bbr->pacing_gain = 1; bbr->cwnd_gain = 1; 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->idle_restart = false; } void BBR_UpdateModel(BBR* bbr, PrrtChannelStateInformation* csi, PrrtRateSample* rs, PrrtPacketTracking* packetTracking) { BBR_UpdateBtlBw(bbr, rs, packetTracking->bytes_delivered, packetTracking->delivered); 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); } void BBR_UpdateTargetCwnd(BBR* bbr) { bbr->target_cwnd = BBR_Inflight(bbr, bbr->cwnd_gain); } void BBR_ModulateCwndForProbeRTT(BBR* bbr) { if (bbr->state == PROBE_RTT) bbr->cwnd = MIN(bbr->cwnd, BBRMinPipeCwnd); } void BBR_ModulateCwndForRecovery(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtSequenceNumber_t packets_in_flight, prrtSequenceNumber_t packets_delivered) { if (packets_lost > 0) bbr->cwnd = MAX(bbr->cwnd - packets_lost, 1); if (bbr->packet_conservation) bbr->cwnd = MAX(bbr->cwnd, packets_in_flight + packets_delivered); } void BBR_SetCwnd(BBR* bbr, PrrtPacketTracking* packetTracking) { BBR_UpdateTargetCwnd(bbr); BBR_ModulateCwndForRecovery(bbr, packetTracking->packets_lost, packetTracking->packets_in_flight, packetTracking->packets_delivered); if (!bbr->packet_conservation) { if (bbr->filled_pipe) bbr->cwnd = MIN(bbr->cwnd + packetTracking->packets_delivered, bbr->target_cwnd); else if (bbr->cwnd < bbr->target_cwnd || packetTracking->delivered < InitialCwnd) bbr->cwnd = bbr->cwnd + packetTracking->packets_delivered; bbr->cwnd = MAX(bbr->cwnd, BBRMinPipeCwnd); } BBR_ModulateCwndForProbeRTT(bbr); debug(DEBUG_BBR, "New cwnd: %u, State: %u", bbr->cwnd, bbr->state); } void BBR_SetPacingRateWithGain(BBR* bbr, float pacing_gain) { uint32_t rate = (uint32_t) (pacing_gain * (float)bbr->bw); debug(DEBUG_BBR, "Current rate: %u, Pacing gain: %f, BtlBw: %u, Calc Rate: %u, Filled pipe: %u", bbr->pacing_rate, pacing_gain, bbr->bw, rate, bbr->filled_pipe); if (rate != 0 && (bbr->filled_pipe || rate > bbr->pacing_rate)) bbr->pacing_rate = rate; } void BBR_SetPacingRate(BBR* bbr) { BBR_SetPacingRateWithGain(bbr, bbr->pacing_gain); } void BBR_OnACK(BBR* bbr, PrrtChannelStateInformation* csi, PrrtRateSample* rs, PrrtPacketTracking* packetTracking) { BBR_UpdateModel(bbr, csi, rs, packetTracking); BBR_SetPacingRate(bbr); BBR_SetCwnd(bbr, packetTracking); } BBR* BBR_Init() { 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_stamp = PrrtClock_get_current_time_us(); bbr->probe_rtt_done_stamp = 0; bbr->probe_rtt_round_done = false; bbr->packet_conservation = false; bbr->prior_cwnd = 0; bbr->idle_restart = false; //Init round counting bbr->next_round_delivered = 0; bbr->round_start = false; bbr->round_count = 0; //Init full pipe bbr->filled_pipe = false; bbr->full_bw = 0; bbr->full_bw_count = 0; //Init pacing rate float nominal_bandwidth = InitialCwnd / (bbr->has_seen_rtt ? bbr->rtt : 1); bbr->pacing_rate = (uint32_t)(bbr->pacing_gain * nominal_bandwidth); BBR_EnterStartup(bbr); return bbr; error: PERROR("Failed to init BBR%s.", ""); return NULL; } void BBR_destroy(BBR* bbr) { WindowedFilter_destroy(bbr->btlBwFilter); free(bbr); } uint32_t BBR_getPacingRate(BBR* bbr) { return bbr->pacing_rate; } uint32_t BBR_getCwnd(BBR* bbr) { return bbr->cwnd; } uint32_t BBR_getBtlBw(BBR* bbr) { return bbr->bw; } uint32_t BBR_getRTProp(BBR* bbr) { return bbr->rtprop; } No newline at end of file prrt/proto/bbr.h 0 → 100644 +83 −0 Original line number Diff line number Diff line #ifndef PRRT_BBR_H #define PRRT_BBR_H #include <stdint.h> #include "stdbool.h" #include "types/packet.h" #include "clock.h" #include "channelStateInformation.h" #include "types/packetTracking.h" #include "types/rateSample.h" #include "../util/windowedFilter.h" #define BtlBwFilterLen 10 #define RTpropFilterLen 10000000 //10s #define BBRHighGain ((2885 / 1000) + 1) #define ProbeRTTInterval 10 #define InitialCwnd 10 #define BBRGainCycleLen 8 #define BBRMinPipeCwnd 4 //#define BBRMinPipeCwnd 200 #define ProbeRTTDuration 200000 //200ms #define Inf 0 //TODO: What is Inf enum bbr_state { STARTUP, DRAIN, PROBE_BW, PROBE_RTT }; typedef struct bbr { uint32_t rtprop; prrtTimestamp_t rtprop_stamp; uint32_t probe_rtt_done_stamp; bool probe_rtt_round_done; bool packet_conservation; uint32_t prior_cwnd; uint32_t cwnd; uint32_t target_cwnd; bool idle_restart; enum bbr_state state; float pacing_gain; float cwnd_gain; bool filled_pipe; uint64_t full_bw; uint32_t full_bw_count; uint32_t pacing_rate; bool has_seen_rtt; uint32_t rtt; uint32_t next_round_delivered; bool round_start; uint32_t round_count; uint32_t next_rtt_delivered; uint32_t rtt_count; bool rtprop_expired; prrtTimestamp_t cycle_stamp; uint8_t cycle_index; float* pacing_gain_cycle; uint32_t send_quantum; uint32_t bw; WindowedFilter* btlBwFilter; } BBR; BBR* BBR_Init(); void BBR_OnACK(BBR* bbr, PrrtChannelStateInformation* csi, PrrtRateSample* rs, PrrtPacketTracking* recv_stats); void BBR_destroy(BBR* bbr); uint32_t BBR_getPacingRate(BBR* bbr); uint32_t BBR_getCwnd(BBR* bbr); uint32_t BBR_getBtlBw(BBR* bbr); uint32_t BBR_getRTProp(BBR* bbr); #endif //PRRT_BBR_H prrt/proto/channelStateInformation.c +0 −10 Original line number Diff line number Diff line Loading @@ -56,16 +56,6 @@ void PrrtChannelStateInformation_update_delivery_rate(PrrtChannelStateInformatio pthread_mutex_lock(&csi->lock); prrtDeliveryRate_t rate = rateSample->delivery_rate; csi->deliveryRate = rate; if(csi->btlbw_rounds > csi->btlbw_filter_length_rtts) { csi->btlbw = 0; } csi->btlbw_rounds += 1; if(csi->btlbw < rate) { csi->btlbw = rate; csi->btlbw_rounds = 0; } pthread_mutex_unlock(&csi->lock); } void PrrtChannelStateInformation_update_app_limited(PrrtChannelStateInformation *csi, bool appLimited) { Loading prrt/proto/channelStateInformation.h +1 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ #define PRRT_CHANNELSTATEINFORMATION_H #include <stdbool.h> #include "types/rateSample.h" #include "types/packet.h" typedef struct prrtChannelStateInformation { Loading Loading
prrt/proto/CMakeLists.txt +2 −1 Original line number Diff line number Diff line add_library(PRRT ../defines.h block.c block.h bbr.c bbr.h channelStateInformation.c channelStateInformation.h clock.c clock.h codingParams.c codingParams.h Loading @@ -20,6 +21,6 @@ add_library(PRRT ../defines.h types/packetTimeout.c types/packetTimeout.h types/lossStatistics.c types/lossStatistics.h types/packet.c types/packet.h vdmcode/block_code.c vdmcode/block_code.h) vdmcode/block_code.c vdmcode/block_code.h types/packetTracking.c types/packetTracking.h types/rateSample.c types/rateSample.h) target_link_libraries(PRRT rt)
prrt/proto/bbr.c 0 → 100644 +280 −0 Original line number Diff line number Diff line #include "bbr.h" #include "../util/dbg.h" #include "../util/common.h" #include "receiver.h" uint32_t BBR_Inflight(BBR* bbr, float gain) { if (bbr->rtprop == Inf) return InitialCwnd; /* no valid RTT samples yet */ uint32_t quanta = 3 * bbr->send_quantum; uint32_t estimated_bdp = bbr->bw * bbr->rtprop; return (uint32_t)(gain * estimated_bdp + quanta); } void BBR_EnterStartup(BBR* bbr) { bbr->state = STARTUP; bbr->pacing_gain = BBRHighGain; bbr->cwnd_gain = BBRHighGain; } void BBR_UpdateBtlBw(BBR* bbr, PrrtRateSample* rs, prrtByteCount_t packet_delivered, prrtByteCount_t delivered) { if (packet_delivered >= bbr->next_round_delivered) { bbr->next_round_delivered = delivered; bbr->round_count++; bbr->round_start = true; } else { bbr->round_start = false; } if ((rs->delivery_rate >= bbr->bw || !rs->is_app_limited) && rs->delivery_rate != 0) { bbr->bw = (uint32_t)WindowedFilter_push(bbr->btlBwFilter, (uint32_t)rs->delivery_rate); debug(DEBUG_BBR, "Current BtlBw: %u, RS delivery rate: %u", bbr->bw, (uint32_t)rs->delivery_rate); } } 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? bbr->full_bw = bbr->bw; // record new baseline level bbr->full_bw_count = 0; return; } bbr->full_bw_count++; // another round w/o much growth if (bbr->full_bw_count >= 3) bbr->filled_pipe = true; } bool BBR_IsNextCyclePhase(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtSequenceNumber_t prior_inflight) { bool is_full_length = (PrrtClock_get_current_time_us() - bbr->cycle_stamp) > bbr->rtprop; if (bbr->pacing_gain == 1) return is_full_length; if (bbr->pacing_gain > 1) return is_full_length && (packets_lost > 0 || prior_inflight >= BBR_Inflight(bbr, bbr->pacing_gain)); return is_full_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}; bbr->pacing_gain = pacing_gain_cycle[bbr->cycle_index]; debug(DEBUG_BBR, "Advanced cycle with gain: %f", bbr->pacing_gain); } void BBR_CheckCyclePhase(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtSequenceNumber_t prior_inflight) { if (bbr->state == PROBE_BW && BBR_IsNextCyclePhase(bbr, packets_lost, prior_inflight)) BBR_AdvanceCyclePhase(bbr); } void BBR_EnterProbeBW(BBR* bbr) { bbr->state = PROBE_BW; bbr->pacing_gain = 1; bbr->cwnd_gain = 2; bbr->cycle_index = (uint8_t)(BBRGainCycleLen - 1 - (random() % 7)); BBR_AdvanceCyclePhase(bbr); } void BBR_CheckDrain(BBR* bbr, prrtSequenceNumber_t packets_in_flight) { if (bbr->state == STARTUP && bbr->filled_pipe) { //Drain bbr->state = DRAIN; 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)) BBR_EnterProbeBW(bbr); // we estimate queue is drained } void BBR_ExitProbeRTT(BBR* bbr) { if (bbr->filled_pipe) BBR_EnterProbeBW(bbr); else BBR_EnterStartup(bbr); } uint32_t BBR_SaveCwnd(BBR* bbr) { //if (!InLossRecovery() && bbr->state != PROBE_RTT) if (bbr->state != PROBE_RTT) return bbr->cwnd; return MAX(bbr->prior_cwnd ,bbr->cwnd); } 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) { 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(); } if (bbr->state != PROBE_RTT && bbr->rtprop_expired && !bbr->idle_restart) { bbr->state = PROBE_RTT; bbr->pacing_gain = 1; bbr->cwnd_gain = 1; 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->idle_restart = false; } void BBR_UpdateModel(BBR* bbr, PrrtChannelStateInformation* csi, PrrtRateSample* rs, PrrtPacketTracking* packetTracking) { BBR_UpdateBtlBw(bbr, rs, packetTracking->bytes_delivered, packetTracking->delivered); 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); } void BBR_UpdateTargetCwnd(BBR* bbr) { bbr->target_cwnd = BBR_Inflight(bbr, bbr->cwnd_gain); } void BBR_ModulateCwndForProbeRTT(BBR* bbr) { if (bbr->state == PROBE_RTT) bbr->cwnd = MIN(bbr->cwnd, BBRMinPipeCwnd); } void BBR_ModulateCwndForRecovery(BBR* bbr, prrtSequenceNumber_t packets_lost, prrtSequenceNumber_t packets_in_flight, prrtSequenceNumber_t packets_delivered) { if (packets_lost > 0) bbr->cwnd = MAX(bbr->cwnd - packets_lost, 1); if (bbr->packet_conservation) bbr->cwnd = MAX(bbr->cwnd, packets_in_flight + packets_delivered); } void BBR_SetCwnd(BBR* bbr, PrrtPacketTracking* packetTracking) { BBR_UpdateTargetCwnd(bbr); BBR_ModulateCwndForRecovery(bbr, packetTracking->packets_lost, packetTracking->packets_in_flight, packetTracking->packets_delivered); if (!bbr->packet_conservation) { if (bbr->filled_pipe) bbr->cwnd = MIN(bbr->cwnd + packetTracking->packets_delivered, bbr->target_cwnd); else if (bbr->cwnd < bbr->target_cwnd || packetTracking->delivered < InitialCwnd) bbr->cwnd = bbr->cwnd + packetTracking->packets_delivered; bbr->cwnd = MAX(bbr->cwnd, BBRMinPipeCwnd); } BBR_ModulateCwndForProbeRTT(bbr); debug(DEBUG_BBR, "New cwnd: %u, State: %u", bbr->cwnd, bbr->state); } void BBR_SetPacingRateWithGain(BBR* bbr, float pacing_gain) { uint32_t rate = (uint32_t) (pacing_gain * (float)bbr->bw); debug(DEBUG_BBR, "Current rate: %u, Pacing gain: %f, BtlBw: %u, Calc Rate: %u, Filled pipe: %u", bbr->pacing_rate, pacing_gain, bbr->bw, rate, bbr->filled_pipe); if (rate != 0 && (bbr->filled_pipe || rate > bbr->pacing_rate)) bbr->pacing_rate = rate; } void BBR_SetPacingRate(BBR* bbr) { BBR_SetPacingRateWithGain(bbr, bbr->pacing_gain); } void BBR_OnACK(BBR* bbr, PrrtChannelStateInformation* csi, PrrtRateSample* rs, PrrtPacketTracking* packetTracking) { BBR_UpdateModel(bbr, csi, rs, packetTracking); BBR_SetPacingRate(bbr); BBR_SetCwnd(bbr, packetTracking); } BBR* BBR_Init() { 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_stamp = PrrtClock_get_current_time_us(); bbr->probe_rtt_done_stamp = 0; bbr->probe_rtt_round_done = false; bbr->packet_conservation = false; bbr->prior_cwnd = 0; bbr->idle_restart = false; //Init round counting bbr->next_round_delivered = 0; bbr->round_start = false; bbr->round_count = 0; //Init full pipe bbr->filled_pipe = false; bbr->full_bw = 0; bbr->full_bw_count = 0; //Init pacing rate float nominal_bandwidth = InitialCwnd / (bbr->has_seen_rtt ? bbr->rtt : 1); bbr->pacing_rate = (uint32_t)(bbr->pacing_gain * nominal_bandwidth); BBR_EnterStartup(bbr); return bbr; error: PERROR("Failed to init BBR%s.", ""); return NULL; } void BBR_destroy(BBR* bbr) { WindowedFilter_destroy(bbr->btlBwFilter); free(bbr); } uint32_t BBR_getPacingRate(BBR* bbr) { return bbr->pacing_rate; } uint32_t BBR_getCwnd(BBR* bbr) { return bbr->cwnd; } uint32_t BBR_getBtlBw(BBR* bbr) { return bbr->bw; } uint32_t BBR_getRTProp(BBR* bbr) { return bbr->rtprop; } No newline at end of file
prrt/proto/bbr.h 0 → 100644 +83 −0 Original line number Diff line number Diff line #ifndef PRRT_BBR_H #define PRRT_BBR_H #include <stdint.h> #include "stdbool.h" #include "types/packet.h" #include "clock.h" #include "channelStateInformation.h" #include "types/packetTracking.h" #include "types/rateSample.h" #include "../util/windowedFilter.h" #define BtlBwFilterLen 10 #define RTpropFilterLen 10000000 //10s #define BBRHighGain ((2885 / 1000) + 1) #define ProbeRTTInterval 10 #define InitialCwnd 10 #define BBRGainCycleLen 8 #define BBRMinPipeCwnd 4 //#define BBRMinPipeCwnd 200 #define ProbeRTTDuration 200000 //200ms #define Inf 0 //TODO: What is Inf enum bbr_state { STARTUP, DRAIN, PROBE_BW, PROBE_RTT }; typedef struct bbr { uint32_t rtprop; prrtTimestamp_t rtprop_stamp; uint32_t probe_rtt_done_stamp; bool probe_rtt_round_done; bool packet_conservation; uint32_t prior_cwnd; uint32_t cwnd; uint32_t target_cwnd; bool idle_restart; enum bbr_state state; float pacing_gain; float cwnd_gain; bool filled_pipe; uint64_t full_bw; uint32_t full_bw_count; uint32_t pacing_rate; bool has_seen_rtt; uint32_t rtt; uint32_t next_round_delivered; bool round_start; uint32_t round_count; uint32_t next_rtt_delivered; uint32_t rtt_count; bool rtprop_expired; prrtTimestamp_t cycle_stamp; uint8_t cycle_index; float* pacing_gain_cycle; uint32_t send_quantum; uint32_t bw; WindowedFilter* btlBwFilter; } BBR; BBR* BBR_Init(); void BBR_OnACK(BBR* bbr, PrrtChannelStateInformation* csi, PrrtRateSample* rs, PrrtPacketTracking* recv_stats); void BBR_destroy(BBR* bbr); uint32_t BBR_getPacingRate(BBR* bbr); uint32_t BBR_getCwnd(BBR* bbr); uint32_t BBR_getBtlBw(BBR* bbr); uint32_t BBR_getRTProp(BBR* bbr); #endif //PRRT_BBR_H
prrt/proto/channelStateInformation.c +0 −10 Original line number Diff line number Diff line Loading @@ -56,16 +56,6 @@ void PrrtChannelStateInformation_update_delivery_rate(PrrtChannelStateInformatio pthread_mutex_lock(&csi->lock); prrtDeliveryRate_t rate = rateSample->delivery_rate; csi->deliveryRate = rate; if(csi->btlbw_rounds > csi->btlbw_filter_length_rtts) { csi->btlbw = 0; } csi->btlbw_rounds += 1; if(csi->btlbw < rate) { csi->btlbw = rate; csi->btlbw_rounds = 0; } pthread_mutex_unlock(&csi->lock); } void PrrtChannelStateInformation_update_app_limited(PrrtChannelStateInformation *csi, bool appLimited) { Loading
prrt/proto/channelStateInformation.h +1 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ #define PRRT_CHANNELSTATEINFORMATION_H #include <stdbool.h> #include "types/rateSample.h" #include "types/packet.h" typedef struct prrtChannelStateInformation { Loading