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  }