blob: 14d6ab6ba9d860629729e14cd0983d399231d047 [file] [log] [blame]
Maros Ondrejicka11a03e92022-12-01 09:56:37 +01001package main
2
3import (
Maros Ondrejicka11a03e92022-12-01 09:56:37 +01004 "encoding/json"
Filip Tehlarf3ee2b62023-01-09 12:07:09 +01005 "fmt"
Maros Ondrejicka11a03e92022-12-01 09:56:37 +01006 "github.com/edwarnicke/exechelper"
7)
8
9const vppConfigTemplate = `unix {
10 nodaemon
11 log %[1]s/var/log/vpp/vpp.log
12 full-coredump
13 cli-listen %[1]s%[2]s
14 runtime-dir %[1]s/var/run
15 gid vpp
16}
17
18api-trace {
19 on
20}
21
22api-segment {
23 gid vpp
24}
25
26socksvr {
27 socket-name %[1]s/var/run/vpp/api.sock
28}
29
30statseg {
31 socket-name %[1]s/var/run/vpp/stats.sock
32}
33
34plugins {
35 plugin unittest_plugin.so { enable }
36 plugin dpdk_plugin.so { disable }
37 plugin crypto_aesni_plugin.so { enable }
38 plugin quic_plugin.so { enable }
39}
40
41`
42
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010043const (
44 defaultCliSocketFilePath = "/var/run/vpp/cli.sock"
45)
46
Maros Ondrejicka11a03e92022-12-01 09:56:37 +010047type VppInstance struct {
Filip Tehlarf3ee2b62023-01-09 12:07:09 +010048 container *Container
49 config VppConfig
Maros Ondrejicka11a03e92022-12-01 09:56:37 +010050 actionFuncName string
51}
52
53type VppConfig struct {
Filip Tehlarf3ee2b62023-01-09 12:07:09 +010054 Variant string
Maros Ondrejicka11a03e92022-12-01 09:56:37 +010055 CliSocketFilePath string
56}
57
58func (vc *VppConfig) getTemplate() string {
59 return fmt.Sprintf(vppConfigTemplate, "%[1]s", vc.CliSocketFilePath)
60}
61
62func (vpp *VppInstance) set2VethsServer() {
63 vpp.actionFuncName = "Configure2Veths"
64 vpp.config.Variant = "srv"
65}
66
67func (vpp *VppInstance) set2VethsClient() {
68 vpp.actionFuncName = "Configure2Veths"
69 vpp.config.Variant = "cln"
70}
71
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010072func (vpp *VppInstance) setVppProxy() {
73 vpp.actionFuncName = "ConfigureVppProxy"
74}
75
76func (vpp *VppInstance) setEnvoyProxy() {
77 vpp.actionFuncName = "ConfigureEnvoyProxy"
78}
79
Maros Ondrejicka11a03e92022-12-01 09:56:37 +010080func (vpp *VppInstance) setCliSocket(filePath string) {
81 vpp.config.CliSocketFilePath = filePath
82}
83
84func (vpp *VppInstance) getCliSocket() string {
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010085 return fmt.Sprintf("%s%s", vpp.container.workDir, vpp.config.CliSocketFilePath)
Maros Ondrejicka11a03e92022-12-01 09:56:37 +010086}
87
88func (vpp *VppInstance) start() error {
Maros Ondrejicka11a03e92022-12-01 09:56:37 +010089 if vpp.actionFuncName == "" {
90 return fmt.Errorf("vpp start failed: action function name must not be blank")
91 }
92
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010093 serializedConfig, err := serializeVppConfig(vpp.config)
Filip Tehlar56160412023-01-25 13:56:38 +010094 if err != nil {
95 return fmt.Errorf("serialize vpp config: %v", err)
96 }
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010097 args := fmt.Sprintf("%s '%s'", vpp.actionFuncName, serializedConfig)
98 _, err = vpp.container.execAction(args)
Maros Ondrejicka11a03e92022-12-01 09:56:37 +010099 if err != nil {
100 return fmt.Errorf("vpp start failed: %s", err)
101 }
102
103 return nil
104}
105
106func (vpp *VppInstance) vppctl(command string) (string, error) {
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100107 cliExecCommand := fmt.Sprintf("docker exec --detach=false %[1]s vppctl -s %[2]s %[3]s",
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100108 vpp.container.name, vpp.getCliSocket(), command)
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100109 output, err := exechelper.CombinedOutput(cliExecCommand)
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100110 if err != nil {
111 return "", fmt.Errorf("vppctl failed: %s", err)
112 }
113
114 return string(output), nil
115}
116
117func NewVppInstance(c *Container) *VppInstance {
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100118 var vppConfig VppConfig
119 vppConfig.CliSocketFilePath = defaultCliSocketFilePath
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100120 vpp := new(VppInstance)
121 vpp.container = c
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100122 vpp.config = vppConfig
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100123 return vpp
124}
125
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100126func serializeVppConfig(vppConfig VppConfig) (string, error) {
127 serializedConfig, err := json.Marshal(vppConfig)
128 if err != nil {
129 return "", fmt.Errorf("vpp start failed: serializing configuration failed: %s", err)
130 }
131 return string(serializedConfig), nil
132}
133
134func deserializeVppConfig(input string) (VppConfig, error) {
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100135 var vppConfig VppConfig
136 err := json.Unmarshal([]byte(input), &vppConfig)
137 if err != nil {
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100138 // Since input is not a valid JSON it is going be used as a variant value
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100139 // for compatibility reasons
140 vppConfig.Variant = input
Maros Ondrejickadb823ed2022-12-14 16:30:04 +0100141 vppConfig.CliSocketFilePath = defaultCliSocketFilePath
Maros Ondrejicka11a03e92022-12-01 09:56:37 +0100142 }
143 return vppConfig, nil
144}