1 // Copyright (c) 2017 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 // Binary stats-client is an example VPP management application that exercises the
16 // govpp API for interface counters together with asynchronous connection to VPP.
26 "git.fd.io/govpp.git/api"
27 "git.fd.io/govpp.git/core"
28 "git.fd.io/govpp.git/examples/bin_api/stats"
32 fmt.Println("Starting stats VPP client..")
34 // async connect to VPP
35 conn, statCh, err := govpp.AsyncConnect("")
37 log.Fatalln("Error:", err)
39 defer conn.Disconnect()
41 // create an API channel that will be used in the examples
42 ch, err := conn.NewAPIChannel()
44 log.Fatalln("Error:", err)
48 // create channel for Interrupt signal
49 sigChan := make(chan os.Signal, 1)
50 signal.Notify(sigChan, os.Interrupt)
52 var notifChan chan api.Message
53 var simpleSub api.SubscriptionCtx
54 var combinedSub api.SubscriptionCtx
56 // loop until Interrupt signal is received
60 case connEvent := <-statCh:
61 // VPP connection state change
62 switch connEvent.State {
64 fmt.Println("VPP connected.")
66 simpleSub, combinedSub, notifChan = subscribeNotifications(ch)
70 case core.Disconnected:
71 fmt.Println("VPP disconnected.")
74 case msg := <-notifChan:
75 switch notif := msg.(type) {
76 case *stats.VnetInterfaceSimpleCounters:
77 // simple counter notification received
78 processSimpleCounters(notif)
79 case *stats.VnetInterfaceCombinedCounters:
80 // combined counter notification received
81 processCombinedCounters(notif)
83 fmt.Println("Ignoring unknown VPP notification")
88 fmt.Println("Interrupt received, exiting.")
93 simpleSub.Unsubscribe()
94 combinedSub.Unsubscribe()
97 // subscribeNotifications subscribes for interface counters notifications.
98 func subscribeNotifications(ch api.Channel) (api.SubscriptionCtx, api.SubscriptionCtx, chan api.Message) {
99 notifChan := make(chan api.Message, 100)
101 simpleSub, err := ch.SubscribeNotification(notifChan, &stats.VnetInterfaceSimpleCounters{})
105 combinedSub, err := ch.SubscribeNotification(notifChan, &stats.VnetInterfaceCombinedCounters{})
110 return simpleSub, combinedSub, notifChan
113 // requestStatistics requests interface counters notifications from VPP.
114 func requestStatistics(ch api.Channel) {
115 if err := ch.SendRequest(&stats.WantStats{
116 PID: uint32(os.Getpid()),
118 }).ReceiveReply(&stats.WantStatsReply{}); err != nil {
123 // processSimpleCounters processes simple counters received from VPP.
124 func processSimpleCounters(counters *stats.VnetInterfaceSimpleCounters) {
125 fmt.Printf("SimpleCounters: %+v\n", counters)
127 counterNames := []string{
131 "RxError", "TxError",
135 for i := uint32(0); i < counters.Count; i++ {
136 fmt.Printf("Interface '%d': %s = %d\n",
137 counters.FirstSwIfIndex+i, counterNames[counters.VnetCounterType], counters.Data[i])
141 // processCombinedCounters processes combined counters received from VPP.
142 func processCombinedCounters(counters *stats.VnetInterfaceCombinedCounters) {
143 fmt.Printf("CombinedCounters: %+v\n", counters)
145 counterNames := []string{"Rx", "Tx"}
147 for i := uint32(0); i < counters.Count; i++ {
148 if len(counterNames) <= int(counters.VnetCounterType) {
151 fmt.Printf("Interface '%d': %s packets = %d, %s bytes = %d\n",
152 counters.FirstSwIfIndex+i,
153 counterNames[counters.VnetCounterType], counters.Data[i].Packets,
154 counterNames[counters.VnetCounterType], counters.Data[i].Bytes)