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.
26 "git.fd.io/govpp.git/api"
27 "git.fd.io/govpp.git/examples/bin_api/acl"
28 "git.fd.io/govpp.git/examples/bin_api/interfaces"
29 "git.fd.io/govpp.git/examples/bin_api/ip"
33 fmt.Println("Starting simple VPP client...")
36 conn, err := govpp.Connect("")
38 fmt.Println("Error:", err)
41 defer conn.Disconnect()
43 // create an API channel that will be used in the examples
44 ch, err := conn.NewAPIChannel()
46 fmt.Println("Error:", err)
51 // individual examples
62 interfaceNotifications(ch)
65 // aclVersion is the simplest API example - one empty request message and one reply message.
66 func aclVersion(ch api.Channel) {
67 req := &acl.ACLPluginGetVersion{}
68 reply := &acl.ACLPluginGetVersionReply{}
70 err := ch.SendRequest(req).ReceiveReply(reply)
73 fmt.Println("Error:", err)
75 fmt.Printf("%+v\n", reply)
79 // aclConfig is another simple API example - in this case, the request contains structured data.
80 func aclConfig(ch api.Channel) {
81 req := &acl.ACLAddReplace{
83 Tag: []byte("access list 1"),
87 SrcIPAddr: net.ParseIP("10.0.0.0").To4(),
89 DstIPAddr: net.ParseIP("192.168.1.0").To4(),
95 SrcIPAddr: net.ParseIP("8.8.8.8").To4(),
97 DstIPAddr: net.ParseIP("172.16.0.0").To4(),
103 reply := &acl.ACLAddReplaceReply{}
105 err := ch.SendRequest(req).ReceiveReply(reply)
108 fmt.Println("Error:", err)
111 if reply.Retval != 0 {
112 fmt.Println("Retval:", reply.Retval)
116 fmt.Printf("%+v\n", reply)
120 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
121 func aclDump(ch api.Channel) {
122 req := &acl.ACLDump{}
123 reply := &acl.ACLDetails{}
125 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
126 fmt.Println("Error:", err)
128 fmt.Printf("%+v\n", reply)
132 // interfaceDump shows an example of multipart request (multiple replies are expected).
133 func interfaceDump(ch api.Channel) {
134 fmt.Println("Dumping interfaces")
136 req := &interfaces.SwInterfaceDump{}
137 reqCtx := ch.SendMultiRequest(req)
140 msg := &interfaces.SwInterfaceDetails{}
141 stop, err := reqCtx.ReceiveReply(msg)
143 break // break out of the loop
146 fmt.Println("ERROR:", err)
148 ifaceName := strings.TrimFunc(string(msg.InterfaceName), func(r rune) bool {
151 fmt.Printf("Interface: %q %+v\n", ifaceName, msg)
155 func ipAddressDump(ch api.Channel) {
156 fmt.Println("Dumping IP addresses")
158 req := &ip.IPAddressDump{
159 SwIfIndex: 1, //^uint32(0),
161 reqCtx := ch.SendMultiRequest(req)
164 msg := &ip.IPAddressDetails{}
165 stop, err := reqCtx.ReceiveReply(msg)
167 break // break out of the loop
170 fmt.Println("ERROR:", err)
172 fmt.Printf("ip address: %d %+v\n", msg.SwIfIndex, msg)
176 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
177 func setIpUnnumbered(ch api.Channel) {
178 req := &interfaces.SwInterfaceSetUnnumbered{
180 UnnumberedSwIfIndex: 2,
183 reply := &interfaces.SwInterfaceSetUnnumberedReply{}
185 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
186 fmt.Println("Error:", err)
188 fmt.Printf("%+v\n", reply)
192 func ipUnnumberedDump(ch api.Channel) {
193 fmt.Println("Dumping IP unnumbered")
195 req := &ip.IPUnnumberedDump{
196 SwIfIndex: ^uint32(0),
198 reqCtx := ch.SendMultiRequest(req)
201 msg := &ip.IPUnnumberedDetails{}
202 stop, err := reqCtx.ReceiveReply(msg)
204 break // break out of the loop
207 fmt.Println("ERROR:", err)
209 fmt.Printf("ip unnumbered: %+v\n", msg)
213 // interfaceNotifications shows the usage of notification API. Note that for notifications,
214 // you are supposed to create your own Go channel with your preferred buffer size. If the channel's
215 // buffer is full, the notifications will not be delivered into it.
216 func interfaceNotifications(ch api.Channel) {
217 // subscribe for specific notification message
218 notifChan := make(chan api.Message, 100)
219 subs, err := ch.SubscribeNotification(notifChan, interfaces.NewSwInterfaceEvent)
224 // enable interface events in VPP
225 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
226 PID: uint32(os.Getpid()),
228 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
233 // generate some events in VPP
234 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
237 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
241 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
244 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
249 // receive one notification
250 notif := (<-notifChan).(*interfaces.SwInterfaceEvent)
251 fmt.Printf("NOTIF: %+v\n", notif)
253 // disable interface events in VPP
254 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
255 PID: uint32(os.Getpid()),
257 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
262 // unsubscribe from delivery of the notifications
263 err = ch.UnsubscribeNotification(subs)