34096df27ba050a763b4f4ec4be9e0f353eaa030
[vpp.git] / extras / hs-test / actions.go
1 package main
2
3 import (
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"
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/vlib"
19         "github.com/edwarnicke/vpphelper"
20 )
21
22 var (
23         workDir, _ = os.Getwd()
24 )
25
26 type ConfFn func(context.Context, api.Connection) error
27
28 type Actions struct {
29 }
30
31 func 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
49 func (a *Actions) RunHttpCliSrv(args []string) *ActionResult {
50         cmd := fmt.Sprintf("http cli server")
51         return ApiCliInband(workDir, cmd)
52 }
53
54 func (a *Actions) RunHttpCliCln(args []string) *ActionResult {
55         cmd := fmt.Sprintf("http cli client uri http://10.10.10.1/80 query %s", getArgs())
56         fmt.Println(cmd)
57         return ApiCliInband(workDir, cmd)
58 }
59
60 func (a *Actions) ConfigureVppProxy(args []string) *ActionResult {
61         ctx, cancel := newVppContext()
62         defer cancel()
63
64         con, vppErrCh := vpphelper.StartAndDialContext(ctx,
65                 vpphelper.WithVppConfig(configTemplate),
66                 vpphelper.WithRootDir(workDir))
67         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
79 func (a *Actions) ConfigureEnvoyProxy(args []string) *ActionResult {
80         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()),
92                 vpphelper.WithRootDir(workDir))
93         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         }
100         err0 := exechelper.Run("chmod 777 -R " + workDir)
101         if err0 != nil {
102                 return NewActionResult(err, ActionResultWithDesc("setting permissions failed"))
103         }
104         writeSyncFile(OkResult())
105         <-ctx.Done()
106         return nil
107 }
108
109 func 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
117 func 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
125 func (a *Actions) RunEchoClient(args []string) *ActionResult {
126         outBuff := bytes.NewBuffer([]byte{})
127         errBuff := bytes.NewBuffer([]byte{})
128
129         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])
130         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
138 func (a *Actions) RunEchoServer(args []string) *ActionResult {
139         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])
140         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
150 func (a *Actions) RunEchoSrvInternal(args []string) *ActionResult {
151         cmd := fmt.Sprintf("test echo server %s uri tcp://10.10.10.1/1234", getArgs())
152         return ApiCliInband(workDir, cmd)
153 }
154
155 func (a *Actions) RunEchoClnInternal(args []string) *ActionResult {
156         cmd := fmt.Sprintf("test echo client %s uri tcp://10.10.10.1/1234", getArgs())
157         return ApiCliInband(workDir, cmd)
158 }
159
160 func (a *Actions) RunVclEchoServer(args []string) *ActionResult {
161         f, err := os.Create("vcl_1.conf")
162         if err != nil {
163                 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
164         }
165         socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/1", workDir)
166         fmt.Fprintf(f, vclTemplate, socketPath, "1")
167         f.Close()
168
169         os.Setenv("VCL_CONFIG", "./vcl_1.conf")
170         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
181 func (a *Actions) RunVclEchoClient(args []string) *ActionResult {
182         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         }
189         socketPath := fmt.Sprintf("%s/var/run/app_ns_sockets/2", workDir)
190         fmt.Fprintf(f, vclTemplate, socketPath, "2")
191         f.Close()
192
193         os.Setenv("VCL_CONFIG", "./vcl_2.conf")
194         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
203 func configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64, optionalHardwareAddress ...string) ConfFn {
204         return func(ctx context.Context,
205                 vppConn api.Connection) error {
206
207                 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                 }
214                 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
238 func (a *Actions) Configure2Veths(args []string) *ActionResult {
239         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()
247
248         vppConfig, err := deserializeVppConfig(args[2])
249         if err != nil {
250                 return NewActionResult(err, ActionResultWithDesc("deserializing configuration failed"))
251         }
252
253         con, vppErrCh := vpphelper.StartAndDialContext(ctx,
254                 vpphelper.WithVppConfig(vppConfig.getTemplate()+startup.ToString()),
255                 vpphelper.WithRootDir(workDir))
256         exitOnErrCh(ctx, cancel, vppErrCh)
257
258         var fn func(context.Context, api.Connection) error
259         switch vppConfig.Variant {
260         case "srv":
261                 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1)
262         case "srv-with-preset-hw-addr":
263                 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1, "00:00:5e:00:53:01")
264         case "cln":
265                 fallthrough
266         default:
267                 fn = configure2vethsTopo("vppcln", "10.10.10.2/24", "2", 2)
268         }
269         err = fn(ctx, con)
270         if err != nil {
271                 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
272         }
273         writeSyncFile(OkResult())
274         <-ctx.Done()
275         return nil
276 }
277
278 func configureAfPacket(ctx context.Context, vppCon api.Connection,
279         name, interfaceAddress string, optionalHardwareAddress ...string) (interface_types.InterfaceIndex, error) {
280         var err error
281         ifaceClient := interfaces.NewServiceClient(vppCon)
282         afPacketCreate := af_packet.AfPacketCreateV2{
283                 UseRandomHwAddr: true,
284                 HostIfName:      name,
285                 NumRxQueues:     1,
286         }
287         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)
296         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
326 func (a *Actions) ConfigureHttpTps(args []string) *ActionResult {
327         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 }