"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"
)
-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)
+var (
+ workDir, _ = os.Getwd()
+)
+
+type ConfFn func(context.Context, api.Connection) error
+
+type Actions struct {
}
func configureProxyTcp(ifName0, ipAddr0, ifName1, ipAddr1 string) ConfFn {
}
}
-func ConfigureVppProxy(args []string) *ActionResult {
+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))
+ 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")
return nil
}
-func ConfigureEnvoyProxy(args []string) *ActionResult {
+func (a *Actions) ConfigureEnvoyProxy(args []string) *ActionResult {
var startup Stanza
startup.
NewStanza("session").
con, vppErrCh := vpphelper.StartAndDialContext(ctx,
vpphelper.WithVppConfig(configTemplate+startup.ToString()),
- vpphelper.WithRootDir("/tmp/vpp-envoy"))
+ vpphelper.WithRootDir(workDir))
exitOnErrCh(ctx, cancel, vppErrCh)
confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
if err != nil {
return NewActionResult(err, ActionResultWithDesc("configuration failed"))
}
- err0 := exechelper.Run("chmod 777 -R /tmp/vpp-envoy")
+ err0 := exechelper.Run("chmod 777 -R " + workDir)
if err0 != nil {
return NewActionResult(err, ActionResultWithDesc("setting permissions failed"))
}
return NewActionResult(err, ActionResultWithStdout(cliInbandReply.Reply))
}
-func RunEchoClient(args []string) *ActionResult {
+func (a *Actions) 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])
+ 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))
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])
+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:
return nil
}
-func RunEchoSrvInternal() *ActionResult {
+func (a *Actions) RunEchoSrvInternal(args []string) *ActionResult {
cmd := fmt.Sprintf("test echo server %s uri tcp://10.10.10.1/1234", getArgs())
- return ApiCliInband("/tmp/2veths", cmd)
+ return ApiCliInband(workDir, cmd)
}
-func RunEchoClnInternal() *ActionResult {
+func (a *Actions) RunEchoClnInternal(args []string) *ActionResult {
cmd := fmt.Sprintf("test echo client %s uri tcp://10.10.10.1/1234", getArgs())
- return ApiCliInband("/tmp/2veths", cmd)
+ 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 configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64) ConfFn {
+
+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 {
- swIfIndex, err := configureAfPacket(ctx, vppConn, ifName, interfaceAddress)
+ 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)
}
}
}
-func Configure2Veths(args []string) *ActionResult {
+func (a *Actions) Configure2Veths(args []string) *ActionResult {
var startup Stanza
startup.
NewStanza("session").
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(configTemplate+startup.ToString()),
- vpphelper.WithRootDir(fmt.Sprintf("/tmp/%s", args[1])))
+ vpphelper.WithVppConfig(vppConfig.getTemplate()+startup.ToString()),
+ vpphelper.WithRootDir(workDir))
exitOnErrCh(ctx, cancel, vppErrCh)
var fn func(context.Context, api.Connection) error
- if args[2] == "srv" {
+ switch vppConfig.Variant {
+ case "srv":
fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1)
- } else {
+ 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)
+ err = fn(ctx, con)
if err != nil {
return NewActionResult(err, ActionResultWithDesc("configuration failed"))
}
}
func configureAfPacket(ctx context.Context, vppCon api.Connection,
- name, interfaceAddress string) (interface_types.InterfaceIndex, error) {
+ name, interfaceAddress string, optionalHardwareAddress ...string) (interface_types.InterfaceIndex, error) {
+ var err error
ifaceClient := interfaces.NewServiceClient(vppCon)
- afPacketCreate := &af_packet.AfPacketCreateV2{
+ afPacketCreate := af_packet.AfPacketCreateV2{
UseRandomHwAddr: true,
HostIfName: name,
NumRxQueues: 1,
}
- afPacketCreateRsp, err := af_packet.NewServiceClient(vppCon).AfPacketCreateV2(ctx, afPacketCreate)
+ 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
return afPacketCreateRsp.SwIfIndex, nil
}
-func ConfigureHttpTps(args []string) *ActionResult {
+func (a *Actions) ConfigureHttpTps(args []string) *ActionResult {
ctx, cancel := newVppContext()
defer cancel()
con, vppErrCh := vpphelper.StartAndDialContext(ctx,
<-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
+}