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.
28 "git.fd.io/govpp.git/adapter/socketclient"
29 "git.fd.io/govpp.git/api"
30 "git.fd.io/govpp.git/core"
31 "git.fd.io/govpp.git/examples/binapi/acl"
32 "git.fd.io/govpp.git/examples/binapi/interfaces"
33 "git.fd.io/govpp.git/examples/binapi/ip"
37 sockAddr = flag.String("sock", socketclient.DefaultSocketName, "Path to VPP binary API socket file")
43 fmt.Println("Starting simple client example")
46 conn, conev, err := govpp.AsyncConnect(*sockAddr, core.DefaultMaxReconnectAttempts, core.DefaultReconnectInterval)
48 log.Fatalln("ERROR:", err)
50 defer conn.Disconnect()
54 if e.State != core.Connected {
55 log.Fatalln("ERROR: connecting to VPP failed:", err)
59 // create an API channel that will be used in the examples
60 ch, err := conn.NewAPIChannel()
62 log.Fatalln("ERROR: creating channel failed:", err)
66 // individual examples
77 interfaceNotifications(ch)
80 // aclVersion is the simplest API example - one empty request message and one reply message.
81 func aclVersion(ch api.Channel) {
82 fmt.Println("ACL getting version")
84 req := &acl.ACLPluginGetVersion{}
85 reply := &acl.ACLPluginGetVersionReply{}
87 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
88 fmt.Println("ERROR:", err)
90 fmt.Printf("ACL version reply: %+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 fmt.Println("ACL adding replace")
98 req := &acl.ACLAddReplace{
100 Tag: []byte("access list 1"),
104 SrcIPAddr: net.ParseIP("10.0.0.0").To4(),
106 DstIPAddr: net.ParseIP("192.168.1.0").To4(),
112 SrcIPAddr: net.ParseIP("8.8.8.8").To4(),
114 DstIPAddr: net.ParseIP("172.16.0.0").To4(),
120 reply := &acl.ACLAddReplaceReply{}
122 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
123 fmt.Println("ERROR:", err)
127 fmt.Printf("ACL add replace reply: %+v\n", reply)
131 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
132 func aclDump(ch api.Channel) {
133 fmt.Println("Dumping ACL")
135 req := &acl.ACLDump{}
136 reply := &acl.ACLDetails{}
138 reqCtx := ch.SendRequest(req)
140 if err := reqCtx.ReceiveReply(reply); err != nil {
141 fmt.Println("ERROR:", err)
143 fmt.Printf("ACL details: %+v\n", reply)
147 // interfaceDump shows an example of multipart request (multiple replies are expected).
148 func interfaceDump(ch api.Channel) {
149 fmt.Println("Dumping interfaces")
151 reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
154 msg := &interfaces.SwInterfaceDetails{}
155 stop, err := reqCtx.ReceiveReply(msg)
160 fmt.Println("ERROR:", err)
163 ifaceName := strings.TrimFunc(string(msg.InterfaceName), func(r rune) bool {
166 fmt.Printf("Interface %q: %+v\n", ifaceName, msg)
170 func ipAddressDump(ch api.Channel) {
171 fmt.Println("Dumping IP addresses")
173 req := &ip.IPAddressDump{
174 SwIfIndex: 1, //^uint32(0),
176 reqCtx := ch.SendMultiRequest(req)
179 msg := &ip.IPAddressDetails{}
180 stop, err := reqCtx.ReceiveReply(msg)
185 fmt.Println("ERROR:", err)
188 fmt.Printf("ip address details: %d %+v\n", msg.SwIfIndex, msg)
192 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
193 func setIpUnnumbered(ch api.Channel) {
194 req := &interfaces.SwInterfaceSetUnnumbered{
196 UnnumberedSwIfIndex: 2,
199 reply := &interfaces.SwInterfaceSetUnnumberedReply{}
201 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
202 fmt.Println("ERROR:", err)
204 fmt.Printf("%+v\n", reply)
208 func ipUnnumberedDump(ch api.Channel) {
209 fmt.Println("Dumping IP unnumbered")
211 reqCtx := ch.SendMultiRequest(&ip.IPUnnumberedDump{
212 SwIfIndex: ^uint32(0),
216 msg := &ip.IPUnnumberedDetails{}
217 stop, err := reqCtx.ReceiveReply(msg)
222 fmt.Println("ERROR:", err)
225 fmt.Printf("IP unnumbered details: %+v\n", msg)
229 // interfaceNotifications shows the usage of notification API. Note that for notifications,
230 // you are supposed to create your own Go channel with your preferred buffer size. If the channel's
231 // buffer is full, the notifications will not be delivered into it.
232 func interfaceNotifications(ch api.Channel) {
233 fmt.Println("Subscribing to notificaiton events")
235 notifChan := make(chan api.Message, 100)
237 // subscribe for specific notification message
238 sub, err := ch.SubscribeNotification(notifChan, &interfaces.SwInterfaceEvent{})
243 // enable interface events in VPP
244 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
245 PID: uint32(os.Getpid()),
247 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
252 // generate some events in VPP
253 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
256 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
260 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
263 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
268 // receive one notification
269 notif := (<-notifChan).(*interfaces.SwInterfaceEvent)
270 fmt.Printf("incoming event: %+v\n", notif)
272 // disable interface events in VPP
273 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
274 PID: uint32(os.Getpid()),
276 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
281 // unsubscribe from delivery of the notifications
282 err = sub.Unsubscribe()