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 | 80 +++++++++++++++++++++++++++--------------- 4 files changed, 121 insertions(+), 56 deletions(-) diff --git a/link_linux.go b/link_linux.go index 8ae7cb5..aedea16 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 7a081d7..10c49c1 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 8631a80..a5d330c 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 54bec93..f94c42b 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, - } - - pi2 := Protinfo{ - Guard: true, - Learning: false, - } - - pi3 := Protinfo{} - - if err := LinkSetProtinfo(iface1, pi1); err != nil { - t.Fatal(err) - } - - gpi1, err := LinkGetProtinfo(iface1) + oldpi1, err := LinkGetProtinfo(iface1) if err != nil { t.Fatal(err) } - if !gpi1.Hairpin { + oldpi2, err := LinkGetProtinfo(iface2) + if err != nil { + t.Fatal(err) + } + + if err := LinkSetHairpin(iface1, true); err != nil { + t.Fatal(err) + } + + if err := LinkSetRootBlock(iface1, true); err != nil { + t.Fatal(err) + } + + pi1, err := LinkGetProtinfo(iface1) + if err != nil { + t.Fatal(err) + } + 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) } }