Refactor GoVPP
[govpp.git] / examples / cmd / simple-client / simple_client.go
1 // Copyright (c) 2017 Cisco and/or its affiliates.
2 //
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:
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14
15 // simple-client is an example VPP management application that exercises the
16 // govpp API on real-world use-cases.
17 package main
18
19 import (
20         "fmt"
21         "net"
22         "os"
23         "strings"
24
25         "git.fd.io/govpp.git"
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"
30 )
31
32 func main() {
33         fmt.Println("Starting simple VPP client...")
34
35         // connect to VPP
36         conn, err := govpp.Connect("")
37         if err != nil {
38                 fmt.Println("Error:", err)
39                 os.Exit(1)
40         }
41         defer conn.Disconnect()
42
43         // create an API channel that will be used in the examples
44         ch, err := conn.NewAPIChannel()
45         if err != nil {
46                 fmt.Println("Error:", err)
47                 os.Exit(1)
48         }
49         defer ch.Close()
50
51         // individual examples
52         aclVersion(ch)
53         aclConfig(ch)
54         aclDump(ch)
55
56         interfaceDump(ch)
57         ipAddressDump(ch)
58
59         setIpUnnumbered(ch)
60         ipUnnumberedDump(ch)
61
62         interfaceNotifications(ch)
63 }
64
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{}
69
70         err := ch.SendRequest(req).ReceiveReply(reply)
71
72         if err != nil {
73                 fmt.Println("Error:", err)
74         } else {
75                 fmt.Printf("%+v\n", reply)
76         }
77 }
78
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{
82                 ACLIndex: ^uint32(0),
83                 Tag:      []byte("access list 1"),
84                 R: []acl.ACLRule{
85                         {
86                                 IsPermit:       1,
87                                 SrcIPAddr:      net.ParseIP("10.0.0.0").To4(),
88                                 SrcIPPrefixLen: 8,
89                                 DstIPAddr:      net.ParseIP("192.168.1.0").To4(),
90                                 DstIPPrefixLen: 24,
91                                 Proto:          6,
92                         },
93                         {
94                                 IsPermit:       1,
95                                 SrcIPAddr:      net.ParseIP("8.8.8.8").To4(),
96                                 SrcIPPrefixLen: 32,
97                                 DstIPAddr:      net.ParseIP("172.16.0.0").To4(),
98                                 DstIPPrefixLen: 16,
99                                 Proto:          6,
100                         },
101                 },
102         }
103         reply := &acl.ACLAddReplaceReply{}
104
105         err := ch.SendRequest(req).ReceiveReply(reply)
106
107         if err != nil {
108                 fmt.Println("Error:", err)
109                 return
110         }
111         if reply.Retval != 0 {
112                 fmt.Println("Retval:", reply.Retval)
113                 return
114         }
115
116         fmt.Printf("%+v\n", reply)
117
118 }
119
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{}
124
125         if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
126                 fmt.Println("Error:", err)
127         } else {
128                 fmt.Printf("%+v\n", reply)
129         }
130 }
131
132 // interfaceDump shows an example of multipart request (multiple replies are expected).
133 func interfaceDump(ch api.Channel) {
134         fmt.Println("Dumping interfaces")
135
136         req := &interfaces.SwInterfaceDump{}
137         reqCtx := ch.SendMultiRequest(req)
138
139         for {
140                 msg := &interfaces.SwInterfaceDetails{}
141                 stop, err := reqCtx.ReceiveReply(msg)
142                 if stop {
143                         break // break out of the loop
144                 }
145                 if err != nil {
146                         fmt.Println("ERROR:", err)
147                 }
148                 ifaceName := strings.TrimFunc(string(msg.InterfaceName), func(r rune) bool {
149                         return r == 0x00
150                 })
151                 fmt.Printf("Interface: %q %+v\n", ifaceName, msg)
152         }
153 }
154
155 func ipAddressDump(ch api.Channel) {
156         fmt.Println("Dumping IP addresses")
157
158         req := &ip.IPAddressDump{
159                 SwIfIndex: 1, //^uint32(0),
160         }
161         reqCtx := ch.SendMultiRequest(req)
162
163         for {
164                 msg := &ip.IPAddressDetails{}
165                 stop, err := reqCtx.ReceiveReply(msg)
166                 if stop {
167                         break // break out of the loop
168                 }
169                 if err != nil {
170                         fmt.Println("ERROR:", err)
171                 }
172                 fmt.Printf("ip address: %d %+v\n", msg.SwIfIndex, msg)
173         }
174 }
175
176 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
177 func setIpUnnumbered(ch api.Channel) {
178         req := &interfaces.SwInterfaceSetUnnumbered{
179                 SwIfIndex:           1,
180                 UnnumberedSwIfIndex: 2,
181                 IsAdd:               1,
182         }
183         reply := &interfaces.SwInterfaceSetUnnumberedReply{}
184
185         if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
186                 fmt.Println("Error:", err)
187         } else {
188                 fmt.Printf("%+v\n", reply)
189         }
190 }
191
192 func ipUnnumberedDump(ch api.Channel) {
193         fmt.Println("Dumping IP unnumbered")
194
195         req := &ip.IPUnnumberedDump{
196                 SwIfIndex: ^uint32(0),
197         }
198         reqCtx := ch.SendMultiRequest(req)
199
200         for {
201                 msg := &ip.IPUnnumberedDetails{}
202                 stop, err := reqCtx.ReceiveReply(msg)
203                 if stop {
204                         break // break out of the loop
205                 }
206                 if err != nil {
207                         fmt.Println("ERROR:", err)
208                 }
209                 fmt.Printf("ip unnumbered: %+v\n", msg)
210         }
211 }
212
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)
220         if err != nil {
221                 panic(err)
222         }
223
224         // enable interface events in VPP
225         err = ch.SendRequest(&interfaces.WantInterfaceEvents{
226                 PID:           uint32(os.Getpid()),
227                 EnableDisable: 1,
228         }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
229         if err != nil {
230                 panic(err)
231         }
232
233         // generate some events in VPP
234         err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
235                 SwIfIndex:   0,
236                 AdminUpDown: 0,
237         }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
238         if err != nil {
239                 panic(err)
240         }
241         err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
242                 SwIfIndex:   0,
243                 AdminUpDown: 1,
244         }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
245         if err != nil {
246                 panic(err)
247         }
248
249         // receive one notification
250         notif := (<-notifChan).(*interfaces.SwInterfaceEvent)
251         fmt.Printf("NOTIF: %+v\n", notif)
252
253         // disable interface events in VPP
254         err = ch.SendRequest(&interfaces.WantInterfaceEvents{
255                 PID:           uint32(os.Getpid()),
256                 EnableDisable: 0,
257         }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
258         if err != nil {
259                 panic(err)
260         }
261
262         // unsubscribe from delivery of the notifications
263         err = ch.UnsubscribeNotification(subs)
264         if err != nil {
265                 panic(err)
266         }
267 }