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