github.com/cilium/cilium@v1.16.2/pkg/datapath/linux/devices.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package linux
     5  
     6  import (
     7  	"fmt"
     8  	"log/slog"
     9  	"net"
    10  	"strings"
    11  
    12  	"github.com/cilium/hive/cell"
    13  	"github.com/cilium/statedb"
    14  
    15  	"github.com/cilium/cilium/pkg/datapath/tables"
    16  	"github.com/cilium/cilium/pkg/hive"
    17  	"github.com/cilium/cilium/pkg/logging/logfields"
    18  	"github.com/cilium/cilium/pkg/node"
    19  	"github.com/cilium/cilium/pkg/option"
    20  )
    21  
    22  // DeviceManager is a temporary compatibility bridge to keep DeviceManager uses as is and reuse its tests
    23  // against DevicesController and the devices table.
    24  //
    25  // This will be refactored away in follow-up PRs that convert code over to the devices table.
    26  // The DirectRoutingDevice and IPv6MCastDevice would computed from the devices table as necessary.
    27  type DeviceManager struct {
    28  	params         devicesManagerParams
    29  	initialDevices []string
    30  	hive           *hive.Hive
    31  }
    32  
    33  func (dm *DeviceManager) Detect(k8sEnabled bool) ([]string, error) {
    34  	rxn := dm.params.DB.ReadTxn()
    35  	devs, _ := tables.SelectedDevices(dm.params.DeviceTable, rxn)
    36  	names := tables.DeviceNames(devs)
    37  	dm.initialDevices = names
    38  
    39  	// Look up the device that holds the node IP. Used as fallback for direct-routing
    40  	// and multicast devices.
    41  	var nodeDevice *tables.Device
    42  	if k8sEnabled {
    43  		nodeIP := node.GetK8sNodeIP()
    44  		for _, dev := range devs {
    45  			if dev.HasIP(nodeIP) {
    46  				nodeDevice = dev
    47  				break
    48  			}
    49  		}
    50  	}
    51  
    52  	if option.Config.DirectRoutingDeviceRequired() {
    53  		var filter deviceFilter
    54  		if option.Config.DirectRoutingDevice != "" {
    55  			filter = deviceFilter(strings.Split(option.Config.DirectRoutingDevice, ","))
    56  		}
    57  		option.Config.DirectRoutingDevice = ""
    58  		if filter.nonEmpty() {
    59  			// User has defined a direct-routing device. Try to find the first matching
    60  			// device.
    61  			for _, dev := range devs {
    62  				if filter.match(dev.Name) {
    63  					option.Config.DirectRoutingDevice = dev.Name
    64  					break
    65  				}
    66  			}
    67  		} else if len(devs) == 1 {
    68  			option.Config.DirectRoutingDevice = devs[0].Name
    69  		} else if nodeDevice != nil {
    70  			option.Config.DirectRoutingDevice = nodeDevice.Name
    71  		}
    72  		if option.Config.DirectRoutingDevice == "" {
    73  			return nil, fmt.Errorf("unable to determine direct routing device. Use --%s to specify it",
    74  				option.DirectRoutingDevice)
    75  		}
    76  		dm.params.Log.Info("Direct routing device detected",
    77  			logfields.DirectRoutingDevice, option.Config.DirectRoutingDevice,
    78  		)
    79  	}
    80  
    81  	if option.Config.EnableIPv6NDP && option.Config.IPv6MCastDevice == "" {
    82  		if nodeDevice != nil && nodeDevice.Flags&net.FlagMulticast != 0 {
    83  			option.Config.IPv6MCastDevice = nodeDevice.Name
    84  		} else {
    85  			return nil, fmt.Errorf("unable to determine Multicast device. Use --%s to specify it",
    86  				option.IPv6MCastDevice)
    87  		}
    88  	}
    89  
    90  	return names, nil
    91  }
    92  
    93  type devicesManagerParams struct {
    94  	cell.In
    95  
    96  	Log         *slog.Logger
    97  	DB          *statedb.DB
    98  	DeviceTable statedb.Table[*tables.Device]
    99  	RouteTable  statedb.Table[*tables.Route]
   100  }
   101  
   102  // newDeviceManager constructs a DeviceManager that implements the old DeviceManager API.
   103  // Dummy dependency to *devicesController to make sure devices table is populated.
   104  func newDeviceManager(p devicesManagerParams, _ *devicesController) *DeviceManager {
   105  	return &DeviceManager{params: p, hive: nil}
   106  }