From 27908bfeb4ad202dc26926a4c9875503a8d05b2b Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Mon, 19 Oct 2015 14:51:29 +0100 Subject: [PATCH] Update netlink library. Signed-off-by: Dimitri John Ledkov --- libnetwork/Godeps/Godeps.json | 4 +- .../vishvananda/netlink/addr_test.go | 45 -- .../github.com/vishvananda/netlink/class.go | 110 +++ .../vishvananda/netlink/class_linux.go | 144 ++++ .../github.com/vishvananda/netlink/filter.go | 140 ++++ .../vishvananda/netlink/filter_linux.go | 322 +++++++++ .../github.com/vishvananda/netlink/link.go | 56 +- .../vishvananda/netlink/link_linux.go | 93 ++- .../vishvananda/netlink/link_test.go | 643 ------------------ .../vishvananda/netlink/link_tuntap_linux.go | 14 + .../vishvananda/netlink/neigh_test.go | 104 --- .../vishvananda/netlink/netlink_test.go | 34 - .../vishvananda/netlink/nl/addr_linux_test.go | 39 -- .../vishvananda/netlink/nl/nl_linux.go | 2 +- .../vishvananda/netlink/nl/nl_linux_test.go | 60 -- .../netlink/nl/route_linux_test.go | 43 -- .../vishvananda/netlink/nl/tc_linux.go | 508 ++++++++++++++ .../vishvananda/netlink/nl/xfrm_linux_test.go | 161 ----- .../netlink/nl/xfrm_policy_linux_test.go | 109 --- .../netlink/nl/xfrm_state_linux_test.go | 207 ------ .../vishvananda/netlink/protinfo_test.go | 98 --- .../github.com/vishvananda/netlink/qdisc.go | 167 +++++ .../vishvananda/netlink/qdisc_linux.go | 316 +++++++++ .../github.com/vishvananda/netlink/route.go | 46 +- .../vishvananda/netlink/route_linux.go | 115 ++-- .../vishvananda/netlink/route_test.go | 84 --- .../vishvananda/netlink/xfrm_policy_test.go | 49 -- .../vishvananda/netlink/xfrm_state_test.go | 50 -- .../vishvananda/netns/netns_linux_s390x.go | 7 + .../vishvananda/netns/netns_test.go | 66 -- 30 files changed, 1989 insertions(+), 1847 deletions(-) delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go create mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class.go create mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go create mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter.go create mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_linux.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go create mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_tuntap_linux.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go create mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/tc_linux.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go create mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go create mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_test.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_policy_test.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state_test.go create mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_linux_s390x.go delete mode 100644 libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_test.go diff --git a/libnetwork/Godeps/Godeps.json b/libnetwork/Godeps/Godeps.json index d7207e6e2b..b22a5e0448 100644 --- a/libnetwork/Godeps/Godeps.json +++ b/libnetwork/Godeps/Godeps.json @@ -216,11 +216,11 @@ }, { "ImportPath": "github.com/vishvananda/netlink", - "Rev": "4b5dce31de6d42af5bb9811c6d265472199e0fec" + "Rev": "8e810149a2e531fed9b837c0c7d8a8922d2bedf7" }, { "ImportPath": "github.com/vishvananda/netns", - "Rev": "493029407eeb434d0c2d44e02ea072ff2488d322" + "Rev": "604eaf189ee867d8c147fafc28def2394e878d25" }, { "ImportPath": "golang.org/x/net/context", diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go deleted file mode 100644 index 45e22c0526..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package netlink - -import ( - "testing" -) - -func TestAddrAddDel(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - link, err := LinkByName("lo") - if err != nil { - t.Fatal(err) - } - - addr, err := ParseAddr("127.1.1.1/24 local") - if err != nil { - t.Fatal(err) - } - - if err = AddrAdd(link, addr); err != nil { - t.Fatal(err) - } - - addrs, err := AddrList(link, FAMILY_ALL) - if err != nil { - t.Fatal(err) - } - - if len(addrs) != 1 || !addr.Equal(addrs[0]) || addrs[0].Label != addr.Label { - t.Fatal("Address not added properly") - } - - if err = AddrDel(link, addr); err != nil { - t.Fatal(err) - } - addrs, err = AddrList(link, FAMILY_ALL) - if err != nil { - t.Fatal(err) - } - - if len(addrs) != 0 { - t.Fatal("Address not removed properly") - } -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class.go new file mode 100644 index 0000000000..35bdb33100 --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class.go @@ -0,0 +1,110 @@ +package netlink + +import ( + "fmt" +) + +type Class interface { + Attrs() *ClassAttrs + Type() string +} + +// Class represents a netlink class. A filter is associated with a link, +// has a handle and a parent. The root filter of a device should have a +// parent == HANDLE_ROOT. +type ClassAttrs struct { + LinkIndex int + Handle uint32 + Parent uint32 + Leaf uint32 +} + +func (q ClassAttrs) String() string { + return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Leaf: %s}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Leaf) +} + +type HtbClassAttrs struct { + // TODO handle all attributes + Rate uint64 + Ceil uint64 + Buffer uint32 + Cbuffer uint32 + Quantum uint32 + Level uint32 + Prio uint32 +} + +func (q HtbClassAttrs) String() string { + return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) +} + +// Htb class +type HtbClass struct { + ClassAttrs + Rate uint64 + Ceil uint64 + Buffer uint32 + Cbuffer uint32 + Quantum uint32 + Level uint32 + Prio uint32 +} + +func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { + mtu := 1600 + rate := cattrs.Rate / 8 + ceil := cattrs.Ceil / 8 + buffer := cattrs.Buffer + cbuffer := cattrs.Cbuffer + if ceil == 0 { + ceil = rate + } + + if buffer == 0 { + buffer = uint32(float64(rate)/Hz() + float64(mtu)) + } + buffer = uint32(Xmittime(rate, buffer)) + + if cbuffer == 0 { + cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) + } + cbuffer = uint32(Xmittime(ceil, cbuffer)) + + return &HtbClass{ + ClassAttrs: attrs, + Rate: rate, + Ceil: ceil, + Buffer: buffer, + Cbuffer: cbuffer, + Quantum: 10, + Level: 0, + Prio: 0, + } +} + +func (q HtbClass) String() string { + return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) +} + +func (class *HtbClass) Attrs() *ClassAttrs { + return &class.ClassAttrs +} + +func (class *HtbClass) Type() string { + return "htb" +} + +// GenericClass classes represent types that are not currently understood +// by this netlink library. +type GenericClass struct { + ClassAttrs + ClassType string +} + +func (class *GenericClass) Attrs() *ClassAttrs { + return &class.ClassAttrs +} + +func (class *GenericClass) Type() string { + return class.ClassType +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go new file mode 100644 index 0000000000..3dcc542bfe --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go @@ -0,0 +1,144 @@ +package netlink + +import ( + "syscall" + + "github.com/vishvananda/netlink/nl" +) + +// ClassDel will delete a class from the system. +// Equivalent to: `tc class del $class` +func ClassDel(class Class) error { + req := nl.NewNetlinkRequest(syscall.RTM_DELTCLASS, syscall.NLM_F_ACK) + base := class.Attrs() + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: int32(base.LinkIndex), + Handle: base.Handle, + Parent: base.Parent, + } + req.AddData(msg) + + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + +// ClassAdd will add a class to the system. +// Equivalent to: `tc class add $class` +func ClassAdd(class Class) error { + req := nl.NewNetlinkRequest(syscall.RTM_NEWTCLASS, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) + base := class.Attrs() + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: int32(base.LinkIndex), + Handle: base.Handle, + Parent: base.Parent, + } + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type()))) + + options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) + if htb, ok := class.(*HtbClass); ok { + opt := nl.TcHtbCopt{} + opt.Rate.Rate = uint32(htb.Rate) + opt.Ceil.Rate = uint32(htb.Ceil) + opt.Buffer = htb.Buffer + opt.Cbuffer = htb.Cbuffer + opt.Quantum = htb.Quantum + opt.Level = htb.Level + opt.Prio = htb.Prio + // TODO: Handle Debug properly. For now default to 0 + nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize()) + } + req.AddData(options) + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + +// ClassList gets a list of classes in the system. +// Equivalent to: `tc class show`. +// Generally retunrs nothing if link and parent are not specified. +func ClassList(link Link, parent uint32) ([]Class, error) { + req := nl.NewNetlinkRequest(syscall.RTM_GETTCLASS, syscall.NLM_F_DUMP) + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Parent: parent, + } + if link != nil { + base := link.Attrs() + ensureIndex(base) + msg.Ifindex = int32(base.Index) + } + req.AddData(msg) + + msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWTCLASS) + if err != nil { + return nil, err + } + + var res []Class + for _, m := range msgs { + msg := nl.DeserializeTcMsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + base := ClassAttrs{ + LinkIndex: int(msg.Ifindex), + Handle: msg.Handle, + Parent: msg.Parent, + } + + var class Class + classType := "" + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.TCA_KIND: + classType = string(attr.Value[:len(attr.Value)-1]) + switch classType { + case "htb": + class = &HtbClass{} + default: + class = &GenericClass{ClassType: classType} + } + case nl.TCA_OPTIONS: + switch classType { + case "htb": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + _, err = parseHtbClassData(class, data) + if err != nil { + return nil, err + } + } + } + } + *class.Attrs() = base + res = append(res, class) + } + + return res, nil +} + +func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) { + htb := class.(*HtbClass) + detailed := false + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_HTB_PARMS: + opt := nl.DeserializeTcHtbCopt(datum.Value) + htb.Rate = uint64(opt.Rate.Rate) + htb.Ceil = uint64(opt.Ceil.Rate) + htb.Buffer = opt.Buffer + htb.Cbuffer = opt.Cbuffer + htb.Quantum = opt.Quantum + htb.Level = opt.Level + htb.Prio = opt.Prio + } + } + return detailed, nil +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter.go new file mode 100644 index 0000000000..80ef34ded4 --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter.go @@ -0,0 +1,140 @@ +package netlink + +import ( + "errors" + "fmt" + "github.com/vishvananda/netlink/nl" +) + +type Filter interface { + Attrs() *FilterAttrs + Type() string +} + +// Filter represents a netlink filter. A filter is associated with a link, +// has a handle and a parent. The root filter of a device should have a +// parent == HANDLE_ROOT. +type FilterAttrs struct { + LinkIndex int + Handle uint32 + Parent uint32 + Priority uint16 // lower is higher priority + Protocol uint16 // syscall.ETH_P_* +} + +func (q FilterAttrs) String() string { + return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Priority: %d, Protocol: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Priority, q.Protocol) +} + +// U32 filters on many packet related properties +type U32 struct { + FilterAttrs + // Currently only supports redirecting to another interface + RedirIndex int +} + +func (filter *U32) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *U32) Type() string { + return "u32" +} + +type FilterFwAttrs struct { + ClassId uint32 + InDev string + Mask uint32 + Index uint32 + Buffer uint32 + Mtu uint32 + Mpu uint16 + Rate uint32 + AvRate uint32 + PeakRate uint32 + Action int + Overhead uint16 + LinkLayer int +} + +// FwFilter filters on firewall marks +type Fw struct { + FilterAttrs + ClassId uint32 + Police nl.TcPolice + InDev string + // TODO Action + Mask uint32 + AvRate uint32 + Rtab [256]uint32 + Ptab [256]uint32 +} + +func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) { + var rtab [256]uint32 + var ptab [256]uint32 + rcell_log := -1 + pcell_log := -1 + avrate := fattrs.AvRate / 8 + police := nl.TcPolice{} + police.Rate.Rate = fattrs.Rate / 8 + police.PeakRate.Rate = fattrs.PeakRate / 8 + buffer := fattrs.Buffer + linklayer := nl.LINKLAYER_ETHERNET + + if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC { + linklayer = fattrs.LinkLayer + } + + police.Action = int32(fattrs.Action) + if police.Rate.Rate != 0 { + police.Rate.Mpu = fattrs.Mpu + police.Rate.Overhead = fattrs.Overhead + if CalcRtable(&police.Rate, rtab, rcell_log, fattrs.Mtu, linklayer) < 0 { + return nil, errors.New("TBF: failed to calculate rate table.") + } + police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer))) + } + police.Mtu = fattrs.Mtu + if police.PeakRate.Rate != 0 { + police.PeakRate.Mpu = fattrs.Mpu + police.PeakRate.Overhead = fattrs.Overhead + if CalcRtable(&police.PeakRate, ptab, pcell_log, fattrs.Mtu, linklayer) < 0 { + return nil, errors.New("POLICE: failed to calculate peak rate table.") + } + } + + return &Fw{ + FilterAttrs: attrs, + ClassId: fattrs.ClassId, + InDev: fattrs.InDev, + Mask: fattrs.Mask, + Police: police, + AvRate: avrate, + Rtab: rtab, + Ptab: ptab, + }, nil +} + +func (filter *Fw) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *Fw) Type() string { + return "fw" +} + +// GenericFilter filters represent types that are not currently understood +// by this netlink library. +type GenericFilter struct { + FilterAttrs + FilterType string +} + +func (filter *GenericFilter) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *GenericFilter) Type() string { + return filter.FilterType +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_linux.go new file mode 100644 index 0000000000..1dc688b124 --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_linux.go @@ -0,0 +1,322 @@ +package netlink + +import ( + "bytes" + "encoding/binary" + "fmt" + "syscall" + + "github.com/vishvananda/netlink/nl" +) + +// FilterDel will delete a filter from the system. +// Equivalent to: `tc filter del $filter` +func FilterDel(filter Filter) error { + req := nl.NewNetlinkRequest(syscall.RTM_DELTFILTER, syscall.NLM_F_ACK) + base := filter.Attrs() + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: int32(base.LinkIndex), + Handle: base.Handle, + Parent: base.Parent, + Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), + } + req.AddData(msg) + + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + +// FilterAdd will add a filter to the system. +// Equivalent to: `tc filter add $filter` +func FilterAdd(filter Filter) error { + native = nl.NativeEndian() + req := nl.NewNetlinkRequest(syscall.RTM_NEWTFILTER, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) + base := filter.Attrs() + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: int32(base.LinkIndex), + Handle: base.Handle, + Parent: base.Parent, + Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), + } + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type()))) + + options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) + if u32, ok := filter.(*U32); ok { + // match all + sel := nl.TcU32Sel{ + Nkeys: 1, + Flags: nl.TC_U32_TERMINAL, + } + sel.Keys = append(sel.Keys, nl.TcU32Key{}) + nl.NewRtAttrChild(options, nl.TCA_U32_SEL, sel.Serialize()) + actions := nl.NewRtAttrChild(options, nl.TCA_U32_ACT, nil) + table := nl.NewRtAttrChild(actions, nl.TCA_ACT_TAB, nil) + nl.NewRtAttrChild(table, nl.TCA_KIND, nl.ZeroTerminated("mirred")) + // redirect to other interface + mir := nl.TcMirred{ + Action: nl.TC_ACT_STOLEN, + Eaction: nl.TCA_EGRESS_REDIR, + Ifindex: uint32(u32.RedirIndex), + } + aopts := nl.NewRtAttrChild(table, nl.TCA_OPTIONS, nil) + nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, mir.Serialize()) + } else if fw, ok := filter.(*Fw); ok { + if fw.Mask != 0 { + b := make([]byte, 4) + native.PutUint32(b, fw.Mask) + nl.NewRtAttrChild(options, nl.TCA_FW_MASK, b) + } + if fw.InDev != "" { + nl.NewRtAttrChild(options, nl.TCA_FW_INDEV, nl.ZeroTerminated(fw.InDev)) + } + if (fw.Police != nl.TcPolice{}) { + + police := nl.NewRtAttrChild(options, nl.TCA_FW_POLICE, nil) + nl.NewRtAttrChild(police, nl.TCA_POLICE_TBF, fw.Police.Serialize()) + if (fw.Police.Rate != nl.TcRateSpec{}) { + payload := SerializeRtab(fw.Rtab) + nl.NewRtAttrChild(police, nl.TCA_POLICE_RATE, payload) + } + if (fw.Police.PeakRate != nl.TcRateSpec{}) { + payload := SerializeRtab(fw.Ptab) + nl.NewRtAttrChild(police, nl.TCA_POLICE_PEAKRATE, payload) + } + } + if fw.ClassId != 0 { + b := make([]byte, 4) + native.PutUint32(b, fw.ClassId) + nl.NewRtAttrChild(options, nl.TCA_FW_CLASSID, b) + } + } + + req.AddData(options) + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + +// FilterList gets a list of filters in the system. +// Equivalent to: `tc filter show`. +// Generally retunrs nothing if link and parent are not specified. +func FilterList(link Link, parent uint32) ([]Filter, error) { + req := nl.NewNetlinkRequest(syscall.RTM_GETTFILTER, syscall.NLM_F_DUMP) + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Parent: parent, + } + if link != nil { + base := link.Attrs() + ensureIndex(base) + msg.Ifindex = int32(base.Index) + } + req.AddData(msg) + + msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWTFILTER) + if err != nil { + return nil, err + } + + var res []Filter + for _, m := range msgs { + msg := nl.DeserializeTcMsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + base := FilterAttrs{ + LinkIndex: int(msg.Ifindex), + Handle: msg.Handle, + Parent: msg.Parent, + } + base.Priority, base.Protocol = MajorMinor(msg.Info) + base.Protocol = nl.Swap16(base.Protocol) + + var filter Filter + filterType := "" + detailed := false + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.TCA_KIND: + filterType = string(attr.Value[:len(attr.Value)-1]) + switch filterType { + case "u32": + filter = &U32{} + case "fw": + filter = &Fw{} + default: + filter = &GenericFilter{FilterType: filterType} + } + case nl.TCA_OPTIONS: + switch filterType { + case "u32": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + detailed, err = parseU32Data(filter, data) + if err != nil { + return nil, err + } + case "fw": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + detailed, err = parseFwData(filter, data) + if err != nil { + return nil, err + } + } + } + } + // only return the detailed version of the filter + if detailed { + *filter.Attrs() = base + res = append(res, filter) + } + } + + return res, nil +} + +func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { + native = nl.NativeEndian() + u32 := filter.(*U32) + detailed := false + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_U32_SEL: + detailed = true + sel := nl.DeserializeTcU32Sel(datum.Value) + // only parse if we have a very basic redirect + if sel.Flags&nl.TC_U32_TERMINAL == 0 || sel.Nkeys != 1 { + return detailed, nil + } + case nl.TCA_U32_ACT: + table, err := nl.ParseRouteAttr(datum.Value) + if err != nil { + return detailed, err + } + if len(table) != 1 || table[0].Attr.Type != nl.TCA_ACT_TAB { + return detailed, fmt.Errorf("Action table not formed properly") + } + aattrs, err := nl.ParseRouteAttr(table[0].Value) + for _, aattr := range aattrs { + switch aattr.Attr.Type { + case nl.TCA_KIND: + actionType := string(aattr.Value[:len(aattr.Value)-1]) + // only parse if the action is mirred + if actionType != "mirred" { + return detailed, nil + } + case nl.TCA_OPTIONS: + adata, err := nl.ParseRouteAttr(aattr.Value) + if err != nil { + return detailed, err + } + for _, adatum := range adata { + switch adatum.Attr.Type { + case nl.TCA_MIRRED_PARMS: + mir := nl.DeserializeTcMirred(adatum.Value) + u32.RedirIndex = int(mir.Ifindex) + } + } + } + } + } + } + return detailed, nil +} + +func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { + native = nl.NativeEndian() + fw := filter.(*Fw) + detailed := true + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_FW_MASK: + fw.Mask = native.Uint32(datum.Value[0:4]) + case nl.TCA_FW_CLASSID: + fw.ClassId = native.Uint32(datum.Value[0:4]) + case nl.TCA_FW_INDEV: + fw.InDev = string(datum.Value[:len(datum.Value)-1]) + case nl.TCA_FW_POLICE: + adata, _ := nl.ParseRouteAttr(datum.Value) + for _, aattr := range adata { + switch aattr.Attr.Type { + case nl.TCA_POLICE_TBF: + fw.Police = *nl.DeserializeTcPolice(aattr.Value) + case nl.TCA_POLICE_RATE: + fw.Rtab = DeserializeRtab(aattr.Value) + case nl.TCA_POLICE_PEAKRATE: + fw.Ptab = DeserializeRtab(aattr.Value) + } + } + } + } + return detailed, nil +} + +func AlignToAtm(size uint) uint { + var linksize, cells int + cells = int(size / nl.ATM_CELL_PAYLOAD) + if (size % nl.ATM_CELL_PAYLOAD) > 0 { + cells++ + } + linksize = cells * nl.ATM_CELL_SIZE + return uint(linksize) +} + +func AdjustSize(sz uint, mpu uint, linklayer int) uint { + if sz < mpu { + sz = mpu + } + switch linklayer { + case nl.LINKLAYER_ATM: + return AlignToAtm(sz) + default: + return sz + } +} + +func CalcRtable(rate *nl.TcRateSpec, rtab [256]uint32, cell_log int, mtu uint32, linklayer int) int { + bps := rate.Rate + mpu := rate.Mpu + var sz uint + if mtu == 0 { + mtu = 2047 + } + if cell_log < 0 { + cell_log = 0 + for (mtu >> uint(cell_log)) > 255 { + cell_log++ + } + } + for i := 0; i < 256; i++ { + sz = AdjustSize(uint((i+1)< syscall.IFF_TAP { + return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode) + } + file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0) + if err != nil { + return err + } + defer file.Close() + var req ifReq + req.Flags |= syscall.IFF_ONE_QUEUE + req.Flags |= syscall.IFF_TUN_EXCL + copy(req.Name[:15], base.Name) + req.Flags |= uint16(tuntap.Mode) + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req))) + if errno != 0 { + return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno) + } + _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETPERSIST), 1) + if errno != 0 { + return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno) + } + ensureIndex(base) + + // can't set master during create, so set it afterwards + if base.MasterIndex != 0 { + // TODO: verify MasterIndex is actually a bridge? + return LinkSetMasterByIndex(link, base.MasterIndex) + } + return nil + } + req := nl.NewNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) @@ -493,6 +533,8 @@ func linkDeserialize(m []byte) (Link, error) { switch linkType { case "dummy": link = &Dummy{} + case "ifb": + link = &Ifb{} case "bridge": link = &Bridge{} case "vlan": @@ -505,8 +547,10 @@ func linkDeserialize(m []byte) (Link, error) { link = &IPVlan{} case "macvlan": link = &Macvlan{} + case "macvtap": + link = &Macvtap{} default: - link = &Generic{LinkType: linkType} + link = &GenericLink{LinkType: linkType} } case nl.IFLA_INFO_DATA: data, err := nl.ParseRouteAttr(info.Value) @@ -522,6 +566,8 @@ func linkDeserialize(m []byte) (Link, error) { parseIPVlanData(link, data) case "macvlan": parseMacvlanData(link, data) + case "macvtap": + parseMacvtapData(link, data) } } } @@ -583,6 +629,46 @@ func LinkList() ([]Link, error) { return res, nil } +// LinkUpdate is used to pass information back from LinkSubscribe() +type LinkUpdate struct { + nl.IfInfomsg + Link +} + +// LinkSubscribe takes a chan down which notifications will be sent +// when links change. Close the 'done' chan to stop subscription. +func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error { + s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK) + if err != nil { + return err + } + if done != nil { + go func() { + <-done + s.Close() + }() + } + go func() { + defer close(ch) + for { + msgs, err := s.Receive() + if err != nil { + return + } + for _, m := range msgs { + ifmsg := nl.DeserializeIfInfomsg(m.Data) + link, err := linkDeserialize(m.Data) + if err != nil { + return + } + ch <- LinkUpdate{IfInfomsg: *ifmsg, Link: link} + } + } + }() + + return nil +} + func LinkSetHairpin(link Link, mode bool) error { return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_MODE) } @@ -696,6 +782,11 @@ func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) { } } +func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) { + macv := link.(*Macvtap) + parseMacvlanData(&macv.Macvlan, data) +} + func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { macv := link.(*Macvlan) for _, datum := range data { diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go deleted file mode 100644 index 9e44f0d0c9..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go +++ /dev/null @@ -1,643 +0,0 @@ -package netlink - -import ( - "bytes" - "net" - "testing" - - "github.com/vishvananda/netns" -) - -const ( - testTxQLen int = 100 - defaultTxQLen int = 1000 -) - -func testLinkAddDel(t *testing.T, link Link) { - links, err := LinkList() - if err != nil { - t.Fatal(err) - } - num := len(links) - - if err := LinkAdd(link); err != nil { - t.Fatal(err) - } - - base := link.Attrs() - - result, err := LinkByName(base.Name) - if err != nil { - t.Fatal(err) - } - - rBase := result.Attrs() - - if vlan, ok := link.(*Vlan); ok { - other, ok := result.(*Vlan) - if !ok { - t.Fatal("Result of create is not a vlan") - } - if vlan.VlanId != other.VlanId { - t.Fatal("Link.VlanId id doesn't match") - } - } - - if rBase.ParentIndex == 0 && base.ParentIndex != 0 { - t.Fatal("Created link doesn't have a Parent but it should") - } else if rBase.ParentIndex != 0 && base.ParentIndex == 0 { - t.Fatal("Created link has a Parent but it shouldn't") - } else if rBase.ParentIndex != 0 && base.ParentIndex != 0 { - if rBase.ParentIndex != base.ParentIndex { - t.Fatal("Link.ParentIndex doesn't match") - } - } - - if veth, ok := result.(*Veth); ok { - if rBase.TxQLen != base.TxQLen { - t.Fatalf("qlen is %d, should be %d", rBase.TxQLen, base.TxQLen) - } - if rBase.MTU != base.MTU { - t.Fatalf("MTU is %d, should be %d", rBase.MTU, base.MTU) - } - - if veth.PeerName != "" { - var peer *Veth - other, err := LinkByName(veth.PeerName) - if err != nil { - t.Fatalf("Peer %s not created", veth.PeerName) - } - if peer, ok = other.(*Veth); !ok { - t.Fatalf("Peer %s is incorrect type", veth.PeerName) - } - if peer.TxQLen != testTxQLen { - t.Fatalf("TxQLen of peer is %d, should be %d", peer.TxQLen, testTxQLen) - } - } - } - - if vxlan, ok := link.(*Vxlan); ok { - other, ok := result.(*Vxlan) - if !ok { - t.Fatal("Result of create is not a vxlan") - } - compareVxlan(t, vxlan, other) - } - - if ipv, ok := link.(*IPVlan); ok { - other, ok := result.(*IPVlan) - if !ok { - t.Fatal("Result of create is not a ipvlan") - } - if ipv.Mode != other.Mode { - t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, ipv.Mode) - } - } - - if macv, ok := link.(*Macvlan); ok { - other, ok := result.(*Macvlan) - if !ok { - t.Fatal("Result of create is not a macvlan") - } - if macv.Mode != other.Mode { - t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, macv.Mode) - } - } - - if err = LinkDel(link); err != nil { - t.Fatal(err) - } - - links, err = LinkList() - if err != nil { - t.Fatal(err) - } - - if len(links) != num { - t.Fatal("Link not removed properly") - } -} - -func compareVxlan(t *testing.T, expected, actual *Vxlan) { - - if actual.VxlanId != expected.VxlanId { - t.Fatal("Vxlan.VxlanId doesn't match") - } - if expected.SrcAddr != nil && !actual.SrcAddr.Equal(expected.SrcAddr) { - t.Fatal("Vxlan.SrcAddr doesn't match") - } - if expected.Group != nil && !actual.Group.Equal(expected.Group) { - t.Fatal("Vxlan.Group doesn't match") - } - if expected.TTL != -1 && actual.TTL != expected.TTL { - t.Fatal("Vxlan.TTL doesn't match") - } - if expected.TOS != -1 && actual.TOS != expected.TOS { - t.Fatal("Vxlan.TOS doesn't match") - } - if actual.Learning != expected.Learning { - t.Fatal("Vxlan.Learning doesn't match") - } - if actual.Proxy != expected.Proxy { - t.Fatal("Vxlan.Proxy doesn't match") - } - if actual.RSC != expected.RSC { - t.Fatal("Vxlan.RSC doesn't match") - } - if actual.L2miss != expected.L2miss { - t.Fatal("Vxlan.L2miss doesn't match") - } - if actual.L3miss != expected.L3miss { - t.Fatal("Vxlan.L3miss doesn't match") - } - if actual.GBP != expected.GBP { - t.Fatal("Vxlan.GBP doesn't match") - } - if expected.NoAge { - if !actual.NoAge { - t.Fatal("Vxlan.NoAge doesn't match") - } - } else if expected.Age > 0 && actual.Age != expected.Age { - t.Fatal("Vxlan.Age doesn't match") - } - if expected.Limit > 0 && actual.Limit != expected.Limit { - t.Fatal("Vxlan.Limit doesn't match") - } - if expected.Port > 0 && actual.Port != expected.Port { - t.Fatal("Vxlan.Port doesn't match") - } - if expected.PortLow > 0 || expected.PortHigh > 0 { - if actual.PortLow != expected.PortLow { - t.Fatal("Vxlan.PortLow doesn't match") - } - if actual.PortHigh != expected.PortHigh { - t.Fatal("Vxlan.PortHigh doesn't match") - } - } -} - -func TestLinkAddDelDummy(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - testLinkAddDel(t, &Dummy{LinkAttrs{Name: "foo"}}) -} - -func TestLinkAddDelBridge(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - testLinkAddDel(t, &Bridge{LinkAttrs{Name: "foo", MTU: 1400}}) -} - -func TestLinkAddDelVlan(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - parent := &Dummy{LinkAttrs{Name: "foo"}} - if err := LinkAdd(parent); err != nil { - t.Fatal(err) - } - - testLinkAddDel(t, &Vlan{LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}, 900}) - - if err := LinkDel(parent); err != nil { - t.Fatal(err) - } -} - -func TestLinkAddDelMacvlan(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - parent := &Dummy{LinkAttrs{Name: "foo"}} - if err := LinkAdd(parent); err != nil { - t.Fatal(err) - } - - testLinkAddDel(t, &Macvlan{ - LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}, - Mode: MACVLAN_MODE_PRIVATE, - }) - - if err := LinkDel(parent); err != nil { - t.Fatal(err) - } -} - -func TestLinkAddDelVeth(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - testLinkAddDel(t, &Veth{LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1400}, "bar"}) -} - -func TestLinkAddVethWithDefaultTxQLen(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - la := NewLinkAttrs() - la.Name = "foo" - - veth := &Veth{LinkAttrs: la, PeerName: "bar"} - if err := LinkAdd(veth); err != nil { - t.Fatal(err) - } - link, err := LinkByName("foo") - if err != nil { - t.Fatal(err) - } - if veth, ok := link.(*Veth); !ok { - t.Fatalf("unexpected link type: %T", link) - } else { - if veth.TxQLen != defaultTxQLen { - t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, defaultTxQLen) - } - } - peer, err := LinkByName("bar") - if err != nil { - t.Fatal(err) - } - if veth, ok := peer.(*Veth); !ok { - t.Fatalf("unexpected link type: %T", link) - } else { - if veth.TxQLen != defaultTxQLen { - t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, defaultTxQLen) - } - } -} - -func TestLinkAddVethWithZeroTxQLen(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - la := NewLinkAttrs() - la.Name = "foo" - la.TxQLen = 0 - - veth := &Veth{LinkAttrs: la, PeerName: "bar"} - if err := LinkAdd(veth); err != nil { - t.Fatal(err) - } - link, err := LinkByName("foo") - if err != nil { - t.Fatal(err) - } - if veth, ok := link.(*Veth); !ok { - t.Fatalf("unexpected link type: %T", link) - } else { - if veth.TxQLen != 0 { - t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, 0) - } - } - peer, err := LinkByName("bar") - if err != nil { - t.Fatal(err) - } - if veth, ok := peer.(*Veth); !ok { - t.Fatalf("unexpected link type: %T", link) - } else { - if veth.TxQLen != 0 { - t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, 0) - } - } -} - -func TestLinkAddDummyWithTxQLen(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - la := NewLinkAttrs() - la.Name = "foo" - la.TxQLen = 1500 - - dummy := &Dummy{LinkAttrs: la} - if err := LinkAdd(dummy); err != nil { - t.Fatal(err) - } - link, err := LinkByName("foo") - if err != nil { - t.Fatal(err) - } - if dummy, ok := link.(*Dummy); !ok { - t.Fatalf("unexpected link type: %T", link) - } else { - if dummy.TxQLen != 1500 { - t.Fatalf("TxQLen is %d, should be %d", dummy.TxQLen, 1500) - } - } -} - -func TestLinkAddDelBridgeMaster(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - master := &Bridge{LinkAttrs{Name: "foo"}} - if err := LinkAdd(master); err != nil { - t.Fatal(err) - } - testLinkAddDel(t, &Dummy{LinkAttrs{Name: "bar", MasterIndex: master.Attrs().Index}}) - - if err := LinkDel(master); err != nil { - t.Fatal(err) - } -} - -func TestLinkSetUnsetResetMaster(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - master := &Bridge{LinkAttrs{Name: "foo"}} - if err := LinkAdd(master); err != nil { - t.Fatal(err) - } - - newmaster := &Bridge{LinkAttrs{Name: "bar"}} - if err := LinkAdd(newmaster); err != nil { - t.Fatal(err) - } - - slave := &Dummy{LinkAttrs{Name: "baz"}} - if err := LinkAdd(slave); err != nil { - t.Fatal(err) - } - - if err := LinkSetMaster(slave, master); err != nil { - t.Fatal(err) - } - - link, err := LinkByName("baz") - if err != nil { - t.Fatal(err) - } - - if link.Attrs().MasterIndex != master.Attrs().Index { - t.Fatal("Master not set properly") - } - - if err := LinkSetMaster(slave, newmaster); err != nil { - t.Fatal(err) - } - - link, err = LinkByName("baz") - if err != nil { - t.Fatal(err) - } - - if link.Attrs().MasterIndex != newmaster.Attrs().Index { - t.Fatal("Master not reset properly") - } - - if err := LinkSetMaster(slave, nil); err != nil { - t.Fatal(err) - } - - link, err = LinkByName("baz") - if err != nil { - t.Fatal(err) - } - - if link.Attrs().MasterIndex != 0 { - t.Fatal("Master not unset properly") - } - if err := LinkDel(slave); err != nil { - t.Fatal(err) - } - - if err := LinkDel(newmaster); err != nil { - t.Fatal(err) - } - - if err := LinkDel(master); err != nil { - t.Fatal(err) - } -} - -func TestLinkSetNs(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - basens, err := netns.Get() - if err != nil { - t.Fatal("Failed to get basens") - } - defer basens.Close() - - newns, err := netns.New() - if err != nil { - t.Fatal("Failed to create newns") - } - defer newns.Close() - - link := &Veth{LinkAttrs{Name: "foo"}, "bar"} - if err := LinkAdd(link); err != nil { - t.Fatal(err) - } - - peer, err := LinkByName("bar") - if err != nil { - t.Fatal(err) - } - - LinkSetNsFd(peer, int(basens)) - if err != nil { - t.Fatal("Failed to set newns for link") - } - - _, err = LinkByName("bar") - if err == nil { - t.Fatal("Link bar is still in newns") - } - - err = netns.Set(basens) - if err != nil { - t.Fatal("Failed to set basens") - } - - peer, err = LinkByName("bar") - if err != nil { - t.Fatal("Link is not in basens") - } - - if err := LinkDel(peer); err != nil { - t.Fatal(err) - } - - err = netns.Set(newns) - if err != nil { - t.Fatal("Failed to set newns") - } - - _, err = LinkByName("foo") - if err == nil { - t.Fatal("Other half of veth pair not deleted") - } - -} - -func TestLinkAddDelVxlan(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - parent := &Dummy{ - LinkAttrs{Name: "foo"}, - } - if err := LinkAdd(parent); err != nil { - t.Fatal(err) - } - - vxlan := Vxlan{ - LinkAttrs: LinkAttrs{ - Name: "bar", - }, - VxlanId: 10, - VtepDevIndex: parent.Index, - Learning: true, - L2miss: true, - L3miss: true, - } - - testLinkAddDel(t, &vxlan) - if err := LinkDel(parent); err != nil { - t.Fatal(err) - } -} - -func TestLinkAddDelIPVlanL2(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - parent := &Dummy{LinkAttrs{Name: "foo"}} - if err := LinkAdd(parent); err != nil { - t.Fatal(err) - } - - ipv := IPVlan{ - LinkAttrs: LinkAttrs{ - Name: "bar", - ParentIndex: parent.Index, - }, - Mode: IPVLAN_MODE_L2, - } - - testLinkAddDel(t, &ipv) -} - -func TestLinkAddDelIPVlanL3(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - parent := &Dummy{LinkAttrs{Name: "foo"}} - if err := LinkAdd(parent); err != nil { - t.Fatal(err) - } - - ipv := IPVlan{ - LinkAttrs: LinkAttrs{ - Name: "bar", - ParentIndex: parent.Index, - }, - Mode: IPVLAN_MODE_L3, - } - - testLinkAddDel(t, &ipv) -} - -func TestLinkAddDelIPVlanNoParent(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - ipv := IPVlan{ - LinkAttrs: LinkAttrs{ - Name: "bar", - }, - Mode: IPVLAN_MODE_L3, - } - err := LinkAdd(&ipv) - if err == nil { - t.Fatal("Add should fail if ipvlan creating without ParentIndex") - } - if err.Error() != "Can't create ipvlan link without ParentIndex" { - t.Fatalf("Error should be about missing ParentIndex, got %q", err) - } -} - -func TestLinkByIndex(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - dummy := &Dummy{LinkAttrs{Name: "dummy"}} - if err := LinkAdd(dummy); err != nil { - t.Fatal(err) - } - - found, err := LinkByIndex(dummy.Index) - if err != nil { - t.Fatal(err) - } - - if found.Attrs().Index != dummy.Attrs().Index { - t.Fatalf("Indices don't match: %v != %v", found.Attrs().Index, dummy.Attrs().Index) - } - - LinkDel(dummy) - - // test not found - _, err = LinkByIndex(dummy.Attrs().Index) - if err == nil { - t.Fatalf("LinkByIndex(%v) found deleted link", err) - } -} - -func TestLinkSet(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - iface := &Dummy{LinkAttrs{Name: "foo"}} - if err := LinkAdd(iface); err != nil { - t.Fatal(err) - } - - link, err := LinkByName("foo") - if err != nil { - t.Fatal(err) - } - - err = LinkSetName(link, "bar") - if err != nil { - t.Fatalf("Could not change interface name: %v", err) - } - - link, err = LinkByName("bar") - if err != nil { - t.Fatalf("Interface name not changed: %v", err) - } - - err = LinkSetMTU(link, 1400) - if err != nil { - t.Fatalf("Could not set MTU: %v", err) - } - - link, err = LinkByName("bar") - if err != nil { - t.Fatal(err) - } - - if link.Attrs().MTU != 1400 { - t.Fatal("MTU not changed!") - } - - addr, err := net.ParseMAC("00:12:34:56:78:AB") - if err != nil { - t.Fatal(err) - } - - err = LinkSetHardwareAddr(link, addr) - if err != nil { - t.Fatal(err) - } - - link, err = LinkByName("bar") - if err != nil { - t.Fatal(err) - } - - if !bytes.Equal(link.Attrs().HardwareAddr, addr) { - t.Fatalf("hardware address not changed!") - } -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_tuntap_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_tuntap_linux.go new file mode 100644 index 0000000000..310bd33d8d --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_tuntap_linux.go @@ -0,0 +1,14 @@ +package netlink + +// ideally golang.org/x/sys/unix would define IfReq but it only has +// IFNAMSIZ, hence this minimalistic implementation +const ( + SizeOfIfReq = 40 + IFNAMSIZ = 16 +) + +type ifReq struct { + Name [IFNAMSIZ]byte + Flags uint16 + pad [SizeOfIfReq - IFNAMSIZ - 2]byte +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go deleted file mode 100644 index 50da59c5c5..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package netlink - -import ( - "net" - "testing" -) - -type arpEntry struct { - ip net.IP - mac net.HardwareAddr -} - -func parseMAC(s string) net.HardwareAddr { - m, err := net.ParseMAC(s) - if err != nil { - panic(err) - } - return m -} - -func dumpContains(dump []Neigh, e arpEntry) bool { - for _, n := range dump { - if n.IP.Equal(e.ip) && (n.State&NUD_INCOMPLETE) == 0 { - return true - } - } - return false -} - -func TestNeighAddDel(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - dummy := Dummy{LinkAttrs{Name: "neigh0"}} - if err := LinkAdd(&dummy); err != nil { - t.Fatal(err) - } - - ensureIndex(dummy.Attrs()) - - arpTable := []arpEntry{ - {net.ParseIP("10.99.0.1"), parseMAC("aa:bb:cc:dd:00:01")}, - {net.ParseIP("10.99.0.2"), parseMAC("aa:bb:cc:dd:00:02")}, - {net.ParseIP("10.99.0.3"), parseMAC("aa:bb:cc:dd:00:03")}, - {net.ParseIP("10.99.0.4"), parseMAC("aa:bb:cc:dd:00:04")}, - {net.ParseIP("10.99.0.5"), parseMAC("aa:bb:cc:dd:00:05")}, - } - - // Add the arpTable - for _, entry := range arpTable { - err := NeighAdd(&Neigh{ - LinkIndex: dummy.Index, - State: NUD_REACHABLE, - IP: entry.ip, - HardwareAddr: entry.mac, - }) - - if err != nil { - t.Errorf("Failed to NeighAdd: %v", err) - } - } - - // Dump and see that all added entries are there - dump, err := NeighList(dummy.Index, 0) - if err != nil { - t.Errorf("Failed to NeighList: %v", err) - } - - for _, entry := range arpTable { - if !dumpContains(dump, entry) { - t.Errorf("Dump does not contain: %v", entry) - } - } - - // Delete the arpTable - for _, entry := range arpTable { - err := NeighDel(&Neigh{ - LinkIndex: dummy.Index, - IP: entry.ip, - HardwareAddr: entry.mac, - }) - - if err != nil { - t.Errorf("Failed to NeighDel: %v", err) - } - } - - // TODO: seems not working because of cache - //// Dump and see that none of deleted entries are there - //dump, err = NeighList(dummy.Index, 0) - //if err != nil { - //t.Errorf("Failed to NeighList: %v", err) - //} - - //for _, entry := range arpTable { - //if dumpContains(dump, entry) { - //t.Errorf("Dump contains: %v", entry) - //} - //} - - if err := LinkDel(&dummy); err != nil { - t.Fatal(err) - } -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go deleted file mode 100644 index 3292b750a9..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package netlink - -import ( - "log" - "os" - "runtime" - "testing" - - "github.com/vishvananda/netns" -) - -type tearDownNetlinkTest func() - -func setUpNetlinkTest(t *testing.T) tearDownNetlinkTest { - if os.Getuid() != 0 { - msg := "Skipped test because it requires root privileges." - log.Printf(msg) - t.Skip(msg) - } - - // new temporary namespace so we don't pollute the host - // lock thread since the namespace is thread local - runtime.LockOSThread() - var err error - ns, err := netns.New() - if err != nil { - t.Fatal("Failed to create newns", ns) - } - - return func() { - ns.Close() - runtime.UnlockOSThread() - } -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go deleted file mode 100644 index 98c3b211f3..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package nl - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "syscall" - "testing" -) - -func (msg *IfAddrmsg) write(b []byte) { - native := NativeEndian() - b[0] = msg.Family - b[1] = msg.Prefixlen - b[2] = msg.Flags - b[3] = msg.Scope - native.PutUint32(b[4:8], msg.Index) -} - -func (msg *IfAddrmsg) serializeSafe() []byte { - len := syscall.SizeofIfAddrmsg - b := make([]byte, len) - msg.write(b) - return b -} - -func deserializeIfAddrmsgSafe(b []byte) *IfAddrmsg { - var msg = IfAddrmsg{} - binary.Read(bytes.NewReader(b[0:syscall.SizeofIfAddrmsg]), NativeEndian(), &msg) - return &msg -} - -func TestIfAddrmsgDeserializeSerialize(t *testing.T) { - var orig = make([]byte, syscall.SizeofIfAddrmsg) - rand.Read(orig) - safemsg := deserializeIfAddrmsgSafe(orig) - msg := DeserializeIfAddrmsg(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go index 3cb137d01b..8dbd92b819 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go @@ -142,7 +142,7 @@ func (a *RtAttr) Len() int { } // Serialize the RtAttr into a byte array -// This can't ust unsafe.cast because it must iterate through children. +// This can't just unsafe.cast because it must iterate through children. func (a *RtAttr) Serialize() []byte { native := NativeEndian() diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go deleted file mode 100644 index 4672684c7a..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package nl - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "reflect" - "syscall" - "testing" -) - -type testSerializer interface { - serializeSafe() []byte - Serialize() []byte -} - -func testDeserializeSerialize(t *testing.T, orig []byte, safemsg testSerializer, msg testSerializer) { - if !reflect.DeepEqual(safemsg, msg) { - t.Fatal("Deserialization failed.\n", safemsg, "\n", msg) - } - safe := msg.serializeSafe() - if !bytes.Equal(safe, orig) { - t.Fatal("Safe serialization failed.\n", safe, "\n", orig) - } - b := msg.Serialize() - if !bytes.Equal(b, safe) { - t.Fatal("Serialization failed.\n", b, "\n", safe) - } -} - -func (msg *IfInfomsg) write(b []byte) { - native := NativeEndian() - b[0] = msg.Family - b[1] = msg.X__ifi_pad - native.PutUint16(b[2:4], msg.Type) - native.PutUint32(b[4:8], uint32(msg.Index)) - native.PutUint32(b[8:12], msg.Flags) - native.PutUint32(b[12:16], msg.Change) -} - -func (msg *IfInfomsg) serializeSafe() []byte { - length := syscall.SizeofIfInfomsg - b := make([]byte, length) - msg.write(b) - return b -} - -func deserializeIfInfomsgSafe(b []byte) *IfInfomsg { - var msg = IfInfomsg{} - binary.Read(bytes.NewReader(b[0:syscall.SizeofIfInfomsg]), NativeEndian(), &msg) - return &msg -} - -func TestIfInfomsgDeserializeSerialize(t *testing.T) { - var orig = make([]byte, syscall.SizeofIfInfomsg) - rand.Read(orig) - safemsg := deserializeIfInfomsgSafe(orig) - msg := DeserializeIfInfomsg(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go deleted file mode 100644 index ba9c410ee1..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package nl - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "syscall" - "testing" -) - -func (msg *RtMsg) write(b []byte) { - native := NativeEndian() - b[0] = msg.Family - b[1] = msg.Dst_len - b[2] = msg.Src_len - b[3] = msg.Tos - b[4] = msg.Table - b[5] = msg.Protocol - b[6] = msg.Scope - b[7] = msg.Type - native.PutUint32(b[8:12], msg.Flags) -} - -func (msg *RtMsg) serializeSafe() []byte { - len := syscall.SizeofRtMsg - b := make([]byte, len) - msg.write(b) - return b -} - -func deserializeRtMsgSafe(b []byte) *RtMsg { - var msg = RtMsg{} - binary.Read(bytes.NewReader(b[0:syscall.SizeofRtMsg]), NativeEndian(), &msg) - return &msg -} - -func TestRtMsgDeserializeSerialize(t *testing.T) { - var orig = make([]byte, syscall.SizeofRtMsg) - rand.Read(orig) - safemsg := deserializeRtMsgSafe(orig) - msg := DeserializeRtMsg(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/tc_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/tc_linux.go new file mode 100644 index 0000000000..4a32055d1a --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/tc_linux.go @@ -0,0 +1,508 @@ +package nl + +import ( + "unsafe" +) + +// LinkLayer +const ( + LINKLAYER_UNSPEC = iota + LINKLAYER_ETHERNET + LINKLAYER_ATM +) + +// ATM +const ( + ATM_CELL_PAYLOAD = 48 + ATM_CELL_SIZE = 53 +) + +const TC_LINKLAYER_MASK = 0x0F + +// Police +const ( + TCA_POLICE_UNSPEC = iota + TCA_POLICE_TBF + TCA_POLICE_RATE + TCA_POLICE_PEAKRATE + TCA_POLICE_AVRATE + TCA_POLICE_RESULT + TCA_POLICE_MAX = TCA_POLICE_RESULT +) + +// Message types +const ( + TCA_UNSPEC = iota + TCA_KIND + TCA_OPTIONS + TCA_STATS + TCA_XSTATS + TCA_RATE + TCA_FCNT + TCA_STATS2 + TCA_STAB + TCA_MAX = TCA_STAB +) + +const ( + TCA_ACT_TAB = 1 + TCAA_MAX = 1 +) + +const ( + TCA_PRIO_UNSPEC = iota + TCA_PRIO_MQ + TCA_PRIO_MAX = TCA_PRIO_MQ +) + +const ( + SizeofTcMsg = 0x14 + SizeofTcActionMsg = 0x04 + SizeofTcPrioMap = 0x14 + SizeofTcRateSpec = 0x0c + SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c + SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14 + SizeofTcHtbGlob = 0x14 + SizeofTcU32Key = 0x10 + SizeofTcU32Sel = 0x10 // without keys + SizeofTcMirred = 0x1c + SizeofTcPolice = 2*SizeofTcRateSpec + 0x20 +) + +// struct tcmsg { +// unsigned char tcm_family; +// unsigned char tcm__pad1; +// unsigned short tcm__pad2; +// int tcm_ifindex; +// __u32 tcm_handle; +// __u32 tcm_parent; +// __u32 tcm_info; +// }; + +type TcMsg struct { + Family uint8 + Pad [3]byte + Ifindex int32 + Handle uint32 + Parent uint32 + Info uint32 +} + +func (msg *TcMsg) Len() int { + return SizeofTcMsg +} + +func DeserializeTcMsg(b []byte) *TcMsg { + return (*TcMsg)(unsafe.Pointer(&b[0:SizeofTcMsg][0])) +} + +func (x *TcMsg) Serialize() []byte { + return (*(*[SizeofTcMsg]byte)(unsafe.Pointer(x)))[:] +} + +// struct tcamsg { +// unsigned char tca_family; +// unsigned char tca__pad1; +// unsigned short tca__pad2; +// }; + +type TcActionMsg struct { + Family uint8 + Pad [3]byte +} + +func (msg *TcActionMsg) Len() int { + return SizeofTcActionMsg +} + +func DeserializeTcActionMsg(b []byte) *TcActionMsg { + return (*TcActionMsg)(unsafe.Pointer(&b[0:SizeofTcActionMsg][0])) +} + +func (x *TcActionMsg) Serialize() []byte { + return (*(*[SizeofTcActionMsg]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TC_PRIO_MAX = 15 +) + +// struct tc_prio_qopt { +// int bands; /* Number of bands */ +// __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */ +// }; + +type TcPrioMap struct { + Bands int32 + Priomap [TC_PRIO_MAX + 1]uint8 +} + +func (msg *TcPrioMap) Len() int { + return SizeofTcPrioMap +} + +func DeserializeTcPrioMap(b []byte) *TcPrioMap { + return (*TcPrioMap)(unsafe.Pointer(&b[0:SizeofTcPrioMap][0])) +} + +func (x *TcPrioMap) Serialize() []byte { + return (*(*[SizeofTcPrioMap]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_TBF_UNSPEC = iota + TCA_TBF_PARMS + TCA_TBF_RTAB + TCA_TBF_PTAB + TCA_TBF_RATE64 + TCA_TBF_PRATE64 + TCA_TBF_BURST + TCA_TBF_PBURST + TCA_TBF_MAX = TCA_TBF_PBURST +) + +// struct tc_ratespec { +// unsigned char cell_log; +// __u8 linklayer; /* lower 4 bits */ +// unsigned short overhead; +// short cell_align; +// unsigned short mpu; +// __u32 rate; +// }; + +type TcRateSpec struct { + CellLog uint8 + Linklayer uint8 + Overhead uint16 + CellAlign int16 + Mpu uint16 + Rate uint32 +} + +func (msg *TcRateSpec) Len() int { + return SizeofTcRateSpec +} + +func DeserializeTcRateSpec(b []byte) *TcRateSpec { + return (*TcRateSpec)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0])) +} + +func (x *TcRateSpec) Serialize() []byte { + return (*(*[SizeofTcRateSpec]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_tbf_qopt { +// struct tc_ratespec rate; +// struct tc_ratespec peakrate; +// __u32 limit; +// __u32 buffer; +// __u32 mtu; +// }; + +type TcTbfQopt struct { + Rate TcRateSpec + Peakrate TcRateSpec + Limit uint32 + Buffer uint32 + Mtu uint32 +} + +func (msg *TcTbfQopt) Len() int { + return SizeofTcTbfQopt +} + +func DeserializeTcTbfQopt(b []byte) *TcTbfQopt { + return (*TcTbfQopt)(unsafe.Pointer(&b[0:SizeofTcTbfQopt][0])) +} + +func (x *TcTbfQopt) Serialize() []byte { + return (*(*[SizeofTcTbfQopt]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_HTB_UNSPEC = iota + TCA_HTB_PARMS + TCA_HTB_INIT + TCA_HTB_CTAB + TCA_HTB_RTAB + TCA_HTB_DIRECT_QLEN + TCA_HTB_RATE64 + TCA_HTB_CEIL64 + TCA_HTB_MAX = TCA_HTB_CEIL64 +) + +//struct tc_htb_opt { +// struct tc_ratespec rate; +// struct tc_ratespec ceil; +// __u32 buffer; +// __u32 cbuffer; +// __u32 quantum; +// __u32 level; /* out only */ +// __u32 prio; +//}; + +type TcHtbCopt struct { + Rate TcRateSpec + Ceil TcRateSpec + Buffer uint32 + Cbuffer uint32 + Quantum uint32 + Level uint32 + Prio uint32 +} + +func (msg *TcHtbCopt) Len() int { + return SizeofTcHtbCopt +} + +func DeserializeTcHtbCopt(b []byte) *TcHtbCopt { + return (*TcHtbCopt)(unsafe.Pointer(&b[0:SizeofTcHtbCopt][0])) +} + +func (x *TcHtbCopt) Serialize() []byte { + return (*(*[SizeofTcHtbCopt]byte)(unsafe.Pointer(x)))[:] +} + +type TcHtbGlob struct { + Version uint32 + Rate2Quantum uint32 + Defcls uint32 + Debug uint32 + DirectPkts uint32 +} + +func (msg *TcHtbGlob) Len() int { + return SizeofTcHtbGlob +} + +func DeserializeTcHtbGlob(b []byte) *TcHtbGlob { + return (*TcHtbGlob)(unsafe.Pointer(&b[0:SizeofTcHtbGlob][0])) +} + +func (x *TcHtbGlob) Serialize() []byte { + return (*(*[SizeofTcHtbGlob]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_U32_UNSPEC = iota + TCA_U32_CLASSID + TCA_U32_HASH + TCA_U32_LINK + TCA_U32_DIVISOR + TCA_U32_SEL + TCA_U32_POLICE + TCA_U32_ACT + TCA_U32_INDEV + TCA_U32_PCNT + TCA_U32_MARK + TCA_U32_MAX = TCA_U32_MARK +) + +// struct tc_u32_key { +// __be32 mask; +// __be32 val; +// int off; +// int offmask; +// }; + +type TcU32Key struct { + Mask uint32 // big endian + Val uint32 // big endian + Off int32 + OffMask int32 +} + +func (msg *TcU32Key) Len() int { + return SizeofTcU32Key +} + +func DeserializeTcU32Key(b []byte) *TcU32Key { + return (*TcU32Key)(unsafe.Pointer(&b[0:SizeofTcU32Key][0])) +} + +func (x *TcU32Key) Serialize() []byte { + return (*(*[SizeofTcU32Key]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_u32_sel { +// unsigned char flags; +// unsigned char offshift; +// unsigned char nkeys; +// +// __be16 offmask; +// __u16 off; +// short offoff; +// +// short hoff; +// __be32 hmask; +// struct tc_u32_key keys[0]; +// }; + +const ( + TC_U32_TERMINAL = 1 << iota + TC_U32_OFFSET = 1 << iota + TC_U32_VAROFFSET = 1 << iota + TC_U32_EAT = 1 << iota +) + +type TcU32Sel struct { + Flags uint8 + Offshift uint8 + Nkeys uint8 + Pad uint8 + Offmask uint16 // big endian + Off uint16 + Offoff int16 + Hoff int16 + Hmask uint32 // big endian + Keys []TcU32Key +} + +func (msg *TcU32Sel) Len() int { + return SizeofTcU32Sel + int(msg.Nkeys)*SizeofTcU32Key +} + +func DeserializeTcU32Sel(b []byte) *TcU32Sel { + x := &TcU32Sel{} + copy((*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:], b) + next := SizeofTcU32Sel + var i uint8 + for i = 0; i < x.Nkeys; i++ { + x.Keys = append(x.Keys, *DeserializeTcU32Key(b[next:])) + next += SizeofTcU32Key + } + return x +} + +func (x *TcU32Sel) Serialize() []byte { + // This can't just unsafe.cast because it must iterate through keys. + buf := make([]byte, x.Len()) + copy(buf, (*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:]) + next := SizeofTcU32Sel + for _, key := range x.Keys { + keyBuf := key.Serialize() + copy(buf[next:], keyBuf) + next += SizeofTcU32Key + } + return buf +} + +const ( + TCA_ACT_MIRRED = 8 +) + +const ( + TCA_MIRRED_UNSPEC = iota + TCA_MIRRED_TM + TCA_MIRRED_PARMS + TCA_MIRRED_MAX = TCA_MIRRED_PARMS +) + +const ( + TCA_EGRESS_REDIR = 1 /* packet redirect to EGRESS*/ + TCA_EGRESS_MIRROR = 2 /* mirror packet to EGRESS */ + TCA_INGRESS_REDIR = 3 /* packet redirect to INGRESS*/ + TCA_INGRESS_MIRROR = 4 /* mirror packet to INGRESS */ +) + +const ( + TC_ACT_UNSPEC = int32(-1) + TC_ACT_OK = 0 + TC_ACT_RECLASSIFY = 1 + TC_ACT_SHOT = 2 + TC_ACT_PIPE = 3 + TC_ACT_STOLEN = 4 + TC_ACT_QUEUED = 5 + TC_ACT_REPEAT = 6 + TC_ACT_JUMP = 0x10000000 +) + +// #define tc_gen \ +// __u32 index; \ +// __u32 capab; \ +// int action; \ +// int refcnt; \ +// int bindcnt +// struct tc_mirred { +// tc_gen; +// int eaction; /* one of IN/EGRESS_MIRROR/REDIR */ +// __u32 ifindex; /* ifindex of egress port */ +// }; + +type TcMirred struct { + Index uint32 + Capab uint32 + Action int32 + Refcnt int32 + Bindcnt int32 + Eaction int32 + Ifindex uint32 +} + +func (msg *TcMirred) Len() int { + return SizeofTcMirred +} + +func DeserializeTcMirred(b []byte) *TcMirred { + return (*TcMirred)(unsafe.Pointer(&b[0:SizeofTcMirred][0])) +} + +func (x *TcMirred) Serialize() []byte { + return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TC_POLICE_UNSPEC = TC_ACT_UNSPEC + TC_POLICE_OK = TC_ACT_OK + TC_POLICE_RECLASSIFY = TC_ACT_RECLASSIFY + TC_POLICE_SHOT = TC_ACT_SHOT + TC_POLICE_PIPE = TC_ACT_PIPE +) + +// struct tc_police { +// __u32 index; +// int action; +// __u32 limit; +// __u32 burst; +// __u32 mtu; +// struct tc_ratespec rate; +// struct tc_ratespec peakrate; +// int refcnt; +// int bindcnt; +// __u32 capab; +// }; + +type TcPolice struct { + Index uint32 + Action int32 + Limit uint32 + Burst uint32 + Mtu uint32 + Rate TcRateSpec + PeakRate TcRateSpec + Refcnt int32 + Bindcnt int32 + Capab uint32 +} + +func (msg *TcPolice) Len() int { + return SizeofTcPolice +} + +func DeserializeTcPolice(b []byte) *TcPolice { + return (*TcPolice)(unsafe.Pointer(&b[0:SizeofTcPolice][0])) +} + +func (x *TcPolice) Serialize() []byte { + return (*(*[SizeofTcPolice]byte)(unsafe.Pointer(x)))[:] +} + +const ( + TCA_FW_UNSPEC = iota + TCA_FW_CLASSID + TCA_FW_POLICE + TCA_FW_INDEV + TCA_FW_ACT + TCA_FW_MASK + TCA_FW_MAX = TCA_FW_MASK +) diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go deleted file mode 100644 index 04404d7511..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package nl - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "testing" -) - -func (msg *XfrmAddress) write(b []byte) { - copy(b[0:SizeofXfrmAddress], msg[:]) -} - -func (msg *XfrmAddress) serializeSafe() []byte { - b := make([]byte, SizeofXfrmAddress) - msg.write(b) - return b -} - -func deserializeXfrmAddressSafe(b []byte) *XfrmAddress { - var msg = XfrmAddress{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmAddress]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmAddressDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmAddress) - rand.Read(orig) - safemsg := deserializeXfrmAddressSafe(orig) - msg := DeserializeXfrmAddress(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmSelector) write(b []byte) { - const AddrEnd = SizeofXfrmAddress * 2 - native := NativeEndian() - msg.Daddr.write(b[0:SizeofXfrmAddress]) - msg.Saddr.write(b[SizeofXfrmAddress:AddrEnd]) - native.PutUint16(b[AddrEnd:AddrEnd+2], msg.Dport) - native.PutUint16(b[AddrEnd+2:AddrEnd+4], msg.DportMask) - native.PutUint16(b[AddrEnd+4:AddrEnd+6], msg.Sport) - native.PutUint16(b[AddrEnd+6:AddrEnd+8], msg.SportMask) - native.PutUint16(b[AddrEnd+8:AddrEnd+10], msg.Family) - b[AddrEnd+10] = msg.PrefixlenD - b[AddrEnd+11] = msg.PrefixlenS - b[AddrEnd+12] = msg.Proto - copy(b[AddrEnd+13:AddrEnd+16], msg.Pad[:]) - native.PutUint32(b[AddrEnd+16:AddrEnd+20], uint32(msg.Ifindex)) - native.PutUint32(b[AddrEnd+20:AddrEnd+24], msg.User) -} - -func (msg *XfrmSelector) serializeSafe() []byte { - length := SizeofXfrmSelector - b := make([]byte, length) - msg.write(b) - return b -} - -func deserializeXfrmSelectorSafe(b []byte) *XfrmSelector { - var msg = XfrmSelector{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmSelector]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmSelectorDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmSelector) - rand.Read(orig) - safemsg := deserializeXfrmSelectorSafe(orig) - msg := DeserializeXfrmSelector(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmLifetimeCfg) write(b []byte) { - native := NativeEndian() - native.PutUint64(b[0:8], msg.SoftByteLimit) - native.PutUint64(b[8:16], msg.HardByteLimit) - native.PutUint64(b[16:24], msg.SoftPacketLimit) - native.PutUint64(b[24:32], msg.HardPacketLimit) - native.PutUint64(b[32:40], msg.SoftAddExpiresSeconds) - native.PutUint64(b[40:48], msg.HardAddExpiresSeconds) - native.PutUint64(b[48:56], msg.SoftUseExpiresSeconds) - native.PutUint64(b[56:64], msg.HardUseExpiresSeconds) -} - -func (msg *XfrmLifetimeCfg) serializeSafe() []byte { - length := SizeofXfrmLifetimeCfg - b := make([]byte, length) - msg.write(b) - return b -} - -func deserializeXfrmLifetimeCfgSafe(b []byte) *XfrmLifetimeCfg { - var msg = XfrmLifetimeCfg{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmLifetimeCfg]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmLifetimeCfgDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmLifetimeCfg) - rand.Read(orig) - safemsg := deserializeXfrmLifetimeCfgSafe(orig) - msg := DeserializeXfrmLifetimeCfg(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmLifetimeCur) write(b []byte) { - native := NativeEndian() - native.PutUint64(b[0:8], msg.Bytes) - native.PutUint64(b[8:16], msg.Packets) - native.PutUint64(b[16:24], msg.AddTime) - native.PutUint64(b[24:32], msg.UseTime) -} - -func (msg *XfrmLifetimeCur) serializeSafe() []byte { - length := SizeofXfrmLifetimeCur - b := make([]byte, length) - msg.write(b) - return b -} - -func deserializeXfrmLifetimeCurSafe(b []byte) *XfrmLifetimeCur { - var msg = XfrmLifetimeCur{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmLifetimeCur]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmLifetimeCurDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmLifetimeCur) - rand.Read(orig) - safemsg := deserializeXfrmLifetimeCurSafe(orig) - msg := DeserializeXfrmLifetimeCur(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmId) write(b []byte) { - native := NativeEndian() - msg.Daddr.write(b[0:SizeofXfrmAddress]) - native.PutUint32(b[SizeofXfrmAddress:SizeofXfrmAddress+4], msg.Spi) - b[SizeofXfrmAddress+4] = msg.Proto - copy(b[SizeofXfrmAddress+5:SizeofXfrmAddress+8], msg.Pad[:]) -} - -func (msg *XfrmId) serializeSafe() []byte { - b := make([]byte, SizeofXfrmId) - msg.write(b) - return b -} - -func deserializeXfrmIdSafe(b []byte) *XfrmId { - var msg = XfrmId{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmId]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmIdDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmId) - rand.Read(orig) - safemsg := deserializeXfrmIdSafe(orig) - msg := DeserializeXfrmId(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go deleted file mode 100644 index 08a604b9cc..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package nl - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "testing" -) - -func (msg *XfrmUserpolicyId) write(b []byte) { - native := NativeEndian() - msg.Sel.write(b[0:SizeofXfrmSelector]) - native.PutUint32(b[SizeofXfrmSelector:SizeofXfrmSelector+4], msg.Index) - b[SizeofXfrmSelector+4] = msg.Dir - copy(b[SizeofXfrmSelector+5:SizeofXfrmSelector+8], msg.Pad[:]) -} - -func (msg *XfrmUserpolicyId) serializeSafe() []byte { - b := make([]byte, SizeofXfrmUserpolicyId) - msg.write(b) - return b -} - -func deserializeXfrmUserpolicyIdSafe(b []byte) *XfrmUserpolicyId { - var msg = XfrmUserpolicyId{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmUserpolicyId]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmUserpolicyIdDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmUserpolicyId) - rand.Read(orig) - safemsg := deserializeXfrmUserpolicyIdSafe(orig) - msg := DeserializeXfrmUserpolicyId(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmUserpolicyInfo) write(b []byte) { - const CfgEnd = SizeofXfrmSelector + SizeofXfrmLifetimeCfg - const CurEnd = CfgEnd + SizeofXfrmLifetimeCur - native := NativeEndian() - msg.Sel.write(b[0:SizeofXfrmSelector]) - msg.Lft.write(b[SizeofXfrmSelector:CfgEnd]) - msg.Curlft.write(b[CfgEnd:CurEnd]) - native.PutUint32(b[CurEnd:CurEnd+4], msg.Priority) - native.PutUint32(b[CurEnd+4:CurEnd+8], msg.Index) - b[CurEnd+8] = msg.Dir - b[CurEnd+9] = msg.Action - b[CurEnd+10] = msg.Flags - b[CurEnd+11] = msg.Share - copy(b[CurEnd+12:CurEnd+16], msg.Pad[:]) -} - -func (msg *XfrmUserpolicyInfo) serializeSafe() []byte { - b := make([]byte, SizeofXfrmUserpolicyInfo) - msg.write(b) - return b -} - -func deserializeXfrmUserpolicyInfoSafe(b []byte) *XfrmUserpolicyInfo { - var msg = XfrmUserpolicyInfo{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmUserpolicyInfo]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmUserpolicyInfoDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmUserpolicyInfo) - rand.Read(orig) - safemsg := deserializeXfrmUserpolicyInfoSafe(orig) - msg := DeserializeXfrmUserpolicyInfo(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmUserTmpl) write(b []byte) { - const AddrEnd = SizeofXfrmId + 4 + SizeofXfrmAddress - native := NativeEndian() - msg.XfrmId.write(b[0:SizeofXfrmId]) - native.PutUint16(b[SizeofXfrmId:SizeofXfrmId+2], msg.Family) - copy(b[SizeofXfrmId+2:SizeofXfrmId+4], msg.Pad1[:]) - msg.Saddr.write(b[SizeofXfrmId+4 : AddrEnd]) - native.PutUint32(b[AddrEnd:AddrEnd+4], msg.Reqid) - b[AddrEnd+4] = msg.Mode - b[AddrEnd+5] = msg.Share - b[AddrEnd+6] = msg.Optional - b[AddrEnd+7] = msg.Pad2 - native.PutUint32(b[AddrEnd+8:AddrEnd+12], msg.Aalgos) - native.PutUint32(b[AddrEnd+12:AddrEnd+16], msg.Ealgos) - native.PutUint32(b[AddrEnd+16:AddrEnd+20], msg.Calgos) -} - -func (msg *XfrmUserTmpl) serializeSafe() []byte { - b := make([]byte, SizeofXfrmUserTmpl) - msg.write(b) - return b -} - -func deserializeXfrmUserTmplSafe(b []byte) *XfrmUserTmpl { - var msg = XfrmUserTmpl{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmUserTmpl]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmUserTmplDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmUserTmpl) - rand.Read(orig) - safemsg := deserializeXfrmUserTmplSafe(orig) - msg := DeserializeXfrmUserTmpl(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go deleted file mode 100644 index d5281e9a64..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go +++ /dev/null @@ -1,207 +0,0 @@ -package nl - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "testing" -) - -func (msg *XfrmUsersaId) write(b []byte) { - native := NativeEndian() - msg.Daddr.write(b[0:SizeofXfrmAddress]) - native.PutUint32(b[SizeofXfrmAddress:SizeofXfrmAddress+4], msg.Spi) - native.PutUint16(b[SizeofXfrmAddress+4:SizeofXfrmAddress+6], msg.Family) - b[SizeofXfrmAddress+6] = msg.Proto - b[SizeofXfrmAddress+7] = msg.Pad -} - -func (msg *XfrmUsersaId) serializeSafe() []byte { - b := make([]byte, SizeofXfrmUsersaId) - msg.write(b) - return b -} - -func deserializeXfrmUsersaIdSafe(b []byte) *XfrmUsersaId { - var msg = XfrmUsersaId{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmUsersaId]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmUsersaIdDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmUsersaId) - rand.Read(orig) - safemsg := deserializeXfrmUsersaIdSafe(orig) - msg := DeserializeXfrmUsersaId(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmStats) write(b []byte) { - native := NativeEndian() - native.PutUint32(b[0:4], msg.ReplayWindow) - native.PutUint32(b[4:8], msg.Replay) - native.PutUint32(b[8:12], msg.IntegrityFailed) -} - -func (msg *XfrmStats) serializeSafe() []byte { - b := make([]byte, SizeofXfrmStats) - msg.write(b) - return b -} - -func deserializeXfrmStatsSafe(b []byte) *XfrmStats { - var msg = XfrmStats{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmStats]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmStatsDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmStats) - rand.Read(orig) - safemsg := deserializeXfrmStatsSafe(orig) - msg := DeserializeXfrmStats(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmUsersaInfo) write(b []byte) { - const IdEnd = SizeofXfrmSelector + SizeofXfrmId - const AddressEnd = IdEnd + SizeofXfrmAddress - const CfgEnd = AddressEnd + SizeofXfrmLifetimeCfg - const CurEnd = CfgEnd + SizeofXfrmLifetimeCur - const StatsEnd = CurEnd + SizeofXfrmStats - native := NativeEndian() - msg.Sel.write(b[0:SizeofXfrmSelector]) - msg.Id.write(b[SizeofXfrmSelector:IdEnd]) - msg.Saddr.write(b[IdEnd:AddressEnd]) - msg.Lft.write(b[AddressEnd:CfgEnd]) - msg.Curlft.write(b[CfgEnd:CurEnd]) - msg.Stats.write(b[CurEnd:StatsEnd]) - native.PutUint32(b[StatsEnd:StatsEnd+4], msg.Seq) - native.PutUint32(b[StatsEnd+4:StatsEnd+8], msg.Reqid) - native.PutUint16(b[StatsEnd+8:StatsEnd+10], msg.Family) - b[StatsEnd+10] = msg.Mode - b[StatsEnd+11] = msg.ReplayWindow - b[StatsEnd+12] = msg.Flags - copy(b[StatsEnd+13:StatsEnd+20], msg.Pad[:]) -} - -func (msg *XfrmUsersaInfo) serializeSafe() []byte { - b := make([]byte, SizeofXfrmUsersaInfo) - msg.write(b) - return b -} - -func deserializeXfrmUsersaInfoSafe(b []byte) *XfrmUsersaInfo { - var msg = XfrmUsersaInfo{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmUsersaInfo]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmUsersaInfoDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmUsersaInfo) - rand.Read(orig) - safemsg := deserializeXfrmUsersaInfoSafe(orig) - msg := DeserializeXfrmUsersaInfo(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmAlgo) write(b []byte) { - native := NativeEndian() - copy(b[0:64], msg.AlgName[:]) - native.PutUint32(b[64:68], msg.AlgKeyLen) - copy(b[68:msg.Len()], msg.AlgKey[:]) -} - -func (msg *XfrmAlgo) serializeSafe() []byte { - b := make([]byte, msg.Len()) - msg.write(b) - return b -} - -func deserializeXfrmAlgoSafe(b []byte) *XfrmAlgo { - var msg = XfrmAlgo{} - copy(msg.AlgName[:], b[0:64]) - binary.Read(bytes.NewReader(b[64:68]), NativeEndian(), &msg.AlgKeyLen) - msg.AlgKey = b[68:msg.Len()] - return &msg -} - -func TestXfrmAlgoDeserializeSerialize(t *testing.T) { - // use a 32 byte key len - var orig = make([]byte, SizeofXfrmAlgo+32) - rand.Read(orig) - // set the key len to 256 bits - orig[64] = 0 - orig[65] = 1 - orig[66] = 0 - orig[67] = 0 - safemsg := deserializeXfrmAlgoSafe(orig) - msg := DeserializeXfrmAlgo(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmAlgoAuth) write(b []byte) { - native := NativeEndian() - copy(b[0:64], msg.AlgName[:]) - native.PutUint32(b[64:68], msg.AlgKeyLen) - native.PutUint32(b[68:72], msg.AlgTruncLen) - copy(b[72:msg.Len()], msg.AlgKey[:]) -} - -func (msg *XfrmAlgoAuth) serializeSafe() []byte { - b := make([]byte, msg.Len()) - msg.write(b) - return b -} - -func deserializeXfrmAlgoAuthSafe(b []byte) *XfrmAlgoAuth { - var msg = XfrmAlgoAuth{} - copy(msg.AlgName[:], b[0:64]) - binary.Read(bytes.NewReader(b[64:68]), NativeEndian(), &msg.AlgKeyLen) - binary.Read(bytes.NewReader(b[68:72]), NativeEndian(), &msg.AlgTruncLen) - msg.AlgKey = b[72:msg.Len()] - return &msg -} - -func TestXfrmAlgoAuthDeserializeSerialize(t *testing.T) { - // use a 32 byte key len - var orig = make([]byte, SizeofXfrmAlgoAuth+32) - rand.Read(orig) - // set the key len to 256 bits - orig[64] = 0 - orig[65] = 1 - orig[66] = 0 - orig[67] = 0 - safemsg := deserializeXfrmAlgoAuthSafe(orig) - msg := DeserializeXfrmAlgoAuth(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} - -func (msg *XfrmEncapTmpl) write(b []byte) { - native := NativeEndian() - native.PutUint16(b[0:2], msg.EncapType) - native.PutUint16(b[2:4], msg.EncapSport) - native.PutUint16(b[4:6], msg.EncapDport) - copy(b[6:8], msg.Pad[:]) - msg.EncapOa.write(b[8:SizeofXfrmAddress]) -} - -func (msg *XfrmEncapTmpl) serializeSafe() []byte { - b := make([]byte, SizeofXfrmEncapTmpl) - msg.write(b) - return b -} - -func deserializeXfrmEncapTmplSafe(b []byte) *XfrmEncapTmpl { - var msg = XfrmEncapTmpl{} - binary.Read(bytes.NewReader(b[0:SizeofXfrmEncapTmpl]), NativeEndian(), &msg) - return &msg -} - -func TestXfrmEncapTmplDeserializeSerialize(t *testing.T) { - var orig = make([]byte, SizeofXfrmEncapTmpl) - rand.Read(orig) - safemsg := deserializeXfrmEncapTmplSafe(orig) - msg := DeserializeXfrmEncapTmpl(orig) - testDeserializeSerialize(t, orig, safemsg, msg) -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go deleted file mode 100644 index f94c42b1c7..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package netlink - -import "testing" - -func TestProtinfo(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - master := &Bridge{LinkAttrs{Name: "foo"}} - if err := LinkAdd(master); err != nil { - t.Fatal(err) - } - iface1 := &Dummy{LinkAttrs{Name: "bar1", MasterIndex: master.Index}} - iface2 := &Dummy{LinkAttrs{Name: "bar2", MasterIndex: master.Index}} - iface3 := &Dummy{LinkAttrs{Name: "bar3"}} - - if err := LinkAdd(iface1); err != nil { - t.Fatal(err) - } - if err := LinkAdd(iface2); err != nil { - t.Fatal(err) - } - if err := LinkAdd(iface3); err != nil { - t.Fatal(err) - } - - oldpi1, err := LinkGetProtinfo(iface1) - if err != nil { - t.Fatal(err) - } - 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 !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 := LinkSetGuard(iface2, true); err != nil { - t.Fatal(err) - } - if err := LinkSetLearning(iface2, false); err != nil { - t.Fatal(err) - } - pi2, err := LinkGetProtinfo(iface2) - if err != nil { - t.Fatal(err) - } - if pi2.Hairpin { - t.Fatalf("Hairpin mode is enabled for %s, but shouldn't", iface2.Name) - } - if !pi2.Guard { - t.Fatalf("Guard is not enabled for %s, but should", iface2.Name) - } - 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 := 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) - } -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go new file mode 100644 index 0000000000..41a4aa8e3e --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go @@ -0,0 +1,167 @@ +package netlink + +import ( + "fmt" +) + +const ( + HANDLE_NONE = 0 + HANDLE_INGRESS = 0xFFFFFFF1 + HANDLE_ROOT = 0xFFFFFFFF + PRIORITY_MAP_LEN = 16 +) + +type Qdisc interface { + Attrs() *QdiscAttrs + Type() string +} + +// Qdisc represents a netlink qdisc. A qdisc is associated with a link, +// has a handle, a parent and a refcnt. The root qdisc of a device should +// have parent == HANDLE_ROOT. +type QdiscAttrs struct { + LinkIndex int + Handle uint32 + Parent uint32 + Refcnt uint32 // read only +} + +func (q QdiscAttrs) String() string { + return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Refcnt: %s}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Refcnt) +} + +func MakeHandle(major, minor uint16) uint32 { + return (uint32(major) << 16) | uint32(minor) +} + +func MajorMinor(handle uint32) (uint16, uint16) { + return uint16((handle & 0xFFFF0000) >> 16), uint16(handle & 0x0000FFFFF) +} + +func HandleStr(handle uint32) string { + switch handle { + case HANDLE_NONE: + return "none" + case HANDLE_INGRESS: + return "ingress" + case HANDLE_ROOT: + return "root" + default: + major, minor := MajorMinor(handle) + return fmt.Sprintf("%x:%x", major, minor) + } +} + +// PfifoFast is the default qdisc created by the kernel if one has not +// been defined for the interface +type PfifoFast struct { + QdiscAttrs + Bands uint8 + PriorityMap [PRIORITY_MAP_LEN]uint8 +} + +func (qdisc *PfifoFast) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *PfifoFast) Type() string { + return "pfifo_fast" +} + +// Prio is a basic qdisc that works just like PfifoFast +type Prio struct { + QdiscAttrs + Bands uint8 + PriorityMap [PRIORITY_MAP_LEN]uint8 +} + +func NewPrio(attrs QdiscAttrs) *Prio { + return &Prio{ + QdiscAttrs: attrs, + Bands: 3, + PriorityMap: [PRIORITY_MAP_LEN]uint8{1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, + } +} + +func (qdisc *Prio) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Prio) Type() string { + return "prio" +} + +// Htb is a classful qdisc that rate limits based on tokens +type Htb struct { + QdiscAttrs + Version uint32 + Rate2Quantum uint32 + Defcls uint32 + Debug uint32 + DirectPkts uint32 +} + +func NewHtb(attrs QdiscAttrs) *Htb { + return &Htb{ + QdiscAttrs: attrs, + Version: 3, + Defcls: 0, + Rate2Quantum: 10, + Debug: 0, + DirectPkts: 0, + } +} + +func (qdisc *Htb) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Htb) Type() string { + return "htb" +} + +// Tbf is a classless qdisc that rate limits based on tokens +type Tbf struct { + QdiscAttrs + // TODO: handle 64bit rate properly + Rate uint64 + Limit uint32 + Buffer uint32 + // TODO: handle other settings +} + +func (qdisc *Tbf) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Tbf) Type() string { + return "tbf" +} + +// Ingress is a qdisc for adding ingress filters +type Ingress struct { + QdiscAttrs +} + +func (qdisc *Ingress) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Ingress) Type() string { + return "ingress" +} + +// GenericQdisc qdiscs represent types that are not currently understood +// by this netlink library. +type GenericQdisc struct { + QdiscAttrs + QdiscType string +} + +func (qdisc *GenericQdisc) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *GenericQdisc) Type() string { + return qdisc.QdiscType +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go new file mode 100644 index 0000000000..a16eb99b34 --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go @@ -0,0 +1,316 @@ +package netlink + +import ( + "fmt" + "io/ioutil" + "strconv" + "strings" + "syscall" + + "github.com/vishvananda/netlink/nl" +) + +// 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) + + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + +// 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) + base := qdisc.Attrs() + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: int32(base.LinkIndex), + Handle: base.Handle, + Parent: base.Parent, + } + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type()))) + + options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) + if prio, ok := qdisc.(*Prio); ok { + tcmap := nl.TcPrioMap{ + Bands: int32(prio.Bands), + Priomap: prio.PriorityMap, + } + options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize()) + } else if tbf, ok := qdisc.(*Tbf); ok { + opt := nl.TcTbfQopt{} + // TODO: handle rate > uint32 + opt.Rate.Rate = uint32(tbf.Rate) + opt.Limit = tbf.Limit + opt.Buffer = tbf.Buffer + nl.NewRtAttrChild(options, nl.TCA_TBF_PARMS, opt.Serialize()) + } else if htb, ok := qdisc.(*Htb); ok { + opt := nl.TcHtbGlob{} + opt.Version = htb.Version + opt.Rate2Quantum = htb.Rate2Quantum + opt.Defcls = htb.Defcls + // TODO: Handle Debug properly. For now default to 0 + opt.Debug = htb.Debug + opt.DirectPkts = htb.DirectPkts + nl.NewRtAttrChild(options, nl.TCA_HTB_INIT, opt.Serialize()) + // nl.NewRtAttrChild(options, nl.TCA_HTB_DIRECT_QLEN, opt.Serialize()) + } else if _, ok := qdisc.(*Ingress); ok { + // ingress filters must use the proper handle + if msg.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 +} + +// QdiscList gets a list of qdiscs in the system. +// Equivalent to: `tc qdisc show`. +// The list can be filtered by link. +func QdiscList(link Link) ([]Qdisc, error) { + req := nl.NewNetlinkRequest(syscall.RTM_GETQDISC, syscall.NLM_F_DUMP) + index := int32(0) + if link != nil { + base := link.Attrs() + ensureIndex(base) + index = int32(base.Index) + } + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: index, + } + req.AddData(msg) + + msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWQDISC) + if err != nil { + return nil, err + } + + var res []Qdisc + for _, m := range msgs { + msg := nl.DeserializeTcMsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + // skip qdiscs from other interfaces + if link != nil && msg.Ifindex != index { + continue + } + + base := QdiscAttrs{ + LinkIndex: int(msg.Ifindex), + Handle: msg.Handle, + Parent: msg.Parent, + Refcnt: msg.Info, + } + var qdisc Qdisc + qdiscType := "" + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.TCA_KIND: + qdiscType = string(attr.Value[:len(attr.Value)-1]) + switch qdiscType { + case "pfifo_fast": + qdisc = &PfifoFast{} + case "prio": + qdisc = &Prio{} + case "tbf": + qdisc = &Tbf{} + case "ingress": + qdisc = &Ingress{} + case "htb": + qdisc = &Htb{} + default: + qdisc = &GenericQdisc{QdiscType: qdiscType} + } + case nl.TCA_OPTIONS: + switch qdiscType { + case "pfifo_fast": + // pfifo returns TcPrioMap directly without wrapping it in rtattr + if err := parsePfifoFastData(qdisc, attr.Value); err != nil { + return nil, err + } + case "prio": + // prio returns TcPrioMap directly without wrapping it in rtattr + if err := parsePrioData(qdisc, attr.Value); err != nil { + return nil, err + } + case "tbf": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + if err := parseTbfData(qdisc, data); err != nil { + return nil, err + } + case "htb": + data, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return nil, err + } + if err := parseHtbData(qdisc, data); err != nil { + return nil, err + } + + // no options for ingress + } + } + } + *qdisc.Attrs() = base + res = append(res, qdisc) + } + + return res, nil +} + +func parsePfifoFastData(qdisc Qdisc, value []byte) error { + pfifo := qdisc.(*PfifoFast) + tcmap := nl.DeserializeTcPrioMap(value) + pfifo.PriorityMap = tcmap.Priomap + pfifo.Bands = uint8(tcmap.Bands) + return nil +} + +func parsePrioData(qdisc Qdisc, value []byte) error { + prio := qdisc.(*Prio) + tcmap := nl.DeserializeTcPrioMap(value) + prio.PriorityMap = tcmap.Priomap + prio.Bands = uint8(tcmap.Bands) + return nil +} + +func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { + native = nl.NativeEndian() + htb := qdisc.(*Htb) + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_HTB_INIT: + opt := nl.DeserializeTcHtbGlob(datum.Value) + htb.Version = opt.Version + htb.Rate2Quantum = opt.Rate2Quantum + htb.Defcls = opt.Defcls + htb.Debug = opt.Debug + htb.DirectPkts = opt.DirectPkts + case nl.TCA_HTB_DIRECT_QLEN: + // TODO + //htb.DirectQlen = native.uint32(datum.Value) + } + } + return nil +} +func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { + native = nl.NativeEndian() + tbf := qdisc.(*Tbf) + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_TBF_PARMS: + opt := nl.DeserializeTcTbfQopt(datum.Value) + tbf.Rate = uint64(opt.Rate.Rate) + tbf.Limit = opt.Limit + tbf.Buffer = opt.Buffer + case nl.TCA_TBF_RATE64: + tbf.Rate = native.Uint64(datum.Value[0:4]) + } + } + return nil +} + +const ( + TIME_UNITS_PER_SEC = 1000000 +) + +var ( + tickInUsec float64 = 0.0 + clockFactor float64 = 0.0 + hz float64 = 0.0 +) + +func initClock() { + data, err := ioutil.ReadFile("/proc/net/psched") + if err != nil { + return + } + parts := strings.Split(strings.TrimSpace(string(data)), " ") + if len(parts) < 3 { + return + } + var vals [3]uint64 + for i := range vals { + val, err := strconv.ParseUint(parts[i], 16, 32) + if err != nil { + return + } + vals[i] = val + } + // compatibility + if vals[2] == 1000000000 { + vals[0] = vals[1] + } + clockFactor = float64(vals[2]) / TIME_UNITS_PER_SEC + tickInUsec = float64(vals[0]) / float64(vals[1]) * clockFactor + hz = float64(vals[0]) +} + +func TickInUsec() float64 { + if tickInUsec == 0.0 { + initClock() + } + return tickInUsec +} + +func ClockFactor() float64 { + if clockFactor == 0.0 { + initClock() + } + return clockFactor +} + +func Hz() float64 { + if hz == 0.0 { + initClock() + } + return hz +} + +func time2Tick(time uint32) uint32 { + return uint32(float64(time) * TickInUsec()) +} + +func tick2Time(tick uint32) uint32 { + return uint32(float64(tick) / TickInUsec()) +} + +func time2Ktime(time uint32) uint32 { + return uint32(float64(time) * ClockFactor()) +} + +func ktime2Time(ktime uint32) uint32 { + return uint32(float64(ktime) / ClockFactor()) +} + +func burst(rate uint64, buffer uint32) uint32 { + return uint32(float64(rate) * float64(tick2Time(buffer)) / TIME_UNITS_PER_SEC) +} + +func latency(rate uint64, limit, buffer uint32) float64 { + return TIME_UNITS_PER_SEC*(float64(limit)/float64(rate)) - float64(tick2Time(buffer)) +} + +func Xmittime(rate uint64, size uint32) float64 { + return TickInUsec() * TIME_UNITS_PER_SEC * (float64(size) / float64(rate)) +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go index 6218546f80..789d39f262 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go @@ -17,6 +17,13 @@ const ( SCOPE_NOWHERE Scope = syscall.RT_SCOPE_NOWHERE ) +type NextHopFlag int + +const ( + FLAG_ONLINK NextHopFlag = syscall.RTNH_F_ONLINK + FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE +) + // Route represents a netlink route. A route is associated with a link, // has a destination network, an optional source ip, and optional // gateway. Advanced route parameters and non-main routing tables are @@ -27,9 +34,44 @@ type Route struct { Dst *net.IPNet Src net.IP Gw net.IP + Flags int } func (r Route) String() string { - return fmt.Sprintf("{Ifindex: %d Dst: %s Src: %s Gw: %s}", r.LinkIndex, r.Dst, - r.Src, r.Gw) + return fmt.Sprintf("{Ifindex: %d Dst: %s Src: %s Gw: %s Flags: %s}", r.LinkIndex, r.Dst, + r.Src, r.Gw, r.ListFlags()) +} + +func (r *Route) SetFlag(flag NextHopFlag) { + r.Flags |= int(flag) +} + +func (r *Route) ClearFlag(flag NextHopFlag) { + r.Flags &^= int(flag) +} + +type flagString struct { + f NextHopFlag + s string +} + +var testFlags = []flagString{ + flagString{f: FLAG_ONLINK, s: "onlink"}, + flagString{f: FLAG_PERVASIVE, s: "pervasive"}, +} + +func (r *Route) ListFlags() []string { + var flags []string + for _, tf := range testFlags { + if r.Flags&int(tf.f) != 0 { + flags = append(flags, tf.s) + } + } + return flags +} + +// RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE +type RouteUpdate struct { + Type uint16 + Route } diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go index 38908951fe..c8910e2332 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go @@ -17,7 +17,7 @@ func RouteAdd(route *Route) error { return routeHandle(route, req, nl.NewRtMsg()) } -// RouteAdd will delete a route from the system. +// RouteDel will delete a route from the system. // Equivalent to: `ip route del $route` func RouteDel(route *Route) error { req := nl.NewNetlinkRequest(syscall.RTM_DELROUTE, syscall.NLM_F_ACK) @@ -30,6 +30,7 @@ func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error { } msg.Scope = uint8(route.Scope) + msg.Flags = uint32(route.Flags) family := -1 var rtAttrs []*nl.RtAttr @@ -117,7 +118,6 @@ func RouteList(link Link, family int) ([]Route, error) { index = base.Index } - native := nl.NativeEndian() var res []Route for _, m := range msgs { msg := nl.DeserializeRtMsg(m) @@ -132,31 +132,14 @@ func RouteList(link Link, family int) ([]Route, error) { continue } - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + route, err := deserializeRoute(m) if err != nil { return nil, err } - route := Route{Scope: Scope(msg.Scope)} - for _, attr := range attrs { - switch attr.Attr.Type { - case syscall.RTA_GATEWAY: - route.Gw = net.IP(attr.Value) - case syscall.RTA_PREFSRC: - route.Src = net.IP(attr.Value) - case syscall.RTA_DST: - route.Dst = &net.IPNet{ - IP: attr.Value, - Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)), - } - case syscall.RTA_OIF: - routeIndex := int(native.Uint32(attr.Value[0:4])) - if link != nil && routeIndex != index { - // Ignore routes from other interfaces - continue - } - route.LinkIndex = routeIndex - } + if link != nil && route.LinkIndex != index { + // Ignore routes from other interfaces + continue } res = append(res, route) } @@ -164,6 +147,37 @@ func RouteList(link Link, family int) ([]Route, error) { return res, nil } +// deserializeRoute decodes a binary netlink message into a Route struct +func deserializeRoute(m []byte) (Route, error) { + route := Route{} + msg := nl.DeserializeRtMsg(m) + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return route, err + } + route.Scope = Scope(msg.Scope) + route.Flags = int(msg.Flags) + + native := nl.NativeEndian() + for _, attr := range attrs { + switch attr.Attr.Type { + case syscall.RTA_GATEWAY: + route.Gw = net.IP(attr.Value) + case syscall.RTA_PREFSRC: + route.Src = net.IP(attr.Value) + case syscall.RTA_DST: + route.Dst = &net.IPNet{ + IP: attr.Value, + Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)), + } + case syscall.RTA_OIF: + routeIndex := int(native.Uint32(attr.Value[0:4])) + route.LinkIndex = routeIndex + } + } + return route, nil +} + // RouteGet gets a route to a specific destination from the host system. // Equivalent to: 'ip route get'. func RouteGet(destination net.IP) ([]Route, error) { @@ -191,34 +205,47 @@ func RouteGet(destination net.IP) ([]Route, error) { return nil, err } - native := nl.NativeEndian() var res []Route for _, m := range msgs { - msg := nl.DeserializeRtMsg(m) - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + route, err := deserializeRoute(m) if err != nil { return nil, err } - - route := Route{} - for _, attr := range attrs { - switch attr.Attr.Type { - case syscall.RTA_GATEWAY: - route.Gw = net.IP(attr.Value) - case syscall.RTA_PREFSRC: - route.Src = net.IP(attr.Value) - case syscall.RTA_DST: - route.Dst = &net.IPNet{ - IP: attr.Value, - Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)), - } - case syscall.RTA_OIF: - routeIndex := int(native.Uint32(attr.Value[0:4])) - route.LinkIndex = routeIndex - } - } res = append(res, route) } return res, nil } + +// RouteSubscribe takes a chan down which notifications will be sent +// when routes are added or deleted. Close the 'done' chan to stop subscription. +func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error { + s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE) + if err != nil { + return err + } + if done != nil { + go func() { + <-done + s.Close() + }() + } + go func() { + defer close(ch) + for { + msgs, err := s.Receive() + if err != nil { + return + } + for _, m := range msgs { + route, err := deserializeRoute(m.Data) + if err != nil { + return + } + ch <- RouteUpdate{Type: m.Header.Type, Route: route} + } + } + }() + + return nil +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_test.go deleted file mode 100644 index f02bef8c87..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package netlink - -import ( - "net" - "testing" -) - -func TestRouteAddDel(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - // get loopback interface - link, err := LinkByName("lo") - if err != nil { - t.Fatal(err) - } - - // bring the interface up - if err = LinkSetUp(link); err != nil { - t.Fatal(err) - } - - // add a gateway route - _, dst, err := net.ParseCIDR("192.168.0.0/24") - - ip := net.ParseIP("127.1.1.1") - route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip} - err = RouteAdd(&route) - if err != nil { - t.Fatal(err) - } - routes, err := RouteList(link, FAMILY_V4) - if err != nil { - t.Fatal(err) - } - if len(routes) != 1 { - t.Fatal("Link not added properly") - } - - dstIP := net.ParseIP("192.168.0.42") - routeToDstIP, err := RouteGet(dstIP) - if err != nil { - t.Fatal(err) - } - - if len(routeToDstIP) == 0 { - t.Fatal("Default route not present") - } - - err = RouteDel(&route) - if err != nil { - t.Fatal(err) - } - - routes, err = RouteList(link, FAMILY_V4) - if err != nil { - t.Fatal(err) - } - if len(routes) != 0 { - t.Fatal("Route not removed properly") - } - -} - -func TestRouteAddIncomplete(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - // get loopback interface - link, err := LinkByName("lo") - if err != nil { - t.Fatal(err) - } - - // bring the interface up - if err = LinkSetUp(link); err != nil { - t.Fatal(err) - } - - route := Route{LinkIndex: link.Attrs().Index} - if err := RouteAdd(&route); err == nil { - t.Fatal("Adding incomplete route should fail") - } -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_policy_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_policy_test.go deleted file mode 100644 index 06d178d1f9..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_policy_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package netlink - -import ( - "net" - "testing" -) - -func TestXfrmPolicyAddDel(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - src, _ := ParseIPNet("127.1.1.1/32") - dst, _ := ParseIPNet("127.1.1.2/32") - policy := XfrmPolicy{ - Src: src, - Dst: dst, - Dir: XFRM_DIR_OUT, - } - tmpl := XfrmPolicyTmpl{ - Src: net.ParseIP("127.0.0.1"), - Dst: net.ParseIP("127.0.0.2"), - Proto: XFRM_PROTO_ESP, - Mode: XFRM_MODE_TUNNEL, - } - policy.Tmpls = append(policy.Tmpls, tmpl) - if err := XfrmPolicyAdd(&policy); err != nil { - t.Fatal(err) - } - policies, err := XfrmPolicyList(FAMILY_ALL) - if err != nil { - t.Fatal(err) - } - - if len(policies) != 1 { - t.Fatal("Policy not added properly") - } - - if err = XfrmPolicyDel(&policy); err != nil { - t.Fatal(err) - } - - policies, err = XfrmPolicyList(FAMILY_ALL) - if err != nil { - t.Fatal(err) - } - if len(policies) != 0 { - t.Fatal("Policy not removed properly") - } -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state_test.go deleted file mode 100644 index df57ef8b7e..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package netlink - -import ( - "net" - "testing" -) - -func TestXfrmStateAddDel(t *testing.T) { - tearDown := setUpNetlinkTest(t) - defer tearDown() - - state := XfrmState{ - Src: net.ParseIP("127.0.0.1"), - Dst: net.ParseIP("127.0.0.2"), - Proto: XFRM_PROTO_ESP, - Mode: XFRM_MODE_TUNNEL, - Spi: 1, - Auth: &XfrmStateAlgo{ - Name: "hmac(sha256)", - Key: []byte("abcdefghijklmnopqrstuvwzyzABCDEF"), - }, - Crypt: &XfrmStateAlgo{ - Name: "cbc(aes)", - Key: []byte("abcdefghijklmnopqrstuvwzyzABCDEF"), - }, - } - if err := XfrmStateAdd(&state); err != nil { - t.Fatal(err) - } - policies, err := XfrmStateList(FAMILY_ALL) - if err != nil { - t.Fatal(err) - } - - if len(policies) != 1 { - t.Fatal("State not added properly") - } - - if err = XfrmStateDel(&state); err != nil { - t.Fatal(err) - } - - policies, err = XfrmStateList(FAMILY_ALL) - if err != nil { - t.Fatal(err) - } - if len(policies) != 0 { - t.Fatal("State not removed properly") - } -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_linux_s390x.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_linux_s390x.go new file mode 100644 index 0000000000..cc13e62665 --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_linux_s390x.go @@ -0,0 +1,7 @@ +// +build linux,s390x + +package netns + +const ( + SYS_SETNS = 339 +) diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_test.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_test.go deleted file mode 100644 index e51981cc1b..0000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package netns - -import ( - "runtime" - "sync" - "testing" -) - -func TestGetNewSetDelete(t *testing.T) { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - origns, err := Get() - if err != nil { - t.Fatal(err) - } - newns, err := New() - if err != nil { - t.Fatal(err) - } - if origns.Equal(newns) { - t.Fatal("New ns failed") - } - if err := Set(origns); err != nil { - t.Fatal(err) - } - newns.Close() - if newns.IsOpen() { - t.Fatal("newns still open after close", newns) - } - ns, err := Get() - if err != nil { - t.Fatal(err) - } - if !ns.Equal(origns) { - t.Fatal("Reset ns failed", origns, newns, ns) - } -} - -func TestNone(t *testing.T) { - ns := None() - if ns.IsOpen() { - t.Fatal("None ns is open", ns) - } -} - -func TestThreaded(t *testing.T) { - ncpu := runtime.GOMAXPROCS(-1) - if ncpu < 2 { - t.Skip("-cpu=2 or larger required") - } - - // Lock this thread simply to ensure other threads get used. - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - wg := &sync.WaitGroup{} - for i := 0; i < ncpu; i++ { - wg.Add(1) - go func() { - defer wg.Done() - TestGetNewSetDelete(t) - }() - } - wg.Wait() -}