go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ifplugin/descriptor/interface_vrf.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  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    23  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx"
    24  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls"
    25  	interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    26  	l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3"
    27  )
    28  
    29  const (
    30  	// InterfaceVrfDescriptorName is the name of the descriptor for assigning
    31  	// VPP interface into VRF table.
    32  	InterfaceVrfDescriptorName = "vpp-interface-vrf"
    33  
    34  	// dependency labels
    35  	vrfV4Dep        = "vrf-table-v4-exists"
    36  	vrfV6Dep        = "vrf-table-v6-exists"
    37  	inheritedVrfDep = "numbered-interface-assigned-to-VRF"
    38  )
    39  
    40  // InterfaceVrfDescriptor (un)assigns VPP interface to IPv4/IPv6 VRF table.
    41  type InterfaceVrfDescriptor struct {
    42  	log       logging.Logger
    43  	ifHandler vppcalls.InterfaceVppAPI
    44  	ifIndex   ifaceidx.IfaceMetadataIndex
    45  }
    46  
    47  // NewInterfaceVrfDescriptor creates a new instance of InterfaceVrfDescriptor.
    48  func NewInterfaceVrfDescriptor(ifHandler vppcalls.InterfaceVppAPI, ifIndex ifaceidx.IfaceMetadataIndex,
    49  	log logging.PluginLogger) *kvs.KVDescriptor {
    50  
    51  	descrCtx := &InterfaceVrfDescriptor{
    52  		ifHandler: ifHandler,
    53  		ifIndex:   ifIndex,
    54  		log:       log.NewLogger("interface-vrf-descriptor"),
    55  	}
    56  	return &kvs.KVDescriptor{
    57  		Name:         InterfaceVrfDescriptorName,
    58  		KeySelector:  descrCtx.IsInterfaceVrfKey,
    59  		Create:       descrCtx.Create,
    60  		Delete:       descrCtx.Delete,
    61  		Dependencies: descrCtx.Dependencies,
    62  	}
    63  }
    64  
    65  // IsInterfaceVrfKey returns true if the key represents assignment of an interface
    66  // into a VRF table.
    67  func (d *InterfaceVrfDescriptor) IsInterfaceVrfKey(key string) bool {
    68  	_, _, _, _, isIfaceVrfKey := interfaces.ParseInterfaceVrfKey(key)
    69  	if isIfaceVrfKey {
    70  		return true
    71  	}
    72  	_, _, isIfaceInherVrfKey := interfaces.ParseInterfaceInheritedVrfKey(key)
    73  	return isIfaceInherVrfKey
    74  }
    75  
    76  // Create puts interface into the given VRF table.
    77  func (d *InterfaceVrfDescriptor) Create(key string, emptyVal proto.Message) (metadata kvs.Metadata, err error) {
    78  	swIfIndex, vrf, inheritedVrf, ipv4, ipv6, err := d.getParametersFromKey(key)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	// unnumbered interfaces (inherited VRF) should not be explicitly set to VRF=0 (probably bug in VPP)
    84  
    85  	if (!inheritedVrf || vrf > 0) && ipv4 {
    86  		err = d.ifHandler.SetInterfaceVrf(swIfIndex, uint32(vrf))
    87  		if err != nil {
    88  			d.log.Error(err)
    89  			return nil, err
    90  		}
    91  	}
    92  	if (!inheritedVrf || vrf > 0) && ipv6 {
    93  		err = d.ifHandler.SetInterfaceVrfIPv6(swIfIndex, uint32(vrf))
    94  		if err != nil {
    95  			d.log.Error(err)
    96  			return nil, err
    97  		}
    98  	}
    99  	return nil, nil
   100  }
   101  
   102  // Delete removes interface from the given VRF table.
   103  func (d *InterfaceVrfDescriptor) Delete(key string, emptyVal proto.Message, metadata kvs.Metadata) (err error) {
   104  	swIfIndex, vrf, inheritedVrf, ipv4, ipv6, err := d.getParametersFromKey(key)
   105  	if err != nil {
   106  		return err
   107  	}
   108  
   109  	if !inheritedVrf && vrf > 0 && ipv4 {
   110  		err = d.ifHandler.SetInterfaceVrf(swIfIndex, uint32(0))
   111  		if err != nil {
   112  			d.log.Error(err)
   113  			return err
   114  		}
   115  	}
   116  	if !inheritedVrf && vrf > 0 && ipv6 {
   117  		err = d.ifHandler.SetInterfaceVrfIPv6(swIfIndex, uint32(0))
   118  		if err != nil {
   119  			d.log.Error(err)
   120  			return err
   121  		}
   122  	}
   123  	return nil
   124  }
   125  
   126  // Dependencies lists the target non-zero VRF as the only dependency.
   127  func (d *InterfaceVrfDescriptor) Dependencies(key string, emptyVal proto.Message) (deps []kvs.Dependency) {
   128  	if _, vrf, ipv4, ipv6, isIfaceVrfKey := interfaces.ParseInterfaceVrfKey(key); isIfaceVrfKey {
   129  		if vrf > 0 && ipv4 {
   130  			deps = append(deps, kvs.Dependency{
   131  				Label: vrfV4Dep,
   132  				Key:   l3.VrfTableKey(uint32(vrf), l3.VrfTable_IPV4),
   133  			})
   134  		}
   135  		if vrf > 0 && ipv6 {
   136  			deps = append(deps, kvs.Dependency{
   137  				Label: vrfV6Dep,
   138  				Key:   l3.VrfTableKey(uint32(vrf), l3.VrfTable_IPV6),
   139  			})
   140  		}
   141  		return deps
   142  	}
   143  
   144  	_, fromIface, _ := interfaces.ParseInterfaceInheritedVrfKey(key)
   145  	return []kvs.Dependency{
   146  		{
   147  			Label: inheritedVrfDep,
   148  			AnyOf: kvs.AnyOfDependency{
   149  				KeyPrefixes: []string{interfaces.InterfaceVrfKeyPrefix(fromIface)},
   150  			},
   151  		},
   152  	}
   153  }
   154  
   155  func (d *InterfaceVrfDescriptor) getParametersFromKey(key string) (swIfIndex, vrf uint32,
   156  	inheritedVrf bool, ipv4, ipv6 bool, err error) {
   157  
   158  	var (
   159  		isIfaceVrfKey    bool
   160  		vrfTableID       int
   161  		iface, fromIface string
   162  	)
   163  
   164  	iface, vrfTableID, ipv4, ipv6, isIfaceVrfKey = interfaces.ParseInterfaceVrfKey(key)
   165  	if !isIfaceVrfKey {
   166  		iface, fromIface, _ = interfaces.ParseInterfaceInheritedVrfKey(key)
   167  		fromIfaceMeta, found := d.ifIndex.LookupByName(fromIface)
   168  		if !found {
   169  			err = errors.Errorf("failed to find interface %s", iface)
   170  			d.log.Error(err)
   171  			return
   172  		}
   173  		vrfTableID = int(fromIfaceMeta.Vrf)
   174  		ipv4, ipv6 = getIPAddressVersions(fromIfaceMeta.IPAddresses)
   175  		inheritedVrf = true
   176  	}
   177  
   178  	ifMeta, found := d.ifIndex.LookupByName(iface)
   179  	if !found {
   180  		err = errors.Errorf("failed to find interface %s", iface)
   181  		d.log.Error(err)
   182  		return
   183  	}
   184  
   185  	swIfIndex = ifMeta.SwIfIndex
   186  	vrf = uint32(vrfTableID)
   187  	return
   188  }