1 // Copyright (c) 2017 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 // simple-client is an example VPP management application that exercises the
16 // govpp API on real-world use-cases.
27 "git.fd.io/govpp.git/adapter/socketclient"
28 "git.fd.io/govpp.git/api"
29 "git.fd.io/govpp.git/core"
30 "git.fd.io/govpp.git/examples/binapi/interface_types"
31 "git.fd.io/govpp.git/examples/binapi/interfaces"
32 "git.fd.io/govpp.git/examples/binapi/ip"
33 "git.fd.io/govpp.git/examples/binapi/ip_types"
34 "git.fd.io/govpp.git/examples/binapi/mactime"
35 "git.fd.io/govpp.git/examples/binapi/vpe"
39 sockAddr = flag.String("sock", socketclient.DefaultSocketName, "Path to VPP binary API socket file")
45 fmt.Println("Starting simple client example")
47 // connect to VPP asynchronously
48 conn, conev, err := govpp.AsyncConnect(*sockAddr, core.DefaultMaxReconnectAttempts, core.DefaultReconnectInterval)
50 log.Fatalln("ERROR:", err)
52 defer conn.Disconnect()
54 // wait for Connected event
57 if e.State != core.Connected {
58 log.Fatalln("ERROR: connecting to VPP failed:", e.Error)
62 // create an API channel that will be used in the examples
63 ch, err := conn.NewAPIChannel()
65 log.Fatalln("ERROR: creating channel failed:", err)
69 if err := ch.CheckCompatiblity(vpe.AllMessages()...); err != nil {
75 if err := ch.CheckCompatiblity(interfaces.AllMessages()...); err != nil {
79 idx := createLoopback(ch)
83 ipAddressDump(ch, idx)
84 interfaceNotifications(ch, idx)
89 fmt.Printf("finished with %d errors\n", len(Errors))
92 fmt.Println("finished successfully")
98 func logError(err error, msg string) {
99 fmt.Printf("ERROR: %s: %v\n", msg, err)
100 Errors = append(Errors, err)
103 // vppVersion is the simplest API example - it retrieves VPP version.
104 func vppVersion(ch api.Channel) {
105 fmt.Println("Retrieving version")
107 req := &vpe.ShowVersion{}
108 reply := &vpe.ShowVersionReply{}
110 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
111 logError(err, "retrieving version")
114 fmt.Printf("reply: %+v\n", reply)
116 fmt.Printf("VPP version: %q\n", reply.Version)
121 // createLoopback sends request to create loopback interface.
122 func createLoopback(ch api.Channel) interfaces.InterfaceIndex {
123 fmt.Println("Creating loopback interface")
125 req := &interfaces.CreateLoopback{}
126 reply := &interfaces.CreateLoopbackReply{}
128 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
129 logError(err, "creating loopback interface")
132 fmt.Printf("reply: %+v\n", reply)
134 fmt.Printf("interface index: %v\n", reply.SwIfIndex)
138 return reply.SwIfIndex
141 // interfaceDump shows an example of multipart request (multiple replies are expected).
142 func interfaceDump(ch api.Channel) {
143 fmt.Println("Dumping interfaces")
146 reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
148 msg := &interfaces.SwInterfaceDetails{}
149 stop, err := reqCtx.ReceiveReply(msg)
154 logError(err, "dumping interfaces")
158 fmt.Printf(" - interface #%d: %+v\n", n, msg)
165 // addIPAddress sends request to add IP address to interface.
166 func addIPAddress(ch api.Channel, index interfaces.InterfaceIndex) {
167 fmt.Printf("Adding IP address to interface to interface index %d\n", index)
169 req := &interfaces.SwInterfaceAddDelAddress{
172 Prefix: interfaces.AddressWithPrefix{
173 Address: interfaces.Address{
174 Af: ip_types.ADDRESS_IP4,
175 Un: ip_types.AddressUnionIP4(interfaces.IP4Address{10, 10, 0, uint8(index)}),
180 reply := &interfaces.SwInterfaceAddDelAddressReply{}
182 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
183 logError(err, "adding IP address to interface")
186 fmt.Printf("reply: %+v\n", reply)
192 func ipAddressDump(ch api.Channel, index interfaces.InterfaceIndex) {
193 fmt.Printf("Dumping IP addresses for interface index %d\n", index)
195 req := &ip.IPAddressDump{
196 SwIfIndex: ip.InterfaceIndex(index),
198 reqCtx := ch.SendMultiRequest(req)
201 msg := &ip.IPAddressDetails{}
202 stop, err := reqCtx.ReceiveReply(msg)
204 logError(err, "dumping IP addresses")
210 fmt.Printf(" - ip address: %+v\n", msg)
217 // interfaceNotifications shows the usage of notification API. Note that for notifications,
218 // you are supposed to create your own Go channel with your preferred buffer size. If the channel's
219 // buffer is full, the notifications will not be delivered into it.
220 func interfaceNotifications(ch api.Channel, index interfaces.InterfaceIndex) {
221 fmt.Printf("Subscribing to notificaiton events for interface index %d\n", index)
223 notifChan := make(chan api.Message, 100)
225 // subscribe for specific notification message
226 sub, err := ch.SubscribeNotification(notifChan, &interfaces.SwInterfaceEvent{})
228 logError(err, "subscribing to interface events")
232 // enable interface events in VPP
233 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
234 PID: uint32(os.Getpid()),
236 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
238 logError(err, "enabling interface events")
242 // receive notifications
244 for notif := range notifChan {
245 fmt.Printf("incoming event: %+v\n", notif.(*interfaces.SwInterfaceEvent))
249 // generate some events in VPP
250 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
252 Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
253 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
255 logError(err, "setting interface flags")
258 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
261 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
263 logError(err, "setting interface flags")
267 // disable interface events in VPP
268 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
269 PID: uint32(os.Getpid()),
271 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
273 logError(err, "setting interface flags")
277 // unsubscribe from delivery of the notifications
278 err = sub.Unsubscribe()
280 logError(err, "unsubscribing from interface events")
288 func mactimeDump(conn api.Connection) {
289 fmt.Println("Sending mactime dump")
291 ctx := context.Background()
293 stream, err := conn.NewStream(ctx)
299 if err := stream.SendMsg(&mactime.MactimeDump{}); err != nil {
300 logError(err, "sending mactime dump")
306 msg, err := stream.RecvMsg()
308 logError(err, "dumping mactime")
313 case *mactime.MactimeDetails:
314 fmt.Printf(" - MactimeDetails: %+v\n", msg)
316 case *mactime.MactimeDumpReply:
317 fmt.Printf(" - MactimeDumpReply: %+v\n", msg)
321 logError(err, "unexpected message")