Compare commits
1 commit
main
...
feature-51
| Author | SHA1 | Date | |
|---|---|---|---|
|
a73bf97697 |
2 changed files with 92 additions and 0 deletions
|
|
@ -1,14 +1,31 @@
|
|||
package netif
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
const (
|
||||
scopeUniverse = 0
|
||||
addressSecondary = 0x01
|
||||
)
|
||||
|
||||
func CreateVxlan(name string, vxlanID int, localIface string, mtu int) error {
|
||||
link, err := netlink.LinkByName(localIface)
|
||||
if err != nil {
|
||||
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{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: name,
|
||||
|
|
@ -17,7 +34,18 @@ func CreateVxlan(name string, vxlanID int, localIface string, mtu int) error {
|
|||
VxlanId: vxlanID,
|
||||
Port: 4789,
|
||||
VtepDevIndex: link.Attrs().Index,
|
||||
SrcAddr: local,
|
||||
Learning: false,
|
||||
}
|
||||
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