From 40cba405c5c06a3dc086a55143cb3ffd1094597e Mon Sep 17 00:00:00 2001 From: Maros Ondrejicka Date: Thu, 23 Feb 2023 13:19:15 +0100 Subject: [PATCH] hs-test: refactor netconfig This joins separate representations of veth and tap interfaces into a single struct. It removes the need for type interface and embedding which simplifies the code. Type: test Signed-off-by: Maros Ondrejicka Change-Id: I1b2c368bfe90a5bdfaaa9a5129c27d7d96f8fe3b --- extras/hs-test/hst_suite.go | 26 +-- extras/hs-test/http_test.go | 4 +- extras/hs-test/linux_iperf_test.go | 2 +- extras/hs-test/netconfig.go | 310 +++++++++++++++-------------------- extras/hs-test/proxy_test.go | 4 +- extras/hs-test/suite_no_topo_test.go | 22 +-- extras/hs-test/topo-network/tap.yaml | 8 +- extras/hs-test/vppinstance.go | 18 +- 8 files changed, 165 insertions(+), 229 deletions(-) diff --git a/extras/hs-test/hst_suite.go b/extras/hs-test/hst_suite.go index 01be2efbf3d..ff7024582dc 100644 --- a/extras/hs-test/hst_suite.go +++ b/extras/hs-test/hst_suite.go @@ -25,7 +25,7 @@ type HstSuite struct { containers map[string]*Container volumes []string netConfigs []NetConfig - netInterfaces map[string]NetInterface + netInterfaces map[string]*NetInterface addresser *Addresser testIds map[string]string } @@ -188,7 +188,7 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) { } s.addresser = NewAddresser(s) - s.netInterfaces = make(map[string]NetInterface) + s.netInterfaces = make(map[string]*NetInterface) for _, elem := range yamlTopo.Devices { switch elem["type"].(string) { case NetNs: @@ -199,20 +199,11 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) { s.T().Fatalf("network config error: %v", err) } } - case Veth: + case Veth, Tap: { - if veth, err := NewVeth(elem, s.addresser); err == nil { - s.netConfigs = append(s.netConfigs, &veth) - s.netInterfaces[veth.Name()] = &veth - } else { - s.T().Fatalf("network config error: %v", err) - } - } - case Tap: - { - if tap, err := NewTap(elem, s.addresser); err == nil { - s.netConfigs = append(s.netConfigs, &tap) - s.netInterfaces[tap.Name()] = &tap + if netIf, err := NewNetworkInterface(elem, s.addresser); err == nil { + s.netConfigs = append(s.netConfigs, netIf) + s.netInterfaces[netIf.Name()] = netIf } else { s.T().Fatalf("network config error: %v", err) } @@ -262,11 +253,6 @@ func (s *HstSuite) getTestId() string { return s.testIds[testName] } -type NetworkAddresses struct { - network int - numberOfAddresses int -} - type AddressCounter = int type Addresser struct { diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go index 93705b22b88..96985be1ca7 100644 --- a/extras/hs-test/http_test.go +++ b/extras/hs-test/http_test.go @@ -51,7 +51,7 @@ func (s *NoTopoSuite) TestNginxAsServer() { err := vpp.waitForApp("-app", 5) s.assertNil(err) - serverAddress := s.netInterfaces[tapNameVpp].IP4AddressString() + serverAddress := s.netInterfaces[tapInterfaceName].Peer().IP4AddressString() defer func() { os.Remove(query) }() go startWget(finished, serverAddress, "80", query, "") @@ -64,7 +64,7 @@ func runNginxPerf(s *NoTopoSuite, mode, ab_or_wrk string) error { var args []string var exeName string - serverAddress := s.netInterfaces[tapNameVpp].IP4AddressString() + serverAddress := s.netInterfaces[tapInterfaceName].Peer().IP4AddressString() if ab_or_wrk == "ab" { args = []string{"-n", fmt.Sprintf("%d", nRequests), "-c", diff --git a/extras/hs-test/linux_iperf_test.go b/extras/hs-test/linux_iperf_test.go index 2c3437fe915..954b54e7e8a 100644 --- a/extras/hs-test/linux_iperf_test.go +++ b/extras/hs-test/linux_iperf_test.go @@ -14,7 +14,7 @@ func (s *TapSuite) TestLinuxIperf() { s.assertNil(err) s.log("server running") - ipAddress := s.netInterfaces["tap0"].IP4AddressString() + ipAddress := s.netInterfaces[tapInterfaceName].IP4AddressString() go StartClientApp(ipAddress, nil, clnCh, clnRes) s.log("client running") s.log(<-clnRes) diff --git a/extras/hs-test/netconfig.go b/extras/hs-test/netconfig.go index db6cbe183f8..f4dce7d262e 100644 --- a/extras/hs-test/netconfig.go +++ b/extras/hs-test/netconfig.go @@ -12,6 +12,7 @@ import ( ) type ( + Cmd = exec.Cmd MacAddress = ethernet_types.MacAddress AddressWithPrefix = ip_types.AddressWithPrefix IP4AddressWithPrefix = ip_types.IP4AddressWithPrefix @@ -29,18 +30,7 @@ type ( category string // what else to call this when `type` is reserved? } - NetInterface interface { - NetConfig - SetAddress(string) - AddressWithPrefix() AddressWithPrefix - IP4AddressWithPrefix() IP4AddressWithPrefix - IP4AddressString() string - SetIndex(InterfaceIndex) - Index() InterfaceIndex - HwAddress() MacAddress - } - - NetInterfaceBase struct { + NetInterface struct { NetConfigBase addresser *Addresser ip4Address string // this will have form 10.10.10.1/24 @@ -48,18 +38,7 @@ type ( hwAddress MacAddress networkNamespace string networkNumber int - } - - NetworkInterfaceVeth struct { - NetInterfaceBase - peerNetworkNamespace string - peerName string - peerNetworkNumber int - peerIp4Address string - } - - NetworkInterfaceTap struct { - NetInterfaceBase + peer *NetInterface } NetworkNamespace struct { @@ -80,173 +59,193 @@ const ( Bridge string = "bridge" ) -func (b *NetConfigBase) Name() string { - return b.name -} - -func (b *NetConfigBase) Type() string { - return b.category -} - -func (b *NetInterfaceBase) SetAddress(address string) { - b.ip4Address = address -} +type InterfaceAdder func(n *NetInterface) *Cmd -func (b *NetInterfaceBase) SetIndex(index InterfaceIndex) { - b.index = index -} - -func (b *NetInterfaceBase) Index() InterfaceIndex { - return b.index -} - -func (b *NetInterfaceBase) AddressWithPrefix() AddressWithPrefix { - address, _ := ip_types.ParseAddressWithPrefix(b.ip4Address) - return address -} - -func (b *NetInterfaceBase) IP4AddressWithPrefix() IP4AddressWithPrefix { - IP4Prefix, _ := ip_types.ParseIP4Prefix(b.ip4Address) - IP4AddressWithPrefix := ip_types.IP4AddressWithPrefix(IP4Prefix) - return IP4AddressWithPrefix -} - -func (b *NetInterfaceBase) IP4AddressString() string { - return strings.Split(b.ip4Address, "/")[0] -} - -func (b *NetInterfaceBase) HwAddress() MacAddress { - return b.hwAddress -} +var ( + ipCommandMap = map[string]InterfaceAdder{ + Veth: func(n *NetInterface) *Cmd { + return exec.Command("ip", "link", "add", n.name, "type", "veth", "peer", "name", n.peer.name) + }, + Tap: func(n *NetInterface) *Cmd { + return exec.Command("ip", "tuntap", "add", n.name, "mode", "tap") + }, + } +) -func NewVeth(cfg NetDevConfig, a *Addresser) (NetworkInterfaceVeth, error) { - var veth NetworkInterfaceVeth +func NewNetworkInterface(cfg NetDevConfig, a *Addresser) (*NetInterface, error) { + var newInterface *NetInterface = &NetInterface{} var err error - veth.addresser = a - veth.name = cfg["name"].(string) - veth.category = "veth" - veth.peerNetworkNumber = defaultNetworkNumber + newInterface.addresser = a + newInterface.name = cfg["name"].(string) + newInterface.networkNumber = defaultNetworkNumber + + if interfaceType, ok := cfg["type"]; ok { + newInterface.category = interfaceType.(string) + } - if cfg["preset-hw-address"] != nil { - veth.hwAddress, err = ethernet_types.ParseMacAddress(cfg["preset-hw-address"].(string)) + if presetHwAddress, ok := cfg["preset-hw-address"]; ok { + newInterface.hwAddress, err = ethernet_types.ParseMacAddress(presetHwAddress.(string)) if err != nil { - return NetworkInterfaceVeth{}, err + return &NetInterface{}, err } } if netns, ok := cfg["netns"]; ok { - veth.networkNamespace = netns.(string) + newInterface.networkNamespace = netns.(string) } if ip, ok := cfg["ip4"]; ok { if n, ok := ip.(NetDevConfig)["network"]; ok { - veth.networkNumber = n.(int) + newInterface.networkNumber = n.(int) } - veth.ip4Address, err = veth.addresser.NewIp4Address(veth.networkNumber) + newInterface.ip4Address, err = newInterface.addresser.NewIp4Address( + newInterface.networkNumber, + ) if err != nil { - return NetworkInterfaceVeth{}, err + return &NetInterface{}, err } } + if _, ok := cfg["peer"]; !ok { + return newInterface, nil + } + peer := cfg["peer"].(NetDevConfig) - veth.peerName = peer["name"].(string) + if newInterface.peer, err = NewNetworkInterface(peer, a); err != nil { + return &NetInterface{}, err + } + + return newInterface, nil +} - if peer["netns"] != nil { - veth.peerNetworkNamespace = peer["netns"].(string) +func (n *NetInterface) ConfigureUpState() error { + err := SetDevUp(n.Name(), "") + if err != nil { + return fmt.Errorf("set link up failed: %v", err) } + return nil +} - if peerIp, ok := peer["ip4"]; ok { - if n, ok := peerIp.(NetDevConfig)["network"]; ok { - veth.peerNetworkNumber = n.(int) - } - veth.peerIp4Address, err = veth.addresser.NewIp4Address(veth.peerNetworkNumber) +func (n *NetInterface) ConfigureNetworkNamespace() error { + if n.networkNamespace != "" { + err := LinkSetNetns(n.name, n.networkNamespace) if err != nil { - return NetworkInterfaceVeth{}, err + return err } } + return nil +} - return veth, nil +func (n *NetInterface) ConfigureAddress() error { + if n.ip4Address != "" { + if err := AddAddress( + n.Name(), + n.ip4Address, + n.networkNamespace, + ); err != nil { + return err + } + + } + return nil } -func (iface *NetworkInterfaceVeth) Configure() error { - err := AddVethPair(iface.name, iface.peerName) +func (n *NetInterface) Configure() error { + cmd := ipCommandMap[n.Type()](n) + _, err := cmd.CombinedOutput() if err != nil { + return fmt.Errorf("creating interface '%v' failed: %v", n.Name(), err) + } + + if err := n.ConfigureUpState(); err != nil { return err } - if iface.networkNamespace != "" { - err := LinkSetNetns(iface.name, iface.networkNamespace) - if err != nil { - return err - } + if err := n.ConfigureNetworkNamespace(); err != nil { + return err } - if iface.peerNetworkNamespace != "" { - err := LinkSetNetns(iface.peerName, iface.peerNetworkNamespace) - if err != nil { + if err := n.ConfigureAddress(); err != nil { + return err + } + + if n.peer != nil && n.peer.name != "" { + if err := n.Peer().ConfigureUpState(); err != nil { return err } - } - if iface.ip4Address != "" { - err = AddAddress( - iface.Name(), - iface.ip4Address, - iface.networkNamespace, - ) - } + if err := n.Peer().ConfigureNetworkNamespace(); err != nil { + return err + } - if iface.peerIp4Address != "" { - err = AddAddress( - iface.peerName, - iface.peerIp4Address, - iface.peerNetworkNamespace, - ) - if err != nil { - return fmt.Errorf("failed to add configure address for %s: %v", iface.peerName, err) + if err := n.Peer().ConfigureAddress(); err != nil { + return err } } + return nil } -func (iface *NetworkInterfaceVeth) Unconfigure() { - DelLink(iface.name) +func (n *NetInterface) Unconfigure() { + DelLink(n.name) } -func (iface *NetworkInterfaceVeth) PeerIp4AddressString() string { - return strings.Split(iface.peerIp4Address, "/")[0] +func (n *NetInterface) Name() string { + return n.name } -func NewTap(cfg NetDevConfig, a *Addresser) (NetworkInterfaceTap, error) { - var tap NetworkInterfaceTap - tap.addresser = a - tap.name = cfg["name"].(string) - tap.category = "tap" - ip4Address, err := tap.addresser.NewIp4Address() - if err != nil { - return NetworkInterfaceTap{}, err - } - tap.SetAddress(ip4Address) - return tap, nil +func (n *NetInterface) Type() string { + return n.category } -func (iface *NetworkInterfaceTap) Configure() error { - err := AddTap(iface.name, iface.IP4AddressString()) - if err != nil { - return err - } - return nil +func (n *NetInterface) SetAddress(address string) { + n.ip4Address = address +} + +func (n *NetInterface) SetIndex(index InterfaceIndex) { + n.index = index } -func (iface *NetworkInterfaceTap) Unconfigure() { - DelLink(iface.name) +func (n *NetInterface) Index() InterfaceIndex { + return n.index +} + +func (n *NetInterface) AddressWithPrefix() AddressWithPrefix { + address, _ := ip_types.ParseAddressWithPrefix(n.ip4Address) + return address +} + +func (n *NetInterface) IP4AddressWithPrefix() IP4AddressWithPrefix { + ip4Prefix, _ := ip_types.ParseIP4Prefix(n.ip4Address) + ip4AddressWithPrefix := ip_types.IP4AddressWithPrefix(ip4Prefix) + return ip4AddressWithPrefix +} + +func (n *NetInterface) IP4AddressString() string { + return strings.Split(n.ip4Address, "/")[0] +} + +func (n *NetInterface) HwAddress() MacAddress { + return n.hwAddress +} + +func (n *NetInterface) Peer() *NetInterface { + return n.peer +} + +func (b *NetConfigBase) Name() string { + return b.name +} + +func (b *NetConfigBase) Type() string { + return b.category } func NewNetNamespace(cfg NetDevConfig) (NetworkNamespace, error) { var networkNamespace NetworkNamespace networkNamespace.name = cfg["name"].(string) - networkNamespace.category = "netns" + networkNamespace.category = NetNs return networkNamespace, nil } @@ -261,7 +260,7 @@ func (ns *NetworkNamespace) Unconfigure() { func NewBridge(cfg NetDevConfig) (NetworkBridge, error) { var bridge NetworkBridge bridge.name = cfg["name"].(string) - bridge.category = "bridge" + bridge.category = Bridge for _, v := range cfg["interfaces"].([]interface{}) { bridge.interfaces = append(bridge.interfaces, v.(string)) } @@ -303,30 +302,6 @@ func SetDevDown(dev, ns string) error { return setDevUpDown(dev, ns, false) } -func AddTap(ifName, ifAddress string) error { - cmd := exec.Command("ip", "tuntap", "add", ifName, "mode", "tap") - o, err := cmd.CombinedOutput() - if err != nil { - s := fmt.Sprintf("error creating tap %s: %v: %s", ifName, err, string(o)) - return errors.New(s) - } - - cmd = exec.Command("ip", "addr", "add", ifAddress, "dev", ifName) - err = cmd.Run() - if err != nil { - DelLink(ifName) - s := fmt.Sprintf("error setting addr for tap %s: %v", ifName, err) - return errors.New(s) - } - - err = SetDevUp(ifName, "") - if err != nil { - DelLink(ifName) - return err - } - return nil -} - func DelLink(ifName string) { cmd := exec.Command("ip", "link", "del", ifName) cmd.Run() @@ -349,23 +324,6 @@ func setDevUpDown(dev, ns string, isUp bool) error { return nil } -func AddVethPair(ifName, peerName string) error { - cmd := exec.Command("ip", "link", "add", ifName, "type", "veth", "peer", "name", peerName) - err := cmd.Run() - if err != nil { - return fmt.Errorf("creating veth pair '%v/%v' failed: %v", ifName, peerName, err) - } - err = SetDevUp(ifName, "") - if err != nil { - return fmt.Errorf("set link up failed: %v", err) - } - err = SetDevUp(peerName, "") - if err != nil { - return fmt.Errorf("set link up failed: %v", err) - } - return nil -} - func addDelNetns(name string, isAdd bool) error { var op string if isAdd { diff --git a/extras/hs-test/proxy_test.go b/extras/hs-test/proxy_test.go index d8918f1842b..f1218662374 100644 --- a/extras/hs-test/proxy_test.go +++ b/extras/hs-test/proxy_test.go @@ -50,14 +50,14 @@ func testProxyHttpTcp(s *NsSuite) error { } func configureVppProxy(s *NsSuite) error { - serverVeth := s.netInterfaces[serverInterface].(*NetworkInterfaceVeth) + serverVeth := s.netInterfaces[serverInterface] clientVeth := s.netInterfaces[clientInterface] testVppProxy := s.getContainerByName("vpp").vppInstance output := testVppProxy.vppctl( "test proxy server server-uri tcp://%s/555 client-uri tcp://%s/666", clientVeth.IP4AddressString(), - serverVeth.PeerIp4AddressString(), + serverVeth.Peer().IP4AddressString(), ) s.log("proxy configured...", output) return nil diff --git a/extras/hs-test/suite_no_topo_test.go b/extras/hs-test/suite_no_topo_test.go index 01958b0a804..12b939e435f 100644 --- a/extras/hs-test/suite_no_topo_test.go +++ b/extras/hs-test/suite_no_topo_test.go @@ -4,8 +4,7 @@ const ( singleTopoContainerVpp = "vpp" singleTopoContainerNginx = "nginx" - tapNameVpp = "vppTap" - tapNameHost = "hostTap" + tapInterfaceName = "hst_tap_host" ) type NoTopoSuite struct { @@ -13,19 +12,9 @@ type NoTopoSuite struct { } func (s *NoTopoSuite) SetupSuite() { - s.loadContainerTopology("single") - - s.addresser = NewAddresser(&s.HstSuite) - - var vppTapDevConfig = NetDevConfig{"name": tapNameVpp} - vppTap, _ := NewTap(vppTapDevConfig, s.addresser) + s.loadNetworkTopology("tap") - var hostTapDevConfig = NetDevConfig{"name": tapNameHost} - hostTap, _ := NewTap(hostTapDevConfig, s.addresser) - - s.netInterfaces = make(map[string]NetInterface) - s.netInterfaces[vppTap.Name()] = &vppTap - s.netInterfaces[hostTap.Name()] = &hostTap + s.loadContainerTopology("single") } func (s *NoTopoSuite) SetupTest() { @@ -43,8 +32,7 @@ func (s *NoTopoSuite) SetupTest() { vpp, _ := container.newVppInstance(startupConfig) vpp.start() - vppTapAddress := s.netInterfaces[tapNameVpp].AddressWithPrefix() - hostTapAddress := s.netInterfaces[tapNameHost].IP4AddressWithPrefix() + tapInterface := s.netInterfaces[tapInterfaceName] - vpp.createTap("tap0", hostTapAddress, vppTapAddress) + vpp.createTap(1, tapInterface) } diff --git a/extras/hs-test/topo-network/tap.yaml b/extras/hs-test/topo-network/tap.yaml index 6f041325987..26481de703b 100644 --- a/extras/hs-test/topo-network/tap.yaml +++ b/extras/hs-test/topo-network/tap.yaml @@ -1,4 +1,10 @@ --- devices: - - name: "tap0" + - name: "hst_tap_host" type: "tap" + ip4: + network: 1 + peer: + name: "" + ip4: + network: 1 diff --git a/extras/hs-test/vppinstance.go b/extras/hs-test/vppinstance.go index 2ecb4de3ecd..29b86d5adcb 100644 --- a/extras/hs-test/vppinstance.go +++ b/extras/hs-test/vppinstance.go @@ -172,10 +172,8 @@ func (vpp *VppInstance) waitForApp(appName string, timeout int) error { } func (vpp *VppInstance) createAfPacket( - netInterface NetInterface, + veth *NetInterface, ) (interface_types.InterfaceIndex, error) { - veth := netInterface.(*NetworkInterfaceVeth) - createReq := &af_packet.AfPacketCreateV2{ UseRandomHwAddr: true, HostIfName: veth.Name(), @@ -206,7 +204,7 @@ func (vpp *VppInstance) createAfPacket( if veth.AddressWithPrefix() == (AddressWithPrefix{}) { var err error var ip4Address string - if ip4Address, err = veth.addresser.NewIp4Address(veth.peerNetworkNumber); err == nil { + if ip4Address, err = veth.addresser.NewIp4Address(veth.Peer().networkNumber); err == nil { veth.SetAddress(ip4Address) } else { return 0, err @@ -255,15 +253,15 @@ func (vpp *VppInstance) addAppNamespace( } func (vpp *VppInstance) createTap( - hostInterfaceName string, - hostIp4Address IP4AddressWithPrefix, - vppIp4Address AddressWithPrefix, + id uint32, + tap *NetInterface, ) error { createTapReq := &tapv2.TapCreateV2{ + ID: id, HostIfNameSet: true, - HostIfName: hostInterfaceName, + HostIfName: tap.Name(), HostIP4PrefixSet: true, - HostIP4Prefix: hostIp4Address, + HostIP4Prefix: tap.IP4AddressWithPrefix(), } createTapReply := &tapv2.TapCreateV2Reply{} @@ -276,7 +274,7 @@ func (vpp *VppInstance) createTap( addAddressReq := &interfaces.SwInterfaceAddDelAddress{ IsAdd: true, SwIfIndex: createTapReply.SwIfIndex, - Prefix: vppIp4Address, + Prefix: tap.Peer().AddressWithPrefix(), } addAddressReply := &interfaces.SwInterfaceAddDelAddressReply{} -- 2.16.6