github.com/cilium/cilium@v1.16.2/pkg/datapath/connector/netkit.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package connector
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/vishvananda/netlink"
    10  
    11  	"github.com/cilium/cilium/api/v1/models"
    12  	"github.com/cilium/cilium/pkg/datapath/link"
    13  	"github.com/cilium/cilium/pkg/datapath/linux/sysctl"
    14  	"github.com/cilium/cilium/pkg/logging/logfields"
    15  	"github.com/cilium/cilium/pkg/netns"
    16  )
    17  
    18  // SetupNetkitRemoteNs renames the netdevice in the target namespace to the
    19  // provided dstIfName.
    20  func SetupNetkitRemoteNs(ns *netns.NetNS, srcIfName, dstIfName string) error {
    21  	return ns.Do(func() error {
    22  		err := link.Rename(srcIfName, dstIfName)
    23  		if err != nil {
    24  			return fmt.Errorf("failed to rename netkit from %q to %q: %w", srcIfName, dstIfName, err)
    25  		}
    26  		return nil
    27  	})
    28  }
    29  
    30  // SetupNetkit sets up the net interface, the temporary interface and fills up some
    31  // endpoint fields such as mac, NodeMac, ifIndex and ifName. Returns a pointer for the
    32  // created netkit, a pointer for the temporary link, the name of the temporary link
    33  // and error if something fails.
    34  func SetupNetkit(id string, mtu, groIPv6MaxSize, gsoIPv6MaxSize, groIPv4MaxSize, gsoIPv4MaxSize int, l2Mode bool, ep *models.EndpointChangeRequest, sysctl sysctl.Sysctl) (*netlink.Netkit, netlink.Link, string, error) {
    35  	if id == "" {
    36  		return nil, nil, "", fmt.Errorf("invalid: empty ID")
    37  	}
    38  
    39  	lxcIfName := Endpoint2IfName(id)
    40  	tmpIfName := Endpoint2TempIfName(id)
    41  
    42  	netkit, link, err := SetupNetkitWithNames(lxcIfName, tmpIfName, mtu,
    43  		groIPv6MaxSize, gsoIPv6MaxSize, groIPv4MaxSize, gsoIPv4MaxSize, l2Mode, ep, sysctl)
    44  	return netkit, link, tmpIfName, err
    45  }
    46  
    47  // SetupNetkitWithNames sets up the net interface, the peer interface and fills up some
    48  // endpoint fields such as mac, NodeMac, ifIndex and ifName. Returns a pointer for the
    49  // created netkit, a pointer for the peer link and error if something fails.
    50  func SetupNetkitWithNames(lxcIfName, peerIfName string, mtu, groIPv6MaxSize, gsoIPv6MaxSize, groIPv4MaxSize, gsoIPv4MaxSize int, l2Mode bool, ep *models.EndpointChangeRequest, sysctl sysctl.Sysctl) (*netlink.Netkit, netlink.Link, error) {
    51  	mode := netlink.NETKIT_MODE_L3
    52  	if l2Mode {
    53  		mode = netlink.NETKIT_MODE_L2
    54  	}
    55  	netkit := &netlink.Netkit{
    56  		LinkAttrs: netlink.LinkAttrs{
    57  			Name:   lxcIfName,
    58  			TxQLen: 1000,
    59  		},
    60  		Mode:       mode,
    61  		Policy:     netlink.NETKIT_POLICY_FORWARD,
    62  		PeerPolicy: netlink.NETKIT_POLICY_BLACKHOLE,
    63  	}
    64  	peerAttr := &netlink.LinkAttrs{
    65  		Name: peerIfName,
    66  	}
    67  	netkit.SetPeerAttrs(peerAttr)
    68  
    69  	err := netlink.LinkAdd(netkit)
    70  	if err != nil {
    71  		return nil, nil, fmt.Errorf("unable to create netkit pair: %w", err)
    72  	}
    73  	defer func() {
    74  		if err != nil {
    75  			if err = netlink.LinkDel(netkit); err != nil {
    76  				log.WithError(err).WithField(logfields.Netkit, netkit.Name).Warn("failed to clean up netkit")
    77  			}
    78  		}
    79  	}()
    80  
    81  	log.WithField(logfields.NetkitPair, []string{peerIfName, lxcIfName}).Debug("Created netkit pair")
    82  
    83  	// Disable reverse path filter on the host side netkit peer to allow
    84  	// container addresses to be used as source address when the linux
    85  	// stack performs routing.
    86  	err = DisableRpFilter(sysctl, lxcIfName)
    87  	if err != nil {
    88  		return nil, nil, err
    89  	}
    90  
    91  	peer, err := netlink.LinkByName(peerIfName)
    92  	if err != nil {
    93  		return nil, nil, fmt.Errorf("unable to lookup netkit peer just created: %w", err)
    94  	}
    95  
    96  	if err = netlink.LinkSetMTU(peer, mtu); err != nil {
    97  		return nil, nil, fmt.Errorf("unable to set MTU to %q: %w", peerIfName, err)
    98  	}
    99  
   100  	hostNetkit, err := netlink.LinkByName(lxcIfName)
   101  	if err != nil {
   102  		return nil, nil, fmt.Errorf("unable to lookup netkit just created: %w", err)
   103  	}
   104  
   105  	if err = netlink.LinkSetMTU(hostNetkit, mtu); err != nil {
   106  		return nil, nil, fmt.Errorf("unable to set MTU to %q: %w", lxcIfName, err)
   107  	}
   108  
   109  	if err = netlink.LinkSetUp(netkit); err != nil {
   110  		return nil, nil, fmt.Errorf("unable to bring up netkit pair: %w", err)
   111  	}
   112  
   113  	if groIPv6MaxSize > 0 {
   114  		if err = netlink.LinkSetGROMaxSize(hostNetkit, groIPv6MaxSize); err != nil {
   115  			return nil, nil, fmt.Errorf("unable to set GRO max size to %q: %w",
   116  				lxcIfName, err)
   117  		}
   118  		if err = netlink.LinkSetGROMaxSize(peer, groIPv6MaxSize); err != nil {
   119  			return nil, nil, fmt.Errorf("unable to set GRO max size to %q: %w",
   120  				peerIfName, err)
   121  		}
   122  	}
   123  
   124  	if gsoIPv6MaxSize > 0 {
   125  		if err = netlink.LinkSetGSOMaxSize(hostNetkit, gsoIPv6MaxSize); err != nil {
   126  			return nil, nil, fmt.Errorf("unable to set GSO max size to %q: %w",
   127  				lxcIfName, err)
   128  		}
   129  		if err = netlink.LinkSetGSOMaxSize(peer, gsoIPv6MaxSize); err != nil {
   130  			return nil, nil, fmt.Errorf("unable to set GSO max size to %q: %w",
   131  				peerIfName, err)
   132  		}
   133  	}
   134  
   135  	if groIPv4MaxSize > 0 {
   136  		if err = netlink.LinkSetGROIPv4MaxSize(hostNetkit, groIPv4MaxSize); err != nil {
   137  			return nil, nil, fmt.Errorf("unable to set GRO max size to %q: %w",
   138  				lxcIfName, err)
   139  		}
   140  		if err = netlink.LinkSetGROIPv4MaxSize(peer, groIPv4MaxSize); err != nil {
   141  			return nil, nil, fmt.Errorf("unable to set GRO max size to %q: %w",
   142  				peerIfName, err)
   143  		}
   144  	}
   145  
   146  	if gsoIPv4MaxSize > 0 {
   147  		if err = netlink.LinkSetGSOIPv4MaxSize(hostNetkit, gsoIPv4MaxSize); err != nil {
   148  			return nil, nil, fmt.Errorf("unable to set GSO max size to %q: %w",
   149  				lxcIfName, err)
   150  		}
   151  		if err = netlink.LinkSetGSOIPv4MaxSize(peer, gsoIPv4MaxSize); err != nil {
   152  			return nil, nil, fmt.Errorf("unable to set GSO max size to %q: %w",
   153  				peerIfName, err)
   154  		}
   155  	}
   156  
   157  	ep.Mac = peer.Attrs().HardwareAddr.String()
   158  	ep.HostMac = hostNetkit.Attrs().HardwareAddr.String()
   159  	ep.InterfaceIndex = int64(hostNetkit.Attrs().Index)
   160  	ep.InterfaceName = lxcIfName
   161  
   162  	return netkit, peer, nil
   163  }