Fix NewHtbClass

- Prio and Quantum should be set equal to the input params
- Fix buffer and cbuffer due to incorrect hz
- Fix Xmittime which is also not equal the behavior of c library.
C library converts time to uint32 to drop precision before multiply
tick_in_usec. ref https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/tc/tc_core.c#n62
This commit is contained in:
Chun Chen
2020-08-24 11:26:04 +08:00
committed by Vish (Ishaya) Abrams
parent 337442361b
commit 339a215d65
4 changed files with 25 additions and 11 deletions

View File

@@ -43,12 +43,12 @@ func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass {
if buffer == 0 { if buffer == 0 {
buffer = uint32(float64(rate)/Hz() + float64(mtu)) buffer = uint32(float64(rate)/Hz() + float64(mtu))
} }
buffer = uint32(Xmittime(rate, buffer)) buffer = Xmittime(rate, buffer)
if cbuffer == 0 { if cbuffer == 0 {
cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) cbuffer = uint32(float64(ceil)/Hz() + float64(mtu))
} }
cbuffer = uint32(Xmittime(ceil, cbuffer)) cbuffer = Xmittime(ceil, cbuffer)
return &HtbClass{ return &HtbClass{
ClassAttrs: attrs, ClassAttrs: attrs,
@@ -56,9 +56,9 @@ func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass {
Ceil: ceil, Ceil: ceil,
Buffer: buffer, Buffer: buffer,
Cbuffer: cbuffer, Cbuffer: cbuffer,
Quantum: 10,
Level: 0, Level: 0,
Prio: 0, Prio: cattrs.Prio,
Quantum: cattrs.Quantum,
} }
} }

View File

@@ -97,6 +97,8 @@ func TestClassAddDel(t *testing.T) {
htbclassattrs := HtbClassAttrs{ htbclassattrs := HtbClassAttrs{
Rate: 1234000, Rate: 1234000,
Cbuffer: 1690, Cbuffer: 1690,
Prio: 2,
Quantum: 1000,
} }
class := NewHtbClass(classattrs, htbclassattrs) class := NewHtbClass(classattrs, htbclassattrs)
if err := ClassAdd(class); err != nil { if err := ClassAdd(class); err != nil {
@@ -126,6 +128,12 @@ func TestClassAddDel(t *testing.T) {
if htb.Cbuffer != class.Cbuffer { if htb.Cbuffer != class.Cbuffer {
t.Fatal("Cbuffer doesn't match") t.Fatal("Cbuffer doesn't match")
} }
if htb.Prio != class.Prio {
t.Fatal("Prio doesn't match")
}
if htb.Quantum != class.Quantum {
t.Fatal("Quantum doesn't match")
}
testClassStats(htb.ClassAttrs.Statistics, NewClassStatistics(), t) testClassStats(htb.ClassAttrs.Statistics, NewClassStatistics(), t)

View File

@@ -89,7 +89,7 @@ func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 { if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 {
return nil, errors.New("TBF: failed to calculate rate table") return nil, errors.New("TBF: failed to calculate rate table")
} }
police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer))) police.Burst = Xmittime(uint64(police.Rate.Rate), uint32(buffer))
} }
police.Mtu = fattrs.Mtu police.Mtu = fattrs.Mtu
if police.PeakRate.Rate != 0 { if police.PeakRate.Rate != 0 {
@@ -783,7 +783,7 @@ func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, lin
} }
for i := 0; i < 256; i++ { for i := 0; i < 256; i++ {
sz = AdjustSize(uint((i+1)<<uint32(cellLog)), uint(mpu), linklayer) sz = AdjustSize(uint((i+1)<<uint32(cellLog)), uint(mpu), linklayer)
rtab[i] = uint32(Xmittime(uint64(bps), uint32(sz))) rtab[i] = Xmittime(uint64(bps), uint32(sz))
} }
rate.CellAlign = -1 rate.CellAlign = -1
rate.CellLog = uint8(cellLog) rate.CellLog = uint8(cellLog)

View File

@@ -598,10 +598,10 @@ func initClock() {
return return
} }
parts := strings.Split(strings.TrimSpace(string(data)), " ") parts := strings.Split(strings.TrimSpace(string(data)), " ")
if len(parts) < 3 { if len(parts) < 4 {
return return
} }
var vals [3]uint64 var vals [4]uint64
for i := range vals { for i := range vals {
val, err := strconv.ParseUint(parts[i], 16, 32) val, err := strconv.ParseUint(parts[i], 16, 32)
if err != nil { if err != nil {
@@ -615,7 +615,12 @@ func initClock() {
} }
clockFactor = float64(vals[2]) / TIME_UNITS_PER_SEC clockFactor = float64(vals[2]) / TIME_UNITS_PER_SEC
tickInUsec = float64(vals[0]) / float64(vals[1]) * clockFactor tickInUsec = float64(vals[0]) / float64(vals[1]) * clockFactor
hz = float64(vals[0]) if vals[2] == 1000000 {
// ref https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/lib/utils.c#n963
hz = float64(vals[3])
} else {
hz = 100
}
} }
func TickInUsec() float64 { func TickInUsec() float64 {
@@ -663,6 +668,7 @@ func latency(rate uint64, limit, buffer uint32) float64 {
return TIME_UNITS_PER_SEC*(float64(limit)/float64(rate)) - float64(tick2Time(buffer)) return TIME_UNITS_PER_SEC*(float64(limit)/float64(rate)) - float64(tick2Time(buffer))
} }
func Xmittime(rate uint64, size uint32) float64 { func Xmittime(rate uint64, size uint32) uint32 {
return TickInUsec() * TIME_UNITS_PER_SEC * (float64(size) / float64(rate)) // https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/tc/tc_core.c#n62
return time2Tick(uint32(TIME_UNITS_PER_SEC * (float64(size) / float64(rate))))
} }