409 lines
8.7 KiB
Go
409 lines
8.7 KiB
Go
package netlink
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
"syscall"
|
|
"testing"
|
|
)
|
|
|
|
type testLink struct {
|
|
name string
|
|
linkType string
|
|
}
|
|
|
|
func addLink(t *testing.T, name string, linkType string) {
|
|
if err := NetworkLinkAdd(name, linkType); err != nil {
|
|
t.Fatalf("Unable to create %s link: %s", name, err)
|
|
}
|
|
}
|
|
|
|
func readLink(t *testing.T, name string) *net.Interface {
|
|
iface, err := net.InterfaceByName(name)
|
|
if err != nil {
|
|
t.Fatalf("Could not find %s interface: %s", name, err)
|
|
}
|
|
|
|
return iface
|
|
}
|
|
|
|
func deleteLink(t *testing.T, name string) {
|
|
if err := NetworkLinkDel(name); err != nil {
|
|
t.Fatalf("Unable to delete %s link: %s", name, err)
|
|
}
|
|
}
|
|
|
|
func upLink(t *testing.T, name string) {
|
|
iface := readLink(t, name)
|
|
if err := NetworkLinkUp(iface); err != nil {
|
|
t.Fatalf("Could not bring UP %#v interface: %s", iface, err)
|
|
}
|
|
}
|
|
|
|
func downLink(t *testing.T, name string) {
|
|
iface := readLink(t, name)
|
|
if err := NetworkLinkDown(iface); err != nil {
|
|
t.Fatalf("Could not bring DOWN %#v interface: %s", iface, err)
|
|
}
|
|
}
|
|
|
|
func ipAssigned(iface *net.Interface, ip net.IP) bool {
|
|
addrs, _ := iface.Addrs()
|
|
|
|
for _, addr := range addrs {
|
|
args := strings.SplitN(addr.String(), "/", 2)
|
|
if args[0] == ip.String() {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func TestNetworkLinkAddDel(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
testLinks := []testLink{
|
|
{"tstEth", "dummy"},
|
|
{"tstBr", "bridge"},
|
|
}
|
|
|
|
for _, tl := range testLinks {
|
|
addLink(t, tl.name, tl.linkType)
|
|
defer deleteLink(t, tl.name)
|
|
readLink(t, tl.name)
|
|
}
|
|
}
|
|
|
|
func TestNetworkLinkUpDown(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
tl := testLink{name: "tstEth", linkType: "dummy"}
|
|
|
|
addLink(t, tl.name, tl.linkType)
|
|
defer deleteLink(t, tl.name)
|
|
|
|
upLink(t, tl.name)
|
|
ifcAfterUp := readLink(t, tl.name)
|
|
|
|
if (ifcAfterUp.Flags & syscall.IFF_UP) != syscall.IFF_UP {
|
|
t.Fatalf("Could not bring UP %#v initerface", tl)
|
|
}
|
|
|
|
downLink(t, tl.name)
|
|
ifcAfterDown := readLink(t, tl.name)
|
|
|
|
if (ifcAfterDown.Flags & syscall.IFF_UP) == syscall.IFF_UP {
|
|
t.Fatalf("Could not bring DOWN %#v initerface", tl)
|
|
}
|
|
}
|
|
|
|
func TestNetworkSetMacAddress(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
tl := testLink{name: "tstEth", linkType: "dummy"}
|
|
macaddr := "22:ce:e0:99:63:6f"
|
|
|
|
addLink(t, tl.name, tl.linkType)
|
|
defer deleteLink(t, tl.name)
|
|
|
|
ifcBeforeSet := readLink(t, tl.name)
|
|
|
|
if err := NetworkSetMacAddress(ifcBeforeSet, macaddr); err != nil {
|
|
t.Fatalf("Could not set %s MAC address on %#v interface: %s", macaddr, tl, err)
|
|
}
|
|
|
|
ifcAfterSet := readLink(t, tl.name)
|
|
|
|
if ifcAfterSet.HardwareAddr.String() != macaddr {
|
|
t.Fatalf("Could not set %s MAC address on %#v interface", macaddr, tl)
|
|
}
|
|
}
|
|
|
|
func TestNetworkSetMTU(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
tl := testLink{name: "tstEth", linkType: "dummy"}
|
|
mtu := 1400
|
|
|
|
addLink(t, tl.name, tl.linkType)
|
|
defer deleteLink(t, tl.name)
|
|
|
|
ifcBeforeSet := readLink(t, tl.name)
|
|
|
|
if err := NetworkSetMTU(ifcBeforeSet, mtu); err != nil {
|
|
t.Fatalf("Could not set %d MTU on %#v interface: %s", mtu, tl, err)
|
|
}
|
|
|
|
ifcAfterSet := readLink(t, tl.name)
|
|
|
|
if ifcAfterSet.MTU != mtu {
|
|
t.Fatalf("Could not set %d MTU on %#v interface", mtu, tl)
|
|
}
|
|
}
|
|
|
|
func TestNetworkSetMasterNoMaster(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
master := testLink{"tstBr", "bridge"}
|
|
slave := testLink{"tstEth", "dummy"}
|
|
testLinks := []testLink{master, slave}
|
|
|
|
for _, tl := range testLinks {
|
|
addLink(t, tl.name, tl.linkType)
|
|
defer deleteLink(t, tl.name)
|
|
upLink(t, tl.name)
|
|
}
|
|
|
|
masterIfc := readLink(t, master.name)
|
|
slaveIfc := readLink(t, slave.name)
|
|
if err := NetworkSetMaster(slaveIfc, masterIfc); err != nil {
|
|
t.Fatalf("Could not set %#v to be the master of %#v: %s", master, slave, err)
|
|
}
|
|
|
|
// Trying to figure out a way to test which will not break on RHEL6.
|
|
// We could check for existence of /sys/class/net/tstEth/upper_tstBr
|
|
// which should point to the ../tstBr which is the UPPER device i.e. network bridge
|
|
|
|
if err := NetworkSetNoMaster(slaveIfc); err != nil {
|
|
t.Fatalf("Could not UNset %#v master of %#v: %s", master, slave, err)
|
|
}
|
|
}
|
|
|
|
func TestNetworkChangeName(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
tl := testLink{"tstEth", "dummy"}
|
|
newName := "newTst"
|
|
|
|
addLink(t, tl.name, tl.linkType)
|
|
|
|
linkIfc := readLink(t, tl.name)
|
|
if err := NetworkChangeName(linkIfc, newName); err != nil {
|
|
deleteLink(t, tl.name)
|
|
t.Fatalf("Could not change %#v interface name to %s: %s", tl, newName, err)
|
|
}
|
|
|
|
readLink(t, newName)
|
|
deleteLink(t, newName)
|
|
}
|
|
|
|
func TestNetworkLinkAddVlan(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
tl := struct {
|
|
name string
|
|
id uint16
|
|
}{
|
|
name: "tstVlan",
|
|
id: 32,
|
|
}
|
|
masterLink := testLink{"tstEth", "dummy"}
|
|
|
|
addLink(t, masterLink.name, masterLink.linkType)
|
|
defer deleteLink(t, masterLink.name)
|
|
|
|
if err := NetworkLinkAddVlan(masterLink.name, tl.name, tl.id); err != nil {
|
|
t.Fatalf("Unable to create %#v VLAN interface: %s", tl, err)
|
|
}
|
|
|
|
readLink(t, tl.name)
|
|
}
|
|
|
|
func TestNetworkLinkAddMacVlan(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
tl := struct {
|
|
name string
|
|
mode string
|
|
}{
|
|
name: "tstVlan",
|
|
mode: "private",
|
|
}
|
|
masterLink := testLink{"tstEth", "dummy"}
|
|
|
|
addLink(t, masterLink.name, masterLink.linkType)
|
|
defer deleteLink(t, masterLink.name)
|
|
|
|
if err := NetworkLinkAddMacVlan(masterLink.name, tl.name, tl.mode); err != nil {
|
|
t.Fatalf("Unable to create %#v MAC VLAN interface: %s", tl, err)
|
|
}
|
|
|
|
readLink(t, tl.name)
|
|
}
|
|
|
|
func TestNetworkLinkAddMacVtap(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
tl := struct {
|
|
name string
|
|
mode string
|
|
}{
|
|
name: "tstVtap",
|
|
mode: "private",
|
|
}
|
|
masterLink := testLink{"tstEth", "dummy"}
|
|
|
|
addLink(t, masterLink.name, masterLink.linkType)
|
|
defer deleteLink(t, masterLink.name)
|
|
|
|
if err := NetworkLinkAddMacVtap(masterLink.name, tl.name, tl.mode); err != nil {
|
|
t.Fatalf("Unable to create %#v MAC VTAP interface: %s", tl, err)
|
|
}
|
|
|
|
readLink(t, tl.name)
|
|
}
|
|
|
|
func TestAddDelNetworkIp(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
ifaceName := "lo"
|
|
ip := net.ParseIP("127.0.1.1")
|
|
mask := net.IPv4Mask(255, 255, 255, 255)
|
|
ipNet := &net.IPNet{IP: ip, Mask: mask}
|
|
|
|
iface, err := net.InterfaceByName(ifaceName)
|
|
if err != nil {
|
|
t.Skip("No 'lo' interface; skipping tests")
|
|
}
|
|
|
|
if err := NetworkLinkAddIp(iface, ip, ipNet); err != nil {
|
|
t.Fatalf("Could not add IP address %s to interface %#v: %s", ip.String(), iface, err)
|
|
}
|
|
|
|
if !ipAssigned(iface, ip) {
|
|
t.Fatalf("Could not locate address '%s' in lo address list.", ip.String())
|
|
}
|
|
|
|
if err := NetworkLinkDelIp(iface, ip, ipNet); err != nil {
|
|
t.Fatalf("Could not delete IP address %s from interface %#v: %s", ip.String(), iface, err)
|
|
}
|
|
|
|
if ipAssigned(iface, ip) {
|
|
t.Fatalf("Located address '%s' in lo address list after removal.", ip.String())
|
|
}
|
|
}
|
|
|
|
func TestAddRouteSourceSelection(t *testing.T) {
|
|
tstIp := "127.1.1.1"
|
|
tl := testLink{name: "tstEth", linkType: "dummy"}
|
|
|
|
addLink(t, tl.name, tl.linkType)
|
|
defer deleteLink(t, tl.name)
|
|
|
|
ip := net.ParseIP(tstIp)
|
|
mask := net.IPv4Mask(255, 255, 255, 255)
|
|
ipNet := &net.IPNet{IP: ip, Mask: mask}
|
|
|
|
iface, err := net.InterfaceByName(tl.name)
|
|
if err != nil {
|
|
t.Fatalf("Lost created link %#v", tl)
|
|
}
|
|
|
|
if err := NetworkLinkAddIp(iface, ip, ipNet); err != nil {
|
|
t.Fatalf("Could not add IP address %s to interface %#v: %s", ip.String(), iface, err)
|
|
}
|
|
|
|
upLink(t, tl.name)
|
|
defer downLink(t, tl.name)
|
|
|
|
if err := AddRoute("127.0.0.0/8", tstIp, "", tl.name); err != nil {
|
|
t.Fatalf("Failed to add route with source address")
|
|
}
|
|
}
|
|
|
|
func TestCreateVethPair(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
var (
|
|
name1 = "veth1"
|
|
name2 = "veth2"
|
|
)
|
|
|
|
if err := NetworkCreateVethPair(name1, name2, 0); err != nil {
|
|
t.Fatalf("Could not create veth pair %s %s: %s", name1, name2, err)
|
|
}
|
|
defer NetworkLinkDel(name1)
|
|
|
|
readLink(t, name1)
|
|
readLink(t, name2)
|
|
}
|
|
|
|
//
|
|
// netlink package tests which do not use RTNETLINK
|
|
//
|
|
func TestCreateBridgeWithMac(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
name := "testbridge"
|
|
|
|
if err := CreateBridge(name, true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if _, err := net.InterfaceByName(name); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// cleanup and tests
|
|
|
|
if err := DeleteBridge(name); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if _, err := net.InterfaceByName(name); err == nil {
|
|
t.Fatalf("expected error getting interface because %s bridge was deleted", name)
|
|
}
|
|
}
|
|
|
|
func TestSetMacAddress(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
|
|
name := "testmac"
|
|
mac := randMacAddr()
|
|
|
|
if err := NetworkLinkAdd(name, "bridge"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer NetworkLinkDel(name)
|
|
|
|
if err := SetMacAddress(name, mac); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
iface, err := net.InterfaceByName(name)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if iface.HardwareAddr.String() != mac {
|
|
t.Fatalf("mac address %q does not match %q", iface.HardwareAddr, mac)
|
|
}
|
|
}
|