From 229f5fcf188cf710f4a8fb269d92f1a1d04a99da Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Tue, 9 Aug 2022 14:44:47 +0000 Subject: misc: add test framework for host stack Type: feature Signed-off-by: Filip Tehlar Change-Id: I5a64a2c095cae3a4d5f8fdc73e624b010339ec8e --- extras/hs-test/actions.go | 268 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100755 extras/hs-test/actions.go (limited to 'extras/hs-test/actions.go') diff --git a/extras/hs-test/actions.go b/extras/hs-test/actions.go new file mode 100755 index 00000000000..aa82f49c4c0 --- /dev/null +++ b/extras/hs-test/actions.go @@ -0,0 +1,268 @@ +package main + +import ( + "bytes" + "context" + "fmt" + "os" + "path/filepath" + + "git.fd.io/govpp.git/api" + "github.com/edwarnicke/exechelper" + "github.com/edwarnicke/govpp/binapi/af_packet" + interfaces "github.com/edwarnicke/govpp/binapi/interface" + "github.com/edwarnicke/govpp/binapi/interface_types" + ip_types "github.com/edwarnicke/govpp/binapi/ip_types" + "github.com/edwarnicke/govpp/binapi/session" + "github.com/edwarnicke/govpp/binapi/vlib" + "github.com/edwarnicke/vpphelper" +) + +func RegisterActions() { + cfgTable = make(map[string]func([]string) *ActionResult) + reg("echo-srv-internal", Configure2Veths) + reg("echo-cln-internal", Configure2Veths) + reg("echo-client", RunEchoClient) + reg("echo-server", RunEchoServer) + reg("vpp-proxy", ConfigureVppProxy) + reg("vpp-envoy", ConfigureEnvoyProxy) + reg("http-tps", ConfigureHttpTps) + reg("2veths", Configure2Veths) +} + +func configureProxyTcp(ifName0, ipAddr0, ifName1, ipAddr1 string) ConfFn { + return func(ctx context.Context, + vppConn api.Connection) error { + + _, err := configureAfPacket(ctx, vppConn, ifName0, ipAddr0) + if err != nil { + fmt.Printf("failed to create af packet: %v", err) + return err + } + _, err = configureAfPacket(ctx, vppConn, ifName1, ipAddr1) + if err != nil { + fmt.Printf("failed to create af packet: %v", err) + return err + } + return nil + } +} + +func ConfigureVppProxy(args []string) *ActionResult { + ctx, cancel := newVppContext() + defer cancel() + + con, vppErrCh := vpphelper.StartAndDialContext(ctx, vpphelper.WithVppConfig(configTemplate)) + exitOnErrCh(ctx, cancel, vppErrCh) + + confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24") + err := confFn(ctx, con) + if err != nil { + return NewActionResult(err, ActionResultWithDesc("configuration failed")) + } + writeSyncFile(OkResult()) + <-ctx.Done() + return nil +} + +func ConfigureEnvoyProxy(args []string) *ActionResult { + var startup Stanza + startup. + NewStanza("session"). + Append("enable"). + Append("use-app-socket-api"). + Append("evt_qs_memfd_seg"). + Append("event-queue-length 100000").Close() + ctx, cancel := newVppContext() + defer cancel() + + con, vppErrCh := vpphelper.StartAndDialContext(ctx, + vpphelper.WithVppConfig(configTemplate+startup.ToString()), + vpphelper.WithRootDir("/tmp/vpp-envoy")) + exitOnErrCh(ctx, cancel, vppErrCh) + + confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24") + err := confFn(ctx, con) + if err != nil { + return NewActionResult(err, ActionResultWithDesc("configuration failed")) + } + err0 := exechelper.Run("chmod 777 -R /tmp/vpp-envoy") + if err0 != nil { + return NewActionResult(err, ActionResultWithDesc("setting permissions failed")) + } + writeSyncFile(OkResult()) + <-ctx.Done() + return nil +} + +func getArgs() string { + s := "" + for i := 2; i < len(os.Args); i++ { + s = s + " " + os.Args[i] + } + return s +} + +func ApiCliInband(root, cmd string) *ActionResult { + ctx, _ := newVppContext() + con := vpphelper.DialContext(ctx, filepath.Join(root, "/var/run/vpp/api.sock")) + cliInband := vlib.CliInband{Cmd: cmd} + cliInbandReply, err := vlib.NewServiceClient(con).CliInband(ctx, &cliInband) + return NewActionResult(err, ActionResultWithStdout(cliInbandReply.Reply)) +} + +func RunEchoClient(args []string) *ActionResult { + outBuff := bytes.NewBuffer([]byte{}) + errBuff := bytes.NewBuffer([]byte{}) + + cmd := fmt.Sprintf("vpp_echo client socket-name /tmp/echo-cln/var/run/app_ns_sockets/2 use-app-socket-api uri %s://10.10.10.1/12344", args[2]) + err := exechelper.Run(cmd, + exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff), + exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr)) + + return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())), + ActionResultWithStderr(string(errBuff.String()))) +} + +func RunEchoServer(args []string) *ActionResult { + cmd := fmt.Sprintf("vpp_echo server TX=RX socket-name /tmp/echo-srv/var/run/app_ns_sockets/1 use-app-socket-api uri %s://10.10.10.1/12344", args[2]) + errCh := exechelper.Start(cmd) + select { + case err := <-errCh: + writeSyncFile(NewActionResult(err, ActionResultWithDesc("echo_server: "))) + default: + } + writeSyncFile(OkResult()) + return nil +} + +func RunEchoSrvInternal() *ActionResult { + cmd := fmt.Sprintf("test echo server %s uri tcp://10.10.10.1/1234", getArgs()) + return ApiCliInband("/tmp/2veths", cmd) +} + +func RunEchoClnInternal() *ActionResult { + cmd := fmt.Sprintf("test echo client %s uri tcp://10.10.10.1/1234", getArgs()) + return ApiCliInband("/tmp/2veths", cmd) +} +func configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64) ConfFn { + return func(ctx context.Context, + vppConn api.Connection) error { + + swIfIndex, err := configureAfPacket(ctx, vppConn, ifName, interfaceAddress) + if err != nil { + fmt.Printf("failed to create af packet: %v", err) + } + _, er := session.NewServiceClient(vppConn).AppNamespaceAddDelV2(ctx, &session.AppNamespaceAddDelV2{ + Secret: secret, + SwIfIndex: swIfIndex, + NamespaceID: namespaceId, + }) + if er != nil { + fmt.Printf("add app namespace: %v", err) + return err + } + + _, er1 := session.NewServiceClient(vppConn).SessionEnableDisable(ctx, &session.SessionEnableDisable{ + IsEnable: true, + }) + if er1 != nil { + fmt.Printf("session enable %v", err) + return err + } + return nil + } +} + +func Configure2Veths(args []string) *ActionResult { + var startup Stanza + startup. + NewStanza("session"). + Append("enable"). + Append("use-app-socket-api").Close() + + ctx, cancel := newVppContext() + defer cancel() + con, vppErrCh := vpphelper.StartAndDialContext(ctx, + vpphelper.WithVppConfig(configTemplate+startup.ToString()), + vpphelper.WithRootDir(fmt.Sprintf("/tmp/%s", args[1]))) + exitOnErrCh(ctx, cancel, vppErrCh) + + var fn func(context.Context, api.Connection) error + if args[2] == "srv" { + fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1) + } else { + fn = configure2vethsTopo("vppcln", "10.10.10.2/24", "2", 2) + } + err := fn(ctx, con) + if err != nil { + return NewActionResult(err, ActionResultWithDesc("configuration failed")) + } + writeSyncFile(OkResult()) + <-ctx.Done() + return nil +} + +func configureAfPacket(ctx context.Context, vppCon api.Connection, + name, interfaceAddress string) (interface_types.InterfaceIndex, error) { + ifaceClient := interfaces.NewServiceClient(vppCon) + afPacketCreate := &af_packet.AfPacketCreateV2{ + UseRandomHwAddr: true, + HostIfName: name, + NumRxQueues: 1, + } + afPacketCreateRsp, err := af_packet.NewServiceClient(vppCon).AfPacketCreateV2(ctx, afPacketCreate) + if err != nil { + fmt.Printf("failed to create af packet: %v", err) + return 0, err + } + _, err = ifaceClient.SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{ + SwIfIndex: afPacketCreateRsp.SwIfIndex, + Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP, + }) + if err != nil { + fmt.Printf("set interface state up failed: %v\n", err) + return 0, err + } + ipPrefix, err := ip_types.ParseAddressWithPrefix(interfaceAddress) + if err != nil { + fmt.Printf("parse ip address %v\n", err) + return 0, err + } + ipAddress := &interfaces.SwInterfaceAddDelAddress{ + IsAdd: true, + SwIfIndex: afPacketCreateRsp.SwIfIndex, + Prefix: ipPrefix, + } + _, errx := ifaceClient.SwInterfaceAddDelAddress(ctx, ipAddress) + if errx != nil { + fmt.Printf("add ip address %v\n", err) + return 0, err + } + return afPacketCreateRsp.SwIfIndex, nil +} + +func ConfigureHttpTps(args []string) *ActionResult { + ctx, cancel := newVppContext() + defer cancel() + con, vppErrCh := vpphelper.StartAndDialContext(ctx, + vpphelper.WithVppConfig(configTemplate)) + exitOnErrCh(ctx, cancel, vppErrCh) + + confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24") + err := confFn(ctx, con) + if err != nil { + return NewActionResult(err, ActionResultWithDesc("configuration failed")) + } + + _, err = session.NewServiceClient(con).SessionEnableDisable(ctx, &session.SessionEnableDisable{ + IsEnable: true, + }) + if err != nil { + return NewActionResult(err, ActionResultWithDesc("configuration failed")) + } + Vppcli("", "http tps uri tcp://0.0.0.0/8080") + writeSyncFile(OkResult()) + <-ctx.Done() + return nil +} -- cgit 1.2.3-korg