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:

committed by
Florin Coras

parent
b0116a13dc
commit
c2f76f4590
@ -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()
|
||||
|
12
extras/hs-test/docker/Dockerfile.nginx-server
Normal file
12
extras/hs-test/docker/Dockerfile.nginx-server
Normal 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"]
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
23
extras/hs-test/mirroring_test.go
Normal file
23
extras/hs-test/mirroring_test.go
Normal 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")
|
||||
}
|
82
extras/hs-test/resources/nginx/nginx_proxy_mirroring.conf
Normal file
82
extras/hs-test/resources/nginx/nginx_proxy_mirroring.conf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
32
extras/hs-test/resources/nginx/nginx_server_mirroring.conf
Normal file
32
extras/hs-test/resources/nginx/nginx_server_mirroring.conf
Normal 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';
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
50
extras/hs-test/suite_nginx_test.go
Normal file
50
extras/hs-test/suite_nginx_test.go
Normal 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)
|
||||
}
|
@ -35,5 +35,5 @@ func (s *NoTopoSuite) SetupTest() {
|
||||
|
||||
tapInterface := s.netInterfaces[tapInterfaceName]
|
||||
|
||||
vpp.createTap(1, tapInterface)
|
||||
vpp.createTap(tapInterface)
|
||||
}
|
||||
|
20
extras/hs-test/topo-containers/nginxProxyAndServer.yaml
Normal file
20
extras/hs-test/topo-containers/nginxProxyAndServer.yaml
Normal 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"
|
18
extras/hs-test/topo-network/2taps.yaml
Normal file
18
extras/hs-test/topo-network/2taps.yaml
Normal 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
|
@ -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,
|
||||
|
Reference in New Issue
Block a user