Exemple #1
0
// NewBridge creates new network bridge on Linux host.
//
// It is equivalent of running: ip link add name br${RANDOM STRING} type bridge
// NewBridge returns Bridger which is initialized to a pointer of type Bridge if the
// bridge was created successfully on the Linux host. Newly created bridge is assigned
// a random name starting with "br".
// It returns error if the bridge could not be created.
func NewBridge() (Bridger, error) {
	brDev := makeNetInterfaceName("br")

	if ok, err := NetInterfaceNameValid(brDev); !ok {
		return nil, err
	}

	if _, err := net.InterfaceByName(brDev); err == nil {
		return nil, fmt.Errorf("Interface name %s already assigned on the host", brDev)
	}

	if err := netlink.NetworkLinkAdd(brDev, "bridge"); err != nil {
		return nil, err
	}

	newIfc, err := net.InterfaceByName(brDev)
	if err != nil {
		return nil, fmt.Errorf("Could not find the new interface: %s", err)
	}

	return &Bridge{
		Link: Link{
			ifc: newIfc,
		},
	}, nil
}
Exemple #2
0
// NewLinkWithOptions creates new network link on Linux host and sets some of its network
// parameters passed in as LinkOptions
//
// Calling NewLinkWithOptions is equivalent of running following commands one after another if
// particular option is passed in as a parameter:
// 		ip link add name ${ifcName} type dummy
// 		ip link set dev ${ifcName} address ${MAC address}
//		ip link set dev ${ifcName} mtu ${MTU value}
//		ip link set dev ${ifcName} up
// NewLinkWithOptions returns Linker which is initialized to a pointer of type Link if the network
// link with given LinkOptions was created successfully on the Linux host.
// It attempts to delete the link if any of the LinkOptions are incorrect or if setting the options
// failed and returns error.
func NewLinkWithOptions(ifcName string, opts LinkOptions) (Linker, error) {
	if ok, err := NetInterfaceNameValid(ifcName); !ok {
		return nil, err
	}

	if _, err := net.InterfaceByName(ifcName); err == nil {
		return nil, fmt.Errorf("Interface name %s already assigned on the host", ifcName)
	}

	if err := netlink.NetworkLinkAdd(ifcName, "dummy"); err != nil {
		return nil, fmt.Errorf("Could not create new link %s: %s", ifcName, err)
	}

	newIfc, err := net.InterfaceByName(ifcName)
	if err != nil {
		return nil, fmt.Errorf("Could not find the new interface: %s", err)
	}

	if (opts != LinkOptions{}) {
		errOpts := setLinkOptions(newIfc, opts)
		if errOpts != nil {
			if errDel := DeleteLink(newIfc.Name); err != nil {
				return nil, fmt.Errorf("Incorrect options specified: %s. Attempt to delete the link failed: %s",
					errOpts, errDel)
			}
			return nil, fmt.Errorf("Could not set link options: %s", errOpts)
		}
	}

	return &Link{
		ifc: newIfc,
	}, nil
}
Exemple #3
0
// Create creates a bridge device and returns the interface.
// If the device already exists, returns the existing interface.
func (Bridge) Create(name string, ip net.IP, subnet *net.IPNet) (intf *net.Interface, err error) {
	netlinkMu.Lock()
	defer netlinkMu.Unlock()

	if err := netlink.NetworkLinkAdd(name, "bridge"); err != nil && err.Error() != "file exists" {
		return nil, fmt.Errorf("devices: create bridge: %v", err)
	}

	if intf, err = net.InterfaceByName(name); err != nil {
		return nil, fmt.Errorf("devices: look up created bridge interface: %v", err)
	}

	if err = netlink.NetworkLinkAddIp(intf, ip, subnet); err != nil && err.Error() != "file exists" {
		return nil, fmt.Errorf("devices: add IP to bridge: %v", err)
	}
	return intf, nil
}
Exemple #4
0
// NewLink creates new network link on Linux host.
//
// It is equivalent of running: ip link add name ${ifcName} type dummy
// NewLink returns Linker which is initialized to a pointer of type Link if the
// link was created successfully on the Linux host.
// It returns error if the network link could not be created on Linux host.
func NewLink(ifcName string) (Linker, error) {
	if ok, err := NetInterfaceNameValid(ifcName); !ok {
		return nil, err
	}

	if _, err := net.InterfaceByName(ifcName); err == nil {
		return nil, fmt.Errorf("Interface name %s already assigned on the host", ifcName)
	}

	if err := netlink.NetworkLinkAdd(ifcName, "dummy"); err != nil {
		return nil, fmt.Errorf("Could not create new link %s: %s", ifcName, err)
	}

	newIfc, err := net.InterfaceByName(ifcName)
	if err != nil {
		return nil, fmt.Errorf("Could not find the new interface: %s", err)
	}

	return &Link{
		ifc: newIfc,
	}, nil
}
Exemple #5
0
// NewBridge creates new network bridge on Linux host with the name passed as a parameter.
// It is equivalent of running: ip link add name ${ifcName} type bridge
// It returns error if the bridge can not be created.
func NewBridgeWithName(ifcName string) (Bridger, error) {
	if ok, err := NetInterfaceNameValid(ifcName); !ok {
		return nil, err
	}

	if _, err := net.InterfaceByName(ifcName); err == nil {
		return nil, fmt.Errorf("Interface name %s already assigned on the host", ifcName)
	}

	if err := netlink.NetworkLinkAdd(ifcName, "bridge"); err != nil {
		return nil, err
	}

	newIfc, err := net.InterfaceByName(ifcName)
	if err != nil {
		return nil, fmt.Errorf("Could not find the new interface: %s", err)
	}

	return &Bridge{
		Link: Link{
			ifc: newIfc,
		},
	}, nil
}
)

var _ = Describe("Link Management", func() {
	var (
		l    devices.Link
		name string
		intf *net.Interface
	)

	BeforeEach(func() {
		cmd, err := gexec.Start(exec.Command("sh", "-c", "mountpoint /sys || mount -t sysfs sysfs /sys"), GinkgoWriter, GinkgoWriter)
		Expect(err).ToNot(HaveOccurred())
		Eventually(cmd).Should(gexec.Exit(0))

		name = fmt.Sprintf("gdn-test-%d", GinkgoParallelNode())
		Expect(netlink.NetworkLinkAdd(name, "dummy")).To(Succeed())
		intf, _ = net.InterfaceByName(name)
	})

	AfterEach(func() {
		cleanup(name)
	})

	Describe("AddIP", func() {
		Context("when the interface exists", func() {
			It("adds the IP succesffuly", func() {
				ip, subnet, _ := net.ParseCIDR("1.2.3.4/5")
				Expect(l.AddIP(intf, ip, subnet)).To(Succeed())

				intf, err := net.InterfaceByName(name)
				Expect(err).ToNot(HaveOccurred())
		Eventually(sess).Should(gexec.Exit(0))
	})

	AfterEach(func() {
		sess, err := gexec.Start(exec.Command("ip", "netns", "delete", fmt.Sprintf("gdn-netnstest-%d", GinkgoParallelNode())), GinkgoWriter, GinkgoWriter)
		Expect(err).NotTo(HaveOccurred())
		Eventually(sess).Should(gexec.Exit(0))
	})

	Describe("Executing a function inside the network namespace", func() {
		It("should be inside the namespace", func() {
			fd, err := os.Open(fmt.Sprintf("/var/run/netns/gdn-netnstest-%d", GinkgoParallelNode()))
			Expect(err).NotTo(HaveOccurred())

			Expect(netns.Exec(fd, func() error {
				netlink.NetworkLinkAdd("banana-iface", "bridge")

				_, err := net.InterfaceByName("banana-iface")
				Expect(err).NotTo(HaveOccurred())
				return nil
			})).To(Succeed())

			_, err = net.InterfaceByName("banana-iface")
			Expect(err).To(HaveOccurred())
		})

		It("bubbles up any errors", func() {
			fd, err := os.Open(fmt.Sprintf("/var/run/netns/gdn-netnstest-%d", GinkgoParallelNode()))
			Expect(err).NotTo(HaveOccurred())

			Expect(