summaryrefslogtreecommitdiffstats
path: root/examples/simple-client
diff options
context:
space:
mode:
authorOndrej Fabry <ofabry@cisco.com>2019-02-08 01:16:32 +0100
committerOndrej Fabry <ofabry@cisco.com>2019-02-08 01:16:32 +0100
commitfa21c9d726ebb807895a8571af9a16dab5cd8d6e (patch)
tree4597d483f90e374e89f3923324b531a56217a0f9 /examples/simple-client
parent8ba70a7b13950593aab9863246f830eda450f06b (diff)
Generator improvements and cleanup
- generator now supports include-comments flag (as opt-in) - minor code cleanup in binapi-generator - remove obsolete unit tests - flatten examples from examples/cmd folder - introduce constant for checking compatibility in future versions Change-Id: I3545f2ba4b869a3b51d6d0de7e742f3f1e1be392 Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
Diffstat (limited to 'examples/simple-client')
-rw-r--r--examples/simple-client/simple_client.go271
1 files changed, 271 insertions, 0 deletions
diff --git a/examples/simple-client/simple_client.go b/examples/simple-client/simple_client.go
new file mode 100644
index 0000000..08d4da6
--- /dev/null
+++ b/examples/simple-client/simple_client.go
@@ -0,0 +1,271 @@
+// Copyright (c) 2017 Cisco and/or its affiliates.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// simple-client is an example VPP management application that exercises the
+// govpp API on real-world use-cases.
+package main
+
+import (
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "strings"
+
+ "git.fd.io/govpp.git"
+ "git.fd.io/govpp.git/api"
+ "git.fd.io/govpp.git/examples/bin_api/acl"
+ "git.fd.io/govpp.git/examples/bin_api/interfaces"
+ "git.fd.io/govpp.git/examples/bin_api/ip"
+)
+
+func main() {
+ fmt.Println("Starting simple VPP client...")
+
+ // connect to VPP
+ conn, err := govpp.Connect("")
+ if err != nil {
+ log.Fatalln("ERROR:", err)
+ }
+ defer conn.Disconnect()
+
+ // create an API channel that will be used in the examples
+ ch, err := conn.NewAPIChannel()
+ if err != nil {
+ log.Fatalln("ERROR:", err)
+ }
+ defer ch.Close()
+
+ // individual examples
+ aclVersion(ch)
+ aclConfig(ch)
+ aclDump(ch)
+
+ interfaceDump(ch)
+ ipAddressDump(ch)
+
+ setIpUnnumbered(ch)
+ ipUnnumberedDump(ch)
+
+ interfaceNotifications(ch)
+}
+
+// aclVersion is the simplest API example - one empty request message and one reply message.
+func aclVersion(ch api.Channel) {
+ fmt.Println("ACL getting version")
+
+ req := &acl.ACLPluginGetVersion{}
+ reply := &acl.ACLPluginGetVersionReply{}
+
+ if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
+ fmt.Println("ERROR:", err)
+ } else {
+ fmt.Printf("ACL version reply: %+v\n", reply)
+ }
+}
+
+// aclConfig is another simple API example - in this case, the request contains structured data.
+func aclConfig(ch api.Channel) {
+ fmt.Println("ACL adding replace")
+
+ req := &acl.ACLAddReplace{
+ ACLIndex: ^uint32(0),
+ Tag: []byte("access list 1"),
+ R: []acl.ACLRule{
+ {
+ IsPermit: 1,
+ SrcIPAddr: net.ParseIP("10.0.0.0").To4(),
+ SrcIPPrefixLen: 8,
+ DstIPAddr: net.ParseIP("192.168.1.0").To4(),
+ DstIPPrefixLen: 24,
+ Proto: 6,
+ },
+ {
+ IsPermit: 1,
+ SrcIPAddr: net.ParseIP("8.8.8.8").To4(),
+ SrcIPPrefixLen: 32,
+ DstIPAddr: net.ParseIP("172.16.0.0").To4(),
+ DstIPPrefixLen: 16,
+ Proto: 6,
+ },
+ },
+ }
+ reply := &acl.ACLAddReplaceReply{}
+
+ if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
+ fmt.Println("ERROR:", err)
+ return
+ }
+ if reply.Retval != 0 {
+ fmt.Println("Retval:", reply.Retval)
+ return
+ }
+
+ fmt.Printf("ACL add replace reply: %+v\n", reply)
+
+}
+
+// aclDump shows an example where SendRequest and ReceiveReply are not chained together.
+func aclDump(ch api.Channel) {
+ fmt.Println("Dumping ACL")
+
+ req := &acl.ACLDump{}
+ reply := &acl.ACLDetails{}
+
+ reqCtx := ch.SendRequest(req)
+
+ if err := reqCtx.ReceiveReply(reply); err != nil {
+ fmt.Println("ERROR:", err)
+ } else {
+ fmt.Printf("ACL details: %+v\n", reply)
+ }
+}
+
+// interfaceDump shows an example of multipart request (multiple replies are expected).
+func interfaceDump(ch api.Channel) {
+ fmt.Println("Dumping interfaces")
+
+ reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
+
+ for {
+ msg := &interfaces.SwInterfaceDetails{}
+ stop, err := reqCtx.ReceiveReply(msg)
+ if stop {
+ break
+ }
+ if err != nil {
+ fmt.Println("ERROR:", err)
+ }
+ ifaceName := strings.TrimFunc(string(msg.InterfaceName), func(r rune) bool {
+ return r == 0x00
+ })
+ fmt.Printf("Interface %q: %+v\n", ifaceName, msg)
+ }
+}
+
+func ipAddressDump(ch api.Channel) {
+ fmt.Println("Dumping IP addresses")
+
+ req := &ip.IPAddressDump{
+ SwIfIndex: 1, //^uint32(0),
+ }
+ reqCtx := ch.SendMultiRequest(req)
+
+ for {
+ msg := &ip.IPAddressDetails{}
+ stop, err := reqCtx.ReceiveReply(msg)
+ if stop {
+ break
+ }
+ if err != nil {
+ fmt.Println("ERROR:", err)
+ }
+ fmt.Printf("ip address details: %d %+v\n", msg.SwIfIndex, msg)
+ }
+}
+
+// aclDump shows an example where SendRequest and ReceiveReply are not chained together.
+func setIpUnnumbered(ch api.Channel) {
+ req := &interfaces.SwInterfaceSetUnnumbered{
+ SwIfIndex: 1,
+ UnnumberedSwIfIndex: 2,
+ IsAdd: 1,
+ }
+ reply := &interfaces.SwInterfaceSetUnnumberedReply{}
+
+ if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
+ fmt.Println("ERROR:", err)
+ } else {
+ fmt.Printf("%+v\n", reply)
+ }
+}
+
+func ipUnnumberedDump(ch api.Channel) {
+ fmt.Println("Dumping IP unnumbered")
+
+ reqCtx := ch.SendMultiRequest(&ip.IPUnnumberedDump{
+ SwIfIndex: ^uint32(0),
+ })
+
+ for {
+ msg := &ip.IPUnnumberedDetails{}
+ stop, err := reqCtx.ReceiveReply(msg)
+ if stop {
+ break
+ }
+ if err != nil {
+ fmt.Println("ERROR:", err)
+ }
+ fmt.Printf("IP unnumbered details: %+v\n", msg)
+ }
+}
+
+// interfaceNotifications shows the usage of notification API. Note that for notifications,
+// you are supposed to create your own Go channel with your preferred buffer size. If the channel's
+// buffer is full, the notifications will not be delivered into it.
+func interfaceNotifications(ch api.Channel) {
+ fmt.Println("Subscribing to notificaiton events")
+
+ notifChan := make(chan api.Message, 100)
+
+ // subscribe for specific notification message
+ sub, err := ch.SubscribeNotification(notifChan, &interfaces.SwInterfaceEvent{})
+ if err != nil {
+ panic(err)
+ }
+
+ // enable interface events in VPP
+ err = ch.SendRequest(&interfaces.WantInterfaceEvents{
+ PID: uint32(os.Getpid()),
+ EnableDisable: 1,
+ }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
+ if err != nil {
+ panic(err)
+ }
+
+ // generate some events in VPP
+ err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
+ SwIfIndex: 0,
+ AdminUpDown: 0,
+ }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
+ if err != nil {
+ panic(err)
+ }
+ err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
+ SwIfIndex: 0,
+ AdminUpDown: 1,
+ }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
+ if err != nil {
+ panic(err)
+ }
+
+ // receive one notification
+ notif := (<-notifChan).(*interfaces.SwInterfaceEvent)
+ fmt.Printf("incoming event: %+v\n", notif)
+
+ // disable interface events in VPP
+ err = ch.SendRequest(&interfaces.WantInterfaceEvents{
+ PID: uint32(os.Getpid()),
+ EnableDisable: 0,
+ }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
+ if err != nil {
+ panic(err)
+ }
+
+ // unsubscribe from delivery of the notifications
+ err = sub.Unsubscribe()
+ if err != nil {
+ panic(err)
+ }
+}