diff options
author | 2019-02-08 01:16:32 +0100 | |
---|---|---|
committer | 2019-02-08 01:16:32 +0100 | |
commit | fa21c9d726ebb807895a8571af9a16dab5cd8d6e (patch) | |
tree | 4597d483f90e374e89f3923324b531a56217a0f9 /examples/cmd | |
parent | 8ba70a7b13950593aab9863246f830eda450f06b (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/cmd')
-rw-r--r-- | examples/cmd/perf-bench/perf-bench.go | 126 | ||||
-rw-r--r-- | examples/cmd/simple-client/simple_client.go | 271 | ||||
-rw-r--r-- | examples/cmd/stats-api/README.md | 68 | ||||
-rw-r--r-- | examples/cmd/stats-api/stats_api.go | 140 | ||||
-rw-r--r-- | examples/cmd/union-example/union_example.go | 103 |
5 files changed, 0 insertions, 708 deletions
diff --git a/examples/cmd/perf-bench/perf-bench.go b/examples/cmd/perf-bench/perf-bench.go deleted file mode 100644 index 664f046..0000000 --- a/examples/cmd/perf-bench/perf-bench.go +++ /dev/null @@ -1,126 +0,0 @@ -// 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. - -// Binary simple-client is an example VPP management application that exercises the -// govpp API on real-world use-cases. -package main - -import ( - "flag" - "fmt" - "log" - "time" - - "github.com/pkg/profile" - "github.com/sirupsen/logrus" - - "git.fd.io/govpp.git" - "git.fd.io/govpp.git/api" - "git.fd.io/govpp.git/core" - "git.fd.io/govpp.git/examples/bin_api/vpe" -) - -const ( - defaultSyncRequestCount = 1000 - defaultAsyncRequestCount = 10000 -) - -func main() { - // parse optional flags - var sync, prof bool - var cnt int - flag.BoolVar(&sync, "sync", false, "run synchronous perf test") - flag.IntVar(&cnt, "count", 0, "count of requests to be sent to VPP") - flag.BoolVar(&prof, "prof", false, "generate profile data") - flag.Parse() - - if cnt == 0 { - // no specific count defined - use defaults - if sync { - cnt = defaultSyncRequestCount - } else { - cnt = defaultAsyncRequestCount - } - } - - if prof { - defer profile.Start().Stop() - } - - // log only errors - core.SetLogger(&logrus.Logger{Level: logrus.ErrorLevel}) - - // connect to VPP - conn, err := govpp.Connect("") - if err != nil { - log.Fatalln("Error:", err) - } - defer conn.Disconnect() - - // create an API channel - ch, err := conn.NewAPIChannelBuffered(cnt, cnt) - if err != nil { - log.Fatalln("Error:", err) - } - defer ch.Close() - - // run the test & measure the time - start := time.Now() - - if sync { - // run synchronous test - syncTest(ch, cnt) - } else { - // run asynchronous test - asyncTest(ch, cnt) - } - - elapsed := time.Since(start) - fmt.Println("Test took:", elapsed) - fmt.Printf("Requests per second: %.0f\n", float64(cnt)/elapsed.Seconds()) -} - -func syncTest(ch api.Channel, cnt int) { - fmt.Printf("Running synchronous perf test with %d requests...\n", cnt) - - for i := 0; i < cnt; i++ { - req := &vpe.ControlPing{} - reply := &vpe.ControlPingReply{} - - if err := ch.SendRequest(req).ReceiveReply(reply); err != nil { - log.Fatalln("Error in reply:", err) - } - } -} - -func asyncTest(ch api.Channel, cnt int) { - fmt.Printf("Running asynchronous perf test with %d requests...\n", cnt) - - ctxChan := make(chan api.RequestCtx, cnt) - - go func() { - for i := 0; i < cnt; i++ { - ctxChan <- ch.SendRequest(&vpe.ControlPing{}) - } - close(ctxChan) - fmt.Printf("Sending asynchronous requests finished\n") - }() - - for ctx := range ctxChan { - reply := &vpe.ControlPingReply{} - if err := ctx.ReceiveReply(reply); err != nil { - log.Fatalln("Error in reply:", err) - } - } -} diff --git a/examples/cmd/simple-client/simple_client.go b/examples/cmd/simple-client/simple_client.go deleted file mode 100644 index 08d4da6..0000000 --- a/examples/cmd/simple-client/simple_client.go +++ /dev/null @@ -1,271 +0,0 @@ -// 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) - } -} diff --git a/examples/cmd/stats-api/README.md b/examples/cmd/stats-api/README.md deleted file mode 100644 index 44a1663..0000000 --- a/examples/cmd/stats-api/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# Stats API Example - -This example demonstrates how to retrieve statistics from VPP using [the new Stats API](https://github.com/FDio/vpp/blob/master/src/vpp/stats/stats.md). - -## Requirements - -The following requirements are required to run this example: - -- install **VPP 18.10+** -- enable stats in VPP: - - ```sh - statseg { - default - } - ``` - > The [default socket](https://wiki.fd.io/view/VPP/Command-line_Arguments#.22statseg.22_parameters) is located at `/run/vpp/stats.sock`. -- run the VPP, ideally with some traffic - -## Running example - -First build the example: `go build git.fd.io/govpp.git/examples/cmd/stats-api`. - -Use commands `ls` and `dump` to list and dump statistics. Optionally, patterns can be used to filter the results. - -### List stats matching patterns `/sys/` and `/if/` -``` -$ ./stats-api ls /sys/ /if/ -Listing stats.. /sys/ /if/ - - /sys/vector_rate - - /sys/input_rate - - /sys/last_update - - /sys/last_stats_clear - - /sys/heartbeat - - /sys/node/clocks - - /sys/node/vectors - - /sys/node/calls - - /sys/node/suspends - - /if/drops - - /if/punt - - /if/ip4 - - /if/ip6 - - /if/rx-no-buf - - /if/rx-miss - - /if/rx-error - - /if/tx-error - - /if/rx - - /if/rx-unicast - - /if/rx-multicast - - /if/rx-broadcast - - /if/tx - - /if/tx-unicast-miss - - /if/tx-multicast - - /if/tx-broadcast -Listed 25 stats -``` - -### Dump all stats with their types and values -``` -$ ./stats-api dump -Dumping stats.. - - /sys/last_update ScalarIndex 10408 - - /sys/heartbeat ScalarIndex 1041 - - /err/ip4-icmp-error/unknown type ErrorIndex 5 - - /net/route/to CombinedCounterVector [[{Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:5 Bytes:420}]] - - /if/drops SimpleCounterVector [[0 5 5]] -Dumped 5 (2798) stats -``` diff --git a/examples/cmd/stats-api/stats_api.go b/examples/cmd/stats-api/stats_api.go deleted file mode 100644 index 6fd46d2..0000000 --- a/examples/cmd/stats-api/stats_api.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2018 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. - -package main - -import ( - "flag" - "fmt" - "log" - "os" - "strings" - - "git.fd.io/govpp.git/adapter" - "git.fd.io/govpp.git/adapter/vppapiclient" -) - -// ------------------------------------------------------------------ -// Example - Stats API -// ------------------------------------------------------------------ -// The example stats_api demonstrates how to retrieve stats -// from the VPP using the new stats API. -// ------------------------------------------------------------------ - -var ( - statsSocket = flag.String("socket", vppapiclient.DefaultStatSocket, "VPP stats segment socket") - dumpAll = flag.Bool("all", false, "Dump all stats including ones with zero values") -) - -func init() { - flag.Usage = func() { - fmt.Fprintf(os.Stderr, "%s: usage [ls|dump] <patterns>...\n", os.Args[0]) - flag.PrintDefaults() - os.Exit(1) - } -} - -func main() { - flag.Parse() - - cmd := flag.Arg(0) - - switch cmd { - case "", "ls", "dump": - default: - flag.Usage() - } - - var patterns []string - if flag.NArg() > 0 { - patterns = flag.Args()[1:] - } - - client := vppapiclient.NewStatClient(*statsSocket) - - fmt.Printf("Connecting to stats socket: %s\n", *statsSocket) - - if err := client.Connect(); err != nil { - log.Fatalln("Connecting failed:", err) - } - defer client.Disconnect() - - switch cmd { - case "dump": - dumpStats(client, patterns, !*dumpAll) - default: - listStats(client, patterns) - } -} - -func listStats(client adapter.StatsAPI, patterns []string) { - fmt.Printf("Listing stats.. %s\n", strings.Join(patterns, " ")) - - list, err := client.ListStats(patterns...) - if err != nil { - log.Fatalln("listing stats failed:", err) - } - - for _, stat := range list { - fmt.Printf(" - %v\n", stat) - } - - fmt.Printf("Listed %d stats\n", len(list)) -} - -func dumpStats(client adapter.StatsAPI, patterns []string, skipZeros bool) { - fmt.Printf("Dumping stats.. %s\n", strings.Join(patterns, " ")) - - stats, err := client.DumpStats(patterns...) - if err != nil { - log.Fatalln("dumping stats failed:", err) - } - - n := 0 - for _, stat := range stats { - if isZero(stat.Data) && skipZeros { - continue - } - fmt.Printf(" - %-25s %25v %+v\n", stat.Name, stat.Type, stat.Data) - n++ - } - - fmt.Printf("Dumped %d (%d) stats\n", n, len(stats)) -} - -func isZero(stat adapter.Stat) bool { - switch s := stat.(type) { - case adapter.ScalarStat: - return s == 0 - case adapter.ErrorStat: - return s == 0 - case adapter.SimpleCounterStat: - for _, ss := range s { - for _, sss := range ss { - if sss != 0 { - return false - } - } - } - case adapter.CombinedCounterStat: - for _, ss := range s { - for _, sss := range ss { - if sss.Bytes != 0 || sss.Packets != 0 { - return false - } - } - } - } - return true -} diff --git a/examples/cmd/union-example/union_example.go b/examples/cmd/union-example/union_example.go deleted file mode 100644 index d4563c6..0000000 --- a/examples/cmd/union-example/union_example.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2018 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. - -// union-example is an example to show how to use unions in VPP binary API. -package main - -import ( - "bytes" - "fmt" - "log" - "net" - - "git.fd.io/govpp.git/examples/bin_api/ip" - "github.com/lunixbochs/struc" -) - -func main() { - encodingExample() - usageExample() -} - -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.ADDRESS_IP4, - Un: ip.AddressUnionIP4(ip.IP4Address{192, 168, 1, 10}), - } - log.Printf("encoding union IPv4: %v", addr.Un.GetIP4()) - - // encode the address with union - data := encode(addr) - // decode the address with union - addr2 := decode(data) - - log.Printf("decoded union IPv4: %v", addr2.Un.GetIP4()) -} - -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) - } - return buf.Bytes() -} - -func decode(data []byte) *ip.Address { - addr := new(ip.Address) - buf := bytes.NewReader(data) - if err := struc.Unpack(buf, addr); err != nil { - panic(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) - } - - convAddr("10.10.10.10") - convAddr("::1") - convAddr("") -} - -func ipToAddress(ipstr string) (addr ip.Address, err error) { - netIP := net.ParseIP(ipstr) - if netIP == nil { - return ip.Address{}, fmt.Errorf("invalid IP: %q", ipstr) - } - if ip4 := netIP.To4(); ip4 == nil { - addr.Af = ip.ADDRESS_IP6 - var ip6addr ip.IP6Address - copy(ip6addr[:], netIP.To16()) - addr.Un.SetIP6(ip6addr) - } else { - addr.Af = ip.ADDRESS_IP4 - var ip4addr ip.IP4Address - copy(ip4addr[:], ip4) - addr.Un.SetIP4(ip4addr) - } - return -} |