Skip to content

Commit e722f97

Browse files
committed
- Added support to bridgeNetwork.Link
- Removed MAC and MTU configuration via AddInterface Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
1 parent 7fc65f0 commit e722f97

File tree

7 files changed

+235
-25
lines changed

7 files changed

+235
-25
lines changed

configure.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ func configureInterface(iface netlink.Link, settings *Interface) error {
1414
ErrMessage string
1515
}{
1616
{setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, settings.DstName)},
17-
{setInterfaceMAC, fmt.Sprintf("error setting interface %q MAC address to %q", ifaceName, settings.MacAddress)},
1817
{setInterfaceIP, fmt.Sprintf("error setting interface %q IP to %q", ifaceName, settings.Address)},
1918
{setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %q", ifaceName, settings.AddressIPv6)},
20-
{setInterfaceMTU, fmt.Sprintf("error setting interface %q MTU to %q", ifaceName, settings.MTU)},
2119
{setInterfaceGateway, fmt.Sprintf("error setting interface %q gateway to %q", ifaceName, settings.Gateway)},
2220
{setInterfaceGatewayIPv6, fmt.Sprintf("error setting interface %q IPv6 gateway to %q", ifaceName, settings.GatewayIPv6)},
2321
}
@@ -78,18 +76,6 @@ func setInterfaceIPv6(iface netlink.Link, settings *Interface) (err error) {
7876
return err
7977
}
8078

81-
func setInterfaceMAC(iface netlink.Link, settings *Interface) (err error) {
82-
var hwAddr net.HardwareAddr
83-
if hwAddr, err = net.ParseMAC(settings.MacAddress); err == nil {
84-
err = netlink.LinkSetHardwareAddr(iface, hwAddr)
85-
}
86-
return err
87-
}
88-
89-
func setInterfaceMTU(iface netlink.Link, settings *Interface) error {
90-
return netlink.LinkSetMTU(iface, settings.MTU)
91-
}
92-
9379
func setInterfaceName(iface netlink.Link, settings *Interface) error {
9480
return netlink.LinkSetName(iface, settings.DstName)
9581
}

drivers/bridge/interface.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package bridge
22

3-
import "github.com/vishvananda/netlink"
3+
import (
4+
"net"
5+
6+
"github.com/vishvananda/netlink"
7+
)
48

59
const (
610
// DefaultBridgeName is the default name for the bridge interface managed
@@ -10,8 +14,10 @@ const (
1014

1115
// Interface models the bridge network device.
1216
type bridgeInterface struct {
13-
Config *Configuration
14-
Link netlink.Link
17+
Config *Configuration
18+
Link netlink.Link
19+
bridgeIPv4 *net.IPNet
20+
bridgeIPv6 *net.IPNet
1521
}
1622

1723
// NewInterface creates a new bridge interface structure. It attempts to find

drivers/bridge/network.go

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
package bridge
22

33
import (
4+
"errors"
5+
"net"
6+
"strings"
7+
8+
"github.com/docker/libcontainer/utils"
49
"github.com/docker/libnetwork"
10+
"github.com/docker/libnetwork/ipallocator"
511
"github.com/vishvananda/netlink"
612
)
713

14+
// ErrEndpointExists is returned if more than one endpoint is added to the network
15+
var ErrEndpointExists = errors.New("Endpoint already exists (Only one endpoint allowed)")
16+
817
type bridgeNetwork struct {
918
NetworkName string
1019
bridge *bridgeInterface
20+
EndPoint *libnetwork.Interface
1121
}
1222

1323
func (b *bridgeNetwork) Name() string {
@@ -19,8 +29,99 @@ func (b *bridgeNetwork) Type() string {
1929
}
2030

2131
func (b *bridgeNetwork) Link(name string) ([]*libnetwork.Interface, error) {
22-
// TODO
23-
return nil, nil
32+
33+
var ipv6Addr net.IPNet
34+
35+
if b.EndPoint != nil {
36+
return nil, ErrEndpointExists
37+
}
38+
39+
name1, err := generateIfaceName()
40+
if err != nil {
41+
return nil, err
42+
}
43+
44+
name2, err := generateIfaceName()
45+
if err != nil {
46+
return nil, err
47+
}
48+
49+
veth := &netlink.Veth{
50+
LinkAttrs: netlink.LinkAttrs{Name: name1, TxQLen: 0},
51+
PeerName: name2}
52+
if err := netlink.LinkAdd(veth); err != nil {
53+
return nil, err
54+
}
55+
56+
host, err := netlink.LinkByName(name1)
57+
if err != nil {
58+
return nil, err
59+
}
60+
defer func() {
61+
if err != nil {
62+
netlink.LinkDel(host)
63+
}
64+
}()
65+
66+
container, err := netlink.LinkByName(name2)
67+
if err != nil {
68+
return nil, err
69+
}
70+
defer func() {
71+
if err != nil {
72+
netlink.LinkDel(container)
73+
}
74+
}()
75+
76+
if err = netlink.LinkSetMaster(host,
77+
&netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: b.bridge.Config.BridgeName}}); err != nil {
78+
return nil, err
79+
}
80+
81+
ip4, err := ipallocator.RequestIP(b.bridge.bridgeIPv4, nil)
82+
if err != nil {
83+
return nil, err
84+
}
85+
ipv4Addr := net.IPNet{IP: ip4, Mask: b.bridge.bridgeIPv4.Mask}
86+
87+
if b.bridge.Config.EnableIPv6 {
88+
ip6, err := ipallocator.RequestIP(b.bridge.bridgeIPv6, nil)
89+
if err != nil {
90+
return nil, err
91+
}
92+
ipv6Addr = net.IPNet{IP: ip6, Mask: b.bridge.bridgeIPv6.Mask}
93+
}
94+
95+
var interfaces []*libnetwork.Interface
96+
intf := &libnetwork.Interface{}
97+
intf.SrcName = name2
98+
intf.DstName = "eth0"
99+
intf.Address = ipv4Addr.String()
100+
intf.Gateway = b.bridge.bridgeIPv4.IP.String()
101+
if b.bridge.Config.EnableIPv6 {
102+
intf.AddressIPv6 = ipv6Addr.String()
103+
intf.GatewayIPv6 = b.bridge.bridgeIPv6.IP.String()
104+
}
105+
106+
b.EndPoint = intf
107+
interfaces = append(interfaces, intf)
108+
return interfaces, nil
109+
}
110+
111+
func generateIfaceName() (string, error) {
112+
for i := 0; i < 10; i++ {
113+
name, err := utils.GenerateRandomName("veth", 7)
114+
if err != nil {
115+
continue
116+
}
117+
if _, err := net.InterfaceByName(name); err != nil {
118+
if strings.Contains(err.Error(), "no such") {
119+
return name, nil
120+
}
121+
return "", err
122+
}
123+
}
124+
return "", errors.New("Failed to find name for new interface")
24125
}
25126

26127
func (b *bridgeNetwork) Delete() error {

drivers/bridge/network_test.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package bridge
2+
3+
import (
4+
"net"
5+
"testing"
6+
7+
"github.com/docker/libnetwork"
8+
"github.com/vishvananda/netlink"
9+
)
10+
11+
func TestLinkCreate(t *testing.T) {
12+
defer libnetwork.SetupTestNetNS(t)()
13+
d := &driver{}
14+
15+
config := &Configuration{
16+
BridgeName: DefaultBridgeName,
17+
EnableIPv6: true}
18+
netw, err := d.CreateNetwork("dummy", config)
19+
if err != nil {
20+
t.Fatalf("Failed to create bridge: %v", err)
21+
}
22+
23+
interfaces, err := netw.Link("ep")
24+
if err != nil {
25+
t.Fatalf("Failed to create a link: %v", err)
26+
}
27+
28+
if len(interfaces) != 1 {
29+
t.Fatalf("Expected exactly one interface. Instead got %d interface(s)", len(interfaces))
30+
}
31+
32+
if interfaces[0].DstName == "" {
33+
t.Fatal("Invalid Dstname returned")
34+
}
35+
36+
_, err = netlink.LinkByName(interfaces[0].SrcName)
37+
if err != nil {
38+
t.Fatalf("Could not find source link %s: %v", interfaces[0].SrcName, err)
39+
}
40+
41+
ip, _, err := net.ParseCIDR(interfaces[0].Address)
42+
if err != nil {
43+
t.Fatalf("Invalid IPv4 address returned, ip = %s: %v", interfaces[0].Address, err)
44+
}
45+
46+
b := netw.(*bridgeNetwork)
47+
if !b.bridge.bridgeIPv4.Contains(ip) {
48+
t.Fatalf("IP %s is not a valid ip in the subnet %s", ip.String(), b.bridge.bridgeIPv4.String())
49+
}
50+
51+
ip6, _, err := net.ParseCIDR(interfaces[0].AddressIPv6)
52+
if err != nil {
53+
t.Fatalf("Invalid IPv6 address returned, ip = %s: %v", interfaces[0].AddressIPv6, err)
54+
}
55+
56+
if !b.bridge.bridgeIPv6.Contains(ip6) {
57+
t.Fatalf("IP %s is not a valid ip in the subnet %s", ip6.String(), bridgeIPv6.String())
58+
}
59+
60+
if interfaces[0].Gateway != b.bridge.bridgeIPv4.IP.String() {
61+
t.Fatalf("Invalid default gateway. Expected %s. Got %s", b.bridge.bridgeIPv4.IP.String(),
62+
interfaces[0].Gateway)
63+
}
64+
65+
if interfaces[0].GatewayIPv6 != b.bridge.bridgeIPv6.IP.String() {
66+
t.Fatalf("Invalid default gateway for IPv6. Expected %s. Got %s", b.bridge.bridgeIPv6.IP.String(),
67+
interfaces[0].GatewayIPv6)
68+
}
69+
}
70+
71+
func TestLinkCreateTwo(t *testing.T) {
72+
defer libnetwork.SetupTestNetNS(t)()
73+
d := &driver{}
74+
75+
config := &Configuration{
76+
BridgeName: DefaultBridgeName,
77+
EnableIPv6: true}
78+
netw, err := d.CreateNetwork("dummy", config)
79+
if err != nil {
80+
t.Fatalf("Failed to create bridge: %v", err)
81+
}
82+
83+
_, err = netw.Link("ep")
84+
if err != nil {
85+
t.Fatalf("Failed to create a link: %v", err)
86+
}
87+
88+
_, err = netw.Link("ep1")
89+
if err != nil {
90+
if err != ErrEndpointExists {
91+
t.Fatalf("Failed with a wrong error :%v", err)
92+
}
93+
} else {
94+
t.Fatalf("Expected to fail while trying to add more than one endpoint")
95+
}
96+
}
97+
98+
func TestLinkCreateNoEnableIPv6(t *testing.T) {
99+
defer libnetwork.SetupTestNetNS(t)()
100+
d := &driver{}
101+
102+
config := &Configuration{
103+
BridgeName: DefaultBridgeName}
104+
netw, err := d.CreateNetwork("dummy", config)
105+
if err != nil {
106+
t.Fatalf("Failed to create bridge: %v", err)
107+
}
108+
109+
interfaces, err := netw.Link("ep")
110+
if err != nil {
111+
t.Fatalf("Failed to create a link: %v", err)
112+
}
113+
114+
if interfaces[0].AddressIPv6 != "" ||
115+
interfaces[0].GatewayIPv6 != "" {
116+
t.Fatalf("Expected IPv6 address and GatewayIPv6 to be empty when IPv6 enabled. Instead got IPv6 = %s and GatewayIPv6 = %s",
117+
interfaces[0].AddressIPv6, interfaces[0].GatewayIPv6)
118+
}
119+
}

drivers/bridge/setup_ipv4.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ func setupBridgeIPv4(i *bridgeInterface) error {
5252
return fmt.Errorf("Failed to add IPv4 address %s to bridge: %v", bridgeIPv4, err)
5353
}
5454

55+
i.bridgeIPv4 = bridgeIPv4
56+
5557
return nil
5658
}
5759

drivers/bridge/setup_ipv6.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,7 @@ func setupBridgeIPv6(i *bridgeInterface) error {
3333
return fmt.Errorf("Failed to add IPv6 address %s to bridge: %v", bridgeIPv6, err)
3434
}
3535

36+
i.bridgeIPv6 = bridgeIPv6
37+
3638
return nil
3739
}

network.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ type Interface struct {
4444
// network namespace.
4545
DstName string
4646

47-
// MAC address for the interface.
48-
MacAddress string
49-
5047
// IPv4 address for the interface.
5148
Address string
5249

@@ -58,9 +55,6 @@ type Interface struct {
5855

5956
// IPv6 gateway for the interface.
6057
GatewayIPv6 string
61-
62-
// Network MTU.
63-
MTU int
6458
}
6559

6660
// A Network represents a logical connectivity zone that containers may

0 commit comments

Comments
 (0)