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  }