1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
//go:build linux
package overlay
import (
"context"
"fmt"
"net"
"syscall"
"github.com/containerd/log"
"github.com/docker/docker/internal/nlwrap"
"github.com/docker/docker/libnetwork/drivers/overlay/overlayutils"
"github.com/docker/docker/libnetwork/netutils"
"github.com/docker/docker/libnetwork/ns"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
)
var soTimeout = ns.NetlinkSocketsTimeout
func validateID(nid, eid string) error {
if nid == "" {
return fmt.Errorf("invalid network id")
}
if eid == "" {
return fmt.Errorf("invalid endpoint id")
}
return nil
}
func createVethPair() (string, string, error) {
nlh := ns.NlHandle()
// Generate a name for what will be the host side pipe interface
name1, err := netutils.GenerateIfaceName(nlh, vethPrefix, vethLen)
if err != nil {
return "", "", fmt.Errorf("error generating veth name1: %v", err)
}
// Generate a name for what will be the sandbox side pipe interface
name2, err := netutils.GenerateIfaceName(nlh, vethPrefix, vethLen)
if err != nil {
return "", "", fmt.Errorf("error generating veth name2: %v", err)
}
// Generate and add the interface pipe host <-> sandbox
veth := &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{Name: name1, TxQLen: 0},
PeerName: name2,
}
if err := nlh.LinkAdd(veth); err != nil {
return "", "", fmt.Errorf("error creating veth pair: %v", err)
}
return name1, name2, nil
}
func createVxlan(name string, vni uint32, mtu int, vtepIPv6 bool) error {
vxlan := &netlink.Vxlan{
LinkAttrs: netlink.LinkAttrs{Name: name, MTU: mtu},
VxlanId: int(vni),
Learning: true,
Port: int(overlayutils.VXLANUDPPort()),
Proxy: true,
L3miss: true,
L2miss: true,
}
// The kernel restricts the destination VTEP (virtual tunnel endpoint) in
// VXLAN forwarding database entries to a single address family, defaulting
// to IPv4 unless either an IPv6 group or default remote destination address
// is configured when the VXLAN link is created.
//
// Set up the VXLAN link for IPv6 destination addresses by setting the VXLAN
// group address to the IPv6 unspecified address, like iproute2.
// https://github.com/iproute2/iproute2/commit/97d564b90ccb1e4a3c756d9caae161f55b2b63a2
// https://patchwork.ozlabs.org/project/netdev/patch/20180917171325.GA2660@localhost.localdomain/
if vtepIPv6 {
vxlan.Group = net.IPv6unspecified
}
if err := ns.NlHandle().LinkAdd(vxlan); err != nil {
return fmt.Errorf("error creating vxlan interface: %v", err)
}
return nil
}
func deleteInterface(name string) error {
link, err := ns.NlHandle().LinkByName(name)
if err != nil {
return fmt.Errorf("failed to find interface with name %s: %v", name, err)
}
if err := ns.NlHandle().LinkDel(link); err != nil {
return fmt.Errorf("error deleting interface with name %s: %v", name, err)
}
return nil
}
func deleteVxlanByVNI(path string, vni uint32) error {
nlh := ns.NlHandle()
if path != "" {
ns, err := netns.GetFromPath(path)
if err != nil {
return fmt.Errorf("failed to get ns handle for %s: %v", path, err)
}
defer ns.Close()
nlh, err = nlwrap.NewHandleAt(ns, syscall.NETLINK_ROUTE)
if err != nil {
return fmt.Errorf("failed to get netlink handle for ns %s: %v", path, err)
}
defer nlh.Close()
err = nlh.SetSocketTimeout(soTimeout)
if err != nil {
log.G(context.TODO()).Warnf("Failed to set the timeout on the netlink handle sockets for vxlan deletion: %v", err)
}
}
links, err := nlh.LinkList()
if err != nil {
return fmt.Errorf("failed to list interfaces while deleting vxlan interface by vni: %v", err)
}
for _, l := range links {
if l.Type() == "vxlan" && (vni == 0 || l.(*netlink.Vxlan).VxlanId == int(vni)) {
err = nlh.LinkDel(l)
if err != nil {
return fmt.Errorf("error deleting vxlan interface with id %d: %v", vni, err)
}
return nil
}
}
return fmt.Errorf("could not find a vxlan interface to delete with id %d", vni)
}
|