support for shm prefixes
[govpp.git] / examples / cmd / stats-client / stats_client.go
1 // Copyright (c) 2017 Cisco and/or its affiliates.
2 //
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:
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14
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.
17 package main
18
19 // Generates Go bindings for all VPP APIs located in the json directory.
20 //go:generate binapi-generator --input-dir=../../bin_api --output-dir=../../bin_api
21
22 import (
23         "fmt"
24         "os"
25         "os/signal"
26
27         "git.fd.io/govpp.git"
28         "git.fd.io/govpp.git/api"
29         "git.fd.io/govpp.git/core"
30         "git.fd.io/govpp.git/examples/bin_api/interfaces"
31         "git.fd.io/govpp.git/examples/bin_api/stats"
32 )
33
34 func main() {
35         fmt.Println("Starting stats VPP client...")
36
37         // async connect to VPP
38         conn, statCh, err := govpp.AsyncConnect("")
39         if err != nil {
40                 fmt.Println("Error:", err)
41                 os.Exit(1)
42         }
43         defer conn.Disconnect()
44
45         // create an API channel that will be used in the examples
46         ch, err := conn.NewAPIChannel()
47         if err != nil {
48                 fmt.Println("Error:", err)
49                 os.Exit(1)
50         }
51         defer ch.Close()
52
53         // create channel for Interrupt signal
54         sigChan := make(chan os.Signal, 1)
55         signal.Notify(sigChan, os.Interrupt)
56
57         var simpleCountersSubs *api.NotifSubscription
58         var combinedCountersSubs *api.NotifSubscription
59         var notifChan chan api.Message
60
61         // loop until Interrupt signal is received
62 loop:
63         for {
64                 select {
65
66                 case connEvent := <-statCh:
67                         // VPP connection state change
68                         switch connEvent.State {
69                         case core.Connected:
70                                 fmt.Println("VPP connected.")
71                                 if simpleCountersSubs == nil {
72                                         simpleCountersSubs, combinedCountersSubs, notifChan = subscribeNotifications(ch)
73                                 }
74                                 requestStatistics(ch)
75
76                         case core.Disconnected:
77                                 fmt.Println("VPP disconnected.")
78                         }
79
80                 case msg := <-notifChan:
81                         switch notif := msg.(type) {
82                         case *interfaces.VnetInterfaceSimpleCounters:
83                                 // simple counter notification received
84                                 processSimpleCounters(notif)
85                         case *interfaces.VnetInterfaceCombinedCounters:
86                                 // combined counter notification received
87                                 processCombinedCounters(notif)
88                         default:
89                                 fmt.Println("Ignoring unknown VPP notification")
90                         }
91
92                 case <-sigChan:
93                         // interrupt received
94                         fmt.Println("Interrupt received, exiting.")
95                         break loop
96                 }
97         }
98
99         ch.UnsubscribeNotification(simpleCountersSubs)
100         ch.UnsubscribeNotification(combinedCountersSubs)
101 }
102
103 // subscribeNotifications subscribes for interface counters notifications.
104 func subscribeNotifications(ch *api.Channel) (*api.NotifSubscription, *api.NotifSubscription, chan api.Message) {
105
106         notifChan := make(chan api.Message, 100)
107         simpleCountersSubs, _ := ch.SubscribeNotification(notifChan, interfaces.NewVnetInterfaceSimpleCounters)
108         combinedCountersSubs, _ := ch.SubscribeNotification(notifChan, interfaces.NewVnetInterfaceCombinedCounters)
109
110         return simpleCountersSubs, combinedCountersSubs, notifChan
111 }
112
113 // requestStatistics requests interface counters notifications from VPP.
114 func requestStatistics(ch *api.Channel) {
115         ch.SendRequest(&stats.WantStats{
116                 Pid:           uint32(os.Getpid()),
117                 EnableDisable: 1,
118         }).ReceiveReply(&stats.WantStatsReply{})
119 }
120
121 // processSimpleCounters processes simple counters received from VPP.
122 func processSimpleCounters(counters *interfaces.VnetInterfaceSimpleCounters) {
123         fmt.Printf("%+v\n", counters)
124
125         counterNames := []string{"Drop", "Punt", "IPv4", "IPv6", "RxNoBuf", "RxMiss", "RxError", "TxError", "MPLS"}
126
127         for i := uint32(0); i < counters.Count; i++ {
128                 fmt.Printf("Interface '%d': %s = %d\n",
129                         counters.FirstSwIfIndex+i, counterNames[counters.VnetCounterType], counters.Data[i])
130         }
131 }
132
133 // processCombinedCounters processes combined counters received from VPP.
134 func processCombinedCounters(counters *interfaces.VnetInterfaceCombinedCounters) {
135         fmt.Printf("%+v\n", counters)
136
137         counterNames := []string{"Rx", "Tx"}
138
139         for i := uint32(0); i < counters.Count; i++ {
140                 fmt.Printf("Interface '%d': %s packets = %d, %s bytes = %d\n",
141                         counters.FirstSwIfIndex+i, counterNames[counters.VnetCounterType], counters.Data[i].Packets,
142                         counterNames[counters.VnetCounterType], counters.Data[i].Bytes)
143         }
144 }