go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/abfplugin/descriptor/abf_to_interface.go (about) 1 // Copyright (c) 2019 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 "fmt" 19 20 "go.ligato.io/vpp-agent/v3/plugins/vpp/abfplugin/abfidx" 21 vpp_abf "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/abf" 22 vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 23 24 "github.com/go-errors/errors" 25 "go.ligato.io/cn-infra/v2/logging" 26 "google.golang.org/protobuf/proto" 27 28 "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 29 "go.ligato.io/vpp-agent/v3/plugins/vpp/abfplugin/vppcalls" 30 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin" 31 ) 32 33 const ( 34 // ABFToInterfaceDescriptorName is name for descriptor 35 ABFToInterfaceDescriptorName = "vpp-abf-to-interface" 36 37 // dependency labels 38 interfaceDep = "interface-exists" 39 ) 40 41 // ABFToInterfaceDescriptor represents assignment of interface to ABF policy. 42 type ABFToInterfaceDescriptor struct { 43 log logging.Logger 44 abfHandler vppcalls.ABFVppAPI 45 abfIndex abfidx.ABFMetadataIndex 46 ifPlugin ifplugin.API 47 } 48 49 // NewABFToInterfaceDescriptor returns new ABFInterface descriptor 50 func NewABFToInterfaceDescriptor(abfIndex abfidx.ABFMetadataIndex, abfHandler vppcalls.ABFVppAPI, ifPlugin ifplugin.API, log logging.PluginLogger) *api.KVDescriptor { 51 ctx := &ABFToInterfaceDescriptor{ 52 log: log, 53 abfHandler: abfHandler, 54 abfIndex: abfIndex, 55 ifPlugin: ifPlugin, 56 } 57 return &api.KVDescriptor{ 58 Name: ABFToInterfaceDescriptorName, 59 KeySelector: ctx.IsABFInterfaceKey, 60 Create: ctx.Create, 61 Delete: ctx.Delete, 62 Dependencies: ctx.Dependencies, 63 } 64 } 65 66 // IsABFInterfaceKey returns true if the key is identifying ABF policy interface (derived value) 67 func (d *ABFToInterfaceDescriptor) IsABFInterfaceKey(key string) bool { 68 _, _, isABFToInterfaceKey := vpp_abf.ParseToInterfaceKey(key) 69 return isABFToInterfaceKey 70 } 71 72 // Create binds interface to ABF. 73 func (d *ABFToInterfaceDescriptor) Create(key string, emptyVal proto.Message) (metadata api.Metadata, err error) { 74 // validate and get all required values 75 isIPv6, abfIdx, ifIdx, priority, err := d.process(key) 76 if err != nil { 77 d.log.Error(err) 78 return nil, err 79 } 80 81 // attach interface to ABF policy 82 if isIPv6 { 83 return nil, d.abfHandler.AbfAttachInterfaceIPv6(abfIdx, ifIdx, priority) 84 } 85 return nil, d.abfHandler.AbfAttachInterfaceIPv4(abfIdx, ifIdx, priority) 86 } 87 88 // Delete unbinds interface from ABF. 89 func (d *ABFToInterfaceDescriptor) Delete(key string, emptyVal proto.Message, metadata api.Metadata) (err error) { 90 // validate and get all required values 91 isIPv6, abfIdx, ifIdx, priority, err := d.process(key) 92 if err != nil { 93 d.log.Error(err) 94 return err 95 } 96 97 // detach interface to ABF policy 98 if isIPv6 { 99 return d.abfHandler.AbfDetachInterfaceIPv6(abfIdx, ifIdx, priority) 100 } 101 return d.abfHandler.AbfDetachInterfaceIPv4(abfIdx, ifIdx, priority) 102 } 103 104 // Dependencies lists the interface as the only dependency for the binding. 105 func (d *ABFToInterfaceDescriptor) Dependencies(key string, emptyVal proto.Message) []api.Dependency { 106 _, ifName, _ := vpp_abf.ParseToInterfaceKey(key) 107 return []api.Dependency{ 108 { 109 Label: interfaceDep, 110 Key: vpp_interfaces.InterfaceKey(ifName), 111 }, 112 } 113 } 114 115 // returns a bunch of values needed to attach/detach interface to/from ABF 116 func (d *ABFToInterfaceDescriptor) process(key string) (isIPv6 bool, abfIdx, ifIdx, priority uint32, err error) { 117 // parse ABF and interface name 118 abfIndex, ifName, isValid := vpp_abf.ParseToInterfaceKey(key) 119 if !isValid { 120 err = fmt.Errorf("ABF to interface key %s is not valid", key) 121 return 122 } 123 // obtain ABF index 124 abfData, exists := d.abfIndex.LookupByName(abfIndex) 125 if !exists { 126 err = errors.Errorf("failed to obtain metadata for ABF %s", abfIndex) 127 return 128 } 129 130 // obtain interface index 131 ifData, exists := d.ifPlugin.GetInterfaceIndex().LookupByName(ifName) 132 if !exists { 133 err = errors.Errorf("failed to obtain metadata for interface %s", ifName) 134 return 135 } 136 137 // find other interface parameters from metadata 138 for _, attachedIf := range abfData.Attached { 139 if attachedIf.InputInterface == ifName { 140 isIPv6, priority = attachedIf.IsIpv6, attachedIf.Priority 141 } 142 } 143 return isIPv6, abfData.Index, ifData.SwIfIndex, priority, nil 144 }