소스 검색

vendor: bump netlink to latest

recent netlink includes fix for VXLAN GBP
(to re-generate glide.lock, run `glide up -s -v -u`)
Evan Farrar 8 년 전
부모
커밋
57ed955cfd

+ 3 - 3
glide.lock

@@ -1,5 +1,5 @@
-hash: ae9f09c90f4bb4230fb7dc06798b809078b98816df63c91f4ad636b89ff31e38
-updated: 2016-06-23T13:29:22.013543886Z
+hash: 17c68b031c830c07db965733785b9c1575b542503c07ad742a00972e59310ffc
+updated: 2016-07-12T01:03:53.553504535-04:00
 imports:
 - name: github.com/aws/aws-sdk-go
   version: 5c0313fff8cd85670ae4fc996254dd7d66cb4cf7
@@ -58,7 +58,7 @@ imports:
 - name: github.com/vaughan0/go-ini
   version: a98ad7ee00ec53921f08832bc06ecf7fd600e6a1
 - name: github.com/vishvananda/netlink
-  version: 293adec04146bfb07bf34f75921ebc9c1ee2cd74
+  version: e73bad418fd727ed3a02830b1af1ad0283a1de6c
   subpackages:
   - nl
 - name: github.com/vishvananda/netns

+ 1 - 1
glide.yaml

@@ -48,7 +48,7 @@ import:
 - package: github.com/vaughan0/go-ini
   version: a98ad7ee00ec53921f08832bc06ecf7fd600e6a1
 - package: github.com/vishvananda/netlink
-  version: 293adec04146bfb07bf34f75921ebc9c1ee2cd74
+  version: e73bad418fd727ed3a02830b1af1ad0283a1de6c
   subpackages:
   - nl
 - package: golang.org/x/net

+ 12 - 1
vendor/github.com/vishvananda/netlink/addr_linux.go

@@ -8,6 +8,7 @@ import (
 	"syscall"
 
 	"github.com/vishvananda/netlink/nl"
+	"github.com/vishvananda/netns"
 )
 
 // IFA_FLAGS is a u32 attribute.
@@ -192,7 +193,17 @@ type AddrUpdate struct {
 // AddrSubscribe takes a chan down which notifications will be sent
 // when addresses change.  Close the 'done' chan to stop subscription.
 func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
-	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
+	return addrSubscribe(netns.None(), netns.None(), ch, done)
+}
+
+// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
+// to choose the network namespace in which to subscribe (ns).
+func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
+	return addrSubscribe(ns, netns.None(), ch, done)
+}
+
+func addrSubscribe(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
+	s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
 	if err != nil {
 		return err
 	}

+ 2 - 2
vendor/github.com/vishvananda/netlink/filter_linux.go

@@ -143,7 +143,7 @@ func (h *Handle) FilterAdd(filter Filter) error {
 		if u32.RedirIndex != 0 {
 			u32.Actions = append([]Action{NewMirredAction(u32.RedirIndex)}, u32.Actions...)
 		}
-		if err := encodeActions(actionsAttr, u32.Actions); err != nil {
+		if err := EncodeActions(actionsAttr, u32.Actions); err != nil {
 			return err
 		}
 	} else if fw, ok := filter.(*Fw); ok {
@@ -309,7 +309,7 @@ func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
 	attrs.Bindcnt = int(tcgen.Bindcnt)
 }
 
-func encodeActions(attr *nl.RtAttr, actions []Action) error {
+func EncodeActions(attr *nl.RtAttr, actions []Action) error {
 	tabIndex := int(nl.TCA_ACT_TAB)
 
 	for _, action := range actions {

+ 35 - 35
vendor/github.com/vishvananda/netlink/handle_linux.go

@@ -1,7 +1,6 @@
 package netlink
 
 import (
-	"sync/atomic"
 	"syscall"
 
 	"github.com/vishvananda/netlink/nl"
@@ -11,27 +10,34 @@ import (
 // Empty handle used by the netlink package methods
 var pkgHandle = &Handle{}
 
-// Handle is an handle for the netlink requests
-// on a specific network namespace. All the requests
-// share the same netlink socket, which gets released
-// when the handle is deleted.
+// Handle is an handle for the netlink requests on a
+// specific network namespace. All the requests on the
+// same netlink family share the same netlink socket,
+// which gets released when the handle is deleted.
 type Handle struct {
-	seq          uint32
-	routeSocket  *nl.NetlinkSocket
-	xfrmSocket   *nl.NetlinkSocket
+	sockets      map[int]*nl.SocketHandle
 	lookupByDump bool
 }
 
+// SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle
+func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
+	_, ok := h.sockets[nlFamily]
+	return ok
+}
+
 // NewHandle returns a netlink handle on the current network namespace.
-func NewHandle() (*Handle, error) {
-	return newHandle(netns.None(), netns.None())
+// Caller may specify the netlink families the handle should support.
+// If no families are specified, all the families the netlink package
+// supports will be automatically added.
+func NewHandle(nlFamilies ...int) (*Handle, error) {
+	return newHandle(netns.None(), netns.None(), nlFamilies...)
 }
 
 // NewHandle returns a netlink handle on the network namespace
 // specified by ns. If ns=netns.None(), current network namespace
 // will be assumed
-func NewHandleAt(ns netns.NsHandle) (*Handle, error) {
-	return newHandle(ns, netns.None())
+func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
+	return newHandle(ns, netns.None(), nlFamilies...)
 }
 
 // NewHandleAtFrom works as NewHandle but allows client to specify the
@@ -40,37 +46,33 @@ func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
 	return newHandle(newNs, curNs)
 }
 
-func newHandle(newNs, curNs netns.NsHandle) (*Handle, error) {
-	var (
-		err     error
-		rSocket *nl.NetlinkSocket
-		xSocket *nl.NetlinkSocket
-	)
-	rSocket, err = nl.GetNetlinkSocketAt(newNs, curNs, syscall.NETLINK_ROUTE)
-	if err != nil {
-		return nil, err
+func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) {
+	h := &Handle{sockets: map[int]*nl.SocketHandle{}}
+	fams := nl.SupportedNlFamilies
+	if len(nlFamilies) != 0 {
+		fams = nlFamilies
 	}
-	xSocket, err = nl.GetNetlinkSocketAt(newNs, curNs, syscall.NETLINK_XFRM)
-	if err != nil {
-		return nil, err
+	for _, f := range fams {
+		s, err := nl.GetNetlinkSocketAt(newNs, curNs, f)
+		if err != nil {
+			return nil, err
+		}
+		h.sockets[f] = &nl.SocketHandle{Socket: s}
 	}
-	return &Handle{routeSocket: rSocket, xfrmSocket: xSocket}, nil
+	return h, nil
 }
 
 // Delete releases the resources allocated to this handle
 func (h *Handle) Delete() {
-	if h.routeSocket != nil {
-		h.routeSocket.Close()
-	}
-	if h.xfrmSocket != nil {
-		h.xfrmSocket.Close()
+	for _, sh := range h.sockets {
+		sh.Close()
 	}
-	h.routeSocket, h.xfrmSocket = nil, nil
+	h.sockets = nil
 }
 
 func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
 	// Do this so that package API still use nl package variable nextSeqNr
-	if h.routeSocket == nil {
+	if h.sockets == nil {
 		return nl.NewNetlinkRequest(proto, flags)
 	}
 	return &nl.NetlinkRequest{
@@ -78,9 +80,7 @@ func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
 			Len:   uint32(syscall.SizeofNlMsghdr),
 			Type:  uint16(proto),
 			Flags: syscall.NLM_F_REQUEST | uint16(flags),
-			Seq:   atomic.AddUint32(&h.seq, 1),
 		},
-		RouteSocket: h.routeSocket,
-		XfmrSocket:  h.xfrmSocket,
+		Sockets: h.sockets,
 	}
 }

+ 10 - 3
vendor/github.com/vishvananda/netlink/handle_test.go

@@ -10,6 +10,7 @@ import (
 	"sync/atomic"
 	"testing"
 
+	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netns"
 )
 
@@ -18,12 +19,18 @@ func TestHandleCreateDelete(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	if h.routeSocket == nil || h.xfrmSocket == nil {
-		t.Fatalf("Handle socket(s) were not created")
+	for _, f := range nl.SupportedNlFamilies {
+		sh, ok := h.sockets[f]
+		if !ok {
+			t.Fatalf("Handle socket(s) for family %d was not created", f)
+		}
+		if sh.Socket == nil {
+			t.Fatalf("Socket for family %d was not created", f)
+		}
 	}
 
 	h.Delete()
-	if h.routeSocket != nil || h.xfrmSocket != nil {
+	if h.sockets != nil {
 		t.Fatalf("Handle socket(s) were not destroyed")
 	}
 }

+ 14 - 3
vendor/github.com/vishvananda/netlink/link_linux.go

@@ -10,6 +10,7 @@ import (
 	"unsafe"
 
 	"github.com/vishvananda/netlink/nl"
+	"github.com/vishvananda/netns"
 )
 
 const SizeofLinkStats = 0x5c
@@ -425,7 +426,7 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
 		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum))
 	}
 	if vxlan.GBP {
-		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, boolAttr(vxlan.GBP))
+		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, []byte{})
 	}
 	if vxlan.NoAge {
 		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
@@ -1011,7 +1012,17 @@ type LinkUpdate struct {
 // LinkSubscribe takes a chan down which notifications will be sent
 // when links change.  Close the 'done' chan to stop subscription.
 func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error {
-	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK)
+	return linkSubscribe(netns.None(), netns.None(), ch, done)
+}
+
+// LinkSubscribeAt works like LinkSubscribe plus it allows the caller
+// to choose the network namespace in which to subscribe (ns).
+func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error {
+	return linkSubscribe(ns, netns.None(), ch, done)
+}
+
+func linkSubscribe(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error {
+	s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK)
 	if err != nil {
 		return err
 	}
@@ -1152,7 +1163,7 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
 		case nl.IFLA_VXLAN_UDP_CSUM:
 			vxlan.UDPCSum = int8(datum.Value[0]) != 0
 		case nl.IFLA_VXLAN_GBP:
-			vxlan.GBP = int8(datum.Value[0]) != 0
+			vxlan.GBP = true
 		case nl.IFLA_VXLAN_AGEING:
 			vxlan.Age = int(native.Uint32(datum.Value[0:4]))
 			vxlan.NoAge = vxlan.Age == 0

+ 81 - 0
vendor/github.com/vishvananda/netlink/link_test.go

@@ -596,6 +596,39 @@ func TestLinkAddDelVxlan(t *testing.T) {
 	}
 }
 
+func TestLinkAddDelVxlanGbp(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)
+	}
+
+	vxlan := Vxlan{
+		LinkAttrs: LinkAttrs{
+			Name: "bar",
+		},
+		VxlanId:      10,
+		VtepDevIndex: parent.Index,
+		Learning:     true,
+		L2miss:       true,
+		L3miss:       true,
+		GBP:          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")
@@ -814,6 +847,54 @@ func TestLinkSubscribe(t *testing.T) {
 	}
 }
 
+func TestLinkSubscribeAt(t *testing.T) {
+	// Create an handle on a custom netns
+	newNs, err := netns.New()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer newNs.Close()
+
+	nh, err := NewHandleAt(newNs)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer nh.Delete()
+
+	// Subscribe for Link events on the custom netns
+	ch := make(chan LinkUpdate)
+	done := make(chan struct{})
+	defer close(done)
+	if err := LinkSubscribeAt(newNs, ch, done); err != nil {
+		t.Fatal(err)
+	}
+
+	link := &Veth{LinkAttrs{Name: "test", TxQLen: testTxQLen, MTU: 1400}, "bar"}
+	if err := nh.LinkAdd(link); err != nil {
+		t.Fatal(err)
+	}
+
+	if !expectLinkUpdate(ch, "test", false) {
+		t.Fatal("Add update not received as expected")
+	}
+
+	if err := nh.LinkSetUp(link); err != nil {
+		t.Fatal(err)
+	}
+
+	if !expectLinkUpdate(ch, "test", true) {
+		t.Fatal("Link Up update not received as expected")
+	}
+
+	if err := nh.LinkDel(link); err != nil {
+		t.Fatal(err)
+	}
+
+	if !expectLinkUpdate(ch, "test", false) {
+		t.Fatal("Del update not received as expected")
+	}
+}
+
 func TestLinkStats(t *testing.T) {
 	defer setUpNetlinkTest(t)()
 

+ 81 - 17
vendor/github.com/vishvananda/netlink/nl/nl_linux.go

@@ -22,6 +22,9 @@ const (
 	FAMILY_V6  = syscall.AF_INET6
 )
 
+// SupportedNlFamilies contains the list of netlink families this netlink package supports
+var SupportedNlFamilies = []int{syscall.NETLINK_ROUTE, syscall.NETLINK_XFRM}
+
 var nextSeqNr uint32
 
 // GetIPFamily returns the family type of a net.IP.
@@ -175,9 +178,8 @@ func (a *RtAttr) Serialize() []byte {
 
 type NetlinkRequest struct {
 	syscall.NlMsghdr
-	Data        []NetlinkRequestData
-	RouteSocket *NetlinkSocket
-	XfmrSocket  *NetlinkSocket
+	Data    []NetlinkRequestData
+	Sockets map[int]*SocketHandle
 }
 
 // Serialize the Netlink Request into a byte array
@@ -217,15 +219,12 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
 		err error
 	)
 
-	switch sockType {
-	case syscall.NETLINK_XFRM:
-		s = req.XfmrSocket
-	case syscall.NETLINK_ROUTE:
-		s = req.RouteSocket
-	default:
-		return nil, fmt.Errorf("Socket type %d is not handled", sockType)
+	if req.Sockets != nil {
+		if sh, ok := req.Sockets[sockType]; ok {
+			s = sh.Socket
+			req.Seq = atomic.AddUint32(&sh.Seq, 1)
+		}
 	}
-
 	sharedSocket := s != nil
 
 	if s == nil {
@@ -332,24 +331,63 @@ func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
 // moves back into it when done. If newNs is close, the socket will be opened
 // in the current network namespace.
 func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSocket, error) {
-	var err error
+	c, err := executeInNetns(newNs, curNs)
+	if err != nil {
+		return nil, err
+	}
+	defer c()
+	return getNetlinkSocket(protocol)
+}
 
+// executeInNetns sets execution of the code following this call to the
+// network namespace newNs, then moves the thread back to curNs if open,
+// otherwise to the current netns at the time the function was invoked
+// In case of success, the caller is expected to execute the returned function
+// at the end of the code that needs to be executed in the network namespace.
+// Example:
+// func jobAt(...) error {
+//      d, err := executeInNetns(...)
+//      if err != nil { return err}
+//      defer d()
+//      < code which needs to be executed in specific netns>
+//  }
+// TODO: his function probably belongs to netns pkg.
+func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) {
+	var (
+		err       error
+		moveBack  func(netns.NsHandle) error
+		closeNs   func() error
+		unlockThd func()
+	)
+	restore := func() {
+		// order matters
+		if moveBack != nil {
+			moveBack(curNs)
+		}
+		if closeNs != nil {
+			closeNs()
+		}
+		if unlockThd != nil {
+			unlockThd()
+		}
+	}
 	if newNs.IsOpen() {
 		runtime.LockOSThread()
-		defer runtime.UnlockOSThread()
+		unlockThd = runtime.UnlockOSThread
 		if !curNs.IsOpen() {
 			if curNs, err = netns.Get(); err != nil {
+				restore()
 				return nil, fmt.Errorf("could not get current namespace while creating netlink socket: %v", err)
 			}
-			defer curNs.Close()
+			closeNs = curNs.Close
 		}
 		if err := netns.Set(newNs); err != nil {
+			restore()
 			return nil, fmt.Errorf("failed to set into network namespace %d while creating netlink socket: %v", newNs, err)
 		}
-		defer netns.Set(curNs)
+		moveBack = netns.Set
 	}
-
-	return getNetlinkSocket(protocol)
+	return restore, nil
 }
 
 // Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE)
@@ -378,6 +416,18 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
 	return s, nil
 }
 
+// SubscribeAt works like Subscribe plus let's the caller choose the network
+// namespace in which the socket would be opened (newNs). Then control goes back
+// to curNs if open, otherwise to the netns at the time this function was called.
+func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*NetlinkSocket, error) {
+	c, err := executeInNetns(newNs, curNs)
+	if err != nil {
+		return nil, err
+	}
+	defer c()
+	return Subscribe(protocol, groups...)
+}
+
 func (s *NetlinkSocket) Close() {
 	syscall.Close(s.fd)
 	s.fd = -1
@@ -486,3 +536,17 @@ func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) {
 	}
 	return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
 }
+
+// SocketHandle contains the netlink socket and the associated
+// sequence counter for a specific netlink family
+type SocketHandle struct {
+	Seq    uint32
+	Socket *NetlinkSocket
+}
+
+// Close closes the netlink socket
+func (sh *SocketHandle) Close() {
+	if sh.Socket != nil {
+		sh.Socket.Close()
+	}
+}

+ 30 - 0
vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go

@@ -10,6 +10,7 @@ const (
 	SizeofXfrmUsersaInfo  = 0xe0
 	SizeofXfrmAlgo        = 0x44
 	SizeofXfrmAlgoAuth    = 0x48
+	SizeofXfrmAlgoAEAD    = 0x48
 	SizeofXfrmEncapTmpl   = 0x18
 	SizeofXfrmUsersaFlush = 0x8
 )
@@ -194,6 +195,35 @@ func (msg *XfrmAlgoAuth) Serialize() []byte {
 //   char    alg_key[0];
 // }
 
+type XfrmAlgoAEAD struct {
+	AlgName   [64]byte
+	AlgKeyLen uint32
+	AlgICVLen uint32
+	AlgKey    []byte
+}
+
+func (msg *XfrmAlgoAEAD) Len() int {
+	return SizeofXfrmAlgoAEAD + int(msg.AlgKeyLen/8)
+}
+
+func DeserializeXfrmAlgoAEAD(b []byte) *XfrmAlgoAEAD {
+	ret := XfrmAlgoAEAD{}
+	copy(ret.AlgName[:], b[0:64])
+	ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64]))
+	ret.AlgICVLen = *(*uint32)(unsafe.Pointer(&b[68]))
+	ret.AlgKey = b[72:ret.Len()]
+	return &ret
+}
+
+func (msg *XfrmAlgoAEAD) Serialize() []byte {
+	b := make([]byte, msg.Len())
+	copy(b[0:64], msg.AlgName[:])
+	copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:])
+	copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgICVLen)))[:])
+	copy(b[72:msg.Len()], msg.AlgKey[:])
+	return b
+}
+
 // struct xfrm_encap_tmpl {
 //   __u16   encap_type;
 //   __be16    encap_sport;

+ 36 - 0
vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go

@@ -239,3 +239,39 @@ func TestXfrmMarkDeserializeSerialize(t *testing.T) {
 	msg := DeserializeXfrmMark(orig)
 	testDeserializeSerialize(t, orig, safemsg, msg)
 }
+
+func (msg *XfrmAlgoAEAD) write(b []byte) {
+	native := NativeEndian()
+	copy(b[0:64], msg.AlgName[:])
+	native.PutUint32(b[64:68], msg.AlgKeyLen)
+	native.PutUint32(b[68:72], msg.AlgICVLen)
+	copy(b[72:msg.Len()], msg.AlgKey[:])
+}
+
+func (msg *XfrmAlgoAEAD) serializeSafe() []byte {
+	b := make([]byte, msg.Len())
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmAlgoAEADSafe(b []byte) *XfrmAlgoAEAD {
+	var msg = XfrmAlgoAEAD{}
+	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.AlgICVLen)
+	msg.AlgKey = b[72:msg.Len()]
+	return &msg
+}
+
+func TestXfrmXfrmAlgoAeadDeserializeSerialize(t *testing.T) {
+	native := NativeEndian()
+	// use a 32 byte key len
+	var orig = make([]byte, SizeofXfrmAlgoAEAD+36)
+	rand.Read(orig)
+	// set the key len to (256 + 32) bits
+	var KeyLen uint32 = 0x00000120
+	native.PutUint32(orig[64:68], KeyLen)
+	safemsg := deserializeXfrmAlgoAEADSafe(orig)
+	msg := DeserializeXfrmAlgoAEAD(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}

+ 12 - 1
vendor/github.com/vishvananda/netlink/route_linux.go

@@ -6,6 +6,7 @@ import (
 	"syscall"
 
 	"github.com/vishvananda/netlink/nl"
+	"github.com/vishvananda/netns"
 )
 
 // RtAttr is shared so it is in netlink_linux.go
@@ -421,7 +422,17 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
 // RouteSubscribe takes a chan down which notifications will be sent
 // when routes are added or deleted. Close the 'done' chan to stop subscription.
 func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
-	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE)
+	return routeSubscribeAt(netns.None(), netns.None(), ch, done)
+}
+
+// RouteSubscribeAt works like RouteSubscribe plus it allows the caller
+// to choose the network namespace in which to subscribe (ns).
+func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
+	return routeSubscribeAt(ns, netns.None(), ch, done)
+}
+
+func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
+	s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE)
 	if err != nil {
 		return err
 	}

+ 58 - 0
vendor/github.com/vishvananda/netlink/route_test.go

@@ -5,6 +5,8 @@ import (
 	"syscall"
 	"testing"
 	"time"
+
+	"github.com/vishvananda/netns"
 )
 
 func TestRouteAddDel(t *testing.T) {
@@ -143,6 +145,62 @@ func TestRouteSubscribe(t *testing.T) {
 	}
 }
 
+func TestRouteSubscribeAt(t *testing.T) {
+	// Create an handle on a custom netns
+	newNs, err := netns.New()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer newNs.Close()
+
+	nh, err := NewHandleAt(newNs)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer nh.Delete()
+
+	// Subscribe for Route events on the custom netns
+	ch := make(chan RouteUpdate)
+	done := make(chan struct{})
+	defer close(done)
+	if err := RouteSubscribeAt(newNs, ch, done); err != nil {
+		t.Fatal(err)
+	}
+
+	// get loopback interface
+	link, err := nh.LinkByName("lo")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// bring the interface up
+	if err = nh.LinkSetUp(link); err != nil {
+		t.Fatal(err)
+	}
+
+	// add a gateway route
+	dst := &net.IPNet{
+		IP:   net.IPv4(192, 169, 0, 0),
+		Mask: net.CIDRMask(24, 32),
+	}
+
+	ip := net.IPv4(127, 100, 1, 1)
+	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
+	if err := nh.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 := nh.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()

+ 12 - 3
vendor/github.com/vishvananda/netlink/xfrm_state.go

@@ -10,10 +10,18 @@ type XfrmStateAlgo struct {
 	Name        string
 	Key         []byte
 	TruncateLen int // Auth only
+	ICVLen      int // AEAD only
 }
 
 func (a XfrmStateAlgo) String() string {
-	return fmt.Sprintf("{Name: %s, Key: 0x%x, TruncateLen: %d}", a.Name, a.Key, a.TruncateLen)
+	base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key)
+	if a.TruncateLen != 0 {
+		base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen)
+	}
+	if a.ICVLen != 0 {
+		base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen)
+	}
+	return fmt.Sprintf("%s}", base)
 }
 
 // EncapType is an enum representing the optional packet encapsulation.
@@ -73,12 +81,13 @@ type XfrmState struct {
 	Mark         *XfrmMark
 	Auth         *XfrmStateAlgo
 	Crypt        *XfrmStateAlgo
+	Aead         *XfrmStateAlgo
 	Encap        *XfrmStateEncap
 }
 
 func (sa XfrmState) String() string {
-	return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, Auth: %v, Crypt: %v, Encap: %v",
-		sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.Auth, sa.Crypt, sa.Encap)
+	return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, Auth: %v, Crypt: %v, Aead: %v,Encap: %v",
+		sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.Auth, sa.Crypt, sa.Aead, sa.Encap)
 }
 func (sa XfrmState) Print(stats bool) string {
 	if !stats {

+ 24 - 0
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go

@@ -35,6 +35,20 @@ func writeStateAlgoAuth(a *XfrmStateAlgo) []byte {
 	return algo.Serialize()
 }
 
+func writeStateAlgoAead(a *XfrmStateAlgo) []byte {
+	algo := nl.XfrmAlgoAEAD{
+		AlgKeyLen: uint32(len(a.Key) * 8),
+		AlgICVLen: uint32(a.ICVLen),
+		AlgKey:    a.Key,
+	}
+	end := len(a.Name)
+	if end > 64 {
+		end = 64
+	}
+	copy(algo.AlgName[:end], a.Name)
+	return algo.Serialize()
+}
+
 func writeMark(m *XfrmMark) []byte {
 	mark := &nl.XfrmMark{
 		Value: m.Value,
@@ -97,6 +111,10 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
 		out := nl.NewRtAttr(nl.XFRMA_ALG_CRYPT, writeStateAlgo(state.Crypt))
 		req.AddData(out)
 	}
+	if state.Aead != nil {
+		out := nl.NewRtAttr(nl.XFRMA_ALG_AEAD, writeStateAlgoAead(state.Aead))
+		req.AddData(out)
+	}
 	if state.Encap != nil {
 		encapData := make([]byte, nl.SizeofXfrmEncapTmpl)
 		encap := nl.DeserializeXfrmEncapTmpl(encapData)
@@ -271,6 +289,12 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
 			state.Auth.Name = nl.BytesToString(algo.AlgName[:])
 			state.Auth.Key = algo.AlgKey
 			state.Auth.TruncateLen = int(algo.AlgTruncLen)
+		case nl.XFRMA_ALG_AEAD:
+			state.Aead = new(XfrmStateAlgo)
+			algo := nl.DeserializeXfrmAlgoAEAD(attr.Value[:])
+			state.Aead.Name = nl.BytesToString(algo.AlgName[:])
+			state.Aead.Key = algo.AlgKey
+			state.Aead.ICVLen = int(algo.AlgICVLen)
 		case nl.XFRMA_ENCAP:
 			encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:])
 			state.Encap = new(XfrmStateEncap)

+ 50 - 6
vendor/github.com/vishvananda/netlink/xfrm_state_test.go

@@ -2,16 +2,20 @@ package netlink
 
 import (
 	"bytes"
+	"encoding/hex"
 	"net"
 	"testing"
 )
 
 func TestXfrmStateAddGetDel(t *testing.T) {
+	for _, s := range []*XfrmState{getBaseState(), getAeadState()} {
+		testXfrmStateAddGetDel(t, s)
+	}
+}
+
+func testXfrmStateAddGetDel(t *testing.T, state *XfrmState) {
 	tearDown := setUpNetlinkTest(t)
 	defer tearDown()
-
-	state := getBaseState()
-
 	if err := XfrmStateAdd(state); err != nil {
 		t.Fatal(err)
 	}
@@ -176,6 +180,23 @@ func getBaseState() *XfrmState {
 	}
 }
 
+func getAeadState() *XfrmState {
+	// 128 key bits + 32 salt bits
+	k, _ := hex.DecodeString("d0562776bf0e75830ba3f7f8eb6c09b555aa1177")
+	return &XfrmState{
+		Src:   net.ParseIP("192.168.1.1"),
+		Dst:   net.ParseIP("192.168.2.2"),
+		Proto: XFRM_PROTO_ESP,
+		Mode:  XFRM_MODE_TUNNEL,
+		Spi:   2,
+		Aead: &XfrmStateAlgo{
+			Name:   "rfc4106(gcm(aes))",
+			Key:    k,
+			ICVLen: 64,
+		},
+	}
+}
+
 func compareStates(a, b *XfrmState) bool {
 	if a == b {
 		return true
@@ -185,9 +206,10 @@ func compareStates(a, b *XfrmState) bool {
 	}
 	return a.Src.Equal(b.Src) && a.Dst.Equal(b.Dst) &&
 		a.Mode == b.Mode && a.Spi == b.Spi && a.Proto == b.Proto &&
-		a.Auth.Name == b.Auth.Name && bytes.Equal(a.Auth.Key, b.Auth.Key) &&
-		a.Crypt.Name == b.Crypt.Name && bytes.Equal(a.Crypt.Key, b.Crypt.Key) &&
-		a.Mark.Value == b.Mark.Value && a.Mark.Mask == b.Mark.Mask
+		compareAlgo(a.Auth, b.Auth) &&
+		compareAlgo(a.Crypt, b.Crypt) &&
+		compareAlgo(a.Aead, b.Aead) &&
+		compareMarks(a.Mark, b.Mark)
 }
 
 func compareLimits(a, b *XfrmState) bool {
@@ -200,3 +222,25 @@ func compareLimits(a, b *XfrmState) bool {
 		a.Limits.TimeUseHard == b.Limits.TimeUseHard &&
 		a.Limits.TimeUseSoft == b.Limits.TimeUseSoft
 }
+
+func compareAlgo(a, b *XfrmStateAlgo) bool {
+	if a == b {
+		return true
+	}
+	if a == nil || b == nil {
+		return false
+	}
+	return a.Name == b.Name && bytes.Equal(a.Key, b.Key) &&
+		(a.TruncateLen == 0 || a.TruncateLen == b.TruncateLen) &&
+		(a.ICVLen == 0 || a.ICVLen == b.ICVLen)
+}
+
+func compareMarks(a, b *XfrmMark) bool {
+	if a == b {
+		return true
+	}
+	if a == nil || b == nil {
+		return false
+	}
+	return a.Value == b.Value && a.Mask == b.Mask
+}