package netlink import ( "errors" "fmt" "github.com/vishvananda/netlink/nl" ) type Class interface { Attrs() *ClassAttrs Type() string } // Class represents a netlink class. A filter is associated with a link, // has a handle and a parent. The root filter of a device should have a // parent == HANDLE_ROOT. type ClassAttrs struct { LinkIndex int Handle uint32 Parent uint32 Leaf uint32 } func (q ClassAttrs) String() string { return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Leaf: %s}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Leaf) } type HtbClassAttrs struct { // TODO handle all attributes Rate uint64 Ceil uint64 Buffer uint32 Cbuffer uint32 Quantum uint32 Level uint32 Prio uint32 } func (q HtbClassAttrs) String() string { return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) } // Htb class type HtbClass struct { ClassAttrs 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, error) { 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 } if buffer == 0 { buffer = uint32(float64(rate)/Hz() + float64(mtu)) } buffer = uint32(Xmittime(rate, buffer)) if cbuffer == 0 { cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) } cbuffer = uint32(Xmittime(ceil, cbuffer)) tcrate := nl.TcRateSpec{Rate: uint32(rate)} if CalcRtable(&tcrate, rtab, cell_log, uint32(mtu), linklayer) < 0 { return nil, errors.New("HTB: failed to calculate rate table.") } tcceil := nl.TcRateSpec{Rate: uint32(ceil)} if CalcRtable(&tcceil, ctab, ccell_log, uint32(mtu), linklayer) < 0 { return nil, errors.New("HTB: failed to calculate ceil rate table.") } return &HtbClass{ ClassAttrs: attrs, Rate: tcrate, Ceil: tcceil, Buffer: buffer, Cbuffer: cbuffer, Quantum: 10, Level: 0, Prio: 0, Rtab: rtab, Ctab: ctab, }, nil } func (q HtbClass) String() string { return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) } func (class *HtbClass) Attrs() *ClassAttrs { return &class.ClassAttrs } func (class *HtbClass) Type() string { return "htb" } // GenericClass classes represent types that are not currently understood // by this netlink library. type GenericClass struct { ClassAttrs ClassType string } func (class *GenericClass) Attrs() *ClassAttrs { return &class.ClassAttrs } func (class *GenericClass) Type() string { return class.ClassType }