aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorOndrej Fabry <ofabry@cisco.com>2020-06-16 10:40:34 +0200
committerOndrej Fabry <ofabry@cisco.com>2020-06-16 10:40:34 +0200
commit280b1c6c83b676ef4e592f4ecf60cb5b54b6a753 (patch)
treebf9a35f020de061ba66a432411ee44866405fe76 /examples
parentf049390060630c0085fe4ad683c83a4a14a47ffb (diff)
Optimize socketclient adapter and add various code improvements
This commit includes: Features - optimized [socketclient](adapter/socketclient) adapter and add method to set client name - added list of compatible messages to `CompatibilityError` Fixes - `MsgCodec` will recover panic occurring during a message decoding - calling `Unsubscibe` will close the notification channel Other - improved log messages to provide more relevant info Examples - added more code samples of working with unions in [union example](examples/union-example) - added profiling mode to [perf bench](examples/perf-bench) example - improved [simple client](examples/simple-client) example to work properly even with multiple runs Dependencies - updated `github.com/sirupsen/logrus` dep to `v1.6.0` - updated `github.com/lunixbochs/struc` dep to `v0.0.0-20200521075829-a4cb8d33dbbe` Change-Id: I136a3968ccf9e93760d7ee2b9902fc7e6390a09d Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
Diffstat (limited to 'examples')
-rw-r--r--examples/perf-bench/perf-bench.go23
-rw-r--r--examples/simple-client/simple_client.go78
-rw-r--r--examples/union-example/union_example.go101
3 files changed, 118 insertions, 84 deletions
diff --git a/examples/perf-bench/perf-bench.go b/examples/perf-bench/perf-bench.go
index f48c154..81d183c 100644
--- a/examples/perf-bench/perf-bench.go
+++ b/examples/perf-bench/perf-bench.go
@@ -20,6 +20,7 @@ import (
"flag"
"fmt"
"log"
+ "os"
"time"
"github.com/pkg/profile"
@@ -39,14 +40,14 @@ const (
func main() {
// parse optional flags
- var sync, prof bool
+ var sync bool
var cnt int
- var sock string
+ var sock, prof string
flag.BoolVar(&sync, "sync", false, "run synchronous perf test")
- flag.StringVar(&sock, "socket", socketclient.DefaultSocketName, "Path to VPP API socket")
- flag.String("socket", statsclient.DefaultSocketName, "Path to VPP stats socket")
+ flag.StringVar(&sock, "api-socket", socketclient.DefaultSocketName, "Path to VPP API socket")
+ flag.String("stats-socket", statsclient.DefaultSocketName, "Path to VPP stats socket")
flag.IntVar(&cnt, "count", 0, "count of requests to be sent to VPP")
- flag.BoolVar(&prof, "prof", false, "generate profile data")
+ flag.StringVar(&prof, "prof", "", "enable profiling mode [mem, cpu]")
flag.Parse()
if cnt == 0 {
@@ -58,8 +59,16 @@ func main() {
}
}
- if prof {
- defer profile.Start().Stop()
+ switch prof {
+ case "mem":
+ defer profile.Start(profile.MemProfile, profile.MemProfileRate(1)).Stop()
+ case "cpu":
+ defer profile.Start(profile.CPUProfile).Stop()
+ case "":
+ default:
+ fmt.Printf("invalid profiling mode: %q\n", prof)
+ flag.Usage()
+ os.Exit(1)
}
a := socketclient.NewVppClient(sock)
diff --git a/examples/simple-client/simple_client.go b/examples/simple-client/simple_client.go
index 6d96ca8..fe7c109 100644
--- a/examples/simple-client/simple_client.go
+++ b/examples/simple-client/simple_client.go
@@ -65,20 +65,22 @@ func main() {
}
defer ch.Close()
+ if err := ch.CheckCompatiblity(vpe.AllMessages()...); err != nil {
+ log.Fatal(err)
+ }
+
vppVersion(ch)
if err := ch.CheckCompatiblity(interfaces.AllMessages()...); err != nil {
log.Fatal(err)
}
- createLoopback(ch)
- createLoopback(ch)
+ idx := createLoopback(ch)
interfaceDump(ch)
- addIPAddress(ch)
- ipAddressDump(ch)
-
- interfaceNotifications(ch)
+ addIPAddress(ch, idx)
+ ipAddressDump(ch, idx)
+ interfaceNotifications(ch, idx)
if len(Errors) > 0 {
fmt.Printf("finished with %d errors\n", len(Errors))
@@ -109,11 +111,12 @@ func vppVersion(ch api.Channel) {
fmt.Printf("reply: %+v\n", reply)
fmt.Printf("VPP version: %q\n", cleanString(reply.Version))
- fmt.Println("ok")
+ fmt.Println("OK")
+ fmt.Println()
}
// createLoopback sends request to create loopback interface.
-func createLoopback(ch api.Channel) {
+func createLoopback(ch api.Channel) interfaces.InterfaceIndex {
fmt.Println("Creating loopback interface")
req := &interfaces.CreateLoopback{}
@@ -121,48 +124,54 @@ func createLoopback(ch api.Channel) {
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")
+ n := 0
reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
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)
}
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 interfaces.InterfaceIndex) {
+ fmt.Printf("Adding IP address to interface to interface index %d\n", index)
req := &interfaces.SwInterfaceAddDelAddress{
- SwIfIndex: 1,
+ SwIfIndex: index,
IsAdd: true,
Prefix: ip_types.AddressWithPrefix{
Address: interfaces.Address{
Af: ip_types.ADDRESS_IP4,
- Un: ip_types.AddressUnionIP4(interfaces.IP4Address{10, 10, 0, 1}),
+ Un: ip_types.AddressUnionIP4(interfaces.IP4Address{10, 10, 0, uint8(index)}),
},
- Len: 24,
+ Len: 32,
},
}
reply := &interfaces.SwInterfaceAddDelAddressReply{}
@@ -174,13 +183,14 @@ func addIPAddress(ch api.Channel) {
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 interfaces.InterfaceIndex) {
+ fmt.Printf("Dumping IP addresses for interface index %d\n", index)
req := &ip.IPAddressDump{
- SwIfIndex: 1,
+ SwIfIndex: index,
}
reqCtx := ch.SendMultiRequest(req)
@@ -198,13 +208,14 @@ func ipAddressDump(ch api.Channel) {
}
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 interfaces.InterfaceIndex) {
+ fmt.Printf("Subscribing to notificaiton events for interface index %d\n", index)
notifChan := make(chan api.Message, 100)
@@ -225,27 +236,31 @@ func interfaceNotifications(ch api.Channel) {
return
}
+ // receive notifications
+ go func() {
+ for notif := range notifChan {
+ fmt.Printf("incoming event: %+v\n", notif.(*interfaces.SwInterfaceEvent))
+ }
+ }()
+
// 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,
- Flags: interface_types.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()),
@@ -263,6 +278,7 @@ func interfaceNotifications(ch api.Channel) {
return
}
+ fmt.Println("OK")
fmt.Println()
}
diff --git a/examples/union-example/union_example.go b/examples/union-example/union_example.go
index 92c3ec2..9993ee1 100644
--- a/examples/union-example/union_example.go
+++ b/examples/union-example/union_example.go
@@ -16,73 +16,82 @@
package main
import (
- "bytes"
"fmt"
"log"
"net"
+ "reflect"
+ "git.fd.io/govpp.git/codec"
"git.fd.io/govpp.git/examples/binapi/ip"
"git.fd.io/govpp.git/examples/binapi/ip_types"
-
- "github.com/lunixbochs/struc"
)
+func init() {
+ log.SetFlags(0)
+}
+
func main() {
+ constructExample()
+
encodingExample()
- usageExample()
+
+ // convert IP from string form into Address type containing union
+ convertIP("10.10.1.1")
+ convertIP("ff80::1")
}
-func encodingExample() {
- // create union with IPv4 address
- var unionIP4 ip.AddressUnion
- unionIP4.SetIP4(ip.IP4Address{192, 168, 1, 10})
-
- // use it in the Address type
- addr := &ip.Address{
- Af: ip_types.ADDRESS_IP4,
- Un: ip_types.AddressUnionIP4(ip.IP4Address{192, 168, 1, 10}),
- }
- log.Printf("encoding union IPv4: %v", addr.Un.GetIP4())
+func constructExample() {
+ var union ip_types.AddressUnion
- // encode the address with union
- data := encode(addr)
- // decode the address with union
- addr2 := decode(data)
+ // create AddressUnion with AdressUnionXXX constructors
+ union = ip_types.AddressUnionIP4(ip.IP4Address{192, 168, 1, 10})
+ union = ip_types.AddressUnionIP6(ip.IP6Address{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02})
- log.Printf("decoded union IPv4: %v", addr2.Un.GetIP4())
+ // set AddressUnion with SetXXX methods
+ union.SetIP4(ip.IP4Address{192, 168, 1, 10})
+ union.SetIP6(ip.IP6Address{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02})
}
-func encode(addr *ip.Address) []byte {
- log.Printf("encoding address: %#v", addr)
- buf := new(bytes.Buffer)
- if err := struc.Pack(buf, addr); err != nil {
- panic(err)
+func encodingExample() {
+ var c codec.MsgCodec
+
+ // encode this message
+ var msg = ip.IPPuntRedirect{
+ Punt: ip.PuntRedirect{
+ Nh: ip_types.Address{
+ Af: ip_types.ADDRESS_IP4,
+ Un: ip_types.AddressUnionIP4(ip.IP4Address{192, 168, 1, 10}),
+ },
+ },
+ IsAdd: true,
}
- return buf.Bytes()
-}
+ log.Printf("encoding message: %+v", msg)
-func decode(data []byte) *ip.Address {
- addr := new(ip.Address)
- buf := bytes.NewReader(data)
- if err := struc.Unpack(buf, addr); err != nil {
- panic(err)
+ b, err := c.EncodeMsg(&msg, 1)
+ if err != nil {
+ log.Fatal(err)
}
- log.Printf("decoded address: %#v", addr)
- return addr
-}
-func usageExample() {
- var convAddr = func(ip string) {
- addr, err := ipToAddress(ip)
- if err != nil {
- log.Printf("converting ip %q failed: %v", ip, err)
- }
- fmt.Printf("% 0X\n", addr)
+ // decode into this message
+ var msg2 ip.IPPuntRedirect
+ if err := c.DecodeMsg(b, &msg2); err != nil {
+ log.Fatal(err)
}
+ log.Printf("decoded message: %+v", msg2)
- convAddr("10.10.10.10")
- convAddr("::1")
- convAddr("")
+ // compare the messages
+ if !reflect.DeepEqual(msg, msg2) {
+ log.Fatal("messages are not equal")
+ }
+}
+
+func convertIP(ip string) {
+ addr, err := ipToAddress(ip)
+ if err != nil {
+ log.Printf("error converting IP: %v", err)
+ return
+ }
+ fmt.Printf("converted IP %q to: %+v\n", ip, addr)
}
func ipToAddress(ipstr string) (addr ip.Address, err error) {
@@ -98,7 +107,7 @@ func ipToAddress(ipstr string) (addr ip.Address, err error) {
} else {
addr.Af = ip_types.ADDRESS_IP4
var ip4addr ip.IP4Address
- copy(ip4addr[:], ip4)
+ copy(ip4addr[:], ip4.To4())
addr.Un.SetIP4(ip4addr)
}
return