@@ -3,12 +3,22 @@ package bpfprogram
33import (
44 "fmt"
55 "log"
6+ "os"
7+ "path/filepath"
68 "syscall"
79
810 blockservice "github.com/Azure/azure-container-networking/bpf-prog/block-iptables/pkg/blockservice"
11+ "github.com/cilium/ebpf"
912 "github.com/cilium/ebpf/link"
1013)
1114
15+ const (
16+ // BPFMapPinPath is the directory where BPF maps are pinned
17+ BPFMapPinPath = "/sys/fs/bpf/block-iptables"
18+ // EventCounterMapName is the name used for pinning the event counter map
19+ EventCounterMapName = "event_counter"
20+ )
21+
1222// Program implements the Manager interface for real BPF program operations.
1323type Program struct {
1424 objs * blockservice.BlockIptablesObjects
@@ -21,7 +31,44 @@ func NewProgram() Attacher {
2131 return & Program {}
2232}
2333
24- // getHostNetnsInode gets the network namespace inode of the current process (host namespace).
34+ // CreatePinPath ensures the BPF map pin directory exists.
35+ func (p * Program ) CreatePinPath () error {
36+ // Ensure the BPF map pin directory exists with correct permissions (drwxr-xr-x)
37+ if err := os .MkdirAll (BPFMapPinPath , 0o755 ); err != nil {
38+ return fmt .Errorf ("failed to create BPF map pin directory: %w" , err )
39+ }
40+ return nil
41+ }
42+
43+ // pinEventCounterMap pins the event counter map to the filesystem
44+ func (p * Program ) pinEventCounterMap () error {
45+ if p .objs == nil || p .objs .EventCounter == nil {
46+ return fmt .Errorf ("event counter map not loaded" )
47+ }
48+
49+ pinPath := filepath .Join (BPFMapPinPath , EventCounterMapName )
50+
51+ if err := p .objs .EventCounter .Pin (pinPath ); err != nil {
52+ return fmt .Errorf ("failed to pin event counter map to %s: %w" , pinPath , err )
53+ }
54+
55+ log .Printf ("Event counter map pinned to %s" , pinPath )
56+ return nil
57+ }
58+
59+ // unpinEventCounterMap unpins the event counter map from the filesystem
60+ func (p * Program ) unpinEventCounterMap () error {
61+ pinPath := filepath .Join (BPFMapPinPath , EventCounterMapName )
62+
63+ if err := os .Remove (pinPath ); err != nil && ! os .IsNotExist (err ) {
64+ log .Printf ("Warning: failed to remove pinned map %s: %v" , pinPath , err )
65+ } else {
66+ log .Printf ("Event counter map unpinned from %s" , pinPath )
67+ }
68+
69+ return nil
70+ }
71+
2572func getHostNetnsInode () (uint32 , error ) {
2673 var stat syscall.Stat_t
2774 err := syscall .Stat ("/proc/self/ns/net" , & stat )
@@ -49,6 +96,10 @@ func (p *Program) Attach() error {
4996 return fmt .Errorf ("failed to get host network namespace inode: %w" , err )
5097 }
5198
99+ if err := p .CreatePinPath (); err != nil {
100+ return fmt .Errorf ("failed to create BPF map pin directory: %w" , err )
101+ }
102+
52103 // Load BPF objects with the host namespace inode set
53104 spec , err := blockservice .LoadBlockIptables ()
54105 if err != nil {
@@ -65,11 +116,22 @@ func (p *Program) Attach() error {
65116
66117 // Load the objects
67118 objs := & blockservice.BlockIptablesObjects {}
68- if err := spec .LoadAndAssign (objs , nil ); err != nil {
119+ options := & ebpf.CollectionOptions {
120+ Maps : ebpf.MapOptions {
121+ PinPath : BPFMapPinPath ,
122+ LoadPinOptions : ebpf.LoadPinOptions {},
123+ },
124+ }
125+ if err := spec .LoadAndAssign (objs , options ); err != nil {
69126 return fmt .Errorf ("failed to load BPF objects: %w" , err )
70127 }
71128 p .objs = objs
72129
130+ // Pin the event counter map to filesystem
131+ if err := p .pinEventCounterMap (); err != nil {
132+ return fmt .Errorf ("failed to pin event counter map: %w" , err )
133+ }
134+
73135 // Attach LSM programs
74136 var links []link.Link
75137
@@ -117,6 +179,11 @@ func (p *Program) Detach() error {
117179
118180 log .Println ("Detaching BPF program..." )
119181
182+ // Unpin the event counter map from filesystem
183+ if err := p .unpinEventCounterMap (); err != nil {
184+ log .Printf ("Warning: failed to unpin event counter map: %v" , err )
185+ }
186+
120187 // Close all links
121188 for _ , l := range p .links {
122189 if err := l .Close (); err != nil {
0 commit comments