blob: 35553f00ff35ea978e2cb23f15b610cf93fc74b3 [file] [log] [blame]
Maros Ondrejickaffa3f602023-01-26 10:07:29 +01001package main
2
3import (
adrianvillin7c675472024-02-12 02:44:53 -05004 "bufio"
Filip Tehlar4b3598e2023-09-02 08:54:21 +02005 "errors"
Filip Tehlar671cf512023-01-31 10:34:18 +01006 "flag"
Filip Tehlar4b3598e2023-09-02 08:54:21 +02007 "fmt"
Adrian Villin637edda2024-05-06 06:55:34 -04008 "io"
9 "log"
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010010 "os"
Filip Tehlar31eaea92023-06-15 10:06:57 +020011 "os/exec"
12 "strings"
Maros Ondrejickaa2d52622023-02-24 11:26:39 +010013 "time"
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010014
15 "github.com/edwarnicke/exechelper"
Adrian Villincee15aa2024-03-14 11:42:55 -040016 . "github.com/onsi/ginkgo/v2"
17 . "github.com/onsi/gomega"
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010018 "gopkg.in/yaml.v3"
19)
20
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010021const (
Filip Tehlar608d0062023-04-28 10:29:47 +020022 DEFAULT_NETWORK_NUM int = 1
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010023)
24
Maros Ondrejickae7625d02023-02-28 16:55:01 +010025var isPersistent = flag.Bool("persist", false, "persists topology config")
26var isVerbose = flag.Bool("verbose", false, "verbose test output")
27var isUnconfiguring = flag.Bool("unconfigure", false, "remove topology")
28var isVppDebug = flag.Bool("debug", false, "attach gdb to vpp")
Filip Tehlar608d0062023-04-28 10:29:47 +020029var nConfiguredCpus = flag.Int("cpus", 1, "number of CPUs assigned to vpp")
Filip Tehlar109f3ce2023-09-05 15:36:28 +020030var vppSourceFileDir = flag.String("vppsrc", "", "vpp source file directory")
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010031
32type HstSuite struct {
Filip Tehlar3a910ab2023-06-08 17:39:39 +020033 containers map[string]*Container
34 volumes []string
35 netConfigs []NetConfig
36 netInterfaces map[string]*NetInterface
37 ip4AddrAllocator *Ip4AddressAllocator
38 testIds map[string]string
39 cpuAllocator *CpuAllocatorT
40 cpuContexts []*CpuContext
41 cpuPerVpp int
Adrian Villincee15aa2024-03-14 11:42:55 -040042 pid string
Adrian Villin46d66002024-05-15 04:33:41 -040043 logger *log.Logger
44 logFile *os.File
Filip Tehlar608d0062023-04-28 10:29:47 +020045}
46
47func (s *HstSuite) SetupSuite() {
Adrian Villin637edda2024-05-06 06:55:34 -040048 s.createLogger()
49 s.log("Suite Setup")
50 RegisterFailHandler(func(message string, callerSkip ...int) {
51 s.hstFail()
52 Fail(message, callerSkip...)
53 })
Filip Tehlar608d0062023-04-28 10:29:47 +020054 var err error
adrianvillin28bd8f02024-02-13 06:00:02 -050055 s.pid = fmt.Sprint(os.Getpid())
Filip Tehlar608d0062023-04-28 10:29:47 +020056 s.cpuAllocator, err = CpuAllocator()
57 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -040058 Fail("failed to init cpu allocator: " + fmt.Sprint(err))
Filip Tehlar608d0062023-04-28 10:29:47 +020059 }
60 s.cpuPerVpp = *nConfiguredCpus
61}
62
63func (s *HstSuite) AllocateCpus() []int {
64 cpuCtx, err := s.cpuAllocator.Allocate(s.cpuPerVpp)
65 s.assertNil(err)
66 s.AddCpuContext(cpuCtx)
67 return cpuCtx.cpus
68}
69
70func (s *HstSuite) AddCpuContext(cpuCtx *CpuContext) {
71 s.cpuContexts = append(s.cpuContexts, cpuCtx)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010072}
73
74func (s *HstSuite) TearDownSuite() {
Adrian Villin637edda2024-05-06 06:55:34 -040075 defer s.logFile.Close()
76 s.log("Suite Teardown")
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010077 s.unconfigureNetworkTopology()
78}
79
80func (s *HstSuite) TearDownTest() {
Adrian Villin637edda2024-05-06 06:55:34 -040081 s.log("Test Teardown")
Maros Ondrejickae7625d02023-02-28 16:55:01 +010082 if *isPersistent {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010083 return
84 }
Filip Tehlar608d0062023-04-28 10:29:47 +020085 for _, c := range s.cpuContexts {
86 c.Release()
87 }
Maros Ondrejickae7625d02023-02-28 16:55:01 +010088 s.resetContainers()
89 s.removeVolumes()
adrianvillin28bd8f02024-02-13 06:00:02 -050090 s.ip4AddrAllocator.deleteIpAddresses()
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010091}
92
Maros Ondrejickaaf004dd2023-02-27 16:52:57 +010093func (s *HstSuite) skipIfUnconfiguring() {
Maros Ondrejickae7625d02023-02-28 16:55:01 +010094 if *isUnconfiguring {
Maros Ondrejickaaf004dd2023-02-27 16:52:57 +010095 s.skip("skipping to unconfigure")
96 }
97}
98
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010099func (s *HstSuite) SetupTest() {
Adrian Villin637edda2024-05-06 06:55:34 -0400100 s.log("Test Setup")
Maros Ondrejickaaf004dd2023-02-27 16:52:57 +0100101 s.skipIfUnconfiguring()
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100102 s.setupVolumes()
103 s.setupContainers()
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100104}
105
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100106func (s *HstSuite) setupVolumes() {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100107 for _, volume := range s.volumes {
108 cmd := "docker volume create --name=" + volume
109 s.log(cmd)
110 exechelper.Run(cmd)
111 }
112}
113
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100114func (s *HstSuite) setupContainers() {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100115 for _, container := range s.containers {
Filip Tehlar608d0062023-04-28 10:29:47 +0200116 if !container.isOptional {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100117 container.run()
118 }
119 }
120}
121
Adrian Villin637edda2024-05-06 06:55:34 -0400122func (s *HstSuite) logVppInstance(container *Container, maxLines int) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400123 if container.vppInstance == nil {
adrianvillin7c675472024-02-12 02:44:53 -0500124 return
125 }
126
127 logSource := container.getHostWorkDir() + defaultLogFilePath
128 file, err := os.Open(logSource)
129
Adrian Villincee15aa2024-03-14 11:42:55 -0400130 if err != nil {
adrianvillin7c675472024-02-12 02:44:53 -0500131 return
132 }
133 defer file.Close()
134
135 scanner := bufio.NewScanner(file)
136 var lines []string
137 var counter int
138
Adrian Villincee15aa2024-03-14 11:42:55 -0400139 for scanner.Scan() {
adrianvillin7c675472024-02-12 02:44:53 -0500140 lines = append(lines, scanner.Text())
141 counter++
142 if counter > maxLines {
143 lines = lines[1:]
144 counter--
145 }
146 }
147
Adrian Villin637edda2024-05-06 06:55:34 -0400148 s.log("vvvvvvvvvvvvvvv " + container.name + " [VPP instance]:")
Adrian Villincee15aa2024-03-14 11:42:55 -0400149 for _, line := range lines {
Adrian Villin637edda2024-05-06 06:55:34 -0400150 s.log(line)
adrianvillin7c675472024-02-12 02:44:53 -0500151 }
Adrian Villin637edda2024-05-06 06:55:34 -0400152 s.log("^^^^^^^^^^^^^^^\n\n")
adrianvillin7c675472024-02-12 02:44:53 -0500153}
154
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100155func (s *HstSuite) hstFail() {
Adrian Villin637edda2024-05-06 06:55:34 -0400156 s.log("Containers: " + fmt.Sprint(s.containers))
Adrian Villincee15aa2024-03-14 11:42:55 -0400157 for _, container := range s.containers {
adrianvillin7c675472024-02-12 02:44:53 -0500158 out, err := container.log(20)
Adrian Villincee15aa2024-03-14 11:42:55 -0400159 if err != nil {
adrianvillin7c675472024-02-12 02:44:53 -0500160 fmt.Printf("An error occured while obtaining '%s' container logs: %s\n", container.name, fmt.Sprint(err))
Matus Fabian616201a2024-05-02 11:17:15 +0200161 continue
adrianvillin7c675472024-02-12 02:44:53 -0500162 }
Adrian Villin637edda2024-05-06 06:55:34 -0400163 s.log("\nvvvvvvvvvvvvvvv " +
Adrian Villincee15aa2024-03-14 11:42:55 -0400164 container.name + ":\n" +
165 out +
166 "^^^^^^^^^^^^^^^\n\n")
Adrian Villin637edda2024-05-06 06:55:34 -0400167 s.logVppInstance(container, 20)
adrianvillin7c675472024-02-12 02:44:53 -0500168 }
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100169}
170
171func (s *HstSuite) assertNil(object interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400172 Expect(object).To(BeNil(), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100173}
174
175func (s *HstSuite) assertNotNil(object interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400176 Expect(object).ToNot(BeNil(), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100177}
178
179func (s *HstSuite) assertEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400180 Expect(actual).To(Equal(expected), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100181}
182
183func (s *HstSuite) assertNotEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400184 Expect(actual).ToNot(Equal(expected), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100185}
186
187func (s *HstSuite) assertContains(testString, contains interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400188 Expect(testString).To(ContainSubstring(fmt.Sprint(contains)), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100189}
190
191func (s *HstSuite) assertNotContains(testString, contains interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400192 Expect(testString).ToNot(ContainSubstring(fmt.Sprint(contains)), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100193}
194
Maros Ondrejicka2ddb2fd2023-02-15 17:44:46 +0100195func (s *HstSuite) assertNotEmpty(object interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400196 Expect(object).ToNot(BeEmpty(), msgAndArgs...)
Maros Ondrejicka2ddb2fd2023-02-15 17:44:46 +0100197}
198
Adrian Villin46d66002024-05-15 04:33:41 -0400199func (s *HstSuite) createLogger() {
Adrian Villin637edda2024-05-06 06:55:34 -0400200 suiteName := CurrentSpecReport().ContainerHierarchyTexts[0]
201 var err error
202 s.logFile, err = os.Create("summary/" + suiteName + ".log")
203 if err != nil {
204 Fail("Unable to create log file.")
205 }
206 s.logger = log.New(io.Writer(s.logFile), "", log.LstdFlags)
207}
208
209// Logs to files by default, logs to stdout when VERBOSE=true with GinkgoWriter
210// to keep console tidy
Adrian Villincee15aa2024-03-14 11:42:55 -0400211func (s *HstSuite) log(arg any) {
Adrian Villin637edda2024-05-06 06:55:34 -0400212 logs := strings.Split(fmt.Sprint(arg), "\n")
213 for _, line := range logs {
214 s.logger.Println(line)
215 }
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100216 if *isVerbose {
Adrian Villin637edda2024-05-06 06:55:34 -0400217 GinkgoWriter.Println(arg)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100218 }
219}
220
Adrian Villincee15aa2024-03-14 11:42:55 -0400221func (s *HstSuite) skip(args string) {
222 Skip(args)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100223}
224
Filip Tehlar608d0062023-04-28 10:29:47 +0200225func (s *HstSuite) SkipIfMultiWorker(args ...any) {
226 if *nConfiguredCpus > 1 {
227 s.skip("test case not supported with multiple vpp workers")
228 }
229}
230
Filip Tehlar31eaea92023-06-15 10:06:57 +0200231func (s *HstSuite) SkipUnlessExtendedTestsBuilt() {
232 imageName := "hs-test/nginx-http3"
233
234 cmd := exec.Command("docker", "images", imageName)
235 byteOutput, err := cmd.CombinedOutput()
236 if err != nil {
237 s.log("error while searching for docker image")
238 return
239 }
240 if !strings.Contains(string(byteOutput), imageName) {
241 s.skip("extended tests not built")
242 }
243}
244
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100245func (s *HstSuite) resetContainers() {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100246 for _, container := range s.containers {
247 container.stop()
248 }
249}
250
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100251func (s *HstSuite) removeVolumes() {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100252 for _, volumeName := range s.volumes {
253 cmd := "docker volume rm " + volumeName
254 exechelper.Run(cmd)
255 os.RemoveAll(volumeName)
256 }
257}
258
adrianvillin28bd8f02024-02-13 06:00:02 -0500259func (s *HstSuite) getNetNamespaceByName(name string) string {
260 return name + s.pid
261}
262
263func (s *HstSuite) getInterfaceByName(name string) *NetInterface {
Adrian Villincee15aa2024-03-14 11:42:55 -0400264 return s.netInterfaces[name+s.pid]
adrianvillin28bd8f02024-02-13 06:00:02 -0500265}
266
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100267func (s *HstSuite) getContainerByName(name string) *Container {
Adrian Villincee15aa2024-03-14 11:42:55 -0400268 return s.containers[name+s.pid]
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100269}
270
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100271/*
272 * Create a copy and return its address, so that individial tests which call this
273 * are not able to modify the original container and affect other tests by doing that
274 */
275func (s *HstSuite) getTransientContainerByName(name string) *Container {
Adrian Villincee15aa2024-03-14 11:42:55 -0400276 containerCopy := *s.containers[name+s.pid]
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100277 return &containerCopy
278}
279
280func (s *HstSuite) loadContainerTopology(topologyName string) {
adrianvillin707210c2024-01-24 01:45:59 -0500281 data, err := os.ReadFile(containerTopologyDir + topologyName + ".yaml")
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100282 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400283 Fail("read error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100284 }
285 var yamlTopo YamlTopology
286 err = yaml.Unmarshal(data, &yamlTopo)
287 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400288 Fail("unmarshal error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100289 }
290
291 for _, elem := range yamlTopo.Volumes {
292 volumeMap := elem["volume"].(VolumeConfig)
293 hostDir := volumeMap["host-dir"].(string)
Adrian Villin637edda2024-05-06 06:55:34 -0400294 workingVolumeDir := logDir + CurrentSpecReport().LeafNodeText + volumeDir
Filip Tehlara1bd50c2024-01-24 11:59:44 +0100295 volDirReplacer := strings.NewReplacer("$HST_VOLUME_DIR", workingVolumeDir)
296 hostDir = volDirReplacer.Replace(hostDir)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100297 s.volumes = append(s.volumes, hostDir)
298 }
299
300 s.containers = make(map[string]*Container)
301 for _, elem := range yamlTopo.Containers {
Adrian Villincee15aa2024-03-14 11:42:55 -0400302 newContainer, err := newContainer(s, elem)
adrianvillin28bd8f02024-02-13 06:00:02 -0500303 newContainer.suite = s
Adrian Villincee15aa2024-03-14 11:42:55 -0400304 newContainer.name += newContainer.suite.pid
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100305 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400306 Fail("container config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100307 }
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100308 s.containers[newContainer.name] = newContainer
309 }
310}
311
312func (s *HstSuite) loadNetworkTopology(topologyName string) {
adrianvillin707210c2024-01-24 01:45:59 -0500313 data, err := os.ReadFile(networkTopologyDir + topologyName + ".yaml")
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100314 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400315 Fail("read error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100316 }
317 var yamlTopo YamlTopology
318 err = yaml.Unmarshal(data, &yamlTopo)
319 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400320 Fail("unmarshal error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100321 }
322
Filip Tehlar3a910ab2023-06-08 17:39:39 +0200323 s.ip4AddrAllocator = NewIp4AddressAllocator()
Maros Ondrejicka40cba402023-02-23 13:19:15 +0100324 s.netInterfaces = make(map[string]*NetInterface)
adrianvillin28bd8f02024-02-13 06:00:02 -0500325
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100326 for _, elem := range yamlTopo.Devices {
adrianvillin28bd8f02024-02-13 06:00:02 -0500327 if _, ok := elem["name"]; ok {
328 elem["name"] = elem["name"].(string) + s.pid
329 }
330
331 if peer, ok := elem["peer"].(NetDevConfig); ok {
Adrian Villincee15aa2024-03-14 11:42:55 -0400332 if peer["name"].(string) != "" {
adrianvillin28bd8f02024-02-13 06:00:02 -0500333 peer["name"] = peer["name"].(string) + s.pid
334 }
Adrian Villincee15aa2024-03-14 11:42:55 -0400335 if _, ok := peer["netns"]; ok {
adrianvillin28bd8f02024-02-13 06:00:02 -0500336 peer["netns"] = peer["netns"].(string) + s.pid
337 }
338 }
339
340 if _, ok := elem["netns"]; ok {
341 elem["netns"] = elem["netns"].(string) + s.pid
342 }
343
344 if _, ok := elem["interfaces"]; ok {
345 interfaceCount := len(elem["interfaces"].([]interface{}))
346 for i := 0; i < interfaceCount; i++ {
347 elem["interfaces"].([]interface{})[i] = elem["interfaces"].([]interface{})[i].(string) + s.pid
348 }
349 }
350
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100351 switch elem["type"].(string) {
352 case NetNs:
353 {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100354 if namespace, err := newNetNamespace(elem); err == nil {
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100355 s.netConfigs = append(s.netConfigs, &namespace)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100356 } else {
Adrian Villincee15aa2024-03-14 11:42:55 -0400357 Fail("network config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100358 }
359 }
Maros Ondrejicka40cba402023-02-23 13:19:15 +0100360 case Veth, Tap:
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100361 {
Filip Tehlar3a910ab2023-06-08 17:39:39 +0200362 if netIf, err := newNetworkInterface(elem, s.ip4AddrAllocator); err == nil {
Maros Ondrejicka40cba402023-02-23 13:19:15 +0100363 s.netConfigs = append(s.netConfigs, netIf)
364 s.netInterfaces[netIf.Name()] = netIf
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100365 } else {
Adrian Villincee15aa2024-03-14 11:42:55 -0400366 Fail("network config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100367 }
368 }
369 case Bridge:
370 {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100371 if bridge, err := newBridge(elem); err == nil {
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100372 s.netConfigs = append(s.netConfigs, &bridge)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100373 } else {
Adrian Villincee15aa2024-03-14 11:42:55 -0400374 Fail("network config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100375 }
376 }
377 }
378 }
379}
380
381func (s *HstSuite) configureNetworkTopology(topologyName string) {
382 s.loadNetworkTopology(topologyName)
383
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100384 if *isUnconfiguring {
Maros Ondrejickaaf004dd2023-02-27 16:52:57 +0100385 return
386 }
387
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100388 for _, nc := range s.netConfigs {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100389 if err := nc.configure(); err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400390 Fail("Network config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100391 }
392 }
393}
394
395func (s *HstSuite) unconfigureNetworkTopology() {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100396 if *isPersistent {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100397 return
398 }
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100399 for _, nc := range s.netConfigs {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100400 nc.unconfigure()
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100401 }
402}
403
Maros Ondrejickaa2d52622023-02-24 11:26:39 +0100404func (s *HstSuite) getTestId() string {
Adrian Villincee15aa2024-03-14 11:42:55 -0400405 testName := CurrentSpecReport().LeafNodeText
Maros Ondrejickaa2d52622023-02-24 11:26:39 +0100406
407 if s.testIds == nil {
408 s.testIds = map[string]string{}
409 }
410
411 if _, ok := s.testIds[testName]; !ok {
Filip Tehlar75776f02023-03-24 13:47:45 +0100412 s.testIds[testName] = time.Now().Format("2006-01-02_15-04-05")
Maros Ondrejickaa2d52622023-02-24 11:26:39 +0100413 }
414
415 return s.testIds[testName]
416}
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200417
adrianvillin28bd8f02024-02-13 06:00:02 -0500418// Returns last 4 digits of PID
419func (s *HstSuite) getPortFromPid() string {
420 port := s.pid
421 for len(port) < 4 {
422 port += "0"
423 }
424 return port[len(port)-4:]
425}
426
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200427func (s *HstSuite) startServerApp(running chan error, done chan struct{}, env []string) {
adrianvillin28bd8f02024-02-13 06:00:02 -0500428 cmd := exec.Command("iperf3", "-4", "-s", "-p", s.getPortFromPid())
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200429 if env != nil {
430 cmd.Env = env
431 }
432 s.log(cmd)
433 err := cmd.Start()
434 if err != nil {
435 msg := fmt.Errorf("failed to start iperf server: %v", err)
436 running <- msg
437 return
438 }
439 running <- nil
440 <-done
441 cmd.Process.Kill()
442}
443
444func (s *HstSuite) startClientApp(ipAddress string, env []string, clnCh chan error, clnRes chan string) {
445 defer func() {
446 clnCh <- nil
447 }()
448
449 nTries := 0
450
451 for {
adrianvillin28bd8f02024-02-13 06:00:02 -0500452 cmd := exec.Command("iperf3", "-c", ipAddress, "-u", "-l", "1460", "-b", "10g", "-p", s.getPortFromPid())
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200453 if env != nil {
454 cmd.Env = env
455 }
456 s.log(cmd)
457 o, err := cmd.CombinedOutput()
458 if err != nil {
459 if nTries > 5 {
460 clnCh <- fmt.Errorf("failed to start client app '%s'.\n%s", err, o)
461 return
462 }
463 time.Sleep(1 * time.Second)
464 nTries++
465 continue
466 } else {
467 clnRes <- fmt.Sprintf("Client output: %s", o)
468 }
469 break
470 }
471}
472
473func (s *HstSuite) startHttpServer(running chan struct{}, done chan struct{}, addressPort, netNs string) {
adrianvillin28bd8f02024-02-13 06:00:02 -0500474 cmd := newCommand([]string{"./http_server", addressPort, s.pid}, netNs)
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200475 err := cmd.Start()
476 s.log(cmd)
477 if err != nil {
Adrian Villin46d66002024-05-15 04:33:41 -0400478 s.log("Failed to start http server: " + fmt.Sprint(err))
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200479 return
480 }
481 running <- struct{}{}
482 <-done
483 cmd.Process.Kill()
484}
485
486func (s *HstSuite) startWget(finished chan error, server_ip, port, query, netNs string) {
487 defer func() {
488 finished <- errors.New("wget error")
489 }()
490
491 cmd := newCommand([]string{"wget", "--timeout=10", "--no-proxy", "--tries=5", "-O", "/dev/null", server_ip + ":" + port + "/" + query},
492 netNs)
493 s.log(cmd)
494 o, err := cmd.CombinedOutput()
495 if err != nil {
496 finished <- fmt.Errorf("wget error: '%v\n\n%s'", err, o)
497 return
498 } else if !strings.Contains(string(o), "200 OK") {
499 finished <- fmt.Errorf("wget error: response not 200 OK")
500 return
501 }
502 finished <- nil
503}