initial commit
[govpp.git] / api / ifcounters / ifcounters.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 package ifcounters
16
17 import (
18         "bytes"
19         "errors"
20         "fmt"
21
22         "github.com/lunixbochs/struc"
23 )
24
25 // VnetInterfaceCounters is the input data type defined in the 'interface.api', with binary encoded Data field,
26 // that can be decoded into the InterfaceCounter or CombinedInterfaceCounter struct using this package.
27 type VnetInterfaceCounters struct {
28         VnetCounterType uint8
29         IsCombined      uint8
30         FirstSwIfIndex  uint32
31         Count           uint32 `struc:"sizeof=Data"`
32         Data            []byte
33 }
34
35 // CounterType is the basic counter type - contains only packet statistics.
36 type CounterType int
37
38 // constants as defined in the vnet_interface_counter_type_t enum in 'vnet/interface.h'
39 const (
40         Drop    CounterType = 0
41         Punt                = 1
42         IPv4                = 2
43         IPv6                = 3
44         RxNoBuf             = 4
45         RxMiss              = 5
46         RxError             = 6
47         TxError             = 7
48         MPLS                = 8
49 )
50
51 // CombinedCounterType is the extended counter type - contains both packet and byte statistics.
52 type CombinedCounterType int
53
54 // constants as defined in the vnet_interface_counter_type_t enum in 'vnet/interface.h'
55 const (
56         Rx CombinedCounterType = 0
57         Tx                     = 1
58 )
59
60 // InterfaceCounter contains basic counter data (contains only packet statistics).
61 type InterfaceCounter struct {
62         Type      CounterType
63         SwIfIndex uint32
64         Packets   uint64
65 }
66
67 // CombinedInterfaceCounter contains extended counter data (contains both packet and byte statistics).
68 type CombinedInterfaceCounter struct {
69         Type      CombinedCounterType
70         SwIfIndex uint32
71         Packets   uint64
72         Bytes     uint64
73 }
74
75 type counterData struct {
76         Packets uint64
77 }
78
79 type counter struct {
80         Count uint32 `struc:"sizeof=Data"`
81         Data  []counterData
82 }
83
84 type combinedCounterData struct {
85         Packets uint64
86         Bytes   uint64
87 }
88
89 type combinedCounter struct {
90         Count uint32 `struc:"sizeof=Data"`
91         Data  []combinedCounterData
92 }
93
94 // DecodeCounters decodes VnetInterfaceCounters struct content into the slice of InterfaceCounter structs.
95 func DecodeCounters(vnetCounters VnetInterfaceCounters) ([]InterfaceCounter, error) {
96         if vnetCounters.IsCombined == 1 {
97                 return nil, errors.New("invalid argument - combined counter passed in")
98         }
99
100         // decode into internal struct
101         var c counter
102         buf := bytes.NewReader(vnetCounters.Data)
103         err := struc.Unpack(buf, &c)
104         if err != nil {
105                 return nil, fmt.Errorf("unable to decode counter data: %v", err)
106         }
107
108         // prepare the slice
109         res := make([]InterfaceCounter, c.Count)
110
111         // fill in the slice
112         for i := uint32(0); i < c.Count; i++ {
113                 res[i].Type = CounterType(vnetCounters.VnetCounterType)
114                 res[i].SwIfIndex = vnetCounters.FirstSwIfIndex + i
115                 res[i].Packets = c.Data[i].Packets
116         }
117
118         return res, nil
119 }
120
121 // DecodeCombinedCounters decodes VnetInterfaceCounters struct content into the slice of CombinedInterfaceCounter structs.
122 func DecodeCombinedCounters(vnetCounters VnetInterfaceCounters) ([]CombinedInterfaceCounter, error) {
123         if vnetCounters.IsCombined != 1 {
124                 return nil, errors.New("invalid argument - simple counter passed in")
125         }
126
127         // decode into internal struct
128         var c combinedCounter
129         buf := bytes.NewReader(vnetCounters.Data)
130         err := struc.Unpack(buf, &c)
131         if err != nil {
132                 return nil, fmt.Errorf("unable to decode counter data: %v", err)
133         }
134
135         // prepare the slice
136         res := make([]CombinedInterfaceCounter, c.Count)
137
138         // fill in the slice
139         for i := uint32(0); i < c.Count; i++ {
140                 res[i].Type = CombinedCounterType(vnetCounters.VnetCounterType)
141                 res[i].SwIfIndex = vnetCounters.FirstSwIfIndex + i
142                 res[i].Packets = c.Data[i].Packets
143                 res[i].Bytes = c.Data[i].Bytes
144         }
145
146         return res, nil
147 }