go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ifplugin/descriptor/interface.go (about) 1 // Copyright (c) 2018 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package descriptor 16 17 import ( 18 context2 "context" 19 "fmt" 20 "hash/fnv" 21 "net" 22 "strings" 23 24 "github.com/pkg/errors" 25 "go.ligato.io/cn-infra/v2/idxmap" 26 "go.ligato.io/cn-infra/v2/logging" 27 "google.golang.org/protobuf/proto" 28 empty "google.golang.org/protobuf/types/known/emptypb" 29 30 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 31 linux_ifdescriptor "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin/descriptor" 32 linux_ifaceidx "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin/ifaceidx" 33 "go.ligato.io/vpp-agent/v3/plugins/linux/nsplugin" 34 "go.ligato.io/vpp-agent/v3/plugins/netalloc" 35 netalloc_descr "go.ligato.io/vpp-agent/v3/plugins/netalloc/descriptor" 36 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/descriptor/adapter" 37 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx" 38 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls" 39 linux_intf "go.ligato.io/vpp-agent/v3/proto/ligato/linux/interfaces" 40 linux_ns "go.ligato.io/vpp-agent/v3/proto/ligato/linux/namespace" 41 netalloc_api "go.ligato.io/vpp-agent/v3/proto/ligato/netalloc" 42 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 43 l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" 44 ) 45 46 const ( 47 // InterfaceDescriptorName is the name of the descriptor for VPP interfaces. 48 InterfaceDescriptorName = "vpp-interface" 49 50 // dependency labels 51 afPacketHostInterfaceDep = "afpacket-host-interface-exists" 52 vxlanMulticastDep = "vxlan-multicast-interface-exists" 53 vxlanVrfTableDep = "vrf-table-for-vxlan-exists" 54 vxlanGpeVrfTableDep = "vrf-table-for-vxlan-gpe-exists" 55 gtpuMulticastDep = "gtpu-multicast-interface-exists" 56 gtpuVrfTableDep = "vrf-table-for-gtpu-exists" 57 ipipVrfTableDep = "vrf-table-for-ipip-exists" 58 microserviceDep = "microservice-available" 59 parentInterfaceDep = "parent-interface-exists" 60 rdmaHostInterfaceDep = "rdma-host-interface-exists" 61 62 // how many characters a logical interface name is allowed to have 63 // - determined by much fits into the VPP interface tag (64 null-terminated character string) 64 logicalNameLengthLimit = 63 65 66 // suffix attached to logical names of dumped TAP interfaces with Linux side 67 // not found by Retrieve of Linux-ifplugin 68 tapMissingLinuxSideSuffix = "-MISSING_LINUX_SIDE" 69 70 // suffix attached to logical names of dumped AF-PACKET interfaces connected 71 // to missing Linux interfaces 72 afPacketMissingAttachedIfSuffix = "-MISSING_ATTACHED_INTERFACE" 73 74 // default memif attributes 75 defaultMemifNumOfQueues uint32 = 1 76 defaultMemifBufferSize uint32 = 2048 77 defaultMemifRingSize uint32 = 1024 78 79 // Length of wireguard private-key in base64. It should be equal 32 in binary 80 wireguardKeyLength = 44 81 82 // default RDMA attributes 83 defaultRdmaQueueNum = 1 84 defaultRdmaQueueSize = 1024 85 ) 86 87 // A list of non-retriable errors: 88 var ( 89 // ErrUnsupportedVPPInterfaceType is returned for VPP interfaces of unknown type. 90 ErrUnsupportedVPPInterfaceType = errors.New("unsupported VPP interface type") 91 92 // ErrInterfaceWithoutName is returned when VPP interface configuration has undefined 93 // Name attribute. 94 ErrInterfaceWithoutName = errors.New("VPP interface defined without logical name") 95 96 // ErrInterfaceNameTooLong is returned when VPP interface logical name exceeds the length limit. 97 ErrInterfaceNameTooLong = errors.New("VPP interface logical name exceeds the length limit (63 characters)") 98 99 // ErrInterfaceWithoutType is returned when VPP interface configuration has undefined 100 // Type attribute. 101 ErrInterfaceWithoutType = errors.New("VPP interface defined without type") 102 103 // ErrUnnumberedWithIP is returned when configuration of a VPP unnumbered interface 104 // includes an IP address. 105 ErrUnnumberedWithIP = errors.New("VPP unnumbered interface was defined with IP address") 106 107 // ErrAfPacketWithoutTarget is returned when AF-Packet configuration is missing reference to the target linux interface. 108 ErrAfPacketWithoutTarget = errors.New( 109 "VPP AF-Packet interface was defined without reference to the target linux interface") 110 111 // ErrInterfaceLinkMismatch is returned when interface type does not match the link configuration. 112 ErrInterfaceLinkMismatch = errors.New("VPP interface type and link configuration do not match") 113 114 // ErrRedefinedRxPlacement is returned when Rx placement has multiple definitions for the same queue. 115 ErrRedefinedRxPlacement = errors.New("redefined RX Placement") 116 117 // ErrSubInterfaceWithoutParent is returned when interface of type sub-interface is defined without parent. 118 ErrSubInterfaceWithoutParent = errors.Errorf("subinterface with no parent interface defined") 119 120 // ErrDPDKInterfaceMissing is returned when the expected DPDK interface does not exist on the VPP. 121 ErrDPDKInterfaceMissing = errors.Errorf("DPDK interface with given name does not exists") 122 123 // ErrBondInterfaceIDExists is returned when the bond interface uses existing ID value 124 ErrBondInterfaceIDExists = errors.Errorf("Bond interface ID already exists") 125 126 // ErrGreBadTunnelType is returned when tunnel type for GRE was not set or set to UNKNOWN 127 ErrGreBadTunnelType = errors.Errorf("bad tunnel type for GRE") 128 129 // ErrGreSrcAddrMissing is returned when source address was not set or set to an empty string. 130 ErrGreSrcAddrMissing = errors.Errorf("missing source address for GRE tunnel") 131 132 // ErrGreDstAddrMissing is returned when destination address was not set or set to an empty string. 133 ErrGreDstAddrMissing = errors.Errorf("missing destination address for GRE tunnel") 134 135 // ErrVxLanGpeBadProtocol is returned when protocol for VxLAN-GPE was not set or set to UNKNOWN. 136 ErrVxLanGpeBadProtocol = errors.Errorf("bad protocol for VxLAN-GPE") 137 138 // ErrVxLanGpeNonZeroDecapVrfID is returned when DecapVrfId was not zero for protocols other than IP4 or IP6. 139 ErrVxLanGpeNonZeroDecapVrfID = errors.Errorf("DecapVrfId must be zero for protocols other than IP4 or IP6") 140 141 // ErrVxLanSrcAddrMissing is returned when source address was not set or set to an empty string. 142 ErrVxLanSrcAddrMissing = errors.Errorf("missing source address for VxLAN tunnel") 143 144 // ErrVxLanDstAddrMissing is returned when destination address was not set or set to an empty string. 145 ErrVxLanDstAddrMissing = errors.Errorf("missing destination address for VxLAN tunnel") 146 147 // ErrVxLanDstAddrBad is returned when destination address was not set to valid IP address. 148 ErrVxLanDstAddrBad = errors.Errorf("bad destination address for VxLAN tunnel") 149 150 // ErrVxLanMulticastIntfMissing is returned when interface for multicast was not specified. 151 ErrVxLanMulticastIntfMissing = errors.Errorf("missing multicast interface name for VxLAN tunnel") 152 153 // ErrGtpuSrcAddrMissing is returned when source address was not set or set to an empty string. 154 ErrGtpuSrcAddrMissing = errors.Errorf("missing source address for GTPU tunnel") 155 156 // ErrGtpuDstAddrMissing is returned when destination address was not set or set to an empty string. 157 ErrGtpuDstAddrMissing = errors.Errorf("missing destination address for GTPU tunnel") 158 159 // ErrGtpuSrcAddrBad is returned when source address was not set to valid IP address. 160 ErrGtpuSrcAddrBad = errors.Errorf("bad source address for GTPU tunnel") 161 162 // ErrGtpuDstAddrBad is returned when destination address was not set to valid IP address. 163 ErrGtpuDstAddrBad = errors.Errorf("bad destination address for GTPU tunnel") 164 165 // ErrIpipSrcAddrMissing is returned when source address was not set or set to an empty string. 166 ErrIpipSrcAddrMissing = errors.Errorf("missing source address for IPIP tunnel") 167 168 // ErrIpipDstAddrMissing is returned when destination address was not set or set to an empty string. 169 ErrIpipDstAddrMissing = errors.Errorf("missing destination address for IPIP tunnel") 170 171 // ErrIpipSrcAddrBad is returned when source address was not set to valid IP address. 172 ErrIpipSrcAddrBad = errors.Errorf("bad source address for IPIP tunnel") 173 174 // ErrIpipDstAddrBad is returned when destination address was not set to valid IP address. 175 ErrIpipDstAddrBad = errors.Errorf("bad destination address for IPIP tunnel") 176 177 // ErrWgKeyLen is returned when private-key length has wrong size. 178 ErrWgKeyLen = errors.New("invalid wireguard private-key length") 179 180 // ErrWgSrcAddrMissing is returned when source address was not set or set to an empty string. 181 ErrWgSrcAddrMissing = errors.Errorf("missing source address for wireguard tunnel") 182 183 // ErrWgSrcAddrBad is returned when source address was not set to valid IP address. 184 ErrWgSrcAddrBad = errors.Errorf("bad source address for wireguard tunnel") 185 186 // ErrWgPort is returned when udp-port exceeds max value. 187 ErrWgPort = errors.New("invalid wireguard port") 188 189 // ErrRdmaHostInterfaceMissing is returned when host_if_name is not configured for RDMA link. 190 ErrRdmaHostInterfaceMissing = errors.Errorf("missing the host interface name for RDMA") 191 192 // ErrRdmaInvalidQueueSize is returned when configured Rx or Tx queue size for RDMA driver is not power of 2. 193 ErrRdmaInvalidQueueSize = errors.Errorf("RDMA Rx/Tx queue size is not power of 2") 194 195 // ErrRdmaQueueSizeTooLarge is returned when configured Rx or Tx queue size for RDMA driver is too large. 196 ErrRdmaQueueSizeTooLarge = errors.Errorf("RDMA Rx/Tx queue size is too large (more than 16bits)") 197 198 // ErrRdmaQueueNumTooLarge is returned when the number of configured Rx/Tx queues for RDMA driver exceeds the limit. 199 ErrRdmaQueueNumTooLarge = errors.Errorf("Number of RDMA queues is too large (more than 16bits)") 200 ) 201 202 // InterfaceDescriptor teaches KVScheduler how to configure VPP interfaces. 203 type InterfaceDescriptor struct { 204 // config 205 defaultMtu uint32 206 207 // dependencies 208 log logging.Logger 209 ifHandler vppcalls.InterfaceVppAPI 210 addrAlloc netalloc.AddressAllocator 211 212 // optional dependencies, provide if AFPacket and/or TAP+TAP_TO_VPP interfaces are used 213 linuxIfPlugin LinuxPluginAPI 214 linuxIfHandler NetlinkAPI 215 nsPlugin nsplugin.API 216 217 // runtime 218 intfIndex ifaceidx.IfaceMetadataIndex 219 memifSocketToID map[string]uint32 // memif socket filename to ID map (all known sockets) 220 defaultMemifSocketPath string 221 bondIDs map[uint32]string // bond ID to name (ID != sw_if_idx) 222 ethernetIfs map[string]uint32 // name-to-index map of ethernet interfaces (entry is not 223 // removed even if interface is un-configured) 224 } 225 226 // LinuxPluginAPI is defined here to avoid import cycles. 227 type LinuxPluginAPI interface { 228 // GetInterfaceIndex gives read-only access to map with metadata of all configured 229 // linux interfaces. 230 GetInterfaceIndex() linux_ifaceidx.LinuxIfMetadataIndex 231 } 232 233 // NetlinkAPI here lists only those Netlink methods that are actually used by InterfaceDescriptor. 234 type NetlinkAPI interface { 235 // InterfaceExists verifies interface existence 236 InterfaceExists(ifName string) (bool, error) 237 } 238 239 // NewInterfaceDescriptor creates a new instance of the Interface descriptor. 240 func NewInterfaceDescriptor( 241 ifHandler vppcalls.InterfaceVppAPI, 242 addrAlloc netalloc.AddressAllocator, 243 defaultMtu uint32, 244 linuxIfHandler NetlinkAPI, 245 linuxIfPlugin LinuxPluginAPI, 246 nsPlugin nsplugin.API, 247 log logging.PluginLogger, 248 ) (*kvs.KVDescriptor, *InterfaceDescriptor) { 249 ctx := &InterfaceDescriptor{ 250 ifHandler: ifHandler, 251 addrAlloc: addrAlloc, 252 defaultMtu: defaultMtu, 253 linuxIfPlugin: linuxIfPlugin, 254 linuxIfHandler: linuxIfHandler, 255 nsPlugin: nsPlugin, 256 log: log.NewLogger("if-descriptor"), 257 memifSocketToID: make(map[string]uint32), 258 ethernetIfs: make(map[string]uint32), 259 bondIDs: make(map[uint32]string), 260 } 261 typedDescr := &adapter.InterfaceDescriptor{ 262 Name: InterfaceDescriptorName, 263 NBKeyPrefix: interfaces.ModelInterface.KeyPrefix(), 264 ValueTypeName: interfaces.ModelInterface.ProtoName(), 265 KeySelector: interfaces.ModelInterface.IsKeyValid, 266 KeyLabel: interfaces.ModelInterface.StripKeyPrefix, 267 ValueComparator: ctx.EquivalentInterfaces, 268 WithMetadata: true, 269 MetadataMapFactory: ctx.MetadataFactory, 270 Validate: ctx.Validate, 271 Create: ctx.Create, 272 Delete: ctx.Delete, 273 Update: ctx.Update, 274 UpdateWithRecreate: ctx.UpdateWithRecreate, 275 Retrieve: ctx.Retrieve, 276 Dependencies: ctx.Dependencies, 277 DerivedValues: ctx.DerivedValues, 278 RetrieveDependencies: []string{ 279 // refresh the pool of allocated IP addresses first 280 netalloc_descr.IPAllocDescriptorName, 281 // If Linux-IfPlugin is loaded, dump it first. 282 linux_ifdescriptor.InterfaceDescriptorName, 283 }, 284 } 285 descr := adapter.NewInterfaceDescriptor(typedDescr) 286 return descr, ctx 287 } 288 289 // SetInterfaceIndex should be used to provide interface index immediately after 290 // the descriptor registration. 291 func (d *InterfaceDescriptor) SetInterfaceIndex(intfIndex ifaceidx.IfaceMetadataIndex) { 292 d.intfIndex = intfIndex 293 } 294 295 // EquivalentInterfaces is case-insensitive comparison function for 296 // interfaces.Interface, also ignoring the order of assigned IP addresses. 297 func (d *InterfaceDescriptor) EquivalentInterfaces(key string, oldIntf, newIntf *interfaces.Interface) bool { 298 // attributes compared as usually: 299 if oldIntf.Name != newIntf.Name || 300 oldIntf.Type != newIntf.Type || 301 oldIntf.Enabled != newIntf.Enabled || 302 oldIntf.SetDhcpClient != newIntf.SetDhcpClient { 303 return false 304 } 305 if !proto.Equal(oldIntf.Unnumbered, newIntf.Unnumbered) { 306 return false 307 } 308 if !proto.Equal(oldIntf.Ip6Nd, newIntf.Ip6Nd) { 309 return false 310 } 311 312 // type-specific (defaults considered) 313 if !d.equivalentTypeSpecificConfig(oldIntf, newIntf) { 314 return false 315 } 316 317 if newIntf.Unnumbered == nil { // unnumbered inherits VRF from numbered interface 318 if oldIntf.Vrf != newIntf.Vrf { 319 return false 320 } 321 } 322 323 // handle default/unspecified MTU (except VxLAN and IPSec tunnel) 324 if newIntf.Type != interfaces.Interface_VXLAN_TUNNEL && newIntf.Type != interfaces.Interface_IPSEC_TUNNEL { 325 if d.getInterfaceMTU(newIntf) != 0 && d.getInterfaceMTU(oldIntf) != d.getInterfaceMTU(newIntf) { 326 return false 327 } 328 } 329 330 // compare MAC addresses case-insensitively (also handle unspecified MAC address) 331 if newIntf.PhysAddress != "" && !strings.EqualFold(oldIntf.PhysAddress, newIntf.PhysAddress) { 332 return false 333 } 334 335 if !equalStringSets(oldIntf.IpAddresses, newIntf.IpAddresses) { 336 // call Update just to update IP addresses in the metadata 337 return false 338 } 339 340 return true 341 } 342 343 // equivalentTypeSpecificConfig compares type-specific sections of two interface configurations. 344 func (d *InterfaceDescriptor) equivalentTypeSpecificConfig(oldIntf, newIntf *interfaces.Interface) bool { 345 switch oldIntf.Type { 346 case interfaces.Interface_TAP: 347 if !proto.Equal(getTapConfig(oldIntf), getTapConfig(newIntf)) { 348 return false 349 } 350 case interfaces.Interface_VXLAN_TUNNEL: 351 if !proto.Equal(oldIntf.GetVxlan(), newIntf.GetVxlan()) { 352 return false 353 } 354 case interfaces.Interface_AF_PACKET: 355 //nolint:staticcheck 356 if oldIntf.GetAfpacket().GetHostIfName() != newIntf.GetAfpacket().GetHostIfName() || 357 oldIntf.GetAfpacket().GetLinuxInterface() != newIntf.GetAfpacket().GetLinuxInterface() { 358 return false 359 } 360 case interfaces.Interface_MEMIF: 361 if !d.equivalentMemifs(oldIntf.GetMemif(), newIntf.GetMemif()) { 362 return false 363 } 364 case interfaces.Interface_IPSEC_TUNNEL: 365 if !d.equivalentIPSecTunnels(oldIntf.GetIpsec(), newIntf.GetIpsec()) { 366 return false 367 } 368 case interfaces.Interface_SUB_INTERFACE: 369 if !proto.Equal(oldIntf.GetSub(), newIntf.GetSub()) { 370 return false 371 } 372 case interfaces.Interface_VMXNET3_INTERFACE: 373 if !d.equivalentVmxNet3(oldIntf.GetVmxNet3(), newIntf.GetVmxNet3()) { 374 return false 375 } 376 case interfaces.Interface_BOND_INTERFACE: 377 if !d.equivalentBond(oldIntf.GetBond(), newIntf.GetBond()) { 378 return false 379 } 380 case interfaces.Interface_GRE_TUNNEL: 381 if !proto.Equal(oldIntf.GetGre(), newIntf.GetGre()) { 382 return false 383 } 384 case interfaces.Interface_GTPU_TUNNEL: 385 if !proto.Equal(oldIntf.GetGtpu(), newIntf.GetGtpu()) { 386 return false 387 } 388 case interfaces.Interface_IPIP_TUNNEL: 389 if !proto.Equal(oldIntf.GetIpip(), newIntf.GetIpip()) { 390 return false 391 } 392 case interfaces.Interface_WIREGUARD_TUNNEL: 393 if !proto.Equal(oldIntf.GetWireguard(), newIntf.GetWireguard()) { 394 return false 395 } 396 case interfaces.Interface_RDMA: 397 if !d.equivalentRdma(oldIntf.GetRdma(), newIntf.GetRdma()) { 398 return false 399 } 400 } 401 return true 402 } 403 404 // equivalentMemifs compares two memifs for equivalence. 405 func (d *InterfaceDescriptor) equivalentMemifs(oldMemif, newMemif *interfaces.MemifLink) bool { 406 if oldMemif.GetMode() != newMemif.GetMode() || 407 oldMemif.GetMaster() != newMemif.GetMaster() || 408 oldMemif.GetId() != newMemif.GetId() || 409 oldMemif.GetSecret() != newMemif.GetSecret() { 410 return false 411 } 412 // default values considered: 413 if d.getMemifSocketFilename(oldMemif) != d.getMemifSocketFilename(newMemif) || 414 d.getMemifBufferSize(oldMemif) != d.getMemifBufferSize(newMemif) || 415 d.getMemifRingSize(oldMemif) != d.getMemifRingSize(newMemif) || 416 d.getMemifNumOfRxQueues(oldMemif) != d.getMemifNumOfRxQueues(newMemif) || 417 d.getMemifNumOfTxQueues(oldMemif) != d.getMemifNumOfTxQueues(newMemif) { 418 return false 419 } 420 return true 421 } 422 423 // equivalentIPSecTunnels compares two IPSec tunnels for equivalence. 424 func (d *InterfaceDescriptor) equivalentIPSecTunnels(oldTun, newTun *interfaces.IPSecLink) bool { 425 return oldTun.Esn == newTun.Esn && 426 oldTun.AntiReplay == newTun.AntiReplay && 427 oldTun.LocalSpi == newTun.LocalSpi && 428 oldTun.RemoteSpi == newTun.RemoteSpi && 429 oldTun.CryptoAlg == newTun.CryptoAlg && 430 oldTun.LocalCryptoKey == newTun.LocalCryptoKey && 431 oldTun.RemoteCryptoKey == newTun.RemoteCryptoKey && 432 oldTun.IntegAlg == newTun.IntegAlg && 433 oldTun.LocalIntegKey == newTun.LocalIntegKey && 434 oldTun.RemoteIntegKey == newTun.RemoteIntegKey && 435 oldTun.EnableUdpEncap == newTun.EnableUdpEncap 436 } 437 438 // equivalentVmxNets compares two vmxnet3 interfaces for equivalence. 439 func (d *InterfaceDescriptor) equivalentVmxNet3(oldVmxNet3, newVmxNet3 *interfaces.VmxNet3Link) bool { 440 return oldVmxNet3.RxqSize == newVmxNet3.RxqSize && 441 oldVmxNet3.TxqSize == newVmxNet3.TxqSize 442 } 443 444 // equivalentBond compares two bond interfaces for equivalence. 445 func (d *InterfaceDescriptor) equivalentBond(oldBond, newBond *interfaces.BondLink) bool { 446 if len(oldBond.BondedInterfaces) != len(newBond.BondedInterfaces) { 447 return false 448 } 449 for _, oldBondSlave := range oldBond.BondedInterfaces { 450 var found bool 451 for _, newBondSlave := range newBond.BondedInterfaces { 452 if oldBondSlave.Name == newBondSlave.Name && 453 oldBondSlave.IsPassive == newBondSlave.IsPassive && 454 oldBondSlave.IsLongTimeout == newBondSlave.IsLongTimeout { 455 found = true 456 } 457 } 458 if !found { 459 return false 460 } 461 } 462 463 return oldBond.Id == newBond.Id && 464 oldBond.Mode == newBond.Mode && 465 oldBond.Lb == newBond.Lb 466 } 467 468 // equivalentRdma compares two RDMA interfaces for equivalence. 469 func (d *InterfaceDescriptor) equivalentRdma(oldRdma, newRdma *interfaces.RDMALink) bool { 470 return oldRdma.GetHostIfName() == newRdma.GetHostIfName() && 471 oldRdma.GetMode() == newRdma.GetMode() && 472 d.getRdmaQueueNum(oldRdma) == d.getRdmaQueueNum(newRdma) && 473 d.getRdmaRxQueueSize(oldRdma) == d.getRdmaRxQueueSize(newRdma) && 474 d.getRdmaTxQueueSize(oldRdma) == d.getRdmaTxQueueSize(newRdma) 475 } 476 477 // MetadataFactory is a factory for index-map customized for VPP interfaces. 478 func (d *InterfaceDescriptor) MetadataFactory() idxmap.NamedMappingRW { 479 return ifaceidx.NewIfaceIndex(d.log, "vpp-interface-index") 480 } 481 482 // Validate validates VPP interface configuration. 483 func (d *InterfaceDescriptor) Validate(key string, intf *interfaces.Interface) error { 484 // validate name 485 if name := intf.GetName(); name == "" { 486 return kvs.NewInvalidValueError(ErrInterfaceWithoutName, "name") 487 } else if len(name) > logicalNameLengthLimit { 488 return kvs.NewInvalidValueError(ErrInterfaceNameTooLong, "name") 489 } 490 491 // validate interface type defined 492 if intf.GetType() == interfaces.Interface_UNDEFINED_TYPE { 493 return kvs.NewInvalidValueError(ErrInterfaceWithoutType, "type") 494 } 495 496 // validate link with interface type 497 linkMismatchErr := kvs.NewInvalidValueError(ErrInterfaceLinkMismatch, "link") 498 switch intf.GetLink().(type) { 499 case *interfaces.Interface_Sub: 500 if intf.Type != interfaces.Interface_SUB_INTERFACE { 501 return linkMismatchErr 502 } 503 case *interfaces.Interface_Memif: 504 if intf.Type != interfaces.Interface_MEMIF { 505 return linkMismatchErr 506 } 507 case *interfaces.Interface_Afpacket: 508 if intf.Type != interfaces.Interface_AF_PACKET { 509 return linkMismatchErr 510 } 511 case *interfaces.Interface_Vxlan: 512 if intf.Type != interfaces.Interface_VXLAN_TUNNEL { 513 return linkMismatchErr 514 } 515 case *interfaces.Interface_Tap: 516 if intf.Type != interfaces.Interface_TAP { 517 return linkMismatchErr 518 } 519 case *interfaces.Interface_Bond: 520 if intf.Type != interfaces.Interface_BOND_INTERFACE { 521 return linkMismatchErr 522 } 523 case *interfaces.Interface_VmxNet3: 524 if intf.Type != interfaces.Interface_VMXNET3_INTERFACE { 525 return linkMismatchErr 526 } 527 case *interfaces.Interface_Ipsec: 528 if intf.Type != interfaces.Interface_IPSEC_TUNNEL { 529 return linkMismatchErr 530 } 531 case *interfaces.Interface_Gre: 532 if intf.Type != interfaces.Interface_GRE_TUNNEL { 533 return linkMismatchErr 534 } 535 case *interfaces.Interface_Gtpu: 536 if intf.Type != interfaces.Interface_GTPU_TUNNEL { 537 return linkMismatchErr 538 } 539 case *interfaces.Interface_Ipip: 540 if intf.Type != interfaces.Interface_IPIP_TUNNEL { 541 return linkMismatchErr 542 } 543 case *interfaces.Interface_Wireguard: 544 if intf.Type != interfaces.Interface_WIREGUARD_TUNNEL { 545 return linkMismatchErr 546 } 547 case *interfaces.Interface_Rdma: 548 if intf.Type != interfaces.Interface_RDMA { 549 return linkMismatchErr 550 } 551 case nil: 552 if intf.Type != interfaces.Interface_SOFTWARE_LOOPBACK && 553 intf.Type != interfaces.Interface_DPDK { 554 return errors.Errorf("VPP interface type %s must have link defined", intf.Type) 555 } 556 } 557 558 // validate type specific 559 switch intf.GetType() { 560 case interfaces.Interface_SUB_INTERFACE: 561 if parentName := intf.GetSub().GetParentName(); parentName == "" { 562 return kvs.NewInvalidValueError(ErrSubInterfaceWithoutParent, "link.sub.parent_name") 563 } 564 case interfaces.Interface_DPDK: 565 if _, ok := d.ethernetIfs[intf.Name]; !ok { 566 return kvs.NewInvalidValueError(ErrDPDKInterfaceMissing, "name") 567 } 568 case interfaces.Interface_AF_PACKET: 569 if intf.GetAfpacket().GetHostIfName() == "" && 570 intf.GetAfpacket().GetLinuxInterface() == "" { 571 return kvs.NewInvalidValueError(ErrAfPacketWithoutTarget, 572 "link.afpacket.host_if_name", "link.afpacket.linux_interface") 573 } 574 case interfaces.Interface_BOND_INTERFACE: 575 if name, ok := d.bondIDs[intf.GetBond().GetId()]; ok && name != intf.GetName() { 576 return kvs.NewInvalidValueError(ErrBondInterfaceIDExists, "link.bond.id") 577 } 578 case interfaces.Interface_GRE_TUNNEL: 579 if intf.GetGre().TunnelType == interfaces.GreLink_UNKNOWN { 580 return kvs.NewInvalidValueError(ErrGreBadTunnelType, "link.gre.tunnel_type") 581 } 582 if intf.GetGre().SrcAddr == "" { 583 return kvs.NewInvalidValueError(ErrGreSrcAddrMissing, "link.gre.src_addr") 584 } 585 if intf.GetGre().DstAddr == "" { 586 return kvs.NewInvalidValueError(ErrGreDstAddrMissing, "link.gre.dst_addr") 587 } 588 case interfaces.Interface_VXLAN_TUNNEL: 589 if intf.GetVxlan().SrcAddress == "" { 590 return kvs.NewInvalidValueError(ErrVxLanSrcAddrMissing, "link.vxlan.src_address") 591 } 592 if intf.GetVxlan().DstAddress == "" { 593 return kvs.NewInvalidValueError(ErrVxLanDstAddrMissing, "link.vxlan.dst_address") 594 } 595 596 if dst := net.ParseIP(intf.GetVxlan().DstAddress); dst != nil { 597 // if destination address is multicast then `Multicast` field must contain interface name. 598 if dst.IsMulticast() && intf.GetVxlan().Multicast == "" { 599 return kvs.NewInvalidValueError(ErrVxLanMulticastIntfMissing, "link.vxlan.multicast") 600 } 601 } else { 602 // destination address is not valid IP address. 603 return kvs.NewInvalidValueError(ErrVxLanDstAddrBad, "link.vxlan.dst_address") 604 } 605 606 if gpe := intf.GetVxlan().Gpe; gpe != nil { 607 if gpe.Protocol == interfaces.VxlanLink_Gpe_UNKNOWN { 608 return kvs.NewInvalidValueError(ErrVxLanGpeBadProtocol, "link.vxlan.gpe.protocol") 609 } 610 611 // DecapVrfId must be zero if the protocol being encapsulated is not IP4 or IP6. 612 isIP46 := gpe.Protocol == interfaces.VxlanLink_Gpe_IP4 || gpe.Protocol == interfaces.VxlanLink_Gpe_IP6 613 if !isIP46 && gpe.DecapVrfId != 0 { 614 return kvs.NewInvalidValueError(ErrVxLanGpeNonZeroDecapVrfID, "link.vxlan.gpe.decap_vrf_id") 615 } 616 617 } 618 case interfaces.Interface_GTPU_TUNNEL: 619 if intf.GetGtpu().SrcAddr == "" { 620 return kvs.NewInvalidValueError(ErrGtpuSrcAddrMissing, "link.gtpu.src_addr") 621 } 622 if net.ParseIP(intf.GetGtpu().SrcAddr) == nil { 623 return kvs.NewInvalidValueError(ErrGtpuSrcAddrBad, "link.gtpu.src_addr") 624 } 625 626 if intf.GetGtpu().DstAddr == "" { 627 return kvs.NewInvalidValueError(ErrGtpuDstAddrMissing, "link.gtpu.dst_addr") 628 } 629 if net.ParseIP(intf.GetGtpu().DstAddr) == nil { 630 return kvs.NewInvalidValueError(ErrGtpuDstAddrBad, "link.gtpu.dst_addr") 631 } 632 case interfaces.Interface_IPIP_TUNNEL: 633 if intf.GetIpip().SrcAddr == "" { 634 return kvs.NewInvalidValueError(ErrIpipSrcAddrMissing, "link.ipip.src_addr") 635 } 636 if net.ParseIP(intf.GetIpip().SrcAddr) == nil { 637 return kvs.NewInvalidValueError(ErrIpipSrcAddrBad, "link.ipip.src_addr") 638 } 639 640 if intf.GetIpip().TunnelMode == interfaces.IPIPLink_POINT_TO_POINT { 641 if intf.GetIpip().DstAddr == "" { 642 return kvs.NewInvalidValueError(ErrIpipDstAddrMissing, "link.ipip.dst_addr") 643 } 644 if net.ParseIP(intf.GetIpip().DstAddr) == nil { 645 return kvs.NewInvalidValueError(ErrIpipDstAddrBad, "link.ipip.dst_addr") 646 } 647 } 648 case interfaces.Interface_WIREGUARD_TUNNEL: 649 if intf.GetWireguard().SrcAddr == "" { 650 return kvs.NewInvalidValueError(ErrWgSrcAddrMissing, "link.wireguard.src_addr") 651 } 652 if net.ParseIP(intf.GetWireguard().SrcAddr) == nil { 653 return kvs.NewInvalidValueError(ErrWgSrcAddrBad, "link.wireguard.src_addr") 654 } 655 656 if len(intf.GetWireguard().PrivateKey) != wireguardKeyLength { 657 return kvs.NewInvalidValueError(ErrWgKeyLen, "link.wireguard.key") 658 } 659 660 if intf.GetWireguard().Port > 0xFFFF { 661 return kvs.NewInvalidValueError(ErrWgPort, "link.wireguard.port") 662 } 663 case interfaces.Interface_RDMA: 664 if intf.GetRdma().GetHostIfName() == "" { 665 return kvs.NewInvalidValueError(ErrRdmaHostInterfaceMissing, "link.rdma.host_if_name") 666 } 667 if intf.GetRdma().GetRxqNum()>>16 != 0 { 668 return kvs.NewInvalidValueError(ErrRdmaQueueNumTooLarge, "link.rdma.rxq_num") 669 } 670 if rxQSize := intf.GetRdma().GetRxqSize(); rxQSize > 0 { 671 if rxQSize&(rxQSize-1) != 0 { 672 return kvs.NewInvalidValueError(ErrRdmaInvalidQueueSize, "link.rdma.rxq_size") 673 } 674 if rxQSize>>16 != 0 { 675 return kvs.NewInvalidValueError(ErrRdmaQueueSizeTooLarge, "link.rdma.rxq_size") 676 } 677 } 678 if txQSize := intf.GetRdma().GetTxqSize(); txQSize > 0 { 679 if txQSize&(txQSize-1) != 0 { 680 return kvs.NewInvalidValueError(ErrRdmaInvalidQueueSize, "link.rdma.txq_size") 681 } 682 if txQSize>>16 != 0 { 683 return kvs.NewInvalidValueError(ErrRdmaQueueSizeTooLarge, "link.rdma.txq_size") 684 } 685 } 686 } 687 688 // validate unnumbered 689 if intf.GetUnnumbered() != nil { 690 if len(intf.GetIpAddresses()) > 0 { 691 return kvs.NewInvalidValueError(ErrUnnumberedWithIP, "unnumbered", "ip_addresses") 692 } 693 } 694 695 // validate rx placements before before deriving 696 for i, rxPlacement1 := range intf.GetRxPlacements() { 697 for j := i + 1; j < len(intf.GetRxPlacements()); j++ { 698 rxPlacement2 := intf.GetRxPlacements()[j] 699 if rxPlacement1.Queue == rxPlacement2.Queue { 700 return kvs.NewInvalidValueError(ErrRedefinedRxPlacement, 701 fmt.Sprintf("rx_placement[.queue=%d]", rxPlacement1.Queue)) 702 } 703 } 704 } 705 706 return nil 707 } 708 709 // UpdateWithRecreate returns true if Type or Type-specific attributes are different. 710 func (d *InterfaceDescriptor) UpdateWithRecreate(key string, oldIntf, newIntf *interfaces.Interface, metadata *ifaceidx.IfaceMetadata) bool { 711 if oldIntf.Type != newIntf.Type { 712 return true 713 } 714 715 // if type-specific attributes have changed, then re-create the interface 716 if !d.equivalentTypeSpecificConfig(oldIntf, newIntf) { 717 return true 718 } 719 720 if (oldIntf.GetType() == interfaces.Interface_VXLAN_TUNNEL || 721 oldIntf.GetType() == interfaces.Interface_GTPU_TUNNEL || 722 oldIntf.GetType() == interfaces.Interface_IPIP_TUNNEL) && 723 oldIntf.Vrf != newIntf.Vrf { 724 // for VXLAN, GTPU and IPIP interfaces a change in the VRF assignment requires full re-creation 725 return true 726 } 727 728 // case for af-packet mac update (cannot be updated directly) 729 if oldIntf.GetType() == interfaces.Interface_AF_PACKET && oldIntf.PhysAddress != newIntf.PhysAddress { 730 return true 731 } 732 733 return false 734 } 735 736 // Dependencies lists dependencies for a VPP interface. 737 func (d *InterfaceDescriptor) Dependencies(key string, intf *interfaces.Interface) (dependencies []kvs.Dependency) { 738 switch intf.Type { 739 case interfaces.Interface_AF_PACKET: 740 // AF-PACKET depends on a referenced Linux interface in the default namespace 741 if intf.GetAfpacket().GetLinuxInterface() != "" { 742 dependencies = append(dependencies, kvs.Dependency{ 743 Label: afPacketHostInterfaceDep, 744 Key: linux_intf.InterfaceKey(intf.GetAfpacket().GetLinuxInterface()), 745 }) 746 } else if intf.GetAfpacket().GetHostIfName() != "" { 747 dependencies = append(dependencies, kvs.Dependency{ 748 Label: afPacketHostInterfaceDep, 749 Key: linux_intf.InterfaceHostNameKey(intf.GetAfpacket().GetHostIfName()), 750 }) 751 } 752 case interfaces.Interface_TAP: 753 // TAP connects VPP with microservice 754 if toMicroservice := intf.GetTap().GetToMicroservice(); toMicroservice != "" { 755 dependencies = append(dependencies, kvs.Dependency{ 756 Label: microserviceDep, 757 Key: linux_ns.MicroserviceKey(toMicroservice), 758 }) 759 } 760 case interfaces.Interface_VXLAN_TUNNEL: 761 // VXLAN referencing an interface with Multicast IP address 762 if vxlanMulticast := intf.GetVxlan().GetMulticast(); vxlanMulticast != "" { 763 dependencies = append(dependencies, kvs.Dependency{ 764 Label: vxlanMulticastDep, 765 AnyOf: kvs.AnyOfDependency{ 766 KeyPrefixes: []string{interfaces.InterfaceAddressPrefix(vxlanMulticast)}, 767 KeySelector: func(key string) bool { 768 _, ifaceAddr, source, _, _ := interfaces.ParseInterfaceAddressKey(key) 769 if source != netalloc_api.IPAddressSource_ALLOC_REF { 770 ip, _, err := net.ParseCIDR(ifaceAddr) 771 return err == nil && ip.IsMulticast() 772 } 773 // TODO: handle the case when multicast IP address is allocated 774 // via netalloc (too specific to bother until really needed) 775 return false 776 }, 777 }, 778 }) 779 } 780 if intf.GetVrf() != 0 { 781 // binary API for creating VXLAN tunnel requires the VRF table 782 // to be already created 783 var protocol l3.VrfTable_Protocol 784 srcAddr := net.ParseIP(intf.GetVxlan().GetSrcAddress()).To4() 785 dstAddr := net.ParseIP(intf.GetVxlan().GetDstAddress()).To4() 786 if srcAddr == nil && dstAddr == nil { 787 protocol = l3.VrfTable_IPV6 788 } 789 dependencies = append(dependencies, kvs.Dependency{ 790 Label: vxlanVrfTableDep, 791 Key: l3.VrfTableKey(intf.GetVrf(), protocol), 792 }) 793 } 794 795 if gpe := intf.GetVxlan().Gpe; gpe != nil { 796 if gpe.DecapVrfId != 0 { 797 var protocol l3.VrfTable_Protocol 798 if gpe.Protocol == interfaces.VxlanLink_Gpe_IP6 { 799 protocol = l3.VrfTable_IPV6 800 } 801 dependencies = append(dependencies, kvs.Dependency{ 802 Label: vxlanGpeVrfTableDep, 803 Key: l3.VrfTableKey(gpe.DecapVrfId, protocol), 804 }) 805 } 806 } 807 808 case interfaces.Interface_GTPU_TUNNEL: 809 // GTPU referencing an interface with Multicast IP address 810 if gtpuMulticast := intf.GetGtpu().GetMulticast(); gtpuMulticast != "" { 811 dependencies = append(dependencies, kvs.Dependency{ 812 Label: gtpuMulticastDep, 813 AnyOf: kvs.AnyOfDependency{ 814 KeyPrefixes: []string{interfaces.InterfaceAddressPrefix(gtpuMulticast)}, 815 KeySelector: func(key string) bool { 816 _, ifaceAddr, source, _, _ := interfaces.ParseInterfaceAddressKey(key) 817 if source != netalloc_api.IPAddressSource_ALLOC_REF { 818 ip, _, err := net.ParseCIDR(ifaceAddr) 819 return err == nil && ip.IsMulticast() 820 } 821 // TODO: handle the case when multicast IP address is allocated 822 // via netalloc (too specific to bother until really needed) 823 return false 824 }, 825 }, 826 }) 827 } 828 if intf.GetGtpu().GetEncapVrfId() != 0 { 829 // binary API for creating GTPU tunnel requires the VRF table 830 // to be already created 831 var protocol l3.VrfTable_Protocol 832 srcAddr := net.ParseIP(intf.GetGtpu().GetSrcAddr()).To4() 833 dstAddr := net.ParseIP(intf.GetGtpu().GetDstAddr()).To4() 834 if srcAddr == nil && dstAddr == nil { 835 protocol = l3.VrfTable_IPV6 836 } 837 dependencies = append(dependencies, kvs.Dependency{ 838 Label: gtpuVrfTableDep, 839 Key: l3.VrfTableKey(intf.GetGtpu().GetEncapVrfId(), protocol), 840 }) 841 } 842 843 case interfaces.Interface_IPIP_TUNNEL: 844 if intf.GetVrf() != 0 { 845 // binary API for creating IPIP tunnel requires the VRF table to be already created 846 var protocol l3.VrfTable_Protocol 847 srcAddr := net.ParseIP(intf.GetIpip().GetSrcAddr()).To4() 848 dstAddr := net.ParseIP(intf.GetIpip().GetDstAddr()).To4() 849 if srcAddr == nil && dstAddr == nil { 850 protocol = l3.VrfTable_IPV6 851 } 852 dependencies = append(dependencies, kvs.Dependency{ 853 Label: ipipVrfTableDep, 854 Key: l3.VrfTableKey(intf.GetVrf(), protocol), 855 }) 856 } 857 858 case interfaces.Interface_SUB_INTERFACE: 859 // SUB_INTERFACE requires parent interface 860 if parentName := intf.GetSub().GetParentName(); parentName != "" { 861 dependencies = append(dependencies, kvs.Dependency{ 862 Label: parentInterfaceDep, 863 Key: interfaces.InterfaceKey(parentName), 864 }) 865 } 866 867 case interfaces.Interface_RDMA: 868 // RDMA depends on a referenced Linux interface in the default namespace 869 dependencies = append(dependencies, kvs.Dependency{ 870 Label: rdmaHostInterfaceDep, 871 Key: linux_intf.InterfaceHostNameKey(intf.GetRdma().GetHostIfName()), 872 }) 873 } 874 875 return dependencies 876 } 877 878 // DerivedValues derives: 879 // - key-value for unnumbered configuration sub-section 880 // - empty value for enabled DHCP client 881 // - configuration for every slave of a bonded interface 882 // - one empty value for every IP address to be assigned to the interface 883 // - one empty value for VRF table to put the interface into 884 // - one value with interface configuration reduced to RxMode if set 885 // - one Interface_RxPlacement for every queue with configured Rx placement 886 // - one empty value which will be created once at least one IP address is 887 // assigned to the interface. 888 func (d *InterfaceDescriptor) DerivedValues(key string, intf *interfaces.Interface) (derValues []kvs.KeyValuePair) { 889 // unnumbered interface 890 if intf.GetUnnumbered() != nil { 891 derValues = append(derValues, kvs.KeyValuePair{ 892 Key: interfaces.UnnumberedKey(intf.Name), 893 Value: intf.GetUnnumbered(), 894 }) 895 } 896 897 // bond slave interface 898 if intf.Type == interfaces.Interface_BOND_INTERFACE && intf.GetBond() != nil { 899 for _, slaveIf := range intf.GetBond().GetBondedInterfaces() { 900 derValues = append(derValues, kvs.KeyValuePair{ 901 Key: interfaces.BondedInterfaceKey(intf.Name, slaveIf.Name), 902 Value: slaveIf, 903 }) 904 } 905 } 906 907 // DHCP client 908 if intf.SetDhcpClient { 909 derValues = append(derValues, kvs.KeyValuePair{ 910 Key: interfaces.DHCPClientKey(intf.Name), 911 Value: &empty.Empty{}, 912 }) 913 } 914 915 // IP6ND config 916 if intf.GetIp6Nd() != nil { 917 derValues = append(derValues, kvs.KeyValuePair{ 918 Key: interfaces.IP6NDKey(intf.Name), 919 Value: intf.GetIp6Nd(), 920 }) 921 } 922 923 // IP addresses 924 for _, ipAddr := range intf.IpAddresses { 925 derValues = append(derValues, kvs.KeyValuePair{ 926 Key: interfaces.InterfaceAddressKey(intf.Name, ipAddr, netalloc_api.IPAddressSource_STATIC), 927 Value: &empty.Empty{}, 928 }) 929 } 930 931 // VRF assignment 932 if intf.GetUnnumbered() != nil { 933 // VRF inherited from the target numbered interface 934 derValues = append(derValues, kvs.KeyValuePair{ 935 Key: interfaces.InterfaceInheritedVrfKey(intf.GetName(), intf.GetUnnumbered().GetInterfaceWithIp()), 936 Value: &empty.Empty{}, 937 }) 938 } else { 939 // not unnumbered 940 var hasIPv4, hasIPv6 bool 941 switch intf.Type { 942 case interfaces.Interface_VXLAN_TUNNEL: 943 srcAddr := net.ParseIP(intf.GetVxlan().GetSrcAddress()).To4() 944 dstAddr := net.ParseIP(intf.GetVxlan().GetDstAddress()).To4() 945 if srcAddr == nil && dstAddr == nil { 946 hasIPv6 = true 947 } else { 948 hasIPv4 = true 949 } 950 case interfaces.Interface_GTPU_TUNNEL: 951 srcAddr := net.ParseIP(intf.GetGtpu().GetSrcAddr()).To4() 952 dstAddr := net.ParseIP(intf.GetGtpu().GetDstAddr()).To4() 953 if srcAddr == nil && dstAddr == nil { 954 hasIPv6 = true 955 } else { 956 hasIPv4 = true 957 } 958 case interfaces.Interface_IPIP_TUNNEL: 959 srcAddr := net.ParseIP(intf.GetIpip().GetSrcAddr()).To4() 960 dstAddr := net.ParseIP(intf.GetIpip().GetDstAddr()).To4() 961 if srcAddr == nil && dstAddr == nil { 962 hasIPv6 = true 963 } else { 964 hasIPv4 = true 965 } 966 default: 967 hasIPv4, hasIPv6 = getIPAddressVersions(intf.IpAddresses) 968 } 969 if hasIPv4 || hasIPv6 { 970 derValues = append(derValues, kvs.KeyValuePair{ 971 Key: interfaces.InterfaceVrfKey(intf.GetName(), int(intf.GetVrf()), hasIPv4, hasIPv6), 972 Value: &empty.Empty{}, 973 }) 974 } 975 } 976 977 // Rx mode 978 if len(intf.GetRxModes()) > 0 { 979 derValues = append(derValues, kvs.KeyValuePair{ 980 Key: interfaces.RxModesKey(intf.GetName()), 981 Value: &interfaces.Interface{ 982 Name: intf.GetName(), 983 Type: intf.GetType(), 984 RxModes: intf.GetRxModes(), 985 }, 986 }) 987 } 988 989 // Rx placement 990 for _, rxPlacement := range intf.GetRxPlacements() { 991 derValues = append(derValues, kvs.KeyValuePair{ 992 Key: interfaces.RxPlacementKey(intf.GetName(), rxPlacement.GetQueue()), 993 Value: rxPlacement, 994 }) 995 } 996 997 // with-IP address (property) 998 if len(intf.GetIpAddresses()) > 0 { 999 derValues = append(derValues, kvs.KeyValuePair{ 1000 Key: interfaces.InterfaceWithIPKey(intf.GetName()), 1001 Value: &empty.Empty{}, 1002 }) 1003 } 1004 1005 // TODO: define derived value for UP/DOWN state (needed for subinterfaces) 1006 1007 return derValues 1008 } 1009 1010 // getInterfaceMTU returns the interface MTU. 1011 func (d *InterfaceDescriptor) getInterfaceMTU(intf *interfaces.Interface) uint32 { 1012 if mtu := intf.GetMtu(); mtu != 0 { 1013 return mtu 1014 } 1015 return d.defaultMtu /* still can be 0, i.e. undefined */ 1016 } 1017 1018 // getAfPacketTargetHostIfName returns the host name of the interface to which the given AF-PACKET 1019 // interface should bind to. 1020 //nolint:staticcheck 1021 func (d *InterfaceDescriptor) getAfPacketTargetHostIfName(afpacket *interfaces.AfpacketLink) (string, error) { 1022 if afpacket.GetLinuxInterface() == "" { 1023 return afpacket.GetHostIfName(), nil 1024 } 1025 if d.linuxIfPlugin == nil { 1026 return "", errors.New("linux ifplugin dependency is needed for AF-PACKET interface") 1027 } 1028 linuxIfIdx := d.linuxIfPlugin.GetInterfaceIndex() 1029 linuxIfMeta, exists := linuxIfIdx.LookupByName(afpacket.GetLinuxInterface()) 1030 if !exists { 1031 return "", errors.Errorf("failed to find linux interface %s", afpacket.GetLinuxInterface()) 1032 } 1033 return linuxIfMeta.HostIfName, nil 1034 } 1035 1036 // resolveMemifSocketFilename returns memif socket filename ID. 1037 // Registers it if does not exists yet. 1038 func (d *InterfaceDescriptor) resolveMemifSocketFilename(memifIf *interfaces.MemifLink) (uint32, error) { 1039 socketFileName := d.getMemifSocketFilename(memifIf) 1040 registeredID, registered := d.memifSocketToID[socketFileName] 1041 if !registered { 1042 // Register new socket. ID is generated (default filename ID is 0, first is ID 1, second ID 2, etc) 1043 registeredID = uint32(len(d.memifSocketToID)) 1044 err := d.ifHandler.RegisterMemifSocketFilename(context2.TODO(), socketFileName, registeredID) 1045 if err != nil { 1046 return 0, errors.Errorf("error registering socket file name %s (ID %d): %v", socketFileName, registeredID, err) 1047 } 1048 d.memifSocketToID[socketFileName] = registeredID 1049 d.log.Debugf("Memif socket filename %s registered under ID %d", socketFileName, registeredID) 1050 } 1051 return registeredID, nil 1052 } 1053 1054 // getMemifSocketFilename returns the memif socket filename. 1055 func (d *InterfaceDescriptor) getMemifSocketFilename(memif *interfaces.MemifLink) string { 1056 if socketFilename := memif.GetSocketFilename(); socketFilename != "" { 1057 return socketFilename 1058 } 1059 return d.defaultMemifSocketPath 1060 } 1061 1062 // getMemifNumOfRxQueues returns the number of memif RX queues. 1063 func (d *InterfaceDescriptor) getMemifNumOfRxQueues(memif *interfaces.MemifLink) uint32 { 1064 if memif.GetRxQueues() == 0 { 1065 return defaultMemifNumOfQueues 1066 } 1067 return memif.GetRxQueues() 1068 } 1069 1070 // getMemifNumOfTxQueues returns the number of memif TX queues. 1071 func (d *InterfaceDescriptor) getMemifNumOfTxQueues(memif *interfaces.MemifLink) uint32 { 1072 if memif.GetTxQueues() == 0 { 1073 return defaultMemifNumOfQueues 1074 } 1075 return memif.GetTxQueues() 1076 } 1077 1078 // getMemifBufferSize returns the memif buffer size. 1079 func (d *InterfaceDescriptor) getMemifBufferSize(memif *interfaces.MemifLink) uint32 { 1080 if memif.GetBufferSize() == 0 { 1081 return defaultMemifBufferSize 1082 } 1083 return memif.GetBufferSize() 1084 } 1085 1086 // getMemifRingSize returns the memif ring size. 1087 func (d *InterfaceDescriptor) getMemifRingSize(memif *interfaces.MemifLink) uint32 { 1088 if memif.GetRingSize() == 0 { 1089 return defaultMemifRingSize 1090 } 1091 return memif.GetRingSize() 1092 } 1093 1094 // getRdmaQueueNum returns the number of RDMA queues. 1095 func (d *InterfaceDescriptor) getRdmaQueueNum(rdma *interfaces.RDMALink) uint32 { 1096 if rdma.GetRxqNum() == 0 { 1097 return defaultRdmaQueueNum 1098 } 1099 return rdma.GetRxqNum() 1100 } 1101 1102 // getRdmaRxQueueSize returns the size of Rx queues of an RDMA interface. 1103 func (d *InterfaceDescriptor) getRdmaRxQueueSize(rdma *interfaces.RDMALink) uint32 { 1104 if rdma.GetRxqSize() == 0 { 1105 return defaultRdmaQueueSize 1106 } 1107 return rdma.GetRxqSize() 1108 } 1109 1110 // getRdmaTxQueueSize returns the size of Tx queues of an RDMA interface. 1111 func (d *InterfaceDescriptor) getRdmaTxQueueSize(rdma *interfaces.RDMALink) uint32 { 1112 if rdma.GetTxqSize() == 0 { 1113 return defaultRdmaQueueSize 1114 } 1115 return rdma.GetTxqSize() 1116 } 1117 1118 // getTapConfig returns the TAP-specific configuration section (handling undefined attributes). 1119 func getTapConfig(intf *interfaces.Interface) (tapLink *interfaces.TapLink) { 1120 tapLink = new(interfaces.TapLink) 1121 proto.Merge(tapLink, intf.GetTap()) 1122 1123 if tapLink.Version == 0 { 1124 tapLink.Version = 1 1125 } 1126 if tapLink.HostIfName == "" { 1127 tapLink.HostIfName = generateTAPHostName(intf.Name) 1128 } 1129 return tapLink 1130 } 1131 1132 // generateTAPHostName (deterministically) generates the host name for a TAP interface. 1133 func generateTAPHostName(tapName string) string { 1134 if tapName == "" { 1135 return "" 1136 } 1137 return fmt.Sprintf("tap-%d", fnvHash(tapName)) 1138 } 1139 1140 // fnvHash hashes string using fnv32a algorithm. 1141 func fnvHash(s string) uint32 { 1142 h := fnv.New32a() 1143 _, _ = h.Write([]byte(s)) 1144 return h.Sum32() 1145 } 1146 1147 // equalStringSets compares two sets of strings for equality. 1148 func equalStringSets(set1, set2 []string) bool { 1149 if len(set1) != len(set2) { 1150 return false 1151 } 1152 for _, item1 := range set1 { 1153 found := false 1154 for _, item2 := range set2 { 1155 if item1 == item2 { 1156 found = true 1157 break 1158 } 1159 } 1160 if !found { 1161 return false 1162 } 1163 } 1164 return true 1165 } 1166 1167 // getIPAddressVersions returns two flags to tell whether the provided list of addresses 1168 // contains IPv4 and/or IPv6 type addresses 1169 func getIPAddressVersions(ipAddrs []string) (hasIPv4, hasIPv6 bool) { 1170 for _, ip := range ipAddrs { 1171 if strings.HasPrefix(ip, netalloc_api.AllocRefPrefix) { 1172 // TODO: figure out how to define VRF-related dependencies with netalloc'd addresses 1173 // - for now assume it is only used with IPv4 1174 hasIPv4 = true 1175 } 1176 if strings.Contains(ip, ":") { 1177 hasIPv6 = true 1178 } else { 1179 hasIPv4 = true 1180 } 1181 } 1182 return 1183 }