go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/l3plugin/vrfidx/vrfidx.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 vrfidx 16 17 import ( 18 "time" 19 20 l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" 21 22 "go.ligato.io/cn-infra/v2/idxmap" 23 "go.ligato.io/cn-infra/v2/logging" 24 25 "go.ligato.io/vpp-agent/v3/pkg/idxvpp" 26 ) 27 28 // VRFMetadataIndex provides read-only access to mapping with VPP VRF 29 // metadata. It extends from NameToIndex. 30 type VRFMetadataIndex interface { 31 // LookupByName retrieves a previously stored metadata of VRF 32 // identified by <label>. If there is no VRF associated with the give 33 // label in the mapping, the <exists> is returned as *false* and <metadata> 34 // as *nil*. 35 LookupByName(name string) (metadata *VRFMetadata, exists bool) 36 37 // LookupByVRFIndex retrieves a previously stored VRF identified in 38 // VPP by the given <index>. 39 // If there is no VRF associated with the given index, <exists> is returned 40 // as *false* with <name> and <metadata> both set to empty values. 41 LookupByVRFIndex(index uint32) (name string, metadata *VRFMetadata, exists bool) 42 43 // ListAllVRFs returns slice of labels of all VRFs in the mapping. 44 ListAllVRFs() (names []string) 45 46 // ListAllVrfMetadata returns a list of VRF metadata - ID/Proto pairs as 47 // read from VRF metadata. 48 ListAllVrfMetadata() (idList []*VRFMetadata) 49 50 // WatchVRFs allows to subscribe to watch for changes in the VRF mapping. 51 WatchVRFs(subscriber string, channel chan<- VRFMetadataDto) 52 } 53 54 // VRFMetadataIndexRW provides read-write access to mapping with VRF 55 // metadata. 56 type VRFMetadataIndexRW interface { 57 VRFMetadataIndex 58 idxmap.NamedMappingRW 59 } 60 61 // VRFMetadata collects metadata for VPP VRF used in secondary lookups. 62 type VRFMetadata struct { 63 Index uint32 64 Protocol l3.VrfTable_Protocol 65 } 66 67 // GetIndex returns VRF index. 68 func (vrfm *VRFMetadata) GetIndex() uint32 { 69 return vrfm.Index 70 } 71 72 // GetProtocol returns VRF IP protocol. 73 func (vrfm *VRFMetadata) GetProtocol() l3.VrfTable_Protocol { 74 return vrfm.Protocol 75 } 76 77 // VRFMetadataDto represents an item sent through watch channel in VRFMetadataIndex. 78 // In contrast to NamedMappingGenericEvent, it contains typed VRF metadata. 79 type VRFMetadataDto struct { 80 idxmap.NamedMappingEvent 81 Metadata *VRFMetadata 82 } 83 84 // vrfMetadataIndex is type-safe implementation of mapping between VRF 85 // label and metadata of type *VRFMeta. 86 type vrfMetadataIndex struct { 87 idxmap.NamedMappingRW /* embeds */ 88 89 log logging.Logger 90 nameToIndex idxvpp.NameToIndex /* contains */ 91 } 92 93 // NewVRFIndex creates a new instance implementing VRFMetadataIndexRW. 94 func NewVRFIndex(logger logging.Logger, title string) VRFMetadataIndexRW { 95 mapping := idxvpp.NewNameToIndex(logger, title, indexMetadata) 96 return &vrfMetadataIndex{ 97 NamedMappingRW: mapping, 98 log: logger, 99 nameToIndex: mapping, 100 } 101 } 102 103 // LookupByName retrieves a previously stored metadata of VRF 104 // identified by <label>. If there is no VRF associated with the given 105 // name in the mapping, the <exists> is returned as *false* and <metadata> 106 // as *nil*. 107 func (m *vrfMetadataIndex) LookupByName(name string) (metadata *VRFMetadata, exists bool) { 108 meta, found := m.GetValue(name) 109 if found { 110 if typedMeta, ok := meta.(*VRFMetadata); ok { 111 return typedMeta, found 112 } 113 } 114 return nil, false 115 } 116 117 // LookupByVRFIndex retrieves a previously stored VRF identified in 118 // VPP by the given/ <index>. 119 // If there is no VRF associated with the given index, <exists> is returned 120 // as *false* with <name> and <metadata> both set to empty values. 121 func (m *vrfMetadataIndex) LookupByVRFIndex(swIfIndex uint32) (name string, metadata *VRFMetadata, exists bool) { 122 var item idxvpp.WithIndex 123 name, item, exists = m.nameToIndex.LookupByIndex(swIfIndex) 124 if exists { 125 var isVrfMeta bool 126 metadata, isVrfMeta = item.(*VRFMetadata) 127 if !isVrfMeta { 128 exists = false 129 } 130 } 131 return 132 } 133 134 // ListAllVRFs returns slice of labels of all VRFs in the mapping. 135 func (m *vrfMetadataIndex) ListAllVRFs() (names []string) { 136 return m.ListAllNames() 137 } 138 139 // ListAllVrfMetadata returns a list of VRF metadata - ID/Proto pairs as 140 // read from VRF metadata. 141 func (m *vrfMetadataIndex) ListAllVrfMetadata() (metaList []*VRFMetadata) { 142 for _, vrf := range m.ListAllNames() { 143 vrfMeta, ok := m.LookupByName(vrf) 144 if vrfMeta == nil || !ok { 145 continue 146 } 147 metaList = append(metaList, vrfMeta) 148 } 149 return 150 } 151 152 // WatchVRFs allows to subscribe to watch for changes in the VRF mapping. 153 func (m *vrfMetadataIndex) WatchVRFs(subscriber string, channel chan<- VRFMetadataDto) { 154 watcher := func(dto idxmap.NamedMappingGenericEvent) { 155 typedMeta, ok := dto.Value.(*VRFMetadata) 156 if !ok { 157 return 158 } 159 msg := VRFMetadataDto{ 160 NamedMappingEvent: dto.NamedMappingEvent, 161 Metadata: typedMeta, 162 } 163 timeout := idxmap.DefaultNotifTimeout 164 select { 165 case channel <- msg: 166 // OK 167 case <-time.After(timeout): 168 m.log.Warnf("Unable to deliver VRF watch notification after %v, channel is full", timeout) 169 } 170 } 171 if err := m.Watch(subscriber, watcher); err != nil { 172 m.log.Error(err) 173 } 174 } 175 176 // indexMetadata is an index function used for VRF metadata. 177 func indexMetadata(metaData interface{}) map[string][]string { 178 indexes := make(map[string][]string) 179 180 ifMeta, ok := metaData.(*VRFMetadata) 181 if !ok || ifMeta == nil { 182 return indexes 183 } 184 185 return indexes 186 }