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