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 }