[ovs-dev] [PATCH 2/2] vswitch: Allow user to set Ethernet address of any internal interface.

Ben Pfaff blp at nicira.com
Fri Oct 2 17:59:23 UTC 2009

Until now the vswitch configuration file has allowed the user to configure
the MAC address on bridge local ports only.  This commit adds the ability
to configure them on any internal interface.

It would be logical to extend this to any bridge port, period, but many
network devices must be brought down before their Ethernet addresses may be
changed.  Bringing a network interface down and then back up can reset a
lot of state, so as we don't actually need the ability to change any bridge
port's MAC address yet this commit does not implement it.

CC: Ian Campbell <Ian.Campbell at citrix.com>
This patch is against the "citrix" branch.  After I push it I will immediately
merge "citrix" in "master", since this commit will cause some merge conflicts.

diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 2d788ae..f9a007e 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -243,6 +243,7 @@ static struct iface *iface_lookup(const struct bridge *, const char *name);
 static struct iface *iface_from_dp_ifidx(const struct bridge *,
                                          uint16_t dp_ifidx);
 static bool iface_is_internal(const struct bridge *, const char *name);
+static void iface_set_mac(struct iface *);
 /* Hooks into ofproto processing. */
 static struct ofhooks bridge_ofhooks;
@@ -585,7 +586,16 @@ bridge_reconfigure(void)
     LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
         for (i = 0; i < br->n_ports; i++) {
             struct port *port = br->ports[i];
+            for (j = 0; j < port->n_ifaces; j++) {
+                struct iface *iface = port->ifaces[j];
+                if (iface->dp_ifidx != ODPP_LOCAL
+                    && iface_is_internal(br, iface->name)) {
+                    iface_set_mac(iface);
+                }
+            }
     LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
@@ -3135,6 +3145,32 @@ iface_is_internal(const struct bridge *br, const char *iface)
     return false;
+/* Set Ethernet address of 'iface', if one is specified in the configuration
+ * file. */
+static void
+iface_set_mac(struct iface *iface)
+    uint64_t mac = cfg_get_mac(0, "iface.%s.mac", iface->name);
+    if (mac) {
+        static uint8_t ea[ETH_ADDR_LEN];
+        eth_addr_from_uint64(mac, ea);
+        if (eth_addr_is_multicast(ea)) {
+            VLOG_ERR("interface %s: not setting MAC to multicast address",
+                     iface->name);
+        } else if (iface->dp_ifidx == ODPP_LOCAL) {
+            VLOG_ERR("ignoring iface.%s.mac; use bridge.%s.mac instead",
+                     iface->name, iface->name);
+        } else {
+            int error = netdev_nodev_set_etheraddr(iface->name, ea);
+            if (error) {
+                VLOG_ERR("interface %s: setting MAC failed (%s)",
+                         iface->name, strerror(error));
+            }
+        }
+    }
 /* Port mirroring. */
diff --git a/vswitchd/ovs-vswitchd.conf.5.in b/vswitchd/ovs-vswitchd.conf.5.in
index e1c12f1..e7c11ff 100644
--- a/vswitchd/ovs-vswitchd.conf.5.in
+++ b/vswitchd/ovs-vswitchd.conf.5.in
@@ -62,7 +62,11 @@ etc. using the usual system tools (e.g. \fBifconfig\fR, \fBip\fR).  To
 designate network device \fInetdev\fR as an internal port, add
 \fBiface.\fInetdev\fB.internal=true\fR to the configuration file.
 \fBovs\-vswitchd\fR will honor this configuration setting by automatically
-creating the named internal port.
+creating the named internal port.  Such an internal port by default
+has a random Ethernet address, but you may configure a specific
+address by setting \fBiface.\fInetdev\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.
 A bridge with a given \fIname\fR always has an internal port with the
 same \fIname\fR, called the ``local port.''  This network device may

More information about the dev mailing list