Pārlūkot izejas kodu

Fallback to dumping ifaces when name lookup fails

Older kernels don't support looking up interface by name (via netlink).
In these cases, fallback to dumping all interfaces. This patch just
pulls in latest netlink library.

Fixes #66
Eugene Yakubovich 10 gadi atpakaļ
vecāks
revīzija
a2dddf030d

+ 1 - 1
Godeps/Godeps.json

@@ -21,7 +21,7 @@
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/vishvananda/netlink",
 			"ImportPath": "github.com/vishvananda/netlink",
-			"Rev": "dd2d5f17ae986599e165402a77c7e85fea606bec"
+			"Rev": "2187ba67a244c1c32f53bf88876e766bbbbcd5e6"
 		}
 		}
 	]
 	]
 }
 }

+ 4 - 2
Godeps/_workspace/src/github.com/vishvananda/netlink/README.md

@@ -1,5 +1,7 @@
 # netlink - netlink library for go #
 # netlink - netlink library for go #
 
 
+[![Build Status](https://travis-ci.org/vishvananda/netlink.png?branch=master)](https://travis-ci.org/vishvananda/netlink)
+
 The netlink package provides a simple netlink library for go. Netlink
 The netlink package provides a simple netlink library for go. Netlink
 is the interface a user-space program in linux uses to communicate with
 is the interface a user-space program in linux uses to communicate with
 the kernel. It can be used to add and remove interfaces, set ip addresses
 the kernel. It can be used to add and remove interfaces, set ip addresses
@@ -41,8 +43,8 @@ import (
 )
 )
 
 
 func main() {
 func main() {
-    mybridge := &netlink.Link{Name: "mybridge", Type: "bridge"}
-    netlink, _ := netlink.LinkAdd(mybridge)
+    mybridge := &netlink.Bridge{netlink.LinkAttrs{Name: "foo"}}
+    _ := netlink.LinkAdd(mybridge)
     eth1, _ := netlink.LinkByName("eth1")
     eth1, _ := netlink.LinkByName("eth1")
     netlink.LinkSetMaster(eth1, mybridge)
     netlink.LinkSetMaster(eth1, mybridge)
 }
 }

+ 30 - 3
Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go

@@ -11,6 +11,7 @@ import (
 )
 )
 
 
 var native = nl.NativeEndian()
 var native = nl.NativeEndian()
+var lookupByDump = false
 
 
 func ensureIndex(link *LinkAttrs) {
 func ensureIndex(link *LinkAttrs) {
 	if link != nil && link.Index == 0 {
 	if link != nil && link.Index == 0 {
@@ -177,7 +178,7 @@ type vxlanPortRange struct {
 	Lo, Hi uint16
 	Lo, Hi uint16
 }
 }
 
 
-func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
+func addVxlanAttrs(vxlan* Vxlan, linkInfo *nl.RtAttr) {
 	data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
 	data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
 	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId)))
 	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId)))
 	if vxlan.VtepDevIndex != 0 {
 	if vxlan.VtepDevIndex != 0 {
@@ -226,7 +227,7 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
 		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_PORT, nl.Uint16Attr(uint16(vxlan.Port)))
 		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_PORT, nl.Uint16Attr(uint16(vxlan.Port)))
 	}
 	}
 	if vxlan.PortLow > 0 || vxlan.PortHigh > 0 {
 	if vxlan.PortLow > 0 || vxlan.PortHigh > 0 {
-		pr := vxlanPortRange{uint16(vxlan.PortLow), uint16(vxlan.PortHigh)}
+		pr := vxlanPortRange{ uint16(vxlan.PortLow), uint16(vxlan.PortHigh) }
 
 
 		buf := new(bytes.Buffer)
 		buf := new(bytes.Buffer)
 		binary.Write(buf, binary.BigEndian, &pr)
 		binary.Write(buf, binary.BigEndian, &pr)
@@ -314,8 +315,26 @@ func LinkDel(link Link) error {
 	return err
 	return err
 }
 }
 
 
+func linkByNameDump(name string) (Link, error) {
+	links, err := LinkList()
+	if err != nil {
+		return nil, err
+	}
+
+	for _, link := range links {
+		if link.Attrs().Name == name {
+			return link, nil
+		}
+	}
+	return nil, fmt.Errorf("Link %s not found", name)
+}
+
 // LinkByName finds a link by name and returns a pointer to the object.
 // LinkByName finds a link by name and returns a pointer to the object.
 func LinkByName(name string) (Link, error) {
 func LinkByName(name string) (Link, error) {
+	if lookupByDump {
+		return linkByNameDump(name)
+	}
+
 	req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_ACK)
 	req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_ACK)
 
 
 	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
 	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
@@ -324,7 +343,15 @@ func LinkByName(name string) (Link, error) {
 	nameData := nl.NewRtAttr(syscall.IFLA_IFNAME, nl.ZeroTerminated(name))
 	nameData := nl.NewRtAttr(syscall.IFLA_IFNAME, nl.ZeroTerminated(name))
 	req.AddData(nameData)
 	req.AddData(nameData)
 
 
-	return execGetLink(req)
+	link, err := execGetLink(req)
+	if err == syscall.EINVAL {
+		// older kernels don't support looking up via IFLA_IFNAME
+		// so fall back to dumping all links
+		lookupByDump = true
+		return linkByNameDump(name)
+	}
+
+	return link, err
 }
 }
 
 
 // LinkByIndex finds a link by index and returns a pointer to the object.
 // LinkByIndex finds a link by index and returns a pointer to the object.

+ 4 - 1
Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go

@@ -349,7 +349,7 @@ func TestLinkAddDelVxlan(t *testing.T) {
 		LinkAttrs: LinkAttrs{
 		LinkAttrs: LinkAttrs{
 			Name: "bar",
 			Name: "bar",
 		},
 		},
-		VxlanId: 10,
+		VxlanId:      10,
 		VtepDevIndex: parent.Index,
 		VtepDevIndex: parent.Index,
 		Learning:     true,
 		Learning:     true,
 		L2miss:       true,
 		L2miss:       true,
@@ -363,6 +363,9 @@ func TestLinkAddDelVxlan(t *testing.T) {
 }
 }
 
 
 func TestLinkByIndex(t *testing.T) {
 func TestLinkByIndex(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
 	dummy := &Dummy{LinkAttrs{Name: "dummy"}}
 	dummy := &Dummy{LinkAttrs{Name: "dummy"}}
 	if err := LinkAdd(dummy); err != nil {
 	if err := LinkAdd(dummy); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)

+ 9 - 6
Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go

@@ -20,7 +20,7 @@ func parseMAC(s string) net.HardwareAddr {
 
 
 func dumpContains(dump []Neigh, e arpEntry) bool {
 func dumpContains(dump []Neigh, e arpEntry) bool {
 	for _, n := range dump {
 	for _, n := range dump {
-		if n.IP.Equal(e.ip) && (n.State & NUD_INCOMPLETE) == 0 {
+		if n.IP.Equal(e.ip) && (n.State&NUD_INCOMPLETE) == 0 {
 			return true
 			return true
 		}
 		}
 	}
 	}
@@ -28,6 +28,9 @@ func dumpContains(dump []Neigh, e arpEntry) bool {
 }
 }
 
 
 func TestNeighAddDel(t *testing.T) {
 func TestNeighAddDel(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
 	dummy := Dummy{LinkAttrs{Name: "neigh0"}}
 	dummy := Dummy{LinkAttrs{Name: "neigh0"}}
 	if err := LinkAdd(&dummy); err != nil {
 	if err := LinkAdd(&dummy); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
@@ -36,11 +39,11 @@ func TestNeighAddDel(t *testing.T) {
 	ensureIndex(dummy.Attrs())
 	ensureIndex(dummy.Attrs())
 
 
 	arpTable := []arpEntry{
 	arpTable := []arpEntry{
-		{ net.ParseIP("10.99.0.1"), parseMAC("aa:bb:cc:dd:00:01") },
-		{ net.ParseIP("10.99.0.2"), parseMAC("aa:bb:cc:dd:00:02") },
-		{ net.ParseIP("10.99.0.3"), parseMAC("aa:bb:cc:dd:00:03") },
-		{ net.ParseIP("10.99.0.4"), parseMAC("aa:bb:cc:dd:00:04") },
-		{ net.ParseIP("10.99.0.5"), parseMAC("aa:bb:cc:dd:00:05") },
+		{net.ParseIP("10.99.0.1"), parseMAC("aa:bb:cc:dd:00:01")},
+		{net.ParseIP("10.99.0.2"), parseMAC("aa:bb:cc:dd:00:02")},
+		{net.ParseIP("10.99.0.3"), parseMAC("aa:bb:cc:dd:00:03")},
+		{net.ParseIP("10.99.0.4"), parseMAC("aa:bb:cc:dd:00:04")},
+		{net.ParseIP("10.99.0.5"), parseMAC("aa:bb:cc:dd:00:05")},
 	}
 	}
 
 
 	// Add the arpTable
 	// Add the arpTable

+ 0 - 1
Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux.go

@@ -45,4 +45,3 @@ func (msg *IfAddrmsg) Serialize() []byte {
 func (msg *IfAddrmsg) Len() int {
 func (msg *IfAddrmsg) Len() int {
 	return syscall.SizeofIfAddrmsg
 	return syscall.SizeofIfAddrmsg
 }
 }
-

+ 2 - 2
Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go

@@ -4,8 +4,8 @@ package nl
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/binary"
 	"encoding/binary"
-	"net"
 	"fmt"
 	"fmt"
+	"net"
 	"sync/atomic"
 	"sync/atomic"
 	"syscall"
 	"syscall"
 	"unsafe"
 	"unsafe"
@@ -304,7 +304,7 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
 	s.lsa.Family = syscall.AF_NETLINK
 	s.lsa.Family = syscall.AF_NETLINK
 
 
 	for _, g := range groups {
 	for _, g := range groups {
-		s.lsa.Groups |= (1 << (g-1))
+		s.lsa.Groups |= (1 << (g - 1))
 	}
 	}
 
 
 	if err := syscall.Bind(fd, &s.lsa); err != nil {
 	if err := syscall.Bind(fd, &s.lsa); err != nil {

+ 0 - 1
Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux.go

@@ -31,4 +31,3 @@ func DeserializeRtMsg(b []byte) *RtMsg {
 func (msg *RtMsg) Serialize() []byte {
 func (msg *RtMsg) Serialize() []byte {
 	return (*(*[syscall.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:]
 	return (*(*[syscall.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:]
 }
 }
-

+ 0 - 1
Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go

@@ -117,4 +117,3 @@ func DeserializeXfrmUserTmpl(b []byte) *XfrmUserTmpl {
 func (msg *XfrmUserTmpl) Serialize() []byte {
 func (msg *XfrmUserTmpl) Serialize() []byte {
 	return (*(*[SizeofXfrmUserTmpl]byte)(unsafe.Pointer(msg)))[:]
 	return (*(*[SizeofXfrmUserTmpl]byte)(unsafe.Pointer(msg)))[:]
 }
 }
-

+ 0 - 1
Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux.go

@@ -219,4 +219,3 @@ func DeserializeXfrmEncapTmpl(b []byte) *XfrmEncapTmpl {
 func (msg *XfrmEncapTmpl) Serialize() []byte {
 func (msg *XfrmEncapTmpl) Serialize() []byte {
 	return (*(*[SizeofXfrmEncapTmpl]byte)(unsafe.Pointer(msg)))[:]
 	return (*(*[SizeofXfrmEncapTmpl]byte)(unsafe.Pointer(msg)))[:]
 }
 }
-