10 "git.fd.io/govpp.git/api"
11 "github.com/edwarnicke/exechelper"
12 "github.com/edwarnicke/govpp/binapi/af_packet"
13 "github.com/edwarnicke/govpp/binapi/ethernet_types"
14 interfaces "github.com/edwarnicke/govpp/binapi/interface"
15 "github.com/edwarnicke/govpp/binapi/interface_types"
16 ip_types "github.com/edwarnicke/govpp/binapi/ip_types"
17 "github.com/edwarnicke/govpp/binapi/session"
18 "github.com/edwarnicke/govpp/binapi/tapv2"
19 "github.com/edwarnicke/govpp/binapi/vlib"
20 "github.com/edwarnicke/vpphelper"
24 workDir, _ = os.Getwd()
27 type ConfFn func(context.Context, api.Connection) error
32 func configureProxyTcp(ifName0, ipAddr0, ifName1, ipAddr1 string) ConfFn {
33 return func(ctx context.Context,
34 vppConn api.Connection) error {
36 _, err := configureAfPacket(ctx, vppConn, ifName0, ipAddr0)
38 fmt.Printf("failed to create af packet: %v", err)
41 _, err = configureAfPacket(ctx, vppConn, ifName1, ipAddr1)
43 fmt.Printf("failed to create af packet: %v", err)
50 func (a *Actions) RunHttpCliSrv(args []string) *ActionResult {
51 cmd := fmt.Sprintf("http cli server")
52 return ApiCliInband(workDir, cmd)
55 func (a *Actions) RunHttpCliCln(args []string) *ActionResult {
56 cmd := fmt.Sprintf("http cli client uri http://10.10.10.1/80 query %s", getArgs())
58 return ApiCliInband(workDir, cmd)
61 func (a *Actions) ConfigureVppProxy(args []string) *ActionResult {
62 ctx, cancel := newVppContext()
65 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
66 vpphelper.WithVppConfig(configTemplate),
67 vpphelper.WithRootDir(workDir))
68 exitOnErrCh(ctx, cancel, vppErrCh)
70 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
71 err := confFn(ctx, con)
73 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
75 writeSyncFile(OkResult())
80 func (a *Actions) ConfigureEnvoyProxy(args []string) *ActionResult {
85 Append("use-app-socket-api").
86 Append("evt_qs_memfd_seg").
87 Append("event-queue-length 100000").Close()
88 ctx, cancel := newVppContext()
91 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
92 vpphelper.WithVppConfig(configTemplate+startup.ToString()),
93 vpphelper.WithRootDir(workDir))
94 exitOnErrCh(ctx, cancel, vppErrCh)
96 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
97 err := confFn(ctx, con)
99 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
101 err0 := exechelper.Run("chmod 777 -R " + workDir)
103 return NewActionResult(err, ActionResultWithDesc("setting permissions failed"))
105 writeSyncFile(OkResult())
110 func getArgs() string {
112 for i := 2; i < len(os.Args); i++ {
113 s = s + " " + os.Args[i]
118 func ApiCliInband(root, cmd string) *ActionResult {
119 ctx, _ := newVppContext()
120 con := vpphelper.DialContext(ctx, filepath.Join(root, "/var/run/vpp/api.sock"))
121 cliInband := vlib.CliInband{Cmd: cmd}
122 cliInbandReply, err := vlib.NewServiceClient(con).CliInband(ctx, &cliInband)
123 return NewActionResult(err, ActionResultWithStdout(cliInbandReply.Reply))
126 func (a *Actions) RunEchoClient(args []string) *ActionResult {
127 outBuff := bytes.NewBuffer([]byte{})
128 errBuff := bytes.NewBuffer([]byte{})
130 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])
131 err := exechelper.Run(cmd,
132 exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff),
133 exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr))
135 return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
136 ActionResultWithStderr(string(errBuff.String())))
139 func (a *Actions) RunEchoServer(args []string) *ActionResult {
140 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])
141 errCh := exechelper.Start(cmd)
144 writeSyncFile(NewActionResult(err, ActionResultWithDesc("echo_server: ")))
147 writeSyncFile(OkResult())
151 func (a *Actions) RunEchoSrvInternal(args []string) *ActionResult {
152 cmd := fmt.Sprintf("test echo server %s uri tcp://10.10.10.1/1234", getArgs())
153 return ApiCliInband(workDir, cmd)
156 func (a *Actions) RunEchoClnInternal(args []string) *ActionResult {
157 cmd := fmt.Sprintf("test echo client %s uri tcp://10.10.10.1/1234", getArgs())
158 return ApiCliInband(workDir, cmd)
161 func (a *Actions) RunVclEchoServer(args []string) *ActionResult {
162 f, err := os.Create("vcl_1.conf")
164 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
166 socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/1", workDir)
167 fmt.Fprintf(f, vclTemplate, socketPath, "1")
170 os.Setenv("VCL_CONFIG", "./vcl_1.conf")
171 cmd := fmt.Sprintf("vcl_test_server -p %s 12346", args[2])
172 errCh := exechelper.Start(cmd)
175 writeSyncFile(NewActionResult(err, ActionResultWithDesc("vcl_test_server: ")))
178 writeSyncFile(OkResult())
182 func (a *Actions) RunVclEchoClient(args []string) *ActionResult {
183 outBuff := bytes.NewBuffer([]byte{})
184 errBuff := bytes.NewBuffer([]byte{})
186 f, err := os.Create("vcl_2.conf")
188 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
190 socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/2", workDir)
191 fmt.Fprintf(f, vclTemplate, socketPath, "2")
194 os.Setenv("VCL_CONFIG", "./vcl_2.conf")
195 cmd := fmt.Sprintf("vcl_test_client -U -p %s 10.10.10.1 12346", args[2])
196 err = exechelper.Run(cmd,
197 exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff),
198 exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr))
200 return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
201 ActionResultWithStderr(string(errBuff.String())))
204 func configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64, optionalHardwareAddress ...string) ConfFn {
205 return func(ctx context.Context,
206 vppConn api.Connection) error {
208 var swIfIndex interface_types.InterfaceIndex
210 if optionalHardwareAddress == nil {
211 swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress)
213 swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress, optionalHardwareAddress[0])
216 fmt.Printf("failed to create af packet: %v", err)
218 _, er := session.NewServiceClient(vppConn).AppNamespaceAddDelV2(ctx, &session.AppNamespaceAddDelV2{
220 SwIfIndex: swIfIndex,
221 NamespaceID: namespaceId,
224 fmt.Printf("add app namespace: %v", err)
228 _, er1 := session.NewServiceClient(vppConn).SessionEnableDisable(ctx, &session.SessionEnableDisable{
232 fmt.Printf("session enable %v", err)
239 func (a *Actions) Configure2Veths(args []string) *ActionResult {
242 NewStanza("session").
244 Append("use-app-socket-api").Close()
246 ctx, cancel := newVppContext()
249 vppConfig, err := deserializeVppConfig(args[2])
251 return NewActionResult(err, ActionResultWithDesc("deserializing configuration failed"))
254 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
255 vpphelper.WithVppConfig(vppConfig.getTemplate()+startup.ToString()),
256 vpphelper.WithRootDir(workDir))
257 exitOnErrCh(ctx, cancel, vppErrCh)
259 var fn func(context.Context, api.Connection) error
260 switch vppConfig.Variant {
262 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1)
263 case "srv-with-preset-hw-addr":
264 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1, "00:00:5e:00:53:01")
268 fn = configure2vethsTopo("vppcln", "10.10.10.2/24", "2", 2)
272 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
274 writeSyncFile(OkResult())
279 func configureAfPacket(ctx context.Context, vppCon api.Connection,
280 name, interfaceAddress string, optionalHardwareAddress ...string) (interface_types.InterfaceIndex, error) {
282 ifaceClient := interfaces.NewServiceClient(vppCon)
283 afPacketCreate := af_packet.AfPacketCreateV2{
284 UseRandomHwAddr: true,
288 if len(optionalHardwareAddress) > 0 {
289 afPacketCreate.HwAddr, err = ethernet_types.ParseMacAddress(optionalHardwareAddress[0])
291 fmt.Printf("failed to parse mac address: %v", err)
294 afPacketCreate.UseRandomHwAddr = false
296 afPacketCreateRsp, err := af_packet.NewServiceClient(vppCon).AfPacketCreateV2(ctx, &afPacketCreate)
298 fmt.Printf("failed to create af packet: %v", err)
301 _, err = ifaceClient.SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{
302 SwIfIndex: afPacketCreateRsp.SwIfIndex,
303 Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
306 fmt.Printf("set interface state up failed: %v\n", err)
309 ipPrefix, err := ip_types.ParseAddressWithPrefix(interfaceAddress)
311 fmt.Printf("parse ip address %v\n", err)
314 ipAddress := &interfaces.SwInterfaceAddDelAddress{
316 SwIfIndex: afPacketCreateRsp.SwIfIndex,
319 _, errx := ifaceClient.SwInterfaceAddDelAddress(ctx, ipAddress)
321 fmt.Printf("add ip address %v\n", err)
324 return afPacketCreateRsp.SwIfIndex, nil
327 func (a *Actions) ConfigureHttpTps(args []string) *ActionResult {
328 ctx, cancel := newVppContext()
330 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
331 vpphelper.WithVppConfig(configTemplate))
332 exitOnErrCh(ctx, cancel, vppErrCh)
334 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
335 err := confFn(ctx, con)
337 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
340 _, err = session.NewServiceClient(con).SessionEnableDisable(ctx, &session.SessionEnableDisable{
344 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
346 Vppcli("", "http tps uri tcp://0.0.0.0/8080")
347 writeSyncFile(OkResult())
352 func (a *Actions) ConfigureTap(args []string) *ActionResult {
355 NewStanza("session").
357 Append("use-app-socket-api").Close()
359 ctx, cancel := newVppContext()
361 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
362 vpphelper.WithRootDir(workDir),
363 vpphelper.WithVppConfig(configTemplate+startup.ToString()))
364 exitOnErrCh(ctx, cancel, vppErrCh)
365 ifaceClient := interfaces.NewServiceClient(con)
367 pref, err := ip_types.ParseIP4Prefix("10.10.10.2/24")
369 return NewActionResult(err, ActionResultWithDesc("failed to parse ip4 address"))
371 createTapReply, err := tapv2.NewServiceClient(con).TapCreateV2(ctx, &tapv2.TapCreateV2{
374 HostIP4PrefixSet: true,
375 HostIP4Prefix: ip_types.IP4AddressWithPrefix(pref),
378 return NewActionResult(err, ActionResultWithDesc("failed to configure tap"))
380 ipPrefix, err := ip_types.ParseAddressWithPrefix("10.10.10.1/24")
382 return NewActionResult(err, ActionResultWithDesc("parsing ip address failed"))
384 ipAddress := &interfaces.SwInterfaceAddDelAddress{
386 SwIfIndex: createTapReply.SwIfIndex,
389 _, errx := ifaceClient.SwInterfaceAddDelAddress(ctx, ipAddress)
391 return NewActionResult(err, ActionResultWithDesc("configuring ip address failed"))
393 _, err = ifaceClient.SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{
394 SwIfIndex: createTapReply.SwIfIndex,
395 Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
398 return NewActionResult(err, ActionResultWithDesc("failed to set interface state"))
400 _, err = session.NewServiceClient(con).SessionEnableDisable(ctx, &session.SessionEnableDisable{
404 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
406 writeSyncFile(OkResult())