mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Libnetwork to set container interface's MAC
- Consistently with what it does for IP addresses, libnetwork will also program the container interface's MAC address with the value set by network driver in InterfaceInfo. Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
parent
f3f0bb75b8
commit
6b40581ea5
7 changed files with 46 additions and 62 deletions
|
@ -934,28 +934,19 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|||
}
|
||||
}
|
||||
|
||||
// Create the sandbox side pipe interface
|
||||
// Store the sandbox side pipe interface parameters
|
||||
endpoint.srcName = containerIfName
|
||||
endpoint.macAddress = ifInfo.MacAddress()
|
||||
endpoint.addr = ifInfo.Address()
|
||||
endpoint.addrv6 = ifInfo.AddressIPv6()
|
||||
|
||||
// Down the interface before configuring mac address.
|
||||
if err = netlink.LinkSetDown(sbox); err != nil {
|
||||
return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err)
|
||||
}
|
||||
|
||||
// Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
|
||||
// Set the sbox's MAC if not provided. If specified, use the one configured by user, otherwise generate one based on IP.
|
||||
if endpoint.macAddress == nil {
|
||||
endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP)
|
||||
if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil {
|
||||
if err = ifInfo.SetMacAddress(endpoint.macAddress); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = netlink.LinkSetHardwareAddr(sbox, endpoint.macAddress)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err)
|
||||
}
|
||||
|
||||
// Up the host interface after finishing all netlink configuration
|
||||
if err = netlink.LinkSetUp(host); err != nil {
|
||||
|
@ -982,7 +973,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|||
}
|
||||
|
||||
endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask}
|
||||
if err := ifInfo.SetIPAddress(endpoint.addrv6); err != nil {
|
||||
if err = ifInfo.SetIPAddress(endpoint.addrv6); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
|
@ -13,7 +12,6 @@ import (
|
|||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func getIPv4Data(t *testing.T) []driverapi.IPAMData {
|
||||
|
@ -497,50 +495,6 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCreateLinkWithOptions(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
if err := d.configure(nil); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
netconfig := &networkConfiguration{BridgeName: DefaultBridgeName}
|
||||
netOptions := make(map[string]interface{})
|
||||
netOptions[netlabel.GenericData] = netconfig
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
err := d.CreateNetwork("net1", netOptions, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
mac := net.HardwareAddr([]byte{0x1e, 0x67, 0x66, 0x44, 0x55, 0x66})
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.MacAddress] = mac
|
||||
|
||||
te := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("net1", "ep", te.Interface(), epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint: %s", err.Error())
|
||||
}
|
||||
|
||||
err = d.Join("net1", "ep", "sbox", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to join the endpoint: %v", err)
|
||||
}
|
||||
|
||||
ifaceName := te.iface.srcName
|
||||
veth, err := netlink.LinkByName(ifaceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(mac, veth.Attrs().HardwareAddr) {
|
||||
t.Fatalf("Failed to parse and program endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
func getExposedPorts() []types.TransportPort {
|
||||
return []types.TransportPort{
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(5000)},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package remote
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -290,7 +291,7 @@ func TestRemoteDriver(t *testing.T) {
|
|||
dst: "vethdst",
|
||||
address: "192.168.5.7/16",
|
||||
addressIPv6: "2001:DB8::5:7/48",
|
||||
macAddress: "",
|
||||
macAddress: "ab:cd:ef:ee:ee:ee",
|
||||
gateway: "192.168.0.1",
|
||||
gatewayIPv6: "2001:DB8::1",
|
||||
hostsPath: "/here/comes/the/host/path",
|
||||
|
@ -326,7 +327,9 @@ func TestRemoteDriver(t *testing.T) {
|
|||
})
|
||||
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
||||
iface := map[string]interface{}{
|
||||
"MacAddress": ep.macAddress,
|
||||
"MacAddress": ep.macAddress,
|
||||
"Address": ep.address,
|
||||
"AddressIPv6": ep.addressIPv6,
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"Interface": iface,
|
||||
|
@ -401,11 +404,19 @@ func TestRemoteDriver(t *testing.T) {
|
|||
}
|
||||
|
||||
endID := "dummy-endpoint"
|
||||
err = d.CreateEndpoint(netID, endID, ep, map[string]interface{}{})
|
||||
ifInfo := &testEndpoint{}
|
||||
err = d.CreateEndpoint(netID, endID, ifInfo, map[string]interface{}{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(ep.MacAddress(), ifInfo.MacAddress()) || !types.CompareIPNet(ep.Address(), ifInfo.Address()) ||
|
||||
!types.CompareIPNet(ep.AddressIPv6(), ifInfo.AddressIPv6()) {
|
||||
t.Fatalf("Unexpected InterfaceInfo data. Expected (%s, %s, %s). Got (%v, %v, %v)",
|
||||
ep.MacAddress(), ep.Address(), ep.AddressIPv6(),
|
||||
ifInfo.MacAddress(), ifInfo.Address(), ifInfo.AddressIPv6())
|
||||
}
|
||||
|
||||
joinOpts := map[string]interface{}{"foo": "fooValue"}
|
||||
err = d.Join(netID, endID, "sandbox-key", ep, joinOpts)
|
||||
if err != nil {
|
||||
|
|
|
@ -19,6 +19,7 @@ type nwIface struct {
|
|||
dstName string
|
||||
master string
|
||||
dstMaster string
|
||||
mac net.HardwareAddr
|
||||
address *net.IPNet
|
||||
addressIPv6 *net.IPNet
|
||||
routes []*net.IPNet
|
||||
|
@ -62,6 +63,13 @@ func (i *nwIface) Master() string {
|
|||
return i.master
|
||||
}
|
||||
|
||||
func (i *nwIface) MacAddress() net.HardwareAddr {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
return types.GetMacCopy(i.mac)
|
||||
}
|
||||
|
||||
func (i *nwIface) Address() *net.IPNet {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
@ -291,6 +299,7 @@ func configureInterface(iface netlink.Link, i *nwIface) error {
|
|||
ErrMessage string
|
||||
}{
|
||||
{setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, i.DstName())},
|
||||
{setInterfaceMAC, fmt.Sprintf("error setting interface %q MAC to %q", ifaceName, i.MacAddress())},
|
||||
{setInterfaceIP, fmt.Sprintf("error setting interface %q IP to %q", ifaceName, i.Address())},
|
||||
{setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %q", ifaceName, i.AddressIPv6())},
|
||||
{setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())},
|
||||
|
@ -313,6 +322,13 @@ func setInterfaceMaster(iface netlink.Link, i *nwIface) error {
|
|||
LinkAttrs: netlink.LinkAttrs{Name: i.DstMaster()}})
|
||||
}
|
||||
|
||||
func setInterfaceMAC(iface netlink.Link, i *nwIface) error {
|
||||
if i.MacAddress() == nil {
|
||||
return nil
|
||||
}
|
||||
return netlink.LinkSetHardwareAddr(iface, i.MacAddress())
|
||||
}
|
||||
|
||||
func setInterfaceIP(iface netlink.Link, i *nwIface) error {
|
||||
if i.Address() == nil {
|
||||
return nil
|
||||
|
|
|
@ -42,6 +42,12 @@ func (n *networkNamespace) Master(name string) IfaceOption {
|
|||
}
|
||||
}
|
||||
|
||||
func (n *networkNamespace) MacAddress(mac net.HardwareAddr) IfaceOption {
|
||||
return func(i *nwIface) {
|
||||
i.mac = mac
|
||||
}
|
||||
}
|
||||
|
||||
func (n *networkNamespace) Address(addr *net.IPNet) IfaceOption {
|
||||
return func(i *nwIface) {
|
||||
i.address = addr
|
||||
|
|
|
@ -76,6 +76,9 @@ type IfaceOptionSetter interface {
|
|||
// Bridge returns an option setter to set if the interface is a bridge.
|
||||
Bridge(bool) IfaceOption
|
||||
|
||||
// MacAddress returns an option setter to set the MAC address.
|
||||
MacAddress(net.HardwareAddr) IfaceOption
|
||||
|
||||
// Address returns an option setter to set IPv4 address.
|
||||
Address(*net.IPNet) IfaceOption
|
||||
|
||||
|
|
|
@ -466,6 +466,9 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
|
|||
if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
|
||||
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6))
|
||||
}
|
||||
if i.mac != nil {
|
||||
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac))
|
||||
}
|
||||
|
||||
if err := sb.osSbox.AddInterface(i.srcName, i.dstPrefix, ifaceOptions...); err != nil {
|
||||
return fmt.Errorf("failed to add interface %s to sandbox: %v", i.srcName, err)
|
||||
|
|
Loading…
Reference in a new issue