Skip to content

Commit

Permalink
Add SACKs sent and packets stats
Browse files Browse the repository at this point in the history
  • Loading branch information
edaniels committed Mar 2, 2024
1 parent 45704b2 commit 19e73c4
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 23 deletions.
21 changes: 14 additions & 7 deletions association.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,11 @@ func (a *Association) Close() error {
<-a.readLoopCloseCh

a.log.Debugf("[%s] association closed", a.name)
a.log.Debugf("[%s] stats nPackets (in) : %d", a.name, a.stats.getNumPacketsReceived())
a.log.Debugf("[%s] stats nPackets (out) : %d", a.name, a.stats.getNumPacketsSent())
a.log.Debugf("[%s] stats nDATAs (in) : %d", a.name, a.stats.getNumDATAs())
a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKs())
a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKsReceived())
a.log.Debugf("[%s] stats nSACKs (out) : %d\n", a.name, a.stats.getNumSACKsSent())
a.log.Debugf("[%s] stats nT3Timeouts : %d", a.name, a.stats.getNumT3Timeouts())
a.log.Debugf("[%s] stats nAckTimeouts: %d", a.name, a.stats.getNumAckTimeouts())
a.log.Debugf("[%s] stats nFastRetrans: %d", a.name, a.stats.getNumFastRetrans())
Expand Down Expand Up @@ -547,7 +550,7 @@ func (a *Association) readLoop() {

a.log.Debugf("[%s] association closed", a.name)
a.log.Debugf("[%s] stats nDATAs (in) : %d", a.name, a.stats.getNumDATAs())
a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKs())
a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKsReceived())
a.log.Debugf("[%s] stats nT3Timeouts : %d", a.name, a.stats.getNumT3Timeouts())
a.log.Debugf("[%s] stats nAckTimeouts: %d", a.name, a.stats.getNumAckTimeouts())
a.log.Debugf("[%s] stats nFastRetrans: %d", a.name, a.stats.getNumFastRetrans())
Expand Down Expand Up @@ -596,6 +599,7 @@ loop:
break loop
}
atomic.AddUint64(&a.bytesSent, uint64(len(raw)))
a.stats.incPacketsSent()
}

if !ok {
Expand Down Expand Up @@ -670,15 +674,15 @@ func (a *Association) handleInbound(raw []byte) error {
return nil
}

a.handleChunkStart()
a.handleChunksStart()

for _, c := range p.chunks {
if err := a.handleChunk(p, c); err != nil {
return err
}
}

a.handleChunkEnd()
a.handleChunksEnd()

return nil
}
Expand Down Expand Up @@ -825,6 +829,7 @@ func (a *Association) gatherOutboundSackPackets(rawPackets [][]byte) [][]byte {
if a.ackState == ackStateImmediate {
a.ackState = ackStateIdle
sack := a.createSelectiveAckChunk()
a.stats.incSACKsSent()
a.log.Debugf("[%s] sending SACK: %s", a.name, sack)
raw, err := a.marshalPacket(a.createPacket([]chunk{sack}))
if err != nil {
Expand Down Expand Up @@ -1718,7 +1723,7 @@ func (a *Association) handleSack(d *chunkSelectiveAck) error {
return nil
}

a.stats.incSACKs()
a.stats.incSACKsReceived()

if sna32GT(a.cumulativeTSNAckPoint, d.cumulativeTSNAck) {
// RFC 4960 sec 6.2.1. Processing a Received SACK
Expand Down Expand Up @@ -2377,15 +2382,17 @@ func pack(p *packet) []*packet {
return []*packet{p}
}

func (a *Association) handleChunkStart() {
func (a *Association) handleChunksStart() {
a.lock.Lock()
defer a.lock.Unlock()

a.stats.incPacketsReceived()

a.delayedAckTriggered = false
a.immediateAckTriggered = false
}

func (a *Association) handleChunkEnd() {
func (a *Association) handleChunksEnd() {
a.lock.Lock()
defer a.lock.Unlock()

Expand Down
50 changes: 40 additions & 10 deletions association_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,30 @@ import (
)

type associationStats struct {
nDATAs uint64
nSACKs uint64
nT3Timeouts uint64
nAckTimeouts uint64
nFastRetrans uint64
nPacketsReceived uint64
nPacketsSent uint64
nDATAs uint64
nSACKsReceived uint64
nSACKsSent uint64
nT3Timeouts uint64
nAckTimeouts uint64
nFastRetrans uint64
}

func (s *associationStats) incPacketsReceived() {
atomic.AddUint64(&s.nPacketsReceived, 1)
}

func (s *associationStats) getNumPacketsReceived() uint64 {
return atomic.LoadUint64(&s.nPacketsReceived)
}

func (s *associationStats) incPacketsSent() {
atomic.AddUint64(&s.nPacketsSent, 1)
}

func (s *associationStats) getNumPacketsSent() uint64 {
return atomic.LoadUint64(&s.nPacketsSent)
}

func (s *associationStats) incDATAs() {
Expand All @@ -23,12 +42,20 @@ func (s *associationStats) getNumDATAs() uint64 {
return atomic.LoadUint64(&s.nDATAs)
}

func (s *associationStats) incSACKs() {
atomic.AddUint64(&s.nSACKs, 1)
func (s *associationStats) incSACKsReceived() {
atomic.AddUint64(&s.nSACKsReceived, 1)
}

func (s *associationStats) getNumSACKsReceived() uint64 {
return atomic.LoadUint64(&s.nSACKsReceived)
}

func (s *associationStats) incSACKsSent() {
atomic.AddUint64(&s.nSACKsSent, 1)
}

func (s *associationStats) getNumSACKs() uint64 {
return atomic.LoadUint64(&s.nSACKs)
func (s *associationStats) getNumSACKsSent() uint64 {
return atomic.LoadUint64(&s.nSACKsSent)
}

func (s *associationStats) incT3Timeouts() {
Expand Down Expand Up @@ -56,8 +83,11 @@ func (s *associationStats) getNumFastRetrans() uint64 {
}

func (s *associationStats) reset() {
atomic.StoreUint64(&s.nPacketsReceived, 0)
atomic.StoreUint64(&s.nPacketsSent, 0)
atomic.StoreUint64(&s.nDATAs, 0)
atomic.StoreUint64(&s.nSACKs, 0)
atomic.StoreUint64(&s.nSACKsReceived, 0)
atomic.StoreUint64(&s.nSACKsSent, 0)
atomic.StoreUint64(&s.nT3Timeouts, 0)
atomic.StoreUint64(&s.nAckTimeouts, 0)
atomic.StoreUint64(&s.nFastRetrans, 0)
Expand Down
12 changes: 6 additions & 6 deletions association_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1823,7 +1823,7 @@ func TestAssocCongestionControl(t *testing.T) {
assert.False(t, inFastRecovery, "should not be in fast-recovery")

t.Logf("nDATAs : %d\n", a1.stats.getNumDATAs())
t.Logf("nSACKs : %d\n", a0.stats.getNumSACKs())
t.Logf("nSACKs : %d\n", a0.stats.getNumSACKsReceived())
t.Logf("nAckTimeouts: %d\n", a1.stats.getNumAckTimeouts())
t.Logf("nFastRetrans: %d\n", a0.stats.getNumFastRetrans())

Expand Down Expand Up @@ -1907,11 +1907,11 @@ func TestAssocCongestionControl(t *testing.T) {
assert.Equal(t, 0, s1.getNumBytesInReassemblyQueue(), "reassembly queue should be empty")

t.Logf("nDATAs : %d\n", a1.stats.getNumDATAs())
t.Logf("nSACKs : %d\n", a0.stats.getNumSACKs())
t.Logf("nSACKs : %d\n", a0.stats.getNumSACKsReceived())
t.Logf("nT3Timeouts : %d\n", a0.stats.getNumT3Timeouts())

assert.Equal(t, uint64(nPacketsToSend), a1.stats.getNumDATAs(), "packet count mismatch")
assert.True(t, a0.stats.getNumSACKs() <= nPacketsToSend/2, "too many sacks")
assert.True(t, a0.stats.getNumSACKsReceived() <= nPacketsToSend/2, "too many sacks")
assert.Equal(t, uint64(0), a0.stats.getNumT3Timeouts(), "should be no retransmit")

closeAssociationPair(br, a0, a1)
Expand Down Expand Up @@ -2002,7 +2002,7 @@ func TestAssocCongestionControl(t *testing.T) {
assert.Equal(t, 0, s1.getNumBytesInReassemblyQueue(), "reassembly queue should be empty")

t.Logf("nDATAs : %d\n", a1.stats.getNumDATAs())
t.Logf("nSACKs : %d\n", a0.stats.getNumSACKs())
t.Logf("nSACKs : %d\n", a0.stats.getNumSACKsReceived())
t.Logf("nAckTimeouts: %d\n", a1.stats.getNumAckTimeouts())

closeAssociationPair(br, a0, a1)
Expand Down Expand Up @@ -2081,11 +2081,11 @@ func TestAssocDelayedAck(t *testing.T) {
assert.Equal(t, 0, s1.getNumBytesInReassemblyQueue(), "reassembly queue should be empty")

t.Logf("nDATAs : %d\n", a1.stats.getNumDATAs())
t.Logf("nSACKs : %d\n", a0.stats.getNumSACKs())
t.Logf("nSACKs : %d\n", a0.stats.getNumSACKsReceived())
t.Logf("nAckTimeouts: %d\n", a1.stats.getNumAckTimeouts())

assert.Equal(t, uint64(1), a1.stats.getNumDATAs(), "DATA chunk count mismatch")
assert.Equal(t, a0.stats.getNumSACKs(), a1.stats.getNumDATAs(), "sack count should be equal to the number of data chunks")
assert.Equal(t, a0.stats.getNumSACKsReceived(), a1.stats.getNumDATAs(), "sack count should be equal to the number of data chunks")
assert.Equal(t, uint64(1), a1.stats.getNumAckTimeouts(), "ackTimeout count mismatch")
assert.Equal(t, uint64(0), a0.stats.getNumT3Timeouts(), "should be no retransmit")

Expand Down

0 comments on commit 19e73c4

Please sign in to comment.