From 51acb6af7f844c6e47b0ca3e9ecbb5bf0886657a Mon Sep 17 00:00:00 2001 From: "jozef.slezak" Date: Mon, 9 Oct 2017 14:37:14 +0200 Subject: [PATCH 1/2] ODPM-633 wrap global sequencers of L2 drivers to struct (for auto tests) --- controller/cnpdriver/sfcctlr_l2_driver.go | 53 +++++++++++++--------- tests/go/itest/agent_test_helpers.go | 11 ++++- tests/go/itest/basic_tcs.go | 3 +- tests/go/itest/linuxtestdata/basic_data.go | 17 +++++++ tests/go/itest/run_all_test.go | 20 +++++--- tests/go/itest/sfctestdata/basic_data.go | 2 +- tests/go/itest/vpptestdata/basic_data.go | 47 ++++++++++++++++++- 7 files changed, 119 insertions(+), 34 deletions(-) create mode 100644 tests/go/itest/linuxtestdata/basic_data.go diff --git a/controller/cnpdriver/sfcctlr_l2_driver.go b/controller/cnpdriver/sfcctlr_l2_driver.go index ec1e4750..a3ac5d0a 100644 --- a/controller/cnpdriver/sfcctlr_l2_driver.go +++ b/controller/cnpdriver/sfcctlr_l2_driver.go @@ -46,11 +46,7 @@ import ( ) var ( - gVLanID uint32 = 4999 - gMemIfID uint32 - gMacInstanceID uint32 - gIPInstanceID uint32 - log = logroot.StandardLogger() + log = logroot.StandardLogger() ) type sfcCtlrL2CNPDriver struct { @@ -62,6 +58,17 @@ type sfcCtlrL2CNPDriver struct { reconcileBefore reconcileCacheType reconcileAfter reconcileCacheType reconcileInProgress bool + seq sequencer +} + +// sequencer groups all sequences used by L2 driver. +// (instead of using global variables that caused +// problems while running automated tests) +type sequencer struct { + VLanID uint32 + MemIfID uint32 + MacInstanceID uint32 + IPInstanceID uint32 } type heToEEStateType struct { @@ -110,6 +117,8 @@ func NewSfcCtlrL2CNPDriver(name string, dbFactory func(string) keyval.ProtoBroke cnpd.initL2CNPCache() cnpd.initReconcileCache() + cnpd.seq.VLanID = 4999 + return cnpd } @@ -421,8 +430,8 @@ func (cnpd *sfcCtlrL2CNPDriver) WireHostEntityToExternalEntity(he *controller.Ho // create the vxlan i'f before the BD ifName := "IF_VXLAN_H2E_" + he.Name + "_" + ee.Name - gVLanID++ // track these at some point - vlanIf, err := cnpd.vxLanCreate(he.Name, ifName, gVLanID, he.LoopbackIpv4, ee.HostVxlan.SourceIpv4) + cnpd.seq.VLanID++ // track these at some point + vlanIf, err := cnpd.vxLanCreate(he.Name, ifName, cnpd.seq.VLanID, he.LoopbackIpv4, ee.HostVxlan.SourceIpv4) if err != nil { log.Error("WireHostEntityToExternalEntity: error creating vxlan: '%s'", ifName) return err @@ -496,8 +505,8 @@ func (cnpd *sfcCtlrL2CNPDriver) WireInternalsForHostEntity(he *controller.HostEn var loopbackMacAddress string if he.LoopbackMacAddr == "" { // if not supplied, generate one - gMacInstanceID++ - loopbackMacAddress = formatMacAddress(gMacInstanceID) + cnpd.seq.MacInstanceID++ + loopbackMacAddress = formatMacAddress(cnpd.seq.MacInstanceID) } else { loopbackMacAddress = he.LoopbackMacAddr @@ -942,7 +951,7 @@ func (cnpd *sfcCtlrL2CNPDriver) createMemIfPair(sfc *controller.SfcEntity, hostN // for now just incr the memIfIndex for each pair of memIfs (vnf, vswitch) // vswitch is master of the (vswitch/vnf) pair - gMemIfID++ + cnpd.seq.MemIfID++ var macAddress string var ipv4Address string @@ -952,8 +961,8 @@ func (cnpd *sfcCtlrL2CNPDriver) createMemIfPair(sfc *controller.SfcEntity, hostN if vnfChainElement.Ipv4Addr == "" { if generateAddresses { if sfc.SfcIpv4Prefix == "" { - gIPInstanceID++ - ipv4Address = formatIpv4Address(gIPInstanceID) + "/24" + cnpd.seq.IPInstanceID++ + ipv4Address = formatIpv4Address(cnpd.seq.IPInstanceID) + "/24" } } } else { @@ -962,8 +971,8 @@ func (cnpd *sfcCtlrL2CNPDriver) createMemIfPair(sfc *controller.SfcEntity, hostN if vnfChainElement.MacAddr == "" { if generateAddresses { - gMacInstanceID++ - macAddress = formatMacAddress(gMacInstanceID) + cnpd.seq.MacInstanceID++ + macAddress = formatMacAddress(cnpd.seq.MacInstanceID) } } else { macAddress = vnfChainElement.MacAddr @@ -971,7 +980,7 @@ func (cnpd *sfcCtlrL2CNPDriver) createMemIfPair(sfc *controller.SfcEntity, hostN // create a memif in the vnf container memIfName := vnfChainElement.PortLabel - if _, err := cnpd.memIfCreate(vnfChainElement.Container, memIfName, gMemIfID, + if _, err := cnpd.memIfCreate(vnfChainElement.Container, memIfName, cnpd.seq.MemIfID, false, ipv4Address, macAddress); err != nil { log.Error("createMemIfPair: error creating memIf for container: '%s'", memIfName) return "", err @@ -979,7 +988,7 @@ func (cnpd *sfcCtlrL2CNPDriver) createMemIfPair(sfc *controller.SfcEntity, hostN // now create a memif for the vpp switch memIfName = "IF_MEMIF_VSWITCH_" + vnfChainElement.Container + "_" + vnfChainElement.PortLabel - memIf, err := cnpd.memIfCreate(vnfChainElement.EtcdVppSwitchKey, memIfName, gMemIfID, + memIf, err := cnpd.memIfCreate(vnfChainElement.EtcdVppSwitchKey, memIfName, cnpd.seq.MemIfID, true, "", "") if err != nil { log.Error("createMemIfPair: error creating memIf for vpp switch: '%s'", memIf.Name) @@ -1030,16 +1039,16 @@ func (cnpd *sfcCtlrL2CNPDriver) createAFPacketVEthPair(sfc *controller.SfcEntity // TODO: figure out how ipam, and macam should be done, for now just start at 1 and increment :-( if vnfChainElement.Ipv4Addr == "" { if sfc.SfcIpv4Prefix == "" { - gIPInstanceID++ - ipv4Address = formatIpv4Address(gIPInstanceID) + "/24" + cnpd.seq.IPInstanceID++ + ipv4Address = formatIpv4Address(cnpd.seq.IPInstanceID) + "/24" } } else { ipv4Address = vnfChainElement.Ipv4Addr + "/24" } } if vnfChainElement.MacAddr == "" { - gMacInstanceID++ - macAddress = formatMacAddress(gMacInstanceID) + cnpd.seq.MacInstanceID++ + macAddress = formatMacAddress(cnpd.seq.MacInstanceID) } else { macAddress = vnfChainElement.MacAddr @@ -1070,7 +1079,7 @@ func (cnpd *sfcCtlrL2CNPDriver) createAFPacketVEthPair(sfc *controller.SfcEntity afPktIf1, err := cnpd.afPacketCreate(vnfChainElement.Container, vnfChainElement.PortLabel, veth1Name, "", "") if err != nil { - log.Error("createAFPacketVEthPair: error creating memIf for vpp switch: '%s'", afPktIf1.Name) + log.Error("createAFPacketVEthPair: error creating afpacket for vpp switch: '%s'", afPktIf1.Name) return "", err } } @@ -1079,7 +1088,7 @@ func (cnpd *sfcCtlrL2CNPDriver) createAFPacketVEthPair(sfc *controller.SfcEntity afPktName := "IF_AFPIF_VSWITCH_" + vnfChainElement.Container + "_" + vnfChainElement.PortLabel afPktIf2, err := cnpd.afPacketCreate(vnfChainElement.EtcdVppSwitchKey, afPktName, veth2Name, "", "") if err != nil { - log.Error("createAFPacketVEthPair: error creating memIf for vpp switch: '%s'", afPktIf2.Name) + log.Error("createAFPacketVEthPair: error creating afpacket for vpp switch: '%s'", afPktIf2.Name) return "", err } diff --git a/tests/go/itest/agent_test_helpers.go b/tests/go/itest/agent_test_helpers.go index 247c1cfe..2823cc3e 100644 --- a/tests/go/itest/agent_test_helpers.go +++ b/tests/go/itest/agent_test_helpers.go @@ -163,9 +163,16 @@ func (t *Then) VppAgentCfgContains(micorserviceLabel string, interfaceBDEtc ...p found, _, err := db.GetValue(key, ifaceExist) gomega.Expect(found).Should(gomega.BeTrue(), "interface not found "+key) gomega.Expect(err).Should(gomega.BeNil(), "error reading "+key) - //TODO enable after gettring rid of globals - // gomega.Expect(ifaceExist).Should(gomega.BeEquivalentTo(ifaceExpected), "error reading "+key) + gomega.Expect(ifaceExist).Should(gomega.BeEquivalentTo(ifaceExpected), "error reading "+key) case *l2.BridgeDomains_BridgeDomain: + bdExpected := expected.(*l2.BridgeDomains_BridgeDomain) + bdActual := &l2.BridgeDomains_BridgeDomain{} + + key := l2.BridgeDomainKey(bdExpected.Name) + found, _, err := db.GetValue(key, bdActual) + gomega.Expect(found).Should(gomega.BeTrue(), "bd not found "+key) + gomega.Expect(err).Should(gomega.BeNil(), "error reading "+key) + gomega.Expect(bdActual).Should(gomega.BeEquivalentTo(bdExpected), "error reading "+key) } } } diff --git a/tests/go/itest/basic_tcs.go b/tests/go/itest/basic_tcs.go index d328963c..99a5b8f2 100644 --- a/tests/go/itest/basic_tcs.go +++ b/tests/go/itest/basic_tcs.go @@ -34,6 +34,7 @@ func (t *basicTCSuite) TC01ResyncEmptyVpp1Agent(sfcCfg *sfccore.YamlConfig, vppA t.Then.VppAgentCfgContains("HOST-1", vppAgentCfg...) t.Then.HTTPGetEntities(sfcCfg) } + // TC02HTTPPostasserts that vpp agent writes properly vpp-agent configuration // This TC assumes that vpp-agent configuration was empty before the test. // Then SFC Controller starts and after that SFC Controller is configured via REST HTTP posts. @@ -46,4 +47,4 @@ func (t *basicTCSuite) TC02HTTPPost(sfcCfg *sfccore.YamlConfig, vppAgentCfg ... t.Given.ConfigSFCviaREST(sfcCfg) t.Then.VppAgentCfgContains("HOST-1", vppAgentCfg...) t.Then.HTTPGetEntities(sfcCfg) -} \ No newline at end of file +} diff --git a/tests/go/itest/linuxtestdata/basic_data.go b/tests/go/itest/linuxtestdata/basic_data.go new file mode 100644 index 00000000..a477888f --- /dev/null +++ b/tests/go/itest/linuxtestdata/basic_data.go @@ -0,0 +1,17 @@ +package linuxtestdata + +import ( + "github.com/ligato/vpp-agent/plugins/linuxplugin/model/interfaces" +) + +var Agent1Veth01 = interfaces.LinuxInterfaces_Interface{ + Name: "agent1_afpacket", + Enabled: true, + //PhysAddress: "02:00:00:00:00:02", + Mtu: 1500, + Type: interfaces.LinuxInterfaces_VETH, + //IpAddresses: []string{"10.0.0.10/24"}, + Veth: &interfaces.LinuxInterfaces_Interface_Veth{ + PeerIfName: "_agent1_", + }, +} diff --git a/tests/go/itest/run_all_test.go b/tests/go/itest/run_all_test.go index fa6b7546..3a7e4acc 100644 --- a/tests/go/itest/run_all_test.go +++ b/tests/go/itest/run_all_test.go @@ -7,6 +7,8 @@ import ( "github.com/ligato/sfc-controller/tests/go/itest/sfctestdata" //"github.com/ligato/sfc-controller/tests/go/itest/vpptestdata" "github.com/ligato/sfc-controller/tests/go/itest/vpptestdata" + "github.com/ligato/sfc-controller/tests/go/itest/linuxtestdata" + "github.com/golang/protobuf/proto" ) // Test runs all TC methods of multiple test suites in sequence @@ -15,16 +17,20 @@ func Test(t *testing.T) { go func() { t.Run("basic_tcs", func(t *testing.T) { - suite := &basicTCSuite{T: t} + VPP1MEMIF2_Loopback_VETH := []proto.Message{&vpptestdata.VPP1MEMIF1, + &vpptestdata.VPP1MEMIF2, + &vpptestdata.Agent1Afpacket01, + &vpptestdata.Agent1Loopback, + &linuxtestdata.Agent1Veth01, + &vpptestdata.BD_INTERNAL_EW_HOST1} + t.Run("TC01ResyncEmptyVpp1Agent", func(t *testing.T) { - suite.TC01ResyncEmptyVpp1Agent(&sfctestdata.VPP1MEMIF2, - &vpptestdata.VPP1MEMIF1, - ) + suite := &basicTCSuite{T: t} + suite.TC01ResyncEmptyVpp1Agent(&sfctestdata.VPP1MEMIF2_Loopback_VETH, VPP1MEMIF2_Loopback_VETH...) }) t.Run("TC02HTTPPost", func(t *testing.T) { - suite.TC02HTTPPost(&sfctestdata.VPP1MEMIF2, - &vpptestdata.VPP1MEMIF1, - ) + suite := &basicTCSuite{T: t} + suite.TC02HTTPPost(&sfctestdata.VPP1MEMIF2_Loopback_VETH, VPP1MEMIF2_Loopback_VETH...) }) }) doneChan <- struct{}{} diff --git a/tests/go/itest/sfctestdata/basic_data.go b/tests/go/itest/sfctestdata/basic_data.go index 574472b5..05c163cb 100644 --- a/tests/go/itest/sfctestdata/basic_data.go +++ b/tests/go/itest/sfctestdata/basic_data.go @@ -5,7 +5,7 @@ import ( "github.com/ligato/sfc-controller/controller/model/controller" ) -var VPP1MEMIF2 = sfccore.YamlConfig{ +var VPP1MEMIF2_Loopback_VETH = sfccore.YamlConfig{ HEs: []controller.HostEntity{{ Name: "HOST-1", //mgmnt_ip_address: "192.168.0.1", diff --git a/tests/go/itest/vpptestdata/basic_data.go b/tests/go/itest/vpptestdata/basic_data.go index de29e3a7..0feba2fd 100644 --- a/tests/go/itest/vpptestdata/basic_data.go +++ b/tests/go/itest/vpptestdata/basic_data.go @@ -2,6 +2,7 @@ package vpptestdata import ( "github.com/ligato/vpp-agent/plugins/defaultplugins/ifplugin/model/interfaces" + "github.com/ligato/vpp-agent/plugins/defaultplugins/l2plugin/model/l2" ) var VPP1MEMIF1 = interfaces.Interfaces_Interface{ @@ -29,4 +30,48 @@ var VPP1MEMIF2 = interfaces.Interfaces_Interface{ Id: 2, SocketFilename: "/tmp/memif.sock", Master: true, - },} + }} + +var BD_INTERNAL_EW_HOST1 = l2.BridgeDomains_BridgeDomain{ + Name: "BD_INTERNAL_EW_HOST-1", + Flood: true, + UnknownUnicastFlood: true, + Forward: true, + Learn: true, + ArpTermination: false, + MacAge: 0, + Interfaces: []*l2.BridgeDomains_BridgeDomain_Interfaces{ + {Name: "IF_MEMIF_VSWITCH__vpp1_memif1"}, + {Name: "IF_MEMIF_VSWITCH__vpp1_memif2"}, + {Name: "IF_AFPIF_VSWITCH__agent1_afpacket1"}}, + ArpTerminationTable: nil, +} + +//time="2017-10-06 11:35:03.62305" level=info msg="ReconcileEnd: add BD key to etcd: +// /vnf-agent/HOST-1/vpp/config/v1/bd/BD_INTERNAL_EW_HOST-1 +// + +//time= "2017-10-06 11:55:55.48623" level = info msg = "{[name:"agent1_afpacket" enabled:true phys_address:"02:00:00:00:00:02" mtu:1500 namespace: veth: ]}" loc = "cnpdriver/sfcctlr_l2_driver.go(1394)" logger = defaultLogger tag = 00000000 +//TODO time = "2017-10-06 11:55:55.49223" level = info msg = "ReconcileEnd: add i/f key to etcd: /vnf-agent/HOST-1/vpp/config/v1/interface/GigabitEthernet13/0/0{GigabitEthernet13/0/0 ETHERNET_CSMACD true 1500 [8.42.0.2] }" loc = "cnpdriver/sfcctlr_l2_driver.go(235)" logger = defaultLogger tag = 00000000 + +var Agent1Afpacket01 = interfaces.Interfaces_Interface{ + Name: "IF_AFPIF_VSWITCH__agent1_afpacket1", + Enabled: true, + //PhysAddress: "02:00:00:00:00:02", + Mtu: 1500, + Type: interfaces.InterfaceType_AF_PACKET_INTERFACE, + //IpAddresses: []string{"10.0.0.10/24"}, + Afpacket: &interfaces.Interfaces_Interface_Afpacket{ + HostIfName: "_agent1_", + }, + //namespace: veth: +} + +var Agent1Loopback = interfaces.Interfaces_Interface{ + Name: "IF_LOOPBACK_H_HOST-1", + Enabled: true, + PhysAddress: "02:00:00:AA:BB:00", + Mtu: 1500, + Type: interfaces.InterfaceType_SOFTWARE_LOOPBACK, + IpAddresses: []string{"6.0.0.100"}, +} From 07db6b1cb22fe22cf47748615576417b11a51e37 Mon Sep 17 00:00:00 2001 From: "jozef.slezak" Date: Mon, 9 Oct 2017 14:46:06 +0200 Subject: [PATCH 2/2] godoc improvement of L2 driver constructors --- controller/cnpdriver/sfcctlr_l2_driver.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/controller/cnpdriver/sfcctlr_l2_driver.go b/controller/cnpdriver/sfcctlr_l2_driver.go index a3ac5d0a..b748de9f 100644 --- a/controller/cnpdriver/sfcctlr_l2_driver.go +++ b/controller/cnpdriver/sfcctlr_l2_driver.go @@ -65,7 +65,7 @@ type sfcCtlrL2CNPDriver struct { // (instead of using global variables that caused // problems while running automated tests) type sequencer struct { - VLanID uint32 + VLanID uint32 MemIfID uint32 MacInstanceID uint32 IPInstanceID uint32 @@ -100,13 +100,18 @@ type reconcileCacheType struct { l3Routes map[string]l3.StaticRoutes_Route } +// NewRemoteClientTxn new vpp-agent remote client instance on top of key-val DB (ETCD) +// that identifies a specific vpp-agent that needs to be configured +// returns new instance of DataBroker for accessing key-val DB (ETCD) func NewRemoteClientTxn(microserviceLabel string, dbFactory func(string) keyval.ProtoBroker) linux.DataChangeDSL { prefix := servicelabel.GetDifferentAgentPrefix(microserviceLabel) broker := dbFactory(prefix) return remoteclient.DataChangeRequestDB(broker) } -// Init the driver/mode for Native SFC Controller L2 Container Networking Policy +// NewSfcCtlrL2CNPDriver creates new driver/mode for Native SFC Controller L2 Container Networking Policy +// of the driver/plugin +// returns new instance of DataBroker for accessing key-val DB (ETCD) func NewSfcCtlrL2CNPDriver(name string, dbFactory func(string) keyval.ProtoBroker) *sfcCtlrL2CNPDriver { cnpd := &sfcCtlrL2CNPDriver{}