blob: 7525085632a66919ab5a486be931bbe54c03f77c [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
22func 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)
Maros Ondrejicka0db15752022-10-12 22:58:01 +020032 reg("vcl-test-server", RunVclEchoServer)
33 reg("vcl-test-client", RunVclEchoClient)
Filip Tehlar229f5fc2022-08-09 14:44:47 +000034}
35
36func 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
54func 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
71func 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
101func 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
109func 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
117func 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
130func 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
142func 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
147func 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}
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200151
152func 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
172func 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
193func configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64, optionalHardwareAddress ...string) ConfFn {
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000194 return func(ctx context.Context,
195 vppConn api.Connection) error {
196
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200197 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 }
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000204 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
228func 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)
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200245 } 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")
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000247 } 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
259func configureAfPacket(ctx context.Context, vppCon api.Connection,
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200260 name, interfaceAddress string, optionalHardwareAddress ...string) (interface_types.InterfaceIndex, error) {
261 var err error
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000262 ifaceClient := interfaces.NewServiceClient(vppCon)
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200263 afPacketCreate := af_packet.AfPacketCreateV2{
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000264 UseRandomHwAddr: true,
265 HostIfName: name,
266 NumRxQueues: 1,
267 }
Maros Ondrejicka0db15752022-10-12 22:58:01 +0200268 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)
Filip Tehlar229f5fc2022-08-09 14:44:47 +0000277 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
307func 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}