1 // Copyright (c) 2021 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 // api-trace is and example how to use the GoVPP API trace tool.
24 "git.fd.io/govpp.git/adapter/socketclient"
25 "git.fd.io/govpp.git/api"
26 interfaces "git.fd.io/govpp.git/binapi/interface"
27 "git.fd.io/govpp.git/binapi/interface_types"
28 "git.fd.io/govpp.git/binapi/ip_types"
29 "git.fd.io/govpp.git/binapi/vpe"
30 "git.fd.io/govpp.git/core"
35 sockAddr = flag.String("socket", socketclient.DefaultSocketName, "Path to VPP API socket file")
41 fmt.Printf("Starting api-trace tool example\n\n")
43 // make synchronous VPP connection
44 conn, err := govpp.Connect(*sockAddr)
46 log.Fatalln("ERROR:", err)
48 defer conn.Disconnect()
54 fmt.Printf("Api-trace tool example finished\n\n")
57 func singleChannel(conn *core.Connection) {
58 // create new channel and perform simple compatibility check
59 ch, err := conn.NewAPIChannel()
61 log.Fatalln("ERROR: creating channel failed:", err)
65 fmt.Printf("=> Example 1\n\nEnabling API trace...\n")
66 conn.Trace().Enable(true)
68 if err := ch.CheckCompatiblity(append(vpe.AllMessages(), interfaces.AllMessages()...)...); err != nil {
73 fmt.Printf("Calling VPP API...\n")
75 idx := createLoopback(ch)
76 addIPAddress("10.10.0.1/24", ch, idx)
78 deleteLoopback(ch, idx)
81 fmt.Printf("API trace (api calls: %d):\n", len(conn.Trace().GetRecords()))
82 fmt.Printf("--------------------\n")
83 for _, item := range conn.Trace().GetRecords() {
86 fmt.Printf("--------------------\n")
88 fmt.Printf("Clearing API trace...\n\n")
92 func multiChannel(conn *core.Connection) {
93 ch1, err := conn.NewAPIChannel()
95 log.Fatalln("ERROR: creating channel failed:", err)
98 ch2, err := conn.NewAPIChannel()
100 log.Fatalln("ERROR: creating channel failed:", err)
105 fmt.Printf("=> Example 2\n\nCalling VPP API (multi-channel)...\n")
107 idx1 := createLoopback(ch1)
108 idx2 := createLoopback(ch2)
109 addIPAddress("20.10.0.1/24", ch1, idx1)
110 addIPAddress("30.10.0.1/24", ch2, idx2)
112 deleteLoopback(ch2, idx1)
113 deleteLoopback(ch1, idx2)
116 chan1, ok := ch1.(*core.Channel)
118 log.Fatalln("ERROR: incorrect type of channel 1:", err)
120 chan2, ok := ch2.(*core.Channel)
122 log.Fatalln("ERROR: incorrect type of channel 2:", err)
125 fmt.Printf("API trace for channel 1 (api calls: %d):\n", len(conn.Trace().GetRecordsForChannel(chan1.GetID())))
126 fmt.Printf("--------------------\n")
127 for _, item := range conn.Trace().GetRecordsForChannel(chan1.GetID()) {
130 fmt.Printf("--------------------\n")
131 fmt.Printf("API trace for channel 2 (api calls: %d):\n", len(conn.Trace().GetRecordsForChannel(chan2.GetID())))
132 fmt.Printf("--------------------\n")
133 for _, item := range conn.Trace().GetRecordsForChannel(chan2.GetID()) {
136 fmt.Printf("--------------------\n")
137 fmt.Printf("cumulative API trace (api calls: %d):\n", len(conn.Trace().GetRecords()))
138 fmt.Printf("--------------------\n")
139 for _, item := range conn.Trace().GetRecords() {
142 fmt.Printf("--------------------\n")
144 fmt.Printf("Clearing API trace...\n\n")
148 func stream(conn *core.Connection) {
149 // create new channel and perform simple compatibility check
150 s, err := conn.NewStream(context.Background())
152 log.Fatalln("ERROR: creating channel failed:", err)
155 if err := s.Close(); err != nil {
156 log.Fatalf("failed to close stream: %v", err)
161 fmt.Printf("=> Example 3\n\nCalling VPP API (stream)...\n")
162 invokeRetrieveVersion(conn)
163 idx := invokeCreateLoopback(conn)
164 invokeAddIPAddress("40.10.0.1/24", conn, idx)
165 invokeInterfaceDump(conn)
166 invokeDeleteLoopback(conn, idx)
169 fmt.Printf("stream API trace (api calls: %d):\n", len(conn.Trace().GetRecords()))
170 fmt.Printf("--------------------\n")
171 for _, item := range conn.Trace().GetRecords() {
174 fmt.Printf("--------------------\n")
176 fmt.Printf("Clearing API trace...\n\n")
177 conn.Trace().GetRecords()
180 func retrieveVersion(ch api.Channel) {
181 req := &vpe.ShowVersion{}
182 reply := &vpe.ShowVersionReply{}
184 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
185 fmt.Printf("ERROR: %v\n", err)
188 fmt.Printf(" - retrieved VPP version: %s\n", reply.Version)
191 func invokeRetrieveVersion(c api.Connection) {
192 req := &vpe.ShowVersion{}
193 reply := &vpe.ShowVersionReply{}
195 if err := c.Invoke(context.Background(), req, reply); err != nil {
196 fmt.Printf("ERROR: %v\n", err)
198 fmt.Printf(" - retrieved VPP version: %s\n", reply.Version)
201 func createLoopback(ch api.Channel) interface_types.InterfaceIndex {
202 req := &interfaces.CreateLoopback{}
203 reply := &interfaces.CreateLoopbackReply{}
205 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
206 fmt.Printf("ERROR: %v\n", err)
209 fmt.Printf(" - created loopback with index: %d\n", reply.SwIfIndex)
210 return reply.SwIfIndex
213 func invokeCreateLoopback(c api.Connection) interface_types.InterfaceIndex {
214 req := &interfaces.CreateLoopback{}
215 reply := &interfaces.CreateLoopbackReply{}
217 if err := c.Invoke(context.Background(), req, reply); err != nil {
218 fmt.Printf("ERROR: %v\n", err)
221 fmt.Printf(" - created loopback with index: %d\n", reply.SwIfIndex)
222 return reply.SwIfIndex
225 func deleteLoopback(ch api.Channel, index interface_types.InterfaceIndex) {
226 req := &interfaces.DeleteLoopback{
229 reply := &interfaces.DeleteLoopbackReply{}
231 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
232 fmt.Printf("ERROR: %v\n", err)
235 fmt.Printf(" - deleted loopback with index: %d\n", index)
238 func invokeDeleteLoopback(c api.Connection, index interface_types.InterfaceIndex) {
239 req := &interfaces.DeleteLoopback{
242 reply := &interfaces.DeleteLoopbackReply{}
244 if err := c.Invoke(context.Background(), req, reply); err != nil {
245 fmt.Printf("ERROR: %v\n", err)
248 fmt.Printf(" - deleted loopback with index: %d\n", index)
251 func addIPAddress(addr string, ch api.Channel, index interface_types.InterfaceIndex) {
252 ipAddr, err := ip_types.ParsePrefix(addr)
254 fmt.Printf("ERROR: %v\n", err)
258 req := &interfaces.SwInterfaceAddDelAddress{
261 Prefix: ip_types.AddressWithPrefix(ipAddr),
263 reply := &interfaces.SwInterfaceAddDelAddressReply{}
265 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
266 fmt.Printf("ERROR: %v\n", err)
269 fmt.Printf(" - IP address %s added to interface with index %d\n", addr, index)
272 func invokeAddIPAddress(addr string, c api.Connection, index interface_types.InterfaceIndex) {
273 ipAddr, err := ip_types.ParsePrefix(addr)
275 fmt.Printf("ERROR: %v\n", err)
279 req := &interfaces.SwInterfaceAddDelAddress{
282 Prefix: ip_types.AddressWithPrefix(ipAddr),
284 reply := &interfaces.SwInterfaceAddDelAddressReply{}
286 if err := c.Invoke(context.Background(), req, reply); err != nil {
287 fmt.Printf("ERROR: %v\n", err)
290 fmt.Printf(" - IP address %s added to interface with index %d\n", addr, index)
293 func interfaceDump(ch api.Channel) {
294 reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{
295 SwIfIndex: ^interface_types.InterfaceIndex(0),
298 msg := &interfaces.SwInterfaceDetails{}
299 stop, err := reqCtx.ReceiveReply(msg)
304 fmt.Printf("ERROR: %v\n", err)
307 fmt.Printf(" - retrieved interface: %v (idx: %d)\n", msg.InterfaceName, msg.SwIfIndex)
311 func invokeInterfaceDump(c api.Connection) {
312 s, err := c.NewStream(context.Background())
314 fmt.Printf("ERROR: %v\n", err)
317 if err := s.SendMsg(&interfaces.SwInterfaceDump{}); err != nil {
318 fmt.Printf("ERROR: %v\n", err)
321 if err := s.SendMsg(&vpe.ControlPing{}); err != nil {
322 fmt.Printf("ERROR: %v\n", err)
326 reply, err := s.RecvMsg()
328 fmt.Printf("ERROR: %v\n", err)
331 switch msg := reply.(type) {
332 case *interfaces.SwInterfaceDetails:
333 fmt.Printf(" - retrieved interface: %v (idx: %d)\n", msg.InterfaceName, msg.SwIfIndex)
334 case *vpe.ControlPingReply:
340 func printTrace(item *api.Record) {
341 h, m, s := item.Timestamp.Clock()
346 fmt.Printf("%dh:%dm:%ds:%dns %s %s\n", h, m, s,
347 item.Timestamp.Nanosecond(), item.Message.GetMessageName(), reply)