From 4e28683688429fdf8413cc610d59fb1841986300 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 10 Jun 2017 15:47:01 +0200 Subject: [PATCH] link: Add support for IFLA_*_COLLECT_METADATA - Implemented for VXLAN and GRE via a flag `FlowBased` - Added unit tests to verify ability Signed-off-by: Thomas Graf --- link.go | 2 ++ link_linux.go | 19 +++++++++++++++++++ link_test.go | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/link.go b/link.go index 547e92e..9ec4ce2 100644 --- a/link.go +++ b/link.go @@ -339,6 +339,7 @@ type Vxlan struct { UDPCSum bool NoAge bool GBP bool + FlowBased bool Age int Limit int Port int @@ -684,6 +685,7 @@ type Gretap struct { EncapType uint16 EncapFlags uint16 Link uint32 + FlowBased bool } func (gretap *Gretap) Attrs() *LinkAttrs { diff --git a/link_linux.go b/link_linux.go index 1c1bc52..f143144 100644 --- a/link_linux.go +++ b/link_linux.go @@ -528,7 +528,13 @@ type vxlanPortRange struct { func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) { data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + + if vxlan.FlowBased { + vxlan.VxlanId = 0 + } + nl.NewRtAttrChild(data, nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId))) + if vxlan.VtepDevIndex != 0 { nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex))) } @@ -569,6 +575,9 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) { if vxlan.GBP { nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, []byte{}) } + if vxlan.FlowBased { + nl.NewRtAttrChild(data, nl.IFLA_VXLAN_FLOWBASED, boolAttr(vxlan.FlowBased)) + } if vxlan.NoAge { nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0)) } else if vxlan.Age > 0 { @@ -1407,6 +1416,8 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) { vxlan.UDPCSum = int8(datum.Value[0]) != 0 case nl.IFLA_VXLAN_GBP: vxlan.GBP = true + case nl.IFLA_VXLAN_FLOWBASED: + vxlan.FlowBased = int8(datum.Value[0]) != 0 case nl.IFLA_VXLAN_AGEING: vxlan.Age = int(native.Uint32(datum.Value[0:4])) vxlan.NoAge = vxlan.Age == 0 @@ -1547,6 +1558,12 @@ func linkFlags(rawFlags uint32) net.Flags { func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) { data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + if gretap.FlowBased { + // In flow based mode, no other attributes need to be configured + nl.NewRtAttrChild(data, nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased)) + return + } + ip := gretap.Local.To4() if ip != nil { nl.NewRtAttrChild(data, nl.IFLA_GRE_LOCAL, []byte(ip)) @@ -1613,6 +1630,8 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) { gre.EncapType = native.Uint16(datum.Value[0:2]) case nl.IFLA_GRE_ENCAP_FLAGS: gre.EncapFlags = native.Uint16(datum.Value[0:2]) + case nl.IFLA_GRE_COLLECT_METADATA: + gre.FlowBased = int8(datum.Value[0]) != 0 } } } diff --git a/link_test.go b/link_test.go index 34aa579..e71c9cf 100644 --- a/link_test.go +++ b/link_test.go @@ -220,6 +220,9 @@ func compareVxlan(t *testing.T, expected, actual *Vxlan) { if actual.GBP != expected.GBP { t.Fatal("Vxlan.GBP doesn't match") } + if actual.FlowBased != expected.FlowBased { + t.Fatal("Vxlan.FlowBased doesn't match") + } if expected.NoAge { if !actual.NoAge { t.Fatal("Vxlan.NoAge doesn't match") @@ -277,6 +280,19 @@ func TestLinkAddDelGretap(t *testing.T) { Remote: net.IPv4(127, 0, 0, 1)}) } +func TestLinkAddDelGretapFlowBased(t *testing.T) { + if os.Getenv("TRAVIS_BUILD_DIR") != "" { + t.Skipf("Kernel in travis is too old for this test") + } + + tearDown := setUpNetlinkTest(t) + defer tearDown() + + testLinkAddDel(t, &Gretap{ + LinkAttrs: LinkAttrs{Name: "foo"}, + FlowBased: true}) +} + func TestLinkAddDelVlan(t *testing.T) { tearDown := setUpNetlinkTest(t) defer tearDown() @@ -693,6 +709,25 @@ func TestLinkAddDelVxlanGbp(t *testing.T) { } } +func TestLinkAddDelVxlanFlowBased(t *testing.T) { + if os.Getenv("TRAVIS_BUILD_DIR") != "" { + t.Skipf("Kernel in travis is too old for this test") + } + + tearDown := setUpNetlinkTest(t) + defer tearDown() + + vxlan := Vxlan{ + LinkAttrs: LinkAttrs{ + Name: "foo", + }, + Learning: false, + FlowBased: true, + } + + testLinkAddDel(t, &vxlan) +} + func TestLinkAddDelIPVlanL2(t *testing.T) { if os.Getenv("TRAVIS_BUILD_DIR") != "" { t.Skipf("Kernel in travis is too old for this test")