From 2e9d285a7160e1c65e1eab8238faf2d6a0dc9a4a Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Tue, 17 Feb 2015 14:16:48 -0800 Subject: [PATCH] Change logic of setting protinfo attrs Now interface is supposing that you setting protinfo attrs for link one by one. But you can get all protinfo attrs with one call. Signed-off-by: Alexander Morozov --- link_linux.go | 46 +++++++++++++++++++++++++++++ netlink_unspecified.go | 24 +++++++++++++++ protinfo.go | 27 ----------------- protinfo_test.go | 66 ++++++++++++++++++++++++++++-------------- 4 files changed, 114 insertions(+), 49 deletions(-) diff --git a/link_linux.go b/link_linux.go index 8ae7cb58..aedea165 100644 --- a/link_linux.go +++ b/link_linux.go @@ -560,6 +560,52 @@ func LinkList() ([]Link, error) { return res, nil } +func LinkSetHairpin(link Link, mode bool) error { + return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_MODE) +} + +func LinkSetGuard(link Link, mode bool) error { + return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD) +} + +func LinkSetFastLeave(link Link, mode bool) error { + return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_FAST_LEAVE) +} + +func LinkSetLearning(link Link, mode bool) error { + return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_LEARNING) +} + +func LinkSetRootBlock(link Link, mode bool) error { + return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROTECT) +} + +func LinkSetFlood(link Link, mode bool) error { + return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD) +} + +func setProtinfoAttr(link Link, mode bool, attr int) error { + base := link.Attrs() + ensureIndex(base) + req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK) + + msg := nl.NewIfInfomsg(syscall.AF_BRIDGE) + msg.Type = syscall.RTM_SETLINK + msg.Flags = syscall.NLM_F_REQUEST + msg.Index = int32(base.Index) + msg.Change = nl.DEFAULT_CHANGE + req.AddData(msg) + + br := nl.NewRtAttr(syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED, nil) + nl.NewRtAttrChild(br, attr, boolToByte(mode)) + req.AddData(br) + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + if err != nil { + return err + } + return nil +} + func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) { vlan := link.(*Vlan) for _, datum := range data { diff --git a/netlink_unspecified.go b/netlink_unspecified.go index 7a081d7c..10c49c1b 100644 --- a/netlink_unspecified.go +++ b/netlink_unspecified.go @@ -42,6 +42,30 @@ func LinkDel(link *Link) error { return ErrNotImplemented } +func SetHairpin(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetGuard(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetFastLeave(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetLearning(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetRootBlock(link Link, mode bool) error { + return ErrNotImplemented +} + +func SetFlood(link Link, mode bool) error { + return ErrNotImplemented +} + func LinkList() ([]Link, error) { return nil, ErrNotImplemented } diff --git a/protinfo.go b/protinfo.go index 8631a80c..a5d330cb 100644 --- a/protinfo.go +++ b/protinfo.go @@ -81,30 +81,3 @@ func LinkGetProtinfo(link Link) (Protinfo, error) { } return pi, fmt.Errorf("Device with index %d not found", base.Index) } - -func LinkSetProtinfo(link Link, p Protinfo) error { - base := link.Attrs() - ensureIndex(base) - req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK) - - msg := nl.NewIfInfomsg(syscall.AF_BRIDGE) - msg.Type = syscall.RTM_SETLINK - msg.Flags = syscall.NLM_F_REQUEST - msg.Index = int32(base.Index) - msg.Change = nl.DEFAULT_CHANGE - req.AddData(msg) - - br := nl.NewRtAttr(syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED, nil) - nl.NewRtAttrChild(br, nl.IFLA_BRPORT_MODE, boolToByte(p.Hairpin)) - nl.NewRtAttrChild(br, nl.IFLA_BRPORT_GUARD, boolToByte(p.Guard)) - nl.NewRtAttrChild(br, nl.IFLA_BRPORT_FAST_LEAVE, boolToByte(p.FastLeave)) - nl.NewRtAttrChild(br, nl.IFLA_BRPORT_PROTECT, boolToByte(p.RootBlock)) - nl.NewRtAttrChild(br, nl.IFLA_BRPORT_LEARNING, boolToByte(p.Learning)) - nl.NewRtAttrChild(br, nl.IFLA_BRPORT_UNICAST_FLOOD, boolToByte(p.Flood)) - req.AddData(br) - _, err := req.Execute(syscall.NETLINK_ROUTE, 0) - if err != nil { - return err - } - return nil -} diff --git a/protinfo_test.go b/protinfo_test.go index 54bec93d..f94c42b1 100644 --- a/protinfo_test.go +++ b/protinfo_test.go @@ -23,54 +23,76 @@ func TestProtinfo(t *testing.T) { t.Fatal(err) } - pi1 := Protinfo{ - Hairpin: true, - RootBlock: true, + oldpi1, err := LinkGetProtinfo(iface1) + if err != nil { + t.Fatal(err) } - - pi2 := Protinfo{ - Guard: true, - Learning: false, + oldpi2, err := LinkGetProtinfo(iface2) + if err != nil { + t.Fatal(err) } - pi3 := Protinfo{} + if err := LinkSetHairpin(iface1, true); err != nil { + t.Fatal(err) + } - if err := LinkSetProtinfo(iface1, pi1); err != nil { + if err := LinkSetRootBlock(iface1, true); err != nil { t.Fatal(err) } - gpi1, err := LinkGetProtinfo(iface1) + pi1, err := LinkGetProtinfo(iface1) if err != nil { t.Fatal(err) } - if !gpi1.Hairpin { + if !pi1.Hairpin { t.Fatalf("Hairpin mode is not enabled for %s, but should", iface1.Name) } - - if !gpi1.RootBlock { + if !pi1.RootBlock { t.Fatalf("RootBlock is not enabled for %s, but should", iface1.Name) } + if pi1.Guard != oldpi1.Guard { + t.Fatalf("Guard field was changed for %s but shouldn't", iface1.Name) + } + if pi1.FastLeave != oldpi1.FastLeave { + t.Fatalf("FastLeave field was changed for %s but shouldn't", iface1.Name) + } + if pi1.Learning != oldpi1.Learning { + t.Fatalf("Learning field was changed for %s but shouldn't", iface1.Name) + } + if pi1.Flood != oldpi1.Flood { + t.Fatalf("Flood field was changed for %s but shouldn't", iface1.Name) + } - if err := LinkSetProtinfo(iface2, pi2); err != nil { + if err := LinkSetGuard(iface2, true); err != nil { t.Fatal(err) } - gpi2, err := LinkGetProtinfo(iface2) + if err := LinkSetLearning(iface2, false); err != nil { + t.Fatal(err) + } + pi2, err := LinkGetProtinfo(iface2) if err != nil { t.Fatal(err) } - if gpi2.Hairpin { + if pi2.Hairpin { t.Fatalf("Hairpin mode is enabled for %s, but shouldn't", iface2.Name) } - - if !gpi2.Guard { + if !pi2.Guard { t.Fatalf("Guard is not enabled for %s, but should", iface2.Name) } - - if gpi2.Learning { + if pi2.Learning { t.Fatalf("Learning is enabled for %s, but shouldn't", iface2.Name) } + if pi2.RootBlock != oldpi2.RootBlock { + t.Fatalf("RootBlock field was changed for %s but shouldn't", iface2.Name) + } + if pi2.FastLeave != oldpi2.FastLeave { + t.Fatalf("FastLeave field was changed for %s but shouldn't", iface2.Name) + } + if pi2.Flood != oldpi2.Flood { + t.Fatalf("Flood field was changed for %s but shouldn't", iface2.Name) + } - if err := LinkSetProtinfo(iface3, pi3); err == nil || err.Error() != "operation not supported" { - t.Fatalf("Set protinfo for link without master is not supported, but err: %s", err) + if err := LinkSetHairpin(iface3, true); err == nil || err.Error() != "operation not supported" { + t.Fatalf("Set protinfo attrs for link without master is not supported, but err: %s", err) } }