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/memclnt"
30 "git.fd.io/govpp.git/binapi/vpe"
31 "git.fd.io/govpp.git/core"
36 sockAddr = flag.String("socket", socketclient.DefaultSocketName, "Path to VPP API socket file")
42 fmt.Printf("Starting api-trace tool example\n\n")
44 // make synchronous VPP connection
45 conn, err := govpp.Connect(*sockAddr)
47 log.Fatalln("ERROR:", err)
49 defer conn.Disconnect()
55 fmt.Printf("Api-trace tool example finished\n\n")
58 func singleChannel(conn *core.Connection) {
59 // create new channel and perform simple compatibility check
60 ch, err := conn.NewAPIChannel()
62 log.Fatalln("ERROR: creating channel failed:", err)
66 fmt.Printf("=> Example 1\n\nEnabling API trace...\n")
67 conn.Trace().Enable(true)
69 if err := ch.CheckCompatiblity(append(vpe.AllMessages(), interfaces.AllMessages()...)...); err != nil {
74 fmt.Printf("Calling VPP API...\n")
76 idx := createLoopback(ch)
77 addIPAddress("10.10.0.1/24", ch, idx)
79 deleteLoopback(ch, idx)
82 fmt.Printf("API trace (api calls: %d):\n", len(conn.Trace().GetRecords()))
83 fmt.Printf("--------------------\n")
84 for _, item := range conn.Trace().GetRecords() {
87 fmt.Printf("--------------------\n")
89 fmt.Printf("Clearing API trace...\n\n")
93 func multiChannel(conn *core.Connection) {
94 ch1, err := conn.NewAPIChannel()
96 log.Fatalln("ERROR: creating channel failed:", err)
99 ch2, err := conn.NewAPIChannel()
101 log.Fatalln("ERROR: creating channel failed:", err)
106 fmt.Printf("=> Example 2\n\nCalling VPP API (multi-channel)...\n")
108 idx1 := createLoopback(ch1)
109 idx2 := createLoopback(ch2)
110 addIPAddress("20.10.0.1/24", ch1, idx1)
111 addIPAddress("30.10.0.1/24", ch2, idx2)
113 deleteLoopback(ch2, idx1)
114 deleteLoopback(ch1, idx2)
117 chan1, ok := ch1.(*core.Channel)
119 log.Fatalln("ERROR: incorrect type of channel 1:", err)
121 chan2, ok := ch2.(*core.Channel)
123 log.Fatalln("ERROR: incorrect type of channel 2:", err)
126 fmt.Printf("API trace for channel 1 (api calls: %d):\n", len(conn.Trace().GetRecordsForChannel(chan1.GetID())))
127 fmt.Printf("--------------------\n")
128 for _, item := range conn.Trace().GetRecordsForChannel(chan1.GetID()) {
131 fmt.Printf("--------------------\n")
132 fmt.Printf("API trace for channel 2 (api calls: %d):\n", len(conn.Trace().GetRecordsForChannel(chan2.GetID())))
133 fmt.Printf("--------------------\n")
134 for _, item := range conn.Trace().GetRecordsForChannel(chan2.GetID()) {
137 fmt.Printf("--------------------\n")
138 fmt.Printf("cumulative API trace (api calls: %d):\n", len(conn.Trace().GetRecords()))
139 fmt.Printf("--------------------\n")
140 for _, item := range conn.Trace().GetRecords() {
143 fmt.Printf("--------------------\n")
145 fmt.Printf("Clearing API trace...\n\n")
149 func stream(conn *core.Connection) {
150 // create new channel and perform simple compatibility check
151 s, err := conn.NewStream(context.Background())
153 log.Fatalln("ERROR: creating channel failed:", err)
156 if err := s.Close(); err != nil {
157 log.Fatalf("failed to close stream: %v", err)
162 fmt.Printf("=> Example 3\n\nCalling VPP API (stream)...\n")
163 invokeRetrieveVersion(conn)
164 idx := invokeCreateLoopback(conn)
165 invokeAddIPAddress("40.10.0.1/24", conn, idx)
166 invokeInterfaceDump(conn)
167 invokeDeleteLoopback(conn, idx)
170 fmt.Printf("stream API trace (api calls: %d):\n", len(conn.Trace().GetRecords()))
171 fmt.Printf("--------------------\n")
172 for _, item := range conn.Trace().GetRecords() {
175 fmt.Printf("--------------------\n")
177 fmt.Printf("Clearing API trace...\n\n")
178 conn.Trace().GetRecords()
181 func retrieveVersion(ch api.Channel) {
182 req := &vpe.ShowVersion{}
183 reply := &vpe.ShowVersionReply{}
185 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
186 fmt.Printf("ERROR: %v\n", err)
189 fmt.Printf(" - retrieved VPP version: %s\n", reply.Version)
192 func invokeRetrieveVersion(c api.Connection) {
193 req := &vpe.ShowVersion{}
194 reply := &vpe.ShowVersionReply{}
196 if err := c.Invoke(context.Background(), req, reply); err != nil {
197 fmt.Printf("ERROR: %v\n", err)
199 fmt.Printf(" - retrieved VPP version: %s\n", reply.Version)
202 func createLoopback(ch api.Channel) interface_types.InterfaceIndex {
203 req := &interfaces.CreateLoopback{}
204 reply := &interfaces.CreateLoopbackReply{}
206 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
207 fmt.Printf("ERROR: %v\n", err)
210 fmt.Printf(" - created loopback with index: %d\n", reply.SwIfIndex)
211 return reply.SwIfIndex
214 func invokeCreateLoopback(c api.Connection) interface_types.InterfaceIndex {
215 req := &interfaces.CreateLoopback{}
216 reply := &interfaces.CreateLoopbackReply{}
218 if err := c.Invoke(context.Background(), req, reply); err != nil {
219 fmt.Printf("ERROR: %v\n", err)
222 fmt.Printf(" - created loopback with index: %d\n", reply.SwIfIndex)
223 return reply.SwIfIndex
226 func deleteLoopback(ch api.Channel, index interface_types.InterfaceIndex) {
227 req := &interfaces.DeleteLoopback{
230 reply := &interfaces.DeleteLoopbackReply{}
232 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
233 fmt.Printf("ERROR: %v\n", err)
236 fmt.Printf(" - deleted loopback with index: %d\n", index)
239 func invokeDeleteLoopback(c api.Connection, index interface_types.InterfaceIndex) {
240 req := &interfaces.DeleteLoopback{
243 reply := &interfaces.DeleteLoopbackReply{}
245 if err := c.Invoke(context.Background(), req, reply); err != nil {
246 fmt.Printf("ERROR: %v\n", err)
249 fmt.Printf(" - deleted loopback with index: %d\n", index)
252 func addIPAddress(addr string, ch api.Channel, index interface_types.InterfaceIndex) {
253 ipAddr, err := ip_types.ParsePrefix(addr)
255 fmt.Printf("ERROR: %v\n", err)
259 req := &interfaces.SwInterfaceAddDelAddress{
262 Prefix: ip_types.AddressWithPrefix(ipAddr),
264 reply := &interfaces.SwInterfaceAddDelAddressReply{}
266 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
267 fmt.Printf("ERROR: %v\n", err)
270 fmt.Printf(" - IP address %s added to interface with index %d\n", addr, index)
273 func invokeAddIPAddress(addr string, c api.Connection, index interface_types.InterfaceIndex) {
274 ipAddr, err := ip_types.ParsePrefix(addr)
276 fmt.Printf("ERROR: %v\n", err)
280 req := &interfaces.SwInterfaceAddDelAddress{
283 Prefix: ip_types.AddressWithPrefix(ipAddr),
285 reply := &interfaces.SwInterfaceAddDelAddressReply{}
287 if err := c.Invoke(context.Background(), req, reply); err != nil {
288 fmt.Printf("ERROR: %v\n", err)
291 fmt.Printf(" - IP address %s added to interface with index %d\n", addr, index)
294 func interfaceDump(ch api.Channel) {
295 reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{
296 SwIfIndex: ^interface_types.InterfaceIndex(0),
299 msg := &interfaces.SwInterfaceDetails{}
300 stop, err := reqCtx.ReceiveReply(msg)
305 fmt.Printf("ERROR: %v\n", err)
308 fmt.Printf(" - retrieved interface: %v (idx: %d)\n", msg.InterfaceName, msg.SwIfIndex)
312 func invokeInterfaceDump(c api.Connection) {
313 s, err := c.NewStream(context.Background())
315 fmt.Printf("ERROR: %v\n", err)
318 if err := s.SendMsg(&interfaces.SwInterfaceDump{}); err != nil {
319 fmt.Printf("ERROR: %v\n", err)
322 if err := s.SendMsg(&memclnt.ControlPing{}); err != nil {
323 fmt.Printf("ERROR: %v\n", err)
327 reply, err := s.RecvMsg()
329 fmt.Printf("ERROR: %v\n", err)
332 switch msg := reply.(type) {
333 case *interfaces.SwInterfaceDetails:
334 fmt.Printf(" - retrieved interface: %v (idx: %d)\n", msg.InterfaceName, msg.SwIfIndex)
335 case *memclnt.ControlPingReply:
341 func printTrace(item *api.Record) {
342 h, m, s := item.Timestamp.Clock()
347 fmt.Printf("%dh:%dm:%ds:%dns %s %s\n", h, m, s,
348 item.Timestamp.Nanosecond(), item.Message.GetMessageName(), reply)