Skip to content

Commit

Permalink
Add congestion control parameters to config
Browse files Browse the repository at this point in the history
The loss-based congestion control get poor
performance under high bandwidth, high rtt
and packet loss case since the congestion
window becomes 1 mtu and increase slowly
after retransmit timeout. And fast recovery
retransmit cause exit slowly in consecutive
packet loss. This change add paramters to
the config then the user can set them to get
higher throughput in such cases.
  • Loading branch information
cnderrauber committed Nov 18, 2024
1 parent 943ac50 commit a62d309
Showing 1 changed file with 34 additions and 7 deletions.
41 changes: 34 additions & 7 deletions association.go
Original file line number Diff line number Diff line change
@@ -212,6 +212,9 @@ type Association struct {
partialBytesAcked uint32
inFastRecovery bool
fastRecoverExitPoint uint32
minCwnd uint32 // Minimum congestion window
fastRtxWnd uint32 // Send window for fast retransmit
cwndCAStep uint32 // Step of congestion window increase at Congestion Avoidance

// RTX & Ack timer
rtoMgr *rtoManager
@@ -261,8 +264,16 @@ type Config struct {
MaxMessageSize uint32
EnableZeroChecksum bool
LoggerFactory logging.LoggerFactory

// congestion control configuration
// RTOMax is the maximum retransmission timeout in milliseconds
RTOMax float64
// Minimum congestion window
MinCwnd uint32
// Send window for fast retransmit
FastRtxWnd uint32
// Step of congestion window increase at Congestion Avoidance
CwndCAStep uint32
}

// Server accepts a SCTP stream over a conn
@@ -325,6 +336,9 @@ func createAssociation(config Config) *Association {
netConn: config.NetConn,
maxReceiveBufferSize: maxReceiveBufferSize,
maxMessageSize: maxMessageSize,
minCwnd: config.MinCwnd,
fastRtxWnd: config.FastRtxWnd,
cwndCAStep: config.CwndCAStep,

// These two max values have us not need to follow
// 5.1.1 where this peer may be incapable of supporting
@@ -803,9 +817,13 @@ func (a *Association) gatherOutboundFastRetransmissionPackets(rawPackets [][]byt
if a.willRetransmitFast {
a.willRetransmitFast = false

toFastRetrans := []chunk{}
toFastRetrans := []*chunkPayloadData{}
fastRetransSize := commonHeaderSize

fastRetransWnd := a.MTU()
if fastRetransWnd < a.fastRtxWnd {
fastRetransWnd = a.fastRtxWnd
}

Check warning on line 826 in association.go

Codecov / codecov/patch

association.go#L825-L826

Added lines #L825 - L826 were not covered by tests
for i := 0; ; i++ {
c, ok := a.inflightQueue.get(a.cumulativeTSNAckPoint + uint32(i) + 1)
if !ok {
@@ -831,7 +849,7 @@ func (a *Association) gatherOutboundFastRetransmissionPackets(rawPackets [][]byt
// packet.

dataChunkSize := dataChunkHeaderSize + uint32(len(c.userData))
if a.MTU() < fastRetransSize+dataChunkSize {
if fastRetransWnd < fastRetransSize+dataChunkSize {
break
}

@@ -845,10 +863,12 @@ func (a *Association) gatherOutboundFastRetransmissionPackets(rawPackets [][]byt
}

if len(toFastRetrans) > 0 {
raw, err := a.marshalPacket(a.createPacket(toFastRetrans))
if err != nil {
a.log.Warnf("[%s] failed to serialize a DATA packet to be fast-retransmitted", a.name)
} else {
for _, p := range a.bundleDataChunksIntoPackets(toFastRetrans) {
raw, err := a.marshalPacket(p)
if err != nil {
a.log.Warnf("[%s] failed to serialize a DATA packet to be fast-retransmitted", a.name)
continue

Check warning on line 870 in association.go

Codecov / codecov/patch

association.go#L869-L870

Added lines #L869 - L870 were not covered by tests
}
rawPackets = append(rawPackets, raw)
}
}
@@ -1115,6 +1135,9 @@ func (a *Association) CWND() uint32 {
}

func (a *Association) setCWND(cwnd uint32) {
if cwnd < a.minCwnd {
cwnd = a.minCwnd
}

Check warning on line 1140 in association.go

Codecov / codecov/patch

association.go#L1139-L1140

Added lines #L1139 - L1140 were not covered by tests
atomic.StoreUint32(&a.cwnd, cwnd)
}

@@ -1720,7 +1743,11 @@ func (a *Association) onCumulativeTSNAckPointAdvanced(totalBytesAcked int) {
// reset partial_bytes_acked to (partial_bytes_acked - cwnd).
if a.partialBytesAcked >= a.CWND() && a.pendingQueue.size() > 0 {
a.partialBytesAcked -= a.CWND()
a.setCWND(a.CWND() + a.MTU())
step := a.MTU()
if step < a.cwndCAStep {
step = a.cwndCAStep
}

Check warning on line 1749 in association.go

Codecov / codecov/patch

association.go#L1748-L1749

Added lines #L1748 - L1749 were not covered by tests
a.setCWND(a.CWND() + step)
a.log.Tracef("[%s] updated cwnd=%d ssthresh=%d acked=%d (CA)",
a.name, a.CWND(), a.ssthresh, totalBytesAcked)
}

0 comments on commit a62d309

Please sign in to comment.