1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

- Added support to bridgeNetwork.Link

- Removed MAC and MTU configuration via AddInterface

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
Jana Radhakrishnan 2015-04-10 16:02:25 +00:00
parent d6cc62a13b
commit 2d364e2c34
7 changed files with 235 additions and 25 deletions

View file

@ -14,10 +14,8 @@ func configureInterface(iface netlink.Link, settings *Interface) error {
ErrMessage string
}{
{setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, settings.DstName)},
{setInterfaceMAC, fmt.Sprintf("error setting interface %q MAC address to %q", ifaceName, settings.MacAddress)},
{setInterfaceIP, fmt.Sprintf("error setting interface %q IP to %q", ifaceName, settings.Address)},
{setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %q", ifaceName, settings.AddressIPv6)},
{setInterfaceMTU, fmt.Sprintf("error setting interface %q MTU to %q", ifaceName, settings.MTU)},
{setInterfaceGateway, fmt.Sprintf("error setting interface %q gateway to %q", ifaceName, settings.Gateway)},
{setInterfaceGatewayIPv6, fmt.Sprintf("error setting interface %q IPv6 gateway to %q", ifaceName, settings.GatewayIPv6)},
}
@ -78,18 +76,6 @@ func setInterfaceIPv6(iface netlink.Link, settings *Interface) (err error) {
return err
}
func setInterfaceMAC(iface netlink.Link, settings *Interface) (err error) {
var hwAddr net.HardwareAddr
if hwAddr, err = net.ParseMAC(settings.MacAddress); err == nil {
err = netlink.LinkSetHardwareAddr(iface, hwAddr)
}
return err
}
func setInterfaceMTU(iface netlink.Link, settings *Interface) error {
return netlink.LinkSetMTU(iface, settings.MTU)
}
func setInterfaceName(iface netlink.Link, settings *Interface) error {
return netlink.LinkSetName(iface, settings.DstName)
}

View file

@ -1,6 +1,10 @@
package bridge
import "github.com/vishvananda/netlink"
import (
"net"
"github.com/vishvananda/netlink"
)
const (
// DefaultBridgeName is the default name for the bridge interface managed
@ -10,8 +14,10 @@ const (
// Interface models the bridge network device.
type bridgeInterface struct {
Config *Configuration
Link netlink.Link
Config *Configuration
Link netlink.Link
bridgeIPv4 *net.IPNet
bridgeIPv6 *net.IPNet
}
// NewInterface creates a new bridge interface structure. It attempts to find

View file

@ -1,13 +1,23 @@
package bridge
import (
"errors"
"net"
"strings"
"github.com/docker/libcontainer/utils"
"github.com/docker/libnetwork"
"github.com/docker/libnetwork/ipallocator"
"github.com/vishvananda/netlink"
)
// ErrEndpointExists is returned if more than one endpoint is added to the network
var ErrEndpointExists = errors.New("Endpoint already exists (Only one endpoint allowed)")
type bridgeNetwork struct {
NetworkName string
bridge *bridgeInterface
EndPoint *libnetwork.Interface
}
func (b *bridgeNetwork) Name() string {
@ -19,8 +29,99 @@ func (b *bridgeNetwork) Type() string {
}
func (b *bridgeNetwork) Link(name string) ([]*libnetwork.Interface, error) {
// TODO
return nil, nil
var ipv6Addr net.IPNet
if b.EndPoint != nil {
return nil, ErrEndpointExists
}
name1, err := generateIfaceName()
if err != nil {
return nil, err
}
name2, err := generateIfaceName()
if err != nil {
return nil, err
}
veth := &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{Name: name1, TxQLen: 0},
PeerName: name2}
if err := netlink.LinkAdd(veth); err != nil {
return nil, err
}
host, err := netlink.LinkByName(name1)
if err != nil {
return nil, err
}
defer func() {
if err != nil {
netlink.LinkDel(host)
}
}()
container, err := netlink.LinkByName(name2)
if err != nil {
return nil, err
}
defer func() {
if err != nil {
netlink.LinkDel(container)
}
}()
if err = netlink.LinkSetMaster(host,
&netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: b.bridge.Config.BridgeName}}); err != nil {
return nil, err
}
ip4, err := ipallocator.RequestIP(b.bridge.bridgeIPv4, nil)
if err != nil {
return nil, err
}
ipv4Addr := net.IPNet{IP: ip4, Mask: b.bridge.bridgeIPv4.Mask}
if b.bridge.Config.EnableIPv6 {
ip6, err := ipallocator.RequestIP(b.bridge.bridgeIPv6, nil)
if err != nil {
return nil, err
}
ipv6Addr = net.IPNet{IP: ip6, Mask: b.bridge.bridgeIPv6.Mask}
}
var interfaces []*libnetwork.Interface
intf := &libnetwork.Interface{}
intf.SrcName = name2
intf.DstName = "eth0"
intf.Address = ipv4Addr.String()
intf.Gateway = b.bridge.bridgeIPv4.IP.String()
if b.bridge.Config.EnableIPv6 {
intf.AddressIPv6 = ipv6Addr.String()
intf.GatewayIPv6 = b.bridge.bridgeIPv6.IP.String()
}
b.EndPoint = intf
interfaces = append(interfaces, intf)
return interfaces, nil
}
func generateIfaceName() (string, error) {
for i := 0; i < 10; i++ {
name, err := utils.GenerateRandomName("veth", 7)
if err != nil {
continue
}
if _, err := net.InterfaceByName(name); err != nil {
if strings.Contains(err.Error(), "no such") {
return name, nil
}
return "", err
}
}
return "", errors.New("Failed to find name for new interface")
}
func (b *bridgeNetwork) Delete() error {

View file

@ -0,0 +1,119 @@
package bridge
import (
"net"
"testing"
"github.com/docker/libnetwork"
"github.com/vishvananda/netlink"
)
func TestLinkCreate(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
d := &driver{}
config := &Configuration{
BridgeName: DefaultBridgeName,
EnableIPv6: true}
netw, err := d.CreateNetwork("dummy", config)
if err != nil {
t.Fatalf("Failed to create bridge: %v", err)
}
interfaces, err := netw.Link("ep")
if err != nil {
t.Fatalf("Failed to create a link: %v", err)
}
if len(interfaces) != 1 {
t.Fatalf("Expected exactly one interface. Instead got %d interface(s)", len(interfaces))
}
if interfaces[0].DstName == "" {
t.Fatal("Invalid Dstname returned")
}
_, err = netlink.LinkByName(interfaces[0].SrcName)
if err != nil {
t.Fatalf("Could not find source link %s: %v", interfaces[0].SrcName, err)
}
ip, _, err := net.ParseCIDR(interfaces[0].Address)
if err != nil {
t.Fatalf("Invalid IPv4 address returned, ip = %s: %v", interfaces[0].Address, err)
}
b := netw.(*bridgeNetwork)
if !b.bridge.bridgeIPv4.Contains(ip) {
t.Fatalf("IP %s is not a valid ip in the subnet %s", ip.String(), b.bridge.bridgeIPv4.String())
}
ip6, _, err := net.ParseCIDR(interfaces[0].AddressIPv6)
if err != nil {
t.Fatalf("Invalid IPv6 address returned, ip = %s: %v", interfaces[0].AddressIPv6, err)
}
if !b.bridge.bridgeIPv6.Contains(ip6) {
t.Fatalf("IP %s is not a valid ip in the subnet %s", ip6.String(), bridgeIPv6.String())
}
if interfaces[0].Gateway != b.bridge.bridgeIPv4.IP.String() {
t.Fatalf("Invalid default gateway. Expected %s. Got %s", b.bridge.bridgeIPv4.IP.String(),
interfaces[0].Gateway)
}
if interfaces[0].GatewayIPv6 != b.bridge.bridgeIPv6.IP.String() {
t.Fatalf("Invalid default gateway for IPv6. Expected %s. Got %s", b.bridge.bridgeIPv6.IP.String(),
interfaces[0].GatewayIPv6)
}
}
func TestLinkCreateTwo(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
d := &driver{}
config := &Configuration{
BridgeName: DefaultBridgeName,
EnableIPv6: true}
netw, err := d.CreateNetwork("dummy", config)
if err != nil {
t.Fatalf("Failed to create bridge: %v", err)
}
_, err = netw.Link("ep")
if err != nil {
t.Fatalf("Failed to create a link: %v", err)
}
_, err = netw.Link("ep1")
if err != nil {
if err != ErrEndpointExists {
t.Fatalf("Failed with a wrong error :%v", err)
}
} else {
t.Fatalf("Expected to fail while trying to add more than one endpoint")
}
}
func TestLinkCreateNoEnableIPv6(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
d := &driver{}
config := &Configuration{
BridgeName: DefaultBridgeName}
netw, err := d.CreateNetwork("dummy", config)
if err != nil {
t.Fatalf("Failed to create bridge: %v", err)
}
interfaces, err := netw.Link("ep")
if err != nil {
t.Fatalf("Failed to create a link: %v", err)
}
if interfaces[0].AddressIPv6 != "" ||
interfaces[0].GatewayIPv6 != "" {
t.Fatalf("Expected IPv6 address and GatewayIPv6 to be empty when IPv6 enabled. Instead got IPv6 = %s and GatewayIPv6 = %s",
interfaces[0].AddressIPv6, interfaces[0].GatewayIPv6)
}
}

View file

@ -52,6 +52,8 @@ func setupBridgeIPv4(i *bridgeInterface) error {
return fmt.Errorf("Failed to add IPv4 address %s to bridge: %v", bridgeIPv4, err)
}
i.bridgeIPv4 = bridgeIPv4
return nil
}

View file

@ -33,5 +33,7 @@ func setupBridgeIPv6(i *bridgeInterface) error {
return fmt.Errorf("Failed to add IPv6 address %s to bridge: %v", bridgeIPv6, err)
}
i.bridgeIPv6 = bridgeIPv6
return nil
}

View file

@ -44,9 +44,6 @@ type Interface struct {
// network namespace.
DstName string
// MAC address for the interface.
MacAddress string
// IPv4 address for the interface.
Address string
@ -58,9 +55,6 @@ type Interface struct {
// IPv6 gateway for the interface.
GatewayIPv6 string
// Network MTU.
MTU int
}
// A Network represents a logical connectivity zone that containers may