mirror of
https://github.com/vishvananda/netlink
synced 2024-12-18 21:04:56 +00:00
Merge pull request #64 from chantra/tc_replace
Add support to replace/change qdisc
This commit is contained in:
commit
3e8d52b0f9
@ -13,24 +13,37 @@ import (
|
||||
// QdiscDel will delete a qdisc from the system.
|
||||
// Equivalent to: `tc qdisc del $qdisc`
|
||||
func QdiscDel(qdisc Qdisc) error {
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_DELQDISC, syscall.NLM_F_ACK)
|
||||
base := qdisc.Attrs()
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
Ifindex: int32(base.LinkIndex),
|
||||
Handle: base.Handle,
|
||||
Parent: base.Parent,
|
||||
}
|
||||
req.AddData(msg)
|
||||
return qdiscModify(syscall.RTM_DELQDISC, 0, qdisc)
|
||||
}
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
// QdiscChange will change a qdisc in place
|
||||
// Equivalent to: `tc qdisc change $qdisc`
|
||||
// The parent and handle MUST NOT be changed.
|
||||
func QdiscChange(qdisc Qdisc) error {
|
||||
return qdiscModify(syscall.RTM_NEWQDISC, 0, qdisc)
|
||||
}
|
||||
|
||||
// QdiscReplace will replace a qdisc to the system.
|
||||
// Equivalent to: `tc qdisc replace $qdisc`
|
||||
// The handle MUST change.
|
||||
func QdiscReplace(qdisc Qdisc) error {
|
||||
return qdiscModify(
|
||||
syscall.RTM_NEWQDISC,
|
||||
syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE,
|
||||
qdisc)
|
||||
}
|
||||
|
||||
// QdiscAdd will add a qdisc to the system.
|
||||
// Equivalent to: `tc qdisc add $qdisc`
|
||||
func QdiscAdd(qdisc Qdisc) error {
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_NEWQDISC, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
||||
return qdiscModify(
|
||||
syscall.RTM_NEWQDISC,
|
||||
syscall.NLM_F_CREATE|syscall.NLM_F_EXCL,
|
||||
qdisc)
|
||||
}
|
||||
|
||||
func qdiscModify(cmd, flags int, qdisc Qdisc) error {
|
||||
req := nl.NewNetlinkRequest(cmd, flags|syscall.NLM_F_ACK)
|
||||
base := qdisc.Attrs()
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
@ -39,6 +52,20 @@ func QdiscAdd(qdisc Qdisc) error {
|
||||
Parent: base.Parent,
|
||||
}
|
||||
req.AddData(msg)
|
||||
|
||||
// When deleting don't bother building the rest of the netlink payload
|
||||
if cmd != syscall.RTM_DELQDISC {
|
||||
if err := qdiscPayload(req, qdisc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type())))
|
||||
|
||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||
@ -99,14 +126,13 @@ func QdiscAdd(qdisc Qdisc) error {
|
||||
}
|
||||
} else if _, ok := qdisc.(*Ingress); ok {
|
||||
// ingress filters must use the proper handle
|
||||
if msg.Parent != HANDLE_INGRESS {
|
||||
if qdisc.Attrs().Parent != HANDLE_INGRESS {
|
||||
return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS")
|
||||
}
|
||||
}
|
||||
|
||||
req.AddData(options)
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// QdiscList gets a list of qdiscs in the system.
|
||||
|
180
qdisc_test.go
180
qdisc_test.go
@ -163,3 +163,183 @@ func TestPrioAddDel(t *testing.T) {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTbfAddHtbReplaceDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Add
|
||||
attrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(1, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
}
|
||||
qdisc := &Tbf{
|
||||
QdiscAttrs: attrs,
|
||||
Rate: 131072,
|
||||
Limit: 1220703,
|
||||
Buffer: 16793,
|
||||
}
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
tbf, ok := qdiscs[0].(*Tbf)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if tbf.Rate != qdisc.Rate {
|
||||
t.Fatal("Rate doesn't match")
|
||||
}
|
||||
if tbf.Limit != qdisc.Limit {
|
||||
t.Fatal("Limit doesn't match")
|
||||
}
|
||||
if tbf.Buffer != qdisc.Buffer {
|
||||
t.Fatal("Buffer doesn't match")
|
||||
}
|
||||
// Replace
|
||||
// For replace to work, the handle MUST be different that the running one
|
||||
attrs.Handle = MakeHandle(2, 0)
|
||||
qdisc2 := NewHtb(attrs)
|
||||
qdisc2.Rate2Quantum = 5
|
||||
if err := QdiscReplace(qdisc2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
htb, ok := qdiscs[0].(*Htb)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if htb.Defcls != qdisc2.Defcls {
|
||||
t.Fatal("Defcls doesn't match")
|
||||
}
|
||||
if htb.Rate2Quantum != qdisc2.Rate2Quantum {
|
||||
t.Fatal("Rate2Quantum doesn't match")
|
||||
}
|
||||
if htb.Debug != qdisc2.Debug {
|
||||
t.Fatal("Debug doesn't match")
|
||||
}
|
||||
|
||||
if err := QdiscDel(qdisc2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTbfAddTbfChangeDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Add
|
||||
attrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(1, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
}
|
||||
qdisc := &Tbf{
|
||||
QdiscAttrs: attrs,
|
||||
Rate: 131072,
|
||||
Limit: 1220703,
|
||||
Buffer: 16793,
|
||||
}
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
tbf, ok := qdiscs[0].(*Tbf)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if tbf.Rate != qdisc.Rate {
|
||||
t.Fatal("Rate doesn't match")
|
||||
}
|
||||
if tbf.Limit != qdisc.Limit {
|
||||
t.Fatal("Limit doesn't match")
|
||||
}
|
||||
if tbf.Buffer != qdisc.Buffer {
|
||||
t.Fatal("Buffer doesn't match")
|
||||
}
|
||||
// Change
|
||||
// For change to work, the handle MUST not change
|
||||
qdisc.Rate = 23456
|
||||
if err := QdiscChange(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
tbf, ok = qdiscs[0].(*Tbf)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if tbf.Rate != qdisc.Rate {
|
||||
t.Fatal("Rate doesn't match")
|
||||
}
|
||||
if tbf.Limit != qdisc.Limit {
|
||||
t.Fatal("Limit doesn't match")
|
||||
}
|
||||
if tbf.Buffer != qdisc.Buffer {
|
||||
t.Fatal("Buffer doesn't match")
|
||||
}
|
||||
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user