Repository: pion/interceptor
Pull request #145 (2022-07-16 15:37:59)

Add RFC8888 feedback to GCC
Enables GCC to work with RFC8888 instead of TWCC.

Only merge after pion/rtcp is released with RFC 8888 support. Remove `replace` from `go.mod` before merging.

mengelbart: I just realized this also depends on some functionality added by #143 
mengelbart: Closes #93 

Patch:
diff --git a/internal/cc/acknowledgment.go b/internal/cc/acknowledgment.go
index 580f81f..00ea058 100644
--- a/internal/cc/acknowledgment.go
+++ b/internal/cc/acknowledgment.go
@@ -3,21 +3,25 @@ package cc
 import (
 	"fmt"
 	"time"
+
+	"github.com/pion/rtcp"
 )
 
 // Acknowledgment holds information about a packet and if/when it has been
 // sent/received.
 type Acknowledgment struct {
-	TLCC      uint16
-	Size      int
-	Departure time.Time
-	Arrival   time.Time
-	RTT       time.Duration
+	SequenceNumber uint16 // Either RTP SequenceNumber or TWCC
+	SSRC           uint32
+	Size           int
+	Departure      time.Time
+	Arrival        time.Time
+	RTT            time.Duration
+	ECN            rtcp.ECN
 }
 
 func (a Acknowledgment) String() string {
 	s := "ACK:\n"
-	s += fmt.Sprintf("\tTLCC:\t%v\n", a.TLCC)
+	s += fmt.Sprintf("\tTLCC:\t%v\n", a.SequenceNumber)
 	s += fmt.Sprintf("\tSIZE:\t%v\n", a.Size)
 	s += fmt.Sprintf("\tDEPARTURE:\t%v\n", int64(float64(a.Departure.UnixNano())/1e+6))
 	s += fmt.Sprintf("\tARRIVAL:\t%v\n", int64(float64(a.Arrival.UnixNano())/1e+6))
diff --git a/internal/cc/feedback_adapter.go b/internal/cc/feedback_adapter.go
index 43c6d72..effe2af 100644
--- a/internal/cc/feedback_adapter.go
+++ b/internal/cc/feedback_adapter.go
@@ -7,6 +7,7 @@ import (
 	"time"
 
 	"github.com/pion/interceptor"
+	"github.com/pion/interceptor/internal/ntp"
 	"github.com/pion/rtcp"
 	"github.com/pion/rtp"
 )
@@ -16,9 +17,8 @@ import (
 const TwccExtensionAttributesKey = iota
 
 var (
-	errMissingTWCCExtensionID = errors.New("missing transport layer cc header extension id")
-	errMissingTWCCExtension   = errors.New("missing transport layer cc header extension")
-	errInvalidFeedback        = errors.New("invalid feedback")
+	errMissingTWCCExtension = errors.New("missing transport layer cc header extension")
+	errInvalidFeedback      = errors.New("invalid feedback")
 )
 
 // FeedbackAdapter converts incoming RTCP Packets (TWCC and RFC8888) into Acknowledgments.
@@ -33,15 +33,24 @@ func NewFeedbackAdapter() *FeedbackAdapter {
 	return &FeedbackAdapter{history: newFeedbackHistory(250)}
 }
 
-// OnSent records that and when an outgoing packet was sent for later mapping to
-// acknowledgments
-func (f *FeedbackAdapter) OnSent(ts time.Time, header *rtp.Header, size int, attributes interceptor.Attributes) error {
-	hdrExtensionID := attributes.Get(TwccExtensionAttributesKey)
-	id, ok := hdrExtensionID.(uint8)
-	if !ok || hdrExtensionID == 0 {
-		return errMissingTWCCExtensionID
-	}
-	sequenceNumber := header.GetExtension(id)
+func (f *FeedbackAdapter) onSentRFC8888(ts time.Time, header *rtp.Header, size int) error {
+	f.lock.Lock()
+	defer f.lock.Unlock()
+
+	f.history.add(Acknowledgment{
+		SequenceNumber: header.SequenceNumber,
+		SSRC:           header.SSRC,
+		Size:           size,
+		Departure:      ts,
+		Arrival:        time.Time{},
+		RTT:            0,
+		ECN:            0,
+	})
+	return nil
+}
+
+func (f *FeedbackAdapter) onSentTWCC(ts time.Time, extID uint8, header *rtp.Header, size int) error {
+	sequenceNumber := header.GetExtension(extID)
 	var tccExt rtp.TransportCCExtension
 	err := tccExt.Unmarshal(sequenceNumber)
 	if err != nil {
@@ -51,15 +60,29 @@ func (f *FeedbackAdapter) OnSent(ts time.Time, header *rtp.Header, size int, att
 	f.lock.Lock()
 	defer f.lock.Unlock()
 	f.history.add(Acknowledgment{
-		TLCC:      tccExt.TransportSequence,
-		Size:      header.MarshalSize() + size,
-		Departure: ts,
-		Arrival:   time.Time{},
-		RTT:       0,
+		SequenceNumber: tccExt.TransportSequence,
+		SSRC:           0,
+		Size:           header.MarshalSize() + size,
+		Departure:      ts,
+		Arrival:        time.Time{},
+		RTT:            0,
+		ECN:            0,
 	})
 	return nil
 }
 
+// OnSent records that and when an outgoing packet was sent for later mapping to
+// acknowledgments
+func (f *FeedbackAdapter) OnSent(ts time.Time, header *rtp.Header, size int, attributes interceptor.Attributes) error {
+	hdrExtensionID := attributes.Get(TwccExtensionAttributesKey)
+	id, ok := hdrExtensionID.(uint8)
+	if ok && hdrExtensionID != 0 {
+		return f.onSentTWCC(ts, id, header, size)
+	}
+
+	return f.onSentRFC8888(ts, header, size)
+}
+
 func (f *FeedbackAdapter) unpackRunLengthChunk(ts time.Time, start uint16, refTime time.Time, chunk *rtcp.RunLengthChunk, deltas []*rtcp.RecvDelta) (consumedDeltas int, nextRef time.Time, acks []Acknowledgment, err error) {
 	result := make([]Acknowledgment, chunk.RunLength)
 	deltaIndex := 0
@@ -67,7 +90,11 @@ func (f *FeedbackAdapter) unpackRunLengthChunk(ts time.Time, start uint16, refTi
 	end := start + chunk.RunLength
 	resultIndex := 0
 	for i := start; i != end; i++ {
-		if ack, ok := f.history.get(i); ok {
+		key := feedbackHistoryKey{
+			ssrc:           0,
+			sequenceNumber: i,
+		}
+		if ack, ok := f.history.get(key); ok {
 			if chunk.PacketStatusSymbol != rtcp.TypeTCCPacketNotReceived {
 				if len(deltas)-1 < deltaIndex {
 					return deltaIndex, refTime, result, errInvalidFeedback
@@ -89,7 +116,11 @@ func (f *FeedbackAdapter) unpackStatusVectorChunk(ts time.Time, start uint16, re
 	deltaIndex := 0
 	resultIndex := 0
 	for i, symbol := range chunk.SymbolList {
-		if ack, ok := f.history.get(start + uint16(i)); ok {
+		key := feedbackHistoryKey{
+			ssrc:           0,
+			sequenceNumber: start + uint16(i),
+		}
+		if ack, ok := f.history.get(key); ok {
 			if symbol != rtcp.TypeTCCPacketNotReceived {
 				if len(deltas)-1 < deltaIndex {
 					return deltaIndex, refTime, result, errInvalidFeedback
@@ -146,21 +177,55 @@ func (f *FeedbackAdapter) OnTransportCCFeedback(ts time.Time, feedback *rtcp.Tra
 	return result, nil
 }
 
+// OnRFC8888Feedback converts incoming Congestion Control Feedback RTCP packet
+// to Acknowledgments.
+func (f *FeedbackAdapter) OnRFC8888Feedback(ts time.Time, feedback *rtcp.CCFeedbackReport) []Acknowledgment {
+	f.lock.Lock()
+	defer f.lock.Unlock()
+
+	result := []Acknowledgment{}
+	referenceTime := ntp.ToTime(uint64(feedback.ReportTimestamp) << 16)
+	for _, rb := range feedback.ReportBlocks {
+		for i, mb := range rb.MetricBlocks {
+			sequenceNumber := rb.BeginSequence + uint16(i)
+			key := feedbackHistoryKey{
+				ssrc:           rb.MediaSSRC,
+				sequenceNumber: sequenceNumber,
+			}
+			if ack, ok := f.history.get(key); ok {
+				if mb.Received {
+					delta := time.Duration((float64(mb.ArrivalTimeOffset) / 1024.0) * float64(time.Second))
+					ack.Arrival = referenceTime.Add(-delta)
+					ack.RTT = ts.Sub(ack.Departure)
+					ack.ECN = mb.ECN
+				}
+				result = append(result, ack)
+			}
+		}
+	}
+	return result
+}
+
+type feedbackHistoryKey struct {
+	ssrc           uint32
+	sequenceNumber uint16
+}
+
 type feedbackHistory struct {
 	size      int
 	evictList *list.List
-	items     map[uint16]*list.Element
+	items     map[feedbackHistoryKey]*list.Element
 }
 
 func newFeedbackHistory(size int) *feedbackHistory {
 	return &feedbackHistory{
 		size:      size,
 		evictList: list.New(),
-		items:     make(map[uint16]*list.Element),
+		items:     make(map[feedbackHistoryKey]*list.Element),
 	}
 }
 
-func (f *feedbackHistory) get(key uint16) (Acknowledgment, bool) {
+func (f *feedbackHistory) get(key feedbackHistoryKey) (Acknowledgment, bool) {
 	ent, ok := f.items[key]
 	if ok {
 		if ack, ok := ent.Value.(Acknowledgment); ok {
@@ -171,15 +236,19 @@ func (f *feedbackHistory) get(key uint16) (Acknowledgment, bool) {
 }
 
 func (f *feedbackHistory) add(ack Acknowledgment) {
+	key := feedbackHistoryKey{
+		ssrc:           ack.SSRC,
+		sequenceNumber: ack.SequenceNumber,
+	}
 	// Check for existing
-	if ent, ok := f.items[ack.TLCC]; ok {
+	if ent, ok := f.items[key]; ok {
 		f.evictList.MoveToFront(ent)
 		ent.Value = ack
 		return
 	}
 	// Add new
 	ent := f.evictList.PushFront(ack)
-	f.items[ack.TLCC] = ent
+	f.items[key] = ent
 	// Evict if necessary
 	if f.evictList.Len() > f.size {
 		f.removeOldest()
@@ -190,7 +259,11 @@ func (f *feedbackHistory) removeOldest() {
 	if ent := f.evictList.Back(); ent != nil {
 		f.evictList.Remove(ent)
 		if ack, ok := ent.Value.(Acknowledgment); ok {
-			delete(f.items, ack.TLCC)
+			key := feedbackHistoryKey{
+				ssrc:           ack.SSRC,
+				sequenceNumber: ack.SequenceNumber,
+			}
+			delete(f.items, key)
 		}
 	}
 }
diff --git a/pkg/cc/interceptor.go b/pkg/cc/interceptor.go
index 2576cbb..e8bfde8 100644
--- a/pkg/cc/interceptor.go
+++ b/pkg/cc/interceptor.go
@@ -5,12 +5,9 @@ package cc
 import (
 	"github.com/pion/interceptor"
 	"github.com/pion/interceptor/pkg/gcc"
-	"github.com/pion/logging"
 	"github.com/pion/rtcp"
 )
 
-const transportCCURI = "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
-
 // Option can be used to set initial options on CC interceptors
 type Option func(*Interceptor) error
 
@@ -68,7 +65,6 @@ func (f *InterceptorFactory) NewInterceptor(id string) (interceptor.Interceptor,
 	}
 	i := &Interceptor{
 		NoOp:      interceptor.NoOp{},
-		log:       logging.NewDefaultLoggerFactory().NewLogger("cc_interceptor"),
 		estimator: bwe,
 		feedback:  make(chan []rtcp.Packet),
 		close:     make(chan struct{}),
@@ -89,7 +85,6 @@ func (f *InterceptorFactory) NewInterceptor(id string) (interceptor.Interceptor,
 // Interceptor implements Google Congestion Control
 type Interceptor struct {
 	interceptor.NoOp
-	log       logging.LeveledLogger
 	estimator BandwidthEstimator
 	feedback  chan []rtcp.Packet
 	close     chan struct{}
@@ -127,17 +122,6 @@ func (c *Interceptor) BindRTCPReader(reader interceptor.RTCPReader) interceptor.
 // BindLocalStream lets you modify any outgoing RTP packets. It is called once
 // for per LocalStream. The returned method will be called once per rtp packet.
 func (c *Interceptor) BindLocalStream(info *interceptor.StreamInfo, writer interceptor.RTPWriter) interceptor.RTPWriter {
-	var hdrExtID uint8
-	for _, e := range info.RTPHeaderExtensions {
-		if e.URI == transportCCURI {
-			hdrExtID = uint8(e.ID)
-			break
-		}
-	}
-	if hdrExtID == 0 { // Nothing to do if header extension ID is 0, because 0 is an invalid extension ID. Means stream is not using TWCC.
-		return writer
-	}
-
 	return c.estimator.AddStream(info, writer)
 }
 
diff --git a/pkg/gcc/rate_controller.go b/pkg/gcc/rate_controller.go
index ed75fda..4d0e175 100644
--- a/pkg/gcc/rate_controller.go
+++ b/pkg/gcc/rate_controller.go
@@ -4,8 +4,6 @@ import (
 	"math"
 	"sync"
 	"time"
-
-	"github.com/pion/logging"
 )
 
 const (
@@ -14,7 +12,6 @@ const (
 )
 
 type rateController struct {
-	log                  logging.LeveledLogger
 	now                  now
 	initialTargetBitrate int
 	minBitrate           int
@@ -52,7 +49,6 @@ func (a *exponentialMovingAverage) update(value float64) {
 
 func newRateController(now now, initialTargetBitrate, minBitrate, maxBitrate int, dsw func(DelayStats)) *rateController {
 	return &rateController{
-		log:                  logging.NewDefaultLoggerFactory().NewLogger("gcc_rate_controller"),
 		now:                  now,
 		initialTargetBitrate: initialTargetBitrate,
 		minBitrate:           minBitrate,
diff --git a/pkg/gcc/send_side_bwe.go b/pkg/gcc/send_side_bwe.go
index eb4caae..9138ba7 100644
--- a/pkg/gcc/send_side_bwe.go
+++ b/pkg/gcc/send_side_bwe.go
@@ -144,14 +144,19 @@ func (e *SendSideBWE) WriteRTCP(pkts []rtcp.Packet, attributes interceptor.Attri
 	}
 
 	for _, pkt := range pkts {
-		if fb, ok := pkt.(*rtcp.TransportLayerCC); ok {
-			acks, err := e.feedbackAdapter.OnTransportCCFeedback(time.Now(), fb)
+		var acks []cc.Acknowledgment
+		var err error
+		switch fb := pkt.(type) {
+		case *rtcp.TransportLayerCC:
+			acks, err = e.feedbackAdapter.OnTransportCCFeedback(time.Now(), fb)
 			if err != nil {
 				return err
 			}
-			e.lossController.updateLossEstimate(acks)
-			e.delayController.updateDelayEstimate(acks)
+		case *rtcp.CCFeedbackReport:
+			acks = e.feedbackAdapter.OnRFC8888Feedback(time.Now(), fb)
 		}
+		e.lossController.updateLossEstimate(acks)
+		e.delayController.updateDelayEstimate(acks)
 	}
 	return nil
 }


Test patch:
diff --git a/internal/cc/feedback_adapter_test.go b/internal/cc/feedback_adapter_test.go
index 7922caf..07b9cfe 100644
--- a/internal/cc/feedback_adapter_test.go
+++ b/internal/cc/feedback_adapter_test.go
@@ -56,46 +56,46 @@ func TestUnpackRunLengthChunk(t *testing.T) {
 			//nolint:dupl
 			acks: []Acknowledgment{
 				{
-					TLCC:      0,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 0,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      1,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 1,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      2,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 2,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      3,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 3,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      4,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 4,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      5,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 5,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 			},
 			n:       6,
@@ -120,46 +120,46 @@ func TestUnpackRunLengthChunk(t *testing.T) {
 			start: 65534,
 			acks: []Acknowledgment{
 				{
-					TLCC:      65534,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(250 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 65534,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(250 * time.Microsecond),
+					RTT:            0,
 				},
 				{
-					TLCC:      65535,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(500 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 65535,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(500 * time.Microsecond),
+					RTT:            0,
 				},
 				{
-					TLCC:      0,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(750 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 0,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(750 * time.Microsecond),
+					RTT:            0,
 				},
 				{
-					TLCC:      1,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(1000 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 1,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(1000 * time.Microsecond),
+					RTT:            0,
 				},
 				{
-					TLCC:      2,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(1250 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 2,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(1250 * time.Microsecond),
+					RTT:            0,
 				},
 				{
-					TLCC:      3,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(1500 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 3,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(1500 * time.Microsecond),
+					RTT:            0,
 				},
 			},
 			n:       6,
@@ -178,46 +178,46 @@ func TestUnpackRunLengthChunk(t *testing.T) {
 			//nolint:dupl
 			acks: []Acknowledgment{
 				{
-					TLCC:      65534,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 65534,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      65535,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 65535,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      0,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 0,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      1,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 1,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      2,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 2,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      3,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 3,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 			},
 			n:       0,
@@ -248,7 +248,7 @@ func TestUnpackRunLengthChunk(t *testing.T) {
 			assert.Equal(t, tc.refTime, refTime)
 
 			for i, a := range acks {
-				assert.Equal(t, tc.sentTLCC[i], a.TLCC)
+				assert.Equal(t, tc.sentTLCC[i], a.SequenceNumber)
 			}
 			assert.Equal(t, tc.acks, acks)
 		})
@@ -305,46 +305,46 @@ func TestUnpackStatusVectorChunk(t *testing.T) {
 			//nolint:dupl
 			acks: []Acknowledgment{
 				{
-					TLCC:      0,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 0,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      1,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 1,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      2,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 2,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      3,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 3,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      4,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 4,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      5,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 5,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 			},
 			n:       6,
@@ -375,46 +375,46 @@ func TestUnpackStatusVectorChunk(t *testing.T) {
 			start: 65534,
 			acks: []Acknowledgment{
 				{
-					TLCC:      65534,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(250 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 65534,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(250 * time.Microsecond),
+					RTT:            0,
 				},
 				{
-					TLCC:      65535,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(500 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 65535,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(500 * time.Microsecond),
+					RTT:            0,
 				},
 				{
-					TLCC:      0,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(750 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 0,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(750 * time.Microsecond),
+					RTT:            0,
 				},
 				{
-					TLCC:      1,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(1000 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 1,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(1000 * time.Microsecond),
+					RTT:            0,
 				},
 				{
-					TLCC:      2,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 2,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				},
 				{
-					TLCC:      3,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{}.Add(1250 * time.Microsecond),
-					RTT:       0,
+					SequenceNumber: 3,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{}.Add(1250 * time.Microsecond),
+					RTT:            0,
 				},
 			},
 			n:       5,
@@ -445,7 +445,7 @@ func TestUnpackStatusVectorChunk(t *testing.T) {
 			assert.Equal(t, tc.refTime, refTime)
 
 			for i, a := range acks {
-				assert.Equal(t, tc.sentTLCC[i], a.TLCC)
+				assert.Equal(t, tc.sentTLCC[i], a.SequenceNumber)
 			}
 			assert.Equal(t, tc.acks, acks)
 		})
@@ -559,55 +559,55 @@ func TestFeedbackAdapterTWCC(t *testing.T) {
 		assert.Len(t, results, 22)
 
 		assert.Contains(t, results, Acknowledgment{
-			TLCC:      0,
-			Size:      headers[0].MarshalSize() + 1200,
-			Departure: t0,
-			Arrival:   t0.Add(4 * time.Microsecond),
-			RTT:       0,
+			SequenceNumber: 0,
+			Size:           headers[0].MarshalSize() + 1200,
+			Departure:      t0,
+			Arrival:        t0.Add(4 * time.Microsecond),
+			RTT:            0,
 		})
 
 		assert.Contains(t, results, Acknowledgment{
-			TLCC:      1,
-			Size:      headers[1].MarshalSize() + 1200,
-			Departure: t0,
-			Arrival:   t0.Add(104 * time.Microsecond),
-			RTT:       0,
+			SequenceNumber: 1,
+			Size:           headers[1].MarshalSize() + 1200,
+			Departure:      t0,
+			Arrival:        t0.Add(104 * time.Microsecond),
+			RTT:            0,
 		})
 
 		for i := uint16(2); i < 7; i++ {
 			assert.Contains(t, results, Acknowledgment{
-				TLCC:      i,
-				Size:      headers[i].MarshalSize() + 1200,
-				Departure: t0,
-				Arrival:   time.Time{},
-				RTT:       0,
+				SequenceNumber: i,
+				Size:           headers[i].MarshalSize() + 1200,
+				Departure:      t0,
+				Arrival:        time.Time{},
+				RTT:            0,
 			})
 		}
 
 		assert.Contains(t, results, Acknowledgment{
-			TLCC:      7,
-			Size:      headers[7].MarshalSize() + 1200,
-			Departure: t0,
-			Arrival:   t0.Add(116 * time.Microsecond),
-			RTT:       0,
+			SequenceNumber: 7,
+			Size:           headers[7].MarshalSize() + 1200,
+			Departure:      t0,
+			Arrival:        t0.Add(116 * time.Microsecond),
+			RTT:            0,
 		})
 
 		for i := uint16(8); i < 21; i++ {
 			assert.Contains(t, results, Acknowledgment{
-				TLCC:      i,
-				Size:      headers[i].MarshalSize() + 1200,
-				Departure: t0,
-				Arrival:   time.Time{},
-				RTT:       0,
+				SequenceNumber: i,
+				Size:           headers[i].MarshalSize() + 1200,
+				Departure:      t0,
+				Arrival:        time.Time{},
+				RTT:            0,
 			})
 		}
 
 		assert.Contains(t, results, Acknowledgment{
-			TLCC:      21,
-			Size:      headers[21].MarshalSize() + 1200,
-			Departure: t0,
-			Arrival:   t0.Add(120 * time.Microsecond),
-			RTT:       0,
+			SequenceNumber: 21,
+			Size:           headers[21].MarshalSize() + 1200,
+			Departure:      t0,
+			Arrival:        t0.Add(120 * time.Microsecond),
+			RTT:            0,
 		})
 	})
 
@@ -697,18 +697,18 @@ func TestFeedbackAdapterTWCC(t *testing.T) {
 		assert.NotEmpty(t, results)
 		assert.Len(t, results, 7)
 		assert.Contains(t, results, Acknowledgment{
-			TLCC:      65535,
-			Size:      pkt65535.Header.MarshalSize() + 1200,
-			Departure: t0,
-			Arrival:   t0.Add(4 * time.Microsecond),
-			RTT:       0,
+			SequenceNumber: 65535,
+			Size:           pkt65535.Header.MarshalSize() + 1200,
+			Departure:      t0,
+			Arrival:        t0.Add(4 * time.Microsecond),
+			RTT:            0,
 		})
 		assert.Contains(t, results, Acknowledgment{
-			TLCC:      0,
-			Size:      pkt0.Header.MarshalSize() + 1200,
-			Departure: t0,
-			Arrival:   t0.Add(8 * time.Microsecond),
-			RTT:       0,
+			SequenceNumber: 0,
+			Size:           pkt0.Header.MarshalSize() + 1200,
+			Departure:      t0,
+			Arrival:        t0.Add(8 * time.Microsecond),
+			RTT:            0,
 		})
 	})
 
@@ -765,20 +765,20 @@ func TestFeedbackAdapterTWCC(t *testing.T) {
 		assert.Len(t, results, 7)
 		for i := uint16(0); i < 3; i++ {
 			assert.Contains(t, results, Acknowledgment{
-				TLCC:      i,
-				Size:      headers[i].MarshalSize() + 1200,
-				Departure: t0,
-				Arrival:   t0.Add(time.Duration((i + 1)) * 4 * time.Microsecond),
-				RTT:       0,
+				SequenceNumber: i,
+				Size:           headers[i].MarshalSize() + 1200,
+				Departure:      t0,
+				Arrival:        t0.Add(time.Duration((i + 1)) * 4 * time.Microsecond),
+				RTT:            0,
 			})
 		}
 		for i := uint16(3); i < 7; i++ {
 			assert.Contains(t, results, Acknowledgment{
-				TLCC:      i,
-				Size:      headers[i].MarshalSize() + 1200,
-				Departure: t0,
-				Arrival:   time.Time{},
-				RTT:       0,
+				SequenceNumber: i,
+				Size:           headers[i].MarshalSize() + 1200,
+				Departure:      t0,
+				Arrival:        time.Time{},
+				RTT:            0,
 			})
 		}
 	})
diff --git a/pkg/gcc/arrival_group_test.go b/pkg/gcc/arrival_group_test.go
index 79ebd46..ac75bd2 100644
--- a/pkg/gcc/arrival_group_test.go
+++ b/pkg/gcc/arrival_group_test.go
@@ -27,19 +27,19 @@ func TestArrivalGroup(t *testing.T) {
 		{
 			name: "createsArrivalGroupContainingSingleACK",
 			acks: []cc.Acknowledgment{{
-				TLCC:      0,
-				Size:      0,
-				Departure: time.Time{},
-				Arrival:   time.Time{},
-				RTT:       0,
+				SequenceNumber: 0,
+				Size:           0,
+				Departure:      time.Time{},
+				Arrival:        time.Time{},
+				RTT:            0,
 			}},
 			expected: arrivalGroup{
 				packets: []cc.Acknowledgment{{
-					TLCC:      0,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 0,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				}},
 				arrival:   time.Time{},
 				departure: time.Time{},
@@ -49,31 +49,31 @@ func TestArrivalGroup(t *testing.T) {
 		{
 			name: "setsTimesToLastACK",
 			acks: []cc.Acknowledgment{{
-				TLCC:      0,
-				Size:      0,
-				Departure: time.Time{},
-				Arrival:   time.Time{},
-				RTT:       0,
+				SequenceNumber: 0,
+				Size:           0,
+				Departure:      time.Time{},
+				Arrival:        time.Time{},
+				RTT:            0,
 			}, {
-				TLCC:      0,
-				Size:      0,
-				Departure: time.Time{}.Add(time.Second),
-				Arrival:   time.Time{}.Add(time.Second),
-				RTT:       time.Hour,
+				SequenceNumber: 0,
+				Size:           0,
+				Departure:      time.Time{}.Add(time.Second),
+				Arrival:        time.Time{}.Add(time.Second),
+				RTT:            time.Hour,
 			}},
 			expected: arrivalGroup{
 				packets: []cc.Acknowledgment{{
-					TLCC:      0,
-					Size:      0,
-					Departure: time.Time{},
-					Arrival:   time.Time{},
-					RTT:       0,
+					SequenceNumber: 0,
+					Size:           0,
+					Departure:      time.Time{},
+					Arrival:        time.Time{},
+					RTT:            0,
 				}, {
-					TLCC:      0,
-					Size:      0,
-					Departure: time.Time{}.Add(time.Second),
-					Arrival:   time.Time{}.Add(time.Second),
-					RTT:       time.Hour,
+					SequenceNumber: 0,
+					Size:           0,
+					Departure:      time.Time{}.Add(time.Second),
+					Arrival:        time.Time{}.Add(time.Second),
+					RTT:            time.Hour,
 				}},
 				arrival:   time.Time{}.Add(time.Second),
 				departure: time.Time{}.Add(time.Second),
diff --git a/pkg/gcc/rate_calculator_test.go b/pkg/gcc/rate_calculator_test.go
index 190a709..9bd9a5e 100644
--- a/pkg/gcc/rate_calculator_test.go
+++ b/pkg/gcc/rate_calculator_test.go
@@ -23,39 +23,39 @@ func TestRateCalculator(t *testing.T) {
 		{
 			name: "ignoresZeroArrivalTimes",
 			acks: []cc.Acknowledgment{{
-				TLCC:      0,
-				Size:      0,
-				Departure: time.Time{},
-				Arrival:   time.Time{},
-				RTT:       0,
+				SequenceNumber: 0,
+				Size:           0,
+				Departure:      time.Time{},
+				Arrival:        time.Time{},
+				RTT:            0,
 			}},
 			expected: []int{},
 		},
 		{
 			name: "singleAckCreatesRate",
 			acks: []cc.Acknowledgment{{
-				TLCC:      0,
-				Size:      1000,
-				Departure: time.Time{},
-				Arrival:   t0,
-				RTT:       0,
+				SequenceNumber: 0,
+				Size:           1000,
+				Departure:      time.Time{},
+				Arrival:        t0,
+				RTT:            0,
 			}},
 			expected: []int{8000},
 		},
 		{
 			name: "twoAcksCalculateCorrectRates",
 			acks: []cc.Acknowledgment{{
-				TLCC:      0,
-				Size:      125,
-				Departure: time.Time{},
-				Arrival:   t0,
-				RTT:       0,
+				SequenceNumber: 0,
+				Size:           125,
+				Departure:      time.Time{},
+				Arrival:        t0,
+				RTT:            0,
 			}, {
-				TLCC:      0,
-				Size:      125,
-				Departure: time.Time{},
-				Arrival:   t0.Add(100 * time.Millisecond),
-				RTT:       0,
+				SequenceNumber: 0,
+				Size:           125,
+				Departure:      time.Time{},
+				Arrival:        t0.Add(100 * time.Millisecond),
+				RTT:            0,
 			}},
 			expected: []int{1000, 20_000},
 		},