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 // Example VPP management application that exercises the govpp API on real-world use-cases.
18 // Generates Go bindings for all VPP APIs located in the json directory.
19 //go:generate binapi_generator --input-dir=bin_api --output-dir=bin_api
27 "gerrit.fd.io/r/govpp.git"
28 "gerrit.fd.io/r/govpp.git/api"
29 "gerrit.fd.io/r/govpp.git/api/ifcounters"
30 "gerrit.fd.io/r/govpp.git/core/bin_api/vpe"
31 "gerrit.fd.io/r/govpp.git/examples/bin_api/acl"
32 "gerrit.fd.io/r/govpp.git/examples/bin_api/interfaces"
33 "gerrit.fd.io/r/govpp.git/examples/bin_api/tap"
37 fmt.Println("Starting example VPP client...")
39 // connect to VPP and create an API channel that will be used in the examples
40 conn, _ := govpp.Connect()
41 defer conn.Disconnect()
43 ch, _ := conn.NewAPIChannel()
46 // check whether the VPP supports our version of some messages
47 compatibilityCheck(ch)
49 // individual examples
57 interfaceNotifications(ch)
59 //interfaceCounters(ch)
62 // compatibilityCheck shows how an management application can check whether generated API messages are
63 // compatible with the version of VPP which the library is connected to.
64 func compatibilityCheck(ch *api.Channel) {
65 err := ch.CheckMessageCompatibility(
66 &interfaces.SwInterfaceDump{},
67 &interfaces.SwInterfaceDetails{},
75 // aclVersion is the simplest API example - one empty request message and one reply message.
76 func aclVersion(ch *api.Channel) {
77 req := &acl.ACLPluginGetVersion{}
78 reply := &acl.ACLPluginGetVersionReply{}
80 err := ch.SendRequest(req).ReceiveReply(reply)
83 fmt.Println("Error:", err)
85 fmt.Printf("%+v\n", reply)
89 // aclConfig is another simple API example - in this case, the request contains structured data.
90 func aclConfig(ch *api.Channel) {
91 req := &acl.ACLAddReplace{
93 Tag: []byte("access list 1"),
97 SrcIPAddr: net.ParseIP("10.0.0.0").To4(),
99 DstIPAddr: net.ParseIP("192.168.1.0").To4(),
105 SrcIPAddr: net.ParseIP("8.8.8.8").To4(),
107 DstIPAddr: net.ParseIP("172.16.0.0").To4(),
113 reply := &acl.ACLAddReplaceReply{}
115 err := ch.SendRequest(req).ReceiveReply(reply)
118 fmt.Println("Error:", err)
120 fmt.Printf("%+v\n", reply)
124 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
125 func aclDump(ch *api.Channel) {
126 req := &acl.ACLDump{}
127 reply := &acl.ACLDetails{}
129 reqCtx := ch.SendRequest(req)
130 err := reqCtx.ReceiveReply(reply)
133 fmt.Println("Error:", err)
135 fmt.Printf("%+v\n", reply)
139 // tapConnect example shows how the Go channels in the API channel can be accessed directly instead
140 // of using SendRequest and ReceiveReply wrappers.
141 func tapConnect(ch *api.Channel) {
142 req := &tap.TapConnect{
143 TapName: []byte("testtap"),
147 // send the request to the request go channel
148 ch.ReqChan <- &api.VppRequest{Message: req}
150 // receive a reply from the reply go channel
151 vppReply := <-ch.ReplyChan
152 if vppReply.Error != nil {
153 fmt.Println("Error:", vppReply.Error)
157 // decode the message
158 reply := &tap.TapConnectReply{}
159 err := ch.MsgDecoder.DecodeMsg(vppReply.Data, reply)
162 fmt.Println("Error:", err)
164 fmt.Printf("%+v\n", reply)
168 // interfaceDump shows an example of multipart request (multiple replies are expected).
169 func interfaceDump(ch *api.Channel) {
170 req := &interfaces.SwInterfaceDump{}
171 reqCtx := ch.SendMultiRequest(req)
174 msg := &interfaces.SwInterfaceDetails{}
175 stop, err := reqCtx.ReceiveReply(msg)
177 break // break out of the loop
180 fmt.Println("Error:", err)
182 fmt.Printf("%+v\n", msg)
186 // interfaceNotifications shows the usage of notification API. Note that for notifications,
187 // you are supposed to create your own Go channel with your preferred buffer size. If the channel's
188 // buffer is full, the notifications will not be delivered into it.
189 func interfaceNotifications(ch *api.Channel) {
190 // subscribe for specific notification message
191 notifChan := make(chan api.Message, 100)
192 subs, _ := ch.SubscribeNotification(notifChan, interfaces.NewSwInterfaceSetFlags)
194 // enable interface events in VPP
195 ch.SendRequest(&interfaces.WantInterfaceEvents{
196 Pid: uint32(os.Getpid()),
198 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
200 // generate some events in VPP
201 ch.SendRequest(&interfaces.SwInterfaceSetFlags{
204 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
205 ch.SendRequest(&interfaces.SwInterfaceSetFlags{
208 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
210 // receive one notification
211 notif := (<-notifChan).(*interfaces.SwInterfaceSetFlags)
212 fmt.Printf("%+v\n", notif)
214 // unsubscribe from delivery of the notifications
215 ch.UnsubscribeNotification(subs)
218 // interfaceCounters is an example of using notification API to periodically retrieve interface statistics.
219 // The ifcounters package contains the API that can be used to decode the strange VnetInterfaceCounters message.
220 func interfaceCounters(ch *api.Channel) {
221 // subscribe for interface counters notifications
222 notifChan := make(chan api.Message, 100)
223 subs, _ := ch.SubscribeNotification(notifChan, interfaces.NewVnetInterfaceCounters)
225 // enable interface counters notifications from VPP
226 ch.SendRequest(&vpe.WantStats{
227 Pid: uint32(os.Getpid()),
229 }).ReceiveReply(&vpe.WantStatsReply{})
231 // create channel for Interrupt signal
232 sigChan := make(chan os.Signal, 1)
233 signal.Notify(sigChan, os.Interrupt)
235 // loop until Interrupt signal is received
240 // interrupt received
242 case notifMsg := <-notifChan:
243 notif := notifMsg.(*interfaces.VnetInterfaceCounters)
244 // notification received
245 fmt.Printf("%+v\n", notif)
247 if notif.IsCombined == 0 {
249 counters, err := ifcounters.DecodeCounters(ifcounters.VnetInterfaceCounters(*notif))
251 fmt.Println("Error:", err)
253 fmt.Printf("%+v\n", counters)
257 counters, err := ifcounters.DecodeCombinedCounters(ifcounters.VnetInterfaceCounters(*notif))
259 fmt.Println("Error:", err)
261 fmt.Printf("%+v\n", counters)
267 // unsubscribe from delivery of the notifications
268 ch.UnsubscribeNotification(subs)