netlink
netlink copied to clipboard
Qdisc Loss/Latency Values Incorrect
Hello!
I admit I am a bit new to GoLang, but I am trying to create a program that lists out the output of "tc qdisc show" across all the interfaces. I seem to be getting some weird values for the Loss and Latency. I made a sample program to test it based on some of the test code.
Expecting: Latency: 5000, Limit: 1000, Loss: 5.0 Receive: Latency: 78125, Limit: 1000, Loss: 214748368
Am I doing something wrong?
My system is a fresh installed virtualbox of Ubuntu 18.04. With Go 1.12.9
package main
import (
"github.com/vishvananda/netlink"
"log"
"os/exec"
)
func main() {
const main_int_name = "enp0s3"
link, err := netlink.LinkByName(main_int_name)
if err != nil {
log.Fatal(err)
}
qdiscs, err := netlink.QdiscList(link)
if err != nil {
log.Fatal(err)
}
for _, qdisc := range qdiscs {
log.Println("NO NETEM: ",qdisc)
}
qattrs := netlink.QdiscAttrs{
LinkIndex: link.Attrs().Index,
Handle: netlink.MakeHandle(0x2, 0),
Parent: netlink.HANDLE_ROOT,
}
nattrs := netlink.NetemQdiscAttrs{
Latency: 5000,
Loss: 5.0,
}
qdiscnetem := netlink.NewNetem(qattrs, nattrs)
if err := netlink.QdiscAdd(qdiscnetem); err != nil {
log.Fatal("unable to add qdisc: ", err)
}
qdiscs, err = netlink.QdiscList(link)
for _, qdisc := range qdiscs {
log.Println("WITH NETEM: ", qdisc)
cmd, _ := exec.Command("tc", "qdisc", "show", "dev", main_int_name).Output()
log.Printf("TC SHOW COMMAND: %s", cmd)
netlink.QdiscDel(qdisc)
}
}
Output:
chris@chris-VirtualBox:~/go/src/awesomeProject$ go build && sudo ./awesomeProject
2019/09/03 13:37:30 NO NETEM: {{LinkIndex: 2, Handle: none, Parent: root, Refcnt: 2} -- Target: 4999, Limit: 10240, Interval: 99999, ECM: 1, Flows: 1024, Quantum: 1514}
2019/09/03 13:37:30 WITH NETEM: {Latency: 78125, Limit: 1000, Loss: 214748368, Gap: 0, Duplicate: 0, Jitter: 0}
2019/09/03 13:37:30 TC SHOW COMMAND: qdisc netem 2: root refcnt 2 limit 1000 delay 5.0ms loss 5%
This also occurs just listing already created by using the tc command.
I haven't looked at this in a while, but I seem to remember there being some really weird logic for how these things are calculated that the tc command does behind the scenes, so there isn't an exact match for the values that tc shows in the underlying structures. I'll have to try to find a reference doc.
Ah my memory was about something else. The issue is that the Qdisc that is returned has the values as u32 so they just need to be converted back into a percentage which could be done using something like: qdisc.Loss / math.MaxUint32 * 100 which will give you approx 5.000
The latency also goes through a time2tick conversion which converts the value into clock ticks. Basically there should probably be a way included to convert these back to human readable values which we don't currently provide. there is a method called tick2Time which converts back but it isn't exposed in an easy manner. I think there should be a NetEm.ToNetemQdiscAttrs() that converts the values back to milliseconds and percentages for you.
Hi, I also encountered this problem related to the latency field. I found a workaround by adjusting the Latency field with TickInUsec()
. However, I noticed that there was a time2Tick(latency)
function in the library, but it was not exposed. So I used TickInUsec()
as an alternative.
I'm concerned that this workaround may break if someone fixes the time correction bug in the future. Can we expect a fix for this issue, and if so, can maintainers notify to this issue?
// Add a new qdisc: tc qdisc add dev eth0 root netem delay 14ms
qdisc := &netlink.Netem{
QdiscAttrs: netlink.QdiscAttrs{
LinkIndex: link.Attrs().Index,
Handle: netlink.MakeHandle(0x1, 0),
Parent: netlink.HANDLE_ROOT,
},
Latency: uint32(14 * 1000 * netlink.TickInUsec()), // 14ms
}