diff --git a/class.go b/class.go index 35bdb33..06dac6a 100644 --- a/class.go +++ b/class.go @@ -2,6 +2,8 @@ package netlink import ( "fmt" + + "github.com/vishvananda/netlink/nl" ) type Class interface { @@ -41,21 +43,29 @@ func (q HtbClassAttrs) String() string { // Htb class type HtbClass struct { ClassAttrs - Rate uint64 - Ceil uint64 + Rate nl.TcRateSpec + Ceil nl.TcRateSpec Buffer uint32 Cbuffer uint32 Quantum uint32 Level uint32 Prio uint32 + Rtab [256]uint32 + Ctab [256]uint32 } func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { + var rtab [256]uint32 + var ctab [256]uint32 + cell_log := -1 + ccell_log := -1 + linklayer := nl.LINKLAYER_ETHERNET mtu := 1600 rate := cattrs.Rate / 8 ceil := cattrs.Ceil / 8 buffer := cattrs.Buffer cbuffer := cattrs.Cbuffer + if ceil == 0 { ceil = rate } @@ -70,15 +80,27 @@ func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { } cbuffer = uint32(Xmittime(ceil, cbuffer)) + tcrate := nl.TcRateSpec{Rate: uint32(rate)} + if CalcRtable(&tcrate, rtab, cell_log, uint32(mtu), linklayer) < 0 { + return nil + } + + tcceil := nl.TcRateSpec{Rate: uint32(ceil)} + if CalcRtable(&tcceil, ctab, ccell_log, uint32(mtu), linklayer) < 0 { + return nil + } + return &HtbClass{ ClassAttrs: attrs, - Rate: rate, - Ceil: ceil, + Rate: tcrate, + Ceil: tcceil, Buffer: buffer, Cbuffer: cbuffer, Quantum: 10, Level: 0, Prio: 0, + Rtab: rtab, + Ctab: ctab, } } diff --git a/class_linux.go b/class_linux.go index 84828da..7a5c8a3 100644 --- a/class_linux.go +++ b/class_linux.go @@ -65,8 +65,8 @@ func classPayload(req *nl.NetlinkRequest, class Class) error { options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) if htb, ok := class.(*HtbClass); ok { opt := nl.TcHtbCopt{} - opt.Rate.Rate = uint32(htb.Rate) - opt.Ceil.Rate = uint32(htb.Ceil) + opt.Rate = htb.Rate + opt.Ceil = htb.Ceil opt.Buffer = htb.Buffer opt.Cbuffer = htb.Cbuffer opt.Quantum = htb.Quantum @@ -74,6 +74,8 @@ func classPayload(req *nl.NetlinkRequest, class Class) error { opt.Prio = htb.Prio // TODO: Handle Debug properly. For now default to 0 nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize()) + nl.NewRtAttrChild(options, nl.TCA_HTB_RTAB, SerializeRtab(htb.Rtab)) + nl.NewRtAttrChild(options, nl.TCA_HTB_CTAB, SerializeRtab(htb.Ctab)) } req.AddData(options) return nil @@ -155,8 +157,8 @@ func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, erro switch datum.Attr.Type { case nl.TCA_HTB_PARMS: opt := nl.DeserializeTcHtbCopt(datum.Value) - htb.Rate = uint64(opt.Rate.Rate) - htb.Ceil = uint64(opt.Ceil.Rate) + htb.Rate = opt.Rate + htb.Ceil = opt.Ceil htb.Buffer = opt.Buffer htb.Cbuffer = opt.Cbuffer htb.Quantum = opt.Quantum diff --git a/class_test.go b/class_test.go index 92fdd4a..f44ae7b 100644 --- a/class_test.go +++ b/class_test.go @@ -67,10 +67,10 @@ func TestClassAddDel(t *testing.T) { if !ok { t.Fatal("Class is the wrong type") } - if htb.Rate != class.Rate { + if htb.Rate.Rate != class.Rate.Rate { t.Fatal("Rate doesn't match") } - if htb.Ceil != class.Ceil { + if htb.Ceil.Rate != class.Ceil.Rate { t.Fatal("Ceil doesn't match") } if htb.Buffer != class.Buffer { @@ -299,7 +299,7 @@ func TestHtbClassAddHtbClassChangeDel(t *testing.T) { t.Fatal("Class is the wrong type") } // Verify that the rate value has changed. - if htb.Rate != class.Rate { + if htb.Rate.Rate != class.Rate.Rate { t.Fatal("Rate did not get changed while changing the class.") } @@ -348,7 +348,7 @@ func TestHtbClassAddHtbClassChangeDel(t *testing.T) { t.Fatal("Class is the wrong type") } // Verify that the rate value has changed. - if htb.Rate != class.Rate { + if htb.Rate.Rate != class.Rate.Rate { t.Fatal("Rate did not get changed while changing the class.") } @@ -375,7 +375,7 @@ func TestHtbClassAddHtbClassChangeDel(t *testing.T) { t.Fatal("Class is the wrong type") } // Verify that the rate value has changed. - if htb.Rate != class.Rate { + if htb.Rate.Rate != class.Rate.Rate { t.Fatal("Rate did not get changed while changing the class.") }