go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/stnplugin/descriptor/stn.go (about)

     1  // Copyright (c) 2018 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  	"github.com/pkg/errors"
    19  	"go.ligato.io/cn-infra/v2/logging"
    20  	"google.golang.org/protobuf/proto"
    21  
    22  	"go.ligato.io/vpp-agent/v3/pkg/models"
    23  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    24  	ifDescriptor "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/descriptor"
    25  	"go.ligato.io/vpp-agent/v3/plugins/vpp/stnplugin/descriptor/adapter"
    26  	"go.ligato.io/vpp-agent/v3/plugins/vpp/stnplugin/vppcalls"
    27  	interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    28  	stn "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/stn"
    29  )
    30  
    31  const (
    32  	// STNDescriptorName is the name of the descriptor for VPP STN rules
    33  	STNDescriptorName = "vpp-stn-rules"
    34  
    35  	// dependency labels
    36  	stnInterfaceDep = "stn-interface-exists"
    37  )
    38  
    39  // A list of non-retriable errors:
    40  var (
    41  	// ErrSTNWithoutInterface is returned when VPP STN rule has undefined interface.
    42  	ErrSTNWithoutInterface = errors.New("VPP STN rule defined without interface")
    43  
    44  	// ErrSTNWithoutIPAddress is returned when VPP STN rule has undefined IP address.
    45  	ErrSTNWithoutIPAddress = errors.New("VPP STN rule defined without IP address")
    46  )
    47  
    48  // STNDescriptor teaches KVScheduler how to configure VPP STN rules.
    49  type STNDescriptor struct {
    50  	// dependencies
    51  	log        logging.Logger
    52  	stnHandler vppcalls.StnVppAPI
    53  }
    54  
    55  // NewSTNDescriptor creates a new instance of the STN descriptor.
    56  func NewSTNDescriptor(stnHandler vppcalls.StnVppAPI, log logging.PluginLogger) *STNDescriptor {
    57  	return &STNDescriptor{
    58  		log:        log.NewLogger("stn-descriptor"),
    59  		stnHandler: stnHandler,
    60  	}
    61  }
    62  
    63  // GetDescriptor returns descriptor suitable for registration (via adapter) with
    64  // the KVScheduler.
    65  func (d *STNDescriptor) GetDescriptor() *adapter.STNDescriptor {
    66  	return &adapter.STNDescriptor{
    67  		Name:                 STNDescriptorName,
    68  		NBKeyPrefix:          stn.ModelRule.KeyPrefix(),
    69  		ValueTypeName:        stn.ModelRule.ProtoName(),
    70  		KeySelector:          stn.ModelRule.IsKeyValid,
    71  		KeyLabel:             stn.ModelRule.StripKeyPrefix,
    72  		ValueComparator:      d.EquivalentSTNs,
    73  		Validate:             d.Validate,
    74  		Create:               d.Create,
    75  		Delete:               d.Delete,
    76  		Retrieve:             d.Retrieve,
    77  		Dependencies:         d.Dependencies,
    78  		RetrieveDependencies: []string{ifDescriptor.InterfaceDescriptorName},
    79  	}
    80  }
    81  
    82  // EquivalentSTNs is case-insensitive comparison function for stn.Rule.
    83  func (d *STNDescriptor) EquivalentSTNs(key string, oldSTN, newSTN *stn.Rule) bool {
    84  	// parameters compared by proto equal
    85  	return proto.Equal(oldSTN, newSTN)
    86  }
    87  
    88  // Validate validates VPP STN rule configuration.
    89  func (d *STNDescriptor) Validate(key string, stn *stn.Rule) error {
    90  	if stn.Interface == "" {
    91  		return kvs.NewInvalidValueError(ErrSTNWithoutInterface, "interface")
    92  	}
    93  	if stn.IpAddress == "" {
    94  		return kvs.NewInvalidValueError(ErrSTNWithoutIPAddress, "ip_address")
    95  	}
    96  	return nil
    97  }
    98  
    99  // Create adds new STN rule.
   100  func (d *STNDescriptor) Create(key string, stn *stn.Rule) (metadata interface{}, err error) {
   101  	// add STN rule
   102  	err = d.stnHandler.AddSTNRule(stn)
   103  	if err != nil {
   104  		d.log.Error(err)
   105  	}
   106  	return nil, err
   107  }
   108  
   109  // Delete removes VPP STN rule.
   110  func (d *STNDescriptor) Delete(key string, stn *stn.Rule, metadata interface{}) error {
   111  	err := d.stnHandler.DeleteSTNRule(stn)
   112  	if err != nil {
   113  		d.log.Error(err)
   114  	}
   115  	return err
   116  }
   117  
   118  // Dependencies for STN rule are represented by interface
   119  func (d *STNDescriptor) Dependencies(key string, stn *stn.Rule) (dependencies []kvs.Dependency) {
   120  	dependencies = append(dependencies, kvs.Dependency{
   121  		Label: stnInterfaceDep,
   122  		Key:   interfaces.InterfaceKey(stn.Interface),
   123  	})
   124  	return dependencies
   125  }
   126  
   127  // Retrieve returns all configured VPP STN rules.
   128  func (d *STNDescriptor) Retrieve(correlate []adapter.STNKVWithMetadata) (retrieved []adapter.STNKVWithMetadata, err error) {
   129  	stnRules, err := d.stnHandler.DumpSTNRules()
   130  	if err != nil {
   131  		d.log.Error(err)
   132  		return retrieved, err
   133  	}
   134  	for _, stnRule := range stnRules {
   135  		retrieved = append(retrieved, adapter.STNKVWithMetadata{
   136  			Key:    models.Key(stnRule.Rule), //stn.Key(stnRule.Rule.Interface, stnRule.Rule.IpAddress),
   137  			Value:  stnRule.Rule,
   138  			Origin: kvs.FromNB, // all STN rules are configured from NB
   139  		})
   140  	}
   141  
   142  	return retrieved, nil
   143  }