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/api"
28 "git.fd.io/govpp.git/examples/bin_api/acl"
29 "git.fd.io/govpp.git/examples/bin_api/interfaces"
30 "git.fd.io/govpp.git/examples/bin_api/ip"
34 fmt.Println("Starting simple VPP client...")
37 conn, err := govpp.Connect("")
39 log.Fatalln("ERROR:", err)
41 defer conn.Disconnect()
43 // create an API channel that will be used in the examples
44 ch, err := conn.NewAPIChannel()
46 log.Fatalln("ERROR:", err)
50 // individual examples
61 interfaceNotifications(ch)
64 // aclVersion is the simplest API example - one empty request message and one reply message.
65 func aclVersion(ch api.Channel) {
66 fmt.Println("ACL getting version")
68 req := &acl.ACLPluginGetVersion{}
69 reply := &acl.ACLPluginGetVersionReply{}
71 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
72 fmt.Println("ERROR:", err)
74 fmt.Printf("ACL version reply: %+v\n", reply)
78 // aclConfig is another simple API example - in this case, the request contains structured data.
79 func aclConfig(ch api.Channel) {
80 fmt.Println("ACL adding replace")
82 req := &acl.ACLAddReplace{
84 Tag: []byte("access list 1"),
88 SrcIPAddr: net.ParseIP("10.0.0.0").To4(),
90 DstIPAddr: net.ParseIP("192.168.1.0").To4(),
96 SrcIPAddr: net.ParseIP("8.8.8.8").To4(),
98 DstIPAddr: net.ParseIP("172.16.0.0").To4(),
104 reply := &acl.ACLAddReplaceReply{}
106 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
107 fmt.Println("ERROR:", err)
110 if reply.Retval != 0 {
111 fmt.Println("Retval:", reply.Retval)
115 fmt.Printf("ACL add replace reply: %+v\n", reply)
119 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
120 func aclDump(ch api.Channel) {
121 fmt.Println("Dumping ACL")
123 req := &acl.ACLDump{}
124 reply := &acl.ACLDetails{}
126 reqCtx := ch.SendRequest(req)
128 if err := reqCtx.ReceiveReply(reply); err != nil {
129 fmt.Println("ERROR:", err)
131 fmt.Printf("ACL details: %+v\n", reply)
135 // interfaceDump shows an example of multipart request (multiple replies are expected).
136 func interfaceDump(ch api.Channel) {
137 fmt.Println("Dumping interfaces")
139 reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
142 msg := &interfaces.SwInterfaceDetails{}
143 stop, err := reqCtx.ReceiveReply(msg)
148 fmt.Println("ERROR:", err)
150 ifaceName := strings.TrimFunc(string(msg.InterfaceName), func(r rune) bool {
153 fmt.Printf("Interface %q: %+v\n", ifaceName, msg)
157 func ipAddressDump(ch api.Channel) {
158 fmt.Println("Dumping IP addresses")
160 req := &ip.IPAddressDump{
161 SwIfIndex: 1, //^uint32(0),
163 reqCtx := ch.SendMultiRequest(req)
166 msg := &ip.IPAddressDetails{}
167 stop, err := reqCtx.ReceiveReply(msg)
172 fmt.Println("ERROR:", err)
174 fmt.Printf("ip address details: %d %+v\n", msg.SwIfIndex, msg)
178 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
179 func setIpUnnumbered(ch api.Channel) {
180 req := &interfaces.SwInterfaceSetUnnumbered{
182 UnnumberedSwIfIndex: 2,
185 reply := &interfaces.SwInterfaceSetUnnumberedReply{}
187 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
188 fmt.Println("ERROR:", err)
190 fmt.Printf("%+v\n", reply)
194 func ipUnnumberedDump(ch api.Channel) {
195 fmt.Println("Dumping IP unnumbered")
197 reqCtx := ch.SendMultiRequest(&ip.IPUnnumberedDump{
198 SwIfIndex: ^uint32(0),
202 msg := &ip.IPUnnumberedDetails{}
203 stop, err := reqCtx.ReceiveReply(msg)
208 fmt.Println("ERROR:", err)
210 fmt.Printf("IP unnumbered details: %+v\n", msg)
214 // interfaceNotifications shows the usage of notification API. Note that for notifications,
215 // you are supposed to create your own Go channel with your preferred buffer size. If the channel's
216 // buffer is full, the notifications will not be delivered into it.
217 func interfaceNotifications(ch api.Channel) {
218 fmt.Println("Subscribing to notificaiton events")
220 notifChan := make(chan api.Message, 100)
222 // subscribe for specific notification message
223 sub, err := ch.SubscribeNotification(notifChan, &interfaces.SwInterfaceEvent{})
228 // enable interface events in VPP
229 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
230 PID: uint32(os.Getpid()),
232 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
237 // generate some events in VPP
238 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
241 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
245 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
248 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
253 // receive one notification
254 notif := (<-notifChan).(*interfaces.SwInterfaceEvent)
255 fmt.Printf("incoming event: %+v\n", notif)
257 // disable interface events in VPP
258 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
259 PID: uint32(os.Getpid()),
261 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
266 // unsubscribe from delivery of the notifications
267 err = sub.Unsubscribe()