Browse Source

Vendoring netlink library

Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
Flavio Crisciani 8 years ago
parent
commit
acf9c53292

+ 7 - 7
libnetwork/vendor.conf

@@ -19,11 +19,11 @@ github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef
 
 github.com/godbus/dbus 5f6efc7ef2759c81b7ba876593971bfce311eab3
 github.com/gogo/protobuf 8d70fb3182befc465c4a1eac8ad4d38ff49778e2
-github.com/golang/protobuf/proto f7137ae6b19afbfd61a94b746fda3b3fe0491874
+github.com/golang/protobuf f7137ae6b19afbfd61a94b746fda3b3fe0491874
 github.com/gorilla/context 215affda49addc4c8ef7e2534915df2c8c35c6cd
 github.com/gorilla/mux 8096f47503459bcc74d1f4c487b7e6e42e5746b5
-github.com/hashicorp/consul/api 954aec66231b79c161a4122b023fbcad13047f79
-github.com/hashicorp/go-msgpack/codec 71c2886f5a673a35f909803f38ece5810165097b
+github.com/hashicorp/consul 954aec66231b79c161a4122b023fbcad13047f79
+github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
 github.com/hashicorp/go-multierror 2167c8ec40776024589f483a6b836489e47e1049
 github.com/hashicorp/memberlist v0.1.0
 github.com/sean-/seed e2103e2c35297fb7e17febb81e49b312087a2372
@@ -31,13 +31,13 @@ github.com/hashicorp/go-sockaddr acd314c5781ea706c710d9ea70069fd2e110d61d
 github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
 github.com/mattn/go-shellwords 525bedee691b5a8df547cb5cf9f86b7fb1883e24
 github.com/miekg/dns d27455715200c7d3e321a1e5cadb27c9ee0b0f02
-github.com/opencontainers/runc/libcontainer ba1568de399395774ad84c2ace65937814c542ed
-github.com/samuel/go-zookeeper/zk d0e0d8e11f318e000a8cc434616d69e329edc374
+github.com/opencontainers/runc ba1568de399395774ad84c2ace65937814c542ed
+github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
 github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1
 github.com/stretchr/testify dab07ac62d4905d3e48d17dc549c684ac3b7c15a
-github.com/syndtr/gocapability/capability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
+github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
 github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065
-github.com/vishvananda/netlink 1e86b2bee5b6a7d377e4c02bb7f98209d6a7297c
+github.com/vishvananda/netlink bd6d5de5ccef2d66b0a26177928d0d8895d7f969
 github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
 golang.org/x/net c427ad74c6d7a814201695e9ffde0c5d400a7674
 golang.org/x/sys 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9

+ 7 - 5
libnetwork/vendor/github.com/vishvananda/netlink/addr.go

@@ -10,11 +10,13 @@ import (
 // include a mask, so it stores the address as a net.IPNet.
 type Addr struct {
 	*net.IPNet
-	Label     string
-	Flags     int
-	Scope     int
-	Peer      *net.IPNet
-	Broadcast net.IP
+	Label       string
+	Flags       int
+	Scope       int
+	Peer        *net.IPNet
+	Broadcast   net.IP
+	PreferedLft int
+	ValidLft    int
 }
 
 // String returns $ip/$netmask $label

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

@@ -195,10 +195,16 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
 			}
 			addr.IPNet = local
+		case syscall.IFA_BROADCAST:
+			addr.Broadcast = attr.Value
 		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]))
+		case nl.IFA_CACHEINFO:
+			ci := nl.DeserializeIfaCacheInfo(attr.Value)
+			addr.PreferedLft = int(ci.IfaPrefered)
+			addr.ValidLft = int(ci.IfaValid)
 		}
 	}
 
@@ -216,6 +222,10 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
 type AddrUpdate struct {
 	LinkAddress net.IPNet
 	LinkIndex   int
+	Flags       int
+	Scope       int
+	PreferedLft int
+	ValidLft    int
 	NewAddr     bool // true=added false=deleted
 }
 
@@ -263,7 +273,13 @@ func addrSubscribe(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-cha
 					continue
 				}
 
-				ch <- AddrUpdate{LinkAddress: *addr.IPNet, LinkIndex: ifindex, NewAddr: msgType == syscall.RTM_NEWADDR}
+				ch <- AddrUpdate{LinkAddress: *addr.IPNet,
+					LinkIndex:   ifindex,
+					NewAddr:     msgType == syscall.RTM_NEWADDR,
+					Flags:       addr.Flags,
+					Scope:       addr.Scope,
+					PreferedLft: addr.PreferedLft,
+					ValidLft:    addr.ValidLft}
 			}
 		}
 	}()

+ 9 - 13
libnetwork/vendor/github.com/vishvananda/netlink/filter_linux.go

@@ -141,19 +141,19 @@ func (h *Handle) FilterAdd(filter Filter) error {
 		}
 
 		if native != networkOrder {
-			// Copy Tcu32Sel.
-			cSel := sel
+			// Copy TcU32Sel.
+			cSel := *sel
 			keys := make([]nl.TcU32Key, cap(sel.Keys))
 			copy(keys, sel.Keys)
 			cSel.Keys = keys
-			sel = cSel
+			sel = &cSel
 
 			// Handle the endianness of attributes
 			sel.Offmask = native.Uint16(htons(sel.Offmask))
 			sel.Hmask = native.Uint32(htonl(sel.Hmask))
-			for _, key := range sel.Keys {
-				key.Mask = native.Uint32(htonl(key.Mask))
-				key.Val = native.Uint32(htonl(key.Val))
+			for i, key := range sel.Keys {
+				sel.Keys[i].Mask = native.Uint32(htonl(key.Mask))
+				sel.Keys[i].Val = native.Uint32(htonl(key.Val))
 			}
 		}
 		sel.Nkeys = uint8(len(sel.Keys))
@@ -453,15 +453,11 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
 				// Handle the endianness of attributes
 				u32.Sel.Offmask = native.Uint16(htons(sel.Offmask))
 				u32.Sel.Hmask = native.Uint32(htonl(sel.Hmask))
-				for _, key := range u32.Sel.Keys {
-					key.Mask = native.Uint32(htonl(key.Mask))
-					key.Val = native.Uint32(htonl(key.Val))
+				for i, key := range u32.Sel.Keys {
+					u32.Sel.Keys[i].Mask = native.Uint32(htonl(key.Mask))
+					u32.Sel.Keys[i].Val = native.Uint32(htonl(key.Val))
 				}
 			}
-			// only parse if we have a very basic redirect
-			if sel.Flags&nl.TC_U32_TERMINAL == 0 || sel.Nkeys != 1 {
-				return detailed, nil
-			}
 		case nl.TCA_U32_ACT:
 			tables, err := nl.ParseRouteAttr(datum.Value)
 			if err != nil {

+ 167 - 0
libnetwork/vendor/github.com/vishvananda/netlink/genetlink_linux.go

@@ -0,0 +1,167 @@
+package netlink
+
+import (
+	"fmt"
+	"syscall"
+
+	"github.com/vishvananda/netlink/nl"
+)
+
+type GenlOp struct {
+	ID    uint32
+	Flags uint32
+}
+
+type GenlMulticastGroup struct {
+	ID   uint32
+	Name string
+}
+
+type GenlFamily struct {
+	ID      uint16
+	HdrSize uint32
+	Name    string
+	Version uint32
+	MaxAttr uint32
+	Ops     []GenlOp
+	Groups  []GenlMulticastGroup
+}
+
+func parseOps(b []byte) ([]GenlOp, error) {
+	attrs, err := nl.ParseRouteAttr(b)
+	if err != nil {
+		return nil, err
+	}
+	ops := make([]GenlOp, 0, len(attrs))
+	for _, a := range attrs {
+		nattrs, err := nl.ParseRouteAttr(a.Value)
+		if err != nil {
+			return nil, err
+		}
+		var op GenlOp
+		for _, na := range nattrs {
+			switch na.Attr.Type {
+			case nl.GENL_CTRL_ATTR_OP_ID:
+				op.ID = native.Uint32(na.Value)
+			case nl.GENL_CTRL_ATTR_OP_FLAGS:
+				op.Flags = native.Uint32(na.Value)
+			}
+		}
+		ops = append(ops, op)
+	}
+	return ops, nil
+}
+
+func parseMulticastGroups(b []byte) ([]GenlMulticastGroup, error) {
+	attrs, err := nl.ParseRouteAttr(b)
+	if err != nil {
+		return nil, err
+	}
+	groups := make([]GenlMulticastGroup, 0, len(attrs))
+	for _, a := range attrs {
+		nattrs, err := nl.ParseRouteAttr(a.Value)
+		if err != nil {
+			return nil, err
+		}
+		var g GenlMulticastGroup
+		for _, na := range nattrs {
+			switch na.Attr.Type {
+			case nl.GENL_CTRL_ATTR_MCAST_GRP_NAME:
+				g.Name = nl.BytesToString(na.Value)
+			case nl.GENL_CTRL_ATTR_MCAST_GRP_ID:
+				g.ID = native.Uint32(na.Value)
+			}
+		}
+		groups = append(groups, g)
+	}
+	return groups, nil
+}
+
+func (f *GenlFamily) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
+	for _, a := range attrs {
+		switch a.Attr.Type {
+		case nl.GENL_CTRL_ATTR_FAMILY_NAME:
+			f.Name = nl.BytesToString(a.Value)
+		case nl.GENL_CTRL_ATTR_FAMILY_ID:
+			f.ID = native.Uint16(a.Value)
+		case nl.GENL_CTRL_ATTR_VERSION:
+			f.Version = native.Uint32(a.Value)
+		case nl.GENL_CTRL_ATTR_HDRSIZE:
+			f.HdrSize = native.Uint32(a.Value)
+		case nl.GENL_CTRL_ATTR_MAXATTR:
+			f.MaxAttr = native.Uint32(a.Value)
+		case nl.GENL_CTRL_ATTR_OPS:
+			ops, err := parseOps(a.Value)
+			if err != nil {
+				return err
+			}
+			f.Ops = ops
+		case nl.GENL_CTRL_ATTR_MCAST_GROUPS:
+			groups, err := parseMulticastGroups(a.Value)
+			if err != nil {
+				return err
+			}
+			f.Groups = groups
+		}
+	}
+
+	return nil
+}
+
+func parseFamilies(msgs [][]byte) ([]*GenlFamily, error) {
+	families := make([]*GenlFamily, 0, len(msgs))
+	for _, m := range msgs {
+		attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
+		if err != nil {
+			return nil, err
+		}
+		family := &GenlFamily{}
+		if err := family.parseAttributes(attrs); err != nil {
+			return nil, err
+		}
+
+		families = append(families, family)
+	}
+	return families, nil
+}
+
+func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) {
+	msg := &nl.Genlmsg{
+		Command: nl.GENL_CTRL_CMD_GETFAMILY,
+		Version: nl.GENL_CTRL_VERSION,
+	}
+	req := h.newNetlinkRequest(nl.GENL_ID_CTRL, syscall.NLM_F_DUMP)
+	req.AddData(msg)
+	msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
+	if err != nil {
+		return nil, err
+	}
+	return parseFamilies(msgs)
+}
+
+func GenlFamilyList() ([]*GenlFamily, error) {
+	return pkgHandle.GenlFamilyList()
+}
+
+func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
+	msg := &nl.Genlmsg{
+		Command: nl.GENL_CTRL_CMD_GETFAMILY,
+		Version: nl.GENL_CTRL_VERSION,
+	}
+	req := h.newNetlinkRequest(nl.GENL_ID_CTRL, 0)
+	req.AddData(msg)
+	req.AddData(nl.NewRtAttr(nl.GENL_CTRL_ATTR_FAMILY_NAME, nl.ZeroTerminated(name)))
+	msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
+	if err != nil {
+		return nil, err
+	}
+	families, err := parseFamilies(msgs)
+	if len(families) != 1 {
+		return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY")
+	}
+	return families[0], nil
+}
+
+func GenlFamilyGet(name string) (*GenlFamily, error) {
+	return pkgHandle.GenlFamilyGet(name)
+}

+ 25 - 0
libnetwork/vendor/github.com/vishvananda/netlink/genetlink_unspecified.go

@@ -0,0 +1,25 @@
+// +build !linux
+
+package netlink
+
+type GenlOp struct{}
+
+type GenlMulticastGroup struct{}
+
+type GenlFamily struct{}
+
+func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) {
+	return nil, ErrNotImplemented
+}
+
+func GenlFamilyList() ([]*GenlFamily, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
+	return nil, ErrNotImplemented
+}
+
+func GenlFamilyGet(name string) (*GenlFamily, error) {
+	return nil, ErrNotImplemented
+}

+ 238 - 0
libnetwork/vendor/github.com/vishvananda/netlink/gtp_linux.go

@@ -0,0 +1,238 @@
+package netlink
+
+import (
+	"fmt"
+	"net"
+	"strings"
+	"syscall"
+
+	"github.com/vishvananda/netlink/nl"
+)
+
+type PDP struct {
+	Version     uint32
+	TID         uint64
+	PeerAddress net.IP
+	MSAddress   net.IP
+	Flow        uint16
+	NetNSFD     uint32
+	ITEI        uint32
+	OTEI        uint32
+}
+
+func (pdp *PDP) String() string {
+	elems := []string{}
+	elems = append(elems, fmt.Sprintf("Version: %d", pdp.Version))
+	if pdp.Version == 0 {
+		elems = append(elems, fmt.Sprintf("TID: %d", pdp.TID))
+	} else if pdp.Version == 1 {
+		elems = append(elems, fmt.Sprintf("TEI: %d/%d", pdp.ITEI, pdp.OTEI))
+	}
+	elems = append(elems, fmt.Sprintf("MS-Address: %s", pdp.MSAddress))
+	elems = append(elems, fmt.Sprintf("Peer-Address: %s", pdp.PeerAddress))
+	return fmt.Sprintf("{%s}", strings.Join(elems, " "))
+}
+
+func (p *PDP) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
+	for _, a := range attrs {
+		switch a.Attr.Type {
+		case nl.GENL_GTP_ATTR_VERSION:
+			p.Version = native.Uint32(a.Value)
+		case nl.GENL_GTP_ATTR_TID:
+			p.TID = native.Uint64(a.Value)
+		case nl.GENL_GTP_ATTR_PEER_ADDRESS:
+			p.PeerAddress = net.IP(a.Value)
+		case nl.GENL_GTP_ATTR_MS_ADDRESS:
+			p.MSAddress = net.IP(a.Value)
+		case nl.GENL_GTP_ATTR_FLOW:
+			p.Flow = native.Uint16(a.Value)
+		case nl.GENL_GTP_ATTR_NET_NS_FD:
+			p.NetNSFD = native.Uint32(a.Value)
+		case nl.GENL_GTP_ATTR_I_TEI:
+			p.ITEI = native.Uint32(a.Value)
+		case nl.GENL_GTP_ATTR_O_TEI:
+			p.OTEI = native.Uint32(a.Value)
+		}
+	}
+	return nil
+}
+
+func parsePDP(msgs [][]byte) ([]*PDP, error) {
+	pdps := make([]*PDP, 0, len(msgs))
+	for _, m := range msgs {
+		attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
+		if err != nil {
+			return nil, err
+		}
+		pdp := &PDP{}
+		if err := pdp.parseAttributes(attrs); err != nil {
+			return nil, err
+		}
+		pdps = append(pdps, pdp)
+	}
+	return pdps, nil
+}
+
+func (h *Handle) GTPPDPList() ([]*PDP, error) {
+	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
+	if err != nil {
+		return nil, err
+	}
+	msg := &nl.Genlmsg{
+		Command: nl.GENL_GTP_CMD_GETPDP,
+		Version: nl.GENL_GTP_VERSION,
+	}
+	req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_DUMP)
+	req.AddData(msg)
+	msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
+	if err != nil {
+		return nil, err
+	}
+	return parsePDP(msgs)
+}
+
+func GTPPDPList() ([]*PDP, error) {
+	return pkgHandle.GTPPDPList()
+}
+
+func gtpPDPGet(req *nl.NetlinkRequest) (*PDP, error) {
+	msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
+	if err != nil {
+		return nil, err
+	}
+	pdps, err := parsePDP(msgs)
+	if err != nil {
+		return nil, err
+	}
+	if len(pdps) != 1 {
+		return nil, fmt.Errorf("invalid reqponse for GENL_GTP_CMD_GETPDP")
+	}
+	return pdps[0], nil
+}
+
+func (h *Handle) GTPPDPByTID(link Link, tid int) (*PDP, error) {
+	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
+	if err != nil {
+		return nil, err
+	}
+	msg := &nl.Genlmsg{
+		Command: nl.GENL_GTP_CMD_GETPDP,
+		Version: nl.GENL_GTP_VERSION,
+	}
+	req := h.newNetlinkRequest(int(f.ID), 0)
+	req.AddData(msg)
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(0)))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(uint64(tid))))
+	return gtpPDPGet(req)
+}
+
+func GTPPDPByTID(link Link, tid int) (*PDP, error) {
+	return pkgHandle.GTPPDPByTID(link, tid)
+}
+
+func (h *Handle) GTPPDPByITEI(link Link, itei int) (*PDP, error) {
+	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
+	if err != nil {
+		return nil, err
+	}
+	msg := &nl.Genlmsg{
+		Command: nl.GENL_GTP_CMD_GETPDP,
+		Version: nl.GENL_GTP_VERSION,
+	}
+	req := h.newNetlinkRequest(int(f.ID), 0)
+	req.AddData(msg)
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(1)))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(uint32(itei))))
+	return gtpPDPGet(req)
+}
+
+func GTPPDPByITEI(link Link, itei int) (*PDP, error) {
+	return pkgHandle.GTPPDPByITEI(link, itei)
+}
+
+func (h *Handle) GTPPDPByMSAddress(link Link, addr net.IP) (*PDP, error) {
+	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
+	if err != nil {
+		return nil, err
+	}
+	msg := &nl.Genlmsg{
+		Command: nl.GENL_GTP_CMD_GETPDP,
+		Version: nl.GENL_GTP_VERSION,
+	}
+	req := h.newNetlinkRequest(int(f.ID), 0)
+	req.AddData(msg)
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(0)))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_MS_ADDRESS, []byte(addr.To4())))
+	return gtpPDPGet(req)
+}
+
+func GTPPDPByMSAddress(link Link, addr net.IP) (*PDP, error) {
+	return pkgHandle.GTPPDPByMSAddress(link, addr)
+}
+
+func (h *Handle) GTPPDPAdd(link Link, pdp *PDP) error {
+	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
+	if err != nil {
+		return err
+	}
+	msg := &nl.Genlmsg{
+		Command: nl.GENL_GTP_CMD_NEWPDP,
+		Version: nl.GENL_GTP_VERSION,
+	}
+	req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req.AddData(msg)
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_PEER_ADDRESS, []byte(pdp.PeerAddress.To4())))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_MS_ADDRESS, []byte(pdp.MSAddress.To4())))
+
+	switch pdp.Version {
+	case 0:
+		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(pdp.TID)))
+		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_FLOW, nl.Uint16Attr(pdp.Flow)))
+	case 1:
+		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(pdp.ITEI)))
+		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_O_TEI, nl.Uint32Attr(pdp.OTEI)))
+	default:
+		return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
+	}
+	_, err = req.Execute(syscall.NETLINK_GENERIC, 0)
+	return err
+}
+
+func GTPPDPAdd(link Link, pdp *PDP) error {
+	return pkgHandle.GTPPDPAdd(link, pdp)
+}
+
+func (h *Handle) GTPPDPDel(link Link, pdp *PDP) error {
+	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
+	if err != nil {
+		return err
+	}
+	msg := &nl.Genlmsg{
+		Command: nl.GENL_GTP_CMD_DELPDP,
+		Version: nl.GENL_GTP_VERSION,
+	}
+	req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req.AddData(msg)
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
+	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
+
+	switch pdp.Version {
+	case 0:
+		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(pdp.TID)))
+	case 1:
+		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(pdp.ITEI)))
+	default:
+		return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
+	}
+	_, err = req.Execute(syscall.NETLINK_GENERIC, 0)
+	return err
+}
+
+func GTPPDPDel(link Link, pdp *PDP) error {
+	return pkgHandle.GTPPDPDel(link, pdp)
+}

+ 36 - 1
libnetwork/vendor/github.com/vishvananda/netlink/link.go

@@ -170,6 +170,7 @@ type LinkStatistics64 struct {
 type LinkXdp struct {
 	Fd       int
 	Attached bool
+	Flags    uint32
 }
 
 // Device links cannot be created via netlink. These links
@@ -215,6 +216,8 @@ func (ifb *Ifb) Type() string {
 // Bridge links are simple linux bridges
 type Bridge struct {
 	LinkAttrs
+	MulticastSnooping *bool
+	HelloTime         *uint32
 }
 
 func (bridge *Bridge) Attrs() *LinkAttrs {
@@ -590,7 +593,11 @@ type Bond struct {
 	LacpRate        BondLacpRate
 	AdSelect        BondAdSelect
 	// looking at iproute tool AdInfo can only be retrived. It can't be set.
-	AdInfo *BondAdInfo
+	AdInfo         *BondAdInfo
+	AdActorSysPrio int
+	AdUserPortKey  int
+	AdActorSystem  net.HardwareAddr
+	TlbDynamicLb   int
 }
 
 func NewLinkBond(atr LinkAttrs) *Bond {
@@ -618,6 +625,10 @@ func NewLinkBond(atr LinkAttrs) *Bond {
 		PackersPerSlave: -1,
 		LacpRate:        -1,
 		AdSelect:        -1,
+		AdActorSysPrio:  -1,
+		AdUserPortKey:   -1,
+		AdActorSystem:   nil,
+		TlbDynamicLb:    -1,
 	}
 }
 
@@ -731,8 +742,32 @@ func (vrf *Vrf) Type() string {
 	return "vrf"
 }
 
+type GTP struct {
+	LinkAttrs
+	FD0         int
+	FD1         int
+	Role        int
+	PDPHashsize int
+}
+
+func (gtp *GTP) Attrs() *LinkAttrs {
+	return &gtp.LinkAttrs
+}
+
+func (gtp *GTP) Type() string {
+	return "gtp"
+}
+
 // iproute2 supported devices;
 // vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
 // bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
 // gre | gretap | ip6gre | ip6gretap | vti | nlmon |
 // bond_slave | ipvlan
+
+// LinkNotFoundError wraps the various not found errors when
+// getting/reading links. This is intended for better error
+// handling by dependent code so that "not found error" can
+// be distinguished from other errors
+type LinkNotFoundError struct {
+	error
+}

+ 127 - 9
libnetwork/vendor/github.com/vishvananda/netlink/link_linux.go

@@ -103,7 +103,7 @@ func (h *Handle) SetPromiscOn(link Link) error {
 
 	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
 	msg.Change = syscall.IFF_PROMISC
-	msg.Flags = syscall.IFF_UP
+	msg.Flags = syscall.IFF_PROMISC
 	msg.Index = int32(base.Index)
 	req.AddData(msg)
 
@@ -111,6 +111,16 @@ func (h *Handle) SetPromiscOn(link Link) error {
 	return err
 }
 
+func BridgeSetMcastSnoop(link Link, on bool) error {
+	return pkgHandle.BridgeSetMcastSnoop(link, on)
+}
+
+func (h *Handle) BridgeSetMcastSnoop(link Link, on bool) error {
+	bridge := link.(*Bridge)
+	bridge.MulticastSnooping = &on
+	return h.linkModify(bridge, syscall.NLM_F_ACK)
+}
+
 func SetPromiscOn(link Link) error {
 	return pkgHandle.SetPromiscOn(link)
 }
@@ -122,7 +132,7 @@ func (h *Handle) SetPromiscOff(link Link) error {
 
 	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
 	msg.Change = syscall.IFF_PROMISC
-	msg.Flags = 0 & ^syscall.IFF_UP
+	msg.Flags = 0 & ^syscall.IFF_PROMISC
 	msg.Index = int32(base.Index)
 	req.AddData(msg)
 
@@ -659,6 +669,18 @@ func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) {
 	if bond.AdSelect >= 0 {
 		nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect)))
 	}
+	if bond.AdActorSysPrio >= 0 {
+		nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio)))
+	}
+	if bond.AdUserPortKey >= 0 {
+		nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey)))
+	}
+	if bond.AdActorSystem != nil {
+		nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem))
+	}
+	if bond.TlbDynamicLb >= 0 {
+		nl.NewRtAttrChild(data, nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb)))
+	}
 }
 
 // LinkAdd adds a new link device. The type and features of the device
@@ -672,7 +694,10 @@ func LinkAdd(link Link) error {
 // are taken fromt the parameters in the link object.
 // Equivalent to: `ip link add $link`
 func (h *Handle) LinkAdd(link Link) error {
-	// TODO: set mtu and hardware address
+	return h.linkModify(link, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+}
+
+func (h *Handle) linkModify(link Link, flags int) error {
 	// TODO: support extra data for macvlan
 	base := link.Attrs()
 
@@ -719,7 +744,7 @@ func (h *Handle) LinkAdd(link Link) error {
 		return nil
 	}
 
-	req := h.newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(syscall.RTM_NEWLINK, flags)
 
 	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
 	// TODO: make it shorter
@@ -767,6 +792,11 @@ func (h *Handle) LinkAdd(link Link) error {
 		req.AddData(qlen)
 	}
 
+	if base.HardwareAddr != nil {
+		hwaddr := nl.NewRtAttr(syscall.IFLA_ADDRESS, []byte(base.HardwareAddr))
+		req.AddData(hwaddr)
+	}
+
 	if base.Namespace != nil {
 		var attr *nl.RtAttr
 		switch base.Namespace.(type) {
@@ -830,6 +860,10 @@ func (h *Handle) LinkAdd(link Link) error {
 		addVtiAttrs(vti, linkInfo)
 	} else if vrf, ok := link.(*Vrf); ok {
 		addVrfAttrs(vrf, linkInfo)
+	} else if bridge, ok := link.(*Bridge); ok {
+		addBridgeAttrs(bridge, linkInfo)
+	} else if gtp, ok := link.(*GTP); ok {
+		addGTPAttrs(gtp, linkInfo)
 	}
 
 	req.AddData(linkInfo)
@@ -885,7 +919,7 @@ func (h *Handle) linkByNameDump(name string) (Link, error) {
 			return link, nil
 		}
 	}
-	return nil, fmt.Errorf("Link %s not found", name)
+	return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)}
 }
 
 func (h *Handle) linkByAliasDump(alias string) (Link, error) {
@@ -899,7 +933,7 @@ func (h *Handle) linkByAliasDump(alias string) (Link, error) {
 			return link, nil
 		}
 	}
-	return nil, fmt.Errorf("Link alias %s not found", alias)
+	return nil, LinkNotFoundError{fmt.Errorf("Link alias %s not found", alias)}
 }
 
 // LinkByName finds a link by name and returns a pointer to the object.
@@ -985,7 +1019,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
 	if err != nil {
 		if errno, ok := err.(syscall.Errno); ok {
 			if errno == syscall.ENODEV {
-				return nil, fmt.Errorf("Link not found")
+				return nil, LinkNotFoundError{fmt.Errorf("Link not found")}
 			}
 		}
 		return nil, err
@@ -993,7 +1027,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
 
 	switch {
 	case len(msgs) == 0:
-		return nil, fmt.Errorf("Link not found")
+		return nil, LinkNotFoundError{fmt.Errorf("Link not found")}
 
 	case len(msgs) == 1:
 		return LinkDeserialize(nil, msgs[0])
@@ -1063,6 +1097,8 @@ func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) {
 						link = &Vti{}
 					case "vrf":
 						link = &Vrf{}
+					case "gtp":
+						link = &GTP{}
 					default:
 						link = &GenericLink{LinkType: linkType}
 					}
@@ -1092,6 +1128,10 @@ func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) {
 						parseVtiData(link, data)
 					case "vrf":
 						parseVrfData(link, data)
+					case "bridge":
+						parseBridgeData(link, data)
+					case "gtp":
+						parseGTPData(link, data)
 					}
 				}
 			}
@@ -1288,6 +1328,22 @@ func (h *Handle) LinkSetFlood(link Link, mode bool) error {
 	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD)
 }
 
+func LinkSetBrProxyArp(link Link, mode bool) error {
+	return pkgHandle.LinkSetBrProxyArp(link, mode)
+}
+
+func (h *Handle) LinkSetBrProxyArp(link Link, mode bool) error {
+	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP)
+}
+
+func LinkSetBrProxyArpWiFi(link Link, mode bool) error {
+	return pkgHandle.LinkSetBrProxyArpWiFi(link, mode)
+}
+
+func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error {
+	return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI)
+}
+
 func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
 	base := link.Attrs()
 	h.ensureIndex(base)
@@ -1370,7 +1426,7 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
 }
 
 func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
-	bond := NewLinkBond(NewLinkAttrs())
+	bond := link.(*Bond)
 	for i := range data {
 		switch data[i].Attr.Type {
 		case nl.IFLA_BOND_MODE:
@@ -1419,6 +1475,14 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
 			bond.AdSelect = BondAdSelect(data[i].Value[0])
 		case nl.IFLA_BOND_AD_INFO:
 			// TODO: implement
+		case nl.IFLA_BOND_AD_ACTOR_SYS_PRIO:
+			bond.AdActorSysPrio = int(native.Uint16(data[i].Value[0:2]))
+		case nl.IFLA_BOND_AD_USER_PORT_KEY:
+			bond.AdUserPortKey = int(native.Uint16(data[i].Value[0:2]))
+		case nl.IFLA_BOND_AD_ACTOR_SYSTEM:
+			bond.AdActorSystem = net.HardwareAddr(data[i].Value[0:6])
+		case nl.IFLA_BOND_TLB_DYNAMIC_LB:
+			bond.TlbDynamicLb = int(data[i].Value[0])
 		}
 	}
 }
@@ -1566,6 +1630,8 @@ func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
 	b := make([]byte, 4)
 	native.PutUint32(b, uint32(xdp.Fd))
 	nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b)
+	native.PutUint32(b, xdp.Flags)
+	nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FLAGS, b)
 	req.AddData(attrs)
 }
 
@@ -1581,6 +1647,8 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) {
 			xdp.Fd = int(native.Uint32(attr.Value[0:4]))
 		case nl.IFLA_XDP_ATTACHED:
 			xdp.Attached = attr.Value[0] != 0
+		case nl.IFLA_XDP_FLAGS:
+			xdp.Flags = native.Uint32(attr.Value[0:4])
 		}
 	}
 	return xdp, nil
@@ -1678,3 +1746,53 @@ func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) {
 		}
 	}
 }
+
+func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) {
+	data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+	if bridge.MulticastSnooping != nil {
+		nl.NewRtAttrChild(data, nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping))
+	}
+	if bridge.HelloTime != nil {
+		nl.NewRtAttrChild(data, nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime))
+	}
+}
+
+func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
+	br := bridge.(*Bridge)
+	for _, datum := range data {
+		switch datum.Attr.Type {
+		case nl.IFLA_BR_HELLO_TIME:
+			helloTime := native.Uint32(datum.Value[0:4])
+			br.HelloTime = &helloTime
+		case nl.IFLA_BR_MCAST_SNOOPING:
+			mcastSnooping := datum.Value[0] == 1
+			br.MulticastSnooping = &mcastSnooping
+		}
+	}
+}
+
+func addGTPAttrs(gtp *GTP, linkInfo *nl.RtAttr) {
+	data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+	nl.NewRtAttrChild(data, nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0)))
+	nl.NewRtAttrChild(data, nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1)))
+	nl.NewRtAttrChild(data, nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072))
+	if gtp.Role != nl.GTP_ROLE_GGSN {
+		nl.NewRtAttrChild(data, nl.IFLA_GTP_ROLE, nl.Uint32Attr(uint32(gtp.Role)))
+	}
+}
+
+func parseGTPData(link Link, data []syscall.NetlinkRouteAttr) {
+	gtp := link.(*GTP)
+	for _, datum := range data {
+		switch datum.Attr.Type {
+		case nl.IFLA_GTP_FD0:
+			gtp.FD0 = int(native.Uint32(datum.Value))
+		case nl.IFLA_GTP_FD1:
+			gtp.FD1 = int(native.Uint32(datum.Value))
+		case nl.IFLA_GTP_PDP_HASHSIZE:
+			gtp.PDPHashsize = int(native.Uint32(datum.Value))
+		case nl.IFLA_GTP_ROLE:
+			gtp.Role = int(native.Uint32(datum.Value))
+		}
+	}
+}

+ 29 - 0
libnetwork/vendor/github.com/vishvananda/netlink/nl/addr_linux.go

@@ -45,3 +45,32 @@ func (msg *IfAddrmsg) Serialize() []byte {
 func (msg *IfAddrmsg) Len() int {
 	return syscall.SizeofIfAddrmsg
 }
+
+// struct ifa_cacheinfo {
+// 	__u32	ifa_prefered;
+// 	__u32	ifa_valid;
+// 	__u32	cstamp; /* created timestamp, hundredths of seconds */
+// 	__u32	tstamp; /* updated timestamp, hundredths of seconds */
+// };
+
+const IFA_CACHEINFO = 6
+const SizeofIfaCacheInfo = 0x10
+
+type IfaCacheInfo struct {
+	IfaPrefered uint32
+	IfaValid    uint32
+	Cstamp      uint32
+	Tstamp      uint32
+}
+
+func (msg *IfaCacheInfo) Len() int {
+	return SizeofIfaCacheInfo
+}
+
+func DeserializeIfaCacheInfo(b []byte) *IfaCacheInfo {
+	return (*IfaCacheInfo)(unsafe.Pointer(&b[0:SizeofIfaCacheInfo][0]))
+}
+
+func (msg *IfaCacheInfo) Serialize() []byte {
+	return (*(*[SizeofIfaCacheInfo]byte)(unsafe.Pointer(msg)))[:]
+}

+ 89 - 0
libnetwork/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go

@@ -0,0 +1,89 @@
+package nl
+
+import (
+	"unsafe"
+)
+
+const SizeofGenlmsg = 4
+
+const (
+	GENL_ID_CTRL      = 0x10
+	GENL_CTRL_VERSION = 2
+	GENL_CTRL_NAME    = "nlctrl"
+)
+
+const (
+	GENL_CTRL_CMD_GETFAMILY = 3
+)
+
+const (
+	GENL_CTRL_ATTR_UNSPEC = iota
+	GENL_CTRL_ATTR_FAMILY_ID
+	GENL_CTRL_ATTR_FAMILY_NAME
+	GENL_CTRL_ATTR_VERSION
+	GENL_CTRL_ATTR_HDRSIZE
+	GENL_CTRL_ATTR_MAXATTR
+	GENL_CTRL_ATTR_OPS
+	GENL_CTRL_ATTR_MCAST_GROUPS
+)
+
+const (
+	GENL_CTRL_ATTR_OP_UNSPEC = iota
+	GENL_CTRL_ATTR_OP_ID
+	GENL_CTRL_ATTR_OP_FLAGS
+)
+
+const (
+	GENL_ADMIN_PERM = 1 << iota
+	GENL_CMD_CAP_DO
+	GENL_CMD_CAP_DUMP
+	GENL_CMD_CAP_HASPOL
+)
+
+const (
+	GENL_CTRL_ATTR_MCAST_GRP_UNSPEC = iota
+	GENL_CTRL_ATTR_MCAST_GRP_NAME
+	GENL_CTRL_ATTR_MCAST_GRP_ID
+)
+
+const (
+	GENL_GTP_VERSION = 0
+	GENL_GTP_NAME    = "gtp"
+)
+
+const (
+	GENL_GTP_CMD_NEWPDP = iota
+	GENL_GTP_CMD_DELPDP
+	GENL_GTP_CMD_GETPDP
+)
+
+const (
+	GENL_GTP_ATTR_UNSPEC = iota
+	GENL_GTP_ATTR_LINK
+	GENL_GTP_ATTR_VERSION
+	GENL_GTP_ATTR_TID
+	GENL_GTP_ATTR_PEER_ADDRESS
+	GENL_GTP_ATTR_MS_ADDRESS
+	GENL_GTP_ATTR_FLOW
+	GENL_GTP_ATTR_NET_NS_FD
+	GENL_GTP_ATTR_I_TEI
+	GENL_GTP_ATTR_O_TEI
+	GENL_GTP_ATTR_PAD
+)
+
+type Genlmsg struct {
+	Command uint8
+	Version uint8
+}
+
+func (msg *Genlmsg) Len() int {
+	return SizeofGenlmsg
+}
+
+func DeserializeGenlmsg(b []byte) *Genlmsg {
+	return (*Genlmsg)(unsafe.Pointer(&b[0:SizeofGenlmsg][0]))
+}
+
+func (msg *Genlmsg) Serialize() []byte {
+	return (*(*[SizeofGenlmsg]byte)(unsafe.Pointer(msg)))[:]
+}

+ 72 - 2
libnetwork/vendor/github.com/vishvananda/netlink/nl/link_linux.go

@@ -102,7 +102,10 @@ const (
 	IFLA_BRPORT_FAST_LEAVE
 	IFLA_BRPORT_LEARNING
 	IFLA_BRPORT_UNICAST_FLOOD
-	IFLA_BRPORT_MAX = IFLA_BRPORT_UNICAST_FLOOD
+	IFLA_BRPORT_PROXYARP
+	IFLA_BRPORT_LEARNING_SYNC
+	IFLA_BRPORT_PROXYARP_WIFI
+	IFLA_BRPORT_MAX = IFLA_BRPORT_PROXYARP_WIFI
 )
 
 const (
@@ -151,6 +154,10 @@ const (
 	IFLA_BOND_AD_LACP_RATE
 	IFLA_BOND_AD_SELECT
 	IFLA_BOND_AD_INFO
+	IFLA_BOND_AD_ACTOR_SYS_PRIO
+	IFLA_BOND_AD_USER_PORT_KEY
+	IFLA_BOND_AD_ACTOR_SYSTEM
+	IFLA_BOND_TLB_DYNAMIC_LB
 )
 
 const (
@@ -416,7 +423,8 @@ const (
 	IFLA_XDP_UNSPEC   = iota
 	IFLA_XDP_FD       /* fd of xdp program to attach, or -1 to remove */
 	IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */
-	IFLA_XDP_MAX      = IFLA_XDP_ATTACHED
+	IFLA_XDP_FLAGS    /* xdp prog related flags */
+	IFLA_XDP_MAX      = IFLA_XDP_FLAGS
 )
 
 const (
@@ -452,3 +460,65 @@ const (
 	IFLA_VRF_UNSPEC = iota
 	IFLA_VRF_TABLE
 )
+
+const (
+	IFLA_BR_UNSPEC = iota
+	IFLA_BR_FORWARD_DELAY
+	IFLA_BR_HELLO_TIME
+	IFLA_BR_MAX_AGE
+	IFLA_BR_AGEING_TIME
+	IFLA_BR_STP_STATE
+	IFLA_BR_PRIORITY
+	IFLA_BR_VLAN_FILTERING
+	IFLA_BR_VLAN_PROTOCOL
+	IFLA_BR_GROUP_FWD_MASK
+	IFLA_BR_ROOT_ID
+	IFLA_BR_BRIDGE_ID
+	IFLA_BR_ROOT_PORT
+	IFLA_BR_ROOT_PATH_COST
+	IFLA_BR_TOPOLOGY_CHANGE
+	IFLA_BR_TOPOLOGY_CHANGE_DETECTED
+	IFLA_BR_HELLO_TIMER
+	IFLA_BR_TCN_TIMER
+	IFLA_BR_TOPOLOGY_CHANGE_TIMER
+	IFLA_BR_GC_TIMER
+	IFLA_BR_GROUP_ADDR
+	IFLA_BR_FDB_FLUSH
+	IFLA_BR_MCAST_ROUTER
+	IFLA_BR_MCAST_SNOOPING
+	IFLA_BR_MCAST_QUERY_USE_IFADDR
+	IFLA_BR_MCAST_QUERIER
+	IFLA_BR_MCAST_HASH_ELASTICITY
+	IFLA_BR_MCAST_HASH_MAX
+	IFLA_BR_MCAST_LAST_MEMBER_CNT
+	IFLA_BR_MCAST_STARTUP_QUERY_CNT
+	IFLA_BR_MCAST_LAST_MEMBER_INTVL
+	IFLA_BR_MCAST_MEMBERSHIP_INTVL
+	IFLA_BR_MCAST_QUERIER_INTVL
+	IFLA_BR_MCAST_QUERY_INTVL
+	IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
+	IFLA_BR_MCAST_STARTUP_QUERY_INTVL
+	IFLA_BR_NF_CALL_IPTABLES
+	IFLA_BR_NF_CALL_IP6TABLES
+	IFLA_BR_NF_CALL_ARPTABLES
+	IFLA_BR_VLAN_DEFAULT_PVID
+	IFLA_BR_PAD
+	IFLA_BR_VLAN_STATS_ENABLED
+	IFLA_BR_MCAST_STATS_ENABLED
+	IFLA_BR_MCAST_IGMP_VERSION
+	IFLA_BR_MCAST_MLD_VERSION
+	IFLA_BR_MAX = IFLA_BR_MCAST_MLD_VERSION
+)
+
+const (
+	IFLA_GTP_UNSPEC = iota
+	IFLA_GTP_FD0
+	IFLA_GTP_FD1
+	IFLA_GTP_PDP_HASHSIZE
+	IFLA_GTP_ROLE
+)
+
+const (
+	GTP_ROLE_GGSN = iota
+	GTP_ROLE_SGSN
+)

+ 14 - 11
libnetwork/vendor/github.com/vishvananda/netlink/nl/nl_linux.go

@@ -459,7 +459,7 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
 }
 
 type NetlinkSocket struct {
-	fd  int
+	fd  int32
 	lsa syscall.SockaddrNetlink
 	sync.Mutex
 }
@@ -470,7 +470,7 @@ func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
 		return nil, err
 	}
 	s := &NetlinkSocket{
-		fd: fd,
+		fd: int32(fd),
 	}
 	s.lsa.Family = syscall.AF_NETLINK
 	if err := syscall.Bind(fd, &s.lsa); err != nil {
@@ -556,7 +556,7 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
 		return nil, err
 	}
 	s := &NetlinkSocket{
-		fd: fd,
+		fd: int32(fd),
 	}
 	s.lsa.Family = syscall.AF_NETLINK
 
@@ -585,30 +585,32 @@ func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*Ne
 }
 
 func (s *NetlinkSocket) Close() {
-	syscall.Close(s.fd)
-	s.fd = -1
+	fd := int(atomic.SwapInt32(&s.fd, -1))
+	syscall.Close(fd)
 }
 
 func (s *NetlinkSocket) GetFd() int {
-	return s.fd
+	return int(atomic.LoadInt32(&s.fd))
 }
 
 func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
-	if s.fd < 0 {
+	fd := int(atomic.LoadInt32(&s.fd))
+	if fd < 0 {
 		return fmt.Errorf("Send called on a closed socket")
 	}
-	if err := syscall.Sendto(s.fd, request.Serialize(), 0, &s.lsa); err != nil {
+	if err := syscall.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil {
 		return err
 	}
 	return nil
 }
 
 func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
-	if s.fd < 0 {
+	fd := int(atomic.LoadInt32(&s.fd))
+	if fd < 0 {
 		return nil, fmt.Errorf("Receive called on a closed socket")
 	}
 	rb := make([]byte, syscall.Getpagesize())
-	nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
+	nr, _, err := syscall.Recvfrom(fd, rb, 0)
 	if err != nil {
 		return nil, err
 	}
@@ -620,7 +622,8 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
 }
 
 func (s *NetlinkSocket) GetPid() (uint32, error) {
-	lsa, err := syscall.Getsockname(s.fd)
+	fd := int(atomic.LoadInt32(&s.fd))
+	lsa, err := syscall.Getsockname(fd)
 	if err != nil {
 		return 0, err
 	}

+ 14 - 6
libnetwork/vendor/github.com/vishvananda/netlink/protinfo.go

@@ -6,12 +6,14 @@ import (
 
 // Protinfo represents bridge flags from netlink.
 type Protinfo struct {
-	Hairpin   bool
-	Guard     bool
-	FastLeave bool
-	RootBlock bool
-	Learning  bool
-	Flood     bool
+	Hairpin      bool
+	Guard        bool
+	FastLeave    bool
+	RootBlock    bool
+	Learning     bool
+	Flood        bool
+	ProxyArp     bool
+	ProxyArpWiFi bool
 }
 
 // String returns a list of enabled flags
@@ -35,6 +37,12 @@ func (prot *Protinfo) String() string {
 	if prot.Flood {
 		boolStrings = append(boolStrings, "Flood")
 	}
+	if prot.ProxyArp {
+		boolStrings = append(boolStrings, "ProxyArp")
+	}
+	if prot.ProxyArpWiFi {
+		boolStrings = append(boolStrings, "ProxyArpWiFi")
+	}
 	return strings.Join(boolStrings, " ")
 }
 

+ 4 - 0
libnetwork/vendor/github.com/vishvananda/netlink/protinfo_linux.go

@@ -64,6 +64,10 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo {
 			pi.Learning = byteToBool(info.Value[0])
 		case nl.IFLA_BRPORT_UNICAST_FLOOD:
 			pi.Flood = byteToBool(info.Value[0])
+		case nl.IFLA_BRPORT_PROXYARP:
+			pi.ProxyArp = byteToBool(info.Value[0])
+		case nl.IFLA_BRPORT_PROXYARP_WIFI:
+			pi.ProxyArpWiFi = byteToBool(info.Value[0])
 		}
 	}
 	return &pi

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

@@ -401,7 +401,7 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
 		}
 		if filter != nil {
 			switch {
-			case filterMask&RT_FILTER_TABLE != 0 && route.Table != filter.Table:
+			case filterMask&RT_FILTER_TABLE != 0 && filter.Table != syscall.RT_TABLE_UNSPEC && route.Table != filter.Table:
 				continue
 			case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
 				continue