go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/abfplugin/descriptor/abf_to_interface.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 descriptor
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"go.ligato.io/vpp-agent/v3/plugins/vpp/abfplugin/abfidx"
    21  	vpp_abf "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/abf"
    22  	vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    23  
    24  	"github.com/go-errors/errors"
    25  	"go.ligato.io/cn-infra/v2/logging"
    26  	"google.golang.org/protobuf/proto"
    27  
    28  	"go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    29  	"go.ligato.io/vpp-agent/v3/plugins/vpp/abfplugin/vppcalls"
    30  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin"
    31  )
    32  
    33  const (
    34  	// ABFToInterfaceDescriptorName is name for descriptor
    35  	ABFToInterfaceDescriptorName = "vpp-abf-to-interface"
    36  
    37  	// dependency labels
    38  	interfaceDep = "interface-exists"
    39  )
    40  
    41  // ABFToInterfaceDescriptor represents assignment of interface to ABF policy.
    42  type ABFToInterfaceDescriptor struct {
    43  	log        logging.Logger
    44  	abfHandler vppcalls.ABFVppAPI
    45  	abfIndex   abfidx.ABFMetadataIndex
    46  	ifPlugin   ifplugin.API
    47  }
    48  
    49  // NewABFToInterfaceDescriptor returns new ABFInterface descriptor
    50  func NewABFToInterfaceDescriptor(abfIndex abfidx.ABFMetadataIndex, abfHandler vppcalls.ABFVppAPI, ifPlugin ifplugin.API, log logging.PluginLogger) *api.KVDescriptor {
    51  	ctx := &ABFToInterfaceDescriptor{
    52  		log:        log,
    53  		abfHandler: abfHandler,
    54  		abfIndex:   abfIndex,
    55  		ifPlugin:   ifPlugin,
    56  	}
    57  	return &api.KVDescriptor{
    58  		Name:         ABFToInterfaceDescriptorName,
    59  		KeySelector:  ctx.IsABFInterfaceKey,
    60  		Create:       ctx.Create,
    61  		Delete:       ctx.Delete,
    62  		Dependencies: ctx.Dependencies,
    63  	}
    64  }
    65  
    66  // IsABFInterfaceKey returns true if the key is identifying ABF policy interface (derived value)
    67  func (d *ABFToInterfaceDescriptor) IsABFInterfaceKey(key string) bool {
    68  	_, _, isABFToInterfaceKey := vpp_abf.ParseToInterfaceKey(key)
    69  	return isABFToInterfaceKey
    70  }
    71  
    72  // Create binds interface to ABF.
    73  func (d *ABFToInterfaceDescriptor) Create(key string, emptyVal proto.Message) (metadata api.Metadata, err error) {
    74  	// validate and get all required values
    75  	isIPv6, abfIdx, ifIdx, priority, err := d.process(key)
    76  	if err != nil {
    77  		d.log.Error(err)
    78  		return nil, err
    79  	}
    80  
    81  	// attach interface to ABF policy
    82  	if isIPv6 {
    83  		return nil, d.abfHandler.AbfAttachInterfaceIPv6(abfIdx, ifIdx, priority)
    84  	}
    85  	return nil, d.abfHandler.AbfAttachInterfaceIPv4(abfIdx, ifIdx, priority)
    86  }
    87  
    88  // Delete unbinds interface from ABF.
    89  func (d *ABFToInterfaceDescriptor) Delete(key string, emptyVal proto.Message, metadata api.Metadata) (err error) {
    90  	// validate and get all required values
    91  	isIPv6, abfIdx, ifIdx, priority, err := d.process(key)
    92  	if err != nil {
    93  		d.log.Error(err)
    94  		return err
    95  	}
    96  
    97  	// detach interface to ABF policy
    98  	if isIPv6 {
    99  		return d.abfHandler.AbfDetachInterfaceIPv6(abfIdx, ifIdx, priority)
   100  	}
   101  	return d.abfHandler.AbfDetachInterfaceIPv4(abfIdx, ifIdx, priority)
   102  }
   103  
   104  // Dependencies lists the interface as the only dependency for the binding.
   105  func (d *ABFToInterfaceDescriptor) Dependencies(key string, emptyVal proto.Message) []api.Dependency {
   106  	_, ifName, _ := vpp_abf.ParseToInterfaceKey(key)
   107  	return []api.Dependency{
   108  		{
   109  			Label: interfaceDep,
   110  			Key:   vpp_interfaces.InterfaceKey(ifName),
   111  		},
   112  	}
   113  }
   114  
   115  // returns a bunch of values needed to attach/detach interface to/from ABF
   116  func (d *ABFToInterfaceDescriptor) process(key string) (isIPv6 bool, abfIdx, ifIdx, priority uint32, err error) {
   117  	// parse ABF and interface name
   118  	abfIndex, ifName, isValid := vpp_abf.ParseToInterfaceKey(key)
   119  	if !isValid {
   120  		err = fmt.Errorf("ABF to interface key %s is not valid", key)
   121  		return
   122  	}
   123  	// obtain ABF index
   124  	abfData, exists := d.abfIndex.LookupByName(abfIndex)
   125  	if !exists {
   126  		err = errors.Errorf("failed to obtain metadata for ABF %s", abfIndex)
   127  		return
   128  	}
   129  
   130  	// obtain interface index
   131  	ifData, exists := d.ifPlugin.GetInterfaceIndex().LookupByName(ifName)
   132  	if !exists {
   133  		err = errors.Errorf("failed to obtain metadata for interface %s", ifName)
   134  		return
   135  	}
   136  
   137  	// find other interface parameters from metadata
   138  	for _, attachedIf := range abfData.Attached {
   139  		if attachedIf.InputInterface == ifName {
   140  			isIPv6, priority = attachedIf.IsIpv6, attachedIf.Priority
   141  		}
   142  	}
   143  	return isIPv6, abfData.Index, ifData.SwIfIndex, priority, nil
   144  }