Skip to content

Commit 4287bf0

Browse files
mhofstettertklauser
authored andcommitted
nat retries map: init in hive cell
This commit moves the logic to create the NAT retries bpf maps at Agent startup from the legacy daemon init logic to a hive lifecycle start hook of the nat map cell. The `Loader` automatically depends on all BPF maps (via `bpf.MapOut`) - this way, the map gets created before the first use of the `Loader`. Signed-off-by: Marco Hofstetter <marco.hofstetter@isovalent.com>
1 parent e9584ec commit 4287bf0

3 files changed

Lines changed: 91 additions & 50 deletions

File tree

daemon/cmd/datapath.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,6 @@ func initMaps(params daemonParams) error {
110110
}
111111
}
112112

113-
if params.KPRConfig.KubeProxyReplacement || option.Config.EnableBPFMasquerade {
114-
if err := nat.CreateRetriesMaps(option.Config.EnableIPv4,
115-
option.Config.EnableIPv6); err != nil {
116-
return fmt.Errorf("initializing NAT retries map: %w", err)
117-
}
118-
}
119-
120113
if !option.Config.RestoreState {
121114
// If we are not restoring state, all endpoints can be
122115
// deleted. Entries will be re-populated.

pkg/maps/nat/cell.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@ import (
77
"context"
88
"fmt"
99

10+
"github.com/cilium/hive/cell"
11+
12+
"github.com/cilium/cilium/pkg/bpf"
1013
"github.com/cilium/cilium/pkg/kpr"
1114
"github.com/cilium/cilium/pkg/metrics"
1215
"github.com/cilium/cilium/pkg/option"
1316
"github.com/cilium/cilium/pkg/promise"
1417
"github.com/cilium/cilium/pkg/time"
1518
"github.com/cilium/cilium/pkg/tuple"
16-
17-
"github.com/cilium/hive/cell"
1819
)
1920

2021
// ErrMapDisabled is the expected error will be if map was not created
@@ -106,6 +107,7 @@ var Cell = cell.Module(
106107

107108
return promise4, promise6
108109
}),
110+
cell.Provide(provideNATRetriesMap),
109111
)
110112

111113
// NatMap4 describes ipv4 nat map behaviors, used for providing map
@@ -121,3 +123,30 @@ type NatMap6 interface {
121123
NatMap
122124
DumpBatch6(func(*tuple.TupleKey6, *NatEntry6)) (count int, err error)
123125
}
126+
127+
// NATRetriesMap is a marker interface for the NAT retries map.
128+
// It doesn't provide any functionality to the Cilium Agent because
129+
// the bpf map is only created by the Cilium Agent for the datapath.
130+
// It's still provided to be picked up as dependency by the Loader
131+
// and initialized at startup.
132+
type NATRetriesMap any
133+
134+
func provideNATRetriesMap(lifecycle cell.Lifecycle, daemonConfig *option.DaemonConfig, kprConfig kpr.KPRConfig) bpf.MapOut[NATRetriesMap] {
135+
if !kprConfig.KubeProxyReplacement && !option.Config.EnableBPFMasquerade {
136+
return bpf.NewMapOut(NATRetriesMap(nil))
137+
}
138+
139+
natRetriesMap := newNATRetriesMap(daemonConfig.IPv4Enabled(), daemonConfig.IPv6Enabled())
140+
141+
lifecycle.Append(cell.Hook{
142+
OnStart: func(context cell.HookContext) error {
143+
return natRetriesMap.init()
144+
},
145+
OnStop: func(context cell.HookContext) error {
146+
// no need to close because the maps are only created for datapath (Create)
147+
return nil
148+
},
149+
})
150+
151+
return bpf.NewMapOut(NATRetriesMap(natRetriesMap))
152+
}

pkg/maps/nat/nat.go

Lines changed: 60 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,10 @@ const (
2525
// MapNameSnat6Global represents global IPv6 NAT table.
2626
MapNameSnat6Global = "cilium_snat_v6_external"
2727

28-
// MinPortSnatDefault represents default min port from range.
29-
MinPortSnatDefault = 1024
30-
// MaxPortSnatDefault represents default max port from range.
31-
MaxPortSnatDefault = 65535
32-
33-
// MapNameSnat4AllocRetries represents the histogram of IPv4 NAT port allocation retries.
34-
MapNameSnat4AllocRetries = "cilium_snat_v4_alloc_retries"
35-
// MapNameSnat6AllocRetries represents the histogram of IPv6 NAT port allocation retries.
36-
MapNameSnat6AllocRetries = "cilium_snat_v6_alloc_retries"
28+
// mapNameSnat4AllocRetries represents the histogram of IPv4 NAT port allocation retries.
29+
mapNameSnat4AllocRetries = "cilium_snat_v4_alloc_retries"
30+
// mapNameSnat6AllocRetries represents the histogram of IPv6 NAT port allocation retries.
31+
mapNameSnat6AllocRetries = "cilium_snat_v6_alloc_retries"
3732

3833
// SnatCollisionRetries represents the maximum number of port allocation retries.
3934
SnatCollisionRetries = 32
@@ -117,7 +112,8 @@ type RetriesKey struct {
117112
Key uint32
118113
}
119114

120-
func (k *RetriesKey) String() string { return fmt.Sprintf("%d", k.Key) }
115+
func (k *RetriesKey) String() string { return fmt.Sprintf("%d", k.Key) }
116+
121117
func (k *RetriesKey) New() bpf.MapKey { return &RetriesKey{} }
122118

123119
type RetriesValue struct {
@@ -126,26 +122,17 @@ type RetriesValue struct {
126122

127123
type RetriesValues []RetriesValue
128124

129-
func (k *RetriesValue) String() string { return fmt.Sprintf("%d", k.Value) }
125+
func (k *RetriesValue) String() string { return fmt.Sprintf("%d", k.Value) }
126+
130127
func (k *RetriesValue) New() bpf.MapValue { return &RetriesValue{} }
131-
func (k *RetriesValue) NewSlice() any { return &RetriesValues{} }
128+
129+
func (k *RetriesValue) NewSlice() any { return &RetriesValues{} }
132130

133131
type RetriesMapRecord struct {
134132
Key *RetriesKey
135133
Value *RetriesValue
136134
}
137135

138-
func NewRetriesMap(name string) *bpf.Map {
139-
return bpf.NewMap(
140-
name,
141-
ebpf.PerCPUArray,
142-
&RetriesKey{},
143-
&RetriesValue{},
144-
SnatCollisionRetries+1,
145-
0,
146-
)
147-
}
148-
149136
// DumpBatch4 uses batch iteration to walk the map and applies fn for each batch of entries.
150137
func (m *Map) DumpBatch4(fn func(*tuple.TupleKey4, *NatEntry4)) (count int, err error) {
151138
if m.family != IPv4 {
@@ -425,32 +412,64 @@ func maxEntries() int {
425412
return option.LimitTableMax
426413
}
427414

415+
type natRetriesMap struct {
416+
bpfMapV4 *bpf.Map
417+
bpfMapV6 *bpf.Map
418+
}
419+
420+
func newNATRetriesMap(ipv4Enabled bool, ipv6Enabled bool) *natRetriesMap {
421+
m := &natRetriesMap{}
422+
423+
if ipv4Enabled {
424+
m.bpfMapV4 = newRetriesMap(mapNameSnat4AllocRetries)
425+
}
426+
427+
if ipv6Enabled {
428+
m.bpfMapV6 = newRetriesMap(mapNameSnat6AllocRetries)
429+
}
430+
431+
return m
432+
}
433+
434+
func (m *natRetriesMap) init() error {
435+
if m.bpfMapV4 != nil {
436+
if err := m.bpfMapV4.Create(); err != nil {
437+
return fmt.Errorf("failed to create nat retries v4 bpf map: %w", err)
438+
}
439+
}
440+
441+
if m.bpfMapV6 != nil {
442+
if err := m.bpfMapV6.Create(); err != nil {
443+
return fmt.Errorf("failed to create nat retries v6 bpf map: %w", err)
444+
}
445+
}
446+
447+
return nil
448+
}
449+
450+
func newRetriesMap(name string) *bpf.Map {
451+
return bpf.NewMap(
452+
name,
453+
ebpf.PerCPUArray,
454+
&RetriesKey{},
455+
&RetriesValue{},
456+
SnatCollisionRetries+1,
457+
0,
458+
)
459+
}
460+
428461
// RetriesMaps returns the maps that contain the histograms of the number of retries.
462+
// This should only be used from components which aren't capable of using hive - mainly the cilium-dbg.
463+
// It needs to initialized beforehand via the Cilium Agent.
429464
func RetriesMaps(ipv4, ipv6, natRequired bool) (ipv4RetriesMap, ipv6RetriesMap RetriesMap) {
430465
if !natRequired {
431466
return
432467
}
433468
if ipv4 {
434-
ipv4RetriesMap = NewRetriesMap(MapNameSnat4AllocRetries)
469+
ipv4RetriesMap = newRetriesMap(mapNameSnat4AllocRetries)
435470
}
436471
if ipv6 {
437-
ipv6RetriesMap = NewRetriesMap(MapNameSnat6AllocRetries)
472+
ipv6RetriesMap = newRetriesMap(mapNameSnat6AllocRetries)
438473
}
439474
return
440475
}
441-
442-
func CreateRetriesMaps(ipv4, ipv6 bool) error {
443-
if ipv4 {
444-
ipv4Map := NewRetriesMap(MapNameSnat4AllocRetries)
445-
if err := ipv4Map.OpenOrCreate(); err != nil {
446-
return err
447-
}
448-
}
449-
if ipv6 {
450-
ipv6Map := NewRetriesMap(MapNameSnat6AllocRetries)
451-
if err := ipv6Map.OpenOrCreate(); err != nil {
452-
return err
453-
}
454-
}
455-
return nil
456-
}

0 commit comments

Comments
 (0)