go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ifplugin/descriptor/interface_vrf.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/vpp/ifplugin/ifaceidx" 24 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls" 25 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 26 l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" 27 ) 28 29 const ( 30 // InterfaceVrfDescriptorName is the name of the descriptor for assigning 31 // VPP interface into VRF table. 32 InterfaceVrfDescriptorName = "vpp-interface-vrf" 33 34 // dependency labels 35 vrfV4Dep = "vrf-table-v4-exists" 36 vrfV6Dep = "vrf-table-v6-exists" 37 inheritedVrfDep = "numbered-interface-assigned-to-VRF" 38 ) 39 40 // InterfaceVrfDescriptor (un)assigns VPP interface to IPv4/IPv6 VRF table. 41 type InterfaceVrfDescriptor struct { 42 log logging.Logger 43 ifHandler vppcalls.InterfaceVppAPI 44 ifIndex ifaceidx.IfaceMetadataIndex 45 } 46 47 // NewInterfaceVrfDescriptor creates a new instance of InterfaceVrfDescriptor. 48 func NewInterfaceVrfDescriptor(ifHandler vppcalls.InterfaceVppAPI, ifIndex ifaceidx.IfaceMetadataIndex, 49 log logging.PluginLogger) *kvs.KVDescriptor { 50 51 descrCtx := &InterfaceVrfDescriptor{ 52 ifHandler: ifHandler, 53 ifIndex: ifIndex, 54 log: log.NewLogger("interface-vrf-descriptor"), 55 } 56 return &kvs.KVDescriptor{ 57 Name: InterfaceVrfDescriptorName, 58 KeySelector: descrCtx.IsInterfaceVrfKey, 59 Create: descrCtx.Create, 60 Delete: descrCtx.Delete, 61 Dependencies: descrCtx.Dependencies, 62 } 63 } 64 65 // IsInterfaceVrfKey returns true if the key represents assignment of an interface 66 // into a VRF table. 67 func (d *InterfaceVrfDescriptor) IsInterfaceVrfKey(key string) bool { 68 _, _, _, _, isIfaceVrfKey := interfaces.ParseInterfaceVrfKey(key) 69 if isIfaceVrfKey { 70 return true 71 } 72 _, _, isIfaceInherVrfKey := interfaces.ParseInterfaceInheritedVrfKey(key) 73 return isIfaceInherVrfKey 74 } 75 76 // Create puts interface into the given VRF table. 77 func (d *InterfaceVrfDescriptor) Create(key string, emptyVal proto.Message) (metadata kvs.Metadata, err error) { 78 swIfIndex, vrf, inheritedVrf, ipv4, ipv6, err := d.getParametersFromKey(key) 79 if err != nil { 80 return nil, err 81 } 82 83 // unnumbered interfaces (inherited VRF) should not be explicitly set to VRF=0 (probably bug in VPP) 84 85 if (!inheritedVrf || vrf > 0) && ipv4 { 86 err = d.ifHandler.SetInterfaceVrf(swIfIndex, uint32(vrf)) 87 if err != nil { 88 d.log.Error(err) 89 return nil, err 90 } 91 } 92 if (!inheritedVrf || vrf > 0) && ipv6 { 93 err = d.ifHandler.SetInterfaceVrfIPv6(swIfIndex, uint32(vrf)) 94 if err != nil { 95 d.log.Error(err) 96 return nil, err 97 } 98 } 99 return nil, nil 100 } 101 102 // Delete removes interface from the given VRF table. 103 func (d *InterfaceVrfDescriptor) Delete(key string, emptyVal proto.Message, metadata kvs.Metadata) (err error) { 104 swIfIndex, vrf, inheritedVrf, ipv4, ipv6, err := d.getParametersFromKey(key) 105 if err != nil { 106 return err 107 } 108 109 if !inheritedVrf && vrf > 0 && ipv4 { 110 err = d.ifHandler.SetInterfaceVrf(swIfIndex, uint32(0)) 111 if err != nil { 112 d.log.Error(err) 113 return err 114 } 115 } 116 if !inheritedVrf && vrf > 0 && ipv6 { 117 err = d.ifHandler.SetInterfaceVrfIPv6(swIfIndex, uint32(0)) 118 if err != nil { 119 d.log.Error(err) 120 return err 121 } 122 } 123 return nil 124 } 125 126 // Dependencies lists the target non-zero VRF as the only dependency. 127 func (d *InterfaceVrfDescriptor) Dependencies(key string, emptyVal proto.Message) (deps []kvs.Dependency) { 128 if _, vrf, ipv4, ipv6, isIfaceVrfKey := interfaces.ParseInterfaceVrfKey(key); isIfaceVrfKey { 129 if vrf > 0 && ipv4 { 130 deps = append(deps, kvs.Dependency{ 131 Label: vrfV4Dep, 132 Key: l3.VrfTableKey(uint32(vrf), l3.VrfTable_IPV4), 133 }) 134 } 135 if vrf > 0 && ipv6 { 136 deps = append(deps, kvs.Dependency{ 137 Label: vrfV6Dep, 138 Key: l3.VrfTableKey(uint32(vrf), l3.VrfTable_IPV6), 139 }) 140 } 141 return deps 142 } 143 144 _, fromIface, _ := interfaces.ParseInterfaceInheritedVrfKey(key) 145 return []kvs.Dependency{ 146 { 147 Label: inheritedVrfDep, 148 AnyOf: kvs.AnyOfDependency{ 149 KeyPrefixes: []string{interfaces.InterfaceVrfKeyPrefix(fromIface)}, 150 }, 151 }, 152 } 153 } 154 155 func (d *InterfaceVrfDescriptor) getParametersFromKey(key string) (swIfIndex, vrf uint32, 156 inheritedVrf bool, ipv4, ipv6 bool, err error) { 157 158 var ( 159 isIfaceVrfKey bool 160 vrfTableID int 161 iface, fromIface string 162 ) 163 164 iface, vrfTableID, ipv4, ipv6, isIfaceVrfKey = interfaces.ParseInterfaceVrfKey(key) 165 if !isIfaceVrfKey { 166 iface, fromIface, _ = interfaces.ParseInterfaceInheritedVrfKey(key) 167 fromIfaceMeta, found := d.ifIndex.LookupByName(fromIface) 168 if !found { 169 err = errors.Errorf("failed to find interface %s", iface) 170 d.log.Error(err) 171 return 172 } 173 vrfTableID = int(fromIfaceMeta.Vrf) 174 ipv4, ipv6 = getIPAddressVersions(fromIfaceMeta.IPAddresses) 175 inheritedVrf = true 176 } 177 178 ifMeta, found := d.ifIndex.LookupByName(iface) 179 if !found { 180 err = errors.Errorf("failed to find interface %s", iface) 181 d.log.Error(err) 182 return 183 } 184 185 swIfIndex = ifMeta.SwIfIndex 186 vrf = uint32(vrfTableID) 187 return 188 }