1 // Copyright (c) 2020 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 "git.fd.io/govpp.git/adapter"
25 type statSegmentV2 struct {
30 type sharedHeaderV2 struct {
35 dirVector unsafe.Pointer
36 errorVector unsafe.Pointer
39 type statSegDirectoryEntryV2 struct {
40 directoryType statDirectoryType
41 // unionData can represent:
49 func newStatSegmentV2(data []byte, size int64) *statSegmentV2 {
50 return &statSegmentV2{
56 func (ss *statSegmentV2) loadSharedHeader(b []byte) (header sharedHeaderV2) {
57 h := (*sharedHeaderV2)(unsafe.Pointer(&b[0]))
58 return sharedHeaderV2{
59 version: atomic.LoadUint64(&h.version),
60 base: atomic.LoadPointer(&h.base),
61 epoch: atomic.LoadInt64(&h.epoch),
62 inProgress: atomic.LoadInt64(&h.inProgress),
63 dirVector: atomic.LoadPointer(&h.dirVector),
64 errorVector: atomic.LoadPointer(&h.errorVector),
68 func (ss *statSegmentV2) GetDirectoryVector() (unsafe.Pointer, error) {
69 header := ss.loadSharedHeader(ss.sharedHeader)
70 return ss.adjust(unsafe.Pointer(&header.dirVector))
73 func (ss *statSegmentV2) GetStatDirOnIndex(p unsafe.Pointer, index uint32) (unsafe.Pointer, statDirectoryName, statDirectoryType) {
74 statSegDir := unsafe.Pointer(uintptr(p) + uintptr(index)*unsafe.Sizeof(statSegDirectoryEntryV2{}))
75 dir := (*statSegDirectoryEntryV2)(statSegDir)
77 for n := 0; n < len(dir.name); n++ {
83 return statSegDir, name, dir.directoryType
86 func (ss *statSegmentV2) GetEpoch() (int64, bool) {
87 sh := ss.loadSharedHeader(ss.sharedHeader)
88 return sh.epoch, sh.inProgress != 0
91 func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
92 dirEntry := (*statSegDirectoryEntryV2)(statSegDir)
93 if dirEntry.unionData == 0 {
94 debugf("data value or pointer not defined for %s", dirEntry.name)
98 switch adapter.StatType(dirEntry.directoryType) {
99 case statDirScalarIndex:
100 return adapter.ScalarStat(dirEntry.unionData)
102 case statDirErrorIndex:
103 dirVector, err := ss.getErrorVector()
105 debugf("error vector pointer is out of range for %s", dirEntry.name)
108 vecLen := *(*uint32)(vectorLen(dirVector))
109 var errData adapter.Counter
110 for i := uint32(0); i < vecLen; i++ {
111 cb := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
112 cbVal, err := ss.adjust(vectorLen(cb))
114 debugf("error counter pointer out of range")
117 offset := uintptr(dirEntry.unionData) * unsafe.Sizeof(adapter.Counter(0))
118 val := *(*adapter.Counter)(statSegPointer(cbVal, offset))
121 return adapter.ErrorStat(errData)
123 case statDirCounterVectorSimple:
124 dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
126 debugf("data vector pointer is out of range for %s", dirEntry.name)
129 vecLen := *(*uint32)(vectorLen(dirVector))
130 data := make([][]adapter.Counter, vecLen)
131 for i := uint32(0); i < vecLen; i++ {
132 counterVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
133 counterVector, err := ss.adjust(vectorLen(counterVectorOffset))
135 debugf("counter (vector simple) pointer out of range")
138 counterVectorLength := *(*uint32)(vectorLen(counterVector))
139 data[i] = make([]adapter.Counter, counterVectorLength)
140 for j := uint32(0); j < counterVectorLength; j++ {
141 offset := uintptr(j) * unsafe.Sizeof(adapter.Counter(0))
142 val := *(*adapter.Counter)(statSegPointer(counterVector, offset))
146 return adapter.SimpleCounterStat(data)
148 case statDirCounterVectorCombined:
149 dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
151 debugf("data vector pointer is out of range for %s", dirEntry.name)
154 vecLen := *(*uint32)(vectorLen(dirVector))
155 data := make([][]adapter.CombinedCounter, vecLen)
156 for i := uint32(0); i < vecLen; i++ {
157 counterVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
158 counterVector, err := ss.adjust(vectorLen(counterVectorOffset))
160 debugf("counter (vector combined) pointer out of range")
163 counterVectorLength := *(*uint32)(vectorLen(counterVector))
164 data[i] = make([]adapter.CombinedCounter, counterVectorLength)
165 for j := uint32(0); j < counterVectorLength; j++ {
166 offset := uintptr(j) * unsafe.Sizeof(adapter.CombinedCounter{})
167 val := *(*adapter.CombinedCounter)(statSegPointer(counterVector, offset))
171 return adapter.CombinedCounterStat(data)
173 case statDirNameVector:
174 dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
176 debugf("data vector pointer is out of range for %s", dirEntry.name)
179 vecLen := *(*uint32)(vectorLen(dirVector))
180 data := make([]adapter.Name, vecLen)
181 for i := uint32(0); i < vecLen; i++ {
182 nameVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
183 if uintptr(nameVectorOffset) == 0 {
184 debugf("name vector out of range for %s (%v)", dirEntry.name, i)
187 nameVector, err := ss.adjust(vectorLen(nameVectorOffset))
189 debugf("name data pointer out of range")
192 nameVectorLen := *(*uint32)(vectorLen(nameVector))
193 name := make([]byte, 0, nameVectorLen)
194 for j := uint32(0); j < nameVectorLen; j++ {
195 offset := uintptr(j) * unsafe.Sizeof(byte(0))
196 value := *(*byte)(statSegPointer(nameVector, offset))
198 name = append(name, value)
203 return adapter.NameStat(data)
209 // TODO: monitor occurrences with metrics
210 debugf("Unknown type %d for stat entry: %q", dirEntry.directoryType, dirEntry.name)
215 func (ss *statSegmentV2) UpdateEntryData(statSegDir unsafe.Pointer, stat *adapter.Stat) error {
216 dirEntry := (*statSegDirectoryEntryV2)(statSegDir)
217 switch (*stat).(type) {
218 case adapter.ScalarStat:
219 *stat = adapter.ScalarStat(dirEntry.unionData)
221 case adapter.ErrorStat:
222 dirVector, err := ss.getErrorVector()
224 debugf("error vector pointer is out of range for %s", dirEntry.name)
227 vecLen := *(*uint32)(vectorLen(dirVector))
228 var errData adapter.Counter
229 for i := uint32(0); i < vecLen; i++ {
230 cb := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
231 cbVal, err := ss.adjust(vectorLen(cb))
233 debugf("error counter pointer out of range")
236 offset := uintptr(dirEntry.unionData) * unsafe.Sizeof(adapter.Counter(0))
237 val := *(*adapter.Counter)(statSegPointer(cbVal, offset))
240 *stat = adapter.ErrorStat(errData)
242 case adapter.SimpleCounterStat:
243 dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
245 debugf("data vector pointer is out of range for %s", dirEntry.name)
248 vecLen := *(*uint32)(vectorLen(dirVector))
249 data := (*stat).(adapter.SimpleCounterStat)
250 if uint32(len(data)) != vecLen {
251 return ErrStatDataLenIncorrect
253 for i := uint32(0); i < vecLen; i++ {
254 counterVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
255 counterVector, err := ss.adjust(vectorLen(counterVectorOffset))
257 debugf("counter (vector simple) pointer out of range")
260 counterVectorLength := *(*uint32)(vectorLen(counterVector))
261 data[i] = make([]adapter.Counter, counterVectorLength)
262 for j := uint32(0); j < counterVectorLength; j++ {
263 offset := uintptr(j) * unsafe.Sizeof(adapter.Counter(0))
264 val := *(*adapter.Counter)(statSegPointer(counterVector, offset))
269 case adapter.CombinedCounterStat:
270 dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
272 debugf("data vector pointer is out of range for %s", dirEntry.name)
275 vecLen := *(*uint32)(vectorLen(dirVector))
276 data := (*stat).(adapter.CombinedCounterStat)
277 for i := uint32(0); i < vecLen; i++ {
278 counterVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
279 counterVector, err := ss.adjust(vectorLen(counterVectorOffset))
281 debugf("counter (vector combined) pointer out of range")
284 counterVectorLength := *(*uint32)(vectorLen(counterVector))
285 data[i] = make([]adapter.CombinedCounter, counterVectorLength)
286 for j := uint32(0); j < counterVectorLength; j++ {
287 offset := uintptr(j) * unsafe.Sizeof(adapter.CombinedCounter{})
288 val := *(*adapter.CombinedCounter)(statSegPointer(counterVector, offset))
293 case adapter.NameStat:
294 dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
296 debugf("data vector pointer is out of range for %s", dirEntry.name)
299 vecLen := *(*uint32)(vectorLen(dirVector))
300 data := (*stat).(adapter.NameStat)
301 for i := uint32(0); i < vecLen; i++ {
302 nameVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
303 if uintptr(nameVectorOffset) == 0 {
304 debugf("name vector out of range for %s (%v)", dirEntry.name, i)
307 nameVector, err := ss.adjust(vectorLen(nameVectorOffset))
309 debugf("name data pointer out of range")
312 nameVectorLen := *(*uint32)(vectorLen(nameVector))
314 if uint32(len(nameData))+1 != nameVectorLen {
315 return ErrStatDataLenIncorrect
317 for j := uint32(0); j < nameVectorLen; j++ {
318 offset := uintptr(j) * unsafe.Sizeof(byte(0))
319 value := *(*byte)(statSegPointer(nameVector, offset))
329 Log.Debugf("Unrecognized stat type %T for stat entry: %v", stat, dirEntry.name)
335 // Adjust data pointer using shared header and base and return
336 // the pointer to a data segment
337 func (ss *statSegmentV2) adjust(data unsafe.Pointer) (unsafe.Pointer, error) {
338 header := ss.loadSharedHeader(ss.sharedHeader)
339 adjusted := unsafe.Pointer(uintptr(unsafe.Pointer(&ss.sharedHeader[0])) +
340 uintptr(*(*uint64)(data)) - uintptr(*(*uint64)(unsafe.Pointer(&header.base))))
341 if uintptr(unsafe.Pointer(&ss.sharedHeader[len(ss.sharedHeader)-1])) <= uintptr(adjusted) ||
342 uintptr(unsafe.Pointer(&ss.sharedHeader[0])) >= uintptr(adjusted) {
343 return nil, fmt.Errorf("adjusted data out of range for %v", data)
348 func (ss *statSegmentV2) getErrorVector() (unsafe.Pointer, error) {
349 header := ss.loadSharedHeader(ss.sharedHeader)
350 return ss.adjust(unsafe.Pointer(&header.errorVector))