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"
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 reg("http-cli-srv", RunHttpCliSrv)
35 reg("http-cli-cln", RunHttpCliCln)
38 func configureProxyTcp(ifName0, ipAddr0, ifName1, ipAddr1 string) ConfFn {
39 return func(ctx context.Context,
40 vppConn api.Connection) error {
42 _, err := configureAfPacket(ctx, vppConn, ifName0, ipAddr0)
44 fmt.Printf("failed to create af packet: %v", err)
47 _, err = configureAfPacket(ctx, vppConn, ifName1, ipAddr1)
49 fmt.Printf("failed to create af packet: %v", err)
56 func RunHttpCliSrv(args []string) *ActionResult {
57 cmd := fmt.Sprintf("http cli server")
58 return ApiCliInband("/tmp/2veths", cmd)
61 func RunHttpCliCln(args []string) *ActionResult {
62 cmd := fmt.Sprintf("http cli client uri http://10.10.10.1/80 query %s", getArgs())
64 return ApiCliInband("/tmp/2veths", cmd)
67 func ConfigureVppProxy(args []string) *ActionResult {
68 ctx, cancel := newVppContext()
71 con, vppErrCh := vpphelper.StartAndDialContext(ctx, vpphelper.WithVppConfig(configTemplate))
72 exitOnErrCh(ctx, cancel, vppErrCh)
74 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
75 err := confFn(ctx, con)
77 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
79 writeSyncFile(OkResult())
84 func ConfigureEnvoyProxy(args []string) *ActionResult {
89 Append("use-app-socket-api").
90 Append("evt_qs_memfd_seg").
91 Append("event-queue-length 100000").Close()
92 ctx, cancel := newVppContext()
95 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
96 vpphelper.WithVppConfig(configTemplate+startup.ToString()),
97 vpphelper.WithRootDir("/tmp/vpp-envoy"))
98 exitOnErrCh(ctx, cancel, vppErrCh)
100 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
101 err := confFn(ctx, con)
103 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
105 err0 := exechelper.Run("chmod 777 -R /tmp/vpp-envoy")
107 return NewActionResult(err, ActionResultWithDesc("setting permissions failed"))
109 writeSyncFile(OkResult())
114 func getArgs() string {
116 for i := 2; i < len(os.Args); i++ {
117 s = s + " " + os.Args[i]
122 func ApiCliInband(root, cmd string) *ActionResult {
123 ctx, _ := newVppContext()
124 con := vpphelper.DialContext(ctx, filepath.Join(root, "/var/run/vpp/api.sock"))
125 cliInband := vlib.CliInband{Cmd: cmd}
126 cliInbandReply, err := vlib.NewServiceClient(con).CliInband(ctx, &cliInband)
127 return NewActionResult(err, ActionResultWithStdout(cliInbandReply.Reply))
130 func RunEchoClient(args []string) *ActionResult {
131 outBuff := bytes.NewBuffer([]byte{})
132 errBuff := bytes.NewBuffer([]byte{})
134 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])
135 err := exechelper.Run(cmd,
136 exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff),
137 exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr))
139 return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
140 ActionResultWithStderr(string(errBuff.String())))
143 func RunEchoServer(args []string) *ActionResult {
144 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])
145 errCh := exechelper.Start(cmd)
148 writeSyncFile(NewActionResult(err, ActionResultWithDesc("echo_server: ")))
151 writeSyncFile(OkResult())
155 func RunEchoSrvInternal() *ActionResult {
156 cmd := fmt.Sprintf("test echo server %s uri tcp://10.10.10.1/1234", getArgs())
157 return ApiCliInband("/tmp/2veths", cmd)
160 func RunEchoClnInternal() *ActionResult {
161 cmd := fmt.Sprintf("test echo client %s uri tcp://10.10.10.1/1234", getArgs())
162 return ApiCliInband("/tmp/2veths", cmd)
165 func RunVclEchoServer(args []string) *ActionResult {
166 f, err := os.Create("vcl_1.conf")
168 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
170 fmt.Fprintf(f, vclTemplate, "/tmp/echo-srv/var/run/app_ns_sockets/1", "1")
173 os.Setenv("VCL_CONFIG", "/vcl_1.conf")
174 cmd := fmt.Sprintf("vcl_test_server -p %s 12346", args[2])
175 errCh := exechelper.Start(cmd)
178 writeSyncFile(NewActionResult(err, ActionResultWithDesc("vcl_test_server: ")))
181 writeSyncFile(OkResult())
185 func RunVclEchoClient(args []string) *ActionResult {
186 outBuff := bytes.NewBuffer([]byte{})
187 errBuff := bytes.NewBuffer([]byte{})
189 f, err := os.Create("vcl_2.conf")
191 return NewActionResult(err, ActionResultWithStderr(("create vcl config: ")))
193 fmt.Fprintf(f, vclTemplate, "/tmp/echo-cln/var/run/app_ns_sockets/2", "2")
196 os.Setenv("VCL_CONFIG", "/vcl_2.conf")
197 cmd := fmt.Sprintf("vcl_test_client -U -p %s 10.10.10.1 12346", args[2])
198 err = exechelper.Run(cmd,
199 exechelper.WithStdout(outBuff), exechelper.WithStderr(errBuff),
200 exechelper.WithStdout(os.Stdout), exechelper.WithStderr(os.Stderr))
202 return NewActionResult(err, ActionResultWithStdout(string(outBuff.String())),
203 ActionResultWithStderr(string(errBuff.String())))
206 func configure2vethsTopo(ifName, interfaceAddress, namespaceId string, secret uint64, optionalHardwareAddress ...string) ConfFn {
207 return func(ctx context.Context,
208 vppConn api.Connection) error {
210 var swIfIndex interface_types.InterfaceIndex
212 if optionalHardwareAddress == nil {
213 swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress)
215 swIfIndex, err = configureAfPacket(ctx, vppConn, ifName, interfaceAddress, optionalHardwareAddress[0])
218 fmt.Printf("failed to create af packet: %v", err)
220 _, er := session.NewServiceClient(vppConn).AppNamespaceAddDelV2(ctx, &session.AppNamespaceAddDelV2{
222 SwIfIndex: swIfIndex,
223 NamespaceID: namespaceId,
226 fmt.Printf("add app namespace: %v", err)
230 _, er1 := session.NewServiceClient(vppConn).SessionEnableDisable(ctx, &session.SessionEnableDisable{
234 fmt.Printf("session enable %v", err)
241 func Configure2Veths(args []string) *ActionResult {
244 NewStanza("session").
246 Append("use-app-socket-api").Close()
248 ctx, cancel := newVppContext()
250 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
251 vpphelper.WithVppConfig(configTemplate+startup.ToString()),
252 vpphelper.WithRootDir(fmt.Sprintf("/tmp/%s", args[1])))
253 exitOnErrCh(ctx, cancel, vppErrCh)
255 var fn func(context.Context, api.Connection) error
256 if args[2] == "srv" {
257 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1)
258 } else if args[2] == "srv-with-preset-hw-addr" {
259 fn = configure2vethsTopo("vppsrv", "10.10.10.1/24", "1", 1, "00:00:5e:00:53:01")
261 fn = configure2vethsTopo("vppcln", "10.10.10.2/24", "2", 2)
265 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
267 writeSyncFile(OkResult())
272 func configureAfPacket(ctx context.Context, vppCon api.Connection,
273 name, interfaceAddress string, optionalHardwareAddress ...string) (interface_types.InterfaceIndex, error) {
275 ifaceClient := interfaces.NewServiceClient(vppCon)
276 afPacketCreate := af_packet.AfPacketCreateV2{
277 UseRandomHwAddr: true,
281 if len(optionalHardwareAddress) > 0 {
282 afPacketCreate.HwAddr, err = ethernet_types.ParseMacAddress(optionalHardwareAddress[0])
284 fmt.Printf("failed to parse mac address: %v", err)
287 afPacketCreate.UseRandomHwAddr = false
289 afPacketCreateRsp, err := af_packet.NewServiceClient(vppCon).AfPacketCreateV2(ctx, &afPacketCreate)
291 fmt.Printf("failed to create af packet: %v", err)
294 _, err = ifaceClient.SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{
295 SwIfIndex: afPacketCreateRsp.SwIfIndex,
296 Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
299 fmt.Printf("set interface state up failed: %v\n", err)
302 ipPrefix, err := ip_types.ParseAddressWithPrefix(interfaceAddress)
304 fmt.Printf("parse ip address %v\n", err)
307 ipAddress := &interfaces.SwInterfaceAddDelAddress{
309 SwIfIndex: afPacketCreateRsp.SwIfIndex,
312 _, errx := ifaceClient.SwInterfaceAddDelAddress(ctx, ipAddress)
314 fmt.Printf("add ip address %v\n", err)
317 return afPacketCreateRsp.SwIfIndex, nil
320 func ConfigureHttpTps(args []string) *ActionResult {
321 ctx, cancel := newVppContext()
323 con, vppErrCh := vpphelper.StartAndDialContext(ctx,
324 vpphelper.WithVppConfig(configTemplate))
325 exitOnErrCh(ctx, cancel, vppErrCh)
327 confFn := configureProxyTcp("vpp0", "10.0.0.2/24", "vpp1", "10.0.1.2/24")
328 err := confFn(ctx, con)
330 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
333 _, err = session.NewServiceClient(con).SessionEnableDisable(ctx, &session.SessionEnableDisable{
337 return NewActionResult(err, ActionResultWithDesc("configuration failed"))
339 Vppcli("", "http tps uri tcp://0.0.0.0/8080")
340 writeSyncFile(OkResult())