From 58b7527ecbf053004cc555aa433168395f0ec622 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 22 Jul 2009 12:21:25 -0700 Subject: [PATCH] xenserver: Honor the MAC address specified in xapi database for bonds. The xapi database for PIFs specifies the MAC address that should be used for bonds, but interface-reconfigure didn't honor it and ovs-vswitchd didn't have a way to configure it anyhow. This commit fixes both problems. Bug #1645. --- vswitchd/bridge.c | 56 +++++++++++++++---- vswitchd/ovs-vswitchd.conf.5.in | 20 +++++-- ...pt_xensource_libexec_interface-reconfigure | 3 + 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 6a82a031..10bd2445 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -613,31 +613,63 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN], memset(ea, 0xff, sizeof ea); for (i = 0; i < br->n_ports; i++) { struct port *port = br->ports[i]; + uint8_t iface_ea[ETH_ADDR_LEN]; + uint64_t iface_ea_u64; + struct iface *iface; + + /* Mirror output ports don't participate. */ if (port->is_mirror_output_port) { continue; } - for (j = 0; j < port->n_ifaces; j++) { - struct iface *iface = port->ifaces[j]; - uint8_t iface_ea[ETH_ADDR_LEN]; + + /* Choose the MAC address to represent the port. */ + iface_ea_u64 = cfg_get_mac(0, "port.%s.mac", port->name); + if (iface_ea_u64) { + /* User specified explicitly. */ + eth_addr_from_uint64(iface_ea_u64, iface_ea); + } else { + /* Choose the interface whose MAC address will represent the port. + * The Linux kernel bonding code always chooses the MAC address of + * the first slave added to a bond, and the Fedora networking + * scripts always add slaves to a bond in alphabetical order, so + * for compatibility we choose the interface with the name that is + * first in alphabetical order. */ + iface = port->ifaces[0]; + for (j = 1; j < port->n_ifaces; j++) { + struct iface *candidate = port->ifaces[j]; + if (strcmp(candidate->name, iface->name) < 0) { + iface = candidate; + } + } + + /* The local port doesn't count (since we're trying to choose its + * MAC address anyway). Other internal ports don't count because + * we really want a physical MAC if we can get it, and internal + * ports typically have randomly generated MACs. */ if (iface->dp_ifidx == ODPP_LOCAL || cfg_get_bool(0, "iface.%s.internal", iface->name)) { continue; } + + /* Grab MAC. */ error = netdev_nodev_get_etheraddr(iface->name, iface_ea); - if (!error) { - if (!eth_addr_is_multicast(iface_ea) && - !eth_addr_is_reserved(iface_ea) && - !eth_addr_is_zero(iface_ea) && - memcmp(iface_ea, ea, ETH_ADDR_LEN) < 0) { - memcpy(ea, iface_ea, ETH_ADDR_LEN); - *devname = iface->name; - } - } else { + if (error) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_ERR_RL(&rl, "failed to obtain Ethernet address of %s: %s", iface->name, strerror(error)); + continue; } } + + /* Compare against our current choice. */ + if (!eth_addr_is_multicast(iface_ea) && + !eth_addr_is_reserved(iface_ea) && + !eth_addr_is_zero(iface_ea) && + memcmp(iface_ea, ea, ETH_ADDR_LEN) < 0) + { + memcpy(ea, iface_ea, ETH_ADDR_LEN); + *devname = iface->name; + } } if (eth_addr_is_multicast(ea) || eth_addr_is_vif(ea)) { memcpy(ea, br->default_ea, ETH_ADDR_LEN); diff --git a/vswitchd/ovs-vswitchd.conf.5.in b/vswitchd/ovs-vswitchd.conf.5.in index 25332db4..bd0ffb74 100644 --- a/vswitchd/ovs-vswitchd.conf.5.in +++ b/vswitchd/ovs-vswitchd.conf.5.in @@ -72,11 +72,23 @@ in the bridge, by specifying it as one of the values for key included, then its MAC address is by default the lowest-numbered MAC address among the other bridge ports, ignoring other internal ports and bridge ports that are -used as port mirroring destinations (see \fBPort Mirroring\fR, below). To -use a specific MAC address instead, set \fBbridge.\fIname\fB.mac\fR to -a MAC address in the format +used as port mirroring destinations (see \fBPort Mirroring\fR, below). +For this purpose, the MAC of a bonded port (see \fBNetwork Device +Bonding\fR, below) is by default the MAC of its slave whose name is first in +alphabetical order. +There are two ways to modify this algorithm for selecting the MAC +address of the local port: +.IP \(bu +To use a specific MAC address for the local port, set +\fBbridge.\fIname\fB.mac\fR to a MAC address in the format \fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR, where each -\fIx\fR is a hex digit. If no valid MAC address can be determined +\fIx\fR is a hex digit. +.IP \(bu +To override the MAC of a port for the purpose of this algorithm, set +\fBport.\fIport\fB.mac\fR to a MAC address in the format described +above. +.PP +If no valid MAC address can be determined either of these ways, then a MAC address is randomly generated. .PP The following syntax defines a bridge named \fBmybr\fR, configured diff --git a/xenserver/opt_xensource_libexec_interface-reconfigure b/xenserver/opt_xensource_libexec_interface-reconfigure index 2a32fad2..1ff53590 100755 --- a/xenserver/opt_xensource_libexec_interface-reconfigure +++ b/xenserver/opt_xensource_libexec_interface-reconfigure @@ -750,6 +750,9 @@ def configure_bond(pif): argv += ["--add=bonding.%s.slave=%s" % (interface, slave) for slave in physdevs] + if pifrec['MAC'] != "": + argv += ['--add=port.%s.mac=%s' % (interface, pifrec['MAC'])] + # Bonding options. bond_options = { "mode": "balance-slb", -- 2.30.2