func TestSetupIPChains(t *testing.T) {
	// Create a test bridge with a basic bridge configuration (name + IPv4).
	defer testutils.SetupTestOSContext(t)()

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}

	driverconfig := &configuration{
		EnableIPTables: true,
	}
	d := &driver{
		config: driverconfig,
	}
	assertChainConfig(d, t)

	config := getBasicTestConfig()
	br := &bridgeInterface{nlh: nh}
	createTestBridge(config, br, t)

	assertBridgeConfig(config, br, d, t)

	config.EnableIPMasquerade = true
	assertBridgeConfig(config, br, d, t)

	config.EnableICC = true
	assertBridgeConfig(config, br, d, t)

	config.EnableIPMasquerade = false
	assertBridgeConfig(config, br, d, t)
}
func TestSetupNewBridge(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	defer nh.Delete()

	config := &networkConfiguration{BridgeName: DefaultBridgeName}
	br := &bridgeInterface{nlh: nh}

	if err := setupDevice(config, br); err != nil {
		t.Fatalf("Bridge creation failed: %v", err)
	}
	if br.Link == nil {
		t.Fatal("bridgeInterface link is nil (expected valid link)")
	}
	if _, err := nh.LinkByName(DefaultBridgeName); err != nil {
		t.Fatalf("Failed to retrieve bridge device: %v", err)
	}
	if br.Link.Attrs().Flags&net.FlagUp == net.FlagUp {
		t.Fatalf("bridgeInterface should be created down")
	}
}
func TestProgramIPTable(t *testing.T) {
	// Create a test bridge with a basic bridge configuration (name + IPv4).
	defer testutils.SetupTestOSContext(t)()

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}

	createTestBridge(getBasicTestConfig(), &bridgeInterface{nlh: nh}, t)

	// Store various iptables chain rules we care for.
	rules := []struct {
		rule  iptRule
		descr string
	}{
		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-d", "127.1.2.3", "-i", "lo", "-o", "lo", "-j", "DROP"}}, "Test Loopback"},
		{iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-s", iptablesTestBridgeIP, "!", "-o", DefaultBridgeName, "-j", "MASQUERADE"}}, "NAT Test"},
		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "!", "-o", DefaultBridgeName, "-j", "ACCEPT"}}, "Test ACCEPT NON_ICC OUTGOING"},
		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-o", DefaultBridgeName, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}}, "Test ACCEPT INCOMING"},
		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "ACCEPT"}}, "Test enable ICC"},
		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "DROP"}}, "Test disable ICC"},
	}

	// Assert the chain rules' insertion and removal.
	for _, c := range rules {
		assertIPTableChainProgramming(c.rule, c.descr, t)
	}
}
func TestSetupGatewayIPv6(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	_, nw, _ := net.ParseCIDR("2001:db8:ea9:9abc:ffff::/80")
	gw := net.ParseIP("2001:db8:ea9:9abc:ffff::254")

	config := &networkConfiguration{
		BridgeName:         DefaultBridgeName,
		AddressIPv6:        nw,
		DefaultGatewayIPv6: gw}

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	defer nh.Delete()

	br := &bridgeInterface{nlh: nh}

	if err := setupGatewayIPv6(config, br); err != nil {
		t.Fatalf("Set Default Gateway failed: %v", err)
	}

	if !gw.Equal(br.gatewayIPv6) {
		t.Fatalf("Set Default Gateway failed. Expected %v, Found %v", gw, br.gatewayIPv6)
	}
}
func TestSetupGatewayIPv4(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	defer nh.Delete()

	ip, nw, _ := net.ParseCIDR("192.168.0.24/16")
	nw.IP = ip
	gw := net.ParseIP("192.168.2.254")

	config := &networkConfiguration{
		BridgeName:         DefaultBridgeName,
		DefaultGatewayIPv4: gw}

	br := &bridgeInterface{bridgeIPv4: nw, nlh: nh}

	if err := setupGatewayIPv4(config, br); err != nil {
		t.Fatalf("Set Default Gateway failed: %v", err)
	}

	if !gw.Equal(br.gatewayIPv4) {
		t.Fatalf("Set Default Gateway failed. Expected %v, Found %v", gw, br.gatewayIPv4)
	}
}
Exemple #6
0
// Init initializes a new network namespace
func Init() {
	var err error
	initNs, err = netns.Get()
	if err != nil {
		log.Errorf("could not get initial namespace: %v", err)
	}
	initNl, err = netlink.NewHandle(getSupportedNlFamilies()...)
	if err != nil {
		log.Errorf("could not create netlink handle on initial namespace: %v", err)
	}
}
func TestInterfaceDefaultName(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	config := &networkConfiguration{}
	if _ = newInterface(nh, config); config.BridgeName != DefaultBridgeName {
		t.Fatalf("Expected default interface name %q, got %q", DefaultBridgeName, config.BridgeName)
	}
}
Exemple #8
0
// Init initializes a new network namespace
func Init() {
	var err error
	initNs, err = netns.Get()
	if err != nil {
		logrus.Errorf("could not get initial namespace: %v", err)
	}
	initNl, err = netlink.NewHandle(getSupportedNlFamilies()...)
	if err != nil {
		logrus.Errorf("could not create netlink handle on initial namespace: %v", err)
	}
	err = initNl.SetSocketTimeout(NetlinkSocketsTimeout)
	if err != nil {
		logrus.Warnf("Failed to set the timeout on the default netlink handle sockets: %v", err)
	}
}
func setupVerifyTest(t *testing.T) *bridgeInterface {
	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	inf := &bridgeInterface{nlh: nh}

	br := netlink.Bridge{}
	br.LinkAttrs.Name = "default0"
	if err := nh.LinkAdd(&br); err == nil {
		inf.Link = &br
	} else {
		t.Fatalf("Failed to create bridge interface: %v", err)
	}

	return inf
}
func TestAddressesEmptyInterface(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	inf := newInterface(nh, &networkConfiguration{})
	addrv4, addrsv6, err := inf.addresses()
	if err != nil {
		t.Fatalf("Failed to get addresses of default interface: %v", err)
	}
	if expected := (netlink.Addr{}); addrv4 != expected {
		t.Fatalf("Default interface has unexpected IPv4: %s", addrv4)
	}
	if len(addrsv6) != 0 {
		t.Fatalf("Default interface has unexpected IPv6: %v", addrsv6)
	}
}
func TestDisableIPv6DAD(t *testing.T) {
	if testutils.RunningOnCircleCI() {
		t.Skipf("Skipping as not supported on CIRCLE CI kernel")
	}

	defer testutils.SetupTestOSContext(t)()

	ipv6, _ := types.ParseCIDR("2001:db8::44/64")
	iface := &nwIface{addressIPv6: ipv6}

	veth := &netlink.Veth{
		LinkAttrs: netlink.LinkAttrs{Name: "sideA"},
		PeerName:  "sideB",
	}
	nlh, err := netlink.NewHandle(syscall.NETLINK_ROUTE)
	if err != nil {
		t.Fatal(err)
	}
	err = nlh.LinkAdd(veth)
	if err != nil {
		t.Fatal(err)
	}

	link, err := nlh.LinkByName("sideA")
	if err != nil {
		t.Fatal(err)
	}

	err = setInterfaceIPv6(nlh, link, iface)
	if err != nil {
		t.Fatal(err)
	}

	addrList, err := nlh.AddrList(link, nl.FAMILY_V6)
	if err != nil {
		t.Fatal(err)
	}

	if addrList[0].Flags&syscall.IFA_F_NODAD == 0 {
		t.Fatalf("Unexpected interface flags: 0x%x. Expected to contain 0x%x", addrList[0].Flags, syscall.IFA_F_NODAD)
	}
}
Exemple #12
0
func TestSetupIPv6(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	defer nh.Delete()

	config, br := setupTestInterface(t, nh)
	if err := setupBridgeIPv6(config, br); err != nil {
		t.Fatalf("Failed to setup bridge IPv6: %v", err)
	}

	procSetting, err := ioutil.ReadFile(fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", config.BridgeName))
	if err != nil {
		t.Fatalf("Failed to read disable_ipv6 kernel setting: %v", err)
	}

	if expected := []byte("0\n"); bytes.Compare(expected, procSetting) != 0 {
		t.Fatalf("Invalid kernel setting disable_ipv6: expected %q, got %q", string(expected), string(procSetting))
	}

	addrsv6, err := nh.AddrList(br.Link, netlink.FAMILY_V6)
	if err != nil {
		t.Fatalf("Failed to list device IPv6 addresses: %v", err)
	}

	var found bool
	for _, addr := range addrsv6 {
		if bridgeIPv6Str == addr.IPNet.String() {
			found = true
			break
		}
	}

	if !found {
		t.Fatalf("Bridge device does not have requested IPv6 address %v", bridgeIPv6Str)
	}

}
func TestSetupNewNonDefaultBridge(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	defer nh.Delete()

	config := &networkConfiguration{BridgeName: "test0", DefaultBridge: true}
	br := &bridgeInterface{nlh: nh}

	err = setupDevice(config, br)
	if err == nil {
		t.Fatal("Expected bridge creation failure with \"non default name\", succeeded")
	}

	if _, ok := err.(NonDefaultBridgeExistError); !ok {
		t.Fatalf("Did not fail with expected error. Actual error: %v", err)
	}
}
func TestSetupBridgeIPv4Fixed(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	ip, netw, err := net.ParseCIDR("192.168.1.1/24")
	if err != nil {
		t.Fatalf("Failed to parse bridge IPv4: %v", err)
	}

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	defer nh.Delete()

	config, br := setupTestInterface(t, nh)
	config.AddressIPv4 = &net.IPNet{IP: ip, Mask: netw.Mask}
	if err := setupBridgeIPv4(config, br); err != nil {
		t.Fatalf("Failed to setup bridge IPv4: %v", err)
	}

	addrsv4, err := nh.AddrList(br.Link, netlink.FAMILY_V4)
	if err != nil {
		t.Fatalf("Failed to list device IPv4 addresses: %v", err)
	}

	var found bool
	for _, addr := range addrsv4 {
		if config.AddressIPv4.String() == addr.IPNet.String() {
			found = true
			break
		}
	}

	if !found {
		t.Fatalf("Bridge device does not have requested IPv4 address %v", config.AddressIPv4)
	}
}
func TestSetupDeviceUp(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	nh, err := netlink.NewHandle()
	if err != nil {
		t.Fatal(err)
	}
	defer nh.Delete()

	config := &networkConfiguration{BridgeName: DefaultBridgeName}
	br := &bridgeInterface{nlh: nh}

	if err := setupDevice(config, br); err != nil {
		t.Fatalf("Bridge creation failed: %v", err)
	}
	if err := setupDeviceUp(config, br); err != nil {
		t.Fatalf("Failed to up bridge device: %v", err)
	}

	lnk, _ := nh.LinkByName(DefaultBridgeName)
	if lnk.Attrs().Flags&net.FlagUp != net.FlagUp {
		t.Fatalf("bridgeInterface should be up")
	}
}
func TestSetInterfaceIP(t *testing.T) {
	defer testutils.SetupTestOSContext(t)()

	ipv4, _ := types.ParseCIDR("172.30.0.33/24")
	ipv6, _ := types.ParseCIDR("2001:db8::44/64")
	iface := &nwIface{address: ipv4, addressIPv6: ipv6}

	nlh, err := netlink.NewHandle(syscall.NETLINK_ROUTE)
	if err != nil {
		t.Fatal(err)
	}

	if err := nlh.LinkAdd(&netlink.Veth{
		LinkAttrs: netlink.LinkAttrs{Name: "sideA"},
		PeerName:  "sideB",
	}); err != nil {
		t.Fatal(err)
	}

	linkA, err := nlh.LinkByName("sideA")
	if err != nil {
		t.Fatal(err)
	}

	linkB, err := nlh.LinkByName("sideB")
	if err != nil {
		t.Fatal(err)
	}

	if err := nlh.LinkSetUp(linkA); err != nil {
		t.Fatal(err)
	}

	if err := nlh.LinkSetUp(linkB); err != nil {
		t.Fatal(err)
	}

	if err := setInterfaceIP(nlh, linkA, iface); err != nil {
		t.Fatal(err)
	}

	if err := setInterfaceIPv6(nlh, linkA, iface); err != nil {
		t.Fatal(err)
	}

	err = setInterfaceIP(nlh, linkB, iface)
	if err == nil {
		t.Fatalf("Expected route conflict error, but succeeded")
	}
	if !strings.Contains(err.Error(), "conflicts with existing route") {
		t.Fatalf("Unexpected error: %v", err)
	}

	err = setInterfaceIPv6(nlh, linkB, iface)
	if err == nil {
		t.Fatalf("Expected route conflict error, but succeeded")
	}
	if !strings.Contains(err.Error(), "conflicts with existing route") {
		t.Fatalf("Unexpected error: %v", err)
	}
}
Exemple #17
0
func (u *NetLinkProbe) start(nsPath string) {
	var context *common.NetNSContext
	var err error

	// Enter the network namespace if necessary
	if nsPath != "" {
		context, err = common.NewNetNsContext(nsPath)
		if err != nil {
			logging.GetLogger().Errorf("Failed to switch namespace: %s", err.Error())
			return
		}
	}

	// Both NewHandle and Subscribe need to done in the network namespace.
	h, err := netlink.NewHandle(syscall.NETLINK_ROUTE)
	if err != nil {
		logging.GetLogger().Errorf("Failed to create netlink handle: %s", err.Error())
		context.Close()
		return
	}
	defer h.Delete()

	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
	if err != nil {
		logging.GetLogger().Errorf("Failed to subscribe to netlink messages: %s", err.Error())
		context.Close()
		return
	}
	defer s.Close()

	u.ethtool, err = ethtool.NewEthtool()
	if err != nil {
		logging.GetLogger().Errorf("Failed to create ethtool object: %s", err.Error())
		context.Close()
		return
	}
	defer u.ethtool.Close()

	epfd, e := syscall.EpollCreate1(0)
	if e != nil {
		logging.GetLogger().Errorf("Failed to create epoll: %s", err.Error())
		return
	}
	defer syscall.Close(epfd)

	// Leave the network namespace
	context.Close()

	u.wg.Add(1)
	defer u.wg.Done()

	atomic.StoreInt64(&u.state, common.RunningState)
	defer atomic.StoreInt64(&u.state, common.StoppedState)

	u.netlink = h
	u.initialize()

	fd := s.GetFd()
	err = syscall.SetNonblock(fd, true)
	if err != nil {
		logging.GetLogger().Errorf("Failed to set the netlink fd as non-blocking: %s", err.Error())
		return
	}

	event := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(fd)}
	if err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil {
		logging.GetLogger().Errorf("Failed to control epoll: %s", err.Error())
		return
	}
	events := make([]syscall.EpollEvent, maxEpollEvents)

	for atomic.LoadInt64(&u.state) == common.RunningState {
		n, err := syscall.EpollWait(epfd, events[:], 1000)
		if err != nil {
			errno, ok := err.(syscall.Errno)
			if ok && errno != syscall.EINTR {
				logging.GetLogger().Errorf("Failed to receive from events from netlink: %s", err.Error())
			}
			continue
		}
		if n == 0 {
			continue
		}

		msgs, err := s.Receive()
		if err != nil {
			if errno, ok := err.(syscall.Errno); !ok || !errno.Temporary() {
				logging.GetLogger().Errorf("Failed to receive from netlink messages: %s", err.Error())
				return
			}
			time.Sleep(1 * time.Second)
			continue
		}

		for _, msg := range msgs {
			switch msg.Header.Type {
			case syscall.RTM_NEWLINK:
				link, err := netlink.LinkDeserialize(msg.Data)
				if err != nil {
					logging.GetLogger().Warningf("Failed to deserialize netlink message: %s", err.Error())
					continue
				}
				u.onLinkAdded(link)
			case syscall.RTM_DELLINK:
				link, err := netlink.LinkDeserialize(msg.Data)
				if err != nil {
					logging.GetLogger().Warningf("Failed to deserialize netlink message: %s", err.Error())
					continue
				}
				u.onLinkDeleted(link)
			case syscall.RTM_NEWADDR:
				addr, family, ifindex, err := parseAddr(msg.Data)
				if err != nil {
					logging.GetLogger().Warningf("Failed to parse newlink message: %s", err.Error())
					continue
				}
				u.onAddressAdded(addr, family, ifindex)
			case syscall.RTM_DELADDR:
				addr, family, ifindex, err := parseAddr(msg.Data)
				if err != nil {
					logging.GetLogger().Warningf("Failed to parse newlink message: %s", err.Error())
					continue
				}
				u.onAddressDeleted(addr, family, ifindex)
			}
		}
	}
}