go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ifplugin/descriptor/interface_address.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 "github.com/pkg/errors" 19 "go.ligato.io/cn-infra/v2/logging" 20 "google.golang.org/protobuf/proto" 21 22 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 23 "go.ligato.io/vpp-agent/v3/plugins/netalloc" 24 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx" 25 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls" 26 netalloc_api "go.ligato.io/vpp-agent/v3/proto/ligato/netalloc" 27 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 28 ) 29 30 const ( 31 // InterfaceAddressDescriptorName is the name of the descriptor for assigning 32 // IP addresses to VPP interfaces. 33 InterfaceAddressDescriptorName = "vpp-interface-address" 34 35 // dependency labels 36 interfaceInVrfDep = "interface-assigned-to-vrf-table" 37 ) 38 39 // InterfaceAddressDescriptor (un)assigns (static) IP address to/from VPP interface. 40 type InterfaceAddressDescriptor struct { 41 log logging.Logger 42 ifHandler vppcalls.InterfaceVppAPI 43 ifIndex ifaceidx.IfaceMetadataIndex 44 addrAlloc netalloc.AddressAllocator 45 } 46 47 // NewInterfaceAddressDescriptor creates a new instance of InterfaceAddressDescriptor. 48 func NewInterfaceAddressDescriptor(ifHandler vppcalls.InterfaceVppAPI, addrAlloc netalloc.AddressAllocator, 49 ifIndex ifaceidx.IfaceMetadataIndex, log logging.PluginLogger) *kvs.KVDescriptor { 50 51 descrCtx := &InterfaceAddressDescriptor{ 52 ifHandler: ifHandler, 53 ifIndex: ifIndex, 54 addrAlloc: addrAlloc, 55 log: log.NewLogger("interface-address-descriptor"), 56 } 57 return &kvs.KVDescriptor{ 58 Name: InterfaceAddressDescriptorName, 59 KeySelector: descrCtx.IsInterfaceAddressKey, 60 Validate: descrCtx.Validate, 61 Create: descrCtx.Create, 62 Delete: descrCtx.Delete, 63 Dependencies: descrCtx.Dependencies, 64 } 65 } 66 67 // IsInterfaceAddressKey returns true if the key represents assignment of an IP address 68 // to a VPP interface (that needs to be applied). KVs representing addresses 69 // already allocated from netalloc plugin or obtained from a DHCP server are 70 // excluded. 71 func (d *InterfaceAddressDescriptor) IsInterfaceAddressKey(key string) bool { 72 _, _, source, _, isAddrKey := interfaces.ParseInterfaceAddressKey(key) 73 return isAddrKey && 74 (source == netalloc_api.IPAddressSource_STATIC || source == netalloc_api.IPAddressSource_ALLOC_REF) 75 } 76 77 // Validate validates IP address to be assigned to an interface. 78 func (d *InterfaceAddressDescriptor) Validate(key string, emptyVal proto.Message) (err error) { 79 iface, addr, _, invalidKey, _ := interfaces.ParseInterfaceAddressKey(key) 80 if invalidKey { 81 return errors.New("invalid key") 82 } 83 84 return d.addrAlloc.ValidateIPAddress(addr, iface, "ip_addresses", netalloc.GwRefUnexpected) 85 } 86 87 // Create assigns IP address to an interface. 88 func (d *InterfaceAddressDescriptor) Create(key string, emptyVal proto.Message) (metadata kvs.Metadata, err error) { 89 iface, addr, _, _, _ := interfaces.ParseInterfaceAddressKey(key) 90 91 ifMeta, found := d.ifIndex.LookupByName(iface) 92 if !found { 93 err = errors.Errorf("failed to find interface %s", iface) 94 d.log.Error(err) 95 return nil, err 96 } 97 98 ipAddr, err := d.addrAlloc.GetOrParseIPAddress(addr, iface, netalloc_api.IPAddressForm_ADDR_WITH_MASK) 99 if err != nil { 100 d.log.Error(err) 101 return nil, err 102 } 103 104 err = d.ifHandler.AddInterfaceIP(ifMeta.SwIfIndex, ipAddr) 105 return nil, err 106 } 107 108 // Delete unassigns IP address from an interface. 109 func (d *InterfaceAddressDescriptor) Delete(key string, emptyVal proto.Message, metadata kvs.Metadata) (err error) { 110 iface, addr, _, _, _ := interfaces.ParseInterfaceAddressKey(key) 111 112 ifMeta, found := d.ifIndex.LookupByName(iface) 113 if !found { 114 err = errors.Errorf("failed to find interface %s", iface) 115 d.log.Error(err) 116 return err 117 } 118 119 ipAddr, err := d.addrAlloc.GetOrParseIPAddress(addr, iface, netalloc_api.IPAddressForm_ADDR_WITH_MASK) 120 if err != nil { 121 d.log.Error(err) 122 return err 123 } 124 125 // do not delete (auto-assigned) IPv6 link-local addresses 126 if ipAddr.IP.To4() == nil && ipAddr.IP.IsLinkLocalUnicast() { 127 return nil 128 } 129 130 err = d.ifHandler.DelInterfaceIP(ifMeta.SwIfIndex, ipAddr) 131 return err 132 } 133 134 // Dependencies lists assignment of the interface into the VRF table and potential 135 // allocation of the IP address as dependencies. 136 func (d *InterfaceAddressDescriptor) Dependencies(key string, emptyVal proto.Message) []kvs.Dependency { 137 iface, addr, _, _, _ := interfaces.ParseInterfaceAddressKey(key) 138 deps := []kvs.Dependency{{ 139 Label: interfaceInVrfDep, 140 AnyOf: kvs.AnyOfDependency{ 141 KeyPrefixes: []string{interfaces.InterfaceVrfKeyPrefix(iface)}, 142 }, 143 }} 144 145 allocDep, hasAllocDep := d.addrAlloc.GetAddressAllocDep(addr, iface, "") 146 if hasAllocDep { 147 deps = append(deps, allocDep) 148 } 149 150 return deps 151 }