aboutsummaryrefslogtreecommitdiffstats
path: root/extras
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2024-06-04 19:00:00 +0200
committerFlorin Coras <florin.coras@gmail.com>2024-06-13 06:35:26 +0000
commit82ad9660becfcdd93c906d909d7e478733c5fbbe (patch)
tree9eb2615037a0e49d87ed73dc2ca8447eeeafc32c /extras
parenteaa7d91ad77f9c6691b42b0e9f631166b4bcf44f (diff)
http: return more than url to server app
Provide all bytes as received from transport as data in the http message to server. Additionally provide offset and length of target path, target query, headers and body. Offers apis for parsing of headers, percent decoding, target path/query syntax verification. Type: improvement Change-Id: Idbe6f13afa378650cc5212ea7d3f9319183ebbbe Signed-off-by: Matus Fabian <matfabia@cisco.com>
Diffstat (limited to 'extras')
-rw-r--r--extras/hs-test/docker/Dockerfile.vpp1
-rw-r--r--extras/hs-test/hst_suite.go3
-rw-r--r--extras/hs-test/http_test.go354
-rw-r--r--extras/hs-test/utils.go23
-rw-r--r--extras/hs-test/vppinstance.go25
5 files changed, 402 insertions, 4 deletions
diff --git a/extras/hs-test/docker/Dockerfile.vpp b/extras/hs-test/docker/Dockerfile.vpp
index 9d900e86772..f87ee30c332 100644
--- a/extras/hs-test/docker/Dockerfile.vpp
+++ b/extras/hs-test/docker/Dockerfile.vpp
@@ -20,6 +20,7 @@ COPY \
$DIR/nsim_plugin.so \
$DIR/prom_plugin.so \
$DIR/tlsopenssl_plugin.so \
+ $DIR/mactime_plugin.so \
/usr/lib/x86_64-linux-gnu/vpp_plugins/
COPY vpp-data/bin/vpp /usr/bin/
diff --git a/extras/hs-test/hst_suite.go b/extras/hs-test/hst_suite.go
index e68c9c77aa8..0bdaad28ef5 100644
--- a/extras/hs-test/hst_suite.go
+++ b/extras/hs-test/hst_suite.go
@@ -6,6 +6,7 @@ import (
"flag"
"fmt"
"github.com/onsi/gomega/gmeasure"
+ "gopkg.in/yaml.v3"
"io"
"log"
"os"
@@ -16,7 +17,6 @@ import (
"github.com/edwarnicke/exechelper"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
- "gopkg.in/yaml.v3"
)
const (
@@ -391,6 +391,7 @@ func (s *HstSuite) configureNetworkTopology(topologyName string) {
}
for _, nc := range s.netConfigs {
+ s.log(nc.Name())
if err := nc.configure(); err != nil {
Fail("Network config error: " + fmt.Sprint(err))
}
diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go
index baf3e5e1298..ca8b618a7b2 100644
--- a/extras/hs-test/http_test.go
+++ b/extras/hs-test/http_test.go
@@ -1,6 +1,7 @@
package main
import (
+ "bytes"
"fmt"
"github.com/onsi/gomega/gmeasure"
"io"
@@ -17,7 +18,12 @@ func init() {
registerNoTopoTests(NginxHttp3Test, NginxAsServerTest,
NginxPerfCpsTest, NginxPerfRpsTest, NginxPerfWrkTest, HeaderServerTest,
HttpStaticMovedTest, HttpStaticNotFoundTest, HttpCliMethodNotAllowedTest,
- HttpCliBadRequestTest, HttpStaticPathTraversalTest)
+ HttpCliBadRequestTest, HttpStaticBuildInUrlGetIfStatsTest, HttpStaticBuildInUrlPostIfStatsTest,
+ HttpInvalidRequestLineTest, HttpMethodNotImplementedTest, HttpInvalidHeadersTest,
+ HttpContentLengthTest, HttpStaticBuildInUrlGetIfListTest, HttpStaticBuildInUrlGetVersionTest,
+ HttpStaticMacTimeTest, HttpStaticBuildInUrlGetVersionVerboseTest, HttpVersionNotSupportedTest,
+ HttpInvalidContentLengthTest, HttpInvalidTargetSyntaxTest, HttpStaticPathTraversalTest, HttpUriDecodeTest,
+ HttpHeadersTest)
registerNoTopoSoloTests(HttpStaticPromTest, HttpTpsTest)
}
@@ -37,7 +43,6 @@ func httpDownloadBenchmark(s *HstSuite, experiment *gmeasure.Experiment, data in
_, err = io.ReadAll(resp.Body)
duration := time.Since(t)
experiment.RecordValue("Download Speed", (float64(resp.ContentLength)/1024/1024)/duration.Seconds(), gmeasure.Units("MB/s"), gmeasure.Precision(2))
-
}
func HttpTpsTest(s *NoTopoSuite) {
@@ -197,6 +202,351 @@ func HttpCliBadRequestTest(s *NoTopoSuite) {
s.assertEqual(400, resp.StatusCode)
}
+func HttpStaticBuildInUrlGetVersionTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/version.json", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(200, resp.StatusCode)
+ data, err := io.ReadAll(resp.Body)
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(string(data), "vpp_details")
+ s.assertContains(string(data), "version")
+ s.assertContains(string(data), "build_date")
+ s.assertNotContains(string(data), "build_by")
+ s.assertNotContains(string(data), "build_host")
+ s.assertNotContains(string(data), "build_dir")
+}
+
+func HttpStaticBuildInUrlGetVersionVerboseTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/version.json?verbose=true", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(200, resp.StatusCode)
+ data, err := io.ReadAll(resp.Body)
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(string(data), "vpp_details")
+ s.assertContains(string(data), "version")
+ s.assertContains(string(data), "build_date")
+ s.assertContains(string(data), "build_by")
+ s.assertContains(string(data), "build_host")
+ s.assertContains(string(data), "build_dir")
+}
+
+func HttpStaticBuildInUrlGetIfListTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/interface_list.json", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(200, resp.StatusCode)
+ data, err := io.ReadAll(resp.Body)
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(string(data), "interface_list")
+ s.assertContains(string(data), s.getInterfaceByName(tapInterfaceName).peer.Name())
+}
+
+func HttpStaticBuildInUrlGetIfStatsTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/interface_stats.json", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(200, resp.StatusCode)
+ data, err := io.ReadAll(resp.Body)
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(string(data), "interface_stats")
+ s.assertContains(string(data), "local0")
+ s.assertContains(string(data), s.getInterfaceByName(tapInterfaceName).peer.Name())
+}
+
+func validatePostInterfaceStats(s *NoTopoSuite, data string) {
+ s.assertContains(data, "interface_stats")
+ s.assertContains(data, s.getInterfaceByName(tapInterfaceName).peer.Name())
+ s.assertNotContains(data, "error")
+ s.assertNotContains(data, "local0")
+}
+
+func HttpStaticBuildInUrlPostIfStatsTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
+ body := []byte(s.getInterfaceByName(tapInterfaceName).peer.Name())
+
+ client := newHttpClient()
+ req, err := http.NewRequest("POST",
+ "http://"+serverAddress+":80/interface_stats.json", bytes.NewBuffer(body))
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(200, resp.StatusCode)
+ data, err := io.ReadAll(resp.Body)
+ s.assertNil(err, fmt.Sprint(err))
+ validatePostInterfaceStats(s, string(data))
+}
+
+func HttpStaticMacTimeTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
+ s.log(vpp.vppctl("mactime enable-disable " + s.getInterfaceByName(tapInterfaceName).peer.Name()))
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/mactime.json", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(200, resp.StatusCode)
+ data, err := io.ReadAll(resp.Body)
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(string(data), "mactime")
+ s.assertContains(string(data), s.getInterfaceByName(tapInterfaceName).ip4AddressString())
+ s.assertContains(string(data), s.getInterfaceByName(tapInterfaceName).hwAddress.String())
+}
+
+func HttpInvalidRequestLineTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ vpp.vppctl("http cli server")
+
+ resp, err := tcpSendReceive(serverAddress+":80", "GET / HTTP/1.1")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "invalid framing not allowed")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET / HTTP/1.1\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "invalid framing not allowed")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "HTTP-version must be present")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "request-target must be present")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "request-target must be present")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET / HTTP/x\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "'HTTP/x' invalid http version not allowed")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET / HTTP1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "'HTTP1.1' invalid http version not allowed")
+}
+
+func HttpInvalidTargetSyntaxTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
+
+ resp, err := tcpSendReceive(serverAddress+":80", "GET /interface|stats.json HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "'|' not allowed in target path")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /interface#stats.json HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "'#' not allowed in target path")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /interface%stats.json HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request",
+ "after '%' there must be two hex-digit characters in target path")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /interface%1stats.json HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request",
+ "after '%' there must be two hex-digit characters in target path")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /interface%Bstats.json HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request",
+ "after '%' there must be two hex-digit characters in target path")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /interface%stats.json%B HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request",
+ "after '%' there must be two hex-digit characters in target path")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /version.json?verbose>true HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "'>' not allowed in target query")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /version.json?verbose%true HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request",
+ "after '%' there must be two hex-digit characters in target query")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /version.json?verbose=%1 HTTP/1.1\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request",
+ "after '%' there must be two hex-digit characters in target query")
+}
+
+func HttpInvalidContentLengthTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ vpp.vppctl("http cli server")
+
+ resp, err := tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nContent-Length:\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "Content-Length value must be present")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nContent-Length: \r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "Content-Length value must be present")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nContent-Length: a\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request",
+ "Content-Length value other than digit not allowed")
+}
+
+func HttpContentLengthTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
+ ifName := s.getInterfaceByName(tapInterfaceName).peer.Name()
+
+ resp, err := tcpSendReceive(serverAddress+":80",
+ "POST /interface_stats.json HTTP/1.1\r\nContent-Length:4\r\n\r\n"+ifName)
+ s.assertNil(err, fmt.Sprint(err))
+ validatePostInterfaceStats(s, resp)
+
+ resp, err = tcpSendReceive(serverAddress+":80",
+ "POST /interface_stats.json HTTP/1.1\r\n Content-Length: 4 \r\n\r\n"+ifName)
+ s.assertNil(err, fmt.Sprint(err))
+ validatePostInterfaceStats(s, resp)
+
+ resp, err = tcpSendReceive(serverAddress+":80",
+ "POST /interface_stats.json HTTP/1.1\r\n\tContent-Length:\t\t4\r\n\r\n"+ifName)
+ s.assertNil(err, fmt.Sprint(err))
+ validatePostInterfaceStats(s, resp)
+}
+
+func HttpMethodNotImplementedTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ vpp.vppctl("http cli server")
+
+ client := newHttpClient()
+ req, err := http.NewRequest("OPTIONS", "http://"+serverAddress+":80/show/version", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(501, resp.StatusCode)
+}
+
+func HttpVersionNotSupportedTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ vpp.vppctl("http cli server")
+
+ resp, err := tcpSendReceive(serverAddress+":80", "GET / HTTP/2\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 505 HTTP Version Not Supported")
+}
+
+func HttpUriDecodeTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ vpp.vppctl("http cli server")
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/sh%6fw%20versio%6E%20verbose", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(200, resp.StatusCode)
+ data, err := io.ReadAll(resp.Body)
+ s.assertNil(err, fmt.Sprint(err))
+ s.log(string(data))
+ s.assertNotContains(string(data), "unknown input")
+ s.assertContains(string(data), "Compiler")
+}
+
+func HttpHeadersTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ vpp.vppctl("http cli server")
+
+ resp, err := tcpSendReceive(
+ serverAddress+":80",
+ "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent:test\r\nAccept:text/xml\r\nAccept:\ttext/plain\t \r\nAccept:text/html\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 200 OK")
+ s.assertContains(resp, "Content-Type: text / plain")
+ s.assertNotContains(resp, "<html>", "html content received instead of plain text")
+}
+
+func HttpInvalidHeadersTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ vpp.vppctl("http cli server")
+
+ resp, err := tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nUser-Agent: test\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "Header section must end with CRLF CRLF")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser@Agent:test\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "'@' not allowed in field name")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "incomplete field line not allowed")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\n: test\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "empty field name not allowed")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\rUser-Agent:test\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "invalid field line end not allowed")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\nUser-Agent:test\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "invalid field line end not allowed")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent:\r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "empty field value not allowed")
+
+ resp, err = tcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent: \r\n\r\n")
+ s.assertNil(err, fmt.Sprint(err))
+ s.assertContains(resp, "HTTP/1.1 400 Bad Request", "empty field value not allowed")
+}
+
func HeaderServerTest(s *NoTopoSuite) {
vpp := s.getContainerByName("vpp").vppInstance
serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
diff --git a/extras/hs-test/utils.go b/extras/hs-test/utils.go
index d250dc64519..b61ac4271d6 100644
--- a/extras/hs-test/utils.go
+++ b/extras/hs-test/utils.go
@@ -3,6 +3,7 @@ package main
import (
"fmt"
"io"
+ "net"
"net/http"
"os"
"strings"
@@ -94,3 +95,25 @@ func newHttpClient() *http.Client {
}}
return client
}
+
+func tcpSendReceive(address, data string) (string, error) {
+ conn, err := net.DialTimeout("tcp", address, time.Second*30)
+ if err != nil {
+ return "", err
+ }
+ defer conn.Close()
+ err = conn.SetDeadline(time.Now().Add(time.Second * 30))
+ if err != nil {
+ return "", err
+ }
+ _, err = conn.Write([]byte(data))
+ if err != nil {
+ return "", err
+ }
+ reply := make([]byte, 1024)
+ _, err = conn.Read(reply)
+ if err != nil {
+ return "", err
+ }
+ return string(reply), nil
+}
diff --git a/extras/hs-test/vppinstance.go b/extras/hs-test/vppinstance.go
index 8a92776894c..4b2c7551034 100644
--- a/extras/hs-test/vppinstance.go
+++ b/extras/hs-test/vppinstance.go
@@ -3,7 +3,9 @@ package main
import (
"context"
"fmt"
+ "go.fd.io/govpp/binapi/ethernet_types"
"io"
+ "net"
"os"
"os/exec"
"os/signal"
@@ -64,6 +66,7 @@ plugins {
plugin tlsopenssl_plugin.so { enable }
plugin ping_plugin.so { enable }
plugin nsim_plugin.so { enable }
+ plugin mactime_plugin.so { enable }
}
logging {
@@ -395,6 +398,21 @@ func (vpp *VppInstance) createTap(
if err = api.RetvalToVPPApiError(reply.Retval); err != nil {
return err
}
+ tap.peer.index = reply.SwIfIndex
+
+ // Get name and mac
+ if err := vpp.apiStream.SendMsg(&interfaces.SwInterfaceDump{
+ SwIfIndex: reply.SwIfIndex,
+ }); err != nil {
+ return err
+ }
+ replymsg, err = vpp.apiStream.RecvMsg()
+ if err != nil {
+ return err
+ }
+ ifDetails := replymsg.(*interfaces.SwInterfaceDetails)
+ tap.peer.name = ifDetails.InterfaceName
+ tap.peer.hwAddress = ifDetails.L2Address
// Add address
addAddressReq := &interfaces.SwInterfaceAddDelAddress{
@@ -421,7 +439,6 @@ func (vpp *VppInstance) createTap(
SwIfIndex: reply.SwIfIndex,
Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
}
-
vpp.getSuite().log("set tap interface " + tap.Name() + " up")
if err := vpp.apiStream.SendMsg(upReq); err != nil {
return err
@@ -435,6 +452,12 @@ func (vpp *VppInstance) createTap(
return err
}
+ // Get host mac
+ netIntf, err := net.InterfaceByName(tap.Name())
+ if err == nil {
+ tap.hwAddress, _ = ethernet_types.ParseMacAddress(netIntf.HardwareAddr.String())
+ }
+
return nil
}