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 }