added async connect API, new structure of examples
[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/api/ifcounters"
30         "git.fd.io/govpp.git/core"
31         "git.fd.io/govpp.git/core/bin_api/vpe"
32         "git.fd.io/govpp.git/examples/bin_api/interfaces"
33 )
34
35 func main() {
36         fmt.Println("Starting stats VPP client...")
37
38         // async connect to VPP
39         conn, statCh, err := govpp.AsyncConnect()
40         if err != nil {
41                 fmt.Println("Error:", err)
42                 os.Exit(1)
43         }
44         defer conn.Disconnect()
45
46         // create an API channel that will be used in the examples
47         ch, err := conn.NewAPIChannel()
48         if err != nil {
49                 fmt.Println("Error:", err)
50                 os.Exit(1)
51         }
52         defer ch.Close()
53
54         // create channel for Interrupt signal
55         sigChan := make(chan os.Signal, 1)
56         signal.Notify(sigChan, os.Interrupt)
57
58         var subs *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 subs == nil {
72                                         subs, notifChan = subscribeNotification(ch)
73                                 }
74                                 requestStatistics(ch)
75
76                         case core.Disconnected:
77                                 fmt.Println("VPP disconnected.")
78                         }
79
80                 case notifMsg := <-notifChan:
81                         // counter notification received
82                         processCounters(notifMsg.(*interfaces.VnetInterfaceCounters))
83
84                 case <-sigChan:
85                         // interrupt received
86                         fmt.Println("Interrupt received, exiting.")
87                         break loop
88                 }
89         }
90
91         ch.UnsubscribeNotification(subs)
92 }
93
94 // subscribeNotification subscribes for interface counters notifications.
95 func subscribeNotification(ch *api.Channel) (*api.NotifSubscription, chan api.Message) {
96
97         notifChan := make(chan api.Message, 100)
98         subs, _ := ch.SubscribeNotification(notifChan, interfaces.NewVnetInterfaceCounters)
99
100         return subs, notifChan
101 }
102
103 // requestStatistics requests interface counters notifications from VPP.
104 func requestStatistics(ch *api.Channel) {
105         ch.SendRequest(&vpe.WantStats{
106                 Pid:           uint32(os.Getpid()),
107                 EnableDisable: 1,
108         }).ReceiveReply(&vpe.WantStatsReply{})
109 }
110
111 // processCounters processes a counter message received from VPP.
112 func processCounters(msg *interfaces.VnetInterfaceCounters) {
113         fmt.Printf("%+v\n", msg)
114
115         if msg.IsCombined == 0 {
116                 // simple counter
117                 counters, err := ifcounters.DecodeCounters(ifcounters.VnetInterfaceCounters(*msg))
118                 if err != nil {
119                         fmt.Println("Error:", err)
120                 } else {
121                         fmt.Printf("%+v\n", counters)
122                 }
123         } else {
124                 // combined counter
125                 counters, err := ifcounters.DecodeCombinedCounters(ifcounters.VnetInterfaceCounters(*msg))
126                 if err != nil {
127                         fmt.Println("Error:", err)
128                 } else {
129                         fmt.Printf("%+v\n", counters)
130                 }
131         }
132 }