github.com/cilium/cilium@v1.16.2/pkg/datapath/tables/device.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package tables 5 6 import ( 7 "bytes" 8 "fmt" 9 "net" 10 "net/netip" 11 "slices" 12 "strings" 13 14 "github.com/cilium/statedb" 15 "github.com/cilium/statedb/index" 16 ) 17 18 var ( 19 DeviceIDIndex = statedb.Index[*Device, int]{ 20 Name: "id", 21 FromObject: func(d *Device) index.KeySet { 22 return index.NewKeySet(index.Int(d.Index)) 23 }, 24 FromKey: index.Int, 25 Unique: true, 26 } 27 28 DeviceNameIndex = statedb.Index[*Device, string]{ 29 Name: "name", 30 FromObject: func(d *Device) index.KeySet { 31 return index.NewKeySet(index.String(d.Name)) 32 }, 33 FromKey: index.String, 34 } 35 36 DeviceSelectedIndex = statedb.Index[*Device, bool]{ 37 Name: "selected", 38 FromObject: func(d *Device) index.KeySet { 39 return index.NewKeySet(index.Bool(d.Selected)) 40 }, 41 FromKey: index.Bool, 42 } 43 ) 44 45 func NewDeviceTable() (statedb.RWTable[*Device], error) { 46 return statedb.NewTable( 47 "devices", 48 DeviceIDIndex, 49 DeviceNameIndex, 50 DeviceSelectedIndex, 51 ) 52 } 53 54 // HardwareAddr is the physical address for a network device. 55 // Defined here instead of using net.HardwareAddr for proper 56 // JSON marshalling. 57 type HardwareAddr []byte 58 59 func (a HardwareAddr) String() string { 60 return net.HardwareAddr([]byte(a)).String() 61 } 62 63 func (a HardwareAddr) MarshalJSON() ([]byte, error) { 64 return []byte("\"" + a.String() + "\""), nil 65 } 66 67 func (a *HardwareAddr) UnmarshalJSON(bs []byte) error { 68 bs = bytes.Trim(bs, "\"") 69 if len(bs) == 0 { 70 return nil 71 } 72 hw, err := net.ParseMAC(string(bs)) 73 if err != nil { 74 return err 75 } 76 *a = []byte(hw) 77 return nil 78 } 79 80 // Device is a local network device along with addresses associated with it. 81 // 82 // The devices that are selected are the external facing native devices that 83 // Cilium will use with features such as load-balancing, host firewall and routing. 84 // For the selection logic applied see 'pkg/datapath/linux/devices_controller.go'. 85 type Device struct { 86 Index int // positive integer that starts at one, zero is never used 87 MTU int // maximum transmission unit 88 Name string // e.g., "en0", "lo0", "eth0.100" 89 HardwareAddr HardwareAddr // IEEE MAC-48, EUI-48 and EUI-64 form 90 Flags net.Flags // e.g. net.FlagUp, net.eFlagLoopback, net.FlagMulticast 91 Addrs []DeviceAddress // Addresses assigned to the device 92 RawFlags uint32 // Raw interface flags 93 Type string // Device type, e.g. "veth" etc. 94 MasterIndex int // Index of the master device (e.g. bridge or bonding device) 95 96 Selected bool // True if this is an external facing device 97 NotSelectedReason string // Reason why this device was not selected 98 } 99 100 func (d *Device) DeepCopy() *Device { 101 copy := *d 102 copy.Addrs = slices.Clone(d.Addrs) 103 return © 104 } 105 106 func (d *Device) HasIP(ip net.IP) bool { 107 for _, addr := range d.Addrs { 108 if addr.AsIP().Equal(ip) { 109 return true 110 } 111 } 112 return false 113 } 114 115 func (*Device) TableHeader() []string { 116 return []string{ 117 "Name", 118 "Index", 119 "Selected", 120 "Type", 121 "MTU", 122 "HWAddr", 123 "Flags", 124 "Addresses", 125 } 126 } 127 128 func (d *Device) TableRow() []string { 129 addrs := []string{} 130 for _, addr := range d.Addrs { 131 addrs = append(addrs, addr.Addr.String()) 132 } 133 return []string{ 134 d.Name, 135 fmt.Sprintf("%d", d.Index), 136 fmt.Sprintf("%v", d.Selected), 137 d.Type, 138 fmt.Sprintf("%d", d.MTU), 139 d.HardwareAddr.String(), 140 d.Flags.String(), 141 strings.Join(addrs, ", "), 142 } 143 } 144 145 type DeviceAddress struct { 146 Addr netip.Addr 147 Secondary bool 148 Scope RouteScope // Address scope, e.g. RT_SCOPE_LINK, RT_SCOPE_HOST etc. 149 } 150 151 func (d *DeviceAddress) AsIP() net.IP { 152 return d.Addr.AsSlice() 153 } 154 155 func (d *DeviceAddress) String() string { 156 return fmt.Sprintf("%s (secondary=%v, scope=%d)", d.Addr, d.Secondary, d.Scope) 157 } 158 159 // SelectedDevices returns the external facing network devices to use for 160 // load-balancing, host firewall and routing. 161 // 162 // The invalidated channel is closed when devices have changed and 163 // should be requeried with a new transaction. 164 func SelectedDevices(tbl statedb.Table[*Device], txn statedb.ReadTxn) ([]*Device, <-chan struct{}) { 165 iter, invalidated := tbl.ListWatch(txn, DeviceSelectedIndex.Query(true)) 166 return statedb.Collect(iter), invalidated 167 } 168 169 // DeviceNames extracts the device names from a slice of devices. 170 func DeviceNames(devs []*Device) (names []string) { 171 names = make([]string, len(devs)) 172 for i := range devs { 173 names[i] = devs[i].Name 174 } 175 return 176 }