support for shm prefixes
[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 // Binary simple-client is an example VPP management application that exercises the
16 // govpp API on real-world use-cases.
17 package main
18
19 // Generates Go bindings for all VPP APIs located in the json directory.
20 //go:generate binapi-generator --input-dir=../../bin_api --output-dir=../../bin_api
21
22 import (
23         "fmt"
24         "net"
25         "os"
26
27         "git.fd.io/govpp.git"
28         "git.fd.io/govpp.git/api"
29         "git.fd.io/govpp.git/examples/bin_api/acl"
30         "git.fd.io/govpp.git/examples/bin_api/interfaces"
31         "git.fd.io/govpp.git/examples/bin_api/tap"
32 )
33
34 func main() {
35         fmt.Println("Starting simple VPP client...")
36
37         // connect to VPP
38         conn, err := govpp.Connect("")
39         if err != nil {
40                 fmt.Println("Error:", err)
41                 os.Exit(1)
42         }
43         defer conn.Disconnect()
44
45         // create an API channel that will be used in the examples
46         ch, err := conn.NewAPIChannel()
47         if err != nil {
48                 fmt.Println("Error:", err)
49                 os.Exit(1)
50         }
51         defer ch.Close()
52
53         // check whether the VPP supports our version of some messages
54         compatibilityCheck(ch)
55
56         // individual examples
57         aclVersion(ch)
58         aclConfig(ch)
59         aclDump(ch)
60
61         tapConnect(ch)
62
63         interfaceDump(ch)
64         interfaceNotifications(ch)
65 }
66
67 // compatibilityCheck shows how an management application can check whether generated API messages are
68 // compatible with the version of VPP which the library is connected to.
69 func compatibilityCheck(ch *api.Channel) {
70         err := ch.CheckMessageCompatibility(
71                 &interfaces.SwInterfaceDump{},
72                 &interfaces.SwInterfaceDetails{},
73         )
74         if err != nil {
75                 fmt.Println(err)
76                 os.Exit(1)
77         }
78 }
79
80 // aclVersion is the simplest API example - one empty request message and one reply message.
81 func aclVersion(ch *api.Channel) {
82         req := &acl.ACLPluginGetVersion{}
83         reply := &acl.ACLPluginGetVersionReply{}
84
85         err := ch.SendRequest(req).ReceiveReply(reply)
86
87         if err != nil {
88                 fmt.Println("Error:", err)
89         } else {
90                 fmt.Printf("%+v\n", reply)
91         }
92 }
93
94 // aclConfig is another simple API example - in this case, the request contains structured data.
95 func aclConfig(ch *api.Channel) {
96         req := &acl.ACLAddReplace{
97                 ACLIndex: ^uint32(0),
98                 Tag:      []byte("access list 1"),
99                 R: []acl.ACLRule{
100                         {
101                                 IsPermit:       1,
102                                 SrcIPAddr:      net.ParseIP("10.0.0.0").To4(),
103                                 SrcIPPrefixLen: 8,
104                                 DstIPAddr:      net.ParseIP("192.168.1.0").To4(),
105                                 DstIPPrefixLen: 24,
106                                 Proto:          6,
107                         },
108                         {
109                                 IsPermit:       1,
110                                 SrcIPAddr:      net.ParseIP("8.8.8.8").To4(),
111                                 SrcIPPrefixLen: 32,
112                                 DstIPAddr:      net.ParseIP("172.16.0.0").To4(),
113                                 DstIPPrefixLen: 16,
114                                 Proto:          6,
115                         },
116                 },
117         }
118         reply := &acl.ACLAddReplaceReply{}
119
120         err := ch.SendRequest(req).ReceiveReply(reply)
121
122         if err != nil {
123                 fmt.Println("Error:", err)
124         } else {
125                 fmt.Printf("%+v\n", reply)
126         }
127 }
128
129 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
130 func aclDump(ch *api.Channel) {
131         req := &acl.ACLDump{}
132         reply := &acl.ACLDetails{}
133
134         reqCtx := ch.SendRequest(req)
135         err := reqCtx.ReceiveReply(reply)
136
137         if err != nil {
138                 fmt.Println("Error:", err)
139         } else {
140                 fmt.Printf("%+v\n", reply)
141         }
142 }
143
144 // tapConnect example shows how the Go channels in the API channel can be accessed directly instead
145 // of using SendRequest and ReceiveReply wrappers.
146 func tapConnect(ch *api.Channel) {
147         req := &tap.TapConnect{
148                 TapName:      []byte("testtap"),
149                 UseRandomMac: 1,
150         }
151
152         // send the request to the request go channel
153         ch.ReqChan <- &api.VppRequest{Message: req}
154
155         // receive a reply from the reply go channel
156         vppReply := <-ch.ReplyChan
157         if vppReply.Error != nil {
158                 fmt.Println("Error:", vppReply.Error)
159                 return
160         }
161
162         // decode the message
163         reply := &tap.TapConnectReply{}
164         err := ch.MsgDecoder.DecodeMsg(vppReply.Data, reply)
165
166         if err != nil {
167                 fmt.Println("Error:", err)
168         } else {
169                 fmt.Printf("%+v\n", reply)
170         }
171 }
172
173 // interfaceDump shows an example of multipart request (multiple replies are expected).
174 func interfaceDump(ch *api.Channel) {
175         req := &interfaces.SwInterfaceDump{}
176         reqCtx := ch.SendMultiRequest(req)
177
178         for {
179                 msg := &interfaces.SwInterfaceDetails{}
180                 stop, err := reqCtx.ReceiveReply(msg)
181                 if stop {
182                         break // break out of the loop
183                 }
184                 if err != nil {
185                         fmt.Println("Error:", err)
186                 }
187                 fmt.Printf("%+v\n", msg)
188         }
189 }
190
191 // interfaceNotifications shows the usage of notification API. Note that for notifications,
192 // you are supposed to create your own Go channel with your preferred buffer size. If the channel's
193 // buffer is full, the notifications will not be delivered into it.
194 func interfaceNotifications(ch *api.Channel) {
195         // subscribe for specific notification message
196         notifChan := make(chan api.Message, 100)
197         subs, _ := ch.SubscribeNotification(notifChan, interfaces.NewSwInterfaceSetFlags)
198
199         // enable interface events in VPP
200         ch.SendRequest(&interfaces.WantInterfaceEvents{
201                 Pid:           uint32(os.Getpid()),
202                 EnableDisable: 1,
203         }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
204
205         // generate some events in VPP
206         ch.SendRequest(&interfaces.SwInterfaceSetFlags{
207                 SwIfIndex:   0,
208                 AdminUpDown: 0,
209         }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
210         ch.SendRequest(&interfaces.SwInterfaceSetFlags{
211                 SwIfIndex:   0,
212                 AdminUpDown: 1,
213         }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
214
215         // receive one notification
216         notif := (<-notifChan).(*interfaces.SwInterfaceSetFlags)
217         fmt.Printf("%+v\n", notif)
218
219         // unsubscribe from delivery of the notifications
220         ch.UnsubscribeNotification(subs)
221 }