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

     1  package descriptor
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/pkg/errors"
     7  
     8  	"go.ligato.io/vpp-agent/v3/plugins/vpp"
     9  
    10  	"go.ligato.io/vpp-agent/v3/pkg/models"
    11  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    12  	nslinuxcalls "go.ligato.io/vpp-agent/v3/plugins/linux/nsplugin/linuxcalls"
    13  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/descriptor/adapter"
    14  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx"
    15  	"go.ligato.io/vpp-agent/v3/proto/ligato/netalloc"
    16  	interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    17  )
    18  
    19  // Create creates a VPP interface.
    20  func (d *InterfaceDescriptor) Create(key string, intf *interfaces.Interface) (metadata *ifaceidx.IfaceMetadata, err error) {
    21  	var ifIdx uint32
    22  	var tapHostIfName string
    23  
    24  	ctx := context.TODO()
    25  
    26  	// create the interface of the given type
    27  	switch intf.Type {
    28  	case interfaces.Interface_TAP:
    29  		tapCfg := getTapConfig(intf)
    30  		tapHostIfName = tapCfg.HostIfName
    31  		ifIdx, err = d.ifHandler.AddTapInterface(intf.Name, tapCfg)
    32  		if err != nil {
    33  			d.log.Error(err)
    34  			return nil, err
    35  		}
    36  
    37  		// TAP hardening: verify that the Linux side was created
    38  		if d.linuxIfHandler != nil && d.nsPlugin != nil {
    39  			// first, move to the default namespace and lock the thread
    40  			nsCtx := nslinuxcalls.NewNamespaceMgmtCtx()
    41  			revert, err := d.nsPlugin.SwitchToNamespace(nsCtx, nil)
    42  			if err != nil {
    43  				d.log.Error(err)
    44  				return nil, err
    45  			}
    46  			exists, err := d.linuxIfHandler.InterfaceExists(tapHostIfName)
    47  			revert()
    48  			if err != nil {
    49  				d.log.Error(err)
    50  				return nil, err
    51  			}
    52  			if !exists {
    53  				err = errors.Errorf("failed to create the Linux side (%s) of the TAP interface %s", tapHostIfName, intf.Name)
    54  				d.log.Error(err)
    55  				return nil, err
    56  			}
    57  		}
    58  
    59  	case interfaces.Interface_MEMIF:
    60  		var socketID uint32
    61  		if socketID, err = d.resolveMemifSocketFilename(intf.GetMemif()); err != nil {
    62  			d.log.Error(err)
    63  			return nil, err
    64  		}
    65  		ifIdx, err = d.ifHandler.AddMemifInterface(ctx, intf.Name, intf.GetMemif(), socketID)
    66  		if err != nil {
    67  			err := errors.WithMessagef(err, "adding memif interface %s (socketID: %d) failed", intf.Name, socketID)
    68  			d.log.Error(err)
    69  			return nil, err
    70  		}
    71  
    72  	case interfaces.Interface_VXLAN_TUNNEL:
    73  		var multicastIfIdx uint32
    74  		multicastIf := intf.GetVxlan().GetMulticast()
    75  		if multicastIf != "" {
    76  			multicastMeta, found := d.intfIndex.LookupByName(multicastIf)
    77  			if !found {
    78  				err = errors.Errorf("failed to find multicast interface %s referenced by VXLAN %s",
    79  					multicastIf, intf.Name)
    80  				d.log.Error(err)
    81  				return nil, err
    82  			}
    83  			multicastIfIdx = multicastMeta.SwIfIndex
    84  		} else {
    85  			// not a multicast tunnel
    86  			multicastIfIdx = 0xFFFFFFFF
    87  		}
    88  
    89  		if intf.GetVxlan().Gpe == nil {
    90  			ifIdx, err = d.ifHandler.AddVxLanTunnel(intf.Name, intf.GetVrf(), multicastIfIdx, intf.GetVxlan())
    91  		} else {
    92  			ifIdx, err = d.ifHandler.AddVxLanGpeTunnel(intf.Name, intf.GetVrf(), multicastIfIdx, intf.GetVxlan())
    93  		}
    94  		if err != nil {
    95  			d.log.Error(err)
    96  			return nil, err
    97  		}
    98  
    99  	case interfaces.Interface_SOFTWARE_LOOPBACK:
   100  		ifIdx, err = d.ifHandler.AddLoopbackInterface(intf.Name)
   101  		if err != nil {
   102  			d.log.Error(err)
   103  			return nil, err
   104  		}
   105  
   106  	case interfaces.Interface_DPDK:
   107  		var found bool
   108  		ifIdx, found = d.ethernetIfs[intf.Name]
   109  		if !found {
   110  			err = errors.Errorf("failed to find physical interface %s", intf.Name)
   111  			d.log.Error(err)
   112  			return nil, err
   113  		}
   114  
   115  	case interfaces.Interface_AF_PACKET:
   116  		targetHostIfName, err := d.getAfPacketTargetHostIfName(intf.GetAfpacket())
   117  		if err != nil {
   118  			d.log.Error(err)
   119  			return nil, err
   120  		}
   121  		ifIdx, err = d.ifHandler.AddAfPacketInterface(intf.Name, intf.GetPhysAddress(), targetHostIfName)
   122  		if err != nil {
   123  			d.log.Error(err)
   124  			return nil, err
   125  		}
   126  	case interfaces.Interface_IPSEC_TUNNEL:
   127  		ifIdx, err = d.ifHandler.AddIPSecTunnelInterface(ctx, intf.Name, intf.GetIpsec())
   128  		if err != nil {
   129  			d.log.Error(err)
   130  			return nil, err
   131  		}
   132  	case interfaces.Interface_WIREGUARD_TUNNEL:
   133  		ifIdx, err = d.ifHandler.AddWireguardTunnel(intf.Name, intf.GetWireguard())
   134  		if err != nil {
   135  			d.log.Error(err)
   136  			return nil, err
   137  		}
   138  	case interfaces.Interface_SUB_INTERFACE:
   139  		sub := intf.GetSub()
   140  		parentMeta, found := d.intfIndex.LookupByName(sub.GetParentName())
   141  		if !found {
   142  			err = errors.Errorf("unable to find parent interface %s referenced by sub interface %s",
   143  				sub.GetParentName(), intf.Name)
   144  			d.log.Error(err)
   145  			return nil, err
   146  		}
   147  		ifIdx, err = d.ifHandler.CreateSubif(parentMeta.SwIfIndex, sub.GetSubId())
   148  		if err != nil {
   149  			d.log.Error(err)
   150  			return nil, err
   151  		}
   152  		err = d.ifHandler.SetInterfaceTag(intf.Name, ifIdx)
   153  		if err != nil {
   154  			d.log.Error(err)
   155  			return nil, err
   156  		}
   157  	case interfaces.Interface_VMXNET3_INTERFACE:
   158  		ifIdx, err = d.ifHandler.AddVmxNet3(intf.Name, intf.GetVmxNet3())
   159  		if err != nil {
   160  			d.log.Error(err)
   161  			return nil, err
   162  		}
   163  	case interfaces.Interface_BOND_INTERFACE:
   164  		ifIdx, err = d.ifHandler.AddBondInterface(intf.Name, intf.PhysAddress, intf.GetBond())
   165  		if err != nil {
   166  			d.log.Error(err)
   167  			return nil, err
   168  		}
   169  		d.bondIDs[intf.GetBond().GetId()] = intf.GetName()
   170  
   171  	case interfaces.Interface_GRE_TUNNEL:
   172  		ifIdx, err = d.ifHandler.AddGreTunnel(intf.Name, intf.GetGre())
   173  		if err != nil {
   174  			d.log.Error(err)
   175  			return nil, err
   176  		}
   177  
   178  	case interfaces.Interface_GTPU_TUNNEL:
   179  		var multicastIfIdx uint32
   180  		multicastIf := intf.GetGtpu().GetMulticast()
   181  		if multicastIf != "" {
   182  			multicastMeta, found := d.intfIndex.LookupByName(multicastIf)
   183  			if !found {
   184  				err = errors.Errorf("failed to find multicast interface %s referenced by GTPU %s",
   185  					multicastIf, intf.Name)
   186  				d.log.Error(err)
   187  				return nil, err
   188  			}
   189  			multicastIfIdx = multicastMeta.SwIfIndex
   190  		} else {
   191  			// not a multicast tunnel
   192  			multicastIfIdx = 0xFFFFFFFF
   193  		}
   194  
   195  		ifIdx, err = d.ifHandler.AddGtpuTunnel(intf.Name, intf.GetGtpu(), multicastIfIdx)
   196  		if err != nil {
   197  			d.log.Error(err)
   198  			return nil, err
   199  		}
   200  
   201  	case interfaces.Interface_IPIP_TUNNEL:
   202  		ifIdx, err = d.ifHandler.AddIpipTunnel(intf.Name, intf.GetVrf(), intf.GetIpip())
   203  		if err != nil {
   204  			d.log.Error(err)
   205  			return nil, err
   206  		}
   207  
   208  	case interfaces.Interface_RDMA:
   209  		ifIdx, err = d.ifHandler.AddRdmaInterface(ctx, intf.Name, intf.GetRdma())
   210  		if err != nil {
   211  			d.log.Error(err)
   212  			return nil, err
   213  		}
   214  	}
   215  
   216  	// MAC address. Note: physical interfaces cannot have the MAC address changed. The bond interface uses its own
   217  	// binary API call to set MAC address.
   218  	if intf.GetPhysAddress() != "" &&
   219  		intf.GetType() != interfaces.Interface_AF_PACKET &&
   220  		intf.GetType() != interfaces.Interface_DPDK &&
   221  		intf.GetType() != interfaces.Interface_BOND_INTERFACE {
   222  		if err = d.ifHandler.SetInterfaceMac(ifIdx, intf.GetPhysAddress()); err != nil {
   223  			err = errors.Errorf("failed to set MAC address %s to interface %s: %v",
   224  				intf.GetPhysAddress(), intf.Name, err)
   225  			d.log.Error(err)
   226  			return nil, err
   227  		}
   228  	}
   229  
   230  	// configure MTU. Prefer value in the interface config, otherwise set the plugin-wide
   231  	// default value if provided.
   232  	if ifaceSupportsSetMTU(intf) {
   233  		mtuToConfigure := intf.Mtu
   234  		if mtuToConfigure == 0 && d.defaultMtu != 0 {
   235  			mtuToConfigure = d.defaultMtu
   236  		}
   237  		if mtuToConfigure != 0 {
   238  			if err = d.ifHandler.SetInterfaceMtu(ifIdx, mtuToConfigure); err != nil {
   239  				err = errors.Errorf("failed to set MTU %d to interface %s: %v", mtuToConfigure, intf.Name, err)
   240  				d.log.Error(err)
   241  				return nil, err
   242  			}
   243  		}
   244  	}
   245  
   246  	// set vlan tag rewrite
   247  	if intf.Type == interfaces.Interface_SUB_INTERFACE && intf.GetSub().TagRwOption != interfaces.SubInterface_DISABLED {
   248  		if err := d.ifHandler.SetVLanTagRewrite(ifIdx, intf.GetSub()); err != nil {
   249  			d.log.Error(err)
   250  			return nil, err
   251  		}
   252  	}
   253  
   254  	// set interface up if enabled
   255  	if intf.Enabled {
   256  		if err = d.ifHandler.InterfaceAdminUp(ctx, ifIdx); err != nil {
   257  			err = errors.Errorf("failed to set interface %s up: %v", intf.Name, err)
   258  			d.log.Error(err)
   259  			return nil, err
   260  		}
   261  	}
   262  
   263  	// fill the metadata
   264  	metadata = &ifaceidx.IfaceMetadata{
   265  		SwIfIndex:     ifIdx,
   266  		Vrf:           intf.Vrf,
   267  		IPAddresses:   intf.GetIpAddresses(),
   268  		TAPHostIfName: tapHostIfName,
   269  	}
   270  	return metadata, nil
   271  }
   272  
   273  // Delete removes VPP interface.
   274  func (d *InterfaceDescriptor) Delete(key string, intf *interfaces.Interface, metadata *ifaceidx.IfaceMetadata) error {
   275  	var err error
   276  	ifIdx := metadata.SwIfIndex
   277  
   278  	ctx := context.TODO()
   279  
   280  	// set interface to ADMIN_DOWN unless the type is AF_PACKET_INTERFACE
   281  	if intf.Type != interfaces.Interface_AF_PACKET {
   282  		if err := d.ifHandler.InterfaceAdminDown(ctx, ifIdx); err != nil {
   283  			err = errors.Errorf("failed to set interface %s down: %v", intf.Name, err)
   284  			d.log.Error(err)
   285  			return err
   286  		}
   287  	}
   288  
   289  	// remove the interface
   290  	switch intf.Type {
   291  	case interfaces.Interface_TAP:
   292  		err = d.ifHandler.DeleteTapInterface(intf.Name, ifIdx, intf.GetTap().GetVersion())
   293  	case interfaces.Interface_MEMIF:
   294  		err = d.ifHandler.DeleteMemifInterface(context.TODO(), intf.Name, ifIdx)
   295  	case interfaces.Interface_VXLAN_TUNNEL:
   296  		if intf.GetVxlan().Gpe == nil {
   297  			err = d.ifHandler.DeleteVxLanTunnel(intf.Name, ifIdx, intf.Vrf, intf.GetVxlan())
   298  		} else {
   299  			err = d.ifHandler.DeleteVxLanGpeTunnel(intf.Name, intf.GetVxlan())
   300  		}
   301  	case interfaces.Interface_SOFTWARE_LOOPBACK:
   302  		err = d.ifHandler.DeleteLoopbackInterface(intf.Name, ifIdx)
   303  	case interfaces.Interface_DPDK:
   304  		d.log.Debugf("Interface %s removal skipped: cannot remove (blacklist) physical interface", intf.Name) // Not an error
   305  		return nil
   306  	case interfaces.Interface_AF_PACKET:
   307  		var targetHostIfName string
   308  		targetHostIfName, err = d.getAfPacketTargetHostIfName(intf.GetAfpacket())
   309  		if err == nil {
   310  			err = d.ifHandler.DeleteAfPacketInterface(intf.Name, ifIdx, targetHostIfName)
   311  		}
   312  	case interfaces.Interface_IPSEC_TUNNEL:
   313  		err = d.ifHandler.DeleteIPSecTunnelInterface(ctx, intf.Name, ifIdx, intf.GetIpsec())
   314  	case interfaces.Interface_WIREGUARD_TUNNEL:
   315  		err = d.ifHandler.DeleteWireguardTunnel(intf.Name, ifIdx)
   316  	case interfaces.Interface_SUB_INTERFACE:
   317  		err = d.ifHandler.DeleteSubif(ifIdx)
   318  	case interfaces.Interface_VMXNET3_INTERFACE:
   319  		err = d.ifHandler.DeleteVmxNet3(intf.Name, ifIdx)
   320  	case interfaces.Interface_BOND_INTERFACE:
   321  		err = d.ifHandler.DeleteBondInterface(intf.Name, ifIdx)
   322  		delete(d.bondIDs, intf.GetBond().GetId())
   323  	case interfaces.Interface_GRE_TUNNEL:
   324  		_, err = d.ifHandler.DelGreTunnel(intf.Name, intf.GetGre())
   325  	case interfaces.Interface_GTPU_TUNNEL:
   326  		err = d.ifHandler.DelGtpuTunnel(intf.Name, intf.GetGtpu())
   327  	case interfaces.Interface_IPIP_TUNNEL:
   328  		err = d.ifHandler.DelIpipTunnel(intf.Name, ifIdx)
   329  	case interfaces.Interface_RDMA:
   330  		err = d.ifHandler.DeleteRdmaInterface(ctx, intf.Name, ifIdx)
   331  	}
   332  	if err != nil {
   333  		err = errors.Errorf("failed to remove interface %s, index %d: %v", intf.Name, ifIdx, err)
   334  		d.log.Error(err)
   335  		return err
   336  	}
   337  
   338  	return nil
   339  }
   340  
   341  // Update is able to change Type-unspecific attributes.
   342  func (d *InterfaceDescriptor) Update(key string, oldIntf, newIntf *interfaces.Interface, oldMetadata *ifaceidx.IfaceMetadata) (newMetadata *ifaceidx.IfaceMetadata, err error) {
   343  	ifIdx := oldMetadata.SwIfIndex
   344  
   345  	ctx := context.TODO()
   346  
   347  	// admin status
   348  	if newIntf.Enabled != oldIntf.Enabled {
   349  		if newIntf.Enabled {
   350  			if err = d.ifHandler.InterfaceAdminUp(ctx, ifIdx); err != nil {
   351  				err = errors.Errorf("failed to set interface %s up: %v", newIntf.Name, err)
   352  				d.log.Error(err)
   353  				return oldMetadata, err
   354  			}
   355  		} else {
   356  			if err = d.ifHandler.InterfaceAdminDown(ctx, ifIdx); err != nil {
   357  				err = errors.Errorf("failed to set interface %s down: %v", newIntf.Name, err)
   358  				d.log.Error(err)
   359  				return oldMetadata, err
   360  			}
   361  		}
   362  	}
   363  
   364  	// configure new MAC address if set (and only if it was changed and only for supported interface type)
   365  	if newIntf.PhysAddress != "" &&
   366  		newIntf.PhysAddress != oldIntf.PhysAddress &&
   367  		oldIntf.Type != interfaces.Interface_AF_PACKET &&
   368  		oldIntf.Type != interfaces.Interface_DPDK &&
   369  		oldIntf.Type != interfaces.Interface_BOND_INTERFACE {
   370  		if err := d.ifHandler.SetInterfaceMac(ifIdx, newIntf.PhysAddress); err != nil {
   371  			err = errors.Errorf("setting interface %s MAC address %s failed: %v",
   372  				newIntf.Name, newIntf.PhysAddress, err)
   373  			d.log.Error(err)
   374  			return oldMetadata, err
   375  		}
   376  	}
   377  
   378  	// update MTU (except VxLan, IPSec)
   379  	if ifaceSupportsSetMTU(newIntf) {
   380  		if newIntf.Mtu != 0 && newIntf.Mtu != oldIntf.Mtu {
   381  			if err := d.ifHandler.SetInterfaceMtu(ifIdx, newIntf.Mtu); err != nil {
   382  				err = errors.Errorf("failed to set MTU to interface %s: %v", newIntf.Name, err)
   383  				d.log.Error(err)
   384  				return oldMetadata, err
   385  			}
   386  		} else if newIntf.Mtu == 0 && d.defaultMtu != 0 {
   387  			if err := d.ifHandler.SetInterfaceMtu(ifIdx, d.defaultMtu); err != nil {
   388  				err = errors.Errorf("failed to set MTU to interface %s: %v", newIntf.Name, err)
   389  				d.log.Error(err)
   390  				return oldMetadata, err
   391  			}
   392  		}
   393  	}
   394  
   395  	// update vlan tag rewrite
   396  	if newIntf.Type == interfaces.Interface_SUB_INTERFACE {
   397  		oldSub, newSub := oldIntf.GetSub(), newIntf.GetSub()
   398  		if oldSub.TagRwOption != newSub.TagRwOption ||
   399  			oldSub.PushDot1Q != newSub.PushDot1Q ||
   400  			oldSub.Tag1 != newSub.Tag1 ||
   401  			oldSub.Tag2 != newSub.Tag2 {
   402  			if err := d.ifHandler.SetVLanTagRewrite(ifIdx, newSub); err != nil {
   403  				d.log.Error(err)
   404  				return nil, err
   405  			}
   406  		}
   407  	}
   408  
   409  	// update metadata
   410  	oldMetadata.IPAddresses = newIntf.IpAddresses
   411  	oldMetadata.Vrf = newIntf.Vrf
   412  	return oldMetadata, nil
   413  }
   414  
   415  // Retrieve returns all configured VPP interfaces.
   416  func (d *InterfaceDescriptor) Retrieve(correlate []adapter.InterfaceKVWithMetadata) (retrieved []adapter.InterfaceKVWithMetadata, err error) {
   417  	// TODO: context should come as first parameter for all descriptor methods
   418  	ctx := context.TODO()
   419  
   420  	// make sure that any checks on the Linux side
   421  	// are done in the default namespace with locked thread
   422  	if d.nsPlugin != nil {
   423  		nsCtx := nslinuxcalls.NewNamespaceMgmtCtx()
   424  		revert, err := d.nsPlugin.SwitchToNamespace(nsCtx, nil)
   425  		if err == nil {
   426  			defer revert()
   427  		}
   428  	}
   429  
   430  	// convert interfaces for correlation into a map
   431  	// interface logical name -> interface config (as expected by correlate)
   432  	ifCfg := make(map[string]*interfaces.Interface)
   433  	for _, kv := range correlate {
   434  		ifCfg[kv.Value.Name] = kv.Value
   435  	}
   436  
   437  	// refresh the map of memif socket IDs
   438  	d.memifSocketToID, err = d.ifHandler.DumpMemifSocketDetails(ctx)
   439  	if errors.Is(err, vpp.ErrPluginDisabled) {
   440  		d.log.Debugf("cannot dump memif socket details: %v", err)
   441  	} else if err != nil {
   442  		return retrieved, errors.Errorf("failed to dump memif socket details: %v", err)
   443  	} else {
   444  		for socketPath, socketID := range d.memifSocketToID {
   445  			if socketID == 0 {
   446  				d.defaultMemifSocketPath = socketPath
   447  			}
   448  		}
   449  	}
   450  
   451  	// clear the map of ethernet interfaces and bond IDs
   452  	d.ethernetIfs = make(map[string]uint32)
   453  	d.bondIDs = make(map[uint32]string)
   454  
   455  	// dump current state of VPP interfaces
   456  	vppIfs, err := d.ifHandler.DumpInterfaces(ctx)
   457  	if err != nil {
   458  		err = errors.Errorf("failed to dump interfaces: %v", err)
   459  		d.log.Error(err)
   460  		return retrieved, err
   461  	}
   462  
   463  	for ifIdx, intf := range vppIfs {
   464  		origin := kvs.FromNB
   465  		if ifIdx == 0 {
   466  			// local0 is created automatically
   467  			origin = kvs.FromSB
   468  		}
   469  		if intf.Interface.Type == interfaces.Interface_DPDK {
   470  			d.ethernetIfs[intf.Interface.Name] = ifIdx
   471  			if !intf.Interface.Enabled && len(intf.Interface.IpAddresses) == 0 {
   472  				// unconfigured physical interface => skip (but add entry to d.ethernetIfs)
   473  				continue
   474  			}
   475  		}
   476  		if intf.Interface.Type == interfaces.Interface_BOND_INTERFACE {
   477  			d.bondIDs[intf.Interface.GetBond().GetId()] = intf.Interface.Name
   478  		}
   479  
   480  		// get TAP host interface name
   481  		var tapHostIfName string
   482  		if intf.Interface.Type == interfaces.Interface_TAP {
   483  			tapHostIfName = intf.Interface.GetTap().GetHostIfName()
   484  			if generateTAPHostName(intf.Interface.Name) == tapHostIfName {
   485  				// if a generated TAP host name matches the dumped one, there is a premise
   486  				// that the retrieved value was generated before and the original host name
   487  				// was empty.
   488  				intf.Interface.GetTap().HostIfName = ""
   489  			}
   490  		}
   491  
   492  		// correlate attributes that cannot be dumped
   493  		if expCfg, hasExpCfg := ifCfg[intf.Interface.Name]; hasExpCfg {
   494  			if expCfg.Type == interfaces.Interface_TAP && intf.Interface.GetTap() != nil {
   495  				intf.Interface.GetTap().ToMicroservice = expCfg.GetTap().GetToMicroservice()
   496  				intf.Interface.GetTap().RxRingSize = expCfg.GetTap().GetRxRingSize()
   497  				intf.Interface.GetTap().TxRingSize = expCfg.GetTap().GetTxRingSize()
   498  				// (seemingly uninitialized section of memory is returned)
   499  				if intf.Interface.GetTap().GetVersion() == 2 {
   500  					intf.Interface.GetTap().HostIfName = expCfg.GetTap().GetHostIfName()
   501  					// set host name in metadata from NB data if defined
   502  					if intf.Interface.GetTap().HostIfName != "" {
   503  						tapHostIfName = expCfg.GetTap().GetHostIfName()
   504  					}
   505  				}
   506  			}
   507  			if expCfg.Type == interfaces.Interface_MEMIF && intf.Interface.GetMemif() != nil {
   508  				intf.Interface.GetMemif().Secret = expCfg.GetMemif().GetSecret()
   509  				intf.Interface.GetMemif().RxQueues = expCfg.GetMemif().GetRxQueues()
   510  				intf.Interface.GetMemif().TxQueues = expCfg.GetMemif().GetTxQueues()
   511  				// if memif is not connected yet, ring-size and buffer-size are
   512  				// 1 and 0, respectively
   513  				if intf.Interface.GetMemif().GetRingSize() == 1 {
   514  					intf.Interface.GetMemif().RingSize = expCfg.GetMemif().GetRingSize()
   515  				}
   516  				if intf.Interface.GetMemif().GetBufferSize() == 0 {
   517  					intf.Interface.GetMemif().BufferSize = expCfg.GetMemif().GetBufferSize()
   518  				}
   519  			}
   520  			//nolint:staticcheck
   521  			if expCfg.Type == interfaces.Interface_AF_PACKET && intf.Interface.GetAfpacket() != nil {
   522  				hostIfName, err := d.getAfPacketTargetHostIfName(expCfg.GetAfpacket())
   523  				if err == nil && hostIfName == intf.Interface.GetAfpacket().GetHostIfName() {
   524  					intf.Interface.GetAfpacket().HostIfName = expCfg.GetAfpacket().GetHostIfName()
   525  					intf.Interface.GetAfpacket().LinuxInterface = expCfg.GetAfpacket().GetLinuxInterface()
   526  				}
   527  			}
   528  
   529  			// remove rx-placement entries for queues with configuration not defined by NB
   530  			rxPlacementDump := intf.Interface.GetRxPlacements()
   531  			rxPlacementCfg := expCfg.GetRxPlacements()
   532  			for i := 0; i < len(rxPlacementDump); {
   533  				queue := rxPlacementDump[i].Queue
   534  				found := false
   535  				for j := 0; j < len(rxPlacementCfg); j++ {
   536  					if rxPlacementCfg[j].Queue == queue {
   537  						found = true
   538  						break
   539  					}
   540  				}
   541  				if found {
   542  					i++
   543  				} else {
   544  					rxPlacementDump = append(rxPlacementDump[:i], rxPlacementDump[i+1:]...)
   545  				}
   546  			}
   547  			intf.Interface.RxPlacements = rxPlacementDump
   548  
   549  			// remove rx-mode from the dump if it is not configured by NB
   550  			if len(expCfg.GetRxModes()) == 0 {
   551  				intf.Interface.RxModes = []*interfaces.Interface_RxMode{}
   552  			}
   553  
   554  			// correlate references to allocated IP addresses
   555  			intf.Interface.IpAddresses = d.addrAlloc.CorrelateRetrievedIPs(
   556  				expCfg.IpAddresses, intf.Interface.IpAddresses,
   557  				intf.Interface.Name, netalloc.IPAddressForm_ADDR_WITH_MASK)
   558  		}
   559  
   560  		// verify links between VPP and Linux side
   561  		if d.linuxIfPlugin != nil && d.linuxIfHandler != nil && d.nsPlugin != nil {
   562  			if intf.Interface.Type == interfaces.Interface_AF_PACKET {
   563  				var exists bool
   564  				hostIfName, err := d.getAfPacketTargetHostIfName(intf.Interface.GetAfpacket())
   565  				if err == nil {
   566  					exists, _ = d.linuxIfHandler.InterfaceExists(hostIfName)
   567  				}
   568  				if err != nil || !exists {
   569  					// the Linux interface that the AF-Packet is attached to does not exist
   570  					// - append special suffix that will make this interface unwanted
   571  					intf.Interface.Name += afPacketMissingAttachedIfSuffix
   572  				}
   573  			}
   574  			if intf.Interface.Type == interfaces.Interface_TAP {
   575  				exists, _ := d.linuxIfHandler.InterfaceExists(tapHostIfName)
   576  				if !exists {
   577  					// check if it was "stolen" by the Linux plugin
   578  					_, _, exists = d.linuxIfPlugin.GetInterfaceIndex().LookupByVPPTap(
   579  						intf.Interface.Name)
   580  				}
   581  				if !exists {
   582  					// the Linux side of the TAP interface side was not found
   583  					// - append special suffix that will make this interface unwanted
   584  					intf.Interface.Name += tapMissingLinuxSideSuffix
   585  				}
   586  			}
   587  		}
   588  
   589  		// add interface record into the dump
   590  		metadata := &ifaceidx.IfaceMetadata{
   591  			SwIfIndex:     ifIdx,
   592  			Vrf:           intf.Interface.Vrf,
   593  			IPAddresses:   intf.Interface.IpAddresses,
   594  			TAPHostIfName: tapHostIfName,
   595  			InternalName:  intf.Meta.InternalName,
   596  			DevType:       intf.Meta.DevType,
   597  		}
   598  		retrieved = append(retrieved, adapter.InterfaceKVWithMetadata{
   599  			Key:      models.Key(intf.Interface),
   600  			Value:    intf.Interface,
   601  			Metadata: metadata,
   602  			Origin:   origin,
   603  		})
   604  
   605  	}
   606  
   607  	return retrieved, nil
   608  }
   609  
   610  func ifaceSupportsSetMTU(intf *interfaces.Interface) bool {
   611  	switch intf.Type {
   612  	case interfaces.Interface_VXLAN_TUNNEL,
   613  		interfaces.Interface_IPSEC_TUNNEL,
   614  		interfaces.Interface_WIREGUARD_TUNNEL,
   615  		interfaces.Interface_SUB_INTERFACE:
   616  		// MTU not supported
   617  		return false
   618  	}
   619  	return true
   620  }