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  }