github.com/cilium/cilium@v1.16.2/pkg/maps/nat/cell.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package nat
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/cilium/cilium/pkg/option"
    11  	"github.com/cilium/cilium/pkg/promise"
    12  	"github.com/cilium/cilium/pkg/time"
    13  	"github.com/cilium/cilium/pkg/tuple"
    14  
    15  	"github.com/cilium/hive/cell"
    16  )
    17  
    18  // MapDisabled is the expected error will be if map was not created
    19  // due to configuration.
    20  var MapDisabled = fmt.Errorf("nat map is disabled")
    21  
    22  // Cell exposes global nat maps via Hive. These maps depend on
    23  // the final state of EnableNodePort, thus the maps are currently
    24  // provided as promises.
    25  // TODO: Once we have a way of finalizing this config prior to runtime
    26  // we'll want to provide these using bpf.MapOut[T] (GH: #32557)
    27  var Cell = cell.Module(
    28  	"nat-maps",
    29  	"NAT Maps",
    30  	cell.Provide(func(lc cell.Lifecycle, cfgPromise promise.Promise[*option.DaemonConfig]) (promise.Promise[NatMap4], promise.Promise[NatMap6]) {
    31  		var ipv4Nat, ipv6Nat *Map
    32  		res4, promise4 := promise.New[NatMap4]()
    33  		res6, promise6 := promise.New[NatMap6]()
    34  
    35  		lc.Append(cell.Hook{
    36  			OnStart: func(hc cell.HookContext) error {
    37  				ctx, cancel := context.WithTimeout(context.Background(), time.Second*60)
    38  				defer cancel()
    39  				cfg, err := cfgPromise.Await(ctx)
    40  				if err != nil {
    41  					return fmt.Errorf("failed to wait for config promise: %w", err)
    42  				}
    43  				if !cfg.EnableNodePort {
    44  					res4.Reject(fmt.Errorf("nat IPv4: %w", MapDisabled))
    45  					res6.Reject(fmt.Errorf("nat IPv6: %w", MapDisabled))
    46  					return nil
    47  				}
    48  
    49  				ipv4Nat, ipv6Nat = GlobalMaps(cfg.EnableIPv4,
    50  					cfg.EnableIPv6, true)
    51  
    52  				// Maps are still created before DaemonConfig promise is resolved in
    53  				// daemon.initMaps(...) under the same circumstances
    54  				// so we just open them here so they can be provided to hive.
    55  				//
    56  				// TODO: Refactor ctmap gc Enable() such that it can use the map descriptors from
    57  				// here so we can move all nat map creation logic into here.
    58  				// NOTE: This code runs concurrently with startDaemon(), so if any dependency to
    59  				// daemon having finished endpoint restore, for example, is added, we should
    60  				// await for an appropriate promise.
    61  				if cfg.EnableIPv4 {
    62  					if err := ipv4Nat.Open(); err != nil {
    63  						return fmt.Errorf("open IPv4 nat map: %w", err)
    64  					}
    65  					res4.Resolve(ipv4Nat)
    66  				} else {
    67  					res4.Reject(MapDisabled)
    68  				}
    69  				if cfg.EnableIPv6 {
    70  					if err := ipv6Nat.Open(); err != nil {
    71  						return fmt.Errorf("open IPv6 nat map: %w", err)
    72  					}
    73  					res6.Resolve(ipv6Nat)
    74  				} else {
    75  					res6.Reject(MapDisabled)
    76  				}
    77  				return nil
    78  			},
    79  			OnStop: func(hc cell.HookContext) error {
    80  				ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
    81  				defer cancel()
    82  				cfg, err := cfgPromise.Await(ctx)
    83  				if err != nil {
    84  					return err
    85  				}
    86  				if !cfg.EnableNodePort {
    87  					return nil
    88  				}
    89  
    90  				if ipv4Nat != nil {
    91  					if err := ipv4Nat.Map.Close(); err != nil {
    92  						return err
    93  					}
    94  				}
    95  				if ipv6Nat != nil {
    96  					if err := ipv6Nat.Map.Close(); err != nil {
    97  						return err
    98  					}
    99  				}
   100  				return nil
   101  			},
   102  		})
   103  
   104  		return promise4, promise6
   105  	}),
   106  )
   107  
   108  // NatMap4 describes ipv4 nat map behaviors, used for providing map
   109  // to hive.
   110  type NatMap4 interface {
   111  	NatMap
   112  	ApplyBatch4(func([]tuple.TupleKey4, []NatEntry4, int)) (count int, err error)
   113  }
   114  
   115  // NatMap6 describes ipv6 nat map behaviors, used for providing map
   116  // to hive.
   117  type NatMap6 interface {
   118  	NatMap
   119  	ApplyBatch6(func([]tuple.TupleKey6, []NatEntry6, int)) (count int, err error)
   120  }