@@ -19,8 +19,9 @@ import (
19
19
//
20
20
// Maps and Programs are passed to NewMapWithOptions and NewProgramsWithOptions.
21
21
type CollectionOptions struct {
22
- Maps MapOptions
23
- Programs ProgramOptions
22
+ Maps MapOptions
23
+ Variables VariableOptions
24
+ Programs ProgramOptions
24
25
25
26
// MapReplacements takes a set of Maps that will be used instead of
26
27
// creating new ones when loading the CollectionSpec.
@@ -36,8 +37,9 @@ type CollectionOptions struct {
36
37
37
38
// CollectionSpec describes a collection.
38
39
type CollectionSpec struct {
39
- Maps map [string ]* MapSpec
40
- Programs map [string ]* ProgramSpec
40
+ Maps map [string ]* MapSpec
41
+ Variables map [string ]* VariableSpec
42
+ Programs map [string ]* ProgramSpec
41
43
42
44
// Types holds type information about Maps and Programs.
43
45
// Modifications to Types are currently undefined behaviour.
@@ -56,6 +58,7 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
56
58
57
59
cpy := CollectionSpec {
58
60
Maps : make (map [string ]* MapSpec , len (cs .Maps )),
61
+ Variables : make (map [string ]* VariableSpec , len (cs .Variables )),
59
62
Programs : make (map [string ]* ProgramSpec , len (cs .Programs )),
60
63
ByteOrder : cs .ByteOrder ,
61
64
Types : cs .Types .Copy (),
@@ -65,6 +68,10 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
65
68
cpy .Maps [name ] = spec .Copy ()
66
69
}
67
70
71
+ for name , spec := range cs .Variables {
72
+ cpy .Variables [name ] = spec .Copy ()
73
+ }
74
+
68
75
for name , spec := range cs .Programs {
69
76
cpy .Programs [name ] = spec .Copy ()
70
77
}
@@ -286,6 +293,7 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
286
293
287
294
// Support assigning Programs and Maps, lazy-loading the required objects.
288
295
assignedMaps := make (map [string ]bool )
296
+ assignedVars := make (map [string ]bool )
289
297
assignedProgs := make (map [string ]bool )
290
298
291
299
getValue := func (typ reflect.Type , name string ) (interface {}, error ) {
@@ -299,6 +307,10 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
299
307
assignedMaps [name ] = true
300
308
return loader .loadMap (name )
301
309
310
+ case reflect .TypeOf ((* Variable )(nil )):
311
+ assignedVars [name ] = true
312
+ return loader .loadVariable (name )
313
+
302
314
default :
303
315
return nil , fmt .Errorf ("unsupported type %s" , typ )
304
316
}
@@ -336,18 +348,21 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
336
348
for m := range assignedMaps {
337
349
delete (loader .maps , m )
338
350
}
351
+ for v := range assignedVars {
352
+ delete (loader .vars , v )
353
+ }
339
354
for p := range assignedProgs {
340
355
delete (loader .programs , p )
341
356
}
342
357
343
358
return nil
344
359
}
345
360
346
- // Collection is a collection of Programs and Maps associated
347
- // with their symbols
361
+ // Collection is a collection of Programs and Maps associated with their variables
348
362
type Collection struct {
349
- Programs map [string ]* Program
350
- Maps map [string ]* Map
363
+ Programs map [string ]* Program
364
+ Maps map [string ]* Map
365
+ Variables map [string ]* Variable
351
366
}
352
367
353
368
// NewCollection creates a Collection from the given spec, creating and
@@ -377,6 +392,11 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co
377
392
return nil , err
378
393
}
379
394
}
395
+ for varName := range spec .Variables {
396
+ if _ , err := loader .loadVariable (varName ); err != nil {
397
+ return nil , err
398
+ }
399
+ }
380
400
381
401
for progName , prog := range spec .Programs {
382
402
if prog .Type == UnspecifiedProgram {
@@ -394,20 +414,23 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co
394
414
return nil , err
395
415
}
396
416
397
- // Prevent loader.cleanup from closing maps and programs.
398
- maps , progs := loader .maps , loader .programs
399
- loader .maps , loader .programs = nil , nil
417
+ // Prevent loader.cleanup from closing maps, vars and programs.
418
+ maps , vars , progs := loader .maps , loader . vars , loader .programs
419
+ loader .maps , loader .vars , loader . programs = nil , nil , nil
400
420
401
421
return & Collection {
402
422
progs ,
403
423
maps ,
424
+ vars ,
404
425
}, nil
405
426
}
406
427
407
428
type collectionLoader struct {
408
429
coll * CollectionSpec
409
430
opts * CollectionOptions
410
431
maps map [string ]* Map
432
+ vars map [string ]* Variable
433
+ memory map [string ]* MapMemory
411
434
programs map [string ]* Program
412
435
}
413
436
@@ -432,6 +455,8 @@ func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) (*collec
432
455
coll ,
433
456
opts ,
434
457
make (map [string ]* Map ),
458
+ make (map [string ]* Variable ),
459
+ make (map [string ]* MapMemory ),
435
460
make (map [string ]* Program ),
436
461
}, nil
437
462
}
@@ -446,6 +471,39 @@ func (cl *collectionLoader) close() {
446
471
}
447
472
}
448
473
474
+ func (cl * collectionLoader ) loadVariable (varName string ) (* Variable , error ) {
475
+ if s := cl .vars [varName ]; s != nil {
476
+ return s , nil
477
+ }
478
+
479
+ varSpec := cl .coll .Variables [varName ]
480
+ if varSpec == nil {
481
+ return nil , fmt .Errorf ("missing variable %s" , varName )
482
+ }
483
+
484
+ m := cl .maps [varSpec .MapName ]
485
+ if m == nil {
486
+ return nil , fmt .Errorf ("map %s for variable %s not found" , varSpec .MapName , varName )
487
+ }
488
+
489
+ if _ , ok := cl .memory [varSpec .MapName ]; ! ok {
490
+ // TODO: kernel before mmap support will always fail to load a prog with variables
491
+ mm , err := m .Memory ()
492
+ if err != nil {
493
+ return nil , err
494
+ }
495
+ cl .memory [varSpec .MapName ] = mm
496
+ }
497
+
498
+ v , err := newVariableWithOptions (varSpec , cl .memory [varSpec .MapName ], cl .opts .Variables )
499
+ if err != nil {
500
+ return nil , fmt .Errorf ("variable %v: %w" , varName , err )
501
+ }
502
+
503
+ cl .vars [varName ] = v
504
+ return v , nil
505
+ }
506
+
449
507
func (cl * collectionLoader ) loadMap (mapName string ) (* Map , error ) {
450
508
if m := cl .maps [mapName ]; m != nil {
451
509
return m , nil
@@ -723,6 +781,7 @@ func LoadCollection(file string) (*Collection, error) {
723
781
// for any successful assigns. On error `to` is left in an undefined state.
724
782
func (coll * Collection ) Assign (to interface {}) error {
725
783
assignedMaps := make (map [string ]bool )
784
+ assignedVars := make (map [string ]bool )
726
785
assignedProgs := make (map [string ]bool )
727
786
728
787
// Assign() only transfers already-loaded Maps and Programs. No extra
@@ -744,6 +803,13 @@ func (coll *Collection) Assign(to interface{}) error {
744
803
}
745
804
return nil , fmt .Errorf ("missing map %q" , name )
746
805
806
+ case reflect .TypeOf ((* Variable )(nil )):
807
+ if v := coll .Variables [name ]; v != nil {
808
+ assignedVars [name ] = true
809
+ return v , nil
810
+ }
811
+ return nil , fmt .Errorf ("missing variable %q" , name )
812
+
747
813
default :
748
814
return nil , fmt .Errorf ("unsupported type %s" , typ )
749
815
}
@@ -757,6 +823,9 @@ func (coll *Collection) Assign(to interface{}) error {
757
823
for p := range assignedProgs {
758
824
delete (coll .Programs , p )
759
825
}
826
+ for s := range assignedVars {
827
+ delete (coll .Variables , s )
828
+ }
760
829
for m := range assignedMaps {
761
830
delete (coll .Maps , m )
762
831
}
0 commit comments