diff --git a/low/low.go b/low/low.go index 837b6fa1..c65c62f3 100644 --- a/low/low.go +++ b/low/low.go @@ -643,7 +643,7 @@ func ReportMempoolsState() { func CreateKni(portId uint16, core uint, name string) error { mempool := (*C.struct_rte_mempool)(CreateMempool("KNI")) if C.create_kni(C.uint16_t(portId), C.uint32_t(core), C.CString(name), mempool) != 0 { - common.WrapWithNFError(nil, "Error with KNI allocation\n", common.FailToCreateKNI) + return common.WrapWithNFError(nil, "Error with KNI allocation\n", common.FailToCreateKNI) } return nil } diff --git a/test/framework/dockerlauncher.go b/test/framework/dockerlauncher.go index 96757812..a83514f8 100644 --- a/test/framework/dockerlauncher.go +++ b/test/framework/dockerlauncher.go @@ -50,6 +50,17 @@ var ( regexp.MustCompile(`average= *(\d+\.?\d*) μs$`), regexp.MustCompile(`stddev= *(\d+\.?\d*) μs$`), } + WrkStatsRegexps = [2]*regexp.Regexp{ + regexp.MustCompile(`Requests/sec: *(\d+\.?\d*)$`), + regexp.MustCompile(`Transfer/sec: *(\d+\.?\d*)([K|M|G|T|P])B$`), + } + unitScale = map[string]float64{ + "K": 1.0, + "M": 1024.0, + "G": 1024.0 * 1024.0, + "T": 1024.0 * 1024.0 * 1024.0, + "P": 1024.0 * 1024.0 * 1024.0 * 1024.0, + } NoDeleteContainersOnExit = false username string @@ -77,6 +88,7 @@ type RunningApp struct { CoresStats []CoresInfo abs *ApacheBenchmarkStats lats *LatencyStats + wrks *WrkBenchmarkStats Logger *Logger benchStartTime time.Time benchEndTime time.Time @@ -138,9 +150,10 @@ func (app *RunningApp) testRoutine(report chan<- TestReport, done <-chan struct{ app.Status = TestRunning if app.config.Type == TestAppApacheBenchmark { app.abs = &ApacheBenchmarkStats{} - } - if app.config.Type == TestAppLatency { + } else if app.config.Type == TestAppLatency { app.lats = &LatencyStats{} + } else if app.config.Type == TestAppWrkBenchmark { + app.wrks = &WrkBenchmarkStats{} } scanner := bufio.NewScanner(logs) @@ -156,6 +169,23 @@ func (app *RunningApp) testRoutine(report chan<- TestReport, done <-chan struct{ } else if TestFailedRegexp.FindStringIndex(str) != nil { status = TestReportedFailed } else { + fillstats := func(stats []float64, rexps []*regexp.Regexp) { + for iii := range rexps { + matches := rexps[iii].FindStringSubmatch(str) + if len(matches) >= 2 { + var value float64 + n, err := fmt.Sscanf(matches[1], "%f", &value) + if err == nil && n == 1 { + stats[iii] = value + if len(matches) == 3 { + // Next match is unit letter + stats[iii] *= unitScale[matches[2]] + } + } + } + } + } + // Scan for strings specific to test application type if app.config.Type == TestAppGo { // Get cores number information for NFF-Go application @@ -175,28 +205,13 @@ func (app *RunningApp) testRoutine(report chan<- TestReport, done <-chan struct{ } } else if app.config.Type == TestAppApacheBenchmark { // Get Apache Benchmark output - for iii := range ABStatsRegexps { - matches := ABStatsRegexps[iii].FindStringSubmatch(str) - if len(matches) == 2 { - var value float32 - n, err := fmt.Sscanf(matches[1], "%f", &value) - if err == nil && n == 1 { - app.abs.Stats[iii] = value - } - } - } + fillstats(app.abs.Stats[:], ABStatsRegexps[:]) } else if app.config.Type == TestAppLatency { // Get Latency perf test output - for iii := range LatStatsRegexps { - matches := LatStatsRegexps[iii].FindStringSubmatch(str) - if len(matches) == 2 { - var value float32 - n, err := fmt.Sscanf(matches[1], "%f", &value) - if err == nil && n == 1 { - app.lats.Stats[iii] = value - } - } - } + fillstats(app.lats.Stats[:], LatStatsRegexps[:]) + } else if app.config.Type == TestAppWrkBenchmark { + // Get Wrk Benchmark output + fillstats(app.wrks.Stats[:], WrkStatsRegexps[:]) } } diff --git a/test/framework/main/perf.json b/test/framework/main/perf.json index a460a3be..31be48d5 100644 --- a/test/framework/main/perf.json +++ b/test/framework/main/perf.json @@ -17,7 +17,7 @@ "OUTPORT1_2": "1", "PKTGENCOREMASK": "0x1ff", "PKTGENPORT": "[1:2-3].0, [4-5:6].1", - "CORES": "0-43" + "CORES": "0-43" }, "tests": [ { diff --git a/test/framework/report.go b/test/framework/report.go index bed5d888..a4079cec 100644 --- a/test/framework/report.go +++ b/test/framework/report.go @@ -30,6 +30,8 @@ type TestcaseReportInfo struct { ABStats *ApacheBenchmarkStats `json:",omitempty"` // Latency type tests LatStats *LatencyStats `json:",omitempty"` + // Latency type tests + WStats *WrkBenchmarkStats `json:",omitempty"` // Per application statistics Apps []RunningApp `json:"-"` } @@ -151,7 +153,14 @@ const ( Requested speed [Pkts/sec]{{index .Stats 1}} - {{end}}{{/* end with .LatStats */}}{{end}}{{/* end if .LatStats */}} + {{end}}{{/* end with .LatStats */}}{{end}}{{/* end if .LatStats */}}{{if .WStats}}{{with .WStats}} + + + + + + +
Requests per second [#/sec]{{index .Stats 0}}
Transfer rate [Kbytes/sec] received{{index .Stats 1}}
{{end}}{{/* end with .WStats */}}{{end}}{{/* end if .WStats */}} {{range $appindex, $appelement := .Apps}} diff --git a/test/framework/report_test.go b/test/framework/report_test.go index c6c9f3c2..31770669 100644 --- a/test/framework/report_test.go +++ b/test/framework/report_test.go @@ -54,12 +54,7 @@ func testScenarios(t *testing.T, logdir string, tests []TestcaseReportInfo) { } for iii := range tests { - select { - case report.Pipe <- tests[iii]: - t.Log("Reported test", iii) - case err := <-report.Done: - t.Fatal(err) - } + report.AddTestResult(&tests[iii]) } report.FinishReport() @@ -88,6 +83,8 @@ func testManyApps(t *testing.T, testtype TestType) { appConfig[iii].Type = TestAppApacheBenchmark } else if iii == 0 && testtype == TestTypeLatency { appConfig[iii].Type = TestAppLatency + } else if iii == 0 && testtype == TestTypeWrkBenchmark { + appConfig[iii].Type = TestAppWrkBenchmark } else { appConfig[iii].Type = TestAppGo } @@ -132,11 +129,15 @@ func testManyApps(t *testing.T, testtype TestType) { } } else if appConfig[iii].Type == TestAppApacheBenchmark { apps[iii].abs = &ApacheBenchmarkStats{ - Stats: [4]float32{111.111, 222.222, 333.333, 444.444}, + Stats: [4]float64{111.111, 222.222, 333.333, 444.444}, } } else if appConfig[iii].Type == TestAppLatency { apps[iii].lats = &LatencyStats{ - Stats: [5]float32{111.111, 1000000, 222.222, 333.333, 444.444}, + Stats: [5]float64{111.111, 1000000, 222.222, 333.333, 444.444}, + } + } else if appConfig[iii].Type == TestAppWrkBenchmark { + apps[iii].wrks = &WrkBenchmarkStats{ + Stats: [2]float64{111.111, 222.222}, } } else { // appConfig[iii].Type == TestAppGo apps[iii].CoresStats = make([]CoresInfo, NUM_MEASUREMENTS) @@ -183,6 +184,13 @@ func testManyApps(t *testing.T, testtype TestType) { break } } + } else if testtype == TestTypeWrkBenchmark { + for iii := range apps { + if apps[iii].config.Type == TestAppWrkBenchmark { + tests[jjj].WStats = apps[iii].wrks + break + } + } } } @@ -204,3 +212,7 @@ func TestApacheBenchmarkManyApps(t *testing.T) { func TestLatencyManyApps(t *testing.T) { testManyApps(t, TestTypeLatency) } + +func TestWrkBenchmarkManyApps(t *testing.T) { + testManyApps(t, TestTypeWrkBenchmark) +} diff --git a/test/framework/testsuite.go b/test/framework/testsuite.go index 40c1df9f..35e40da5 100644 --- a/test/framework/testsuite.go +++ b/test/framework/testsuite.go @@ -188,6 +188,14 @@ func (config *TestsuiteConfig) executeOneTest(test *TestConfig, logdir string, break } } + } else if test.Type == TestTypeWrkBenchmark { + // Find which app has Wrk Benchmark statistics report + for iii := range apps { + if apps[iii].config.Type == TestAppWrkBenchmark { + tri.WStats = apps[iii].wrks + break + } + } } return &tri diff --git a/test/framework/types.go b/test/framework/types.go index 3b1bfbb7..914806b8 100644 --- a/test/framework/types.go +++ b/test/framework/types.go @@ -61,6 +61,7 @@ const ( TestAppPktgen TestAppApacheBenchmark TestAppLatency + TestAppWrkBenchmark ) // UnmarshalJSON unmarshals data and checks app type validity. @@ -77,6 +78,7 @@ func (at *AppType) UnmarshalJSON(data []byte) error { "TestAppPktgen": TestAppPktgen, "TestAppApacheBenchmark": TestAppApacheBenchmark, "TestAppLatency": TestAppLatency, + "TestAppWrkBenchmark": TestAppWrkBenchmark, }[s] if !ok { return fmt.Errorf("invalid AppType %q", s) @@ -91,9 +93,10 @@ type TestType int // Constants for different test types. const ( TestTypeBenchmark TestType = iota + TestTypeScenario TestTypeApacheBenchmark TestTypeLatency - TestTypeScenario + TestTypeWrkBenchmark ) // UnmarshalJSON unmarshals data and checks test type validity. @@ -107,9 +110,10 @@ func (at *TestType) UnmarshalJSON(data []byte) error { // Use map to get int keys for string values got, ok := map[string]TestType{ "TestTypeBenchmark": TestTypeBenchmark, + "TestTypeScenario": TestTypeScenario, "TestTypeApacheBenchmark": TestTypeApacheBenchmark, "TestTypeLatency": TestTypeLatency, - "TestTypeScenario": TestTypeScenario, + "TestTypeWrkBenchmark": TestTypeWrkBenchmark, }[s] if !ok { return fmt.Errorf("invalid TestType %q", s) @@ -137,16 +141,16 @@ type ReportCoresInfo struct { // Indexes in array of Apache Benchmark stats ApacheBenchmarkStats const ( - RequestsPerSecond = iota - TimePerRequest - TimePerRequestConcurrent - TransferRate + AbRequestsPerSecond = iota + AbTimePerRequest + AbTimePerRequestConcurrent + AbTransferRate ) // ApacheBenchmarkStats has info about running Apache Benchmark web // client. type ApacheBenchmarkStats struct { - Stats [4]float32 + Stats [4]float64 } // Indexes in array of latency stats LatencyStats @@ -160,7 +164,16 @@ const ( // LatencyStats has info about finished latency perf test type LatencyStats struct { - Stats [5]float32 + Stats [5]float64 +} + +const ( + WrkRequestsPerSecond = iota + WrkTransferRate +) + +type WrkBenchmarkStats struct { + Stats [2]float64 } // TestReport has info about test status and application. diff --git a/vagrant/Vagrantfile b/vagrant/Vagrantfile index 87c109a8..e84067bc 100644 --- a/vagrant/Vagrantfile +++ b/vagrant/Vagrantfile @@ -33,7 +33,7 @@ Vagrant.configure(2) do |config| config.vm.provider "libvirt" do |lv| lv.driver = "kvm" lv.memory = "4096" - lv.cpus = 8 + lv.cpus = 16 lv.storage_pool_name = "images" end @@ -52,7 +52,10 @@ sudo sed -i -e 's,biosdevname=0,biosdevname=1,' /etc/default/grub sudo sed -i -e 's,net.ifnames=0,net.ifnames=1,' /etc/default/grub sudo grub2-mkconfig -o /boot/grub2/grub.cfg -if [ $(readlink /etc/udev/rules.d/80-net-setup-link.rules) == /dev/null ] +echo Disabling SELinux +sudo sed -i -e 's,SELINUX=enforcing,SELINUX=disabled,' /etc/selinux/config + +if [ "$(readlink /etc/udev/rules.d/80-net-setup-link.rules)" == /dev/null ] then echo Fixing udev to use consistent interface names sudo rm /etc/udev/rules.d/80-net-setup-link.rules @@ -80,16 +83,21 @@ echo Reassigning "${syscon}" interface to system name sudo nmcli c mod "${syscon}" connection.id 'System connection' echo Unpacking Go language into /opt -(cd /opt; sudo sh -c 'curl -L -s https://dl.google.com/go/go1.11.1.linux-amd64.tar.gz | tar zx') +(cd /opt; sudo sh -c 'curl -L -s https://dl.google.com/go/go1.11.2.linux-amd64.tar.gz | tar zx') mkdir go chmod +x ~/scripts.sh . ~/scripts.sh echo . ~/scripts.sh >> .bashrc -setupdocker +setuptesthost -echo Downloading and building NFF-GO +echo Downloading and building NFF-GO framework go get -d -v github.com/intel-go/nff-go -(cd \"$GOPATH\"/src/github.com/intel-go/nff-go; git checkout develop; ./scripts/get-depends.sh; make) +(cd "${GOPATH}"/src/github.com/intel-go/nff-go; git checkout develop; ./scripts/get-depends.sh; make) +echo Downloading and building NFF-GO NAT example and its dependencies +go get github.com/golang/protobuf/protoc-gen-go +git clone -b develop --recurse-submodules http://github.com/intel-go/nff-go-nat +(cd nff-go-nat; . env.sh; make) +./nff-go-nat/test/httpperfserv/install-systemd-service.sh "-port 8008" echo Setting up 1024 huge pages sudo sh -c 'echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages' diff --git a/vagrant/scripts.sh b/vagrant/scripts.sh index 5b10ff00..8e199997 100644 --- a/vagrant/scripts.sh +++ b/vagrant/scripts.sh @@ -30,75 +30,11 @@ runpktgen () rc=$?; if [[ $rc == 0 ]]; then reset; fi } -# Perform transient NAT client machine configuration. It initializes -# two network interfaces and sets up default routes to the server -# network. -natclient () -{ - sudo ip route add 192.168.16.0/24 via 192.168.14.1 dev $CARD1 - sudo ip route add 192.168.26.0/24 via 192.168.24.1 dev $CARD2 -} - -# Perform one-time configuration needed for NAT client test -# machine. For it apache package is installed for apache benchmark -# program. -setupnatclient () -{ - sudo nmcli c add type ethernet ifname $CARD1 con-name $CARD1 ip4 192.168.14.2/24 - sudo nmcli c add type ethernet ifname $CARD2 con-name $CARD2 ip4 192.168.24.2/24 - sudo nmcli c up $CARD1 - sudo nmcli c up $CARD2 - - natclient - - if [ $DISTRO == Ubuntu ]; then - sudo apt-get install -y apache2 - elif [ $DISTRO == Fedora ]; then - sudo dnf -y install httpd - fi -} - -# Perform transient configuration for NAT middle machine. It -# initializes two first network interfaces for NFF-GO bindports -# command and initializes second interface pair for use with Linux -# NAT. In this setup enp0s16 is connected to server (public network) -# and enp0s9 is connected to client (private network). -natmiddle () -{ - export NFF_GO_CARDS="00:08.0 00:0a.0" - export CARD1=ens7 - export CARD2=ens9 - - bindports - - sudo sysctl -w net.ipv4.ip_forward=1 - - sudo iptables -t nat -A POSTROUTING -o $CARD2 -j MASQUERADE - sudo iptables -A FORWARD -i $CARD2 -o $CARD1 -m state --state RELATED,ESTABLISHED -j ACCEPT - sudo iptables -A FORWARD -i $CARD1 -o $CARD2 -j ACCEPT -} - -# Perform one-time configuration needed for NAT middle machine. On -# Fedora we use firewall daemon to permanently record IP forwarding -# rules. -setupnatmiddle () -{ - natmiddle - - sudo nmcli c add type ethernet ifname $CARD1 con-name $CARD1 ip4 192.168.24.1/24 - sudo nmcli c add type ethernet ifname $CARD2 con-name $CARD2 ip4 192.168.26.1/24 - sudo nmcli c up $CARD1 - sudo nmcli c up $CARD2 -} - -# Perform one-time configuration needed for NAT server side +# Perform one-time configuration needed for NAT test # machine. It installs Apache web server. -setupnatserver () +setuptesthost () { - sudo nmcli c add type ethernet ifname $CARD1 con-name $CARD1 ip4 192.168.16.2/24 - sudo nmcli c add type ethernet ifname $CARD2 con-name $CARD2 ip4 192.168.26.2/24 - sudo nmcli c up $CARD1 - sudo nmcli c up $CARD2 + setupdocker if [ $DISTRO == Ubuntu ]; then sudo apt-get install -y apache2 @@ -128,17 +64,32 @@ setupdocker () elif [ $DISTRO == Fedora ]; then sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo sudo dnf -y install docker-ce + sudo sed -i -e 's,ExecStart=/usr/bin/dockerd -H unix://,ExecStart=/usr/bin/dockerd,' /lib/systemd/system/docker.service sudo gpasswd -a vagrant docker fi + if [ ! -z "${http_proxy}" ] + then + sudo mkdir /etc/systemd/system/docker.service.d + sudo sh -c 'cat > /etc/systemd/system/docker.service.d/http-proxy.conf < /etc/docker/daemon.json <