From ae3e7dba57271b4e976c4f91637861ee477135e2 Mon Sep 17 00:00:00 2001 From: Eugene Yakubovich Date: Fri, 20 Feb 2015 09:19:47 -0800 Subject: [PATCH] added support for MACVLAN mode --- link.go | 12 ++++++++++++ link_linux.go | 39 +++++++++++++++++++++++++++++++++++++++ link_test.go | 15 ++++++++++++++- nl/link_linux.go | 15 +++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/link.go b/link.go index a424639..0cb6fc3 100644 --- a/link.go +++ b/link.go @@ -82,9 +82,21 @@ func (vlan *Vlan) Type() string { return "vlan" } +type MacvlanMode uint16 + +const ( + MACVLAN_MODE_DEFAULT MacvlanMode = iota + MACVLAN_MODE_PRIVATE + MACVLAN_MODE_VEPA + MACVLAN_MODE_BRIDGE + MACVLAN_MODE_PASSTHRU + MACVLAN_MODE_SOURCE +) + // Macvlan links have ParentIndex set in their Attrs() type Macvlan struct { LinkAttrs + Mode MacvlanMode } func (macvlan *Macvlan) Attrs() *LinkAttrs { diff --git a/link_linux.go b/link_linux.go index 5897af6..8b0da0d 100644 --- a/link_linux.go +++ b/link_linux.go @@ -13,6 +13,15 @@ import ( var native = nl.NativeEndian() var lookupByDump = false +var macvlanModes = [...]uint32{ + 0, + nl.MACVLAN_MODE_PRIVATE, + nl.MACVLAN_MODE_VEPA, + nl.MACVLAN_MODE_BRIDGE, + nl.MACVLAN_MODE_PASSTHRU, + nl.MACVLAN_MODE_SOURCE, +} + func ensureIndex(link *LinkAttrs) { if link != nil && link.Index == 0 { newlink, _ := LinkByName(link.Name) @@ -350,6 +359,11 @@ func LinkAdd(link Link) error { } 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))) + } else if macv, ok := link.(*Macvlan); ok { + if macv.Mode != MACVLAN_MODE_DEFAULT { + data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macv.Mode])) + } } req.AddData(linkInfo) @@ -497,6 +511,8 @@ func linkDeserialize(m []byte) (Link, error) { link = &Vxlan{} case "ipvlan": link = &IPVlan{} + case "macvlan": + link = &Macvlan{} default: link = &Generic{LinkType: linkType} } @@ -512,6 +528,8 @@ func linkDeserialize(m []byte) (Link, error) { parseVxlanData(link, data) case "ipvlan": parseIPVlanData(link, data) + case "macvlan": + parseMacvlanData(link, data) } } } @@ -688,6 +706,27 @@ func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) { } } +func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { + macv := link.(*Macvlan) + for _, datum := range data { + if datum.Attr.Type == nl.IFLA_MACVLAN_MODE { + switch native.Uint32(datum.Value[0:4]) { + case nl.MACVLAN_MODE_PRIVATE: + macv.Mode = MACVLAN_MODE_PRIVATE + case nl.MACVLAN_MODE_VEPA: + macv.Mode = MACVLAN_MODE_VEPA + case nl.MACVLAN_MODE_BRIDGE: + macv.Mode = MACVLAN_MODE_BRIDGE + case nl.MACVLAN_MODE_PASSTHRU: + macv.Mode = MACVLAN_MODE_PASSTHRU + case nl.MACVLAN_MODE_SOURCE: + macv.Mode = MACVLAN_MODE_SOURCE + } + return + } + } +} + // copied from pkg/net_linux.go func linkFlags(rawFlags uint32) net.Flags { var f net.Flags diff --git a/link_test.go b/link_test.go index 05b8e95..41349ca 100644 --- a/link_test.go +++ b/link_test.go @@ -91,6 +91,16 @@ func testLinkAddDel(t *testing.T, link Link) { } } + if macv, ok := link.(*Macvlan); ok { + other, ok := result.(*Macvlan) + if !ok { + t.Fatal("Result of create is not a macvlan") + } + if macv.Mode != other.Mode { + t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, macv.Mode) + } + } + if err = LinkDel(link); err != nil { t.Fatal(err) } @@ -199,7 +209,10 @@ func TestLinkAddDelMacvlan(t *testing.T) { t.Fatal(err) } - testLinkAddDel(t, &Macvlan{LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}}) + testLinkAddDel(t, &Macvlan{ + LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}, + Mode: MACVLAN_MODE_PRIVATE, + }) if err := LinkDel(parent); err != nil { t.Fatal(err) diff --git a/nl/link_linux.go b/nl/link_linux.go index ab0dede..64ef5fd 100644 --- a/nl/link_linux.go +++ b/nl/link_linux.go @@ -79,3 +79,18 @@ const ( // not defined in syscall IFLA_NET_NS_FD = 28 ) + +const ( + IFLA_MACVLAN_UNSPEC = iota + IFLA_MACVLAN_MODE + IFLA_MACVLAN_FLAGS + IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS +) + +const ( + MACVLAN_MODE_PRIVATE = 1 + MACVLAN_MODE_VEPA = 2 + MACVLAN_MODE_BRIDGE = 4 + MACVLAN_MODE_PASSTHRU = 8 + MACVLAN_MODE_SOURCE = 16 +)