github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/datasource/accessors.go (about) 1 // Copyright 2024 The Inspektor Gadget authors 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 datasource 16 17 import ( 18 "errors" 19 "fmt" 20 "maps" 21 "math" 22 "slices" 23 24 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-service/api" 25 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets" 26 ) 27 28 // FieldAccessor grants access to the underlying buffer of a field 29 type FieldAccessor interface { 30 Name() string 31 32 // Size returns the expected size of the underlying field or zero, if the field has a dynamic size 33 Size() uint32 34 35 // Get returns the underlying memory of the field 36 Get(data Data) []byte 37 38 // Set sets value as the new reference for the field; if the FieldAccessor is used for the member of a 39 // statically sized payload (for example a member of an eBPF struct), value will be copied to the existing 40 // memory instead. 41 Set(data Data, value []byte) error 42 43 // IsRequested returns whether the consumer is interested in this field; if not, operators are not required 44 // to fill them out 45 IsRequested() bool 46 47 // AddSubField adds a new field as member of the current field; be careful when doing this on an existing 48 // non-empty field, as that might be dropped on serialization // TODO 49 AddSubField(name string, opts ...FieldOption) (FieldAccessor, error) 50 51 // GetSubFieldsWithTag returns all SubFields matching any given tag 52 GetSubFieldsWithTag(tag ...string) []FieldAccessor 53 54 // Parent returns the parent of this field, if this field is a SubField 55 Parent() FieldAccessor 56 57 // SubFields returns all existing SubFields of the current field 58 SubFields() []FieldAccessor 59 60 // SetHidden marks a field as hidden (by default) - it can still be requested 61 SetHidden(hidden bool, recurse bool) 62 63 // Type returns the underlying type of the field 64 Type() api.Kind 65 66 // Flags returns the flags of the field 67 Flags() uint32 68 69 // Annotations returns stored annotations of the field 70 Annotations() map[string]string 71 72 // RemoveReference removes the reference by name from the hierarchy, effectively freeing the name 73 // tbd: name 74 RemoveReference(recurse bool) 75 76 // Rename changes the name of the field. Currently it's not supported for subfields. 77 Rename(string) error 78 79 Uint8(Data) uint8 80 Uint16(Data) uint16 81 Uint32(Data) uint32 82 Uint64(Data) uint64 83 Int8(Data) int8 84 Int16(Data) int16 85 Int32(Data) int32 86 Int64(Data) int64 87 88 Float32(Data) float32 89 Float64(Data) float64 90 91 PutUint8(Data, uint8) 92 PutUint16(Data, uint16) 93 PutUint32(Data, uint32) 94 PutUint64(Data, uint64) 95 PutInt8(Data, int8) 96 PutInt16(Data, int16) 97 PutInt32(Data, int32) 98 PutInt64(Data, int64) 99 100 String(Data) string 101 CString(Data) string 102 } 103 104 type fieldAccessor struct { 105 ds *dataSource 106 f *field 107 } 108 109 func (a *fieldAccessor) Name() string { 110 return a.f.Name 111 } 112 113 func (a *fieldAccessor) Rename(name string) error { 114 a.ds.lock.Lock() 115 defer a.ds.lock.Unlock() 116 117 if _, ok := a.ds.fieldMap[name]; ok { 118 return fmt.Errorf("field with name %q already exists", name) 119 } 120 121 if a.f.Name != a.f.FullName { 122 return errors.New("Rename() not supported for subfields") 123 } 124 125 delete(a.ds.fieldMap, a.f.FullName) 126 127 a.f.Name = name 128 a.f.FullName = name 129 a.ds.fieldMap[name] = a.f 130 131 return nil 132 } 133 134 func (a *fieldAccessor) Size() uint32 { 135 return a.f.Size 136 } 137 138 func (a *fieldAccessor) Type() api.Kind { 139 return a.f.Kind 140 } 141 142 func (a *fieldAccessor) Get(d Data) []byte { 143 if FieldFlagEmpty.In(a.f.Flags) { 144 return nil 145 } 146 if a.f.Size > 0 { 147 // size and offset must be valid here; checks take place on initialization 148 return d.(*data).Payload[a.f.PayloadIndex][a.f.Offs : a.f.Offs+a.f.Size] 149 } 150 return d.(*data).Payload[a.f.PayloadIndex] 151 } 152 153 func (a *fieldAccessor) setHidden(hidden bool, recurse bool) { 154 if !hidden { 155 FieldFlagHidden.RemoveFrom(&a.f.Flags) 156 } else { 157 FieldFlagHidden.AddTo(&a.f.Flags) 158 } 159 if recurse { 160 for _, acc := range a.subFields() { 161 acc.(*fieldAccessor).setHidden(hidden, recurse) 162 } 163 } 164 } 165 166 func (a *fieldAccessor) SetHidden(hidden bool, recurse bool) { 167 a.ds.lock.Lock() 168 defer a.ds.lock.Unlock() 169 a.setHidden(hidden, recurse) 170 } 171 172 func (a *fieldAccessor) Set(d Data, b []byte) error { 173 if FieldFlagEmpty.In(a.f.Flags) { 174 return errors.New("field cannot contain a value") 175 } 176 if FieldFlagStaticMember.In(a.f.Flags) { 177 if uint32(len(b)) != a.f.Size { 178 return fmt.Errorf("invalid size, static member expected %d, got %d", a.f.Size, len(b)) 179 } 180 // When accessing a member of a statically sized field, copy memory 181 copy(d.Raw().Payload[a.f.PayloadIndex][a.f.Offs:a.f.Offs+a.f.Size], b) 182 return nil 183 } 184 if FieldFlagContainer.In(a.f.Flags) { 185 if uint32(len(b)) != a.f.Size { 186 return fmt.Errorf("invalid size, container expected %d, got %d", a.f.Size, len(b)) 187 } 188 } 189 d.(*data).Payload[a.f.PayloadIndex] = b 190 return nil 191 } 192 193 func (a *fieldAccessor) removeReference(recurse bool) { 194 // Add flag and remove from fieldMap 195 FieldFlagUnreferenced.AddTo(&a.f.Flags) 196 delete(a.ds.fieldMap, a.f.FullName) 197 if recurse { 198 for _, acc := range a.subFields() { 199 acc.(*fieldAccessor).removeReference(recurse) 200 } 201 } 202 } 203 204 func (a *fieldAccessor) RemoveReference(recurse bool) { 205 a.ds.lock.Lock() 206 defer a.ds.lock.Unlock() 207 a.removeReference(recurse) 208 } 209 210 func (a *fieldAccessor) AddSubField(name string, opts ...FieldOption) (FieldAccessor, error) { 211 a.ds.lock.Lock() 212 defer a.ds.lock.Unlock() 213 214 parentFullName, err := resolveNames(a.f.Index, a.ds.fields, 0) 215 if err != nil { 216 return nil, fmt.Errorf("resolving parent field name: %w", err) 217 } 218 219 nf := &field{ 220 Name: name, 221 FullName: parentFullName + "." + name, 222 Kind: api.Kind_Invalid, 223 Parent: a.f.Index, 224 Index: uint32(len(a.ds.fields)), 225 } 226 for _, opt := range opts { 227 opt(nf) 228 } 229 230 if _, ok := a.ds.fieldMap[nf.FullName]; ok { 231 return nil, fmt.Errorf("field with name %q already exists", nf.FullName) 232 } 233 234 FieldFlagHasParent.AddTo(&nf.Flags) 235 236 if !FieldFlagEmpty.In(nf.Flags) { 237 nf.PayloadIndex = a.ds.payloadCount 238 a.ds.payloadCount++ 239 } 240 241 a.ds.fields = append(a.ds.fields, nf) 242 a.ds.fieldMap[nf.FullName] = nf 243 return &fieldAccessor{ds: a.ds, f: nf}, nil 244 } 245 246 func (a *fieldAccessor) subFields() []FieldAccessor { 247 var res []FieldAccessor 248 for _, f := range a.ds.fields { 249 if !FieldFlagHasParent.In(f.Flags) { 250 continue 251 } 252 if f.Parent != a.f.Index { 253 continue 254 } 255 res = append(res, &fieldAccessor{ 256 ds: a.ds, 257 f: f, 258 }) 259 } 260 return res 261 } 262 263 func (a *fieldAccessor) SubFields() []FieldAccessor { 264 a.ds.lock.RLock() 265 defer a.ds.lock.RUnlock() 266 return a.subFields() 267 } 268 269 func (a *fieldAccessor) Parent() FieldAccessor { 270 a.ds.lock.RLock() 271 defer a.ds.lock.RUnlock() 272 273 if !FieldFlagHasParent.In(a.f.Flags) { 274 return nil 275 } 276 if a.f.Parent >= uint32(len(a.ds.fields)) { 277 return nil 278 } 279 return &fieldAccessor{ds: a.ds, f: a.ds.fields[a.f.Parent]} 280 } 281 282 func (a *fieldAccessor) GetSubFieldsWithTag(tag ...string) []FieldAccessor { 283 a.ds.lock.RLock() 284 defer a.ds.lock.RUnlock() 285 286 res := make([]FieldAccessor, 0) 287 for _, f := range a.ds.fields { 288 if !FieldFlagHasParent.In(f.Flags) { 289 continue 290 } 291 if f.Parent != a.f.Index { 292 continue 293 } 294 for _, t := range tag { 295 if slices.Contains(f.Tags, t) { 296 res = append(res, &fieldAccessor{ds: a.ds, f: f}) 297 break 298 } 299 } 300 } 301 return res 302 } 303 304 func (a *fieldAccessor) IsRequested() bool { 305 return a.ds.IsRequestedField(a.f.Name) 306 } 307 308 func (a *fieldAccessor) Flags() uint32 { 309 return a.f.Flags 310 } 311 312 func (a *fieldAccessor) Annotations() map[string]string { 313 if a.f.Annotations == nil { 314 // Return an empty map to allow access without prior checks 315 return map[string]string{} 316 } 317 // return a clone to avoid write access 318 return maps.Clone(a.f.Annotations) 319 } 320 321 func (a *fieldAccessor) Uint8(data Data) uint8 { 322 val := a.Get(data) 323 if len(val) < 1 { 324 return 0 325 } 326 return val[0] 327 } 328 329 func (a *fieldAccessor) Uint16(data Data) uint16 { 330 val := a.Get(data) 331 if len(val) < 2 { 332 return 0 333 } 334 return a.ds.byteOrder.Uint16(val) 335 } 336 337 func (a *fieldAccessor) Uint32(data Data) uint32 { 338 val := a.Get(data) 339 if len(val) < 4 { 340 return 0 341 } 342 return a.ds.byteOrder.Uint32(val) 343 } 344 345 func (a *fieldAccessor) Uint64(data Data) uint64 { 346 val := a.Get(data) 347 if len(val) < 8 { 348 return 0 349 } 350 return a.ds.byteOrder.Uint64(val) 351 } 352 353 func (a *fieldAccessor) Int8(data Data) int8 { 354 val := a.Get(data) 355 if len(val) < 1 { 356 return 0 357 } 358 return int8(val[0]) 359 } 360 361 func (a *fieldAccessor) Int16(data Data) int16 { 362 val := a.Get(data) 363 if len(val) < 2 { 364 return 0 365 } 366 return int16(a.ds.byteOrder.Uint16(val)) 367 } 368 369 func (a *fieldAccessor) Int32(data Data) int32 { 370 val := a.Get(data) 371 if len(val) < 4 { 372 return 0 373 } 374 return int32(a.ds.byteOrder.Uint32(val)) 375 } 376 377 func (a *fieldAccessor) Int64(data Data) int64 { 378 val := a.Get(data) 379 if len(val) < 8 { 380 return 0 381 } 382 return int64(a.ds.byteOrder.Uint64(val)) 383 } 384 385 func (a *fieldAccessor) Float32(data Data) float32 { 386 return math.Float32frombits(a.Uint32(data)) 387 } 388 389 func (a *fieldAccessor) Float64(data Data) float64 { 390 return math.Float64frombits(a.Uint64(data)) 391 } 392 393 func (a *fieldAccessor) String(data Data) string { 394 return string(a.Get(data)) 395 } 396 397 func (a *fieldAccessor) CString(data Data) string { 398 return gadgets.FromCString(a.Get(data)) 399 } 400 401 func (a *fieldAccessor) PutUint8(data Data, val uint8) { 402 a.Get(data)[0] = val 403 } 404 405 func (a *fieldAccessor) PutUint16(data Data, val uint16) { 406 a.ds.byteOrder.PutUint16(a.Get(data), val) 407 } 408 409 func (a *fieldAccessor) PutUint32(data Data, val uint32) { 410 a.ds.byteOrder.PutUint32(a.Get(data), val) 411 } 412 413 func (a *fieldAccessor) PutUint64(data Data, val uint64) { 414 a.ds.byteOrder.PutUint64(a.Get(data), val) 415 } 416 417 func (a *fieldAccessor) PutInt8(data Data, val int8) { 418 a.Get(data)[0] = uint8(val) 419 } 420 421 func (a *fieldAccessor) PutInt16(data Data, val int16) { 422 a.ds.byteOrder.PutUint16(a.Get(data), uint16(val)) 423 } 424 425 func (a *fieldAccessor) PutInt32(data Data, val int32) { 426 a.ds.byteOrder.PutUint32(a.Get(data), uint32(val)) 427 } 428 429 func (a *fieldAccessor) PutInt64(data Data, val int64) { 430 a.ds.byteOrder.PutUint64(a.Get(data), uint64(val)) 431 }