hs-test: clean-up ip address generation

Type: test
Signed-off-by: Maros Ondrejicka <mondreji@cisco.com>
Change-Id: I74c505920d1363d0ff2b3213fd831c181b70a173
diff --git a/extras/hs-test/hst_suite.go b/extras/hs-test/hst_suite.go
index 9cd9aea..409ab16 100644
--- a/extras/hs-test/hst_suite.go
+++ b/extras/hs-test/hst_suite.go
@@ -12,7 +12,7 @@
 )
 
 const (
-	defaultNamespaceName string = "default"
+	defaultNetworkNumber int = 1
 )
 
 func IsPersistent() bool {
@@ -173,7 +173,6 @@
 		if err != nil {
 			s.T().Fatalf("container config error: %v", err)
 		}
-		s.log(newContainer.getRunCommand())
 		s.containers[newContainer.name] = newContainer
 	}
 }
@@ -250,47 +249,48 @@
 	}
 }
 
-type NamespaceAddresses struct {
-	namespace         string
+type NetworkAddresses struct {
+	network           int
 	numberOfAddresses int
 }
 
+type AddressCounter = int
+
 type Addresser struct {
-	namespaces []*NamespaceAddresses
-	suite      *HstSuite
+	networks map[int]AddressCounter
+	suite    *HstSuite
 }
 
-func (a *Addresser) AddNamespace(name string) {
-	var newNamespace = &NamespaceAddresses{
-		namespace:         name,
-		numberOfAddresses: 0,
+func (a *Addresser) AddNetwork(networkNumber int) {
+	a.networks[networkNumber] = 1
+}
+
+func (a *Addresser) NewIp4Address(inputNetworkNumber ...int) (string, error) {
+	var networkNumber int = 0
+	if len(inputNetworkNumber) > 0 {
+		networkNumber = inputNetworkNumber[0]
 	}
-	a.namespaces = append(a.namespaces, newNamespace)
-}
 
-func (a *Addresser) NewIp4Address() (string, error) {
-	return a.NewIp4AddressWithNamespace(defaultNamespaceName)
-}
-
-func (a *Addresser) NewIp4AddressWithNamespace(namespace string) (string, error) {
-	for i, val := range a.namespaces {
-		if val.namespace != namespace {
-			continue
-		}
-		if val.numberOfAddresses == 255 {
-			return "", fmt.Errorf("no available IPv4 addresses")
-		}
-		address := fmt.Sprintf("10.10.%v.%v/24", i, val.numberOfAddresses+1)
-		val.numberOfAddresses++
-		return address, nil
+	if _, ok := a.networks[networkNumber]; !ok {
+		a.AddNetwork(networkNumber)
 	}
-	a.AddNamespace(namespace)
-	return a.NewIp4AddressWithNamespace(namespace)
+
+	numberOfAddresses := a.networks[networkNumber]
+
+	if numberOfAddresses == 254 {
+		return "", fmt.Errorf("no available IPv4 addresses")
+	}
+
+	address := fmt.Sprintf("10.10.%v.%v/24", networkNumber, numberOfAddresses)
+	a.networks[networkNumber] = numberOfAddresses + 1
+
+	return address, nil
 }
 
 func NewAddresser(suite *HstSuite) *Addresser {
 	var addresser = new(Addresser)
 	addresser.suite = suite
-	addresser.AddNamespace(defaultNamespaceName)
+	addresser.networks = make(map[int]AddressCounter)
+	addresser.AddNetwork(0)
 	return addresser
 }
diff --git a/extras/hs-test/netconfig.go b/extras/hs-test/netconfig.go
index 5b199fd..db6cbe1 100644
--- a/extras/hs-test/netconfig.go
+++ b/extras/hs-test/netconfig.go
@@ -42,16 +42,19 @@
 
 	NetInterfaceBase struct {
 		NetConfigBase
-		addresser  *Addresser
-		ip4address string // this will have form 10.10.10.1/24
-		index      InterfaceIndex
-		hwAddress  MacAddress
+		addresser        *Addresser
+		ip4Address       string // this will have form 10.10.10.1/24
+		index            InterfaceIndex
+		hwAddress        MacAddress
+		networkNamespace string
+		networkNumber    int
 	}
 
 	NetworkInterfaceVeth struct {
 		NetInterfaceBase
 		peerNetworkNamespace string
 		peerName             string
+		peerNetworkNumber    int
 		peerIp4Address       string
 	}
 
@@ -86,7 +89,7 @@
 }
 
 func (b *NetInterfaceBase) SetAddress(address string) {
-	b.ip4address = address
+	b.ip4Address = address
 }
 
 func (b *NetInterfaceBase) SetIndex(index InterfaceIndex) {
@@ -98,52 +101,31 @@
 }
 
 func (b *NetInterfaceBase) AddressWithPrefix() AddressWithPrefix {
-	address, _ := ip_types.ParseAddressWithPrefix(b.ip4address)
+	address, _ := ip_types.ParseAddressWithPrefix(b.ip4Address)
 	return address
 }
 
 func (b *NetInterfaceBase) IP4AddressWithPrefix() IP4AddressWithPrefix {
-	IP4Prefix, _ := ip_types.ParseIP4Prefix(b.ip4address)
+	IP4Prefix, _ := ip_types.ParseIP4Prefix(b.ip4Address)
 	IP4AddressWithPrefix := ip_types.IP4AddressWithPrefix(IP4Prefix)
 	return IP4AddressWithPrefix
 }
 
 func (b *NetInterfaceBase) IP4AddressString() string {
-	return strings.Split(b.ip4address, "/")[0]
+	return strings.Split(b.ip4Address, "/")[0]
 }
 
 func (b *NetInterfaceBase) HwAddress() MacAddress {
 	return b.hwAddress
 }
 
-func (iface *NetworkInterfaceVeth) Configure() error {
-	err := AddVethPair(iface.name, iface.peerName)
-	if err != nil {
-		return err
-	}
-
-	if iface.peerNetworkNamespace != "" {
-		err := LinkSetNetns(iface.peerName, iface.peerNetworkNamespace)
-		if 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)
-		}
-	}
-	return nil
-}
-
 func NewVeth(cfg NetDevConfig, a *Addresser) (NetworkInterfaceVeth, error) {
 	var veth NetworkInterfaceVeth
 	var err error
 	veth.addresser = a
 	veth.name = cfg["name"].(string)
 	veth.category = "veth"
+	veth.peerNetworkNumber = defaultNetworkNumber
 
 	if cfg["preset-hw-address"] != nil {
 		veth.hwAddress, err = ethernet_types.ParseMacAddress(cfg["preset-hw-address"].(string))
@@ -152,6 +134,20 @@
 		}
 	}
 
+	if netns, ok := cfg["netns"]; ok {
+		veth.networkNamespace = netns.(string)
+	}
+
+	if ip, ok := cfg["ip4"]; ok {
+		if n, ok := ip.(NetDevConfig)["network"]; ok {
+			veth.networkNumber = n.(int)
+		}
+		veth.ip4Address, err = veth.addresser.NewIp4Address(veth.networkNumber)
+		if err != nil {
+			return NetworkInterfaceVeth{}, err
+		}
+	}
+
 	peer := cfg["peer"].(NetDevConfig)
 
 	veth.peerName = peer["name"].(string)
@@ -160,9 +156,11 @@
 		veth.peerNetworkNamespace = peer["netns"].(string)
 	}
 
-	if peer["ip4"] != nil && peer["ip4"].(bool) == true {
-		veth.peerIp4Address, err = veth.addresser.
-			NewIp4AddressWithNamespace(veth.peerNetworkNamespace)
+	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)
 		if err != nil {
 			return NetworkInterfaceVeth{}, err
 		}
@@ -171,6 +169,47 @@
 	return veth, nil
 }
 
+func (iface *NetworkInterfaceVeth) Configure() error {
+	err := AddVethPair(iface.name, iface.peerName)
+	if err != nil {
+		return err
+	}
+
+	if iface.networkNamespace != "" {
+		err := LinkSetNetns(iface.name, iface.networkNamespace)
+		if err != nil {
+			return err
+		}
+	}
+
+	if iface.peerNetworkNamespace != "" {
+		err := LinkSetNetns(iface.peerName, iface.peerNetworkNamespace)
+		if err != nil {
+			return err
+		}
+	}
+
+	if iface.ip4Address != "" {
+		err = AddAddress(
+			iface.Name(),
+			iface.ip4Address,
+			iface.networkNamespace,
+		)
+	}
+
+	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)
+		}
+	}
+	return nil
+}
+
 func (iface *NetworkInterfaceVeth) Unconfigure() {
 	DelLink(iface.name)
 }
@@ -226,7 +265,11 @@
 	for _, v := range cfg["interfaces"].([]interface{}) {
 		bridge.interfaces = append(bridge.interfaces, v.(string))
 	}
-	bridge.networkNamespace = cfg["netns"].(string)
+
+	bridge.networkNamespace = ""
+	if netns, ok := cfg["netns"]; ok {
+		bridge.networkNamespace = netns.(string)
+	}
 	return bridge, nil
 }
 
@@ -310,12 +353,16 @@
 	cmd := exec.Command("ip", "link", "add", ifName, "type", "veth", "peer", "name", peerName)
 	err := cmd.Run()
 	if err != nil {
-		return fmt.Errorf("creating veth pair failed: %v", err)
+		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
 }
 
diff --git a/extras/hs-test/topo-network/ns.yaml b/extras/hs-test/topo-network/ns.yaml
index c018365..cf77f7e 100644
--- a/extras/hs-test/topo-network/ns.yaml
+++ b/extras/hs-test/topo-network/ns.yaml
@@ -11,11 +11,13 @@
     peer:
       name: "client"
       netns: "client"
-      ip4: true
+      ip4:
+        network: 1
 
   - name: "hst_server_vpp"
     type: "veth"
     peer:
       name: "server"
       netns: "server"
-      ip4: true
+      ip4:
+        network: 2
diff --git a/extras/hs-test/vppinstance.go b/extras/hs-test/vppinstance.go
index dfaf405..4bb7261 100644
--- a/extras/hs-test/vppinstance.go
+++ b/extras/hs-test/vppinstance.go
@@ -60,10 +60,10 @@
 )
 
 type VppInstance struct {
-	container      *Container
-	additionalConfig  Stanza
-	connection     *core.Connection
-	apiChannel     api.Channel
+	container        *Container
+	additionalConfig Stanza
+	connection       *core.Connection
+	apiChannel       api.Channel
 }
 
 func (vpp *VppInstance) Suite() *HstSuite {
@@ -96,11 +96,11 @@
 
 	// Create startup.conf inside the container
 	configContent := fmt.Sprintf(
-                vppConfigTemplate,
-                containerWorkDir,
-                defaultCliSocketFilePath,
-                defaultApiSocketFilePath,
-        )
+		vppConfigTemplate,
+		containerWorkDir,
+		defaultCliSocketFilePath,
+		defaultApiSocketFilePath,
+	)
 	configContent += vpp.additionalConfig.ToString()
 	startupFileName := vpp.getEtcDir() + "/startup.conf"
 	vpp.container.createFile(startupFileName, configContent)
@@ -166,7 +166,7 @@
 func (vpp *VppInstance) createAfPacket(
 	netInterface NetInterface,
 ) (interface_types.InterfaceIndex, error) {
-        veth := netInterface.(*NetworkInterfaceVeth)
+	veth := netInterface.(*NetworkInterfaceVeth)
 
 	createReq := &af_packet.AfPacketCreateV2{
 		UseRandomHwAddr: true,
@@ -198,14 +198,7 @@
 	if veth.AddressWithPrefix() == (AddressWithPrefix{}) {
 		var err error
 		var ip4Address string
-		if veth.peerNetworkNamespace != "" {
-			ip4Address, err = veth.addresser.
-				NewIp4AddressWithNamespace(veth.peerNetworkNamespace)
-		} else {
-			ip4Address, err = veth.addresser.
-				NewIp4Address()
-		}
-		if err == nil {
+		if ip4Address, err = veth.addresser.NewIp4Address(veth.peerNetworkNumber); err == nil {
 			veth.SetAddress(ip4Address)
 		} else {
 			return 0, err