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.srcName = containerIfName
|
||||||
endpoint.macAddress = ifInfo.MacAddress()
|
endpoint.macAddress = ifInfo.MacAddress()
|
||||||
endpoint.addr = ifInfo.Address()
|
endpoint.addr = ifInfo.Address()
|
||||||
endpoint.addrv6 = ifInfo.AddressIPv6()
|
endpoint.addrv6 = ifInfo.AddressIPv6()
|
||||||
|
|
||||||
// Down the interface before configuring mac address.
|
// Set the sbox's MAC if not provided. If specified, use the one configured by user, otherwise generate one based on IP.
|
||||||
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.
|
|
||||||
if endpoint.macAddress == nil {
|
if endpoint.macAddress == nil {
|
||||||
endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP)
|
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
|
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
|
// Up the host interface after finishing all netlink configuration
|
||||||
if err = netlink.LinkSetUp(host); err != nil {
|
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}
|
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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package bridge
|
package bridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -13,7 +12,6 @@ import (
|
||||||
"github.com/docker/libnetwork/netlabel"
|
"github.com/docker/libnetwork/netlabel"
|
||||||
"github.com/docker/libnetwork/testutils"
|
"github.com/docker/libnetwork/testutils"
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getIPv4Data(t *testing.T) []driverapi.IPAMData {
|
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 {
|
func getExposedPorts() []types.TransportPort {
|
||||||
return []types.TransportPort{
|
return []types.TransportPort{
|
||||||
types.TransportPort{Proto: types.TCP, Port: uint16(5000)},
|
types.TransportPort{Proto: types.TCP, Port: uint16(5000)},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package remote
|
package remote
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -290,7 +291,7 @@ func TestRemoteDriver(t *testing.T) {
|
||||||
dst: "vethdst",
|
dst: "vethdst",
|
||||||
address: "192.168.5.7/16",
|
address: "192.168.5.7/16",
|
||||||
addressIPv6: "2001:DB8::5:7/48",
|
addressIPv6: "2001:DB8::5:7/48",
|
||||||
macAddress: "",
|
macAddress: "ab:cd:ef:ee:ee:ee",
|
||||||
gateway: "192.168.0.1",
|
gateway: "192.168.0.1",
|
||||||
gatewayIPv6: "2001:DB8::1",
|
gatewayIPv6: "2001:DB8::1",
|
||||||
hostsPath: "/here/comes/the/host/path",
|
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{} {
|
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
||||||
iface := map[string]interface{}{
|
iface := map[string]interface{}{
|
||||||
"MacAddress": ep.macAddress,
|
"MacAddress": ep.macAddress,
|
||||||
|
"Address": ep.address,
|
||||||
|
"AddressIPv6": ep.addressIPv6,
|
||||||
}
|
}
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"Interface": iface,
|
"Interface": iface,
|
||||||
|
@ -401,11 +404,19 @@ func TestRemoteDriver(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
endID := "dummy-endpoint"
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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"}
|
joinOpts := map[string]interface{}{"foo": "fooValue"}
|
||||||
err = d.Join(netID, endID, "sandbox-key", ep, joinOpts)
|
err = d.Join(netID, endID, "sandbox-key", ep, joinOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -19,6 +19,7 @@ type nwIface struct {
|
||||||
dstName string
|
dstName string
|
||||||
master string
|
master string
|
||||||
dstMaster string
|
dstMaster string
|
||||||
|
mac net.HardwareAddr
|
||||||
address *net.IPNet
|
address *net.IPNet
|
||||||
addressIPv6 *net.IPNet
|
addressIPv6 *net.IPNet
|
||||||
routes []*net.IPNet
|
routes []*net.IPNet
|
||||||
|
@ -62,6 +63,13 @@ func (i *nwIface) Master() string {
|
||||||
return i.master
|
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 {
|
func (i *nwIface) Address() *net.IPNet {
|
||||||
i.Lock()
|
i.Lock()
|
||||||
defer i.Unlock()
|
defer i.Unlock()
|
||||||
|
@ -291,6 +299,7 @@ func configureInterface(iface netlink.Link, i *nwIface) error {
|
||||||
ErrMessage string
|
ErrMessage string
|
||||||
}{
|
}{
|
||||||
{setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, i.DstName())},
|
{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())},
|
{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())},
|
{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())},
|
{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()}})
|
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 {
|
func setInterfaceIP(iface netlink.Link, i *nwIface) error {
|
||||||
if i.Address() == nil {
|
if i.Address() == nil {
|
||||||
return 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 {
|
func (n *networkNamespace) Address(addr *net.IPNet) IfaceOption {
|
||||||
return func(i *nwIface) {
|
return func(i *nwIface) {
|
||||||
i.address = addr
|
i.address = addr
|
||||||
|
|
|
@ -76,6 +76,9 @@ type IfaceOptionSetter interface {
|
||||||
// Bridge returns an option setter to set if the interface is a bridge.
|
// Bridge returns an option setter to set if the interface is a bridge.
|
||||||
Bridge(bool) IfaceOption
|
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 returns an option setter to set IPv4 address.
|
||||||
Address(*net.IPNet) IfaceOption
|
Address(*net.IPNet) IfaceOption
|
||||||
|
|
||||||
|
|
|
@ -466,6 +466,9 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
|
||||||
if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
|
if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
|
||||||
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6))
|
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 {
|
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)
|
return fmt.Errorf("failed to add interface %s to sandbox: %v", i.srcName, err)
|
||||||
|
|
Loading…
Reference in a new issue