@@ -554,42 +554,61 @@ func (spec *MapSpec) createMap(inner *sys.FD, c *btf.Cache) (_ *Map, err error)
554
554
defer handle .Close ()
555
555
556
556
if spec .Type == StructOpsMap {
557
+ if handle == nil {
558
+ return nil , fmt .Errorf ("struct_ops: BTF handle is not resolved" )
559
+ }
560
+
557
561
if spec .Value == nil {
558
562
return nil , fmt .Errorf ("struct_ops map: missing value type information" )
559
563
}
560
564
561
- valueType , ok := btf.As [* btf.Struct ](spec .Value )
565
+ if spec .Key == nil {
566
+ return nil , fmt .Errorf ("struct_ops map: Key must be specified" )
567
+ }
568
+
569
+ keyType , ok := btf.As [* btf.Int ](spec .Key )
562
570
if ! ok {
563
- return nil , fmt .Errorf ("value must be Struct type" )
571
+ return nil , fmt .Errorf ("key must be Int type" )
564
572
}
565
573
566
- if spec .KeySize != 4 {
567
- return nil , fmt .Errorf ("struct_ops: KeySize must be 4" )
574
+ // The key size of StructOps is always 4
575
+ if keyType .Size != 4 {
576
+ return nil , fmt .Errorf ("key size must be 4" )
577
+ }
578
+
579
+ valueType , ok := btf.As [* btf.Struct ](spec .Value )
580
+ if ! ok {
581
+ return nil , fmt .Errorf ("value must be Struct type" )
568
582
}
569
583
570
584
// struct_ops: resolve value type ("bpf_struct_ops_<name>") and
571
585
// record kernel-specific BTF IDs / FDs needed for map creation.
572
- target := btf .Type ((* btf .Struct )(nil ))
573
- s , module , err := findTargetInKernel (valueType .Name , & target , c )
586
+ vTarget := btf .Type ((* btf .Struct )(nil ))
587
+ s , module , err := findTargetInKernel (valueType .Name , & vTarget , c )
574
588
if err != nil {
575
589
return nil , fmt .Errorf ("lookup value type %q: %w" , valueType .Name , err )
576
590
}
577
591
defer module .Close ()
578
592
579
- vType := target .(* btf.Struct )
580
-
593
+ vType := vTarget .(* btf.Struct )
581
594
btfValueTypeId , err := s .TypeID (vType )
582
595
if err != nil {
583
596
return nil , fmt .Errorf ("lookup type_id: %w" , err )
584
597
}
585
598
586
- attr .ValueSize = spec . ValueSize
599
+ attr .BtfFd = uint32 ( handle . FD ())
587
600
attr .BtfVmlinuxValueTypeId = btfValueTypeId
588
-
589
- if handle == nil {
590
- return nil , fmt .Errorf ("struct_ops: BTF handle is not resolved" )
601
+ attr .KeySize , spec .KeySize = keyType .Size , keyType .Size
602
+
603
+ if spec .ValueSize == 0 {
604
+ attr .ValueSize , spec .ValueSize = vType .Size , vType .Size
605
+ } else {
606
+ // If spec.ValueSize is non-zero but does not match vtype.size, it should fail.
607
+ if spec .ValueSize != vType .Size {
608
+ return nil , fmt .Errorf ("struct_ops: ValueSize (%d) mismatches vtype size (%d)" , spec .ValueSize , vType .Size )
609
+ }
610
+ attr .ValueSize = spec .ValueSize
591
611
}
592
- attr .BtfFd = uint32 (handle .FD ())
593
612
594
613
if module != nil {
595
614
// BPF_F_VTYPE_BTF_OBJ_FD is required if the type comes from a module
0 commit comments