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/adapter/socketclient"
28 "git.fd.io/govpp.git/api"
29 "git.fd.io/govpp.git/core"
30 "git.fd.io/govpp.git/examples/binapi/interfaces"
31 "git.fd.io/govpp.git/examples/binapi/ip"
32 "git.fd.io/govpp.git/examples/binapi/vpe"
36 sockAddr = flag.String("sock", socketclient.DefaultSocketName, "Path to VPP binary API socket file")
42 fmt.Println("Starting simple client example")
44 // connect to VPP asynchronously
45 conn, conev, err := govpp.AsyncConnect(*sockAddr, core.DefaultMaxReconnectAttempts, core.DefaultReconnectInterval)
47 log.Fatalln("ERROR:", err)
49 defer conn.Disconnect()
51 // wait for Connected event
54 if e.State != core.Connected {
55 log.Fatalln("ERROR: connecting to VPP failed:", e.Error)
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)
75 interfaceNotifications(ch)
78 fmt.Printf("finished with %d errors\n", len(Errors))
81 fmt.Println("finished successfully")
87 func logError(err error, msg string) {
88 fmt.Printf("ERROR: %s: %v\n", msg, err)
89 Errors = append(Errors, err)
92 // vppVersion is the simplest API example - it retrieves VPP version.
93 func vppVersion(ch api.Channel) {
94 fmt.Println("Retrieving version")
96 req := &vpe.ShowVersion{}
97 reply := &vpe.ShowVersionReply{}
99 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
100 logError(err, "retrieving version")
103 fmt.Printf("reply: %+v\n", reply)
105 fmt.Printf("VPP version: %q\n", cleanString(reply.Version))
109 // createLoopback sends request to create loopback interface.
110 func createLoopback(ch api.Channel) {
111 fmt.Println("Creating loopback interface")
113 req := &interfaces.CreateLoopback{}
114 reply := &interfaces.CreateLoopbackReply{}
116 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
117 logError(err, "creating loopback interface")
120 fmt.Printf("reply: %+v\n", reply)
122 fmt.Printf("loopback interface index: %v\n", reply.SwIfIndex)
126 // interfaceDump shows an example of multipart request (multiple replies are expected).
127 func interfaceDump(ch api.Channel) {
128 fmt.Println("Dumping interfaces")
130 reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
132 msg := &interfaces.SwInterfaceDetails{}
133 stop, err := reqCtx.ReceiveReply(msg)
135 logError(err, "dumping interfaces")
141 fmt.Printf(" - interface: %+v\n", msg)
147 // addIPAddress sends request to add IP address to interface.
148 func addIPAddress(ch api.Channel) {
149 fmt.Println("Adding IP address to interface")
151 req := &interfaces.SwInterfaceAddDelAddress{
154 Address: []byte{10, 10, 0, 1},
156 /* below for 20.01-rc0
158 Prefix: interfaces.Prefix{
159 Address: interfaces.Address{
160 Af: interfaces.ADDRESS_IP4,
161 Un: interfaces.AddressUnionIP4(interfaces.IP4Address{10, 10, 0, 1}),
166 reply := &interfaces.SwInterfaceAddDelAddressReply{}
168 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
169 logError(err, "adding IP address to interface")
172 fmt.Printf("reply: %+v\n", reply)
177 func ipAddressDump(ch api.Channel) {
178 fmt.Println("Dumping IP addresses")
180 req := &ip.IPAddressDump{
183 reqCtx := ch.SendMultiRequest(req)
186 msg := &ip.IPAddressDetails{}
187 stop, err := reqCtx.ReceiveReply(msg)
189 logError(err, "dumping IP addresses")
195 fmt.Printf(" - ip address: %+v\n", msg)
201 // interfaceNotifications shows the usage of notification API. Note that for notifications,
202 // you are supposed to create your own Go channel with your preferred buffer size. If the channel's
203 // buffer is full, the notifications will not be delivered into it.
204 func interfaceNotifications(ch api.Channel) {
205 fmt.Println("Subscribing to notificaiton events")
207 notifChan := make(chan api.Message, 100)
209 // subscribe for specific notification message
210 sub, err := ch.SubscribeNotification(notifChan, &interfaces.SwInterfaceEvent{})
212 logError(err, "subscribing to interface events")
216 // enable interface events in VPP
217 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
218 PID: uint32(os.Getpid()),
220 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
222 logError(err, "enabling interface events")
226 // generate some events in VPP
227 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
229 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
231 logError(err, "setting interface flags")
234 err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
237 /* below for 20.01-rc0
239 Flags: interfaces.IF_STATUS_API_FLAG_ADMIN_UP,*/
240 }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
242 logError(err, "setting interface flags")
246 // receive one notification
247 notif := (<-notifChan).(*interfaces.SwInterfaceEvent)
248 fmt.Printf("incoming event: %+v\n", notif)
250 // disable interface events in VPP
251 err = ch.SendRequest(&interfaces.WantInterfaceEvents{
252 PID: uint32(os.Getpid()),
254 }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
256 logError(err, "setting interface flags")
260 // unsubscribe from delivery of the notifications
261 err = sub.Unsubscribe()
263 logError(err, "unsubscribing from interface events")
270 func cleanString(str string) string {
271 return strings.Split(str, "\x00")[0]