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
28 "git.fd.io/govpp.git/api"
29 "git.fd.io/govpp.git/api/ifcounters"
30 "git.fd.io/govpp.git/core/bin_api/vpe"
31 "git.fd.io/govpp.git/examples/bin_api/acl"
32 "git.fd.io/govpp.git/examples/bin_api/interfaces"
33 "git.fd.io/govpp.git/examples/bin_api/tap"
37 fmt.Println("Starting example VPP client...")
40 conn, err := govpp.Connect()
42 fmt.Println("Error:", err)
45 defer conn.Disconnect()
47 // create an API channel that will be used in the examples
48 ch, err := conn.NewAPIChannel()
50 fmt.Println("Error:", err)
55 // check whether the VPP supports our version of some messages
56 compatibilityCheck(ch)
58 // individual examples
66 interfaceNotifications(ch)
68 //interfaceCounters(ch)
71 // compatibilityCheck shows how an management application can check whether generated API messages are
72 // compatible with the version of VPP which the library is connected to.
73 func compatibilityCheck(ch *api.Channel) {
74 err := ch.CheckMessageCompatibility(
75 &interfaces.SwInterfaceDump{},
76 &interfaces.SwInterfaceDetails{},
84 // aclVersion is the simplest API example - one empty request message and one reply message.
85 func aclVersion(ch *api.Channel) {
86 req := &acl.ACLPluginGetVersion{}
87 reply := &acl.ACLPluginGetVersionReply{}
89 err := ch.SendRequest(req).ReceiveReply(reply)
92 fmt.Println("Error:", err)
94 fmt.Printf("%+v\n", reply)
98 // aclConfig is another simple API example - in this case, the request contains structured data.
99 func aclConfig(ch *api.Channel) {
100 req := &acl.ACLAddReplace{
101 ACLIndex: ^uint32(0),
102 Tag: []byte("access list 1"),
106 SrcIPAddr: net.ParseIP("10.0.0.0").To4(),
108 DstIPAddr: net.ParseIP("192.168.1.0").To4(),
114 SrcIPAddr: net.ParseIP("8.8.8.8").To4(),
116 DstIPAddr: net.ParseIP("172.16.0.0").To4(),
122 reply := &acl.ACLAddReplaceReply{}
124 err := ch.SendRequest(req).ReceiveReply(reply)
127 fmt.Println("Error:", err)
129 fmt.Printf("%+v\n", reply)
133 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
134 func aclDump(ch *api.Channel) {
135 req := &acl.ACLDump{}
136 reply := &acl.ACLDetails{}
138 reqCtx := ch.SendRequest(req)
139 err := reqCtx.ReceiveReply(reply)
142 fmt.Println("Error:", err)
144 fmt.Printf("%+v\n", reply)
148 // tapConnect example shows how the Go channels in the API channel can be accessed directly instead
149 // of using SendRequest and ReceiveReply wrappers.
150 func tapConnect(ch *api.Channel) {
151 req := &tap.TapConnect{
152 TapName: []byte("testtap"),
156 // send the request to the request go channel
157 ch.ReqChan <- &api.VppRequest{Message: req}
159 // receive a reply from the reply go channel
160 vppReply := <-ch.ReplyChan
161 if vppReply.Error != nil {
162 fmt.Println("Error:", vppReply.Error)
166 // decode the message
167 reply := &tap.TapConnectReply{}
168 err := ch.MsgDecoder.DecodeMsg(vppReply.Data, reply)
171 fmt.Println("Error:", err)
173 fmt.Printf("%+v\n", reply)
177 // interfaceDump shows an example of multipart request (multiple replies are expected).
178 func interfaceDump(ch *api.Channel) {
179 req := &interfaces.SwInterfaceDump{}
180 reqCtx := ch.SendMultiRequest(req)
183 msg := &interfaces.SwInterfaceDetails{}
184 stop, err := reqCtx.ReceiveReply(msg)
186 break // break out of the loop
189 fmt.Println("Error:", err)
191 fmt.Printf("%+v\n", msg)
195 // interfaceNotifications shows the usage of notification API. Note that for notifications,
196 // you are supposed to create your own Go channel with your preferred buffer size. If the channel's
197 // buffer is full, the notifications will not be delivered into it.
198 func interfaceNotifications(ch *api.Channel) {
199 // subscribe for specific notification message
200 notifChan := make(chan api.Message, 100)
201 subs, _ := ch.SubscribeNotification(notifChan, interfaces.NewSwInterfaceSetFlags)
203 // enable interface events in VPP
204 ch.SendRequest(&interfaces.WantInterfaceEvents{
205 Pid: uint32(os.Getpid()),
207 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
209 // generate some events in VPP
210 ch.SendRequest(&interfaces.SwInterfaceSetFlags{
213 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
214 ch.SendRequest(&interfaces.SwInterfaceSetFlags{
217 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
219 // receive one notification
220 notif := (<-notifChan).(*interfaces.SwInterfaceSetFlags)
221 fmt.Printf("%+v\n", notif)
223 // unsubscribe from delivery of the notifications
224 ch.UnsubscribeNotification(subs)
227 // interfaceCounters is an example of using notification API to periodically retrieve interface statistics.
228 // The ifcounters package contains the API that can be used to decode the strange VnetInterfaceCounters message.
229 func interfaceCounters(ch *api.Channel) {
230 // subscribe for interface counters notifications
231 notifChan := make(chan api.Message, 100)
232 subs, _ := ch.SubscribeNotification(notifChan, interfaces.NewVnetInterfaceCounters)
234 // enable interface counters notifications from VPP
235 ch.SendRequest(&vpe.WantStats{
236 Pid: uint32(os.Getpid()),
238 }).ReceiveReply(&vpe.WantStatsReply{})
240 // create channel for Interrupt signal
241 sigChan := make(chan os.Signal, 1)
242 signal.Notify(sigChan, os.Interrupt)
244 // loop until Interrupt signal is received
249 // interrupt received
251 case notifMsg := <-notifChan:
252 notif := notifMsg.(*interfaces.VnetInterfaceCounters)
253 // notification received
254 fmt.Printf("%+v\n", notif)
256 if notif.IsCombined == 0 {
258 counters, err := ifcounters.DecodeCounters(ifcounters.VnetInterfaceCounters(*notif))
260 fmt.Println("Error:", err)
262 fmt.Printf("%+v\n", counters)
266 counters, err := ifcounters.DecodeCombinedCounters(ifcounters.VnetInterfaceCounters(*notif))
268 fmt.Println("Error:", err)
270 fmt.Printf("%+v\n", counters)
276 // unsubscribe from delivery of the notifications
277 ch.UnsubscribeNotification(subs)