blob: 4c6d5b2664b9720896c4e2c5000b45d12ecaa04c [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 Villincee15aa2024-03-14 11:42:55 -04008 "log/slog"
Maros Ondrejickaffa3f602023-01-26 10:07:29 +01009 "os"
Filip Tehlar31eaea92023-06-15 10:06:57 +020010 "os/exec"
11 "strings"
Maros Ondrejickaa2d52622023-02-24 11:26:39 +010012 "time"
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010013
14 "github.com/edwarnicke/exechelper"
Adrian Villincee15aa2024-03-14 11:42:55 -040015 . "github.com/onsi/ginkgo/v2"
16 . "github.com/onsi/gomega"
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010017 "gopkg.in/yaml.v3"
18)
19
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010020const (
Filip Tehlar608d0062023-04-28 10:29:47 +020021 DEFAULT_NETWORK_NUM int = 1
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010022)
23
Maros Ondrejickae7625d02023-02-28 16:55:01 +010024var isPersistent = flag.Bool("persist", false, "persists topology config")
25var isVerbose = flag.Bool("verbose", false, "verbose test output")
26var isUnconfiguring = flag.Bool("unconfigure", false, "remove topology")
27var isVppDebug = flag.Bool("debug", false, "attach gdb to vpp")
Filip Tehlar608d0062023-04-28 10:29:47 +020028var nConfiguredCpus = flag.Int("cpus", 1, "number of CPUs assigned to vpp")
Filip Tehlar109f3ce2023-09-05 15:36:28 +020029var vppSourceFileDir = flag.String("vppsrc", "", "vpp source file directory")
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010030
31type HstSuite struct {
Filip Tehlar3a910ab2023-06-08 17:39:39 +020032 containers map[string]*Container
33 volumes []string
34 netConfigs []NetConfig
35 netInterfaces map[string]*NetInterface
36 ip4AddrAllocator *Ip4AddressAllocator
37 testIds map[string]string
38 cpuAllocator *CpuAllocatorT
39 cpuContexts []*CpuContext
40 cpuPerVpp int
Adrian Villincee15aa2024-03-14 11:42:55 -040041 pid string
Filip Tehlar608d0062023-04-28 10:29:47 +020042}
43
44func (s *HstSuite) SetupSuite() {
45 var err error
adrianvillin28bd8f02024-02-13 06:00:02 -050046 s.pid = fmt.Sprint(os.Getpid())
Filip Tehlar608d0062023-04-28 10:29:47 +020047 s.cpuAllocator, err = CpuAllocator()
48 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -040049 Fail("failed to init cpu allocator: " + fmt.Sprint(err))
Filip Tehlar608d0062023-04-28 10:29:47 +020050 }
51 s.cpuPerVpp = *nConfiguredCpus
52}
53
54func (s *HstSuite) AllocateCpus() []int {
55 cpuCtx, err := s.cpuAllocator.Allocate(s.cpuPerVpp)
56 s.assertNil(err)
57 s.AddCpuContext(cpuCtx)
58 return cpuCtx.cpus
59}
60
61func (s *HstSuite) AddCpuContext(cpuCtx *CpuContext) {
62 s.cpuContexts = append(s.cpuContexts, cpuCtx)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010063}
64
65func (s *HstSuite) TearDownSuite() {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010066 s.unconfigureNetworkTopology()
67}
68
69func (s *HstSuite) TearDownTest() {
Maros Ondrejickae7625d02023-02-28 16:55:01 +010070 if *isPersistent {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010071 return
72 }
Filip Tehlar608d0062023-04-28 10:29:47 +020073 for _, c := range s.cpuContexts {
74 c.Release()
75 }
Maros Ondrejickae7625d02023-02-28 16:55:01 +010076 s.resetContainers()
77 s.removeVolumes()
adrianvillin28bd8f02024-02-13 06:00:02 -050078 s.ip4AddrAllocator.deleteIpAddresses()
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010079}
80
Maros Ondrejickaaf004dd2023-02-27 16:52:57 +010081func (s *HstSuite) skipIfUnconfiguring() {
Maros Ondrejickae7625d02023-02-28 16:55:01 +010082 if *isUnconfiguring {
Maros Ondrejickaaf004dd2023-02-27 16:52:57 +010083 s.skip("skipping to unconfigure")
84 }
85}
86
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010087func (s *HstSuite) SetupTest() {
Adrian Villincee15aa2024-03-14 11:42:55 -040088 RegisterFailHandler(func(message string, callerSkip ...int) {
89 s.hstFail()
90 Fail(message, callerSkip...)
91 })
Maros Ondrejickaaf004dd2023-02-27 16:52:57 +010092 s.skipIfUnconfiguring()
Maros Ondrejickae7625d02023-02-28 16:55:01 +010093 s.setupVolumes()
94 s.setupContainers()
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010095}
96
Maros Ondrejickae7625d02023-02-28 16:55:01 +010097func (s *HstSuite) setupVolumes() {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010098 for _, volume := range s.volumes {
99 cmd := "docker volume create --name=" + volume
100 s.log(cmd)
101 exechelper.Run(cmd)
102 }
103}
104
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100105func (s *HstSuite) setupContainers() {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100106 for _, container := range s.containers {
Filip Tehlar608d0062023-04-28 10:29:47 +0200107 if !container.isOptional {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100108 container.run()
109 }
110 }
111}
112
Adrian Villincee15aa2024-03-14 11:42:55 -0400113func logVppInstance(container *Container, maxLines int) {
114 if container.vppInstance == nil {
adrianvillin7c675472024-02-12 02:44:53 -0500115 return
116 }
117
118 logSource := container.getHostWorkDir() + defaultLogFilePath
119 file, err := os.Open(logSource)
120
Adrian Villincee15aa2024-03-14 11:42:55 -0400121 if err != nil {
adrianvillin7c675472024-02-12 02:44:53 -0500122 return
123 }
124 defer file.Close()
125
126 scanner := bufio.NewScanner(file)
127 var lines []string
128 var counter int
129
Adrian Villincee15aa2024-03-14 11:42:55 -0400130 for scanner.Scan() {
adrianvillin7c675472024-02-12 02:44:53 -0500131 lines = append(lines, scanner.Text())
132 counter++
133 if counter > maxLines {
134 lines = lines[1:]
135 counter--
136 }
137 }
138
139 fmt.Println("vvvvvvvvvvvvvvv " + container.name + " [VPP instance]:")
Adrian Villincee15aa2024-03-14 11:42:55 -0400140 for _, line := range lines {
adrianvillin7c675472024-02-12 02:44:53 -0500141 fmt.Println(line)
142 }
143 fmt.Printf("^^^^^^^^^^^^^^^\n\n")
adrianvillin7c675472024-02-12 02:44:53 -0500144}
145
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100146func (s *HstSuite) hstFail() {
adrianvillin7c675472024-02-12 02:44:53 -0500147 fmt.Println("Containers: " + fmt.Sprint(s.containers))
Adrian Villincee15aa2024-03-14 11:42:55 -0400148 for _, container := range s.containers {
adrianvillin7c675472024-02-12 02:44:53 -0500149 out, err := container.log(20)
Adrian Villincee15aa2024-03-14 11:42:55 -0400150 if err != nil {
adrianvillin7c675472024-02-12 02:44:53 -0500151 fmt.Printf("An error occured while obtaining '%s' container logs: %s\n", container.name, fmt.Sprint(err))
152 break
153 }
154 fmt.Printf("\nvvvvvvvvvvvvvvv " +
Adrian Villincee15aa2024-03-14 11:42:55 -0400155 container.name + ":\n" +
156 out +
157 "^^^^^^^^^^^^^^^\n\n")
adrianvillin7c675472024-02-12 02:44:53 -0500158 logVppInstance(container, 20)
159 }
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100160}
161
162func (s *HstSuite) assertNil(object interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400163 Expect(object).To(BeNil(), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100164}
165
166func (s *HstSuite) assertNotNil(object interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400167 Expect(object).ToNot(BeNil(), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100168}
169
170func (s *HstSuite) assertEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400171 Expect(actual).To(Equal(expected), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100172}
173
174func (s *HstSuite) assertNotEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400175 Expect(actual).ToNot(Equal(expected), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100176}
177
178func (s *HstSuite) assertContains(testString, contains interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400179 Expect(testString).To(ContainSubstring(fmt.Sprint(contains)), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100180}
181
182func (s *HstSuite) assertNotContains(testString, contains interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400183 Expect(testString).ToNot(ContainSubstring(fmt.Sprint(contains)), msgAndArgs...)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100184}
185
Maros Ondrejicka2ddb2fd2023-02-15 17:44:46 +0100186func (s *HstSuite) assertNotEmpty(object interface{}, msgAndArgs ...interface{}) {
Adrian Villincee15aa2024-03-14 11:42:55 -0400187 Expect(object).ToNot(BeEmpty(), msgAndArgs...)
Maros Ondrejicka2ddb2fd2023-02-15 17:44:46 +0100188}
189
Adrian Villincee15aa2024-03-14 11:42:55 -0400190func (s *HstSuite) log(arg any) {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100191 if *isVerbose {
Adrian Villincee15aa2024-03-14 11:42:55 -0400192 slog.Info(fmt.Sprint(arg))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100193 }
194}
195
Adrian Villincee15aa2024-03-14 11:42:55 -0400196func (s *HstSuite) skip(args string) {
197 Skip(args)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100198}
199
Filip Tehlar608d0062023-04-28 10:29:47 +0200200func (s *HstSuite) SkipIfMultiWorker(args ...any) {
201 if *nConfiguredCpus > 1 {
202 s.skip("test case not supported with multiple vpp workers")
203 }
204}
205
Filip Tehlar31eaea92023-06-15 10:06:57 +0200206func (s *HstSuite) SkipUnlessExtendedTestsBuilt() {
207 imageName := "hs-test/nginx-http3"
208
209 cmd := exec.Command("docker", "images", imageName)
210 byteOutput, err := cmd.CombinedOutput()
211 if err != nil {
212 s.log("error while searching for docker image")
213 return
214 }
215 if !strings.Contains(string(byteOutput), imageName) {
216 s.skip("extended tests not built")
217 }
218}
219
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100220func (s *HstSuite) resetContainers() {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100221 for _, container := range s.containers {
222 container.stop()
223 }
224}
225
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100226func (s *HstSuite) removeVolumes() {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100227 for _, volumeName := range s.volumes {
228 cmd := "docker volume rm " + volumeName
229 exechelper.Run(cmd)
230 os.RemoveAll(volumeName)
231 }
232}
233
adrianvillin28bd8f02024-02-13 06:00:02 -0500234func (s *HstSuite) getNetNamespaceByName(name string) string {
235 return name + s.pid
236}
237
238func (s *HstSuite) getInterfaceByName(name string) *NetInterface {
Adrian Villincee15aa2024-03-14 11:42:55 -0400239 return s.netInterfaces[name+s.pid]
adrianvillin28bd8f02024-02-13 06:00:02 -0500240}
241
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100242func (s *HstSuite) getContainerByName(name string) *Container {
Adrian Villincee15aa2024-03-14 11:42:55 -0400243 return s.containers[name+s.pid]
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100244}
245
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100246/*
247 * Create a copy and return its address, so that individial tests which call this
248 * are not able to modify the original container and affect other tests by doing that
249 */
250func (s *HstSuite) getTransientContainerByName(name string) *Container {
Adrian Villincee15aa2024-03-14 11:42:55 -0400251 containerCopy := *s.containers[name+s.pid]
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100252 return &containerCopy
253}
254
255func (s *HstSuite) loadContainerTopology(topologyName string) {
adrianvillin707210c2024-01-24 01:45:59 -0500256 data, err := os.ReadFile(containerTopologyDir + topologyName + ".yaml")
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100257 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400258 Fail("read error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100259 }
260 var yamlTopo YamlTopology
261 err = yaml.Unmarshal(data, &yamlTopo)
262 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400263 Fail("unmarshal error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100264 }
265
266 for _, elem := range yamlTopo.Volumes {
267 volumeMap := elem["volume"].(VolumeConfig)
268 hostDir := volumeMap["host-dir"].(string)
Adrian Villincee15aa2024-03-14 11:42:55 -0400269 workingVolumeDir := logDir + CurrentSpecReport().LeafNodeText + s.pid + volumeDir
Filip Tehlara1bd50c2024-01-24 11:59:44 +0100270 volDirReplacer := strings.NewReplacer("$HST_VOLUME_DIR", workingVolumeDir)
271 hostDir = volDirReplacer.Replace(hostDir)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100272 s.volumes = append(s.volumes, hostDir)
273 }
274
275 s.containers = make(map[string]*Container)
276 for _, elem := range yamlTopo.Containers {
Adrian Villincee15aa2024-03-14 11:42:55 -0400277 newContainer, err := newContainer(s, elem)
adrianvillin28bd8f02024-02-13 06:00:02 -0500278 newContainer.suite = s
Adrian Villincee15aa2024-03-14 11:42:55 -0400279 newContainer.name += newContainer.suite.pid
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100280 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400281 Fail("container config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100282 }
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100283 s.containers[newContainer.name] = newContainer
284 }
285}
286
287func (s *HstSuite) loadNetworkTopology(topologyName string) {
adrianvillin707210c2024-01-24 01:45:59 -0500288 data, err := os.ReadFile(networkTopologyDir + topologyName + ".yaml")
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100289 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400290 Fail("read error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100291 }
292 var yamlTopo YamlTopology
293 err = yaml.Unmarshal(data, &yamlTopo)
294 if err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400295 Fail("unmarshal error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100296 }
297
Filip Tehlar3a910ab2023-06-08 17:39:39 +0200298 s.ip4AddrAllocator = NewIp4AddressAllocator()
Maros Ondrejicka40cba402023-02-23 13:19:15 +0100299 s.netInterfaces = make(map[string]*NetInterface)
adrianvillin28bd8f02024-02-13 06:00:02 -0500300
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100301 for _, elem := range yamlTopo.Devices {
adrianvillin28bd8f02024-02-13 06:00:02 -0500302 if _, ok := elem["name"]; ok {
303 elem["name"] = elem["name"].(string) + s.pid
304 }
305
306 if peer, ok := elem["peer"].(NetDevConfig); ok {
Adrian Villincee15aa2024-03-14 11:42:55 -0400307 if peer["name"].(string) != "" {
adrianvillin28bd8f02024-02-13 06:00:02 -0500308 peer["name"] = peer["name"].(string) + s.pid
309 }
Adrian Villincee15aa2024-03-14 11:42:55 -0400310 if _, ok := peer["netns"]; ok {
adrianvillin28bd8f02024-02-13 06:00:02 -0500311 peer["netns"] = peer["netns"].(string) + s.pid
312 }
313 }
314
315 if _, ok := elem["netns"]; ok {
316 elem["netns"] = elem["netns"].(string) + s.pid
317 }
318
319 if _, ok := elem["interfaces"]; ok {
320 interfaceCount := len(elem["interfaces"].([]interface{}))
321 for i := 0; i < interfaceCount; i++ {
322 elem["interfaces"].([]interface{})[i] = elem["interfaces"].([]interface{})[i].(string) + s.pid
323 }
324 }
325
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100326 switch elem["type"].(string) {
327 case NetNs:
328 {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100329 if namespace, err := newNetNamespace(elem); err == nil {
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100330 s.netConfigs = append(s.netConfigs, &namespace)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100331 } else {
Adrian Villincee15aa2024-03-14 11:42:55 -0400332 Fail("network config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100333 }
334 }
Maros Ondrejicka40cba402023-02-23 13:19:15 +0100335 case Veth, Tap:
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100336 {
Filip Tehlar3a910ab2023-06-08 17:39:39 +0200337 if netIf, err := newNetworkInterface(elem, s.ip4AddrAllocator); err == nil {
Maros Ondrejicka40cba402023-02-23 13:19:15 +0100338 s.netConfigs = append(s.netConfigs, netIf)
339 s.netInterfaces[netIf.Name()] = netIf
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100340 } else {
Adrian Villincee15aa2024-03-14 11:42:55 -0400341 Fail("network config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100342 }
343 }
344 case Bridge:
345 {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100346 if bridge, err := newBridge(elem); err == nil {
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100347 s.netConfigs = append(s.netConfigs, &bridge)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100348 } else {
Adrian Villincee15aa2024-03-14 11:42:55 -0400349 Fail("network config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100350 }
351 }
352 }
353 }
354}
355
356func (s *HstSuite) configureNetworkTopology(topologyName string) {
357 s.loadNetworkTopology(topologyName)
358
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100359 if *isUnconfiguring {
Maros Ondrejickaaf004dd2023-02-27 16:52:57 +0100360 return
361 }
362
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100363 for _, nc := range s.netConfigs {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100364 if err := nc.configure(); err != nil {
Adrian Villincee15aa2024-03-14 11:42:55 -0400365 Fail("Network config error: " + fmt.Sprint(err))
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100366 }
367 }
368}
369
370func (s *HstSuite) unconfigureNetworkTopology() {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100371 if *isPersistent {
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100372 return
373 }
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +0100374 for _, nc := range s.netConfigs {
Maros Ondrejickae7625d02023-02-28 16:55:01 +0100375 nc.unconfigure()
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100376 }
377}
378
Maros Ondrejickaa2d52622023-02-24 11:26:39 +0100379func (s *HstSuite) getTestId() string {
Adrian Villincee15aa2024-03-14 11:42:55 -0400380 testName := CurrentSpecReport().LeafNodeText
Maros Ondrejickaa2d52622023-02-24 11:26:39 +0100381
382 if s.testIds == nil {
383 s.testIds = map[string]string{}
384 }
385
386 if _, ok := s.testIds[testName]; !ok {
Filip Tehlar75776f02023-03-24 13:47:45 +0100387 s.testIds[testName] = time.Now().Format("2006-01-02_15-04-05")
Maros Ondrejickaa2d52622023-02-24 11:26:39 +0100388 }
389
390 return s.testIds[testName]
391}
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200392
adrianvillin28bd8f02024-02-13 06:00:02 -0500393// Returns last 4 digits of PID
394func (s *HstSuite) getPortFromPid() string {
395 port := s.pid
396 for len(port) < 4 {
397 port += "0"
398 }
399 return port[len(port)-4:]
400}
401
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200402func (s *HstSuite) startServerApp(running chan error, done chan struct{}, env []string) {
adrianvillin28bd8f02024-02-13 06:00:02 -0500403 cmd := exec.Command("iperf3", "-4", "-s", "-p", s.getPortFromPid())
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200404 if env != nil {
405 cmd.Env = env
406 }
407 s.log(cmd)
408 err := cmd.Start()
409 if err != nil {
410 msg := fmt.Errorf("failed to start iperf server: %v", err)
411 running <- msg
412 return
413 }
414 running <- nil
415 <-done
416 cmd.Process.Kill()
417}
418
419func (s *HstSuite) startClientApp(ipAddress string, env []string, clnCh chan error, clnRes chan string) {
420 defer func() {
421 clnCh <- nil
422 }()
423
424 nTries := 0
425
426 for {
adrianvillin28bd8f02024-02-13 06:00:02 -0500427 cmd := exec.Command("iperf3", "-c", ipAddress, "-u", "-l", "1460", "-b", "10g", "-p", s.getPortFromPid())
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200428 if env != nil {
429 cmd.Env = env
430 }
431 s.log(cmd)
432 o, err := cmd.CombinedOutput()
433 if err != nil {
434 if nTries > 5 {
435 clnCh <- fmt.Errorf("failed to start client app '%s'.\n%s", err, o)
436 return
437 }
438 time.Sleep(1 * time.Second)
439 nTries++
440 continue
441 } else {
442 clnRes <- fmt.Sprintf("Client output: %s", o)
443 }
444 break
445 }
446}
447
448func (s *HstSuite) startHttpServer(running chan struct{}, done chan struct{}, addressPort, netNs string) {
adrianvillin28bd8f02024-02-13 06:00:02 -0500449 cmd := newCommand([]string{"./http_server", addressPort, s.pid}, netNs)
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200450 err := cmd.Start()
451 s.log(cmd)
452 if err != nil {
adrianvillin7c675472024-02-12 02:44:53 -0500453 fmt.Println("Failed to start http server: " + fmt.Sprint(err))
Filip Tehlar4b3598e2023-09-02 08:54:21 +0200454 return
455 }
456 running <- struct{}{}
457 <-done
458 cmd.Process.Kill()
459}
460
461func (s *HstSuite) startWget(finished chan error, server_ip, port, query, netNs string) {
462 defer func() {
463 finished <- errors.New("wget error")
464 }()
465
466 cmd := newCommand([]string{"wget", "--timeout=10", "--no-proxy", "--tries=5", "-O", "/dev/null", server_ip + ":" + port + "/" + query},
467 netNs)
468 s.log(cmd)
469 o, err := cmd.CombinedOutput()
470 if err != nil {
471 finished <- fmt.Errorf("wget error: '%v\n\n%s'", err, o)
472 return
473 } else if !strings.Contains(string(o), "200 OK") {
474 finished <- fmt.Errorf("wget error: response not 200 OK")
475 return
476 }
477 finished <- nil
478}