Browse Source

Merge pull request #679 from clearlinux/master

Update netlink library.
aboch 9 years ago
parent
commit
5359d01a51
30 changed files with 1988 additions and 1846 deletions
  1. 2 2
      libnetwork/Godeps/Godeps.json
  2. 0 45
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go
  3. 110 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class.go
  4. 144 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go
  5. 140 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter.go
  6. 322 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_linux.go
  7. 51 5
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go
  8. 92 1
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go
  9. 0 643
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go
  10. 14 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_tuntap_linux.go
  11. 0 104
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go
  12. 0 34
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go
  13. 0 39
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go
  14. 1 1
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go
  15. 0 60
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go
  16. 0 43
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go
  17. 508 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/tc_linux.go
  18. 0 161
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go
  19. 0 109
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go
  20. 0 207
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go
  21. 0 98
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go
  22. 167 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go
  23. 316 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go
  24. 44 2
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go
  25. 70 43
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go
  26. 0 84
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_test.go
  27. 0 49
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_policy_test.go
  28. 0 50
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state_test.go
  29. 7 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_linux_s390x.go
  30. 0 66
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_test.go

+ 2 - 2
libnetwork/Godeps/Godeps.json

@@ -216,11 +216,11 @@
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/vishvananda/netlink",
 			"ImportPath": "github.com/vishvananda/netlink",
-			"Rev": "4b5dce31de6d42af5bb9811c6d265472199e0fec"
+			"Rev": "8e810149a2e531fed9b837c0c7d8a8922d2bedf7"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/vishvananda/netns",
 			"ImportPath": "github.com/vishvananda/netns",
-			"Rev": "493029407eeb434d0c2d44e02ea072ff2488d322"
+			"Rev": "604eaf189ee867d8c147fafc28def2394e878d25"
 		},
 		},
 		{
 		{
 			"ImportPath": "golang.org/x/net/context",
 			"ImportPath": "golang.org/x/net/context",

+ 0 - 45
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go

@@ -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")
-	}
-}

+ 110 - 0
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
+}

+ 144 - 0
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
+}

+ 140 - 0
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
+}

+ 322 - 0
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)<<uint32(cell_log)), uint(mpu), linklayer)
+		rtab[i] = uint32(Xmittime(uint64(bps), uint32(sz)))
+	}
+	rate.CellAlign = -1
+	rate.CellLog = uint8(cell_log)
+	rate.Linklayer = uint8(linklayer & nl.TC_LINKLAYER_MASK)
+	return cell_log
+}
+
+func DeserializeRtab(b []byte) [256]uint32 {
+	var rtab [256]uint32
+	native := nl.NativeEndian()
+	r := bytes.NewReader(b)
+	_ = binary.Read(r, native, &rtab)
+	return rtab
+}
+
+func SerializeRtab(rtab [256]uint32) []byte {
+	native := nl.NativeEndian()
+	var w bytes.Buffer
+	_ = binary.Write(&w, native, rtab)
+	return w.Bytes()
+}

+ 51 - 5
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go

@@ -1,6 +1,9 @@
 package netlink
 package netlink
 
 
-import "net"
+import (
+	"net"
+	"syscall"
+)
 
 
 // Link represents a link device from netlink. Shared link attributes
 // Link represents a link device from netlink. Shared link attributes
 // like name may be retrieved using the Attrs() method. Unique data
 // like name may be retrieved using the Attrs() method. Unique data
@@ -62,6 +65,19 @@ func (dummy *Dummy) Type() string {
 	return "dummy"
 	return "dummy"
 }
 }
 
 
+// Ifb links are advanced dummy devices for packet filtering
+type Ifb struct {
+	LinkAttrs
+}
+
+func (ifb *Ifb) Attrs() *LinkAttrs {
+	return &ifb.LinkAttrs
+}
+
+func (ifb *Ifb) Type() string {
+	return "ifb"
+}
+
 // Bridge links are simple linux bridges
 // Bridge links are simple linux bridges
 type Bridge struct {
 type Bridge struct {
 	LinkAttrs
 	LinkAttrs
@@ -114,6 +130,36 @@ func (macvlan *Macvlan) Type() string {
 	return "macvlan"
 	return "macvlan"
 }
 }
 
 
+// Macvtap - macvtap is a virtual interfaces based on macvlan
+type Macvtap struct {
+	Macvlan
+}
+
+func (macvtap Macvtap) Type() string {
+	return "macvtap"
+}
+
+type TuntapMode uint16
+
+const (
+	TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
+	TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
+)
+
+// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
+type Tuntap struct {
+	LinkAttrs
+	Mode TuntapMode
+}
+
+func (tuntap *Tuntap) Attrs() *LinkAttrs {
+	return &tuntap.LinkAttrs
+}
+
+func (tuntap *Tuntap) Type() string {
+	return "tuntap"
+}
+
 // Veth devices must specify PeerName on create
 // Veth devices must specify PeerName on create
 type Veth struct {
 type Veth struct {
 	LinkAttrs
 	LinkAttrs
@@ -128,18 +174,18 @@ func (veth *Veth) Type() string {
 	return "veth"
 	return "veth"
 }
 }
 
 
-// Generic links represent types that are not currently understood
+// GenericLink links represent types that are not currently understood
 // by this netlink library.
 // by this netlink library.
-type Generic struct {
+type GenericLink struct {
 	LinkAttrs
 	LinkAttrs
 	LinkType string
 	LinkType string
 }
 }
 
 
-func (generic *Generic) Attrs() *LinkAttrs {
+func (generic *GenericLink) Attrs() *LinkAttrs {
 	return &generic.LinkAttrs
 	return &generic.LinkAttrs
 }
 }
 
 
-func (generic *Generic) Type() string {
+func (generic *GenericLink) Type() string {
 	return generic.LinkType
 	return generic.LinkType
 }
 }
 
 

+ 92 - 1
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go

@@ -5,7 +5,9 @@ import (
 	"encoding/binary"
 	"encoding/binary"
 	"fmt"
 	"fmt"
 	"net"
 	"net"
+	"os"
 	"syscall"
 	"syscall"
+	"unsafe"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
 )
 )
@@ -285,6 +287,44 @@ func LinkAdd(link Link) error {
 		return fmt.Errorf("LinkAttrs.Name cannot be empty!")
 		return fmt.Errorf("LinkAttrs.Name cannot be empty!")
 	}
 	}
 
 
+	if tuntap, ok := link.(*Tuntap); ok {
+		// TODO: support user
+		// TODO: support group
+		// TODO: support non- one_queue
+		// TODO: support pi | vnet_hdr | multi_queue
+		// TODO: support non- exclusive
+		// TODO: support non- persistent
+		if tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > 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)
 	req := nl.NewNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
 
 
 	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
 	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
@@ -493,6 +533,8 @@ func linkDeserialize(m []byte) (Link, error) {
 					switch linkType {
 					switch linkType {
 					case "dummy":
 					case "dummy":
 						link = &Dummy{}
 						link = &Dummy{}
+					case "ifb":
+						link = &Ifb{}
 					case "bridge":
 					case "bridge":
 						link = &Bridge{}
 						link = &Bridge{}
 					case "vlan":
 					case "vlan":
@@ -505,8 +547,10 @@ func linkDeserialize(m []byte) (Link, error) {
 						link = &IPVlan{}
 						link = &IPVlan{}
 					case "macvlan":
 					case "macvlan":
 						link = &Macvlan{}
 						link = &Macvlan{}
+					case "macvtap":
+						link = &Macvtap{}
 					default:
 					default:
-						link = &Generic{LinkType: linkType}
+						link = &GenericLink{LinkType: linkType}
 					}
 					}
 				case nl.IFLA_INFO_DATA:
 				case nl.IFLA_INFO_DATA:
 					data, err := nl.ParseRouteAttr(info.Value)
 					data, err := nl.ParseRouteAttr(info.Value)
@@ -522,6 +566,8 @@ func linkDeserialize(m []byte) (Link, error) {
 						parseIPVlanData(link, data)
 						parseIPVlanData(link, data)
 					case "macvlan":
 					case "macvlan":
 						parseMacvlanData(link, data)
 						parseMacvlanData(link, data)
+					case "macvtap":
+						parseMacvtapData(link, data)
 					}
 					}
 				}
 				}
 			}
 			}
@@ -583,6 +629,46 @@ func LinkList() ([]Link, error) {
 	return res, nil
 	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 {
 func LinkSetHairpin(link Link, mode bool) error {
 	return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_MODE)
 	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) {
 func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
 	macv := link.(*Macvlan)
 	macv := link.(*Macvlan)
 	for _, datum := range data {
 	for _, datum := range data {

+ 0 - 643
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go

@@ -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!")
-	}
-}

+ 14 - 0
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
+}

+ 0 - 104
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go

@@ -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)
-	}
-}

+ 0 - 34
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go

@@ -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()
-	}
-}

+ 0 - 39
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go

@@ -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)
-}

+ 1 - 1
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
 // 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 {
 func (a *RtAttr) Serialize() []byte {
 	native := NativeEndian()
 	native := NativeEndian()
 
 

+ 0 - 60
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go

@@ -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)
-}

+ 0 - 43
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go

@@ -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)
-}

+ 508 - 0
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
+)

+ 0 - 161
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go

@@ -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)
-}

+ 0 - 109
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go

@@ -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)
-}

+ 0 - 207
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go

@@ -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)
-}

+ 0 - 98
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go

@@ -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)
-	}
-}

+ 167 - 0
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
+}

+ 316 - 0
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))
+}

+ 44 - 2
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go

@@ -17,6 +17,13 @@ const (
 	SCOPE_NOWHERE  Scope = syscall.RT_SCOPE_NOWHERE
 	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,
 // Route represents a netlink route. A route is associated with a link,
 // has a destination network, an optional source ip, and optional
 // has a destination network, an optional source ip, and optional
 // gateway. Advanced route parameters and non-main routing tables are
 // gateway. Advanced route parameters and non-main routing tables are
@@ -27,9 +34,44 @@ type Route struct {
 	Dst       *net.IPNet
 	Dst       *net.IPNet
 	Src       net.IP
 	Src       net.IP
 	Gw        net.IP
 	Gw        net.IP
+	Flags     int
 }
 }
 
 
 func (r Route) String() string {
 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
 }
 }

+ 70 - 43
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())
 	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`
 // Equivalent to: `ip route del $route`
 func RouteDel(route *Route) error {
 func RouteDel(route *Route) error {
 	req := nl.NewNetlinkRequest(syscall.RTM_DELROUTE, syscall.NLM_F_ACK)
 	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.Scope = uint8(route.Scope)
+	msg.Flags = uint32(route.Flags)
 	family := -1
 	family := -1
 	var rtAttrs []*nl.RtAttr
 	var rtAttrs []*nl.RtAttr
 
 
@@ -117,7 +118,6 @@ func RouteList(link Link, family int) ([]Route, error) {
 		index = base.Index
 		index = base.Index
 	}
 	}
 
 
-	native := nl.NativeEndian()
 	var res []Route
 	var res []Route
 	for _, m := range msgs {
 	for _, m := range msgs {
 		msg := nl.DeserializeRtMsg(m)
 		msg := nl.DeserializeRtMsg(m)
@@ -132,31 +132,14 @@ func RouteList(link Link, family int) ([]Route, error) {
 			continue
 			continue
 		}
 		}
 
 
-		attrs, err := nl.ParseRouteAttr(m[msg.Len():])
+		route, err := deserializeRoute(m)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			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)
 		res = append(res, route)
 	}
 	}
@@ -164,6 +147,37 @@ func RouteList(link Link, family int) ([]Route, error) {
 	return res, nil
 	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.
 // RouteGet gets a route to a specific destination from the host system.
 // Equivalent to: 'ip route get'.
 // Equivalent to: 'ip route get'.
 func RouteGet(destination net.IP) ([]Route, error) {
 func RouteGet(destination net.IP) ([]Route, error) {
@@ -191,34 +205,47 @@ func RouteGet(destination net.IP) ([]Route, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	native := nl.NativeEndian()
 	var res []Route
 	var res []Route
 	for _, m := range msgs {
 	for _, m := range msgs {
-		msg := nl.DeserializeRtMsg(m)
-		attrs, err := nl.ParseRouteAttr(m[msg.Len():])
+		route, err := deserializeRoute(m)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
+		res = append(res, route)
+	}
+	return res, nil
+
+}
 
 
-		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)),
+// 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
 				}
 				}
-			case syscall.RTA_OIF:
-				routeIndex := int(native.Uint32(attr.Value[0:4]))
-				route.LinkIndex = routeIndex
+				ch <- RouteUpdate{Type: m.Header.Type, Route: route}
 			}
 			}
 		}
 		}
-		res = append(res, route)
-	}
-	return res, nil
+	}()
 
 
+	return nil
 }
 }

+ 0 - 84
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_test.go

@@ -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")
-	}
-}

+ 0 - 49
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_policy_test.go

@@ -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")
-	}
-}

+ 0 - 50
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state_test.go

@@ -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")
-	}
-}

+ 7 - 0
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
+)

+ 0 - 66
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netns/netns_test.go

@@ -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()
-}