IPVlan support

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
This commit is contained in:
Alexander Morozov
2015-02-10 15:00:36 -08:00
parent 31e1715aea
commit d710fe886a
5 changed files with 119 additions and 6 deletions

30
link.go
View File

@@ -1,8 +1,6 @@
package netlink
import (
"net"
)
import "net"
// Link represents a link device from netlink. Shared link attributes
// like name may be retrieved using the Attrs() method. Unique data
@@ -149,7 +147,29 @@ func (vxlan *Vxlan) Type() string {
return "vxlan"
}
type IPVlanMode uint16
const (
IPVLAN_MODE_L2 IPVlanMode = iota
IPVLAN_MODE_L3 = iota
IPVLAN_MODE_MAX = iota
)
type IPVlan struct {
LinkAttrs
Mode IPVlanMode
}
func (ipvlan *IPVlan) Attrs() *LinkAttrs {
return &ipvlan.LinkAttrs
}
func (ipvlan *IPVlan) Type() string {
return "ipvlan"
}
// iproute2 supported devices;
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
// can | bridge | bond | ipoib | ip6tnl | ipip | sit |
// vxlan | gre | gretap | ip6gre | ip6gretap | vti
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
// gre | gretap | ip6gre | ip6gretap | vti | nlmon |
// bond_slave | ipvlan

View File

@@ -300,6 +300,8 @@ func LinkAdd(link Link) error {
native.PutUint32(b, uint32(base.ParentIndex))
data := nl.NewRtAttr(syscall.IFLA_LINK, b)
req.AddData(data)
} else if link.Type() == "ipvlan" {
return fmt.Errorf("Can't create ipvlan link without ParentIndex")
}
nameData := nl.NewRtAttr(syscall.IFLA_IFNAME, nl.ZeroTerminated(base.Name))
@@ -331,6 +333,9 @@ func LinkAdd(link Link) error {
}
} else if vxlan, ok := link.(*Vxlan); ok {
addVxlanAttrs(vxlan, linkInfo)
} else if ipv, ok := link.(*IPVlan); ok {
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
nl.NewRtAttrChild(data, nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(ipv.Mode)))
}
req.AddData(linkInfo)
@@ -476,6 +481,8 @@ func linkDeserialize(m []byte) (Link, error) {
link = &Veth{}
case "vxlan":
link = &Vxlan{}
case "ipvlan":
link = &IPVlan{}
default:
link = &Generic{LinkType: linkType}
}
@@ -489,6 +496,8 @@ func linkDeserialize(m []byte) (Link, error) {
parseVlanData(link, data)
case "vxlan":
parseVxlanData(link, data)
case "ipvlan":
parseIPVlanData(link, data)
}
}
}
@@ -609,6 +618,16 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
ipv := link.(*IPVlan)
for _, datum := range data {
if datum.Attr.Type == nl.IFLA_IPVLAN_MODE {
ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
return
}
}
}
// copied from pkg/net_linux.go
func linkFlags(rawFlags uint32) net.Flags {
var f net.Flags

View File

@@ -81,6 +81,16 @@ func testLinkAddDel(t *testing.T, link Link) {
compareVxlan(t, vxlan, other)
}
if ipv, ok := link.(*IPVlan); ok {
other, ok := result.(*IPVlan)
if !ok {
t.Fatal("Result of create is not a vxlan")
}
if ipv.Mode != other.Mode {
t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, ipv.Mode)
}
}
if err = LinkDel(link); err != nil {
t.Fatal(err)
}
@@ -378,6 +388,63 @@ func TestLinkAddDelVxlan(t *testing.T) {
}
}
func TestLinkAddDelIPVlanL2(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
parent := &Dummy{LinkAttrs{Name: "foo"}}
if err := LinkAdd(parent); err != nil {
t.Fatal(err)
}
ipv := IPVlan{
LinkAttrs: LinkAttrs{
Name: "bar",
ParentIndex: parent.Index,
},
Mode: IPVLAN_MODE_L2,
}
testLinkAddDel(t, &ipv)
}
func TestLinkAddDelIPVlanL3(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
parent := &Dummy{LinkAttrs{Name: "foo"}}
if err := LinkAdd(parent); err != nil {
t.Fatal(err)
}
ipv := IPVlan{
LinkAttrs: LinkAttrs{
Name: "bar",
ParentIndex: parent.Index,
},
Mode: IPVLAN_MODE_L3,
}
testLinkAddDel(t, &ipv)
}
func TestLinkAddDelIPVlanNoParent(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
ipv := IPVlan{
LinkAttrs: LinkAttrs{
Name: "bar",
},
Mode: IPVLAN_MODE_L3,
}
err := LinkAdd(&ipv)
if err == nil {
t.Fatal("Add should fail if ipvlan creating without ParentIndex")
}
if err.Error() != "Can't create ipvlan link without ParentIndex" {
t.Fatalf("Error should be about missing ParentIndex, got %q", err)
}
}
func TestLinkByIndex(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()

View File

@@ -1,11 +1,12 @@
package netlink
import (
"github.com/vishvananda/netns"
"log"
"os"
"runtime"
"testing"
"github.com/vishvananda/netns"
)
type tearDownNetlinkTest func()

View File

@@ -69,6 +69,12 @@ const (
IFLA_BRPORT_MAX = IFLA_BRPORT_UNICAST_FLOOD
)
const (
IFLA_IPVLAN_UNSPEC = iota
IFLA_IPVLAN_MODE = iota
IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE
)
const (
// not defined in syscall
IFLA_NET_NS_FD = 28