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 // Binary simple-client is an example VPP management application that exercises the
16 // govpp API on real-world use-cases.
19 // Generates Go bindings for all VPP APIs located in the json directory.
20 //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/examples/bin_api/acl"
30 "git.fd.io/govpp.git/examples/bin_api/interfaces"
31 "git.fd.io/govpp.git/examples/bin_api/tap"
35 fmt.Println("Starting simple VPP client...")
38 conn, err := govpp.Connect()
40 fmt.Println("Error:", err)
43 defer conn.Disconnect()
45 // create an API channel that will be used in the examples
46 ch, err := conn.NewAPIChannel()
48 fmt.Println("Error:", err)
53 // check whether the VPP supports our version of some messages
54 compatibilityCheck(ch)
56 // individual examples
64 interfaceNotifications(ch)
67 // compatibilityCheck shows how an management application can check whether generated API messages are
68 // compatible with the version of VPP which the library is connected to.
69 func compatibilityCheck(ch *api.Channel) {
70 err := ch.CheckMessageCompatibility(
71 &interfaces.SwInterfaceDump{},
72 &interfaces.SwInterfaceDetails{},
80 // aclVersion is the simplest API example - one empty request message and one reply message.
81 func aclVersion(ch *api.Channel) {
82 req := &acl.ACLPluginGetVersion{}
83 reply := &acl.ACLPluginGetVersionReply{}
85 err := ch.SendRequest(req).ReceiveReply(reply)
88 fmt.Println("Error:", err)
90 fmt.Printf("%+v\n", reply)
94 // aclConfig is another simple API example - in this case, the request contains structured data.
95 func aclConfig(ch *api.Channel) {
96 req := &acl.ACLAddReplace{
98 Tag: []byte("access list 1"),
102 SrcIPAddr: net.ParseIP("10.0.0.0").To4(),
104 DstIPAddr: net.ParseIP("192.168.1.0").To4(),
110 SrcIPAddr: net.ParseIP("8.8.8.8").To4(),
112 DstIPAddr: net.ParseIP("172.16.0.0").To4(),
118 reply := &acl.ACLAddReplaceReply{}
120 err := ch.SendRequest(req).ReceiveReply(reply)
123 fmt.Println("Error:", err)
125 fmt.Printf("%+v\n", reply)
129 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
130 func aclDump(ch *api.Channel) {
131 req := &acl.ACLDump{}
132 reply := &acl.ACLDetails{}
134 reqCtx := ch.SendRequest(req)
135 err := reqCtx.ReceiveReply(reply)
138 fmt.Println("Error:", err)
140 fmt.Printf("%+v\n", reply)
144 // tapConnect example shows how the Go channels in the API channel can be accessed directly instead
145 // of using SendRequest and ReceiveReply wrappers.
146 func tapConnect(ch *api.Channel) {
147 req := &tap.TapConnect{
148 TapName: []byte("testtap"),
152 // send the request to the request go channel
153 ch.ReqChan <- &api.VppRequest{Message: req}
155 // receive a reply from the reply go channel
156 vppReply := <-ch.ReplyChan
157 if vppReply.Error != nil {
158 fmt.Println("Error:", vppReply.Error)
162 // decode the message
163 reply := &tap.TapConnectReply{}
164 err := ch.MsgDecoder.DecodeMsg(vppReply.Data, reply)
167 fmt.Println("Error:", err)
169 fmt.Printf("%+v\n", reply)
173 // interfaceDump shows an example of multipart request (multiple replies are expected).
174 func interfaceDump(ch *api.Channel) {
175 req := &interfaces.SwInterfaceDump{}
176 reqCtx := ch.SendMultiRequest(req)
179 msg := &interfaces.SwInterfaceDetails{}
180 stop, err := reqCtx.ReceiveReply(msg)
182 break // break out of the loop
185 fmt.Println("Error:", err)
187 fmt.Printf("%+v\n", msg)
191 // interfaceNotifications shows the usage of notification API. Note that for notifications,
192 // you are supposed to create your own Go channel with your preferred buffer size. If the channel's
193 // buffer is full, the notifications will not be delivered into it.
194 func interfaceNotifications(ch *api.Channel) {
195 // subscribe for specific notification message
196 notifChan := make(chan api.Message, 100)
197 subs, _ := ch.SubscribeNotification(notifChan, interfaces.NewSwInterfaceSetFlags)
199 // enable interface events in VPP
200 ch.SendRequest(&interfaces.WantInterfaceEvents{
201 Pid: uint32(os.Getpid()),
203 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
205 // generate some events in VPP
206 ch.SendRequest(&interfaces.SwInterfaceSetFlags{
209 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
210 ch.SendRequest(&interfaces.SwInterfaceSetFlags{
213 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
215 // receive one notification
216 notif := (<-notifChan).(*interfaces.SwInterfaceSetFlags)
217 fmt.Printf("%+v\n", notif)
219 // unsubscribe from delivery of the notifications
220 ch.UnsubscribeNotification(subs)