hs-test: auto register test actions
[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 type ConfFn func(context.Context, api.Connection) error
23
24 type Actions struct {
25 }
26
27 func configureProxyTcp(ifName0, ipAddr0, ifName1, ipAddr1 string) ConfFn {
28         return func(ctx context.Context,
29                 vppConn api.Connection) error {
30
31                 _, err := configureAfPacket(ctx, vppConn, ifName0, ipAddr0)
32                 if err != nil {
33                         fmt.Printf("failed to create af packet: %v", err)
34                         return err
35                 }
36                 _, err = configureAfPacket(ctx, vppConn, ifName1, ipAddr1)
37                 if err != nil {
38                         fmt.Printf("failed to create af packet: %v", err)
39                         return err
40                 }
41                 return nil
42         }
43 }
44
45 func (a *Actions) RunHttpCliSrv(args []string) *ActionResult {
46         cmd := fmt.Sprintf("http cli server")
47         return ApiCliInband("/tmp/Configure2Veths", cmd)
48 }
49
50 func (a *Actions) RunHttpCliCln(args []string) *ActionResult {
51         cmd := fmt.Sprintf("http cli client uri http://10.10.10.1/80 query %s", getArgs())
52         fmt.Println(cmd)
53         return ApiCliInband("/tmp/Configure2Veths", cmd)
54 }
55
56 func (a *Actions) ConfigureVppProxy(args []string) *ActionResult {
57         ctx, cancel := newVppContext()
58         defer cancel()
59
60         con, vppErrCh := vpphelper.StartAndDialContext(ctx, vpphelper.WithVppConfig(configTemplate))
61         exitOnErrCh(ctx, cancel, vppErrCh)
62
63         confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
64         err := confFn(ctx, con)
65         if err != nil {
66                 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
67         }
68         writeSyncFile(OkResult())
69         <-ctx.Done()
70         return nil
71 }
72
73 func (a *Actions) ConfigureEnvoyProxy(args []string) *ActionResult {
74         var startup Stanza
75         startup.
76                 NewStanza("session").
77                 Append("enable").
78                 Append("use-app-socket-api").
79                 Append("evt_qs_memfd_seg").
80                 Append("event-queue-length 100000").Close()
81         ctx, cancel := newVppContext()
82         defer cancel()
83
84         con, vppErrCh := vpphelper.StartAndDialContext(ctx,
85                 vpphelper.WithVppConfig(configTemplate+startup.ToString()),
86                 vpphelper.WithRootDir("/tmp/vpp-envoy"))
87         exitOnErrCh(ctx, cancel, vppErrCh)
88
89         confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
90         err := confFn(ctx, con)
91         if err != nil {
92                 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
93         }
94         err0 := exechelper.Run("chmod 777 -R /tmp/vpp-envoy")
95         if err0 != nil {
96                 return NewActionResult(err, ActionResultWithDesc("setting permissions failed"))
97         }
98         writeSyncFile(OkResult())
99         <-ctx.Done()
100         return nil
101 }
102
103 func getArgs() string {
104         s := ""
105         for i := 2; i < len(os.Args); i++ {
106                 s = s + " " + os.Args[i]
107         }
108         return s
109 }
110
111 func ApiCliInband(root, cmd string) *ActionResult {
112         ctx, _ := newVppContext()
113         con := vpphelper.DialContext(ctx, filepath.Join(root, "/var/run/vpp/api.sock"))
114         cliInband := vlib.CliInband{Cmd: cmd}
115         cliInbandReply, err := vlib.NewServiceClient(con).CliInband(ctx, &cliInband)
116         return NewActionResult(err, ActionResultWithStdout(cliInbandReply.Reply))
117 }
118
119 func (a *Actions) RunEchoClient(args []string) *ActionResult {
120         outBuff := bytes.NewBuffer([]byte{})
121         errBuff := bytes.NewBuffer([]byte{})
122
123         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])
124         err := exechelper.Run(cmd,
125                 exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff),
126                 exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr))
127
128         return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
129                 ActionResultWithStderr(string(errBuff.String())))
130 }
131
132 func (a *Actions) RunEchoServer(args []string) *ActionResult {
133         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])
134         errCh := exechelper.Start(cmd)
135         select {
136         case err := <-errCh:
137                 writeSyncFile(NewActionResult(err, ActionResultWithDesc("echo_server: ")))
138         default:
139         }
140         writeSyncFile(OkResult())
141         return nil
142 }
143
144 func (a *Actions) RunEchoSrvInternal(args []string) *ActionResult {
145         cmd := fmt.Sprintf("test echo server %s uri tcp://10.10.10.1/1234", getArgs())
146         return ApiCliInband("/tmp/Configure2Veths", cmd)
147 }
148
149 func (a *Actions) RunEchoClnInternal(args []string) *ActionResult {
150         cmd := fmt.Sprintf("test echo client %s uri tcp://10.10.10.1/1234", getArgs())
151         return ApiCliInband("/tmp/Configure2Veths", cmd)
152 }
153
154 func (a *Actions) RunVclEchoServer(args []string) *ActionResult {
155         f, err := os.Create("vcl_1.conf")
156         if err != nil {
157                 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
158         }
159         fmt.Fprintf(f, vclTemplate, "/tmp/echo-srv/var/run/app_ns_sockets/1", "1")
160         f.Close()
161
162         os.Setenv("VCL_CONFIG", "/vcl_1.conf")
163         cmd := fmt.Sprintf("vcl_test_server -p %s 12346", args[2])
164         errCh := exechelper.Start(cmd)
165         select {
166         case err := <-errCh:
167                 writeSyncFile(NewActionResult(err, ActionResultWithDesc("vcl_test_server: ")))
168         default:
169         }
170         writeSyncFile(OkResult())
171         return nil
172 }
173
174 func (a *Actions) RunVclEchoClient(args []string) *ActionResult {
175         outBuff := bytes.NewBuffer([]byte{})
176         errBuff := bytes.NewBuffer([]byte{})
177
178         f, err := os.Create("vcl_2.conf")
179         if err != nil {
180                 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
181         }
182         fmt.Fprintf(f, vclTemplate, "/tmp/echo-cln/var/run/app_ns_sockets/2", "2")
183         f.Close()
184
185         os.Setenv("VCL_CONFIG", "/vcl_2.conf")
186         cmd := fmt.Sprintf("vcl_test_client -U -p %s 10.10.10.1 12346", args[2])
187         err = exechelper.Run(cmd,
188                 exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff),
189                 exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr))
190
191         return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
192                 ActionResultWithStderr(string(errBuff.String())))
193 }
194
195 func configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64, optionalHardwareAddress ...string) ConfFn {
196         return func(ctx context.Context,
197                 vppConn api.Connection) error {
198
199                 var swIfIndex interface_types.InterfaceIndex
200                 var err error
201                 if optionalHardwareAddress == nil {
202                         swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress)
203                 } else {
204                         swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress, optionalHardwareAddress[0])
205                 }
206                 if err != nil {
207                         fmt.Printf("failed to create af packet: %v", err)
208                 }
209                 _, er := session.NewServiceClient(vppConn).AppNamespaceAddDelV2(ctx, &session.AppNamespaceAddDelV2{
210                         Secret:      secret,
211                         SwIfIndex:   swIfIndex,
212                         NamespaceID: namespaceId,
213                 })
214                 if er != nil {
215                         fmt.Printf("add app namespace: %v", err)
216                         return err
217                 }
218
219                 _, er1 := session.NewServiceClient(vppConn).SessionEnableDisable(ctx, &session.SessionEnableDisable{
220                         IsEnable: true,
221                 })
222                 if er1 != nil {
223                         fmt.Printf("session enable %v", err)
224                         return err
225                 }
226                 return nil
227         }
228 }
229
230 func (a *Actions) Configure2Veths(args []string) *ActionResult {
231         var startup Stanza
232         startup.
233                 NewStanza("session").
234                 Append("enable").
235                 Append("use-app-socket-api").Close()
236
237         ctx, cancel := newVppContext()
238         defer cancel()
239         con, vppErrCh := vpphelper.StartAndDialContext(ctx,
240                 vpphelper.WithVppConfig(configTemplate+startup.ToString()),
241                 vpphelper.WithRootDir(fmt.Sprintf("/tmp/%s", args[1])))
242         exitOnErrCh(ctx, cancel, vppErrCh)
243
244         var fn func(context.Context, api.Connection) error
245         if args[2] == "srv" {
246                 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1)
247         } else if args[2] == "srv-with-preset-hw-addr" {
248                 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1, "00:00:5e:00:53:01")
249         } else {
250                 fn = configure2vethsTopo("vppcln", "10.10.10.2/24", "2", 2)
251         }
252         err := fn(ctx, con)
253         if err != nil {
254                 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
255         }
256         writeSyncFile(OkResult())
257         <-ctx.Done()
258         return nil
259 }
260
261 func configureAfPacket(ctx context.Context, vppCon api.Connection,
262         name, interfaceAddress string, optionalHardwareAddress ...string) (interface_types.InterfaceIndex, error) {
263         var err error
264         ifaceClient := interfaces.NewServiceClient(vppCon)
265         afPacketCreate := af_packet.AfPacketCreateV2{
266                 UseRandomHwAddr: true,
267                 HostIfName:      name,
268                 NumRxQueues:     1,
269         }
270         if len(optionalHardwareAddress) > 0 {
271                 afPacketCreate.HwAddr, err = ethernet_types.ParseMacAddress(optionalHardwareAddress[0])
272                 if err != nil {
273                         fmt.Printf("failed to parse mac address: %v", err)
274                         return 0, err
275                 }
276                 afPacketCreate.UseRandomHwAddr = false
277         }
278         afPacketCreateRsp, err := af_packet.NewServiceClient(vppCon).AfPacketCreateV2(ctx, &afPacketCreate)
279         if err != nil {
280                 fmt.Printf("failed to create af packet: %v", err)
281                 return 0, err
282         }
283         _, err = ifaceClient.SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{
284                 SwIfIndex: afPacketCreateRsp.SwIfIndex,
285                 Flags:     interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
286         })
287         if err != nil {
288                 fmt.Printf("set interface state up failed: %v\n", err)
289                 return 0, err
290         }
291         ipPrefix, err := ip_types.ParseAddressWithPrefix(interfaceAddress)
292         if err != nil {
293                 fmt.Printf("parse ip address %v\n", err)
294                 return 0, err
295         }
296         ipAddress := &interfaces.SwInterfaceAddDelAddress{
297                 IsAdd:     true,
298                 SwIfIndex: afPacketCreateRsp.SwIfIndex,
299                 Prefix:    ipPrefix,
300         }
301         _, errx := ifaceClient.SwInterfaceAddDelAddress(ctx, ipAddress)
302         if errx != nil {
303                 fmt.Printf("add ip address %v\n", err)
304                 return 0, err
305         }
306         return afPacketCreateRsp.SwIfIndex, nil
307 }
308
309 func (a *Actions) ConfigureHttpTps(args []string) *ActionResult {
310         ctx, cancel := newVppContext()
311         defer cancel()
312         con, vppErrCh := vpphelper.StartAndDialContext(ctx,
313                 vpphelper.WithVppConfig(configTemplate))
314         exitOnErrCh(ctx, cancel, vppErrCh)
315
316         confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
317         err := confFn(ctx, con)
318         if err != nil {
319                 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
320         }
321
322         _, err = session.NewServiceClient(con).SessionEnableDisable(ctx, &session.SessionEnableDisable{
323                 IsEnable: true,
324         })
325         if err != nil {
326                 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
327         }
328         Vppcli("", "http tps uri tcp://0.0.0.0/8080")
329         writeSyncFile(OkResult())
330         <-ctx.Done()
331         return nil
332 }