hs-test: test vpp+nginx mirroring with tap ifaces

Type: test
Signed-off-by: Maros Ondrejicka <mondreji@cisco.com>
Change-Id: I05bbed8fd9d40929f040574044aed5292a475e91
This commit is contained in:
Maros Ondrejicka
2023-02-27 13:22:45 +01:00
committed by Florin Coras
parent b0116a13dc
commit c2f76f4590
13 changed files with 281 additions and 16 deletions

View File

@ -121,12 +121,22 @@ func (c *Container) GetContainerWorkDir() (res string) {
return
}
func (c *Container) getRunCommand() string {
cmd := "docker run --cap-add=all -d --privileged --network host --rm"
cmd += c.getVolumesAsCliOption()
cmd += c.getEnvVarsAsCliOption()
cmd += " --name " + c.name + " " + c.image + " " + c.extraRunningArgs
return cmd
func (c *Container) getContainerArguments() string {
args := "--cap-add=all --privileged --network host --rm"
args += c.getVolumesAsCliOption()
args += c.getEnvVarsAsCliOption()
args += " --name " + c.name + " " + c.image
return args
}
func (c *Container) create() {
cmd := "docker create " + c.getContainerArguments()
exechelper.Run(cmd)
}
func (c *Container) start() {
cmd := "docker start " + c.name
exechelper.Run(cmd)
}
func (c *Container) run() error {
@ -134,7 +144,8 @@ func (c *Container) run() error {
return fmt.Errorf("run container failed: name is blank")
}
cmd := c.getRunCommand()
cmd := "docker run -d " + c.getContainerArguments() + " " + c.extraRunningArgs
c.Suite().log(cmd)
err := exechelper.Run(cmd)
if err != nil {
return fmt.Errorf("container run failed: %s", err)
@ -273,6 +284,14 @@ func (c *Container) saveLogs() {
f.Close()
}
func (c *Container) log() string {
cmd := "docker logs " + c.name
c.Suite().log(cmd)
o, err := exechelper.CombinedOutput(cmd)
c.Suite().assertNil(err)
return string(o)
}
func (c *Container) stop() error {
if c.vppInstance != nil && c.vppInstance.apiChannel != nil {
c.vppInstance.saveLogs()

View File

@ -0,0 +1,12 @@
ARG UBUNTU_VERSION
FROM ubuntu:${UBUNTU_VERSION}
RUN apt-get update \
&& apt-get install -y nginx \
&& rm -rf /var/lib/apt/lists/*
COPY resources/nginx/nginx_server_mirroring.conf /nginx.conf
ENTRYPOINT ["nginx", "-c", "/nginx.conf"]

View File

@ -25,3 +25,8 @@ func TestNoTopo(t *testing.T) {
var m NoTopoSuite
suite.Run(t, &m)
}
func TestNginx(t *testing.T) {
var m NginxSuite
suite.Run(t, &m)
}

View File

@ -48,8 +48,7 @@ func (s *NoTopoSuite) TestNginxAsServer() {
s.assertNil(nginxCont.run())
vpp := s.getContainerByName("vpp").vppInstance
err := vpp.waitForApp("-app", 5)
s.assertNil(err)
vpp.waitForApp("-app", 5)
serverAddress := s.netInterfaces[tapInterfaceName].Peer().IP4AddressString()
@ -86,8 +85,7 @@ func runNginxPerf(s *NoTopoSuite, mode, ab_or_wrk string) error {
nginxCont := s.getContainerByName("nginx")
s.assertNil(nginxCont.run())
err := vpp.waitForApp("-app", 5)
s.assertNil(err)
vpp.waitForApp("-app", 5)
cmd := exec.Command(exeName, args...)
s.log(cmd)

View File

@ -0,0 +1,23 @@
package main
import (
"github.com/edwarnicke/exechelper"
)
func (s *NginxSuite) TestMirroring() {
proxyAddress := s.netInterfaces[mirroringClientInterfaceName].Peer().IP4AddressString()
path := "/64B.json"
testCommand := "wrk -c 20 -t 10 -d 40 http://" + proxyAddress + ":80" + path
s.log(testCommand)
o, _ := exechelper.Output(testCommand)
s.log(string(o))
s.assertNotEmpty(o)
// Check if log output from VPP contains 'no lcl port' warnings
// TODO: Need to change after adding session worker counter
vppProxyContainer := s.getContainerByName(vppProxyContainerName)
logContent := vppProxyContainer.log()
s.assertNotContains(logContent, "no lcl port")
}

View File

@ -0,0 +1,82 @@
user root;
worker_processes 4;
worker_rlimit_nofile 102400;
daemon off;
events {
use epoll;
worker_connections 102400;
accept_mutex off;
}
http {
include mime.types;
default_type application/octet-stream;
access_log off;
keepalive_timeout 300;
keepalive_requests 1000000;
proxy_connect_timeout 300;
large_client_header_buffers 4 512k;
client_max_body_size 3000m;
client_header_buffer_size 2048m;
client_body_buffer_size 1024m;
proxy_buffers 16 10240k;
proxy_buffer_size 10240k;
gzip on;
upstream bk {
server 10.10.2.1:8091;
keepalive 30000;
}
upstream bk1 {
server 10.10.2.1:8092;
keepalive 30000;
}
upstream bk2 {
server 10.10.2.1:8093;
keepalive 30000;
}
server {
listen 80;
server_name 10.10.1.2;
server_tokens off;
proxy_redirect off;
location / {
root html;
index index.html index.htm;
proxy_pass http://bk;
proxy_set_header Connection "";
proxy_set_header X-Original-URI $request_uri;
proxy_set_header Host $host:$server_port;
chunked_transfer_encoding on;
proxy_http_version 1.1;
mirror /mimic1;
mirror /mimic2;
mirror_request_body on;
}
location /mimic1 {
proxy_pass http://bk1$request_uri;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header Connection "";
chunked_transfer_encoding on;
proxy_http_version 1.1;
proxy_set_header Host $host:$server_port;
}
location /mimic2 {
proxy_pass http://bk2$request_uri;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header Host $host:$server_port;
proxy_set_header Connection "";
proxy_http_version 1.1;
chunked_transfer_encoding on;
}
}
}

View File

@ -0,0 +1,32 @@
master_process on;
worker_rlimit_nofile 10240;
worker_processes 2;
daemon off;
events {
use epoll;
worker_connections 10240;
accept_mutex off;
multi_accept off;
}
http {
keepalive_timeout 300s;
keepalive_requests 1000000;
sendfile on;
server {
listen 8091;
listen 8092;
listen 8093;
root /usr/share/nginx;
index index.html index.htm;
location /return_ok
{
return 200 '';
}
location /64B.json
{
return 200 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
}
}
}

View File

@ -61,3 +61,4 @@ docker_build () {
docker_build hs-test/vpp vpp
docker_build hs-test/nginx-ldp nginx
docker_build hs-test/nginx-server nginx-server

View File

@ -0,0 +1,50 @@
package main
const (
// These correspond to names used in yaml config
mirroringClientInterfaceName = "hst_client"
mirroringServerInterfaceName = "hst_server"
vppProxyContainerName = "vpp-proxy"
nginxProxyContainerName = "nginx-proxy"
nginxServerContainerName = "nginx-server"
)
type NginxSuite struct {
HstSuite
}
func (s *NginxSuite) SetupSuite() {
s.loadNetworkTopology("2taps")
s.loadContainerTopology("nginxProxyAndServer")
}
func (s *NginxSuite) SetupTest() {
s.SetupVolumes()
s.SetupContainers()
// Setup test conditions
var startupConfig Stanza
startupConfig.
NewStanza("session").
Append("enable").
Append("use-app-socket-api").Close()
// ... for proxy
vppProxyContainer := s.getContainerByName(vppProxyContainerName)
proxyVpp, _ := vppProxyContainer.newVppInstance(startupConfig)
proxyVpp.start()
clientInterface := s.netInterfaces[mirroringClientInterfaceName]
proxyVpp.createTap(clientInterface, 1)
serverInterface := s.netInterfaces[mirroringServerInterfaceName]
proxyVpp.createTap(serverInterface, 2)
nginxContainer := s.getTransientContainerByName(nginxProxyContainerName)
nginxContainer.create()
nginxContainer.copy("./resources/nginx/nginx_proxy_mirroring.conf", "/nginx.conf")
nginxContainer.start()
proxyVpp.waitForApp("-app", 5)
}

View File

@ -35,5 +35,5 @@ func (s *NoTopoSuite) SetupTest() {
tapInterface := s.netInterfaces[tapInterfaceName]
vpp.createTap(1, tapInterface)
vpp.createTap(tapInterface)
}

View File

@ -0,0 +1,20 @@
---
volumes:
- volume: &shared-vol-proxy
host-dir: /tmp/shared-vol-proxy
containers:
- name: "vpp-proxy"
volumes:
- <<: *shared-vol-proxy
container-dir: "/tmp/vpp"
is-default-work-dir: true
- name: "nginx-proxy"
volumes:
- <<: *shared-vol-proxy
container-dir: "/tmp/nginx"
is-default-work-dir: true
image: "hs-test/nginx-ldp"
is-optional: true
- name: "nginx-server"
image: "hs-test/nginx-server"

View File

@ -0,0 +1,18 @@
---
devices:
- name: "hst_client"
type: "tap"
ip4:
network: 1
peer:
name: ""
ip4:
network: 1
- name: "hst_server"
type: "tap"
ip4:
network: 2
peer:
name: ""
ip4:
network: 2

View File

@ -160,15 +160,16 @@ func (vpp *VppInstance) vppctl(command string, arguments ...any) string {
return string(output)
}
func (vpp *VppInstance) waitForApp(appName string, timeout int) error {
func (vpp *VppInstance) waitForApp(appName string, timeout int) {
for i := 0; i < timeout; i++ {
o := vpp.vppctl("show app")
if strings.Contains(o, appName) {
return nil
return
}
time.Sleep(1 * time.Second)
}
return fmt.Errorf("timeout while waiting for app '%s'", appName)
vpp.Suite().assertNil(1, "Timeout while waiting for app '%s'", appName)
return
}
func (vpp *VppInstance) createAfPacket(
@ -253,9 +254,13 @@ func (vpp *VppInstance) addAppNamespace(
}
func (vpp *VppInstance) createTap(
id uint32,
tap *NetInterface,
tapId ...uint32,
) error {
var id uint32 = 1
if len(tapId) > 0 {
id = tapId[0]
}
createTapReq := &tapv2.TapCreateV2{
ID: id,
HostIfNameSet: true,