Compare commits
2 commits
01c67bd0f9
...
79eb8cc175
| Author | SHA1 | Date | |
|---|---|---|---|
|
79eb8cc175 |
|||
|
a73bf97697 |
2 changed files with 92 additions and 0 deletions
|
|
@ -1,14 +1,31 @@
|
||||||
package netif
|
package netif
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
scopeUniverse = 0
|
||||||
|
addressSecondary = 0x01
|
||||||
|
)
|
||||||
|
|
||||||
func CreateVxlan(name string, vxlanID int, localIface string, mtu int) error {
|
func CreateVxlan(name string, vxlanID int, localIface string, mtu int) error {
|
||||||
link, err := netlink.LinkByName(localIface)
|
link, err := netlink.LinkByName(localIface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
local, err := vtepAddress(localIface, addrs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
vxlan := &netlink.Vxlan{
|
vxlan := &netlink.Vxlan{
|
||||||
LinkAttrs: netlink.LinkAttrs{
|
LinkAttrs: netlink.LinkAttrs{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
|
@ -17,7 +34,18 @@ func CreateVxlan(name string, vxlanID int, localIface string, mtu int) error {
|
||||||
VxlanId: vxlanID,
|
VxlanId: vxlanID,
|
||||||
Port: 4789,
|
Port: 4789,
|
||||||
VtepDevIndex: link.Attrs().Index,
|
VtepDevIndex: link.Attrs().Index,
|
||||||
|
SrcAddr: local,
|
||||||
Learning: false,
|
Learning: false,
|
||||||
}
|
}
|
||||||
return netlink.LinkAdd(vxlan)
|
return netlink.LinkAdd(vxlan)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func vtepAddress(iface string, addrs []netlink.Addr) (net.IP, error) {
|
||||||
|
for _, a := range addrs {
|
||||||
|
if a.IPNet == nil || a.IP.To4() == nil || a.Scope != scopeUniverse || a.Flags&addressSecondary != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return a.IP.To4(), nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("no primary global IPv4 address on %s for the VXLAN local endpoint", iface)
|
||||||
|
}
|
||||||
|
|
|
||||||
64
internal/netif/vxlan_test.go
Normal file
64
internal/netif/vxlan_test.go
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
package netif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addr(cidr string, scope, flags int) netlink.Addr {
|
||||||
|
ip, network, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
network.IP = ip
|
||||||
|
return netlink.Addr{IPNet: network, Scope: scope, Flags: flags}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVtepAddress_PicksThePrimaryGlobalIPv4(t *testing.T) {
|
||||||
|
addrs := []netlink.Addr{
|
||||||
|
addr("127.0.0.1/8", 254, 0),
|
||||||
|
addr("169.254.0.3/28", 0, 0x01),
|
||||||
|
addr("192.168.14.11/24", 0, 0x80),
|
||||||
|
addr("192.168.14.99/24", 0, 0x01),
|
||||||
|
}
|
||||||
|
got, err := vtepAddress("br-000000", addrs)
|
||||||
|
if err != nil || got.String() != "192.168.14.11" {
|
||||||
|
t.Errorf("vtepAddress = %v, %v, want 192.168.14.11", got, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVtepAddress_SkipsLinkScopeAndSecondaryAddresses(t *testing.T) {
|
||||||
|
addrs := []netlink.Addr{
|
||||||
|
addr("169.254.0.3/28", 253, 0),
|
||||||
|
addr("192.168.14.99/24", 0, 0x01),
|
||||||
|
addr("192.168.14.12/24", 0, 0),
|
||||||
|
}
|
||||||
|
got, err := vtepAddress("br-000000", addrs)
|
||||||
|
if err != nil || got.String() != "192.168.14.12" {
|
||||||
|
t.Errorf("vtepAddress = %v, %v, want 192.168.14.12", got, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVtepAddress_RefusesAnInterfaceWithoutUsableAddress(t *testing.T) {
|
||||||
|
for name, addrs := range map[string][]netlink.Addr{
|
||||||
|
"no address": nil,
|
||||||
|
"only secondary": {addr("192.168.14.99/24", 0, 0x01)},
|
||||||
|
"only link": {addr("169.254.0.3/28", 253, 0)},
|
||||||
|
"only IPv6": {addr("fd00::11/64", 0, 0)},
|
||||||
|
} {
|
||||||
|
_, err := vtepAddress("br-000000", addrs)
|
||||||
|
if err == nil || !strings.Contains(err.Error(), "no primary global IPv4 address on br-000000") {
|
||||||
|
t.Errorf("%s: error = %v", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVtepAddress_ReturnsAFourByteAddress(t *testing.T) {
|
||||||
|
got, err := vtepAddress("br-000000", []netlink.Addr{addr("192.168.14.11/24", 0, 0)})
|
||||||
|
if err != nil || len(got) != 4 {
|
||||||
|
t.Errorf("vtepAddress = %v (%d bytes), %v", got, len(got), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue