993c86f339
Type: style Signed-off-by: Filip Tehlar <ftehlar@cisco.com> Change-Id: Ia87b28e81b6fd06c8c3681bf3cb1dd6ce8c84f41
410 lines
12 KiB
Go
410 lines
12 KiB
Go
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"
|
|
"github.com/edwarnicke/govpp/binapi/ethernet_types"
|
|
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/tapv2"
|
|
"github.com/edwarnicke/govpp/binapi/vlib"
|
|
"github.com/edwarnicke/vpphelper"
|
|
)
|
|
|
|
var (
|
|
workDir, _ = os.Getwd()
|
|
)
|
|
|
|
type ConfFn func(context.Context, api.Connection) error
|
|
|
|
type Actions struct {
|
|
}
|
|
|
|
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 (a *Actions) RunHttpCliSrv(args []string) *ActionResult {
|
|
cmd := fmt.Sprintf("http cli server")
|
|
return ApiCliInband(workDir, cmd)
|
|
}
|
|
|
|
func (a *Actions) RunHttpCliCln(args []string) *ActionResult {
|
|
cmd := fmt.Sprintf("http cli client uri http://10.10.10.1/80 query %s", getArgs())
|
|
fmt.Println(cmd)
|
|
return ApiCliInband(workDir, cmd)
|
|
}
|
|
|
|
func (a *Actions) ConfigureVppProxy(args []string) *ActionResult {
|
|
ctx, cancel := newVppContext()
|
|
defer cancel()
|
|
|
|
con, vppErrCh := vpphelper.StartAndDialContext(ctx,
|
|
vpphelper.WithVppConfig(configTemplate),
|
|
vpphelper.WithRootDir(workDir))
|
|
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 (a *Actions) 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(workDir))
|
|
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 " + workDir)
|
|
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 (a *Actions) RunEchoClient(args []string) *ActionResult {
|
|
outBuff := bytes.NewBuffer([]byte{})
|
|
errBuff := bytes.NewBuffer([]byte{})
|
|
|
|
cmd := fmt.Sprintf("vpp_echo client socket-name %s/var/run/app_ns_sockets/2 use-app-socket-api uri %s://10.10.10.1/12344", workDir, 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 (a *Actions) RunEchoServer(args []string) *ActionResult {
|
|
cmd := fmt.Sprintf("vpp_echo server TX=RX socket-name %s/var/run/app_ns_sockets/1 use-app-socket-api uri %s://10.10.10.1/12344", workDir, args[2])
|
|
errCh := exechelper.Start(cmd)
|
|
select {
|
|
case err := <-errCh:
|
|
writeSyncFile(NewActionResult(err, ActionResultWithDesc("echo_server: ")))
|
|
default:
|
|
}
|
|
writeSyncFile(OkResult())
|
|
return nil
|
|
}
|
|
|
|
func (a *Actions) RunEchoSrvInternal(args []string) *ActionResult {
|
|
cmd := fmt.Sprintf("test echo server %s uri tcp://10.10.10.1/1234", getArgs())
|
|
return ApiCliInband(workDir, cmd)
|
|
}
|
|
|
|
func (a *Actions) RunEchoClnInternal(args []string) *ActionResult {
|
|
cmd := fmt.Sprintf("test echo client %s uri tcp://10.10.10.1/1234", getArgs())
|
|
return ApiCliInband(workDir, cmd)
|
|
}
|
|
|
|
func (a *Actions) RunVclEchoServer(args []string) *ActionResult {
|
|
f, err := os.Create("vcl_1.conf")
|
|
if err != nil {
|
|
return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
|
|
}
|
|
socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/1", workDir)
|
|
fmt.Fprintf(f, vclTemplate, socketPath, "1")
|
|
f.Close()
|
|
|
|
os.Setenv("VCL_CONFIG", "./vcl_1.conf")
|
|
cmd := fmt.Sprintf("vcl_test_server -p %s 12346", args[2])
|
|
errCh := exechelper.Start(cmd)
|
|
select {
|
|
case err := <-errCh:
|
|
writeSyncFile(NewActionResult(err, ActionResultWithDesc("vcl_test_server: ")))
|
|
default:
|
|
}
|
|
writeSyncFile(OkResult())
|
|
return nil
|
|
}
|
|
|
|
func (a *Actions) RunVclEchoClient(args []string) *ActionResult {
|
|
outBuff := bytes.NewBuffer([]byte{})
|
|
errBuff := bytes.NewBuffer([]byte{})
|
|
|
|
f, err := os.Create("vcl_2.conf")
|
|
if err != nil {
|
|
return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
|
|
}
|
|
socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/2", workDir)
|
|
fmt.Fprintf(f, vclTemplate, socketPath, "2")
|
|
f.Close()
|
|
|
|
os.Setenv("VCL_CONFIG", "./vcl_2.conf")
|
|
cmd := fmt.Sprintf("vcl_test_client -U -p %s 10.10.10.1 12346", 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 configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64, optionalHardwareAddress ...string) ConfFn {
|
|
return func(ctx context.Context,
|
|
vppConn api.Connection) error {
|
|
|
|
var swIfIndex interface_types.InterfaceIndex
|
|
var err error
|
|
if optionalHardwareAddress == nil {
|
|
swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress)
|
|
} else {
|
|
swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress, optionalHardwareAddress[0])
|
|
}
|
|
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 (a *Actions) Configure2Veths(args []string) *ActionResult {
|
|
var startup Stanza
|
|
startup.
|
|
NewStanza("session").
|
|
Append("enable").
|
|
Append("use-app-socket-api").Close()
|
|
|
|
ctx, cancel := newVppContext()
|
|
defer cancel()
|
|
|
|
vppConfig, err := deserializeVppConfig(args[2])
|
|
if err != nil {
|
|
return NewActionResult(err, ActionResultWithDesc("deserializing configuration failed"))
|
|
}
|
|
|
|
con, vppErrCh := vpphelper.StartAndDialContext(ctx,
|
|
vpphelper.WithVppConfig(vppConfig.getTemplate()+startup.ToString()),
|
|
vpphelper.WithRootDir(workDir))
|
|
exitOnErrCh(ctx, cancel, vppErrCh)
|
|
|
|
var fn func(context.Context, api.Connection) error
|
|
switch vppConfig.Variant {
|
|
case "srv":
|
|
fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1)
|
|
case "srv-with-preset-hw-addr":
|
|
fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1, "00:00:5e:00:53:01")
|
|
case "cln":
|
|
fallthrough
|
|
default:
|
|
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, optionalHardwareAddress ...string) (interface_types.InterfaceIndex, error) {
|
|
var err error
|
|
ifaceClient := interfaces.NewServiceClient(vppCon)
|
|
afPacketCreate := af_packet.AfPacketCreateV2{
|
|
UseRandomHwAddr: true,
|
|
HostIfName: name,
|
|
NumRxQueues: 1,
|
|
}
|
|
if len(optionalHardwareAddress) > 0 {
|
|
afPacketCreate.HwAddr, err = ethernet_types.ParseMacAddress(optionalHardwareAddress[0])
|
|
if err != nil {
|
|
fmt.Printf("failed to parse mac address: %v", err)
|
|
return 0, err
|
|
}
|
|
afPacketCreate.UseRandomHwAddr = false
|
|
}
|
|
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 (a *Actions) 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
|
|
}
|
|
|
|
func (a *Actions) ConfigureTap(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.WithRootDir(workDir),
|
|
vpphelper.WithVppConfig(configTemplate+startup.ToString()))
|
|
exitOnErrCh(ctx, cancel, vppErrCh)
|
|
ifaceClient := interfaces.NewServiceClient(con)
|
|
|
|
pref, err := ip_types.ParseIP4Prefix("10.10.10.2/24")
|
|
if err != nil {
|
|
return NewActionResult(err, ActionResultWithDesc("failed to parse ip4 address"))
|
|
}
|
|
createTapReply, err := tapv2.NewServiceClient(con).TapCreateV2(ctx, &tapv2.TapCreateV2{
|
|
HostIfNameSet: true,
|
|
HostIfName: "tap0",
|
|
HostIP4PrefixSet: true,
|
|
HostIP4Prefix: ip_types.IP4AddressWithPrefix(pref),
|
|
})
|
|
if err != nil {
|
|
return NewActionResult(err, ActionResultWithDesc("failed to configure tap"))
|
|
}
|
|
ipPrefix, err := ip_types.ParseAddressWithPrefix("10.10.10.1/24")
|
|
if err != nil {
|
|
return NewActionResult(err, ActionResultWithDesc("parsing ip address failed"))
|
|
}
|
|
ipAddress := &interfaces.SwInterfaceAddDelAddress{
|
|
IsAdd: true,
|
|
SwIfIndex: createTapReply.SwIfIndex,
|
|
Prefix: ipPrefix,
|
|
}
|
|
_, errx := ifaceClient.SwInterfaceAddDelAddress(ctx, ipAddress)
|
|
if errx != nil {
|
|
return NewActionResult(err, ActionResultWithDesc("configuring ip address failed"))
|
|
}
|
|
_, err = ifaceClient.SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{
|
|
SwIfIndex: createTapReply.SwIfIndex,
|
|
Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
|
|
})
|
|
if err != nil {
|
|
return NewActionResult(err, ActionResultWithDesc("failed to set interface state"))
|
|
}
|
|
_, err = session.NewServiceClient(con).SessionEnableDisable(ctx, &session.SessionEnableDisable{
|
|
IsEnable: true,
|
|
})
|
|
if err != nil {
|
|
return NewActionResult(err, ActionResultWithDesc("configuration failed"))
|
|
}
|
|
writeSyncFile(OkResult())
|
|
<-ctx.Done()
|
|
return nil
|
|
}
|