hs-test: add hsi and transparent proxy test 11/43511/3
authorMatus Fabian <[email protected]>
Fri, 1 Aug 2025 16:08:59 +0000 (12:08 -0400)
committerFlorin Coras <[email protected]>
Tue, 5 Aug 2025 02:01:28 +0000 (02:01 +0000)
Type: test

Change-Id: Ie7fdc987ee300cf0d3dc5aed31dd28a972f0c394
Signed-off-by: Matus Fabian <[email protected]>
extras/hs-test/Makefile
extras/hs-test/docker/Dockerfile.vpp
extras/hs-test/hsi_test.go [new file with mode: 0644]
extras/hs-test/infra/suite_hsi.go [new file with mode: 0644]
extras/hs-test/infra/vppinstance.go
extras/hs-test/topo-network/ns.yaml

index b264795..5406b69 100644 (file)
@@ -88,7 +88,8 @@ endif
 FORCE_BUILD?=true
 BUILD_AS:=$(strip $(shell echo $${SUDO_USER:-$${USER:-root}}))
 
-DOCKER_CAPABILITIES:=--cap-add=NET_ADMIN --cap-add=SYS_RESOURCE --cap-add=IPC_LOCK
+# privileged is needed for "ip netns" otherwise we are not able to create namespace
+DOCKER_CAPABILITIES:=--privileged
 DOCKER_DEVICES:=--device /dev/vhost-net:/dev/vhost-net --device /dev/net/tun:/dev/net/tun
 DOCKER_VOLUMES:=-v $(WS_ROOT):$(WS_ROOT) -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/hs-test:/tmp/hs-test \
        -v /etc/localtime:/etc/localtime:ro $(CORE_VOLUME) -v $(HS_ROOT)/.go_cache/mod:/root/go/pkg/mod \
index 1e69e2c..cf620ee 100644 (file)
@@ -17,6 +17,7 @@ COPY \
    $DIR/unittest_plugin.so \
    $DIR/quic_plugin.so \
    $DIR/quic_quicly_plugin.so \
+   $DIR/hsi_plugin.so \
    $DIR/http_static_plugin.so \
    $DIR/ping_plugin.so \
    $DIR/nsim_plugin.so \
diff --git a/extras/hs-test/hsi_test.go b/extras/hs-test/hsi_test.go
new file mode 100644 (file)
index 0000000..b5a8e61
--- /dev/null
@@ -0,0 +1,31 @@
+package main
+
+import (
+       "os"
+       "strconv"
+
+       . "fd.io/hs-test/infra"
+       . "github.com/onsi/ginkgo/v2"
+)
+
+func init() {
+       RegisterHsiSoloTests(HsiTransparentProxyTest)
+}
+
+func HsiTransparentProxyTest(s *HsiSuite) {
+       s.SetupNginxServer()
+       vpp := s.Containers.Vpp.VppInstance
+       s.Log(vpp.Vppctl("set interface feature host-" + s.Interfaces.Client.Name() + " hsi4-in arc ip4-unicast"))
+       s.Log(vpp.Vppctl("set interface feature host-" + s.Interfaces.Server.Name() + " hsi4-in arc ip4-unicast"))
+       s.Log(vpp.Vppctl("test proxy server server-uri tcp://0.0.0.0:%d client-uri tcp://%s:%d",
+               s.Ports.Server, s.ServerAddr(), s.Ports.Server))
+
+       query := "httpTestFile"
+       finished := make(chan error, 1)
+       defer os.Remove(query)
+       go func() {
+               defer GinkgoRecover()
+               s.StartWget(finished, s.ServerAddr(), strconv.Itoa(int(s.Ports.Server)), query, s.NetNamespaces.Client)
+       }()
+       s.AssertNil(<-finished)
+}
diff --git a/extras/hs-test/infra/suite_hsi.go b/extras/hs-test/infra/suite_hsi.go
new file mode 100644 (file)
index 0000000..0575577
--- /dev/null
@@ -0,0 +1,223 @@
+package hst
+
+import (
+       "fmt"
+       "os/exec"
+       "reflect"
+       "runtime"
+       "strings"
+
+       . "fd.io/hs-test/infra/common"
+       . "github.com/onsi/ginkgo/v2"
+)
+
+type HsiSuite struct {
+       HstSuite
+       maxTimeout int
+       Interfaces struct {
+               Client *NetInterface
+               Server *NetInterface
+       }
+       Containers struct {
+               Vpp                  *Container
+               NginxServerTransient *Container
+       }
+       Ports struct {
+               Server    uint16
+               ServerSsl uint16
+       }
+       NetNamespaces struct {
+               Client string
+       }
+}
+
+var hsiTests = map[string][]func(s *HsiSuite){}
+var hsiSoloTests = map[string][]func(s *HsiSuite){}
+var hsiMWTests = map[string][]func(s *HsiSuite){}
+
+func RegisterHsiTests(tests ...func(s *HsiSuite)) {
+       hsiTests[GetTestFilename()] = tests
+}
+
+func RegisterHsiSoloTests(tests ...func(s *HsiSuite)) {
+       hsiSoloTests[GetTestFilename()] = tests
+}
+
+func RegisterHsiMWTests(tests ...func(s *HsiSuite)) {
+       hsiMWTests[GetTestFilename()] = tests
+}
+
+func (s *HsiSuite) SetupSuite() {
+       s.HstSuite.SetupSuite()
+       s.ConfigureNetworkTopology("ns")
+       s.LoadContainerTopology("single")
+       s.Ports.Server = s.GeneratePortAsInt()
+       s.Ports.ServerSsl = s.GeneratePortAsInt()
+
+       if *IsVppDebug {
+               s.maxTimeout = 600
+       } else {
+               s.maxTimeout = 60
+       }
+       s.Interfaces.Client = s.GetInterfaceByName("hclnvpp")
+       s.Interfaces.Server = s.GetInterfaceByName("hsrvvpp")
+       s.NetNamespaces.Client = s.GetNetNamespaceByName("cln")
+       s.Containers.NginxServerTransient = s.GetTransientContainerByName("nginx-server")
+       s.Containers.Vpp = s.GetContainerByName("vpp")
+}
+
+func (s *HsiSuite) SetupTest() {
+       s.HstSuite.SetupTest()
+
+       vpp, err := s.Containers.Vpp.newVppInstance(s.Containers.Vpp.AllocatedCpus)
+       s.AssertNotNil(vpp, fmt.Sprint(err))
+
+       s.AssertNil(vpp.Start())
+       idx, err := vpp.createAfPacket(s.Interfaces.Client, false)
+       s.AssertNil(err, fmt.Sprint(err))
+       s.AssertNotEqual(0, idx)
+       idx, err = vpp.createAfPacket(s.Interfaces.Server, false)
+       s.AssertNil(err, fmt.Sprint(err))
+       s.AssertNotEqual(0, idx)
+
+       s.Log(vpp.Vppctl("set interface feature host-" + s.Interfaces.Client.Name() + " hsi4-in arc ip4-unicast"))
+       s.Log(vpp.Vppctl("set interface feature host-" + s.Interfaces.Server.Name() + " hsi4-in arc ip4-unicast"))
+
+       // let the host know howto get to the server
+       cmd := exec.Command("ip", "netns", "exec", s.NetNamespaces.Client, "ip", "route", "add",
+               s.ServerAddr(), "via", s.Interfaces.Client.Ip4AddressString())
+       s.Log(cmd.String())
+       _, err = cmd.CombinedOutput()
+       s.AssertNil(err, fmt.Sprint(err))
+
+       if *DryRun {
+               s.LogStartedContainers()
+               s.Skip("Dry run mode = true")
+       }
+}
+
+func (s *HsiSuite) TeardownTest() {
+       defer s.HstSuite.TeardownTest()
+       vpp := s.Containers.Vpp.VppInstance
+       if CurrentSpecReport().Failed() {
+               s.Log(vpp.Vppctl("show session verbose 2"))
+               s.Log(vpp.Vppctl("show error"))
+               s.CollectNginxLogs(s.Containers.NginxServerTransient)
+       }
+}
+
+func (s *HsiSuite) SetupNginxServer() {
+       s.AssertNil(s.Containers.NginxServerTransient.Create())
+       nginxSettings := struct {
+               LogPrefix string
+               Address   string
+               Port      uint16
+               PortSsl   uint16
+               Http2     string
+               Timeout   int
+       }{
+               LogPrefix: s.Containers.NginxServerTransient.Name,
+               Address:   s.ServerAddr(),
+               Port:      s.Ports.Server,
+               PortSsl:   s.Ports.ServerSsl,
+               Http2:     "off",
+               Timeout:   s.maxTimeout,
+       }
+       s.Containers.NginxServerTransient.CreateConfigFromTemplate(
+               "/nginx.conf",
+               "./resources/nginx/nginx_server.conf",
+               nginxSettings,
+       )
+       s.AssertNil(s.Containers.NginxServerTransient.Start())
+}
+
+func (s *HsiSuite) ServerAddr() string {
+       return s.Interfaces.Server.Peer.Ip4AddressString()
+}
+
+var _ = Describe("HsiSuite", Ordered, ContinueOnFailure, func() {
+       var s HsiSuite
+       BeforeAll(func() {
+               s.SetupSuite()
+       })
+       BeforeEach(func() {
+               s.SetupTest()
+       })
+       AfterAll(func() {
+               s.TeardownSuite()
+       })
+       AfterEach(func() {
+               s.TeardownTest()
+       })
+
+       for filename, tests := range hsiTests {
+               for _, test := range tests {
+                       test := test
+                       pc := reflect.ValueOf(test).Pointer()
+                       funcValue := runtime.FuncForPC(pc)
+                       testName := filename + "/" + strings.Split(funcValue.Name(), ".")[2]
+                       It(testName, func(ctx SpecContext) {
+                               s.Log(testName + ": BEGIN")
+                               test(&s)
+                       }, SpecTimeout(TestTimeout))
+               }
+       }
+})
+
+var _ = Describe("HsiSoloSuite", Ordered, ContinueOnFailure, Serial, func() {
+       var s HsiSuite
+       BeforeAll(func() {
+               s.SetupSuite()
+       })
+       BeforeEach(func() {
+               s.SetupTest()
+       })
+       AfterAll(func() {
+               s.TeardownSuite()
+       })
+       AfterEach(func() {
+               s.TeardownTest()
+       })
+
+       for filename, tests := range hsiSoloTests {
+               for _, test := range tests {
+                       test := test
+                       pc := reflect.ValueOf(test).Pointer()
+                       funcValue := runtime.FuncForPC(pc)
+                       testName := filename + "/" + strings.Split(funcValue.Name(), ".")[2]
+                       It(testName, Label("SOLO"), func(ctx SpecContext) {
+                               s.Log(testName + ": BEGIN")
+                               test(&s)
+                       }, SpecTimeout(TestTimeout))
+               }
+       }
+})
+
+var _ = Describe("HsiMWSuite", Ordered, ContinueOnFailure, Serial, func() {
+       var s HsiSuite
+       BeforeAll(func() {
+               s.SetupSuite()
+       })
+       BeforeEach(func() {
+               s.SkipIfNotEnoguhCpus = true
+       })
+       AfterAll(func() {
+               s.TeardownSuite()
+       })
+       AfterEach(func() {
+               s.TeardownTest()
+       })
+
+       for filename, tests := range hsiMWTests {
+               for _, test := range tests {
+                       test := test
+                       pc := reflect.ValueOf(test).Pointer()
+                       funcValue := runtime.FuncForPC(pc)
+                       testName := filename + "/" + strings.Split(funcValue.Name(), ".")[2]
+                       It(testName, Label("SOLO", "VPP Multi-Worker"), func(ctx SpecContext) {
+                               s.Log(testName + ": BEGIN")
+                               test(&s)
+                       }, SpecTimeout(TestTimeout))
+               }
+       }
+})
index b601e46..2e9c756 100644 (file)
@@ -63,6 +63,7 @@ plugins {
   plugin quic_quicly_plugin.so { enable }
   plugin af_packet_plugin.so { enable }
   plugin hs_apps_plugin.so { enable }
+  plugin hsi_plugin.so { enable }
   plugin http_plugin.so { enable }
   plugin http_unittest_plugin.so { enable }
   plugin http_static_plugin.so { enable }
index 018c329..233ab49 100644 (file)
@@ -3,9 +3,6 @@ devices:
   - name: "cln"
     type: "netns"
 
-  - name: "srv"
-    type: "netns"
-
   - name: "hclnvpp"
     type: "veth"
     peer:
@@ -18,6 +15,5 @@ devices:
     type: "veth"
     peer:
       name: "srv"
-      netns: "srv"
       ip4:
         network: 2