go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/l3plugin/descriptor/teib_entry.go (about) 1 // Copyright (c) 2020 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 "context" 19 "fmt" 20 21 "github.com/pkg/errors" 22 "go.ligato.io/cn-infra/v2/logging" 23 "go.ligato.io/cn-infra/v2/utils/addrs" 24 25 "go.ligato.io/vpp-agent/v3/pkg/models" 26 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 27 ifdescriptor "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/descriptor" 28 "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/descriptor/adapter" 29 "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls" 30 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 31 l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" 32 ) 33 34 const ( 35 // TeibDescriptorName is the name of the descriptor. 36 TeibDescriptorName = "vpp-teib" 37 38 // dependency labels 39 teibEntryInterfaceDep = "interface-exists" 40 teibEntryVrfTableDep = "vrf-table-exists" 41 ) 42 43 // TeibDescriptor instructs KVScheduler how to configure VPP TEIB entries. 44 type TeibDescriptor struct { 45 log logging.Logger 46 teibHandler vppcalls.TeibVppAPI 47 scheduler kvs.KVScheduler 48 } 49 50 // NewTeibDescriptor creates a new instance of the TeibDescriptor. 51 func NewTeibDescriptor(scheduler kvs.KVScheduler, 52 teibHandler vppcalls.TeibVppAPI, log logging.PluginLogger) *kvs.KVDescriptor { 53 54 ctx := &TeibDescriptor{ 55 scheduler: scheduler, 56 teibHandler: teibHandler, 57 log: log.NewLogger("teib-descriptor"), 58 } 59 60 typedDescr := &adapter.TeibEntryDescriptor{ 61 Name: TeibDescriptorName, 62 NBKeyPrefix: l3.ModelTeib.KeyPrefix(), 63 ValueTypeName: l3.ModelTeib.ProtoName(), 64 KeySelector: l3.ModelTeib.IsKeyValid, 65 KeyLabel: l3.ModelTeib.StripKeyPrefix, 66 Validate: ctx.Validate, 67 Create: ctx.Create, 68 Delete: ctx.Delete, 69 Retrieve: ctx.Retrieve, 70 Dependencies: ctx.Dependencies, 71 RetrieveDependencies: []string{ifdescriptor.InterfaceDescriptorName}, 72 } 73 return adapter.NewTeibEntryDescriptor(typedDescr) 74 } 75 76 // Validate validates VPP TEIB entry configuration. 77 func (d *TeibDescriptor) Validate(key string, entry *l3.TeibEntry) (err error) { 78 if entry.Interface == "" { 79 return kvs.NewInvalidValueError(fmt.Errorf("no interface defined"), "interface") 80 } 81 if entry.PeerAddr == "" { 82 return kvs.NewInvalidValueError(fmt.Errorf("no peer address defined"), "peer_addr") 83 } 84 if entry.NextHopAddr == "" { 85 return kvs.NewInvalidValueError(fmt.Errorf("no next hop address defined"), "next_hop_addr") 86 } 87 return nil 88 } 89 90 // Create adds a VPP TEIB entry. 91 func (d *TeibDescriptor) Create(key string, entry *l3.TeibEntry) (interface{}, error) { 92 return nil, d.teibHandler.VppAddTeibEntry(context.Background(), entry) 93 } 94 95 // Delete removes a VPP TEIB entry. 96 func (d *TeibDescriptor) Delete(key string, entry *l3.TeibEntry, metadata interface{}) error { 97 return d.teibHandler.VppDelTeibEntry(context.Background(), entry) 98 } 99 100 // Retrieve returns all TEIB entries. 101 func (d *TeibDescriptor) Retrieve(correlate []adapter.TeibEntryKVWithMetadata) ( 102 retrieved []adapter.TeibEntryKVWithMetadata, err error, 103 ) { 104 entries, err := d.teibHandler.DumpTeib() 105 if errors.Is(err, vppcalls.ErrTeibUnsupported) { 106 d.log.Debug("DumpTeib failed:", err) 107 return nil, nil 108 } else if err != nil { 109 return nil, err 110 } 111 for _, entry := range entries { 112 retrieved = append(retrieved, adapter.TeibEntryKVWithMetadata{ 113 Key: models.Key(entry), 114 Value: entry, 115 Origin: kvs.UnknownOrigin, 116 }) 117 } 118 return 119 } 120 121 // Dependencies lists dependencies for a VPP TEIB entry. 122 func (d *TeibDescriptor) Dependencies(key string, entry *l3.TeibEntry) (deps []kvs.Dependency) { 123 124 // the referenced interface must exist 125 deps = append(deps, kvs.Dependency{ 126 Label: teibEntryInterfaceDep, 127 Key: interfaces.InterfaceKey(entry.Interface), 128 }) 129 130 // non-zero VRF must exists 131 if entry.VrfId != 0 { 132 var protocol l3.VrfTable_Protocol 133 _, isIPv6, _ := addrs.ParseIPWithPrefix(entry.NextHopAddr) 134 if isIPv6 { 135 protocol = l3.VrfTable_IPV6 136 } 137 deps = append(deps, kvs.Dependency{ 138 Label: teibEntryVrfTableDep, 139 Key: l3.VrfTableKey(entry.VrfId, protocol), 140 }) 141 } 142 return deps 143 }