diff --git a/vendor.conf b/vendor.conf index 3d9f47c944..cdbc0decb1 100644 --- a/vendor.conf +++ b/vendor.conf @@ -26,7 +26,7 @@ github.com/imdario/mergo 0.2.1 golang.org/x/sync de49d9dcd27d4f764488181bea099dfe6179bcf0 #get libnetwork packages -github.com/docker/libnetwork 2e99f06621c23a5f4038968f1af1e28c84e4104e +github.com/docker/libnetwork eb57059e91bc54c9da23c5a633b75b3faf910a68 github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec @@ -38,7 +38,7 @@ github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870 github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 -github.com/vishvananda/netlink 1e86b2bee5b6a7d377e4c02bb7f98209d6a7297c +github.com/vishvananda/netlink bd6d5de5ccef2d66b0a26177928d0d8895d7f969 github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060 github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374 github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d diff --git a/vendor/github.com/docker/libnetwork/agent.go b/vendor/github.com/docker/libnetwork/agent.go index d67d446fe8..485713171e 100644 --- a/vendor/github.com/docker/libnetwork/agent.go +++ b/vendor/github.com/docker/libnetwork/agent.go @@ -722,15 +722,13 @@ func (n *network) cancelDriverWatches() { } } -func (c *controller) handleTableEvents(ch chan events.Event, fn func(events.Event)) { +func (c *controller) handleTableEvents(ch *events.Channel, fn func(events.Event)) { for { select { - case ev, ok := <-ch: - if !ok { - return - } - + case ev := <-ch.C: fn(ev) + case <-ch.Done(): + return } } } diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_linux.go b/vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_linux.go new file mode 100644 index 0000000000..85840cf8c4 --- /dev/null +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_linux.go @@ -0,0 +1,30 @@ +package overlay + +import ( + "io/ioutil" + "path" + "strings" + + "github.com/Sirupsen/logrus" +) + +var sysctlConf = map[string]string{ + "net.ipv4.neigh.default.gc_thresh1": "8192", + "net.ipv4.neigh.default.gc_thresh2": "49152", + "net.ipv4.neigh.default.gc_thresh3": "65536", +} + +// writeSystemProperty writes the value to a path under /proc/sys as determined from the key. +// For e.g. net.ipv4.ip_forward translated to /proc/sys/net/ipv4/ip_forward. +func writeSystemProperty(key, value string) error { + keyPath := strings.Replace(key, ".", "/", -1) + return ioutil.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0644) +} + +func applyOStweaks() { + for k, v := range sysctlConf { + if err := writeSystemProperty(k, v); err != nil { + logrus.Errorf("error setting the kernel parameter %s = %s, err: %s", k, v, err) + } + } +} diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_unsupported.go b/vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_unsupported.go new file mode 100644 index 0000000000..a5e8d91083 --- /dev/null +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_unsupported.go @@ -0,0 +1,5 @@ +// +build !linux + +package overlay + +func applyOStweaks() {} diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go b/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go index 64e5744403..6be88d9179 100644 --- a/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go @@ -3,8 +3,10 @@ package overlay import ( "encoding/json" "fmt" + "io/ioutil" "net" "os" + "os/exec" "path/filepath" "strconv" "strings" @@ -12,6 +14,7 @@ import ( "syscall" "github.com/Sirupsen/logrus" + "github.com/docker/docker/pkg/reexec" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/netlabel" @@ -55,6 +58,7 @@ type network struct { dbIndex uint64 dbExists bool sbox osl.Sandbox + nlSocket *nl.NetlinkSocket endpoints endpointTable driver *driver joinCnt int @@ -67,6 +71,54 @@ type network struct { sync.Mutex } +func init() { + reexec.Register("set-default-vlan", setDefaultVlan) +} + +func setDefaultVlan() { + if len(os.Args) < 3 { + logrus.Error("insufficient number of arguments") + os.Exit(1) + } + nsPath := os.Args[1] + ns, err := netns.GetFromPath(nsPath) + if err != nil { + logrus.Errorf("overlay namespace get failed, %v", err) + os.Exit(1) + } + if err = netns.Set(ns); err != nil { + logrus.Errorf("setting into overlay namespace failed, %v", err) + os.Exit(1) + } + + // make sure the sysfs mount doesn't propagate back + if err = syscall.Unshare(syscall.CLONE_NEWNS); err != nil { + logrus.Errorf("unshare failed, %v", err) + os.Exit(1) + } + + flag := syscall.MS_PRIVATE | syscall.MS_REC + if err = syscall.Mount("", "/", "", uintptr(flag), ""); err != nil { + logrus.Errorf("root mount failed, %v", err) + os.Exit(1) + } + + if err = syscall.Mount("sysfs", "/sys", "sysfs", 0, ""); err != nil { + logrus.Errorf("mounting sysfs failed, %v", err) + os.Exit(1) + } + + brName := os.Args[2] + path := filepath.Join("/sys/class/net", brName, "bridge/default_pvid") + data := []byte{'0', '\n'} + + if err = ioutil.WriteFile(path, data, 0644); err != nil { + logrus.Errorf("endbling default vlan on bridge %s failed %v", brName, err) + os.Exit(1) + } + os.Exit(0) +} + func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) { return nil, types.NotImplementedErrorf("not implemented") } @@ -294,6 +346,12 @@ func (n *network) destroySandbox() { } } + // Close the netlink socket, this will also release the watchMiss goroutine that is using it + if n.nlSocket != nil { + n.nlSocket.Close() + n.nlSocket = nil + } + n.sbox.Destroy() n.sbox = nil } @@ -505,6 +563,25 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error return fmt.Errorf("vxlan interface creation failed for subnet %q: %v", s.subnetIP.String(), err) } + if !hostMode { + var name string + for _, i := range sbox.Info().Interfaces() { + if i.Bridge() { + name = i.DstName() + } + } + cmd := &exec.Cmd{ + Path: reexec.Self(), + Args: []string{"set-default-vlan", sbox.Key(), name}, + Stdout: os.Stdout, + Stderr: os.Stderr, + } + if err := cmd.Run(); err != nil { + // not a fatal error + logrus.Errorf("reexec to set bridge default vlan failed %v", err) + } + } + if hostMode { if err := addFilters(n.id[:12], brName); err != nil { return err @@ -615,6 +692,7 @@ func (n *network) initSandbox(restore bool) error { sbox.InvokeFunc(func() { nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) }) + n.setNetlinkSocket(nlSock) if err == nil { go n.watchMiss(nlSock) @@ -630,6 +708,13 @@ func (n *network) watchMiss(nlSock *nl.NetlinkSocket) { for { msgs, err := nlSock.Receive() if err != nil { + n.Lock() + nlFd := nlSock.GetFd() + n.Unlock() + if nlFd == -1 { + // The netlink socket got closed, simply exit to not leak this goroutine + return + } logrus.Errorf("Failed to receive from netlink: %v ", err) continue } @@ -746,6 +831,12 @@ func (n *network) setSandbox(sbox osl.Sandbox) { n.Unlock() } +func (n *network) setNetlinkSocket(nlSk *nl.NetlinkSocket) { + n.Lock() + n.nlSocket = nlSk + n.Unlock() +} + func (n *network) vxlanID(s *subnet) uint32 { n.Lock() defer n.Unlock() diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go b/vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go index 8a932cf370..8d19b2e1d4 100644 --- a/vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go @@ -46,7 +46,7 @@ type driver struct { store datastore.DataStore localStore datastore.DataStore vxlanIdm *idm.Idm - once sync.Once + initOS sync.Once joinOnce sync.Once localJoinOnce sync.Once keys []*key @@ -180,6 +180,10 @@ func Fini(drv driverapi.Driver) { } func (d *driver) configure() error { + + // Apply OS specific kernel configs if needed + d.initOS.Do(applyOStweaks) + if d.store == nil { return nil } diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go b/vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go index 6551e7bcad..21cd1fbe3d 100644 --- a/vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go @@ -222,7 +222,7 @@ func (d *driver) peerDbUpdateSandbox(nid string) { for pKeyStr, pEntry := range pMap.mp { var pKey peerKey if _, err := fmt.Sscan(pKeyStr, &pKey); err != nil { - fmt.Printf("peer key scan failed: %v", err) + logrus.Errorf("peer key scan failed: %v", err) } if pEntry.isLocal { @@ -237,7 +237,7 @@ func (d *driver) peerDbUpdateSandbox(nid string) { if err := d.peerAdd(nid, entry.eid, pKey.peerIP, entry.peerIPMask, pKey.peerMac, entry.vtep, false, false, false); err != nil { - fmt.Printf("peerdbupdate in sandbox failed for ip %s and mac %s: %v", + logrus.Errorf("peerdbupdate in sandbox failed for ip %s and mac %s: %v", pKey.peerIP, pKey.peerMac, err) } } diff --git a/vendor/github.com/docker/libnetwork/networkdb/watch.go b/vendor/github.com/docker/libnetwork/networkdb/watch.go index 088b666f01..2ef30422a8 100644 --- a/vendor/github.com/docker/libnetwork/networkdb/watch.go +++ b/vendor/github.com/docker/libnetwork/networkdb/watch.go @@ -43,7 +43,7 @@ type DeleteEvent event // filter is an empty string it acts as a wildcard for that // field. Watch returns a channel of events, where the events will be // sent. -func (nDB *NetworkDB) Watch(tname, nid, key string) (chan events.Event, func()) { +func (nDB *NetworkDB) Watch(tname, nid, key string) (*events.Channel, func()) { var matcher events.Matcher if tname != "" || nid != "" || key != "" { @@ -82,7 +82,7 @@ func (nDB *NetworkDB) Watch(tname, nid, key string) (chan events.Event, func()) } nDB.broadcaster.Add(sink) - return ch.C, func() { + return ch, func() { nDB.broadcaster.Remove(sink) ch.Close() sink.Close() diff --git a/vendor/github.com/docker/libnetwork/osl/neigh_linux.go b/vendor/github.com/docker/libnetwork/osl/neigh_linux.go index 81b6cd9c1c..161ffa7beb 100644 --- a/vendor/github.com/docker/libnetwork/osl/neigh_linux.go +++ b/vendor/github.com/docker/libnetwork/osl/neigh_linux.go @@ -78,6 +78,23 @@ func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, if err := nlh.NeighDel(nlnh); err != nil { logrus.Warnf("Deleting neighbor IP %s, mac %s failed, %v", dstIP, dstMac, err) } + + // Delete the dynamic entry in the bridge + if nlnh.Family > 0 { + nlnh := &netlink.Neigh{ + IP: dstIP, + Family: nh.family, + } + + nlnh.HardwareAddr = dstMac + nlnh.Flags = netlink.NTF_MASTER + if nh.linkDst != "" { + nlnh.LinkIndex = iface.Attrs().Index + } + if err := nlh.NeighDel(nlnh); err != nil { + logrus.Warnf("Deleting bridge mac mac %s failed, %v", dstMac, err) + } + } } n.Lock() diff --git a/vendor/github.com/docker/libnetwork/vendor.conf b/vendor/github.com/docker/libnetwork/vendor.conf index 0f1db6d18f..203e1cebf5 100644 --- a/vendor/github.com/docker/libnetwork/vendor.conf +++ b/vendor/github.com/docker/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 diff --git a/vendor/github.com/vishvananda/netlink/addr.go b/vendor/github.com/vishvananda/netlink/addr.go index fe3e3d3668..f08c956969 100644 --- a/vendor/github.com/vishvananda/netlink/addr.go +++ b/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 diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go index 220f0f22f1..f33242a7c2 100644 --- a/vendor/github.com/vishvananda/netlink/addr_linux.go +++ b/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} } } }() diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go index eb1802c444..dc0f90af88 100644 --- a/vendor/github.com/vishvananda/netlink/filter_linux.go +++ b/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 { diff --git a/vendor/github.com/vishvananda/netlink/genetlink_linux.go b/vendor/github.com/vishvananda/netlink/genetlink_linux.go new file mode 100644 index 0000000000..a388a87001 --- /dev/null +++ b/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) +} diff --git a/vendor/github.com/vishvananda/netlink/genetlink_unspecified.go b/vendor/github.com/vishvananda/netlink/genetlink_unspecified.go new file mode 100644 index 0000000000..0192b991e3 --- /dev/null +++ b/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 +} diff --git a/vendor/github.com/vishvananda/netlink/gtp_linux.go b/vendor/github.com/vishvananda/netlink/gtp_linux.go new file mode 100644 index 0000000000..7331303ecb --- /dev/null +++ b/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) +} diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go index 924211cd48..547e92ec12 100644 --- a/vendor/github.com/vishvananda/netlink/link.go +++ b/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 >p.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 +} diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go index 0c04d3adde..1c1bc52c4d 100644 --- a/vendor/github.com/vishvananda/netlink/link_linux.go +++ b/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 = >P{} 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)) + } + } +} diff --git a/vendor/github.com/vishvananda/netlink/nl/addr_linux.go b/vendor/github.com/vishvananda/netlink/nl/addr_linux.go index 17088fa0c0..fe362e9fa7 100644 --- a/vendor/github.com/vishvananda/netlink/nl/addr_linux.go +++ b/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)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go new file mode 100644 index 0000000000..81b46f2c79 --- /dev/null +++ b/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)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go index 6d9af56998..f7b9575919 100644 --- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go +++ b/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 +) diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go index 5820e8422b..1329acd864 100644 --- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go +++ b/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 } diff --git a/vendor/github.com/vishvananda/netlink/protinfo.go b/vendor/github.com/vishvananda/netlink/protinfo.go index ead3f2f15e..0087c4438b 100644 --- a/vendor/github.com/vishvananda/netlink/protinfo.go +++ b/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, " ") } diff --git a/vendor/github.com/vishvananda/netlink/protinfo_linux.go b/vendor/github.com/vishvananda/netlink/protinfo_linux.go index ea72695343..10dd0d5335 100644 --- a/vendor/github.com/vishvananda/netlink/protinfo_linux.go +++ b/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 diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go index 9e0f1f932d..cd739e7146 100644 --- a/vendor/github.com/vishvananda/netlink/route_linux.go +++ b/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