mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #848 from aboch/nlvnd
Disable DAD for sandbox IPv6 addresses
This commit is contained in:
commit
3184188851
43 changed files with 4893 additions and 92 deletions
2
libnetwork/Godeps/Godeps.json
generated
2
libnetwork/Godeps/Godeps.json
generated
|
@ -243,7 +243,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/vishvananda/netlink",
|
||||
"Rev": "8e810149a2e531fed9b837c0c7d8a8922d2bedf7"
|
||||
"Rev": "bfd70f556483c008636b920dda142fdaa0d59ef9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vishvananda/netns",
|
||||
|
|
7
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/.travis.yml
generated
vendored
7
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/.travis.yml
generated
vendored
|
@ -1,3 +1,8 @@
|
|||
language: go
|
||||
before_script:
|
||||
# make sure we keep path in tact when we sudo
|
||||
- sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
|
||||
# modprobe ip_gre or else the first gre device can't be deleted
|
||||
- sudo modprobe ip_gre
|
||||
install:
|
||||
- go get github.com/vishvananda/netns
|
||||
- go get github.com/vishvananda/netns
|
||||
|
|
2
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/Makefile
generated
vendored
2
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/Makefile
generated
vendored
|
@ -11,7 +11,7 @@ goroot = $(addprefix ../../../,$(1))
|
|||
unroot = $(subst ../../../,,$(1))
|
||||
fmt = $(addprefix fmt-,$(1))
|
||||
|
||||
all: fmt
|
||||
all: fmt test
|
||||
|
||||
$(call goroot,$(DEPS)):
|
||||
go get $(call unroot,$@)
|
||||
|
|
4
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr.go
generated
vendored
4
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr.go
generated
vendored
|
@ -11,11 +11,13 @@ import (
|
|||
type Addr struct {
|
||||
*net.IPNet
|
||||
Label string
|
||||
Flags int
|
||||
Scope int
|
||||
}
|
||||
|
||||
// String returns $ip/$netmask $label
|
||||
func (a Addr) String() string {
|
||||
return fmt.Sprintf("%s %s", a.IPNet, a.Label)
|
||||
return strings.TrimSpace(fmt.Sprintf("%s %s", a.IPNet, a.Label))
|
||||
}
|
||||
|
||||
// ParseAddr parses the string representation of an address in the
|
||||
|
|
14
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
14
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
|
@ -9,6 +9,9 @@ import (
|
|||
"github.com/vishvananda/netlink/nl"
|
||||
)
|
||||
|
||||
// IFA_FLAGS is a u32 attribute.
|
||||
const IFA_FLAGS = 0x8
|
||||
|
||||
// AddrAdd will add an IP address to a link device.
|
||||
// Equivalent to: `ip addr add $addr dev $link`
|
||||
func AddrAdd(link Link, addr *Addr) error {
|
||||
|
@ -35,6 +38,7 @@ func addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error {
|
|||
|
||||
msg := nl.NewIfAddrmsg(family)
|
||||
msg.Index = uint32(base.Index)
|
||||
msg.Scope = uint8(addr.Scope)
|
||||
prefixlen, _ := addr.Mask.Size()
|
||||
msg.Prefixlen = uint8(prefixlen)
|
||||
req.AddData(msg)
|
||||
|
@ -52,6 +56,13 @@ func addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error {
|
|||
addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, addrData)
|
||||
req.AddData(addressData)
|
||||
|
||||
if addr.Flags != 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(addr.Flags))
|
||||
flagsData := nl.NewRtAttr(IFA_FLAGS, b)
|
||||
req.AddData(flagsData)
|
||||
}
|
||||
|
||||
if addr.Label != "" {
|
||||
labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label))
|
||||
req.AddData(labelData)
|
||||
|
@ -111,6 +122,8 @@ func AddrList(link Link, family int) ([]Addr, error) {
|
|||
}
|
||||
case syscall.IFA_LABEL:
|
||||
addr.Label = string(attr.Value[:len(attr.Value)-1])
|
||||
case IFA_FLAGS:
|
||||
addr.Flags = int(native.Uint32(attr.Value[0:4]))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,6 +133,7 @@ func AddrList(link Link, family int) ([]Addr, error) {
|
|||
} else {
|
||||
addr.IPNet = dst
|
||||
}
|
||||
addr.Scope = int(msg.Scope)
|
||||
|
||||
res = append(res, addr)
|
||||
}
|
||||
|
|
93
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go
generated
vendored
Normal file
93
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAddr(t *testing.T) {
|
||||
if os.Getenv("TRAVIS_BUILD_DIR") != "" {
|
||||
t.Skipf("Fails in travis with: addr_test.go:68: Address flags not set properly, got=0, expected=128")
|
||||
}
|
||||
// TODO: IFA_F_PERMANENT does not seem to be set by default on older kernels?
|
||||
var address = &net.IPNet{net.IPv4(127, 0, 0, 2), net.CIDRMask(24, 32)}
|
||||
var addrTests = []struct {
|
||||
addr *Addr
|
||||
expected *Addr
|
||||
}{
|
||||
{
|
||||
&Addr{IPNet: address},
|
||||
&Addr{IPNet: address, Label: "lo", Scope: syscall.RT_SCOPE_UNIVERSE, Flags: syscall.IFA_F_PERMANENT},
|
||||
},
|
||||
{
|
||||
&Addr{IPNet: address, Label: "local"},
|
||||
&Addr{IPNet: address, Label: "local", Scope: syscall.RT_SCOPE_UNIVERSE, Flags: syscall.IFA_F_PERMANENT},
|
||||
},
|
||||
{
|
||||
&Addr{IPNet: address, Flags: syscall.IFA_F_OPTIMISTIC},
|
||||
&Addr{IPNet: address, Label: "lo", Flags: syscall.IFA_F_OPTIMISTIC | syscall.IFA_F_PERMANENT, Scope: syscall.RT_SCOPE_UNIVERSE},
|
||||
},
|
||||
{
|
||||
&Addr{IPNet: address, Flags: syscall.IFA_F_OPTIMISTIC | syscall.IFA_F_DADFAILED},
|
||||
&Addr{IPNet: address, Label: "lo", Flags: syscall.IFA_F_OPTIMISTIC | syscall.IFA_F_DADFAILED | syscall.IFA_F_PERMANENT, Scope: syscall.RT_SCOPE_UNIVERSE},
|
||||
},
|
||||
{
|
||||
&Addr{IPNet: address, Scope: syscall.RT_SCOPE_NOWHERE},
|
||||
&Addr{IPNet: address, Label: "lo", Flags: syscall.IFA_F_PERMANENT, Scope: syscall.RT_SCOPE_NOWHERE},
|
||||
},
|
||||
}
|
||||
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
link, err := LinkByName("lo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, tt := range addrTests {
|
||||
if err = AddrAdd(link, tt.addr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addrs, err := AddrList(link, FAMILY_ALL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(addrs) != 1 {
|
||||
t.Fatal("Address not added properly")
|
||||
}
|
||||
|
||||
if !addrs[0].Equal(*tt.expected) {
|
||||
t.Fatalf("Address ip no set properly, got=%s, expected=%s", addrs[0], tt.expected)
|
||||
}
|
||||
|
||||
if addrs[0].Label != tt.expected.Label {
|
||||
t.Fatalf("Address label not set properly, got=%s, expected=%s", addrs[0].Label, tt.expected.Label)
|
||||
}
|
||||
|
||||
if addrs[0].Flags != tt.expected.Flags {
|
||||
t.Fatalf("Address flags not set properly, got=%d, expected=%d", addrs[0].Flags, tt.expected.Flags)
|
||||
}
|
||||
|
||||
if addrs[0].Scope != tt.expected.Scope {
|
||||
t.Fatalf("Address scope not set properly, got=%d, expected=%d", addrs[0].Scope, tt.expected.Scope)
|
||||
}
|
||||
|
||||
if err = AddrDel(link, tt.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")
|
||||
}
|
||||
}
|
||||
}
|
54
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go
generated
vendored
54
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go
generated
vendored
|
@ -9,24 +9,38 @@ import (
|
|||
// 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)
|
||||
return classModify(syscall.RTM_DELTCLASS, 0, class)
|
||||
}
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
// ClassChange will change a class in place
|
||||
// Equivalent to: `tc class change $class`
|
||||
// The parent and handle MUST NOT be changed.
|
||||
|
||||
func ClassChange(class Class) error {
|
||||
return classModify(syscall.RTM_NEWTCLASS, 0, class)
|
||||
}
|
||||
|
||||
// ClassReplace will replace a class to the system.
|
||||
// quivalent to: `tc class replace $class`
|
||||
// The handle MAY be changed.
|
||||
// If a class already exist with this parent/handle pair, the class is changed.
|
||||
// If a class does not already exist with this parent/handle, a new class is created.
|
||||
func ClassReplace(class Class) error {
|
||||
return classModify(syscall.RTM_NEWTCLASS, syscall.NLM_F_CREATE, class)
|
||||
}
|
||||
|
||||
// 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)
|
||||
return classModify(
|
||||
syscall.RTM_NEWTCLASS,
|
||||
syscall.NLM_F_CREATE|syscall.NLM_F_EXCL,
|
||||
class,
|
||||
)
|
||||
}
|
||||
|
||||
func classModify(cmd, flags int, class Class) error {
|
||||
req := nl.NewNetlinkRequest(cmd, flags|syscall.NLM_F_ACK)
|
||||
base := class.Attrs()
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
|
@ -35,6 +49,17 @@ func ClassAdd(class Class) error {
|
|||
Parent: base.Parent,
|
||||
}
|
||||
req.AddData(msg)
|
||||
|
||||
if cmd != syscall.RTM_DELTCLASS {
|
||||
if err := classPayload(req, class); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
func classPayload(req *nl.NetlinkRequest, class Class) error {
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type())))
|
||||
|
||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||
|
@ -51,13 +76,12 @@ func ClassAdd(class Class) error {
|
|||
nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize())
|
||||
}
|
||||
req.AddData(options)
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClassList gets a list of classes in the system.
|
||||
// Equivalent to: `tc class show`.
|
||||
// Generally retunrs nothing if link and parent are not specified.
|
||||
// Generally returns 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{
|
||||
|
|
406
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_test.go
generated
vendored
Normal file
406
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_test.go
generated
vendored
Normal file
|
@ -0,0 +1,406 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestClassAddDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
attrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(0xffff, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
}
|
||||
qdisc := NewHtb(attrs)
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
_, ok := qdiscs[0].(*Htb)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
|
||||
classattrs := ClassAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Parent: MakeHandle(0xffff, 0),
|
||||
Handle: MakeHandle(0xffff, 2),
|
||||
}
|
||||
|
||||
htbclassattrs := HtbClassAttrs{
|
||||
Rate: 1234000,
|
||||
Cbuffer: 1690,
|
||||
}
|
||||
class := NewHtbClass(classattrs, htbclassattrs)
|
||||
if err := ClassAdd(class); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
classes, err := ClassList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(classes) != 1 {
|
||||
t.Fatal("Failed to add class")
|
||||
}
|
||||
|
||||
htb, ok := classes[0].(*HtbClass)
|
||||
if !ok {
|
||||
t.Fatal("Class is the wrong type")
|
||||
}
|
||||
if htb.Rate != class.Rate {
|
||||
t.Fatal("Rate doesn't match")
|
||||
}
|
||||
if htb.Ceil != class.Ceil {
|
||||
t.Fatal("Ceil doesn't match")
|
||||
}
|
||||
if htb.Buffer != class.Buffer {
|
||||
t.Fatal("Buffer doesn't match")
|
||||
}
|
||||
if htb.Cbuffer != class.Cbuffer {
|
||||
t.Fatal("Cbuffer doesn't match")
|
||||
}
|
||||
|
||||
qattrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(0x2, 0),
|
||||
Parent: MakeHandle(0xffff, 2),
|
||||
}
|
||||
nattrs := NetemQdiscAttrs{
|
||||
Latency: 20000,
|
||||
Loss: 23.4,
|
||||
Duplicate: 14.3,
|
||||
LossCorr: 8.34,
|
||||
Jitter: 1000,
|
||||
DelayCorr: 12.3,
|
||||
ReorderProb: 23.4,
|
||||
CorruptProb: 10.0,
|
||||
CorruptCorr: 10,
|
||||
}
|
||||
qdiscnetem := NewNetem(qattrs, nattrs)
|
||||
if err := QdiscAdd(qdiscnetem); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 2 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
_, ok = qdiscs[0].(*Htb)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
|
||||
netem, ok := qdiscs[1].(*Netem)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
// Compare the record we got from the list with the one we created
|
||||
if netem.Loss != qdiscnetem.Loss {
|
||||
t.Fatal("Loss does not match")
|
||||
}
|
||||
if netem.Latency != qdiscnetem.Latency {
|
||||
t.Fatal("Latency does not match")
|
||||
}
|
||||
if netem.CorruptProb != qdiscnetem.CorruptProb {
|
||||
t.Fatal("CorruptProb does not match")
|
||||
}
|
||||
if netem.Jitter != qdiscnetem.Jitter {
|
||||
t.Fatal("Jitter does not match")
|
||||
}
|
||||
if netem.LossCorr != qdiscnetem.LossCorr {
|
||||
t.Fatal("Loss does not match")
|
||||
}
|
||||
if netem.DuplicateCorr != qdiscnetem.DuplicateCorr {
|
||||
t.Fatal("DuplicateCorr does not match")
|
||||
}
|
||||
|
||||
// Deletion
|
||||
if err := ClassDel(class); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
classes, err = ClassList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(classes) != 0 {
|
||||
t.Fatal("Failed to remove class")
|
||||
}
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHtbClassAddHtbClassChangeDel(t *testing.T) {
|
||||
/**
|
||||
This test first set up a interface ans set up a Htb qdisc
|
||||
A HTB class is attach to it and a Netem qdisc is attached to that class
|
||||
Next, we test changing the HTB class in place and confirming the Netem is
|
||||
still attached. We also check that invoting ClassChange with a non-existing
|
||||
class will fail.
|
||||
Finally, we test ClassReplace. We confirm it correctly behave like
|
||||
ClassChange when the parent/handle pair exists and that it will create a
|
||||
new class if the handle is modified.
|
||||
*/
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
attrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(0xffff, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
}
|
||||
qdisc := NewHtb(attrs)
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
_, ok := qdiscs[0].(*Htb)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
|
||||
classattrs := ClassAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Parent: MakeHandle(0xffff, 0),
|
||||
Handle: MakeHandle(0xffff, 2),
|
||||
}
|
||||
|
||||
htbclassattrs := HtbClassAttrs{
|
||||
Rate: 1234000,
|
||||
Cbuffer: 1690,
|
||||
}
|
||||
class := NewHtbClass(classattrs, htbclassattrs)
|
||||
if err := ClassAdd(class); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
classes, err := ClassList(link, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(classes) != 1 {
|
||||
t.Fatal("Failed to add class")
|
||||
}
|
||||
|
||||
htb, ok := classes[0].(*HtbClass)
|
||||
if !ok {
|
||||
t.Fatal("Class is the wrong type")
|
||||
}
|
||||
|
||||
qattrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(0x2, 0),
|
||||
Parent: MakeHandle(0xffff, 2),
|
||||
}
|
||||
nattrs := NetemQdiscAttrs{
|
||||
Latency: 20000,
|
||||
Loss: 23.4,
|
||||
Duplicate: 14.3,
|
||||
LossCorr: 8.34,
|
||||
Jitter: 1000,
|
||||
DelayCorr: 12.3,
|
||||
ReorderProb: 23.4,
|
||||
CorruptProb: 10.0,
|
||||
CorruptCorr: 10,
|
||||
}
|
||||
qdiscnetem := NewNetem(qattrs, nattrs)
|
||||
if err := QdiscAdd(qdiscnetem); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 2 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
|
||||
_, ok = qdiscs[1].(*Netem)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
|
||||
// Change
|
||||
// For change to work, the handle and parent cannot be changed.
|
||||
|
||||
// First, test it fails if we change the Handle.
|
||||
old_handle := classattrs.Handle
|
||||
classattrs.Handle = MakeHandle(0xffff, 3)
|
||||
class = NewHtbClass(classattrs, htbclassattrs)
|
||||
if err := ClassChange(class); err == nil {
|
||||
t.Fatal("ClassChange should not work when using a different handle.")
|
||||
}
|
||||
// It should work with the same handle
|
||||
classattrs.Handle = old_handle
|
||||
htbclassattrs.Rate = 4321000
|
||||
class = NewHtbClass(classattrs, htbclassattrs)
|
||||
if err := ClassChange(class); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
classes, err = ClassList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(classes) != 1 {
|
||||
t.Fatalf(
|
||||
"1 class expected, %d found",
|
||||
len(classes),
|
||||
)
|
||||
}
|
||||
|
||||
htb, ok = classes[0].(*HtbClass)
|
||||
if !ok {
|
||||
t.Fatal("Class is the wrong type")
|
||||
}
|
||||
// Verify that the rate value has changed.
|
||||
if htb.Rate != class.Rate {
|
||||
t.Fatal("Rate did not get changed while changing the class.")
|
||||
}
|
||||
|
||||
// Check that we still have the netem child qdisc
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(qdiscs) != 2 {
|
||||
t.Fatalf("2 qdisc expected, %d found", len(qdiscs))
|
||||
}
|
||||
_, ok = qdiscs[0].(*Htb)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
|
||||
_, ok = qdiscs[1].(*Netem)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
|
||||
// Replace
|
||||
// First replace by keeping the same handle, class will be changed.
|
||||
// Then, replace by providing a new handle, n new class will be created.
|
||||
|
||||
// Replace acting as Change
|
||||
class = NewHtbClass(classattrs, htbclassattrs)
|
||||
if err := ClassReplace(class); err != nil {
|
||||
t.Fatal("Failed to replace class that is existing.")
|
||||
}
|
||||
|
||||
classes, err = ClassList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(classes) != 1 {
|
||||
t.Fatalf(
|
||||
"1 class expected, %d found",
|
||||
len(classes),
|
||||
)
|
||||
}
|
||||
|
||||
htb, ok = classes[0].(*HtbClass)
|
||||
if !ok {
|
||||
t.Fatal("Class is the wrong type")
|
||||
}
|
||||
// Verify that the rate value has changed.
|
||||
if htb.Rate != class.Rate {
|
||||
t.Fatal("Rate did not get changed while changing the class.")
|
||||
}
|
||||
|
||||
// It should work with the same handle
|
||||
classattrs.Handle = MakeHandle(0xffff, 3)
|
||||
class = NewHtbClass(classattrs, htbclassattrs)
|
||||
if err := ClassReplace(class); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
classes, err = ClassList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(classes) != 2 {
|
||||
t.Fatalf(
|
||||
"2 classes expected, %d found",
|
||||
len(classes),
|
||||
)
|
||||
}
|
||||
|
||||
htb, ok = classes[1].(*HtbClass)
|
||||
if !ok {
|
||||
t.Fatal("Class is the wrong type")
|
||||
}
|
||||
// Verify that the rate value has changed.
|
||||
if htb.Rate != class.Rate {
|
||||
t.Fatal("Rate did not get changed while changing the class.")
|
||||
}
|
||||
|
||||
// Deletion
|
||||
for _, class := range classes {
|
||||
if err := ClassDel(class); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
classes, err = ClassList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(classes) != 0 {
|
||||
t.Fatal("Failed to remove class")
|
||||
}
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
248
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_test.go
generated
vendored
Normal file
248
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_test.go
generated
vendored
Normal file
|
@ -0,0 +1,248 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
)
|
||||
|
||||
func TestFilterAddDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
redir, err := LinkByName("bar")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(redir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdisc := &Ingress{
|
||||
QdiscAttrs: QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(0xffff, 0),
|
||||
Parent: HANDLE_INGRESS,
|
||||
},
|
||||
}
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
_, ok := qdiscs[0].(*Ingress)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
filter := &U32{
|
||||
FilterAttrs: FilterAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Parent: MakeHandle(0xffff, 0),
|
||||
Priority: 1,
|
||||
Protocol: syscall.ETH_P_IP,
|
||||
},
|
||||
RedirIndex: redir.Attrs().Index,
|
||||
}
|
||||
if err := FilterAdd(filter); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
filters, err := FilterList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(filters) != 1 {
|
||||
t.Fatal("Failed to add filter")
|
||||
}
|
||||
if err := FilterDel(filter); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
filters, err = FilterList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(filters) != 0 {
|
||||
t.Fatal("Failed to remove filter")
|
||||
}
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterFwAddDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
redir, err := LinkByName("bar")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(redir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
attrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(0xffff, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
}
|
||||
qdisc := NewHtb(attrs)
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
_, ok := qdiscs[0].(*Htb)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
|
||||
classattrs := ClassAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Parent: MakeHandle(0xffff, 0),
|
||||
Handle: MakeHandle(0xffff, 2),
|
||||
}
|
||||
|
||||
htbclassattrs := HtbClassAttrs{
|
||||
Rate: 1234000,
|
||||
Cbuffer: 1690,
|
||||
}
|
||||
class := NewHtbClass(classattrs, htbclassattrs)
|
||||
if err := ClassAdd(class); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
classes, err := ClassList(link, MakeHandle(0xffff, 2))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(classes) != 1 {
|
||||
t.Fatal("Failed to add class")
|
||||
}
|
||||
|
||||
filterattrs := FilterAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Parent: MakeHandle(0xffff, 0),
|
||||
Handle: MakeHandle(0, 0x6),
|
||||
Priority: 1,
|
||||
Protocol: syscall.ETH_P_IP,
|
||||
}
|
||||
fwattrs := FilterFwAttrs{
|
||||
Buffer: 12345,
|
||||
Rate: 1234,
|
||||
PeakRate: 2345,
|
||||
Action: nl.TC_POLICE_SHOT,
|
||||
ClassId: MakeHandle(0xffff, 2),
|
||||
}
|
||||
|
||||
filter, err := NewFw(filterattrs, fwattrs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := FilterAdd(filter); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
filters, err := FilterList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(filters) != 1 {
|
||||
t.Fatal("Failed to add filter")
|
||||
}
|
||||
fw, ok := filters[0].(*Fw)
|
||||
if !ok {
|
||||
t.Fatal("Filter is the wrong type")
|
||||
}
|
||||
if fw.Police.Rate.Rate != filter.Police.Rate.Rate {
|
||||
t.Fatal("Police Rate doesn't match")
|
||||
}
|
||||
for i := range fw.Rtab {
|
||||
if fw.Rtab[i] != filter.Rtab[i] {
|
||||
t.Fatal("Rtab doesn't match")
|
||||
}
|
||||
if fw.Ptab[i] != filter.Ptab[i] {
|
||||
t.Fatal("Ptab doesn't match")
|
||||
}
|
||||
}
|
||||
if fw.ClassId != filter.ClassId {
|
||||
t.Fatal("ClassId doesn't match")
|
||||
}
|
||||
if fw.InDev != filter.InDev {
|
||||
t.Fatal("InDev doesn't match")
|
||||
}
|
||||
if fw.AvRate != filter.AvRate {
|
||||
t.Fatal("AvRate doesn't match")
|
||||
}
|
||||
|
||||
if err := FilterDel(filter); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
filters, err = FilterList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(filters) != 0 {
|
||||
t.Fatal("Failed to remove filter")
|
||||
}
|
||||
if err := ClassDel(class); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
classes, err = ClassList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(classes) != 0 {
|
||||
t.Fatal("Failed to remove class")
|
||||
}
|
||||
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
312
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go
generated
vendored
312
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
@ -29,6 +30,7 @@ type LinkAttrs struct {
|
|||
ParentIndex int // index of the parent link device
|
||||
MasterIndex int // must be the index of a bridge
|
||||
Namespace interface{} // nil | NsPid | NsFd
|
||||
Alias string
|
||||
}
|
||||
|
||||
// NewLinkAttrs returns LinkAttrs structure filled with default values
|
||||
|
@ -240,6 +242,316 @@ func (ipvlan *IPVlan) Type() string {
|
|||
return "ipvlan"
|
||||
}
|
||||
|
||||
// BondMode type
|
||||
type BondMode int
|
||||
|
||||
func (b BondMode) String() string {
|
||||
s, ok := bondModeToString[b]
|
||||
if !ok {
|
||||
return fmt.Sprintf("BondMode(%d)", b)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// StringToBondMode returns bond mode, or uknonw is the s is invalid.
|
||||
func StringToBondMode(s string) BondMode {
|
||||
mode, ok := StringToBondModeMap[s]
|
||||
if !ok {
|
||||
return BOND_MODE_UNKNOWN
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
||||
// Possible BondMode
|
||||
const (
|
||||
BOND_MODE_802_3AD BondMode = iota
|
||||
BOND_MODE_BALANCE_RR
|
||||
BOND_MODE_ACTIVE_BACKUP
|
||||
BOND_MODE_BALANCE_XOR
|
||||
BOND_MODE_BROADCAST
|
||||
BOND_MODE_BALANCE_TLB
|
||||
BOND_MODE_BALANCE_ALB
|
||||
BOND_MODE_UNKNOWN
|
||||
)
|
||||
|
||||
var bondModeToString = map[BondMode]string{
|
||||
BOND_MODE_802_3AD: "802.3ad",
|
||||
BOND_MODE_BALANCE_RR: "balance-rr",
|
||||
BOND_MODE_ACTIVE_BACKUP: "active-backup",
|
||||
BOND_MODE_BALANCE_XOR: "balance-xor",
|
||||
BOND_MODE_BROADCAST: "broadcast",
|
||||
BOND_MODE_BALANCE_TLB: "balance-tlb",
|
||||
BOND_MODE_BALANCE_ALB: "balance-alb",
|
||||
}
|
||||
var StringToBondModeMap = map[string]BondMode{
|
||||
"802.3ad": BOND_MODE_802_3AD,
|
||||
"balance-rr": BOND_MODE_BALANCE_RR,
|
||||
"active-backup": BOND_MODE_ACTIVE_BACKUP,
|
||||
"balance-xor": BOND_MODE_BALANCE_XOR,
|
||||
"broadcast": BOND_MODE_BROADCAST,
|
||||
"balance-tlb": BOND_MODE_BALANCE_TLB,
|
||||
"balance-alb": BOND_MODE_BALANCE_ALB,
|
||||
}
|
||||
|
||||
// BondArpValidate type
|
||||
type BondArpValidate int
|
||||
|
||||
// Possible BondArpValidate value
|
||||
const (
|
||||
BOND_ARP_VALIDATE_NONE BondArpValidate = iota
|
||||
BOND_ARP_VALIDATE_ACTIVE
|
||||
BOND_ARP_VALIDATE_BACKUP
|
||||
BOND_ARP_VALIDATE_ALL
|
||||
)
|
||||
|
||||
// BondPrimaryReselect type
|
||||
type BondPrimaryReselect int
|
||||
|
||||
// Possible BondPrimaryReselect value
|
||||
const (
|
||||
BOND_PRIMARY_RESELECT_ALWAYS BondPrimaryReselect = iota
|
||||
BOND_PRIMARY_RESELECT_BETTER
|
||||
BOND_PRIMARY_RESELECT_FAILURE
|
||||
)
|
||||
|
||||
// BondArpAllTargets type
|
||||
type BondArpAllTargets int
|
||||
|
||||
// Possible BondArpAllTargets value
|
||||
const (
|
||||
BOND_ARP_ALL_TARGETS_ANY BondArpAllTargets = iota
|
||||
BOND_ARP_ALL_TARGETS_ALL
|
||||
)
|
||||
|
||||
// BondFailOverMac type
|
||||
type BondFailOverMac int
|
||||
|
||||
// Possible BondFailOverMac value
|
||||
const (
|
||||
BOND_FAIL_OVER_MAC_NONE BondFailOverMac = iota
|
||||
BOND_FAIL_OVER_MAC_ACTIVE
|
||||
BOND_FAIL_OVER_MAC_FOLLOW
|
||||
)
|
||||
|
||||
// BondXmitHashPolicy type
|
||||
type BondXmitHashPolicy int
|
||||
|
||||
func (b BondXmitHashPolicy) String() string {
|
||||
s, ok := bondXmitHashPolicyToString[b]
|
||||
if !ok {
|
||||
return fmt.Sprintf("XmitHashPolicy(%d)", b)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// StringToBondXmitHashPolicy returns bond lacp arte, or uknonw is the s is invalid.
|
||||
func StringToBondXmitHashPolicy(s string) BondXmitHashPolicy {
|
||||
lacp, ok := StringToBondXmitHashPolicyMap[s]
|
||||
if !ok {
|
||||
return BOND_XMIT_HASH_POLICY_UNKNOWN
|
||||
}
|
||||
return lacp
|
||||
}
|
||||
|
||||
// Possible BondXmitHashPolicy value
|
||||
const (
|
||||
BOND_XMIT_HASH_POLICY_LAYER2 BondXmitHashPolicy = iota
|
||||
BOND_XMIT_HASH_POLICY_LAYER3_4
|
||||
BOND_XMIT_HASH_POLICY_LAYER2_3
|
||||
BOND_XMIT_HASH_POLICY_ENCAP2_3
|
||||
BOND_XMIT_HASH_POLICY_ENCAP3_4
|
||||
BOND_XMIT_HASH_POLICY_UNKNOWN
|
||||
)
|
||||
|
||||
var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{
|
||||
BOND_XMIT_HASH_POLICY_LAYER2: "layer2",
|
||||
BOND_XMIT_HASH_POLICY_LAYER3_4: "layer3+4",
|
||||
BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3",
|
||||
BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3",
|
||||
BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4",
|
||||
}
|
||||
var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{
|
||||
"layer2": BOND_XMIT_HASH_POLICY_LAYER2,
|
||||
"layer3+4": BOND_XMIT_HASH_POLICY_LAYER3_4,
|
||||
"layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3,
|
||||
"encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3,
|
||||
"encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4,
|
||||
}
|
||||
|
||||
// BondLacpRate type
|
||||
type BondLacpRate int
|
||||
|
||||
func (b BondLacpRate) String() string {
|
||||
s, ok := bondLacpRateToString[b]
|
||||
if !ok {
|
||||
return fmt.Sprintf("LacpRate(%d)", b)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// StringToBondLacpRate returns bond lacp arte, or uknonw is the s is invalid.
|
||||
func StringToBondLacpRate(s string) BondLacpRate {
|
||||
lacp, ok := StringToBondLacpRateMap[s]
|
||||
if !ok {
|
||||
return BOND_LACP_RATE_UNKNOWN
|
||||
}
|
||||
return lacp
|
||||
}
|
||||
|
||||
// Possible BondLacpRate value
|
||||
const (
|
||||
BOND_LACP_RATE_SLOW BondLacpRate = iota
|
||||
BOND_LACP_RATE_FAST
|
||||
BOND_LACP_RATE_UNKNOWN
|
||||
)
|
||||
|
||||
var bondLacpRateToString = map[BondLacpRate]string{
|
||||
BOND_LACP_RATE_SLOW: "slow",
|
||||
BOND_LACP_RATE_FAST: "fast",
|
||||
}
|
||||
var StringToBondLacpRateMap = map[string]BondLacpRate{
|
||||
"slow": BOND_LACP_RATE_SLOW,
|
||||
"fast": BOND_LACP_RATE_FAST,
|
||||
}
|
||||
|
||||
// BondAdSelect type
|
||||
type BondAdSelect int
|
||||
|
||||
// Possible BondAdSelect value
|
||||
const (
|
||||
BOND_AD_SELECT_STABLE BondAdSelect = iota
|
||||
BOND_AD_SELECT_BANDWIDTH
|
||||
BOND_AD_SELECT_COUNT
|
||||
)
|
||||
|
||||
// BondAdInfo
|
||||
type BondAdInfo struct {
|
||||
AggregatorId int
|
||||
NumPorts int
|
||||
ActorKey int
|
||||
PartnerKey int
|
||||
PartnerMac net.HardwareAddr
|
||||
}
|
||||
|
||||
// Bond representation
|
||||
type Bond struct {
|
||||
LinkAttrs
|
||||
Mode BondMode
|
||||
ActiveSlave int
|
||||
Miimon int
|
||||
UpDelay int
|
||||
DownDelay int
|
||||
UseCarrier int
|
||||
ArpInterval int
|
||||
ArpIpTargets []net.IP
|
||||
ArpValidate BondArpValidate
|
||||
ArpAllTargets BondArpAllTargets
|
||||
Primary int
|
||||
PrimaryReselect BondPrimaryReselect
|
||||
FailOverMac BondFailOverMac
|
||||
XmitHashPolicy BondXmitHashPolicy
|
||||
ResendIgmp int
|
||||
NumPeerNotif int
|
||||
AllSlavesActive int
|
||||
MinLinks int
|
||||
LpInterval int
|
||||
PackersPerSlave int
|
||||
LacpRate BondLacpRate
|
||||
AdSelect BondAdSelect
|
||||
// looking at iproute tool AdInfo can only be retrived. It can't be set.
|
||||
AdInfo *BondAdInfo
|
||||
}
|
||||
|
||||
func NewLinkBond(atr LinkAttrs) *Bond {
|
||||
return &Bond{
|
||||
LinkAttrs: atr,
|
||||
Mode: -1,
|
||||
ActiveSlave: -1,
|
||||
Miimon: -1,
|
||||
UpDelay: -1,
|
||||
DownDelay: -1,
|
||||
UseCarrier: -1,
|
||||
ArpInterval: -1,
|
||||
ArpIpTargets: nil,
|
||||
ArpValidate: -1,
|
||||
ArpAllTargets: -1,
|
||||
Primary: -1,
|
||||
PrimaryReselect: -1,
|
||||
FailOverMac: -1,
|
||||
XmitHashPolicy: -1,
|
||||
ResendIgmp: -1,
|
||||
NumPeerNotif: -1,
|
||||
AllSlavesActive: -1,
|
||||
MinLinks: -1,
|
||||
LpInterval: -1,
|
||||
PackersPerSlave: -1,
|
||||
LacpRate: -1,
|
||||
AdSelect: -1,
|
||||
}
|
||||
}
|
||||
|
||||
// Flag mask for bond options. Bond.Flagmask must be set to on for option to work.
|
||||
const (
|
||||
BOND_MODE_MASK uint64 = 1 << (1 + iota)
|
||||
BOND_ACTIVE_SLAVE_MASK
|
||||
BOND_MIIMON_MASK
|
||||
BOND_UPDELAY_MASK
|
||||
BOND_DOWNDELAY_MASK
|
||||
BOND_USE_CARRIER_MASK
|
||||
BOND_ARP_INTERVAL_MASK
|
||||
BOND_ARP_VALIDATE_MASK
|
||||
BOND_ARP_ALL_TARGETS_MASK
|
||||
BOND_PRIMARY_MASK
|
||||
BOND_PRIMARY_RESELECT_MASK
|
||||
BOND_FAIL_OVER_MAC_MASK
|
||||
BOND_XMIT_HASH_POLICY_MASK
|
||||
BOND_RESEND_IGMP_MASK
|
||||
BOND_NUM_PEER_NOTIF_MASK
|
||||
BOND_ALL_SLAVES_ACTIVE_MASK
|
||||
BOND_MIN_LINKS_MASK
|
||||
BOND_LP_INTERVAL_MASK
|
||||
BOND_PACKETS_PER_SLAVE_MASK
|
||||
BOND_LACP_RATE_MASK
|
||||
BOND_AD_SELECT_MASK
|
||||
)
|
||||
|
||||
// Attrs implementation.
|
||||
func (bond *Bond) Attrs() *LinkAttrs {
|
||||
return &bond.LinkAttrs
|
||||
}
|
||||
|
||||
// Type implementation fro Vxlan.
|
||||
func (bond *Bond) Type() string {
|
||||
return "bond"
|
||||
}
|
||||
|
||||
// GreTap devices must specify LocalIP and RemoteIP on create
|
||||
type Gretap struct {
|
||||
LinkAttrs
|
||||
IKey uint32
|
||||
OKey uint32
|
||||
EncapSport uint16
|
||||
EncapDport uint16
|
||||
Local net.IP
|
||||
Remote net.IP
|
||||
IFlags uint16
|
||||
OFlags uint16
|
||||
PMtuDisc uint8
|
||||
Ttl uint8
|
||||
Tos uint8
|
||||
EncapType uint16
|
||||
EncapFlags uint16
|
||||
Link uint32
|
||||
}
|
||||
|
||||
func (gretap *Gretap) Attrs() *LinkAttrs {
|
||||
return &gretap.LinkAttrs
|
||||
}
|
||||
|
||||
func (gretap *Gretap) Type() string {
|
||||
return "gretap"
|
||||
}
|
||||
|
||||
// iproute2 supported devices;
|
||||
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
|
||||
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
|
||||
|
|
330
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go
generated
vendored
330
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go
generated
vendored
|
@ -106,6 +106,24 @@ func LinkSetName(link Link, name string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// LinkSetAlias sets the alias of the link device.
|
||||
// Equivalent to: `ip link set dev $link alias $name`
|
||||
func LinkSetAlias(link Link, name string) error {
|
||||
base := link.Attrs()
|
||||
ensureIndex(base)
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
data := nl.NewRtAttr(syscall.IFLA_IFALIAS, []byte(name))
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetHardwareAddr sets the hardware address of the link device.
|
||||
// Equivalent to: `ip link set $link address $hwaddr`
|
||||
func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
|
||||
|
@ -133,9 +151,18 @@ func LinkSetMaster(link Link, master *Bridge) error {
|
|||
ensureIndex(masterBase)
|
||||
index = masterBase.Index
|
||||
}
|
||||
if index <= 0 {
|
||||
return fmt.Errorf("Device does not exist")
|
||||
}
|
||||
return LinkSetMasterByIndex(link, index)
|
||||
}
|
||||
|
||||
// LinkSetNoMaster removes the master of the link device.
|
||||
// Equivalent to: `ip link set $link nomaster`
|
||||
func LinkSetNoMaster(link Link) error {
|
||||
return LinkSetMasterByIndex(link, 0)
|
||||
}
|
||||
|
||||
// LinkSetMasterByIndex sets the master of the link device.
|
||||
// Equivalent to: `ip link set $link master $master`
|
||||
func LinkSetMasterByIndex(link Link, masterIndex int) error {
|
||||
|
@ -275,6 +302,87 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
|
|||
}
|
||||
}
|
||||
|
||||
func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) {
|
||||
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
||||
if bond.Mode >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_MODE, nl.Uint8Attr(uint8(bond.Mode)))
|
||||
}
|
||||
if bond.ActiveSlave >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_ACTIVE_SLAVE, nl.Uint32Attr(uint32(bond.ActiveSlave)))
|
||||
}
|
||||
if bond.Miimon >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_MIIMON, nl.Uint32Attr(uint32(bond.Miimon)))
|
||||
}
|
||||
if bond.UpDelay >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_UPDELAY, nl.Uint32Attr(uint32(bond.UpDelay)))
|
||||
}
|
||||
if bond.DownDelay >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_DOWNDELAY, nl.Uint32Attr(uint32(bond.DownDelay)))
|
||||
}
|
||||
if bond.UseCarrier >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_USE_CARRIER, nl.Uint8Attr(uint8(bond.UseCarrier)))
|
||||
}
|
||||
if bond.ArpInterval >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_ARP_INTERVAL, nl.Uint32Attr(uint32(bond.ArpInterval)))
|
||||
}
|
||||
if bond.ArpIpTargets != nil {
|
||||
msg := nl.NewRtAttrChild(data, nl.IFLA_BOND_ARP_IP_TARGET, nil)
|
||||
for i := range bond.ArpIpTargets {
|
||||
ip := bond.ArpIpTargets[i].To4()
|
||||
if ip != nil {
|
||||
nl.NewRtAttrChild(msg, i, []byte(ip))
|
||||
continue
|
||||
}
|
||||
ip = bond.ArpIpTargets[i].To16()
|
||||
if ip != nil {
|
||||
nl.NewRtAttrChild(msg, i, []byte(ip))
|
||||
}
|
||||
}
|
||||
}
|
||||
if bond.ArpValidate >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_ARP_VALIDATE, nl.Uint32Attr(uint32(bond.ArpValidate)))
|
||||
}
|
||||
if bond.ArpAllTargets >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_ARP_ALL_TARGETS, nl.Uint32Attr(uint32(bond.ArpAllTargets)))
|
||||
}
|
||||
if bond.Primary >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_PRIMARY, nl.Uint32Attr(uint32(bond.Primary)))
|
||||
}
|
||||
if bond.PrimaryReselect >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_PRIMARY_RESELECT, nl.Uint8Attr(uint8(bond.PrimaryReselect)))
|
||||
}
|
||||
if bond.FailOverMac >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_FAIL_OVER_MAC, nl.Uint8Attr(uint8(bond.FailOverMac)))
|
||||
}
|
||||
if bond.XmitHashPolicy >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_XMIT_HASH_POLICY, nl.Uint8Attr(uint8(bond.XmitHashPolicy)))
|
||||
}
|
||||
if bond.ResendIgmp >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_RESEND_IGMP, nl.Uint32Attr(uint32(bond.ResendIgmp)))
|
||||
}
|
||||
if bond.NumPeerNotif >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_NUM_PEER_NOTIF, nl.Uint8Attr(uint8(bond.NumPeerNotif)))
|
||||
}
|
||||
if bond.AllSlavesActive >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_ALL_SLAVES_ACTIVE, nl.Uint8Attr(uint8(bond.AllSlavesActive)))
|
||||
}
|
||||
if bond.MinLinks >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_MIN_LINKS, nl.Uint32Attr(uint32(bond.MinLinks)))
|
||||
}
|
||||
if bond.LpInterval >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval)))
|
||||
}
|
||||
if bond.PackersPerSlave >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PackersPerSlave)))
|
||||
}
|
||||
if bond.LacpRate >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate)))
|
||||
}
|
||||
if bond.AdSelect >= 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect)))
|
||||
}
|
||||
}
|
||||
|
||||
// LinkAdd adds a new link device. The type and features of the device
|
||||
// are taken fromt the parameters in the link object.
|
||||
// Equivalent to: `ip link add $link`
|
||||
|
@ -328,6 +436,27 @@ func LinkAdd(link Link) error {
|
|||
req := nl.NewNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
||||
// TODO: make it shorter
|
||||
if base.Flags&net.FlagUp != 0 {
|
||||
msg.Change = syscall.IFF_UP
|
||||
msg.Flags = syscall.IFF_UP
|
||||
}
|
||||
if base.Flags&net.FlagBroadcast != 0 {
|
||||
msg.Change |= syscall.IFF_BROADCAST
|
||||
msg.Flags |= syscall.IFF_BROADCAST
|
||||
}
|
||||
if base.Flags&net.FlagLoopback != 0 {
|
||||
msg.Change |= syscall.IFF_LOOPBACK
|
||||
msg.Flags |= syscall.IFF_LOOPBACK
|
||||
}
|
||||
if base.Flags&net.FlagPointToPoint != 0 {
|
||||
msg.Change |= syscall.IFF_POINTOPOINT
|
||||
msg.Flags |= syscall.IFF_POINTOPOINT
|
||||
}
|
||||
if base.Flags&net.FlagMulticast != 0 {
|
||||
msg.Change |= syscall.IFF_MULTICAST
|
||||
msg.Flags |= syscall.IFF_MULTICAST
|
||||
}
|
||||
req.AddData(msg)
|
||||
|
||||
if base.ParentIndex != 0 {
|
||||
|
@ -388,6 +517,8 @@ func LinkAdd(link Link) error {
|
|||
|
||||
} else if vxlan, ok := link.(*Vxlan); ok {
|
||||
addVxlanAttrs(vxlan, linkInfo)
|
||||
} else if bond, ok := link.(*Bond); ok {
|
||||
addBondAttrs(bond, linkInfo)
|
||||
} else if ipv, ok := link.(*IPVlan); ok {
|
||||
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
||||
nl.NewRtAttrChild(data, nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(ipv.Mode)))
|
||||
|
@ -396,6 +527,8 @@ func LinkAdd(link Link) error {
|
|||
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
||||
nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macv.Mode]))
|
||||
}
|
||||
} else if gretap, ok := link.(*Gretap); ok {
|
||||
addGretapAttrs(gretap, linkInfo)
|
||||
}
|
||||
|
||||
req.AddData(linkInfo)
|
||||
|
@ -447,6 +580,20 @@ func linkByNameDump(name string) (Link, error) {
|
|||
return nil, fmt.Errorf("Link %s not found", name)
|
||||
}
|
||||
|
||||
func linkByAliasDump(alias string) (Link, error) {
|
||||
links, err := LinkList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, link := range links {
|
||||
if link.Attrs().Alias == alias {
|
||||
return link, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Link alias %s not found", alias)
|
||||
}
|
||||
|
||||
// LinkByName finds a link by name and returns a pointer to the object.
|
||||
func LinkByName(name string) (Link, error) {
|
||||
if lookupByDump {
|
||||
|
@ -472,6 +619,32 @@ func LinkByName(name string) (Link, error) {
|
|||
return link, err
|
||||
}
|
||||
|
||||
// LinkByAlias finds a link by its alias and returns a pointer to the object.
|
||||
// If there are multiple links with the alias it returns the first one
|
||||
func LinkByAlias(alias string) (Link, error) {
|
||||
if lookupByDump {
|
||||
return linkByAliasDump(alias)
|
||||
}
|
||||
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
||||
req.AddData(msg)
|
||||
|
||||
nameData := nl.NewRtAttr(syscall.IFLA_IFALIAS, nl.ZeroTerminated(alias))
|
||||
req.AddData(nameData)
|
||||
|
||||
link, err := execGetLink(req)
|
||||
if err == syscall.EINVAL {
|
||||
// older kernels don't support looking up via IFLA_IFALIAS
|
||||
// so fall back to dumping all links
|
||||
lookupByDump = true
|
||||
return linkByAliasDump(alias)
|
||||
}
|
||||
|
||||
return link, err
|
||||
}
|
||||
|
||||
// LinkByIndex finds a link by index and returns a pointer to the object.
|
||||
func LinkByIndex(index int) (Link, error) {
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_ACK)
|
||||
|
@ -543,12 +716,16 @@ func linkDeserialize(m []byte) (Link, error) {
|
|||
link = &Veth{}
|
||||
case "vxlan":
|
||||
link = &Vxlan{}
|
||||
case "bond":
|
||||
link = &Bond{}
|
||||
case "ipvlan":
|
||||
link = &IPVlan{}
|
||||
case "macvlan":
|
||||
link = &Macvlan{}
|
||||
case "macvtap":
|
||||
link = &Macvtap{}
|
||||
case "gretap":
|
||||
link = &Gretap{}
|
||||
default:
|
||||
link = &GenericLink{LinkType: linkType}
|
||||
}
|
||||
|
@ -562,12 +739,16 @@ func linkDeserialize(m []byte) (Link, error) {
|
|||
parseVlanData(link, data)
|
||||
case "vxlan":
|
||||
parseVxlanData(link, data)
|
||||
case "bond":
|
||||
parseBondData(link, data)
|
||||
case "ipvlan":
|
||||
parseIPVlanData(link, data)
|
||||
case "macvlan":
|
||||
parseMacvlanData(link, data)
|
||||
case "macvtap":
|
||||
parseMacvtapData(link, data)
|
||||
case "gretap":
|
||||
parseGretapData(link, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -591,6 +772,8 @@ func linkDeserialize(m []byte) (Link, error) {
|
|||
base.MasterIndex = int(native.Uint32(attr.Value[0:4]))
|
||||
case syscall.IFLA_TXQLEN:
|
||||
base.TxQLen = int(native.Uint32(attr.Value[0:4]))
|
||||
case syscall.IFLA_IFALIAS:
|
||||
base.Alias = string(attr.Value[:len(attr.Value)-1])
|
||||
}
|
||||
}
|
||||
// Links that don't have IFLA_INFO_KIND are hardware devices
|
||||
|
@ -772,6 +955,60 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
|||
}
|
||||
}
|
||||
|
||||
func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
bond := NewLinkBond(NewLinkAttrs())
|
||||
for i := range data {
|
||||
switch data[i].Attr.Type {
|
||||
case nl.IFLA_BOND_MODE:
|
||||
bond.Mode = BondMode(data[i].Value[0])
|
||||
case nl.IFLA_BOND_ACTIVE_SLAVE:
|
||||
bond.ActiveSlave = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_MIIMON:
|
||||
bond.Miimon = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_UPDELAY:
|
||||
bond.UpDelay = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_DOWNDELAY:
|
||||
bond.DownDelay = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_USE_CARRIER:
|
||||
bond.UseCarrier = int(data[i].Value[0])
|
||||
case nl.IFLA_BOND_ARP_INTERVAL:
|
||||
bond.ArpInterval = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_ARP_IP_TARGET:
|
||||
// TODO: implement
|
||||
case nl.IFLA_BOND_ARP_VALIDATE:
|
||||
bond.ArpValidate = BondArpValidate(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_ARP_ALL_TARGETS:
|
||||
bond.ArpAllTargets = BondArpAllTargets(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_PRIMARY:
|
||||
bond.Primary = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_PRIMARY_RESELECT:
|
||||
bond.PrimaryReselect = BondPrimaryReselect(data[i].Value[0])
|
||||
case nl.IFLA_BOND_FAIL_OVER_MAC:
|
||||
bond.FailOverMac = BondFailOverMac(data[i].Value[0])
|
||||
case nl.IFLA_BOND_XMIT_HASH_POLICY:
|
||||
bond.XmitHashPolicy = BondXmitHashPolicy(data[i].Value[0])
|
||||
case nl.IFLA_BOND_RESEND_IGMP:
|
||||
bond.ResendIgmp = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_NUM_PEER_NOTIF:
|
||||
bond.NumPeerNotif = int(data[i].Value[0])
|
||||
case nl.IFLA_BOND_ALL_SLAVES_ACTIVE:
|
||||
bond.AllSlavesActive = int(data[i].Value[0])
|
||||
case nl.IFLA_BOND_MIN_LINKS:
|
||||
bond.MinLinks = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_LP_INTERVAL:
|
||||
bond.LpInterval = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_PACKETS_PER_SLAVE:
|
||||
bond.PackersPerSlave = int(native.Uint32(data[i].Value[0:4]))
|
||||
case nl.IFLA_BOND_AD_LACP_RATE:
|
||||
bond.LacpRate = BondLacpRate(data[i].Value[0])
|
||||
case nl.IFLA_BOND_AD_SELECT:
|
||||
bond.AdSelect = BondAdSelect(data[i].Value[0])
|
||||
case nl.IFLA_BOND_AD_INFO:
|
||||
// TODO: implement
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
ipv := link.(*IPVlan)
|
||||
for _, datum := range data {
|
||||
|
@ -828,3 +1065,96 @@ func linkFlags(rawFlags uint32) net.Flags {
|
|||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func htonl(val uint32) []byte {
|
||||
bytes := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(bytes, val)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func htons(val uint16) []byte {
|
||||
bytes := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(bytes, val)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func ntohl(buf []byte) uint32 {
|
||||
return binary.BigEndian.Uint32(buf)
|
||||
}
|
||||
|
||||
func ntohs(buf []byte) uint16 {
|
||||
return binary.BigEndian.Uint16(buf)
|
||||
}
|
||||
|
||||
func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
|
||||
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
ip := gretap.Local.To4()
|
||||
if ip != nil {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_LOCAL, []byte(ip))
|
||||
}
|
||||
ip = gretap.Remote.To4()
|
||||
if ip != nil {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_REMOTE, []byte(ip))
|
||||
}
|
||||
|
||||
if gretap.IKey != 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_IKEY, htonl(gretap.IKey))
|
||||
gretap.IFlags |= uint16(nl.GRE_KEY)
|
||||
}
|
||||
|
||||
if gretap.OKey != 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_OKEY, htonl(gretap.OKey))
|
||||
gretap.OFlags |= uint16(nl.GRE_KEY)
|
||||
}
|
||||
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_IFLAGS, htons(gretap.IFlags))
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_OFLAGS, htons(gretap.OFlags))
|
||||
|
||||
if gretap.Link != 0 {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_LINK, nl.Uint32Attr(gretap.Link))
|
||||
}
|
||||
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gretap.PMtuDisc))
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_TTL, nl.Uint8Attr(gretap.Ttl))
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_TOS, nl.Uint8Attr(gretap.Tos))
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gretap.EncapType))
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gretap.EncapFlags))
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_SPORT, htons(gretap.EncapSport))
|
||||
nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_DPORT, htons(gretap.EncapDport))
|
||||
}
|
||||
|
||||
func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
gre := link.(*Gretap)
|
||||
for _, datum := range data {
|
||||
switch datum.Attr.Type {
|
||||
case nl.IFLA_GRE_OKEY:
|
||||
gre.IKey = ntohl(datum.Value[0:4])
|
||||
case nl.IFLA_GRE_IKEY:
|
||||
gre.OKey = ntohl(datum.Value[0:4])
|
||||
case nl.IFLA_GRE_LOCAL:
|
||||
gre.Local = net.IP(datum.Value[0:4])
|
||||
case nl.IFLA_GRE_REMOTE:
|
||||
gre.Remote = net.IP(datum.Value[0:4])
|
||||
case nl.IFLA_GRE_ENCAP_SPORT:
|
||||
gre.EncapSport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_GRE_ENCAP_DPORT:
|
||||
gre.EncapDport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_GRE_IFLAGS:
|
||||
gre.IFlags = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_GRE_OFLAGS:
|
||||
gre.OFlags = ntohs(datum.Value[0:2])
|
||||
|
||||
case nl.IFLA_GRE_TTL:
|
||||
gre.Ttl = uint8(datum.Value[0])
|
||||
case nl.IFLA_GRE_TOS:
|
||||
gre.Tos = uint8(datum.Value[0])
|
||||
case nl.IFLA_GRE_PMTUDISC:
|
||||
gre.PMtuDisc = uint8(datum.Value[0])
|
||||
case nl.IFLA_GRE_ENCAP_TYPE:
|
||||
gre.EncapType = native.Uint16(datum.Value[0:2])
|
||||
case nl.IFLA_GRE_ENCAP_FLAGS:
|
||||
gre.EncapFlags = native.Uint16(datum.Value[0:2])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
781
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go
generated
vendored
Normal file
781
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go
generated
vendored
Normal file
|
@ -0,0 +1,781 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"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 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 original, ok := link.(*Veth); ok {
|
||||
if original.PeerName != "" {
|
||||
var peer *Veth
|
||||
other, err := LinkByName(original.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// recent kernels set the parent index for veths in the response
|
||||
if rBase.ParentIndex == 0 && base.ParentIndex != 0 {
|
||||
t.Fatal("Created link doesn't have parent %d but it should", base.ParentIndex)
|
||||
} else if rBase.ParentIndex != 0 && base.ParentIndex == 0 {
|
||||
t.Fatalf("Created link has parent %d but it shouldn't", rBase.ParentIndex)
|
||||
} else if rBase.ParentIndex != 0 && base.ParentIndex != 0 {
|
||||
if rBase.ParentIndex != base.ParentIndex {
|
||||
t.Fatalf("Link.ParentIndex doesn't match %d != %d", rBase.ParentIndex, base.ParentIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
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 TestLinkAddDelIfb(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
testLinkAddDel(t, &Ifb{LinkAttrs{Name: "foo"}})
|
||||
}
|
||||
|
||||
func TestLinkAddDelBridge(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
testLinkAddDel(t, &Bridge{LinkAttrs{Name: "foo", MTU: 1400}})
|
||||
}
|
||||
|
||||
func TestLinkAddDelGretap(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
testLinkAddDel(t, &Gretap{
|
||||
LinkAttrs: LinkAttrs{Name: "foo"},
|
||||
IKey: 0x101,
|
||||
OKey: 0x101,
|
||||
PMtuDisc: 1,
|
||||
Local: net.IPv4(127, 0, 0, 1),
|
||||
Remote: net.IPv4(127, 0, 0, 1)})
|
||||
}
|
||||
|
||||
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 TestLinkAddDelMacvtap(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
parent := &Dummy{LinkAttrs{Name: "foo"}}
|
||||
if err := LinkAdd(parent); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testLinkAddDel(t, &Macvtap{
|
||||
Macvlan: 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()
|
||||
|
||||
veth := &Veth{LinkAttrs: LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1400}, PeerName: "bar"}
|
||||
testLinkAddDel(t, veth)
|
||||
}
|
||||
|
||||
func TestLinkAddDelBond(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
testLinkAddDel(t, NewLinkBond(LinkAttrs{Name: "foo"}))
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
nonexistsmaster := &Bridge{LinkAttrs{Name: "foobar"}}
|
||||
|
||||
if err := LinkSetMaster(slave, nonexistsmaster); err == nil {
|
||||
t.Fatal("error expected")
|
||||
}
|
||||
|
||||
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 := LinkSetNoMaster(slave); 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) {
|
||||
if os.Getenv("TRAVIS_BUILD_DIR") != "" {
|
||||
t.Skipf("Kernel in travis is too old for this test")
|
||||
}
|
||||
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) {
|
||||
if os.Getenv("TRAVIS_BUILD_DIR") != "" {
|
||||
t.Skipf("Kernel in travis is too old for this test")
|
||||
}
|
||||
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!")
|
||||
}
|
||||
|
||||
err = LinkSetAlias(link, "barAlias")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not set alias: %v", err)
|
||||
}
|
||||
|
||||
link, err = LinkByName("bar")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if link.Attrs().Alias != "barAlias" {
|
||||
t.Fatalf("alias not changed!")
|
||||
}
|
||||
|
||||
link, err = LinkByAlias("barAlias")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func expectLinkUpdate(ch <-chan LinkUpdate, ifaceName string, up bool) bool {
|
||||
for {
|
||||
timeout := time.After(time.Minute)
|
||||
select {
|
||||
case update := <-ch:
|
||||
if ifaceName == update.Link.Attrs().Name && (update.IfInfomsg.Flags&syscall.IFF_UP != 0) == up {
|
||||
return true
|
||||
}
|
||||
case <-timeout:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinkSubscribe(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
ch := make(chan LinkUpdate)
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
if err := LinkSubscribe(ch, done); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
link := &Veth{LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1400}, "bar"}
|
||||
if err := LinkAdd(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !expectLinkUpdate(ch, "foo", false) {
|
||||
t.Fatal("Add update not received as expected")
|
||||
}
|
||||
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !expectLinkUpdate(ch, "foo", true) {
|
||||
t.Fatal("Link Up update not received as expected")
|
||||
}
|
||||
|
||||
if err := LinkDel(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !expectLinkUpdate(ch, "foo", false) {
|
||||
t.Fatal("Del update not received as expected")
|
||||
}
|
||||
}
|
5
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
5
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
|
@ -70,10 +70,10 @@ func NeighAdd(neigh *Neigh) error {
|
|||
return neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL)
|
||||
}
|
||||
|
||||
// NeighAdd will add or replace an IP to MAC mapping to the ARP table
|
||||
// NeighSet will add or replace an IP to MAC mapping to the ARP table
|
||||
// Equivalent to: `ip neigh replace....`
|
||||
func NeighSet(neigh *Neigh) error {
|
||||
return neighAdd(neigh, syscall.NLM_F_CREATE)
|
||||
return neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE)
|
||||
}
|
||||
|
||||
// NeighAppend will append an entry to FDB
|
||||
|
@ -133,6 +133,7 @@ func NeighList(linkIndex, family int) ([]Neigh, error) {
|
|||
req := nl.NewNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
|
||||
msg := Ndmsg{
|
||||
Family: uint8(family),
|
||||
Index: uint32(linkIndex),
|
||||
}
|
||||
req.AddData(&msg)
|
||||
|
||||
|
|
104
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go
generated
vendored
Normal file
104
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go
generated
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
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)
|
||||
}
|
||||
}
|
7
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink.go
generated
vendored
7
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink.go
generated
vendored
|
@ -33,7 +33,10 @@ func ParseIPNet(s string) (*net.IPNet, error) {
|
|||
return &net.IPNet{IP: ip, Mask: ipNet.Mask}, nil
|
||||
}
|
||||
|
||||
// NewIPNet generates an IPNet from an ip address using a netmask of 32.
|
||||
// NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128.
|
||||
func NewIPNet(ip net.IP) *net.IPNet {
|
||||
return &net.IPNet{IP: ip, Mask: net.CIDRMask(32, 32)}
|
||||
if ip.To4() != nil {
|
||||
return &net.IPNet{IP: ip, Mask: net.CIDRMask(32, 32)}
|
||||
}
|
||||
return &net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)}
|
||||
}
|
||||
|
|
34
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go
generated
vendored
Normal file
34
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
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()
|
||||
}
|
||||
}
|
39
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go
generated
vendored
Normal file
39
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
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)
|
||||
}
|
80
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
80
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
|
@ -102,3 +102,83 @@ const (
|
|||
MACVLAN_MODE_PASSTHRU = 8
|
||||
MACVLAN_MODE_SOURCE = 16
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_BOND_UNSPEC = iota
|
||||
IFLA_BOND_MODE
|
||||
IFLA_BOND_ACTIVE_SLAVE
|
||||
IFLA_BOND_MIIMON
|
||||
IFLA_BOND_UPDELAY
|
||||
IFLA_BOND_DOWNDELAY
|
||||
IFLA_BOND_USE_CARRIER
|
||||
IFLA_BOND_ARP_INTERVAL
|
||||
IFLA_BOND_ARP_IP_TARGET
|
||||
IFLA_BOND_ARP_VALIDATE
|
||||
IFLA_BOND_ARP_ALL_TARGETS
|
||||
IFLA_BOND_PRIMARY
|
||||
IFLA_BOND_PRIMARY_RESELECT
|
||||
IFLA_BOND_FAIL_OVER_MAC
|
||||
IFLA_BOND_XMIT_HASH_POLICY
|
||||
IFLA_BOND_RESEND_IGMP
|
||||
IFLA_BOND_NUM_PEER_NOTIF
|
||||
IFLA_BOND_ALL_SLAVES_ACTIVE
|
||||
IFLA_BOND_MIN_LINKS
|
||||
IFLA_BOND_LP_INTERVAL
|
||||
IFLA_BOND_PACKETS_PER_SLAVE
|
||||
IFLA_BOND_AD_LACP_RATE
|
||||
IFLA_BOND_AD_SELECT
|
||||
IFLA_BOND_AD_INFO
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_BOND_AD_INFO_UNSPEC = iota
|
||||
IFLA_BOND_AD_INFO_AGGREGATOR
|
||||
IFLA_BOND_AD_INFO_NUM_PORTS
|
||||
IFLA_BOND_AD_INFO_ACTOR_KEY
|
||||
IFLA_BOND_AD_INFO_PARTNER_KEY
|
||||
IFLA_BOND_AD_INFO_PARTNER_MAC
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_BOND_SLAVE_UNSPEC = iota
|
||||
IFLA_BOND_SLAVE_STATE
|
||||
IFLA_BOND_SLAVE_MII_STATUS
|
||||
IFLA_BOND_SLAVE_LINK_FAILURE_COUNT
|
||||
IFLA_BOND_SLAVE_PERM_HWADDR
|
||||
IFLA_BOND_SLAVE_QUEUE_ID
|
||||
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_GRE_UNSPEC = iota
|
||||
IFLA_GRE_LINK
|
||||
IFLA_GRE_IFLAGS
|
||||
IFLA_GRE_OFLAGS
|
||||
IFLA_GRE_IKEY
|
||||
IFLA_GRE_OKEY
|
||||
IFLA_GRE_LOCAL
|
||||
IFLA_GRE_REMOTE
|
||||
IFLA_GRE_TTL
|
||||
IFLA_GRE_TOS
|
||||
IFLA_GRE_PMTUDISC
|
||||
IFLA_GRE_ENCAP_LIMIT
|
||||
IFLA_GRE_FLOWINFO
|
||||
IFLA_GRE_FLAGS
|
||||
IFLA_GRE_ENCAP_TYPE
|
||||
IFLA_GRE_ENCAP_FLAGS
|
||||
IFLA_GRE_ENCAP_SPORT
|
||||
IFLA_GRE_ENCAP_DPORT
|
||||
IFLA_GRE_COLLECT_METADATA
|
||||
IFLA_GRE_MAX = IFLA_GRE_COLLECT_METADATA
|
||||
)
|
||||
|
||||
const (
|
||||
GRE_CSUM = 0x8000
|
||||
GRE_ROUTING = 0x4000
|
||||
GRE_KEY = 0x2000
|
||||
GRE_SEQ = 0x1000
|
||||
GRE_STRICT = 0x0800
|
||||
GRE_REC = 0x0700
|
||||
GRE_FLAGS = 0x00F8
|
||||
GRE_VERSION = 0x0007
|
||||
)
|
||||
|
|
12
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
12
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
|
@ -149,10 +149,12 @@ func (a *RtAttr) Serialize() []byte {
|
|||
length := a.Len()
|
||||
buf := make([]byte, rtaAlignOf(length))
|
||||
|
||||
next := 4
|
||||
if a.Data != nil {
|
||||
copy(buf[4:], a.Data)
|
||||
} else {
|
||||
next := 4
|
||||
copy(buf[next:], a.Data)
|
||||
next += rtaAlignOf(len(a.Data))
|
||||
}
|
||||
if len(a.children) > 0 {
|
||||
for _, child := range a.children {
|
||||
childBuf := child.Serialize()
|
||||
copy(buf[next:], childBuf)
|
||||
|
@ -323,6 +325,10 @@ func (s *NetlinkSocket) Close() {
|
|||
syscall.Close(s.fd)
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) GetFd() int {
|
||||
return s.fd
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
|
||||
if err := syscall.Sendto(s.fd, request.Serialize(), 0, &s.lsa); err != nil {
|
||||
return err
|
||||
|
|
60
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go
generated
vendored
Normal file
60
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
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)
|
||||
}
|
43
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go
generated
vendored
Normal file
43
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
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)
|
||||
}
|
37
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
Normal file
37
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
package nl
|
||||
|
||||
// syscall package lack of rule atributes type.
|
||||
// Thus there are defined below
|
||||
const (
|
||||
FRA_UNSPEC = iota
|
||||
FRA_DST /* destination address */
|
||||
FRA_SRC /* source address */
|
||||
FRA_IIFNAME /* interface name */
|
||||
FRA_GOTO /* target to jump to (FR_ACT_GOTO) */
|
||||
FRA_UNUSED2
|
||||
FRA_PRIORITY /* priority/preference */
|
||||
FRA_UNUSED3
|
||||
FRA_UNUSED4
|
||||
FRA_UNUSED5
|
||||
FRA_FWMARK /* mark */
|
||||
FRA_FLOW /* flow/class id */
|
||||
FRA_TUN_ID
|
||||
FRA_SUPPRESS_IFGROUP
|
||||
FRA_SUPPRESS_PREFIXLEN
|
||||
FRA_TABLE /* Extended table id */
|
||||
FRA_FWMASK /* mask for netfilter mark */
|
||||
FRA_OIFNAME
|
||||
)
|
||||
|
||||
// ip rule netlink request types
|
||||
const (
|
||||
FR_ACT_UNSPEC = iota
|
||||
FR_ACT_TO_TBL /* Pass to fixed table */
|
||||
FR_ACT_GOTO /* Jump to another rule */
|
||||
FR_ACT_NOP /* No operation */
|
||||
FR_ACT_RES3
|
||||
FR_ACT_RES4
|
||||
FR_ACT_BLACKHOLE /* Drop without notification */
|
||||
FR_ACT_UNREACHABLE /* Drop with ENETUNREACH */
|
||||
FR_ACT_PROHIBIT /* Drop with EACCES */
|
||||
)
|
141
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
141
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
|
@ -56,17 +56,21 @@ const (
|
|||
)
|
||||
|
||||
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
|
||||
SizeofTcMsg = 0x14
|
||||
SizeofTcActionMsg = 0x04
|
||||
SizeofTcPrioMap = 0x14
|
||||
SizeofTcRateSpec = 0x0c
|
||||
SizeofTcNetemQopt = 0x18
|
||||
SizeofTcNetemCorr = 0x0c
|
||||
SizeofTcNetemReorder = 0x08
|
||||
SizeofTcNetemCorrupt = 0x08
|
||||
SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c
|
||||
SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14
|
||||
SizeofTcHtbGlob = 0x14
|
||||
SizeofTcU32Key = 0x10
|
||||
SizeofTcU32Sel = 0x10 // without keys
|
||||
SizeofTcMirred = 0x1c
|
||||
SizeofTcPolice = 2*SizeofTcRateSpec + 0x20
|
||||
)
|
||||
|
||||
// struct tcmsg {
|
||||
|
@ -191,6 +195,121 @@ func (x *TcRateSpec) Serialize() []byte {
|
|||
return (*(*[SizeofTcRateSpec]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
/**
|
||||
* NETEM
|
||||
*/
|
||||
|
||||
const (
|
||||
TCA_NETEM_UNSPEC = iota
|
||||
TCA_NETEM_CORR
|
||||
TCA_NETEM_DELAY_DIST
|
||||
TCA_NETEM_REORDER
|
||||
TCA_NETEM_CORRUPT
|
||||
TCA_NETEM_LOSS
|
||||
TCA_NETEM_RATE
|
||||
TCA_NETEM_ECN
|
||||
TCA_NETEM_RATE64
|
||||
TCA_NETEM_MAX = TCA_NETEM_RATE64
|
||||
)
|
||||
|
||||
// struct tc_netem_qopt {
|
||||
// __u32 latency; /* added delay (us) */
|
||||
// __u32 limit; /* fifo limit (packets) */
|
||||
// __u32 loss; /* random packet loss (0=none ~0=100%) */
|
||||
// __u32 gap; /* re-ordering gap (0 for none) */
|
||||
// __u32 duplicate; /* random packet dup (0=none ~0=100%) */
|
||||
// __u32 jitter; /* random jitter in latency (us) */
|
||||
// };
|
||||
|
||||
type TcNetemQopt struct {
|
||||
Latency uint32
|
||||
Limit uint32
|
||||
Loss uint32
|
||||
Gap uint32
|
||||
Duplicate uint32
|
||||
Jitter uint32
|
||||
}
|
||||
|
||||
func (msg *TcNetemQopt) Len() int {
|
||||
return SizeofTcNetemQopt
|
||||
}
|
||||
|
||||
func DeserializeTcNetemQopt(b []byte) *TcNetemQopt {
|
||||
return (*TcNetemQopt)(unsafe.Pointer(&b[0:SizeofTcNetemQopt][0]))
|
||||
}
|
||||
|
||||
func (x *TcNetemQopt) Serialize() []byte {
|
||||
return (*(*[SizeofTcNetemQopt]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// struct tc_netem_corr {
|
||||
// __u32 delay_corr; /* delay correlation */
|
||||
// __u32 loss_corr; /* packet loss correlation */
|
||||
// __u32 dup_corr; /* duplicate correlation */
|
||||
// };
|
||||
|
||||
type TcNetemCorr struct {
|
||||
DelayCorr uint32
|
||||
LossCorr uint32
|
||||
DupCorr uint32
|
||||
}
|
||||
|
||||
func (msg *TcNetemCorr) Len() int {
|
||||
return SizeofTcNetemCorr
|
||||
}
|
||||
|
||||
func DeserializeTcNetemCorr(b []byte) *TcNetemCorr {
|
||||
return (*TcNetemCorr)(unsafe.Pointer(&b[0:SizeofTcNetemCorr][0]))
|
||||
}
|
||||
|
||||
func (x *TcNetemCorr) Serialize() []byte {
|
||||
return (*(*[SizeofTcNetemCorr]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// struct tc_netem_reorder {
|
||||
// __u32 probability;
|
||||
// __u32 correlation;
|
||||
// };
|
||||
|
||||
type TcNetemReorder struct {
|
||||
Probability uint32
|
||||
Correlation uint32
|
||||
}
|
||||
|
||||
func (msg *TcNetemReorder) Len() int {
|
||||
return SizeofTcNetemReorder
|
||||
}
|
||||
|
||||
func DeserializeTcNetemReorder(b []byte) *TcNetemReorder {
|
||||
return (*TcNetemReorder)(unsafe.Pointer(&b[0:SizeofTcNetemReorder][0]))
|
||||
}
|
||||
|
||||
func (x *TcNetemReorder) Serialize() []byte {
|
||||
return (*(*[SizeofTcNetemReorder]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// struct tc_netem_corrupt {
|
||||
// __u32 probability;
|
||||
// __u32 correlation;
|
||||
// };
|
||||
|
||||
type TcNetemCorrupt struct {
|
||||
Probability uint32
|
||||
Correlation uint32
|
||||
}
|
||||
|
||||
func (msg *TcNetemCorrupt) Len() int {
|
||||
return SizeofTcNetemCorrupt
|
||||
}
|
||||
|
||||
func DeserializeTcNetemCorrupt(b []byte) *TcNetemCorrupt {
|
||||
return (*TcNetemCorrupt)(unsafe.Pointer(&b[0:SizeofTcNetemCorrupt][0]))
|
||||
}
|
||||
|
||||
func (x *TcNetemCorrupt) Serialize() []byte {
|
||||
return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// struct tc_tbf_qopt {
|
||||
// struct tc_ratespec rate;
|
||||
// struct tc_ratespec peakrate;
|
||||
|
|
173
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/tc_linux_test.go
generated
vendored
Normal file
173
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/tc_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
package nl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
)
|
||||
|
||||
/* TcMsg */
|
||||
func (msg *TcMsg) write(b []byte) {
|
||||
native := NativeEndian()
|
||||
b[0] = msg.Family
|
||||
copy(b[1:4], msg.Pad[:])
|
||||
native.PutUint32(b[4:8], uint32(msg.Ifindex))
|
||||
native.PutUint32(b[8:12], msg.Handle)
|
||||
native.PutUint32(b[12:16], msg.Parent)
|
||||
native.PutUint32(b[16:20], msg.Info)
|
||||
}
|
||||
|
||||
func (msg *TcMsg) serializeSafe() []byte {
|
||||
length := SizeofTcMsg
|
||||
b := make([]byte, length)
|
||||
msg.write(b)
|
||||
return b
|
||||
}
|
||||
|
||||
func deserializeTcMsgSafe(b []byte) *TcMsg {
|
||||
var msg = TcMsg{}
|
||||
binary.Read(bytes.NewReader(b[0:SizeofTcMsg]), NativeEndian(), &msg)
|
||||
return &msg
|
||||
}
|
||||
|
||||
func TestTcMsgDeserializeSerialize(t *testing.T) {
|
||||
var orig = make([]byte, SizeofTcMsg)
|
||||
rand.Read(orig)
|
||||
safemsg := deserializeTcMsgSafe(orig)
|
||||
msg := DeserializeTcMsg(orig)
|
||||
testDeserializeSerialize(t, orig, safemsg, msg)
|
||||
}
|
||||
|
||||
/* TcActionMsg */
|
||||
func (msg *TcActionMsg) write(b []byte) {
|
||||
b[0] = msg.Family
|
||||
copy(b[1:4], msg.Pad[:])
|
||||
}
|
||||
|
||||
func (msg *TcActionMsg) serializeSafe() []byte {
|
||||
length := SizeofTcActionMsg
|
||||
b := make([]byte, length)
|
||||
msg.write(b)
|
||||
return b
|
||||
}
|
||||
|
||||
func deserializeTcActionMsgSafe(b []byte) *TcActionMsg {
|
||||
var msg = TcActionMsg{}
|
||||
binary.Read(bytes.NewReader(b[0:SizeofTcActionMsg]), NativeEndian(), &msg)
|
||||
return &msg
|
||||
}
|
||||
|
||||
func TestTcActionMsgDeserializeSerialize(t *testing.T) {
|
||||
var orig = make([]byte, SizeofTcActionMsg)
|
||||
rand.Read(orig)
|
||||
safemsg := deserializeTcActionMsgSafe(orig)
|
||||
msg := DeserializeTcActionMsg(orig)
|
||||
testDeserializeSerialize(t, orig, safemsg, msg)
|
||||
}
|
||||
|
||||
/* TcRateSpec */
|
||||
func (msg *TcRateSpec) write(b []byte) {
|
||||
native := NativeEndian()
|
||||
b[0] = msg.CellLog
|
||||
b[1] = msg.Linklayer
|
||||
native.PutUint16(b[2:4], msg.Overhead)
|
||||
native.PutUint16(b[4:6], uint16(msg.CellAlign))
|
||||
native.PutUint16(b[6:8], msg.Mpu)
|
||||
native.PutUint32(b[8:12], msg.Rate)
|
||||
}
|
||||
|
||||
func (msg *TcRateSpec) serializeSafe() []byte {
|
||||
length := SizeofTcRateSpec
|
||||
b := make([]byte, length)
|
||||
msg.write(b)
|
||||
return b
|
||||
}
|
||||
|
||||
func deserializeTcRateSpecSafe(b []byte) *TcRateSpec {
|
||||
var msg = TcRateSpec{}
|
||||
binary.Read(bytes.NewReader(b[0:SizeofTcRateSpec]), NativeEndian(), &msg)
|
||||
return &msg
|
||||
}
|
||||
|
||||
func TestTcRateSpecDeserializeSerialize(t *testing.T) {
|
||||
var orig = make([]byte, SizeofTcRateSpec)
|
||||
rand.Read(orig)
|
||||
safemsg := deserializeTcRateSpecSafe(orig)
|
||||
msg := DeserializeTcRateSpec(orig)
|
||||
testDeserializeSerialize(t, orig, safemsg, msg)
|
||||
}
|
||||
|
||||
/* TcTbfQopt */
|
||||
func (msg *TcTbfQopt) write(b []byte) {
|
||||
native := NativeEndian()
|
||||
msg.Rate.write(b[0:SizeofTcRateSpec])
|
||||
start := SizeofTcRateSpec
|
||||
msg.Peakrate.write(b[start : start+SizeofTcRateSpec])
|
||||
start += SizeofTcRateSpec
|
||||
native.PutUint32(b[start:start+4], msg.Limit)
|
||||
start += 4
|
||||
native.PutUint32(b[start:start+4], msg.Buffer)
|
||||
start += 4
|
||||
native.PutUint32(b[start:start+4], msg.Mtu)
|
||||
}
|
||||
|
||||
func (msg *TcTbfQopt) serializeSafe() []byte {
|
||||
length := SizeofTcTbfQopt
|
||||
b := make([]byte, length)
|
||||
msg.write(b)
|
||||
return b
|
||||
}
|
||||
|
||||
func deserializeTcTbfQoptSafe(b []byte) *TcTbfQopt {
|
||||
var msg = TcTbfQopt{}
|
||||
binary.Read(bytes.NewReader(b[0:SizeofTcTbfQopt]), NativeEndian(), &msg)
|
||||
return &msg
|
||||
}
|
||||
|
||||
func TestTcTbfQoptDeserializeSerialize(t *testing.T) {
|
||||
var orig = make([]byte, SizeofTcTbfQopt)
|
||||
rand.Read(orig)
|
||||
safemsg := deserializeTcTbfQoptSafe(orig)
|
||||
msg := DeserializeTcTbfQopt(orig)
|
||||
testDeserializeSerialize(t, orig, safemsg, msg)
|
||||
}
|
||||
|
||||
/* TcHtbCopt */
|
||||
func (msg *TcHtbCopt) write(b []byte) {
|
||||
native := NativeEndian()
|
||||
msg.Rate.write(b[0:SizeofTcRateSpec])
|
||||
start := SizeofTcRateSpec
|
||||
msg.Ceil.write(b[start : start+SizeofTcRateSpec])
|
||||
start += SizeofTcRateSpec
|
||||
native.PutUint32(b[start:start+4], msg.Buffer)
|
||||
start += 4
|
||||
native.PutUint32(b[start:start+4], msg.Cbuffer)
|
||||
start += 4
|
||||
native.PutUint32(b[start:start+4], msg.Quantum)
|
||||
start += 4
|
||||
native.PutUint32(b[start:start+4], msg.Level)
|
||||
start += 4
|
||||
native.PutUint32(b[start:start+4], msg.Prio)
|
||||
}
|
||||
|
||||
func (msg *TcHtbCopt) serializeSafe() []byte {
|
||||
length := SizeofTcHtbCopt
|
||||
b := make([]byte, length)
|
||||
msg.write(b)
|
||||
return b
|
||||
}
|
||||
|
||||
func deserializeTcHtbCoptSafe(b []byte) *TcHtbCopt {
|
||||
var msg = TcHtbCopt{}
|
||||
binary.Read(bytes.NewReader(b[0:SizeofTcHtbCopt]), NativeEndian(), &msg)
|
||||
return &msg
|
||||
}
|
||||
|
||||
func TestTcHtbCoptDeserializeSerialize(t *testing.T) {
|
||||
var orig = make([]byte, SizeofTcHtbCopt)
|
||||
rand.Read(orig)
|
||||
safemsg := deserializeTcHtbCoptSafe(orig)
|
||||
msg := DeserializeTcHtbCopt(orig)
|
||||
testDeserializeSerialize(t, orig, safemsg, msg)
|
||||
}
|
161
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go
generated
vendored
Normal file
161
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,161 @@
|
|||
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)
|
||||
}
|
109
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go
generated
vendored
Normal file
109
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
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)
|
||||
}
|
207
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go
generated
vendored
Normal file
207
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,207 @@
|
|||
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)
|
||||
}
|
98
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go
generated
vendored
Normal file
98
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
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)
|
||||
}
|
||||
}
|
123
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go
generated
vendored
123
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go
generated
vendored
|
@ -2,6 +2,7 @@ package netlink
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -52,6 +53,14 @@ func HandleStr(handle uint32) string {
|
|||
}
|
||||
}
|
||||
|
||||
func Percentage2u32(percentage float32) uint32 {
|
||||
// FIXME this is most likely not the best way to convert from % to uint32
|
||||
if percentage == 100 {
|
||||
return math.MaxUint32
|
||||
}
|
||||
return uint32(math.MaxUint32 * (percentage / 100))
|
||||
}
|
||||
|
||||
// PfifoFast is the default qdisc created by the kernel if one has not
|
||||
// been defined for the interface
|
||||
type PfifoFast struct {
|
||||
|
@ -120,6 +129,120 @@ func (qdisc *Htb) Type() string {
|
|||
return "htb"
|
||||
}
|
||||
|
||||
// Netem is a classless qdisc that rate limits based on tokens
|
||||
|
||||
type NetemQdiscAttrs struct {
|
||||
Latency uint32 // in us
|
||||
DelayCorr float32 // in %
|
||||
Limit uint32
|
||||
Loss float32 // in %
|
||||
LossCorr float32 // in %
|
||||
Gap uint32
|
||||
Duplicate float32 // in %
|
||||
DuplicateCorr float32 // in %
|
||||
Jitter uint32 // in us
|
||||
ReorderProb float32 // in %
|
||||
ReorderCorr float32 // in %
|
||||
CorruptProb float32 // in %
|
||||
CorruptCorr float32 // in %
|
||||
}
|
||||
|
||||
func (q NetemQdiscAttrs) String() string {
|
||||
return fmt.Sprintf(
|
||||
"{Latency: %d, Limit: %d, Loss: %d, Gap: %d, Duplicate: %d, Jitter: %d}",
|
||||
q.Latency, q.Limit, q.Loss, q.Gap, q.Duplicate, q.Jitter,
|
||||
)
|
||||
}
|
||||
|
||||
type Netem struct {
|
||||
QdiscAttrs
|
||||
Latency uint32
|
||||
DelayCorr uint32
|
||||
Limit uint32
|
||||
Loss uint32
|
||||
LossCorr uint32
|
||||
Gap uint32
|
||||
Duplicate uint32
|
||||
DuplicateCorr uint32
|
||||
Jitter uint32
|
||||
ReorderProb uint32
|
||||
ReorderCorr uint32
|
||||
CorruptProb uint32
|
||||
CorruptCorr uint32
|
||||
}
|
||||
|
||||
func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
|
||||
var limit uint32 = 1000
|
||||
var loss_corr, delay_corr, duplicate_corr uint32
|
||||
var reorder_prob, reorder_corr uint32
|
||||
var corrupt_prob, corrupt_corr uint32
|
||||
|
||||
latency := nattrs.Latency
|
||||
loss := Percentage2u32(nattrs.Loss)
|
||||
gap := nattrs.Gap
|
||||
duplicate := Percentage2u32(nattrs.Duplicate)
|
||||
jitter := nattrs.Jitter
|
||||
|
||||
// Correlation
|
||||
if latency > 0 && jitter > 0 {
|
||||
delay_corr = Percentage2u32(nattrs.DelayCorr)
|
||||
}
|
||||
if loss > 0 {
|
||||
loss_corr = Percentage2u32(nattrs.LossCorr)
|
||||
}
|
||||
if duplicate > 0 {
|
||||
duplicate_corr = Percentage2u32(nattrs.DuplicateCorr)
|
||||
}
|
||||
// FIXME should validate values(like loss/duplicate are percentages...)
|
||||
latency = time2Tick(latency)
|
||||
|
||||
if nattrs.Limit != 0 {
|
||||
limit = nattrs.Limit
|
||||
}
|
||||
// Jitter is only value if latency is > 0
|
||||
if latency > 0 {
|
||||
jitter = time2Tick(jitter)
|
||||
}
|
||||
|
||||
reorder_prob = Percentage2u32(nattrs.ReorderProb)
|
||||
reorder_corr = Percentage2u32(nattrs.ReorderCorr)
|
||||
|
||||
if reorder_prob > 0 {
|
||||
// ERROR if lantency == 0
|
||||
if gap == 0 {
|
||||
gap = 1
|
||||
}
|
||||
}
|
||||
|
||||
corrupt_prob = Percentage2u32(nattrs.CorruptProb)
|
||||
corrupt_corr = Percentage2u32(nattrs.CorruptCorr)
|
||||
|
||||
return &Netem{
|
||||
QdiscAttrs: attrs,
|
||||
Latency: latency,
|
||||
DelayCorr: delay_corr,
|
||||
Limit: limit,
|
||||
Loss: loss,
|
||||
LossCorr: loss_corr,
|
||||
Gap: gap,
|
||||
Duplicate: duplicate,
|
||||
DuplicateCorr: duplicate_corr,
|
||||
Jitter: jitter,
|
||||
ReorderProb: reorder_prob,
|
||||
ReorderCorr: reorder_corr,
|
||||
CorruptProb: corrupt_prob,
|
||||
CorruptCorr: corrupt_corr,
|
||||
}
|
||||
}
|
||||
|
||||
func (qdisc *Netem) Attrs() *QdiscAttrs {
|
||||
return &qdisc.QdiscAttrs
|
||||
}
|
||||
|
||||
func (qdisc *Netem) Type() string {
|
||||
return "netem"
|
||||
}
|
||||
|
||||
// Tbf is a classless qdisc that rate limits based on tokens
|
||||
type Tbf struct {
|
||||
QdiscAttrs
|
||||
|
|
129
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
129
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
|
@ -13,24 +13,37 @@ import (
|
|||
// QdiscDel will delete a qdisc from the system.
|
||||
// Equivalent to: `tc qdisc del $qdisc`
|
||||
func QdiscDel(qdisc Qdisc) error {
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_DELQDISC, syscall.NLM_F_ACK)
|
||||
base := qdisc.Attrs()
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
Ifindex: int32(base.LinkIndex),
|
||||
Handle: base.Handle,
|
||||
Parent: base.Parent,
|
||||
}
|
||||
req.AddData(msg)
|
||||
return qdiscModify(syscall.RTM_DELQDISC, 0, qdisc)
|
||||
}
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
// QdiscChange will change a qdisc in place
|
||||
// Equivalent to: `tc qdisc change $qdisc`
|
||||
// The parent and handle MUST NOT be changed.
|
||||
func QdiscChange(qdisc Qdisc) error {
|
||||
return qdiscModify(syscall.RTM_NEWQDISC, 0, qdisc)
|
||||
}
|
||||
|
||||
// QdiscReplace will replace a qdisc to the system.
|
||||
// Equivalent to: `tc qdisc replace $qdisc`
|
||||
// The handle MUST change.
|
||||
func QdiscReplace(qdisc Qdisc) error {
|
||||
return qdiscModify(
|
||||
syscall.RTM_NEWQDISC,
|
||||
syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE,
|
||||
qdisc)
|
||||
}
|
||||
|
||||
// QdiscAdd will add a qdisc to the system.
|
||||
// Equivalent to: `tc qdisc add $qdisc`
|
||||
func QdiscAdd(qdisc Qdisc) error {
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_NEWQDISC, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
||||
return qdiscModify(
|
||||
syscall.RTM_NEWQDISC,
|
||||
syscall.NLM_F_CREATE|syscall.NLM_F_EXCL,
|
||||
qdisc)
|
||||
}
|
||||
|
||||
func qdiscModify(cmd, flags int, qdisc Qdisc) error {
|
||||
req := nl.NewNetlinkRequest(cmd, flags|syscall.NLM_F_ACK)
|
||||
base := qdisc.Attrs()
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
|
@ -39,6 +52,20 @@ func QdiscAdd(qdisc Qdisc) error {
|
|||
Parent: base.Parent,
|
||||
}
|
||||
req.AddData(msg)
|
||||
|
||||
// When deleting don't bother building the rest of the netlink payload
|
||||
if cmd != syscall.RTM_DELQDISC {
|
||||
if err := qdiscPayload(req, qdisc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type())))
|
||||
|
||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||
|
@ -65,15 +92,47 @@ func QdiscAdd(qdisc Qdisc) error {
|
|||
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 netem, ok := qdisc.(*Netem); ok {
|
||||
opt := nl.TcNetemQopt{}
|
||||
opt.Latency = netem.Latency
|
||||
opt.Limit = netem.Limit
|
||||
opt.Loss = netem.Loss
|
||||
opt.Gap = netem.Gap
|
||||
opt.Duplicate = netem.Duplicate
|
||||
opt.Jitter = netem.Jitter
|
||||
options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize())
|
||||
// Correlation
|
||||
corr := nl.TcNetemCorr{}
|
||||
corr.DelayCorr = netem.DelayCorr
|
||||
corr.LossCorr = netem.LossCorr
|
||||
corr.DupCorr = netem.DuplicateCorr
|
||||
|
||||
if corr.DelayCorr > 0 || corr.LossCorr > 0 || corr.DupCorr > 0 {
|
||||
nl.NewRtAttrChild(options, nl.TCA_NETEM_CORR, corr.Serialize())
|
||||
}
|
||||
// Corruption
|
||||
corruption := nl.TcNetemCorrupt{}
|
||||
corruption.Probability = netem.CorruptProb
|
||||
corruption.Correlation = netem.CorruptCorr
|
||||
if corruption.Probability > 0 {
|
||||
nl.NewRtAttrChild(options, nl.TCA_NETEM_CORRUPT, corruption.Serialize())
|
||||
}
|
||||
// Reorder
|
||||
reorder := nl.TcNetemReorder{}
|
||||
reorder.Probability = netem.ReorderProb
|
||||
reorder.Correlation = netem.ReorderCorr
|
||||
if reorder.Probability > 0 {
|
||||
nl.NewRtAttrChild(options, nl.TCA_NETEM_REORDER, reorder.Serialize())
|
||||
}
|
||||
} else if _, ok := qdisc.(*Ingress); ok {
|
||||
// ingress filters must use the proper handle
|
||||
if msg.Parent != HANDLE_INGRESS {
|
||||
if qdisc.Attrs().Parent != HANDLE_INGRESS {
|
||||
return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS")
|
||||
}
|
||||
}
|
||||
|
||||
req.AddData(options)
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// QdiscList gets a list of qdiscs in the system.
|
||||
|
@ -135,6 +194,8 @@ func QdiscList(link Link) ([]Qdisc, error) {
|
|||
qdisc = &Ingress{}
|
||||
case "htb":
|
||||
qdisc = &Htb{}
|
||||
case "netem":
|
||||
qdisc = &Netem{}
|
||||
default:
|
||||
qdisc = &GenericQdisc{QdiscType: qdiscType}
|
||||
}
|
||||
|
@ -166,6 +227,10 @@ func QdiscList(link Link) ([]Qdisc, error) {
|
|||
if err := parseHtbData(qdisc, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "netem":
|
||||
if err := parseNetemData(qdisc, attr.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// no options for ingress
|
||||
}
|
||||
|
@ -213,6 +278,40 @@ func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseNetemData(qdisc Qdisc, value []byte) error {
|
||||
netem := qdisc.(*Netem)
|
||||
opt := nl.DeserializeTcNetemQopt(value)
|
||||
netem.Latency = opt.Latency
|
||||
netem.Limit = opt.Limit
|
||||
netem.Loss = opt.Loss
|
||||
netem.Gap = opt.Gap
|
||||
netem.Duplicate = opt.Duplicate
|
||||
netem.Jitter = opt.Jitter
|
||||
data, err := nl.ParseRouteAttr(value[nl.SizeofTcNetemQopt:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, datum := range data {
|
||||
switch datum.Attr.Type {
|
||||
case nl.TCA_NETEM_CORR:
|
||||
opt := nl.DeserializeTcNetemCorr(datum.Value)
|
||||
netem.DelayCorr = opt.DelayCorr
|
||||
netem.LossCorr = opt.LossCorr
|
||||
netem.DuplicateCorr = opt.DupCorr
|
||||
case nl.TCA_NETEM_CORRUPT:
|
||||
opt := nl.DeserializeTcNetemCorrupt(datum.Value)
|
||||
netem.CorruptProb = opt.Probability
|
||||
netem.CorruptCorr = opt.Correlation
|
||||
case nl.TCA_NETEM_REORDER:
|
||||
opt := nl.DeserializeTcNetemReorder(datum.Value)
|
||||
netem.ReorderProb = opt.Probability
|
||||
netem.ReorderCorr = opt.Correlation
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
||||
native = nl.NativeEndian()
|
||||
tbf := qdisc.(*Tbf)
|
||||
|
|
345
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_test.go
generated
vendored
Normal file
345
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_test.go
generated
vendored
Normal file
|
@ -0,0 +1,345 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTbfAddDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdisc := &Tbf{
|
||||
QdiscAttrs: QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(1, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
},
|
||||
Rate: 131072,
|
||||
Limit: 1220703,
|
||||
Buffer: 16793,
|
||||
}
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
tbf, ok := qdiscs[0].(*Tbf)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if tbf.Rate != qdisc.Rate {
|
||||
t.Fatal("Rate doesn't match")
|
||||
}
|
||||
if tbf.Limit != qdisc.Limit {
|
||||
t.Fatal("Limit doesn't match")
|
||||
}
|
||||
if tbf.Buffer != qdisc.Buffer {
|
||||
t.Fatal("Buffer doesn't match")
|
||||
}
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHtbAddDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
attrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(1, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
}
|
||||
|
||||
qdisc := NewHtb(attrs)
|
||||
qdisc.Rate2Quantum = 5
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
htb, ok := qdiscs[0].(*Htb)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if htb.Defcls != qdisc.Defcls {
|
||||
t.Fatal("Defcls doesn't match")
|
||||
}
|
||||
if htb.Rate2Quantum != qdisc.Rate2Quantum {
|
||||
t.Fatal("Rate2Quantum doesn't match")
|
||||
}
|
||||
if htb.Debug != qdisc.Debug {
|
||||
t.Fatal("Debug doesn't match")
|
||||
}
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrioAddDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdisc := NewPrio(QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(1, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
})
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
_, ok := qdiscs[0].(*Prio)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTbfAddHtbReplaceDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Add
|
||||
attrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(1, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
}
|
||||
qdisc := &Tbf{
|
||||
QdiscAttrs: attrs,
|
||||
Rate: 131072,
|
||||
Limit: 1220703,
|
||||
Buffer: 16793,
|
||||
}
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
tbf, ok := qdiscs[0].(*Tbf)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if tbf.Rate != qdisc.Rate {
|
||||
t.Fatal("Rate doesn't match")
|
||||
}
|
||||
if tbf.Limit != qdisc.Limit {
|
||||
t.Fatal("Limit doesn't match")
|
||||
}
|
||||
if tbf.Buffer != qdisc.Buffer {
|
||||
t.Fatal("Buffer doesn't match")
|
||||
}
|
||||
// Replace
|
||||
// For replace to work, the handle MUST be different that the running one
|
||||
attrs.Handle = MakeHandle(2, 0)
|
||||
qdisc2 := NewHtb(attrs)
|
||||
qdisc2.Rate2Quantum = 5
|
||||
if err := QdiscReplace(qdisc2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
htb, ok := qdiscs[0].(*Htb)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if htb.Defcls != qdisc2.Defcls {
|
||||
t.Fatal("Defcls doesn't match")
|
||||
}
|
||||
if htb.Rate2Quantum != qdisc2.Rate2Quantum {
|
||||
t.Fatal("Rate2Quantum doesn't match")
|
||||
}
|
||||
if htb.Debug != qdisc2.Debug {
|
||||
t.Fatal("Debug doesn't match")
|
||||
}
|
||||
|
||||
if err := QdiscDel(qdisc2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTbfAddTbfChangeDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Add
|
||||
attrs := QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(1, 0),
|
||||
Parent: HANDLE_ROOT,
|
||||
}
|
||||
qdisc := &Tbf{
|
||||
QdiscAttrs: attrs,
|
||||
Rate: 131072,
|
||||
Limit: 1220703,
|
||||
Buffer: 16793,
|
||||
}
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
tbf, ok := qdiscs[0].(*Tbf)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if tbf.Rate != qdisc.Rate {
|
||||
t.Fatal("Rate doesn't match")
|
||||
}
|
||||
if tbf.Limit != qdisc.Limit {
|
||||
t.Fatal("Limit doesn't match")
|
||||
}
|
||||
if tbf.Buffer != qdisc.Buffer {
|
||||
t.Fatal("Buffer doesn't match")
|
||||
}
|
||||
// Change
|
||||
// For change to work, the handle MUST not change
|
||||
qdisc.Rate = 23456
|
||||
if err := QdiscChange(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 1 {
|
||||
t.Fatal("Failed to add qdisc")
|
||||
}
|
||||
tbf, ok = qdiscs[0].(*Tbf)
|
||||
if !ok {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
if tbf.Rate != qdisc.Rate {
|
||||
t.Fatal("Rate doesn't match")
|
||||
}
|
||||
if tbf.Limit != qdisc.Limit {
|
||||
t.Fatal("Limit doesn't match")
|
||||
}
|
||||
if tbf.Buffer != qdisc.Buffer {
|
||||
t.Fatal("Buffer doesn't match")
|
||||
}
|
||||
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = QdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(qdiscs) != 0 {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
23
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go
generated
vendored
23
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go
generated
vendored
|
@ -24,17 +24,20 @@ const (
|
|||
FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE
|
||||
)
|
||||
|
||||
// Route represents a netlink route. A route is associated with a link,
|
||||
// has a destination network, an optional source ip, and optional
|
||||
// gateway. Advanced route parameters and non-main routing tables are
|
||||
// currently not supported.
|
||||
// Route represents a netlink route.
|
||||
type Route struct {
|
||||
LinkIndex int
|
||||
Scope Scope
|
||||
Dst *net.IPNet
|
||||
Src net.IP
|
||||
Gw net.IP
|
||||
Flags int
|
||||
LinkIndex int
|
||||
ILinkIndex int
|
||||
Scope Scope
|
||||
Dst *net.IPNet
|
||||
Src net.IP
|
||||
Gw net.IP
|
||||
Protocol int
|
||||
Priority int
|
||||
Table int
|
||||
Type int
|
||||
Tos int
|
||||
Flags int
|
||||
}
|
||||
|
||||
func (r Route) String() string {
|
||||
|
|
132
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go
generated
vendored
132
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go
generated
vendored
|
@ -10,6 +10,19 @@ import (
|
|||
|
||||
// RtAttr is shared so it is in netlink_linux.go
|
||||
|
||||
const (
|
||||
RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota)
|
||||
RT_FILTER_SCOPE
|
||||
RT_FILTER_TYPE
|
||||
RT_FILTER_TOS
|
||||
RT_FILTER_IIF
|
||||
RT_FILTER_OIF
|
||||
RT_FILTER_DST
|
||||
RT_FILTER_SRC
|
||||
RT_FILTER_GW
|
||||
RT_FILTER_TABLE
|
||||
)
|
||||
|
||||
// RouteAdd will add a route to the system.
|
||||
// Equivalent to: `ip route add $route`
|
||||
func RouteAdd(route *Route) error {
|
||||
|
@ -29,8 +42,6 @@ func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
|
|||
return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
|
||||
}
|
||||
|
||||
msg.Scope = uint8(route.Scope)
|
||||
msg.Flags = uint32(route.Flags)
|
||||
family := -1
|
||||
var rtAttrs []*nl.RtAttr
|
||||
|
||||
|
@ -79,8 +90,34 @@ func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
|
|||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_GATEWAY, gwData))
|
||||
}
|
||||
|
||||
msg.Family = uint8(family)
|
||||
if route.Table > 0 {
|
||||
if route.Table >= 256 {
|
||||
msg.Table = syscall.RT_TABLE_UNSPEC
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(route.Table))
|
||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_TABLE, b))
|
||||
} else {
|
||||
msg.Table = uint8(route.Table)
|
||||
}
|
||||
}
|
||||
|
||||
if route.Priority > 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(route.Priority))
|
||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PRIORITY, b))
|
||||
}
|
||||
if route.Tos > 0 {
|
||||
msg.Tos = uint8(route.Tos)
|
||||
}
|
||||
if route.Protocol > 0 {
|
||||
msg.Protocol = uint8(route.Protocol)
|
||||
}
|
||||
if route.Type > 0 {
|
||||
msg.Type = uint8(route.Type)
|
||||
}
|
||||
|
||||
msg.Scope = uint8(route.Scope)
|
||||
msg.Family = uint8(family)
|
||||
req.AddData(msg)
|
||||
for _, attr := range rtAttrs {
|
||||
req.AddData(attr)
|
||||
|
@ -102,61 +139,95 @@ func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
|
|||
// Equivalent to: `ip route show`.
|
||||
// The list can be filtered by link and ip family.
|
||||
func RouteList(link Link, family int) ([]Route, error) {
|
||||
var routeFilter *Route
|
||||
if link != nil {
|
||||
routeFilter = &Route{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
}
|
||||
}
|
||||
return RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
|
||||
}
|
||||
|
||||
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
|
||||
// All rules must be defined in RouteFilter struct
|
||||
func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
|
||||
msg := nl.NewIfInfomsg(family)
|
||||
req.AddData(msg)
|
||||
infmsg := nl.NewIfInfomsg(family)
|
||||
req.AddData(infmsg)
|
||||
|
||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
index := 0
|
||||
if link != nil {
|
||||
base := link.Attrs()
|
||||
ensureIndex(base)
|
||||
index = base.Index
|
||||
}
|
||||
|
||||
var res []Route
|
||||
for _, m := range msgs {
|
||||
msg := nl.DeserializeRtMsg(m)
|
||||
|
||||
if msg.Flags&syscall.RTM_F_CLONED != 0 {
|
||||
// Ignore cloned routes
|
||||
continue
|
||||
}
|
||||
|
||||
if msg.Table != syscall.RT_TABLE_MAIN {
|
||||
// Ignore non-main tables
|
||||
continue
|
||||
if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
|
||||
// Ignore non-main tables
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
route, err := deserializeRoute(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if link != nil && route.LinkIndex != index {
|
||||
// Ignore routes from other interfaces
|
||||
continue
|
||||
if filter != nil {
|
||||
switch {
|
||||
case filterMask&RT_FILTER_TABLE != 0 && route.Table != filter.Table:
|
||||
continue
|
||||
case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
|
||||
continue
|
||||
case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope:
|
||||
continue
|
||||
case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type:
|
||||
continue
|
||||
case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
|
||||
continue
|
||||
case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
|
||||
continue
|
||||
case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
|
||||
continue
|
||||
case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw):
|
||||
continue
|
||||
case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src):
|
||||
continue
|
||||
case filterMask&RT_FILTER_DST != 0 && filter.Dst != nil:
|
||||
if route.Dst == nil {
|
||||
continue
|
||||
}
|
||||
aMaskLen, aMaskBits := route.Dst.Mask.Size()
|
||||
bMaskLen, bMaskBits := filter.Dst.Mask.Size()
|
||||
if !(route.Dst.IP.Equal(filter.Dst.IP) && aMaskLen == bMaskLen && aMaskBits == bMaskBits) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
res = append(res, route)
|
||||
}
|
||||
|
||||
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
|
||||
return Route{}, err
|
||||
}
|
||||
route := Route{
|
||||
Scope: Scope(msg.Scope),
|
||||
Protocol: int(msg.Protocol),
|
||||
Table: int(msg.Table),
|
||||
Type: int(msg.Type),
|
||||
Tos: int(msg.Tos),
|
||||
Flags: int(msg.Flags),
|
||||
}
|
||||
route.Scope = Scope(msg.Scope)
|
||||
route.Flags = int(msg.Flags)
|
||||
|
||||
native := nl.NativeEndian()
|
||||
for _, attr := range attrs {
|
||||
|
@ -171,8 +242,13 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||
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
|
||||
route.LinkIndex = int(native.Uint32(attr.Value[0:4]))
|
||||
case syscall.RTA_IIF:
|
||||
route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
|
||||
case syscall.RTA_PRIORITY:
|
||||
route.Priority = int(native.Uint32(attr.Value[0:4]))
|
||||
case syscall.RTA_TABLE:
|
||||
route.Table = int(native.Uint32(attr.Value[0:4]))
|
||||
}
|
||||
}
|
||||
return route, nil
|
||||
|
|
210
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_test.go
generated
vendored
Normal file
210
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_test.go
generated
vendored
Normal file
|
@ -0,0 +1,210 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
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 := &net.IPNet{
|
||||
IP: net.IPv4(192, 168, 0, 0),
|
||||
Mask: net.CIDRMask(24, 32),
|
||||
}
|
||||
|
||||
ip := net.IPv4(127, 1, 1, 1)
|
||||
route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
|
||||
if err := RouteAdd(&route); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
routes, err := RouteList(link, FAMILY_V4)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(routes) != 1 {
|
||||
t.Fatal("Route not added properly")
|
||||
}
|
||||
|
||||
dstIP := net.IPv4(192, 168, 0, 42)
|
||||
routeToDstIP, err := RouteGet(dstIP)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(routeToDstIP) == 0 {
|
||||
t.Fatal("Default route not present")
|
||||
}
|
||||
if err := RouteDel(&route); 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")
|
||||
}
|
||||
}
|
||||
|
||||
func expectRouteUpdate(ch <-chan RouteUpdate, t uint16, dst net.IP) bool {
|
||||
for {
|
||||
timeout := time.After(time.Minute)
|
||||
select {
|
||||
case update := <-ch:
|
||||
if update.Type == t && update.Route.Dst.IP.Equal(dst) {
|
||||
return true
|
||||
}
|
||||
case <-timeout:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouteSubscribe(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
ch := make(chan RouteUpdate)
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
if err := RouteSubscribe(ch, done); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 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 := &net.IPNet{
|
||||
IP: net.IPv4(192, 168, 0, 0),
|
||||
Mask: net.CIDRMask(24, 32),
|
||||
}
|
||||
|
||||
ip := net.IPv4(127, 1, 1, 1)
|
||||
route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
|
||||
if err := RouteAdd(&route); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !expectRouteUpdate(ch, syscall.RTM_NEWROUTE, dst.IP) {
|
||||
t.Fatal("Add update not received as expected")
|
||||
}
|
||||
if err := RouteDel(&route); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !expectRouteUpdate(ch, syscall.RTM_DELROUTE, dst.IP) {
|
||||
t.Fatal("Del update not received as expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouteExtraFields(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 := &net.IPNet{
|
||||
IP: net.IPv4(1, 1, 1, 1),
|
||||
Mask: net.CIDRMask(32, 32),
|
||||
}
|
||||
|
||||
src := net.IPv4(127, 3, 3, 3)
|
||||
route := Route{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Dst: dst,
|
||||
Src: src,
|
||||
Scope: syscall.RT_SCOPE_LINK,
|
||||
Priority: 13,
|
||||
Table: syscall.RT_TABLE_MAIN,
|
||||
Type: syscall.RTN_UNICAST,
|
||||
Tos: 14,
|
||||
}
|
||||
if err := RouteAdd(&route); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
routes, err := RouteListFiltered(FAMILY_V4, &Route{
|
||||
Dst: dst,
|
||||
Src: src,
|
||||
Scope: syscall.RT_SCOPE_LINK,
|
||||
Table: syscall.RT_TABLE_MAIN,
|
||||
Type: syscall.RTN_UNICAST,
|
||||
Tos: 14,
|
||||
}, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(routes) != 1 {
|
||||
t.Fatal("Route not added properly")
|
||||
}
|
||||
|
||||
if routes[0].Scope != syscall.RT_SCOPE_LINK {
|
||||
t.Fatal("Invalid Scope. Route not added properly")
|
||||
}
|
||||
if routes[0].Priority != 13 {
|
||||
t.Fatal("Invalid Priority. Route not added properly")
|
||||
}
|
||||
if routes[0].Table != syscall.RT_TABLE_MAIN {
|
||||
t.Fatal("Invalid Scope. Route not added properly")
|
||||
}
|
||||
if routes[0].Type != syscall.RTN_UNICAST {
|
||||
t.Fatal("Invalid Type. Route not added properly")
|
||||
}
|
||||
if routes[0].Tos != 14 {
|
||||
t.Fatal("Invalid Tos. Route not added properly")
|
||||
}
|
||||
}
|
43
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule.go
generated
vendored
Normal file
43
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
)
|
||||
|
||||
// Rule represents a netlink rule.
|
||||
type Rule struct {
|
||||
*nl.RtMsg
|
||||
Priority int
|
||||
Table int
|
||||
Mark int
|
||||
Mask int
|
||||
TunID uint
|
||||
Goto int
|
||||
Src *net.IPNet
|
||||
Dst *net.IPNet
|
||||
Flow int
|
||||
IifName string
|
||||
OifName string
|
||||
SuppressIfgroup int
|
||||
SuppressPrefixlen int
|
||||
}
|
||||
|
||||
func (r Rule) String() string {
|
||||
return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table)
|
||||
}
|
||||
|
||||
// NewRule return empty rules.
|
||||
func NewRule() *Rule {
|
||||
return &Rule{
|
||||
SuppressIfgroup: -1,
|
||||
SuppressPrefixlen: -1,
|
||||
Priority: -1,
|
||||
Mark: -1,
|
||||
Mask: -1,
|
||||
Goto: -1,
|
||||
Flow: -1,
|
||||
}
|
||||
}
|
198
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
Normal file
198
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
)
|
||||
|
||||
// RuleAdd adds a rule to the system.
|
||||
// Equivalent to: ip rule add
|
||||
func RuleAdd(rule *Rule) error {
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_NEWRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
||||
return ruleHandle(rule, req)
|
||||
}
|
||||
|
||||
// RuleDel deletes a rule from the system.
|
||||
// Equivalent to: ip rule del
|
||||
func RuleDel(rule *Rule) error {
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_DELRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
||||
return ruleHandle(rule, req)
|
||||
}
|
||||
|
||||
func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
||||
msg := nl.NewRtMsg()
|
||||
msg.Family = syscall.AF_INET
|
||||
var dstFamily uint8
|
||||
|
||||
var rtAttrs []*nl.RtAttr
|
||||
if rule.Dst != nil && rule.Dst.IP != nil {
|
||||
dstLen, _ := rule.Dst.Mask.Size()
|
||||
msg.Dst_len = uint8(dstLen)
|
||||
msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP))
|
||||
dstFamily = msg.Family
|
||||
var dstData []byte
|
||||
if msg.Family == syscall.AF_INET {
|
||||
dstData = rule.Dst.IP.To4()
|
||||
} else {
|
||||
dstData = rule.Dst.IP.To16()
|
||||
}
|
||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData))
|
||||
}
|
||||
|
||||
if rule.Src != nil && rule.Src.IP != nil {
|
||||
msg.Family = uint8(nl.GetIPFamily(rule.Src.IP))
|
||||
if dstFamily != 0 && dstFamily != msg.Family {
|
||||
return fmt.Errorf("source and destination ip are not the same IP family")
|
||||
}
|
||||
srcLen, _ := rule.Src.Mask.Size()
|
||||
msg.Src_len = uint8(srcLen)
|
||||
var srcData []byte
|
||||
if msg.Family == syscall.AF_INET {
|
||||
srcData = rule.Src.IP.To4()
|
||||
} else {
|
||||
srcData = rule.Src.IP.To16()
|
||||
}
|
||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_SRC, srcData))
|
||||
}
|
||||
|
||||
if rule.Table >= 0 {
|
||||
msg.Table = uint8(rule.Table)
|
||||
if rule.Table >= 256 {
|
||||
msg.Table = syscall.RT_TABLE_UNSPEC
|
||||
}
|
||||
}
|
||||
|
||||
req.AddData(msg)
|
||||
for i := range rtAttrs {
|
||||
req.AddData(rtAttrs[i])
|
||||
}
|
||||
|
||||
var (
|
||||
b = make([]byte, 4)
|
||||
native = nl.NativeEndian()
|
||||
)
|
||||
|
||||
if rule.Priority >= 0 {
|
||||
native.PutUint32(b, uint32(rule.Priority))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
|
||||
}
|
||||
if rule.Mark >= 0 {
|
||||
native.PutUint32(b, uint32(rule.Mark))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
|
||||
}
|
||||
if rule.Mask >= 0 {
|
||||
native.PutUint32(b, uint32(rule.Mask))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
|
||||
}
|
||||
if rule.Flow >= 0 {
|
||||
native.PutUint32(b, uint32(rule.Flow))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b))
|
||||
}
|
||||
if rule.TunID > 0 {
|
||||
native.PutUint32(b, uint32(rule.TunID))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b))
|
||||
}
|
||||
if rule.Table >= 256 {
|
||||
native.PutUint32(b, uint32(rule.Table))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b))
|
||||
}
|
||||
if msg.Table > 0 {
|
||||
if rule.SuppressPrefixlen >= 0 {
|
||||
native.PutUint32(b, uint32(rule.SuppressPrefixlen))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b))
|
||||
}
|
||||
if rule.SuppressIfgroup >= 0 {
|
||||
native.PutUint32(b, uint32(rule.SuppressIfgroup))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b))
|
||||
}
|
||||
}
|
||||
if rule.IifName != "" {
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName)))
|
||||
}
|
||||
if rule.OifName != "" {
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName)))
|
||||
}
|
||||
if rule.Goto >= 0 {
|
||||
msg.Type = nl.FR_ACT_NOP
|
||||
native.PutUint32(b, uint32(rule.Goto))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
|
||||
}
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// RuleList lists rules in the system.
|
||||
// Equivalent to: ip rule list
|
||||
func RuleList(family int) ([]Rule, error) {
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_GETRULE, syscall.NLM_F_DUMP|syscall.NLM_F_REQUEST)
|
||||
msg := nl.NewIfInfomsg(family)
|
||||
req.AddData(msg)
|
||||
|
||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWRULE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
native := nl.NativeEndian()
|
||||
var res = make([]Rule, 0)
|
||||
for i := range msgs {
|
||||
msg := nl.DeserializeRtMsg(msgs[i])
|
||||
attrs, err := nl.ParseRouteAttr(msgs[i][msg.Len():])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rule := NewRule()
|
||||
rule.RtMsg = msg
|
||||
|
||||
for j := range attrs {
|
||||
switch attrs[j].Attr.Type {
|
||||
case syscall.RTA_TABLE:
|
||||
rule.Table = int(native.Uint32(attrs[j].Value[0:4]))
|
||||
case nl.FRA_SRC:
|
||||
rule.Src = &net.IPNet{
|
||||
IP: attrs[j].Value,
|
||||
Mask: net.CIDRMask(int(msg.Src_len), 8*len(attrs[j].Value)),
|
||||
}
|
||||
case nl.FRA_DST:
|
||||
rule.Dst = &net.IPNet{
|
||||
IP: attrs[j].Value,
|
||||
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)),
|
||||
}
|
||||
case nl.FRA_FWMARK:
|
||||
rule.Mark = int(native.Uint32(attrs[j].Value[0:4]))
|
||||
case nl.FRA_FWMASK:
|
||||
rule.Mask = int(native.Uint32(attrs[j].Value[0:4]))
|
||||
case nl.FRA_TUN_ID:
|
||||
rule.TunID = uint(native.Uint64(attrs[j].Value[0:4]))
|
||||
case nl.FRA_IIFNAME:
|
||||
rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1])
|
||||
case nl.FRA_OIFNAME:
|
||||
rule.OifName = string(attrs[j].Value[:len(attrs[j].Value)-1])
|
||||
case nl.FRA_SUPPRESS_PREFIXLEN:
|
||||
i := native.Uint32(attrs[j].Value[0:4])
|
||||
if i != 0xffffffff {
|
||||
rule.SuppressPrefixlen = int(i)
|
||||
}
|
||||
case nl.FRA_SUPPRESS_IFGROUP:
|
||||
i := native.Uint32(attrs[j].Value[0:4])
|
||||
if i != 0xffffffff {
|
||||
rule.SuppressIfgroup = int(i)
|
||||
}
|
||||
case nl.FRA_FLOW:
|
||||
rule.Flow = int(native.Uint32(attrs[j].Value[0:4]))
|
||||
case nl.FRA_GOTO:
|
||||
rule.Goto = int(native.Uint32(attrs[j].Value[0:4]))
|
||||
case nl.FRA_PRIORITY:
|
||||
rule.Priority = int(native.Uint32(attrs[j].Value[0:4]))
|
||||
}
|
||||
}
|
||||
res = append(res, *rule)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
66
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule_test.go
generated
vendored
Normal file
66
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule_test.go
generated
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRuleAddDel(t *testing.T) {
|
||||
srcNet := &net.IPNet{IP: net.IPv4(172, 16, 0, 1), Mask: net.CIDRMask(16, 32)}
|
||||
dstNet := &net.IPNet{IP: net.IPv4(172, 16, 1, 1), Mask: net.CIDRMask(24, 32)}
|
||||
|
||||
rules_begin, err := RuleList(syscall.AF_INET)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rule := NewRule()
|
||||
rule.Table = syscall.RT_TABLE_MAIN
|
||||
rule.Src = srcNet
|
||||
rule.Dst = dstNet
|
||||
rule.Priority = 5
|
||||
rule.OifName = "lo"
|
||||
rule.IifName = "lo"
|
||||
if err := RuleAdd(rule); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rules, err := RuleList(syscall.AF_INET)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(rules) != len(rules_begin)+1 {
|
||||
t.Fatal("Rule not added properly")
|
||||
}
|
||||
|
||||
// find this rule
|
||||
var found bool
|
||||
for i := range rules {
|
||||
if rules[i].Table == rule.Table &&
|
||||
rules[i].Src != nil && rules[i].Src.String() == srcNet.String() &&
|
||||
rules[i].Dst != nil && rules[i].Dst.String() == dstNet.String() &&
|
||||
rules[i].OifName == rule.OifName &&
|
||||
rules[i].Priority == rule.Priority &&
|
||||
rules[i].IifName == rule.IifName {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("Rule has diffrent options than one added")
|
||||
}
|
||||
|
||||
if err := RuleDel(rule); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rules_end, err := RuleList(syscall.AF_INET)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(rules_end) != len(rules_begin) {
|
||||
t.Fatal("Rule not removed properly")
|
||||
}
|
||||
}
|
49
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_policy_test.go
generated
vendored
Normal file
49
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_policy_test.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
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")
|
||||
}
|
||||
}
|
50
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state_test.go
generated
vendored
Normal file
50
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state_test.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
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")
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ build_image=libnetworkbuild
|
|||
dockerargs = --privileged -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork
|
||||
container_env = -e "INSIDECONTAINER=-incontainer=true"
|
||||
docker = docker run --rm -it ${dockerargs} $$EXTRA_ARGS ${container_env} ${build_image}
|
||||
ciargs = -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" -e "INSIDECONTAINER=-incontainer=true"
|
||||
ciargs = -e CIRCLECI -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" -e "INSIDECONTAINER=-incontainer=true"
|
||||
cidocker = docker run ${dockerargs} ${ciargs} ${container_env} ${build_image}
|
||||
CROSS_PLATFORMS = linux/amd64 linux/386 linux/arm windows/amd64 windows/386
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"os/exec"
|
||||
"regexp"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
@ -337,7 +338,7 @@ func setInterfaceIPv6(iface netlink.Link, i *nwIface) error {
|
|||
if i.AddressIPv6() == nil {
|
||||
return nil
|
||||
}
|
||||
ipAddr := &netlink.Addr{IPNet: i.AddressIPv6(), Label: ""}
|
||||
ipAddr := &netlink.Addr{IPNet: i.AddressIPv6(), Label: "", Flags: syscall.IFA_F_NODAD}
|
||||
return netlink.AddrAdd(iface, ipAddr)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,15 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"github.com/vishvananda/netns"
|
||||
)
|
||||
|
||||
|
@ -179,3 +182,43 @@ func TestScanStatistics(t *testing.T) {
|
|||
t.Fatalf("Error scanning the statistics")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisableIPv6DAD(t *testing.T) {
|
||||
if testutils.RunningOnCircleCI() {
|
||||
t.Skipf("Skipping as not supported on CIRCLE CI kernel")
|
||||
}
|
||||
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
ipv6, _ := types.ParseCIDR("2001:db8::44/64")
|
||||
iface := &nwIface{addressIPv6: ipv6}
|
||||
|
||||
veth := &netlink.Veth{
|
||||
LinkAttrs: netlink.LinkAttrs{Name: "sideA"},
|
||||
PeerName: "sideB",
|
||||
}
|
||||
|
||||
err := netlink.LinkAdd(veth)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
link, err := netlink.LinkByName("sideA")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = setInterfaceIPv6(link, iface)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addrList, err := netlink.AddrList(link, nl.FAMILY_V6)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if addrList[0].Flags&syscall.IFA_F_NODAD == 0 {
|
||||
t.Fatalf("Unexpected interface flags: 0x%x. Expected to contain 0x%x", addrList[0].Flags, syscall.IFA_F_NODAD)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package testutils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
@ -37,3 +38,8 @@ func SetupTestOSContext(t *testing.T) func() {
|
|||
runtime.UnlockOSThread()
|
||||
}
|
||||
}
|
||||
|
||||
// RunningOnCircleCI returns true if being executed on libnetwork Circle CI setup
|
||||
func RunningOnCircleCI() bool {
|
||||
return os.Getenv("CIRCLECI") != ""
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue