1 // Copyright (c) 2019 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.
22 "go.fd.io/govpp/adapter"
25 type statSegmentV1 struct {
30 type sharedHeaderV1 struct {
39 type statSegDirectoryEntryV1 struct {
41 // unionData can represent:
50 func newStatSegmentV1(data []byte, size int64) *statSegmentV1 {
51 return &statSegmentV1{
57 func (ss *statSegmentV1) loadSharedHeader(b []byte) (header sharedHeaderV1) {
58 h := (*sharedHeaderV1)(unsafe.Pointer(&b[0]))
59 return sharedHeaderV1{
60 version: atomic.LoadUint64(&h.version),
61 epoch: atomic.LoadInt64(&h.epoch),
62 inProgress: atomic.LoadInt64(&h.inProgress),
63 directoryOffset: atomic.LoadInt64(&h.directoryOffset),
64 errorOffset: atomic.LoadInt64(&h.errorOffset),
65 statsOffset: atomic.LoadInt64(&h.statsOffset),
69 func (ss *statSegmentV1) GetDirectoryVector() dirVector {
70 dirOffset, _, _ := ss.getOffsets()
71 return dirVector(&ss.sharedHeader[dirOffset])
74 func (ss *statSegmentV1) getErrorVector() (unsafe.Pointer, error) {
75 return nil, fmt.Errorf("error vector is not defined for stats API v1")
78 func (ss *statSegmentV1) GetStatDirOnIndex(v dirVector, index uint32) (dirSegment, dirName, adapter.StatType) {
79 statSegDir := dirSegment(uintptr(v) + uintptr(index)*unsafe.Sizeof(statSegDirectoryEntryV1{}))
80 dir := (*statSegDirectoryEntryV1)(statSegDir)
82 for n := 0; n < len(dir.name); n++ {
88 return statSegDir, name, getStatType(dir.directoryType, true)
91 func (ss *statSegmentV1) GetEpoch() (int64, bool) {
92 sh := ss.loadSharedHeader(ss.sharedHeader)
93 return sh.epoch, sh.inProgress != 0
96 func (ss *statSegmentV1) CopyEntryData(segment dirSegment, _ uint32) adapter.Stat {
97 dirEntry := (*statSegDirectoryEntryV1)(segment)
98 typ := getStatType(dirEntry.directoryType, true)
101 case adapter.ScalarIndex:
102 return adapter.ScalarStat(dirEntry.unionData)
104 case adapter.ErrorIndex:
105 if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
106 debugf("offset out of range for %s", dirEntry.name)
110 _, errOffset, _ := ss.getOffsets()
111 offsetVector := dirVector(&ss.sharedHeader[errOffset])
113 var errData []adapter.Counter
115 vecLen := *(*uint32)(vectorLen(offsetVector))
116 for i := uint32(0); i < vecLen; i++ {
117 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
118 offset := uintptr(cb) + uintptr(dirEntry.unionData)*unsafe.Sizeof(adapter.Counter(0))
119 debugf("error index, cb: %d, offset: %d", cb, offset)
120 val := *(*adapter.Counter)(statSegPointer(dirVector(&ss.sharedHeader[0]), offset))
121 errData = append(errData, val)
123 return adapter.ErrorStat(errData)
125 case adapter.SimpleCounterVector:
126 if dirEntry.unionData == 0 {
127 debugf("offset invalid for %s", dirEntry.name)
129 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
130 debugf("offset out of range for %s", dirEntry.name)
134 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
135 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
137 data := make([][]adapter.Counter, vecLen)
138 for i := uint32(0); i < vecLen; i++ {
139 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
140 counterVec := dirVector(&ss.sharedHeader[uintptr(cb)])
141 vecLen2 := *(*uint32)(vectorLen(counterVec))
142 data[i] = make([]adapter.Counter, vecLen2)
143 for j := uint32(0); j < vecLen2; j++ {
144 offset := uintptr(j) * unsafe.Sizeof(adapter.Counter(0))
145 val := *(*adapter.Counter)(statSegPointer(counterVec, offset))
149 return adapter.SimpleCounterStat(data)
151 case adapter.CombinedCounterVector:
152 if dirEntry.unionData == 0 {
153 debugf("offset invalid for %s", dirEntry.name)
155 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
156 debugf("offset out of range for %s", dirEntry.name)
160 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
161 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
163 data := make([][]adapter.CombinedCounter, vecLen)
164 for i := uint32(0); i < vecLen; i++ {
165 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
166 counterVec := dirVector(&ss.sharedHeader[uintptr(cb)])
167 vecLen2 := *(*uint32)(vectorLen(counterVec))
168 data[i] = make([]adapter.CombinedCounter, vecLen2)
169 for j := uint32(0); j < vecLen2; j++ {
170 offset := uintptr(j) * unsafe.Sizeof(adapter.CombinedCounter{})
171 val := *(*adapter.CombinedCounter)(statSegPointer(counterVec, offset))
175 return adapter.CombinedCounterStat(data)
177 case adapter.NameVector:
178 if dirEntry.unionData == 0 {
179 debugf("offset invalid for %s", dirEntry.name)
181 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
182 debugf("offset out of range for %s", dirEntry.name)
186 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
187 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
189 data := make([]adapter.Name, vecLen)
190 for i := uint32(0); i < vecLen; i++ {
191 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
193 debugf("name vector out of range for %s (%v)", dirEntry.name, i)
196 nameVec := dirVector(&ss.sharedHeader[cb])
197 vecLen2 := *(*uint32)(vectorLen(nameVec))
199 nameStr := make([]byte, 0, vecLen2)
200 for j := uint32(0); j < vecLen2; j++ {
201 offset := uintptr(j) * unsafe.Sizeof(byte(0))
202 val := *(*byte)(statSegPointer(nameVec, offset))
204 nameStr = append(nameStr, val)
209 return adapter.NameStat(data)
214 case adapter.Symlink:
215 debugf("Symlinks are not supported for stats v1")
218 // TODO: monitor occurrences with metrics
219 debugf("Unknown type %d for stat entry: %q", dirEntry.directoryType, dirEntry.name)
224 func (ss *statSegmentV1) UpdateEntryData(segment dirSegment, stat *adapter.Stat) error {
225 dirEntry := (*statSegDirectoryEntryV1)(segment)
226 switch (*stat).(type) {
227 case adapter.ScalarStat:
228 *stat = adapter.ScalarStat(dirEntry.unionData)
230 case adapter.ErrorStat:
231 if dirEntry.unionData == 0 {
232 debugf("offset invalid for %s", dirEntry.name)
234 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
235 debugf("offset out of range for %s", dirEntry.name)
239 _, errOffset, _ := ss.getOffsets()
240 offsetVector := dirVector(&ss.sharedHeader[errOffset])
242 var errData []adapter.Counter
244 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[errOffset])))
245 for i := uint32(0); i < vecLen; i++ {
246 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
247 offset := uintptr(cb) + uintptr(dirEntry.unionData)*unsafe.Sizeof(adapter.Counter(0))
248 val := *(*adapter.Counter)(statSegPointer(dirVector(&ss.sharedHeader[0]), offset))
249 errData = append(errData, val)
251 *stat = adapter.ErrorStat(errData)
253 case adapter.SimpleCounterStat:
254 if dirEntry.unionData == 0 {
255 debugf("offset invalid for %s", dirEntry.name)
257 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
258 debugf("offset out of range for %s", dirEntry.name)
262 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
263 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
265 data := (*stat).(adapter.SimpleCounterStat)
266 if uint32(len(data)) != vecLen {
267 return ErrStatDataLenIncorrect
269 for i := uint32(0); i < vecLen; i++ {
270 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
271 counterVec := dirVector(&ss.sharedHeader[uintptr(cb)])
272 vecLen2 := *(*uint32)(vectorLen(counterVec))
273 simpleData := data[i]
274 if uint32(len(simpleData)) != vecLen2 {
275 return ErrStatDataLenIncorrect
277 for j := uint32(0); j < vecLen2; j++ {
278 offset := uintptr(j) * unsafe.Sizeof(adapter.Counter(0))
279 val := *(*adapter.Counter)(statSegPointer(counterVec, offset))
284 case adapter.CombinedCounterStat:
285 if dirEntry.unionData == 0 {
286 debugf("offset invalid for %s", dirEntry.name)
288 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
289 debugf("offset out of range for %s", dirEntry.name)
293 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
294 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
296 data := (*stat).(adapter.CombinedCounterStat)
297 if uint32(len(data)) != vecLen {
298 return ErrStatDataLenIncorrect
300 for i := uint32(0); i < vecLen; i++ {
301 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
302 counterVec := dirVector(&ss.sharedHeader[uintptr(cb)])
303 vecLen2 := *(*uint32)(vectorLen(counterVec))
305 if uint32(len(combData)) != vecLen2 {
306 return ErrStatDataLenIncorrect
308 for j := uint32(0); j < vecLen2; j++ {
309 offset := uintptr(j) * unsafe.Sizeof(adapter.CombinedCounter{})
310 val := *(*adapter.CombinedCounter)(statSegPointer(counterVec, offset))
315 case adapter.NameStat:
316 if dirEntry.unionData == 0 {
317 debugf("offset invalid for %s", dirEntry.name)
319 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
320 debugf("offset out of range for %s", dirEntry.name)
324 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
325 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
327 data := (*stat).(adapter.NameStat)
328 if uint32(len(data)) != vecLen {
329 return ErrStatDataLenIncorrect
331 for i := uint32(0); i < vecLen; i++ {
332 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
336 nameVec := dirVector(&ss.sharedHeader[cb])
337 vecLen2 := *(*uint32)(vectorLen(nameVec))
340 if uint32(len(nameData))+1 != vecLen2 {
341 return ErrStatDataLenIncorrect
343 for j := uint32(0); j < vecLen2; j++ {
344 offset := uintptr(j) * unsafe.Sizeof(byte(0))
345 val := *(*byte)(statSegPointer(nameVec, offset))
355 Log.Debugf("Unrecognized stat type %T for stat entry: %v", stat, dirEntry.name)
361 // Get offsets for various types of data
362 func (ss *statSegmentV1) getOffsets() (dir, err, stat int64) {
363 sh := ss.loadSharedHeader(ss.sharedHeader)
364 return sh.directoryOffset, sh.errorOffset, sh.statsOffset