blob: 279589b5d415087d10cec63072878d0046a9e88a [file] [log] [blame]
Filip Tehlar229f5fc2022-08-09 14:44:47 +00001package main
2
3import (
4 "bytes"
5 "context"
6 "fmt"
7 "os"
8 "path/filepath"
9
10 "git.fd.io/govpp.git/api"
11 "github.com/edwarnicke/exechelper"
12 "github.com/edwarnicke/govpp/binapi/af_packet"
Maros Ondrejicka0db15752022-10-12 22:58:01 +020013 "github.com/edwarnicke/govpp/binapi/ethernet_types"
Filip Tehlar229f5fc2022-08-09 14:44:47 +000014 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"
Filip Tehlarc204c872022-12-21 08:59:16 +010018 "github.com/edwarnicke/govpp/binapi/tapv2"
Filip Tehlar229f5fc2022-08-09 14:44:47 +000019 "github.com/edwarnicke/govpp/binapi/vlib"
20 "github.com/edwarnicke/vpphelper"
21)
22
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010023var (
24 workDir, _ = os.Getwd()
25)
26
Filip Tehlar1a9dc752022-11-22 12:49:22 +010027type ConfFn func(context.Context, api.Connection) error
28
29type Actions struct {
Filip Tehlar229f5fc2022-08-09 14:44:47 +000030}
31
32func configureProxyTcp(ifName0, ipAddr0, ifName1, ipAddr1 string) ConfFn {
33 return func(ctx context.Context,
34 vppConn api.Connection) error {
35
36 _, err := configureAfPacket(ctx, vppConn, ifName0, ipAddr0)
37 if err != nil {
38 fmt.Printf("failed to create af packet: %v", err)
39 return err
40 }
41 _, err = configureAfPacket(ctx, vppConn, ifName1, ipAddr1)
42 if err != nil {
43 fmt.Printf("failed to create af packet: %v", err)
44 return err
45 }
46 return nil
47 }
48}
49
Filip Tehlar1a9dc752022-11-22 12:49:22 +010050func (a *Actions) RunHttpCliSrv(args []string) *ActionResult {
Filip Tehlarb15a0002022-11-10 12:34:17 +010051 cmd := fmt.Sprintf("http cli server")
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010052 return ApiCliInband(workDir, cmd)
Filip Tehlarb15a0002022-11-10 12:34:17 +010053}
54
Filip Tehlar1a9dc752022-11-22 12:49:22 +010055func (a *Actions) RunHttpCliCln(args []string) *ActionResult {
Filip Tehlarb15a0002022-11-10 12:34:17 +010056 cmd := fmt.Sprintf("http cli client uri http://10.10.10.1/80 query %s", getArgs())
57 fmt.Println(cmd)
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010058 return ApiCliInband(workDir, cmd)
Filip Tehlarb15a0002022-11-10 12:34:17 +010059}
60
Filip Tehlar1a9dc752022-11-22 12:49:22 +010061func (a *Actions) ConfigureVppProxy(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +000062 ctx, cancel := newVppContext()
63 defer cancel()
64
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010065 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
66 vpphelper.WithVppConfig(configTemplate),
67 vpphelper.WithRootDir(workDir))
Filip Tehlar229f5fc2022-08-09 14:44:47 +000068 exitOnErrCh(ctx, cancel, vppErrCh)
69
70 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
71 err := confFn(ctx, con)
72 if err != nil {
73 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
74 }
75 writeSyncFile(OkResult())
76 <-ctx.Done()
77 return nil
78}
79
Filip Tehlar1a9dc752022-11-22 12:49:22 +010080func (a *Actions) ConfigureEnvoyProxy(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +000081 var startup Stanza
82 startup.
83 NewStanza("session").
84 Append("enable").
85 Append("use-app-socket-api").
86 Append("evt_qs_memfd_seg").
87 Append("event-queue-length 100000").Close()
88 ctx, cancel := newVppContext()
89 defer cancel()
90
91 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
92 vpphelper.WithVppConfig(configTemplate+startup.ToString()),
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010093 vpphelper.WithRootDir(workDir))
Filip Tehlar229f5fc2022-08-09 14:44:47 +000094 exitOnErrCh(ctx, cancel, vppErrCh)
95
96 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
97 err := confFn(ctx, con)
98 if err != nil {
99 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
100 }
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100101 err0 := exechelper.Run("chmod 777 -R " + workDir)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000102 if err0 != nil {
103 return NewActionResult(err, ActionResultWithDesc("setting permissions failed"))
104 }
105 writeSyncFile(OkResult())
106 <-ctx.Done()
107 return nil
108}
109
110func getArgs() string {
111 s := ""
112 for i := 2; i < len(os.Args); i++ {
113 s = s + " " + os.Args[i]
114 }
115 return s
116}
117
118func 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))
124}
125
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100126func (a *Actions) RunEchoClient(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000127 outBuff := bytes.NewBuffer([]byte{})
128 errBuff := bytes.NewBuffer([]byte{})
129
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100130 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])
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000131 err := exechelper.Run(cmd,
132 exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff),
133 exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr))
134
135 return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
136 ActionResultWithStderr(string(errBuff.String())))
137}
138
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100139func (a *Actions) RunEchoServer(args []string) *ActionResult {
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100140 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])
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000141 errCh := exechelper.Start(cmd)
142 select {
143 case err := <-errCh:
144 writeSyncFile(NewActionResult(err, ActionResultWithDesc("echo_server: ")))
145 default:
146 }
147 writeSyncFile(OkResult())
148 return nil
149}
150
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100151func (a *Actions) RunEchoSrvInternal(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000152 cmd := fmt.Sprintf("test echo server %s uri tcp://10.10.10.1/1234", getArgs())
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100153 return ApiCliInband(workDir, cmd)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000154}
155
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100156func (a *Actions) RunEchoClnInternal(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000157 cmd := fmt.Sprintf("test echo client %s uri tcp://10.10.10.1/1234", getArgs())
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100158 return ApiCliInband(workDir, cmd)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000159}
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200160
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100161func (a *Actions) RunVclEchoServer(args []string) *ActionResult {
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200162 f, err := os.Create("vcl_1.conf")
163 if err != nil {
164 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
165 }
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100166 socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/1", workDir)
167 fmt.Fprintf(f, vclTemplate, socketPath, "1")
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200168 f.Close()
169
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100170 os.Setenv("VCL_CONFIG", "./vcl_1.conf")
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200171 cmd := fmt.Sprintf("vcl_test_server -p %s 12346", args[2])
172 errCh := exechelper.Start(cmd)
173 select {
174 case err := <-errCh:
175 writeSyncFile(NewActionResult(err, ActionResultWithDesc("vcl_test_server: ")))
176 default:
177 }
178 writeSyncFile(OkResult())
179 return nil
180}
181
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100182func (a *Actions) RunVclEchoClient(args []string) *ActionResult {
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200183 outBuff := bytes.NewBuffer([]byte{})
184 errBuff := bytes.NewBuffer([]byte{})
185
186 f, err := os.Create("vcl_2.conf")
187 if err != nil {
188 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
189 }
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100190 socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/2", workDir)
191 fmt.Fprintf(f, vclTemplate, socketPath, "2")
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200192 f.Close()
193
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100194 os.Setenv("VCL_CONFIG", "./vcl_2.conf")
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200195 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))
199
200 return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
201 ActionResultWithStderr(string(errBuff.String())))
202}
203
204func configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64, optionalHardwareAddress ...string) ConfFn {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000205 return func(ctx context.Context,
206 vppConn api.Connection) error {
207
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200208 var swIfIndex interface_types.InterfaceIndex
209 var err error
210 if optionalHardwareAddress == nil {
211 swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress)
212 } else {
213 swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress, optionalHardwareAddress[0])
214 }
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000215 if err != nil {
216 fmt.Printf("failed to create af packet: %v", err)
217 }
218 _, er := session.NewServiceClient(vppConn).AppNamespaceAddDelV2(ctx, &session.AppNamespaceAddDelV2{
219 Secret: secret,
220 SwIfIndex: swIfIndex,
221 NamespaceID: namespaceId,
222 })
223 if er != nil {
224 fmt.Printf("add app namespace: %v", err)
225 return err
226 }
227
228 _, er1 := session.NewServiceClient(vppConn).SessionEnableDisable(ctx, &session.SessionEnableDisable{
229 IsEnable: true,
230 })
231 if er1 != nil {
232 fmt.Printf("session enable %v", err)
233 return err
234 }
235 return nil
236 }
237}
238
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100239func (a *Actions) Configure2Veths(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000240 var startup Stanza
241 startup.
242 NewStanza("session").
243 Append("enable").
244 Append("use-app-socket-api").Close()
245
246 ctx, cancel := newVppContext()
247 defer cancel()
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100248
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100249 vppConfig, err := deserializeVppConfig(args[2])
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100250 if err != nil {
251 return NewActionResult(err, ActionResultWithDesc("deserializing configuration failed"))
252 }
253
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000254 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100255 vpphelper.WithVppConfig(vppConfig.getTemplate()+startup.ToString()),
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100256 vpphelper.WithRootDir(workDir))
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000257 exitOnErrCh(ctx, cancel, vppErrCh)
258
259 var fn func(context.Context, api.Connection) error
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100260 switch vppConfig.Variant {
261 case "srv":
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000262 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1)
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100263 case "srv-with-preset-hw-addr":
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200264 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1, "00:00:5e:00:53:01")
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100265 case "cln":
266 fallthrough
267 default:
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000268 fn = configure2vethsTopo("vppcln", "10.10.10.2/24", "2", 2)
269 }
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100270 err = fn(ctx, con)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000271 if err != nil {
272 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
273 }
274 writeSyncFile(OkResult())
275 <-ctx.Done()
276 return nil
277}
278
279func configureAfPacket(ctx context.Context, vppCon api.Connection,
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200280 name, interfaceAddress string, optionalHardwareAddress ...string) (interface_types.InterfaceIndex, error) {
281 var err error
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000282 ifaceClient := interfaces.NewServiceClient(vppCon)
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200283 afPacketCreate := af_packet.AfPacketCreateV2{
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000284 UseRandomHwAddr: true,
285 HostIfName: name,
286 NumRxQueues: 1,
287 }
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200288 if len(optionalHardwareAddress) > 0 {
289 afPacketCreate.HwAddr, err = ethernet_types.ParseMacAddress(optionalHardwareAddress[0])
290 if err != nil {
291 fmt.Printf("failed to parse mac address: %v", err)
292 return 0, err
293 }
294 afPacketCreate.UseRandomHwAddr = false
295 }
296 afPacketCreateRsp, err := af_packet.NewServiceClient(vppCon).AfPacketCreateV2(ctx, &afPacketCreate)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000297 if err != nil {
298 fmt.Printf("failed to create af packet: %v", err)
299 return 0, err
300 }
301 _, err = ifaceClient.SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{
302 SwIfIndex: afPacketCreateRsp.SwIfIndex,
303 Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
304 })
305 if err != nil {
306 fmt.Printf("set interface state up failed: %v\n", err)
307 return 0, err
308 }
309 ipPrefix, err := ip_types.ParseAddressWithPrefix(interfaceAddress)
310 if err != nil {
311 fmt.Printf("parse ip address %v\n", err)
312 return 0, err
313 }
314 ipAddress := &interfaces.SwInterfaceAddDelAddress{
315 IsAdd: true,
316 SwIfIndex: afPacketCreateRsp.SwIfIndex,
317 Prefix: ipPrefix,
318 }
319 _, errx := ifaceClient.SwInterfaceAddDelAddress(ctx, ipAddress)
320 if errx != nil {
321 fmt.Printf("add ip address %v\n", err)
322 return 0, err
323 }
324 return afPacketCreateRsp.SwIfIndex, nil
325}
326
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100327func (a *Actions) ConfigureHttpTps(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000328 ctx, cancel := newVppContext()
329 defer cancel()
330 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
331 vpphelper.WithVppConfig(configTemplate))
332 exitOnErrCh(ctx, cancel, vppErrCh)
333
334 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
335 err := confFn(ctx, con)
336 if err != nil {
337 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
338 }
339
340 _, err = session.NewServiceClient(con).SessionEnableDisable(ctx, &session.SessionEnableDisable{
341 IsEnable: true,
342 })
343 if err != nil {
344 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
345 }
346 Vppcli("", "http tps uri tcp://0.0.0.0/8080")
347 writeSyncFile(OkResult())
348 <-ctx.Done()
349 return nil
350}
Filip Tehlarc204c872022-12-21 08:59:16 +0100351
352func (a *Actions) ConfigureTap(args []string) *ActionResult {
353 var startup Stanza
354 startup.
355 NewStanza("session").
356 Append("enable").
357 Append("use-app-socket-api").Close()
358
359 ctx, cancel := newVppContext()
360 defer cancel()
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)
366
367 pref, err := ip_types.ParseIP4Prefix("10.10.10.2/24")
368 if err != nil {
369 return NewActionResult(err, ActionResultWithDesc("failed to parse ip4 address"))
370 }
371 createTapReply, err := tapv2.NewServiceClient(con).TapCreateV2(ctx, &tapv2.TapCreateV2{
372 HostIfNameSet: true,
373 HostIfName: "tap0",
374 HostIP4PrefixSet: true,
375 HostIP4Prefix: ip_types.IP4AddressWithPrefix(pref),
376 })
377 if err != nil {
378 return NewActionResult(err, ActionResultWithDesc("failed to configure tap"))
379 }
380 ipPrefix, err := ip_types.ParseAddressWithPrefix("10.10.10.1/24")
381 if err != nil {
382 return NewActionResult(err, ActionResultWithDesc("parsing ip address failed"))
383 }
384 ipAddress := &interfaces.SwInterfaceAddDelAddress{
385 IsAdd: true,
386 SwIfIndex: createTapReply.SwIfIndex,
387 Prefix: ipPrefix,
388 }
389 _, errx := ifaceClient.SwInterfaceAddDelAddress(ctx, ipAddress)
390 if errx != nil {
391 return NewActionResult(err, ActionResultWithDesc("configuring ip address failed"))
392 }
393 _, err = ifaceClient.SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{
394 SwIfIndex: createTapReply.SwIfIndex,
395 Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
396 })
397 if err != nil {
398 return NewActionResult(err, ActionResultWithDesc("failed to set interface state"))
399 }
400 _, err = session.NewServiceClient(con).SessionEnableDisable(ctx, &session.SessionEnableDisable{
401 IsEnable: true,
402 })
403 if err != nil {
404 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
405 }
406 writeSyncFile(OkResult())
407 <-ctx.Done()
408 return nil
409}