blob: 34096df27ba050a763b4f4ec4be9e0f353eaa030 [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"
18 "github.com/edwarnicke/govpp/binapi/vlib"
19 "github.com/edwarnicke/vpphelper"
20)
21
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010022var (
23 workDir, _ = os.Getwd()
24)
25
Filip Tehlar1a9dc752022-11-22 12:49:22 +010026type ConfFn func(context.Context, api.Connection) error
27
28type Actions struct {
Filip Tehlar229f5fc2022-08-09 14:44:47 +000029}
30
31func configureProxyTcp(ifName0, ipAddr0, ifName1, ipAddr1 string) ConfFn {
32 return func(ctx context.Context,
33 vppConn api.Connection) error {
34
35 _, err := configureAfPacket(ctx, vppConn, ifName0, ipAddr0)
36 if err != nil {
37 fmt.Printf("failed to create af packet: %v", err)
38 return err
39 }
40 _, err = configureAfPacket(ctx, vppConn, ifName1, ipAddr1)
41 if err != nil {
42 fmt.Printf("failed to create af packet: %v", err)
43 return err
44 }
45 return nil
46 }
47}
48
Filip Tehlar1a9dc752022-11-22 12:49:22 +010049func (a *Actions) RunHttpCliSrv(args []string) *ActionResult {
Filip Tehlarb15a0002022-11-10 12:34:17 +010050 cmd := fmt.Sprintf("http cli server")
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010051 return ApiCliInband(workDir, cmd)
Filip Tehlarb15a0002022-11-10 12:34:17 +010052}
53
Filip Tehlar1a9dc752022-11-22 12:49:22 +010054func (a *Actions) RunHttpCliCln(args []string) *ActionResult {
Filip Tehlarb15a0002022-11-10 12:34:17 +010055 cmd := fmt.Sprintf("http cli client uri http://10.10.10.1/80 query %s", getArgs())
56 fmt.Println(cmd)
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010057 return ApiCliInband(workDir, cmd)
Filip Tehlarb15a0002022-11-10 12:34:17 +010058}
59
Filip Tehlar1a9dc752022-11-22 12:49:22 +010060func (a *Actions) ConfigureVppProxy(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +000061 ctx, cancel := newVppContext()
62 defer cancel()
63
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010064 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
65 vpphelper.WithVppConfig(configTemplate),
66 vpphelper.WithRootDir(workDir))
Filip Tehlar229f5fc2022-08-09 14:44:47 +000067 exitOnErrCh(ctx, cancel, vppErrCh)
68
69 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
70 err := confFn(ctx, con)
71 if err != nil {
72 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
73 }
74 writeSyncFile(OkResult())
75 <-ctx.Done()
76 return nil
77}
78
Filip Tehlar1a9dc752022-11-22 12:49:22 +010079func (a *Actions) ConfigureEnvoyProxy(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +000080 var startup Stanza
81 startup.
82 NewStanza("session").
83 Append("enable").
84 Append("use-app-socket-api").
85 Append("evt_qs_memfd_seg").
86 Append("event-queue-length 100000").Close()
87 ctx, cancel := newVppContext()
88 defer cancel()
89
90 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
91 vpphelper.WithVppConfig(configTemplate+startup.ToString()),
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010092 vpphelper.WithRootDir(workDir))
Filip Tehlar229f5fc2022-08-09 14:44:47 +000093 exitOnErrCh(ctx, cancel, vppErrCh)
94
95 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
96 err := confFn(ctx, con)
97 if err != nil {
98 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
99 }
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100100 err0 := exechelper.Run("chmod 777 -R " + workDir)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000101 if err0 != nil {
102 return NewActionResult(err, ActionResultWithDesc("setting permissions failed"))
103 }
104 writeSyncFile(OkResult())
105 <-ctx.Done()
106 return nil
107}
108
109func getArgs() string {
110 s := ""
111 for i := 2; i < len(os.Args); i++ {
112 s = s + " " + os.Args[i]
113 }
114 return s
115}
116
117func ApiCliInband(root, cmd string) *ActionResult {
118 ctx, _ := newVppContext()
119 con := vpphelper.DialContext(ctx, filepath.Join(root, "/var/run/vpp/api.sock"))
120 cliInband := vlib.CliInband{Cmd: cmd}
121 cliInbandReply, err := vlib.NewServiceClient(con).CliInband(ctx, &cliInband)
122 return NewActionResult(err, ActionResultWithStdout(cliInbandReply.Reply))
123}
124
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100125func (a *Actions) RunEchoClient(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000126 outBuff := bytes.NewBuffer([]byte{})
127 errBuff := bytes.NewBuffer([]byte{})
128
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100129 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 +0000130 err := exechelper.Run(cmd,
131 exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff),
132 exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr))
133
134 return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
135 ActionResultWithStderr(string(errBuff.String())))
136}
137
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100138func (a *Actions) RunEchoServer(args []string) *ActionResult {
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100139 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 +0000140 errCh := exechelper.Start(cmd)
141 select {
142 case err := <-errCh:
143 writeSyncFile(NewActionResult(err, ActionResultWithDesc("echo_server: ")))
144 default:
145 }
146 writeSyncFile(OkResult())
147 return nil
148}
149
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100150func (a *Actions) RunEchoSrvInternal(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000151 cmd := fmt.Sprintf("test echo server %s uri tcp://10.10.10.1/1234", getArgs())
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100152 return ApiCliInband(workDir, cmd)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000153}
154
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100155func (a *Actions) RunEchoClnInternal(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000156 cmd := fmt.Sprintf("test echo client %s uri tcp://10.10.10.1/1234", getArgs())
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100157 return ApiCliInband(workDir, cmd)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000158}
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200159
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100160func (a *Actions) RunVclEchoServer(args []string) *ActionResult {
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200161 f, err := os.Create("vcl_1.conf")
162 if err != nil {
163 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
164 }
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100165 socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/1", workDir)
166 fmt.Fprintf(f, vclTemplate, socketPath, "1")
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200167 f.Close()
168
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100169 os.Setenv("VCL_CONFIG", "./vcl_1.conf")
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200170 cmd := fmt.Sprintf("vcl_test_server -p %s 12346", args[2])
171 errCh := exechelper.Start(cmd)
172 select {
173 case err := <-errCh:
174 writeSyncFile(NewActionResult(err, ActionResultWithDesc("vcl_test_server: ")))
175 default:
176 }
177 writeSyncFile(OkResult())
178 return nil
179}
180
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100181func (a *Actions) RunVclEchoClient(args []string) *ActionResult {
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200182 outBuff := bytes.NewBuffer([]byte{})
183 errBuff := bytes.NewBuffer([]byte{})
184
185 f, err := os.Create("vcl_2.conf")
186 if err != nil {
187 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
188 }
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100189 socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/2", workDir)
190 fmt.Fprintf(f, vclTemplate, socketPath, "2")
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200191 f.Close()
192
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100193 os.Setenv("VCL_CONFIG", "./vcl_2.conf")
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200194 cmd := fmt.Sprintf("vcl_test_client -U -p %s 10.10.10.1 12346", args[2])
195 err = exechelper.Run(cmd,
196 exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff),
197 exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr))
198
199 return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
200 ActionResultWithStderr(string(errBuff.String())))
201}
202
203func configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64, optionalHardwareAddress ...string) ConfFn {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000204 return func(ctx context.Context,
205 vppConn api.Connection) error {
206
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200207 var swIfIndex interface_types.InterfaceIndex
208 var err error
209 if optionalHardwareAddress == nil {
210 swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress)
211 } else {
212 swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress, optionalHardwareAddress[0])
213 }
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000214 if err != nil {
215 fmt.Printf("failed to create af packet: %v", err)
216 }
217 _, er := session.NewServiceClient(vppConn).AppNamespaceAddDelV2(ctx, &session.AppNamespaceAddDelV2{
218 Secret: secret,
219 SwIfIndex: swIfIndex,
220 NamespaceID: namespaceId,
221 })
222 if er != nil {
223 fmt.Printf("add app namespace: %v", err)
224 return err
225 }
226
227 _, er1 := session.NewServiceClient(vppConn).SessionEnableDisable(ctx, &session.SessionEnableDisable{
228 IsEnable: true,
229 })
230 if er1 != nil {
231 fmt.Printf("session enable %v", err)
232 return err
233 }
234 return nil
235 }
236}
237
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100238func (a *Actions) Configure2Veths(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000239 var startup Stanza
240 startup.
241 NewStanza("session").
242 Append("enable").
243 Append("use-app-socket-api").Close()
244
245 ctx, cancel := newVppContext()
246 defer cancel()
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100247
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100248 vppConfig, err := deserializeVppConfig(args[2])
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100249 if err != nil {
250 return NewActionResult(err, ActionResultWithDesc("deserializing configuration failed"))
251 }
252
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000253 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100254 vpphelper.WithVppConfig(vppConfig.getTemplate()+startup.ToString()),
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100255 vpphelper.WithRootDir(workDir))
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000256 exitOnErrCh(ctx, cancel, vppErrCh)
257
258 var fn func(context.Context, api.Connection) error
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100259 switch vppConfig.Variant {
260 case "srv":
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000261 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1)
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100262 case "srv-with-preset-hw-addr":
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200263 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1, "00:00:5e:00:53:01")
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100264 case "cln":
265 fallthrough
266 default:
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000267 fn = configure2vethsTopo("vppcln", "10.10.10.2/24", "2", 2)
268 }
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100269 err = fn(ctx, con)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000270 if err != nil {
271 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
272 }
273 writeSyncFile(OkResult())
274 <-ctx.Done()
275 return nil
276}
277
278func configureAfPacket(ctx context.Context, vppCon api.Connection,
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200279 name, interfaceAddress string, optionalHardwareAddress ...string) (interface_types.InterfaceIndex, error) {
280 var err error
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000281 ifaceClient := interfaces.NewServiceClient(vppCon)
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200282 afPacketCreate := af_packet.AfPacketCreateV2{
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000283 UseRandomHwAddr: true,
284 HostIfName: name,
285 NumRxQueues: 1,
286 }
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200287 if len(optionalHardwareAddress) > 0 {
288 afPacketCreate.HwAddr, err = ethernet_types.ParseMacAddress(optionalHardwareAddress[0])
289 if err != nil {
290 fmt.Printf("failed to parse mac address: %v", err)
291 return 0, err
292 }
293 afPacketCreate.UseRandomHwAddr = false
294 }
295 afPacketCreateRsp, err := af_packet.NewServiceClient(vppCon).AfPacketCreateV2(ctx, &afPacketCreate)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000296 if err != nil {
297 fmt.Printf("failed to create af packet: %v", err)
298 return 0, err
299 }
300 _, err = ifaceClient.SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{
301 SwIfIndex: afPacketCreateRsp.SwIfIndex,
302 Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
303 })
304 if err != nil {
305 fmt.Printf("set interface state up failed: %v\n", err)
306 return 0, err
307 }
308 ipPrefix, err := ip_types.ParseAddressWithPrefix(interfaceAddress)
309 if err != nil {
310 fmt.Printf("parse ip address %v\n", err)
311 return 0, err
312 }
313 ipAddress := &interfaces.SwInterfaceAddDelAddress{
314 IsAdd: true,
315 SwIfIndex: afPacketCreateRsp.SwIfIndex,
316 Prefix: ipPrefix,
317 }
318 _, errx := ifaceClient.SwInterfaceAddDelAddress(ctx, ipAddress)
319 if errx != nil {
320 fmt.Printf("add ip address %v\n", err)
321 return 0, err
322 }
323 return afPacketCreateRsp.SwIfIndex, nil
324}
325
Filip Tehlar1a9dc752022-11-22 12:49:22 +0100326func (a *Actions) ConfigureHttpTps(args []string) *ActionResult {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000327 ctx, cancel := newVppContext()
328 defer cancel()
329 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
330 vpphelper.WithVppConfig(configTemplate))
331 exitOnErrCh(ctx, cancel, vppErrCh)
332
333 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
334 err := confFn(ctx, con)
335 if err != nil {
336 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
337 }
338
339 _, err = session.NewServiceClient(con).SessionEnableDisable(ctx, &session.SessionEnableDisable{
340 IsEnable: true,
341 })
342 if err != nil {
343 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
344 }
345 Vppcli("", "http tps uri tcp://0.0.0.0/8080")
346 writeSyncFile(OkResult())
347 <-ctx.Done()
348 return nil
349}