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