Refactor GoVPP
[govpp.git] / examples / cmd / simple-client / simple_client.go
index 7b7dbcd..b9e8052 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Binary simple-client is an example VPP management application that exercises the
+// simple-client is an example VPP management application that exercises the
 // govpp API on real-world use-cases.
 package main
 
-// Generates Go bindings for all VPP APIs located in the json directory.
-//go:generate binapi-generator --input-dir=../../bin_api --output-dir=../../bin_api
-
 import (
        "fmt"
        "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/tap"
+       "git.fd.io/govpp.git/examples/bin_api/ip"
 )
 
 func main() {
@@ -50,31 +48,18 @@ func main() {
        }
        defer ch.Close()
 
-       // check whether the VPP supports our version of some messages
-       compatibilityCheck(ch)
-
        // individual examples
        aclVersion(ch)
        aclConfig(ch)
        aclDump(ch)
 
-       tapConnect(ch)
-
        interfaceDump(ch)
-       interfaceNotifications(ch)
-}
+       ipAddressDump(ch)
 
-// compatibilityCheck shows how an management application can check whether generated API messages are
-// compatible with the version of VPP which the library is connected to.
-func compatibilityCheck(ch api.Channel) {
-       err := ch.CheckMessageCompatibility(
-               &interfaces.SwInterfaceDump{},
-               &interfaces.SwInterfaceDetails{},
-       )
-       if err != nil {
-               fmt.Println(err)
-               os.Exit(1)
-       }
+       setIpUnnumbered(ch)
+       ipUnnumberedDump(ch)
+
+       interfaceNotifications(ch)
 }
 
 // aclVersion is the simplest API example - one empty request message and one reply message.
@@ -121,9 +106,15 @@ func aclConfig(ch api.Channel) {
 
        if err != nil {
                fmt.Println("Error:", err)
-       } else {
-               fmt.Printf("%+v\n", reply)
+               return
        }
+       if reply.Retval != 0 {
+               fmt.Println("Retval:", reply.Retval)
+               return
+       }
+
+       fmt.Printf("%+v\n", reply)
+
 }
 
 // aclDump shows an example where SendRequest and ReceiveReply are not chained together.
@@ -131,60 +122,91 @@ func aclDump(ch api.Channel) {
        req := &acl.ACLDump{}
        reply := &acl.ACLDetails{}
 
-       reqCtx := ch.SendRequest(req)
-       err := reqCtx.ReceiveReply(reply)
-
-       if err != nil {
+       if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
                fmt.Println("Error:", err)
        } else {
                fmt.Printf("%+v\n", reply)
        }
 }
 
-// tapConnect example shows how the Go channels in the API channel can be accessed directly instead
-// of using SendRequest and ReceiveReply wrappers.
-func tapConnect(ch api.Channel) {
-       req := &tap.TapConnect{
-               TapName:      []byte("testtap"),
-               UseRandomMac: 1,
+// interfaceDump shows an example of multipart request (multiple replies are expected).
+func interfaceDump(ch api.Channel) {
+       fmt.Println("Dumping interfaces")
+
+       req := &interfaces.SwInterfaceDump{}
+       reqCtx := ch.SendMultiRequest(req)
+
+       for {
+               msg := &interfaces.SwInterfaceDetails{}
+               stop, err := reqCtx.ReceiveReply(msg)
+               if stop {
+                       break // break out of the loop
+               }
+               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)
        }
+}
 
-       // send the request to the request go channel
-       ch.GetRequestChannel() <- &api.VppRequest{Message: req}
+func ipAddressDump(ch api.Channel) {
+       fmt.Println("Dumping IP addresses")
 
-       // receive a reply from the reply go channel
-       vppReply := <-ch.GetReplyChannel()
-       if vppReply.Error != nil {
-               fmt.Println("Error:", vppReply.Error)
-               return
+       req := &ip.IPAddressDump{
+               SwIfIndex: 1, //^uint32(0),
        }
+       reqCtx := ch.SendMultiRequest(req)
 
-       // decode the message
-       reply := &tap.TapConnectReply{}
-       err := ch.GetMessageDecoder().DecodeMsg(vppReply.Data, reply)
+       for {
+               msg := &ip.IPAddressDetails{}
+               stop, err := reqCtx.ReceiveReply(msg)
+               if stop {
+                       break // break out of the loop
+               }
+               if err != nil {
+                       fmt.Println("ERROR:", err)
+               }
+               fmt.Printf("ip address: %d %+v\n", msg.SwIfIndex, msg)
+       }
+}
 
-       if err != nil {
+// 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)
        }
 }
 
-// interfaceDump shows an example of multipart request (multiple replies are expected).
-func interfaceDump(ch api.Channel) {
-       req := &interfaces.SwInterfaceDump{}
+func ipUnnumberedDump(ch api.Channel) {
+       fmt.Println("Dumping IP unnumbered")
+
+       req := &ip.IPUnnumberedDump{
+               SwIfIndex: ^uint32(0),
+       }
        reqCtx := ch.SendMultiRequest(req)
 
        for {
-               msg := &interfaces.SwInterfaceDetails{}
+               msg := &ip.IPUnnumberedDetails{}
                stop, err := reqCtx.ReceiveReply(msg)
                if stop {
                        break // break out of the loop
                }
                if err != nil {
-                       fmt.Println("Error:", err)
+                       fmt.Println("ERROR:", err)
                }
-               fmt.Printf("%+v\n", msg)
+               fmt.Printf("ip unnumbered: %+v\n", msg)
        }
 }
 
@@ -194,28 +216,52 @@ func interfaceDump(ch api.Channel) {
 func interfaceNotifications(ch api.Channel) {
        // subscribe for specific notification message
        notifChan := make(chan api.Message, 100)
-       subs, _ := ch.SubscribeNotification(notifChan, interfaces.NewSwInterfaceSetFlags)
+       subs, err := ch.SubscribeNotification(notifChan, interfaces.NewSwInterfaceEvent)
+       if err != nil {
+               panic(err)
+       }
 
        // enable interface events in VPP
-       ch.SendRequest(&interfaces.WantInterfaceEvents{
-               Pid:           uint32(os.Getpid()),
+       err = ch.SendRequest(&interfaces.WantInterfaceEvents{
+               PID:           uint32(os.Getpid()),
                EnableDisable: 1,
        }).ReceiveReply(&interfaces.WantInterfaceEventsReply{})
+       if err != nil {
+               panic(err)
+       }
 
        // generate some events in VPP
-       ch.SendRequest(&interfaces.SwInterfaceSetFlags{
+       err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{
                SwIfIndex:   0,
                AdminUpDown: 0,
        }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{})
-       ch.SendRequest(&interfaces.SwInterfaceSetFlags{
+       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.SwInterfaceSetFlags)
-       fmt.Printf("%+v\n", notif)
+       notif := (<-notifChan).(*interfaces.SwInterfaceEvent)
+       fmt.Printf("NOTIF: %+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
-       ch.UnsubscribeNotification(subs)
+       err = ch.UnsubscribeNotification(subs)
+       if err != nil {
+               panic(err)
+       }
 }