hs-test: refactor netconfig 46/38346/4
authorMaros Ondrejicka <mondreji@cisco.com>
Thu, 23 Feb 2023 12:19:15 +0000 (13:19 +0100)
committerFlorin Coras <florin.coras@gmail.com>
Mon, 27 Feb 2023 17:26:41 +0000 (17:26 +0000)
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 <mondreji@cisco.com>
Change-Id: I1b2c368bfe90a5bdfaaa9a5129c27d7d96f8fe3b

extras/hs-test/hst_suite.go
extras/hs-test/http_test.go
extras/hs-test/linux_iperf_test.go
extras/hs-test/netconfig.go
extras/hs-test/proxy_test.go
extras/hs-test/suite_no_topo_test.go
extras/hs-test/topo-network/tap.yaml
extras/hs-test/vppinstance.go

index 01be2ef..ff70245 100644 (file)
@@ -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 {
index 93705b2..96985be 100644 (file)
@@ -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",
index 2c3437f..954b54e 100644 (file)
@@ -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)
index db6cbe1..f4dce7d 100644 (file)
@@ -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 {
index d8918f1..f121866 100644 (file)
@@ -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
index 01958b0..12b939e 100644 (file)
@@ -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)
 }
index 6f04132..26481de 100644 (file)
@@ -1,4 +1,10 @@
 ---
 devices:
-  - name: "tap0"
+  - name: "hst_tap_host"
     type: "tap"
+    ip4:
+      network: 1
+    peer:
+      name: ""
+      ip4:
+        network: 1
index 2ecb4de..29b86d5 100644 (file)
@@ -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{}