Skip to content

Commit

Permalink
Service curves fix
Browse files Browse the repository at this point in the history
There was something off with the math for the ServiceCurves. The set value was 8
times too large and the returned one was 8 times too small.

This is now fixed in `class.go` and `class_linux.go` so the user can just set the rate in bit and
it will match the tc show output.
  • Loading branch information
fbegyn authored and fcrisciani committed Jan 27, 2020
1 parent b237268 commit 01d9156
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 23 deletions.
56 changes: 42 additions & 14 deletions class.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ func (class *GenericClass) Type() string {
return class.ClassType
}

// ServiceCurve is the way the HFSC curve are represented
// ServiceCurve is a nondecreasing function of some time unit, returning the amount of service
// (an allowed or allocated amount of bandwidth) at some specific point in time. The purpose of it
// should be subconsciously obvious: if a class was allowed to transfer not less than the amount
// specified by its service curve, then the service curve is not violated.
type ServiceCurve struct {
m1 uint32
d uint32
Expand All @@ -144,6 +147,21 @@ func (c *ServiceCurve) Attrs() (uint32, uint32, uint32) {
return c.m1, c.d, c.m2
}

// Burst returns the burst rate (m1) of the curve
func (c *ServiceCurve) Burst() uint32 {
return c.m1
}

// Delay return the delay (d) of the curve
func (c *ServiceCurve) Delay() uint32 {
return c.d
}

// Rate returns the rate (m2) of the curve
func (c *ServiceCurve) Rate() uint32 {
return c.m2
}

// HfscClass is a representation of the HFSC class
type HfscClass struct {
ClassAttrs
Expand All @@ -152,35 +170,44 @@ type HfscClass struct {
Usc ServiceCurve
}

// SetUsc sets the Usc curve
// SetUsc sets the USC curve. The bandwidth (m1 and m2) is specified in bits and the delay in
// seconds.
func (hfsc *HfscClass) SetUsc(m1 uint32, d uint32, m2 uint32) {
hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
hfsc.Usc = ServiceCurve{m1: m1, d: d, m2: m2}
}

// SetFsc sets the Fsc curve
// SetFsc sets the Fsc curve. The bandwidth (m1 and m2) is specified in bits and the delay in
// seconds.
func (hfsc *HfscClass) SetFsc(m1 uint32, d uint32, m2 uint32) {
hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
hfsc.Fsc = ServiceCurve{m1: m1, d: d, m2: m2}
}

// SetRsc sets the Rsc curve
// SetRsc sets the Rsc curve. The bandwidth (m1 and m2) is specified in bits and the delay in
// seconds.
func (hfsc *HfscClass) SetRsc(m1 uint32, d uint32, m2 uint32) {
hfsc.Rsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
hfsc.Rsc = ServiceCurve{m1: m1, d: d, m2: m2}
}

// SetSC implements the SC from the tc CLI
// SetSC implements the SC from the `tc` CLI. This function behaves the same as if one would set the
// USC through the `tc` command-line tool. This means bandwidth (m1 and m2) is specified in bits and
// the delay in ms.
func (hfsc *HfscClass) SetSC(m1 uint32, d uint32, m2 uint32) {
hfsc.Rsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
hfsc.SetRsc(m1, d, m2)
hfsc.SetFsc(m1, d, m2)
}

// SetUL implements the UL from the tc CLI
// SetUL implements the UL from the `tc` CLI. This function behaves the same as if one would set the
// USC through the `tc` command-line tool. This means bandwidth (m1 and m2) is specified in bits and
// the delay in ms.
func (hfsc *HfscClass) SetUL(m1 uint32, d uint32, m2 uint32) {
hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
hfsc.SetUsc(m1, d, m2)
}

// SetLS implements the LS from the tc CLI
// SetLS implements the LS from the `tc` CLI. This function behaves the same as if one would set the
// USC through the `tc` command-line tool. This means bandwidth (m1 and m2) is specified in bits and
// the delay in ms.
func (hfsc *HfscClass) SetLS(m1 uint32, d uint32, m2 uint32) {
hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
hfsc.SetFsc(m1, d, m2)
}

// NewHfscClass returns a new HFSC struct with the set parameters
Expand All @@ -193,6 +220,7 @@ func NewHfscClass(attrs ClassAttrs) *HfscClass {
}
}

// String() returns a string that contains the information and attributes of the HFSC class
func (hfsc *HfscClass) String() string {
return fmt.Sprintf(
"{%s -- {RSC: {m1=%d d=%d m2=%d}} {FSC: {m1=%d d=%d m2=%d}} {USC: {m1=%d d=%d m2=%d}}}",
Expand Down
21 changes: 12 additions & 9 deletions class_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,15 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
case "hfsc":
hfsc := class.(*HfscClass)
opt := nl.HfscCopt{}
opt.Rsc.Set(hfsc.Rsc.Attrs())
opt.Fsc.Set(hfsc.Fsc.Attrs())
opt.Usc.Set(hfsc.Usc.Attrs())
options.AddRtAttr(nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc))
options.AddRtAttr(nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc))
options.AddRtAttr(nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc))
rm1, rd, rm2 := hfsc.Rsc.Attrs()
opt.Rsc.Set(rm1/8, rd, rm2/8)
fm1, fd, fm2 := hfsc.Fsc.Attrs()
opt.Fsc.Set(fm1/8, fd, fm2/8)
um1, ud, um2 := hfsc.Usc.Attrs()
opt.Usc.Set(um1/8, ud, um2/8)
nl.NewRtAttrChild(options, nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc))
nl.NewRtAttrChild(options, nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc))
nl.NewRtAttrChild(options, nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc))
}
req.AddData(options)
return nil
Expand Down Expand Up @@ -315,11 +318,11 @@ func parseHfscClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, err
m1, d, m2 := nl.DeserializeHfscCurve(datum.Value).Attrs()
switch datum.Attr.Type {
case nl.TCA_HFSC_RSC:
hfsc.Rsc = ServiceCurve{m1: m1, d: d, m2: m2}
hfsc.Rsc = ServiceCurve{m1: m1 * 8, d: d, m2: m2 * 8}
case nl.TCA_HFSC_FSC:
hfsc.Fsc = ServiceCurve{m1: m1, d: d, m2: m2}
hfsc.Fsc = ServiceCurve{m1: m1 * 8, d: d, m2: m2 * 8}
case nl.TCA_HFSC_USC:
hfsc.Usc = ServiceCurve{m1: m1, d: d, m2: m2}
hfsc.Usc = ServiceCurve{m1: m1 * 8, d: d, m2: m2 * 8}
}
}
return detailed, nil
Expand Down

0 comments on commit 01d9156

Please sign in to comment.