X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=examples%2Fsimple-client%2Fsimple_client.go;h=10a0ea6a30072ebb90fcc37ae6184074bced3b45;hb=refs%2Fchanges%2F05%2F29605%2F2;hp=3ed811d5a7fcf0785b34ae00ce73487a45dfd8f4;hpb=e45d8802fd8de3602db630d75b370ff804000da9;p=govpp.git diff --git a/examples/simple-client/simple_client.go b/examples/simple-client/simple_client.go index 3ed811d..10a0ea6 100644 --- a/examples/simple-client/simple_client.go +++ b/examples/simple-client/simple_client.go @@ -17,19 +17,21 @@ package main import ( + "encoding/json" "flag" "fmt" "log" "os" - "strings" "git.fd.io/govpp.git" "git.fd.io/govpp.git/adapter/socketclient" "git.fd.io/govpp.git/api" + interfaces "git.fd.io/govpp.git/binapi/interface" + "git.fd.io/govpp.git/binapi/interface_types" + "git.fd.io/govpp.git/binapi/ip" + "git.fd.io/govpp.git/binapi/ip_types" + "git.fd.io/govpp.git/binapi/vpe" "git.fd.io/govpp.git/core" - "git.fd.io/govpp.git/examples/binapi/interfaces" - "git.fd.io/govpp.git/examples/binapi/ip" - "git.fd.io/govpp.git/examples/binapi/vpe" ) var ( @@ -40,9 +42,10 @@ func main() { flag.Parse() fmt.Println("Starting simple client example") + fmt.Println() // connect to VPP asynchronously - conn, conev, err := govpp.AsyncConnect(*sockAddr, core.DefaultMaxReconnectAttempts, core.DefaultReconnectInterval) + conn, connEv, err := govpp.AsyncConnect(*sockAddr, core.DefaultMaxReconnectAttempts, core.DefaultReconnectInterval) if err != nil { log.Fatalln("ERROR:", err) } @@ -50,139 +53,152 @@ func main() { // wait for Connected event select { - case e := <-conev: + case e := <-connEv: if e.State != core.Connected { log.Fatalln("ERROR: connecting to VPP failed:", e.Error) } } - // create an API channel that will be used in the examples + // check compatibility of used messages ch, err := conn.NewAPIChannel() if err != nil { log.Fatalln("ERROR: creating channel failed:", err) } defer ch.Close() - - vppVersion(ch) - + if err := ch.CheckCompatiblity(vpe.AllMessages()...); err != nil { + log.Fatal(err) + } if err := ch.CheckCompatiblity(interfaces.AllMessages()...); err != nil { log.Fatal(err) } - createLoopback(ch) - createLoopback(ch) + // process errors encountered during the example + defer func() { + if len(Errors) > 0 { + fmt.Printf("finished with %d errors\n", len(Errors)) + os.Exit(1) + } else { + fmt.Println("finished successfully") + } + }() + + // use request/reply (channel API) + getVppVersion(ch) + getSystemTime(ch) + idx := createLoopback(ch) interfaceDump(ch) + addIPAddress(ch, idx) + ipAddressDump(ch, idx) + interfaceNotifications(ch, idx) +} - addIPAddress(ch) - ipAddressDump(ch) +func getVppVersion(ch api.Channel) { + fmt.Println("Retrieving version..") - interfaceNotifications(ch) + req := &vpe.ShowVersion{} + reply := &vpe.ShowVersionReply{} - if len(Errors) > 0 { - fmt.Printf("finished with %d errors\n", len(Errors)) - os.Exit(1) - } else { - fmt.Println("finished successfully") + if err := ch.SendRequest(req).ReceiveReply(reply); err != nil { + logError(err, "retrieving version") + return } -} - -var Errors []error -func logError(err error, msg string) { - fmt.Printf("ERROR: %s: %v\n", msg, err) - Errors = append(Errors, err) + fmt.Printf("VPP version: %q\n", reply.Version) + fmt.Println("OK") + fmt.Println() } -// vppVersion is the simplest API example - it retrieves VPP version. -func vppVersion(ch api.Channel) { - fmt.Println("Retrieving version") +func getSystemTime(ch api.Channel) { + fmt.Println("Retrieving system time..") - req := &vpe.ShowVersion{} - reply := &vpe.ShowVersionReply{} + req := &vpe.ShowVpeSystemTime{} + reply := &vpe.ShowVpeSystemTimeReply{} if err := ch.SendRequest(req).ReceiveReply(reply); err != nil { - logError(err, "retrieving version") + logError(err, "retrieving system time") return } - fmt.Printf("reply: %+v\n", reply) - fmt.Printf("VPP version: %q\n", cleanString(reply.Version)) - fmt.Println("ok") + fmt.Printf("system time: %v\n", reply.VpeSystemTime) + fmt.Println("OK") + fmt.Println() } -// createLoopback sends request to create loopback interface. -func createLoopback(ch api.Channel) { - fmt.Println("Creating loopback interface") +func createLoopback(ch api.Channel) interface_types.InterfaceIndex { + fmt.Println("Creating loopback interface..") req := &interfaces.CreateLoopback{} reply := &interfaces.CreateLoopbackReply{} if err := ch.SendRequest(req).ReceiveReply(reply); err != nil { logError(err, "creating loopback interface") - return + return 0 } - fmt.Printf("reply: %+v\n", reply) - fmt.Printf("loopback interface index: %v\n", reply.SwIfIndex) + fmt.Printf("interface index: %v\n", reply.SwIfIndex) fmt.Println("OK") + fmt.Println() + + return reply.SwIfIndex } -// interfaceDump shows an example of multipart request (multiple replies are expected). func interfaceDump(ch api.Channel) { - fmt.Println("Dumping interfaces") + fmt.Println("Dumping interfaces..") - reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{}) + n := 0 + reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{ + SwIfIndex: ^interface_types.InterfaceIndex(0), + }) for { msg := &interfaces.SwInterfaceDetails{} stop, err := reqCtx.ReceiveReply(msg) + if stop { + break + } if err != nil { logError(err, "dumping interfaces") return } - if stop { - break - } - fmt.Printf(" - interface: %+v\n", msg) + n++ + fmt.Printf(" - interface #%d: %+v\n", n, msg) + marshal(msg) } fmt.Println("OK") + fmt.Println() } -// addIPAddress sends request to add IP address to interface. -func addIPAddress(ch api.Channel) { - fmt.Println("Adding IP address to interface") +func addIPAddress(ch api.Channel, index interface_types.InterfaceIndex) { + fmt.Printf("Adding IP address to interface index %d\n", index) req := &interfaces.SwInterfaceAddDelAddress{ - SwIfIndex: 1, - IsAdd: 1, - Address: []byte{10, 10, 0, 1}, - AddressLength: 24, - /* below for 20.01-rc0 + SwIfIndex: index, IsAdd: true, - Prefix: interfaces.Prefix{ - Address: interfaces.Address{ - Af: interfaces.ADDRESS_IP4, - Un: interfaces.AddressUnionIP4(interfaces.IP4Address{10, 10, 0, 1}), + Prefix: ip_types.AddressWithPrefix{ + Address: ip_types.Address{ + Af: ip_types.ADDRESS_IP4, + Un: ip_types.AddressUnionIP4(ip_types.IP4Address{10, 10, 0, uint8(index)}), }, - Len: 24, - },*/ + Len: 32, + }, } + marshal(req) reply := &interfaces.SwInterfaceAddDelAddressReply{} if err := ch.SendRequest(req).ReceiveReply(reply); err != nil { logError(err, "adding IP address to interface") return } - fmt.Printf("reply: %+v\n", reply) fmt.Println("OK") + fmt.Println() } -func ipAddressDump(ch api.Channel) { - fmt.Println("Dumping IP addresses") +func ipAddressDump(ch api.Channel, index interface_types.InterfaceIndex) { + fmt.Printf("Dumping IP addresses for interface index %d..\n", index) req := &ip.IPAddressDump{ - SwIfIndex: 1, + SwIfIndex: index, } reqCtx := ch.SendMultiRequest(req) @@ -197,16 +213,18 @@ func ipAddressDump(ch api.Channel) { break } fmt.Printf(" - ip address: %+v\n", msg) + marshal(msg) } fmt.Println("OK") + fmt.Println() } // 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") +func interfaceNotifications(ch api.Channel, index interface_types.InterfaceIndex) { + fmt.Printf("Subscribing to notificaiton events for interface index %d\n", index) notifChan := make(chan api.Message, 100) @@ -227,30 +245,33 @@ func interfaceNotifications(ch api.Channel) { return } + // receive notifications + go func() { + for notif := range notifChan { + e := notif.(*interfaces.SwInterfaceEvent) + fmt.Printf("incoming event: %+v\n", e) + marshal(e) + } + }() + // generate some events in VPP err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{ - SwIfIndex: 1, + SwIfIndex: index, + Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP, }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{}) if err != nil { logError(err, "setting interface flags") return } err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{ - SwIfIndex: 1, - AdminUpDown: 1, - /* below for 20.01-rc0 - AdminUpDown: true, - Flags: interfaces.IF_STATUS_API_FLAG_ADMIN_UP,*/ + SwIfIndex: index, + Flags: 0, }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{}) if err != nil { logError(err, "setting interface flags") return } - // 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()), @@ -268,9 +289,22 @@ func interfaceNotifications(ch api.Channel) { return } + fmt.Println("OK") fmt.Println() } -func cleanString(str string) string { - return strings.Split(str, "\x00")[0] +func marshal(v interface{}) { + fmt.Printf("GO: %#v\n", v) + b, err := json.MarshalIndent(v, "", " ") + if err != nil { + panic(err) + } + fmt.Printf("JSON: %s\n", b) +} + +var Errors []error + +func logError(err error, msg string) { + fmt.Printf("ERROR: %s: %v\n", msg, err) + Errors = append(Errors, err) }