Add support for TCA_NETEM_RATE64 in Netem qdisc

- `Rate64` field added to the `Netem` struct in `qdisc.go`
- Implemented serialization and deserialization methods for `Rate64`
- Modify `TestClassAddDel` test to validate Rate64 changes
This commit is contained in:
Byoungchan Lee 2023-07-26 14:31:56 +09:00 committed by Alessandro Boch
parent 306ce7b5b2
commit 6765a4402e
4 changed files with 54 additions and 0 deletions

View File

@ -154,6 +154,7 @@ func TestClassAddDel(t *testing.T) {
ReorderProb: 23.4, ReorderProb: 23.4,
CorruptProb: 10.0, CorruptProb: 10.0,
CorruptCorr: 10, CorruptCorr: 10,
Rate64: 10 * 1024 * 1024,
} }
qdiscnetem := NewNetem(qattrs, nattrs) qdiscnetem := NewNetem(qattrs, nattrs)
if err := QdiscAdd(qdiscnetem); err != nil { if err := QdiscAdd(qdiscnetem); err != nil {
@ -195,6 +196,9 @@ func TestClassAddDel(t *testing.T) {
if netem.DuplicateCorr != qdiscnetem.DuplicateCorr { if netem.DuplicateCorr != qdiscnetem.DuplicateCorr {
t.Fatal("DuplicateCorr does not match") t.Fatal("DuplicateCorr does not match")
} }
if netem.Rate64 != qdiscnetem.Rate64 {
t.Fatalf("Rate64 does not match. Expected %d, got %d", netem.Rate64, qdiscnetem.Rate64)
}
// Deletion // Deletion
// automatically removes netem qdisc // automatically removes netem qdisc

View File

@ -105,6 +105,7 @@ const (
SizeofTcNetemCorr = 0x0c SizeofTcNetemCorr = 0x0c
SizeofTcNetemReorder = 0x08 SizeofTcNetemReorder = 0x08
SizeofTcNetemCorrupt = 0x08 SizeofTcNetemCorrupt = 0x08
SizeOfTcNetemRate = 0x10
SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c
SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14 SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14
SizeofTcHtbGlob = 0x14 SizeofTcHtbGlob = 0x14
@ -372,6 +373,26 @@ func (x *TcNetemCorrupt) Serialize() []byte {
return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:] return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:]
} }
// TcNetemRate is a struct that represents the rate of a netem qdisc
type TcNetemRate struct {
Rate uint32
PacketOverhead int32
CellSize uint32
CellOverhead int32
}
func (msg *TcNetemRate) Len() int {
return SizeofTcRateSpec
}
func DeserializeTcNetemRate(b []byte) *TcNetemRate {
return (*TcNetemRate)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0]))
}
func (msg *TcNetemRate) Serialize() []byte {
return (*(*[SizeOfTcNetemRate]byte)(unsafe.Pointer(msg)))[:]
}
// struct tc_tbf_qopt { // struct tc_tbf_qopt {
// struct tc_ratespec rate; // struct tc_ratespec rate;
// struct tc_ratespec peakrate; // struct tc_ratespec peakrate;

View File

@ -160,6 +160,7 @@ type NetemQdiscAttrs struct {
ReorderCorr float32 // in % ReorderCorr float32 // in %
CorruptProb float32 // in % CorruptProb float32 // in %
CorruptCorr float32 // in % CorruptCorr float32 // in %
Rate64 uint64
} }
func (q NetemQdiscAttrs) String() string { func (q NetemQdiscAttrs) String() string {
@ -184,6 +185,7 @@ type Netem struct {
ReorderCorr uint32 ReorderCorr uint32
CorruptProb uint32 CorruptProb uint32
CorruptCorr uint32 CorruptCorr uint32
Rate64 uint64
} }
func (netem *Netem) String() string { func (netem *Netem) String() string {

View File

@ -17,6 +17,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
var lossCorr, delayCorr, duplicateCorr uint32 var lossCorr, delayCorr, duplicateCorr uint32
var reorderProb, reorderCorr uint32 var reorderProb, reorderCorr uint32
var corruptProb, corruptCorr uint32 var corruptProb, corruptCorr uint32
var rate64 uint64
latency := nattrs.Latency latency := nattrs.Latency
loss := Percentage2u32(nattrs.Loss) loss := Percentage2u32(nattrs.Loss)
@ -57,6 +58,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
corruptProb = Percentage2u32(nattrs.CorruptProb) corruptProb = Percentage2u32(nattrs.CorruptProb)
corruptCorr = Percentage2u32(nattrs.CorruptCorr) corruptCorr = Percentage2u32(nattrs.CorruptCorr)
rate64 = nattrs.Rate64
return &Netem{ return &Netem{
QdiscAttrs: attrs, QdiscAttrs: attrs,
@ -73,6 +75,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
ReorderCorr: reorderCorr, ReorderCorr: reorderCorr,
CorruptProb: corruptProb, CorruptProb: corruptProb,
CorruptCorr: corruptCorr, CorruptCorr: corruptCorr,
Rate64: rate64,
} }
} }
@ -234,6 +237,17 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
if reorder.Probability > 0 { if reorder.Probability > 0 {
options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize()) options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize())
} }
// Rate
if qdisc.Rate64 > 0 {
rate := nl.TcNetemRate{}
if qdisc.Rate64 >= uint64(1<<32) {
options.AddRtAttr(nl.TCA_NETEM_RATE64, nl.Uint64Attr(qdisc.Rate64))
rate.Rate = ^uint32(0)
} else {
rate.Rate = uint32(qdisc.Rate64)
}
options.AddRtAttr(nl.TCA_NETEM_RATE, rate.Serialize())
}
case *Clsact: case *Clsact:
options = nil options = nil
case *Ingress: case *Ingress:
@ -601,6 +615,8 @@ func parseNetemData(qdisc Qdisc, value []byte) error {
if err != nil { if err != nil {
return err return err
} }
var rate *nl.TcNetemRate
var rate64 uint64
for _, datum := range data { for _, datum := range data {
switch datum.Attr.Type { switch datum.Attr.Type {
case nl.TCA_NETEM_CORR: case nl.TCA_NETEM_CORR:
@ -616,8 +632,19 @@ func parseNetemData(qdisc Qdisc, value []byte) error {
opt := nl.DeserializeTcNetemReorder(datum.Value) opt := nl.DeserializeTcNetemReorder(datum.Value)
netem.ReorderProb = opt.Probability netem.ReorderProb = opt.Probability
netem.ReorderCorr = opt.Correlation netem.ReorderCorr = opt.Correlation
case nl.TCA_NETEM_RATE:
rate = nl.DeserializeTcNetemRate(datum.Value)
case nl.TCA_NETEM_RATE64:
rate64 = native.Uint64(datum.Value)
} }
} }
if rate != nil {
netem.Rate64 = uint64(rate.Rate)
if rate64 > 0 {
netem.Rate64 = rate64
}
}
return nil return nil
} }