static void bridge_fetch_dp_ifaces(struct bridge *);
static void bridge_flush(struct bridge *);
static void bridge_pick_local_hw_addr(struct bridge *,
- struct iface *local_iface);
+ uint8_t ea[ETH_ADDR_LEN]);
static void bond_run(struct bridge *);
static void bond_wait(struct bridge *);
bridge_fetch_dp_ifaces(br);
for (i = 0; i < br->n_ports; ) {
struct port *port = br->ports[i];
+ struct iface *local_iface = NULL;
+ uint8_t ea[8];
+ uint64_t dpid;
+
for (j = 0; j < port->n_ifaces; ) {
struct iface *iface = port->ifaces[j];
if (iface->dp_ifidx < 0) {
iface->name, dpif_id(&br->dpif));
iface_destroy(iface);
} else {
+ if (iface->dp_ifidx == ODPP_LOCAL) {
+ local_iface = iface;
+ }
VLOG_DBG("dp%u has interface %s on port %d",
dpif_id(&br->dpif), iface->name, iface->dp_ifidx);
j++;
}
- if (!strcmp(iface->name, br->name)) {
- bridge_pick_local_hw_addr(br, iface);
- }
}
if (!port->n_ifaces) {
VLOG_ERR("%s port has no interfaces, dropping", port->name);
port_destroy(port);
- } else {
- i++;
+ continue;
+ }
+
+ /* Pick local port hardware address. */
+ bridge_pick_local_hw_addr(br, ea);
+ if (local_iface) {
+ int error = netdev_nodev_set_etheraddr(local_iface->name, ea);
+ if (error) {
+ static struct vlog_rate_limit rl
+ = VLOG_RATE_LIMIT_INIT(1, 5);
+ VLOG_ERR_RL(&rl, "bridge %s: failed to set bridge "
+ "Ethernet address: %s",
+ br->name, strerror(error));
+ }
+ }
+
+ /* Pick datapath ID. */
+ dpid = cfg_get_dpid(0, "bridge.%s.datapath-id", br->name);
+ if (!dpid) {
+ dpid = eth_addr_to_uint64(ea);
}
+ ofproto_set_datapath_id(br->ofproto, dpid);
+
+ /* Set the controller. (It would be more straightforward to do
+ * this in bridge_reconfigure_one(), but then the
+ * ofproto_set_datapath_id() above would disconnect right away, and
+ * we can't call ofproto_set_datapath_id() until we know the set of
+ * ports actually in the bridge, hence not until now.) */
+ ofproto_set_controller(br->ofproto, br->controller);
+ i++;
}
}
LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
}
static void
-bridge_set_local_hw_addr(struct bridge *br, struct iface *local_iface,
- const uint8_t ea[ETH_ADDR_LEN])
+bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN])
{
- int error = netdev_nodev_set_etheraddr(local_iface->name, ea);
- if (error) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
- VLOG_ERR_RL(&rl, "bridge %s: failed to set bridge Ethernet "
- "address: %s", br->name, strerror(error));
- }
-}
-
-static void
-bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface)
-{
- uint8_t ea[ETH_ADDR_LEN];
uint64_t requested_ea;
size_t i, j;
int error;
} else if (eth_addr_is_zero(ea)) {
VLOG_ERR("bridge %s: cannot set MAC address to zero", br->name);
} else {
- bridge_set_local_hw_addr(br, local_iface, ea);
return;
}
}
for (j = 0; j < port->n_ifaces; j++) {
struct iface *iface = port->ifaces[j];
uint8_t iface_ea[ETH_ADDR_LEN];
- if (iface == local_iface) {
+ if (iface->dp_ifidx == ODPP_LOCAL) {
continue;
}
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);
}
}
}
}
- if (eth_addr_is_broadcast(ea)) {
+ if (eth_addr_is_multicast(ea)) {
memcpy(ea, br->default_ea, ETH_ADDR_LEN);
VLOG_WARN("bridge %s: using default bridge Ethernet "
"address "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(ea));
VLOG_DBG("bridge %s: using bridge Ethernet address "ETH_ADDR_FMT,
br->name, ETH_ADDR_ARGS(ea));
}
- bridge_set_local_hw_addr(br, local_iface, ea);
}
int
|| cfg_get_bool(0, "%s.in-band", pfx));
ofproto_set_discovery(br->ofproto, false, NULL, NULL);
ofproto_set_in_band(br->ofproto, in_band);
- if (!br->controller || strcmp(ctl, br->controller)) {
- ofproto_set_controller(br->ofproto, ctl);
- }
error = netdev_open(br->name, NETDEV_ETH_TYPE_NONE, &netdev);
if (!error) {
ofproto_add_flow(br->ofproto, &flow, OFPFW_ALL, 0,
&action, 1, NULL, 0);
- ofproto_set_controller(br->ofproto, NULL);
ofproto_set_in_band(br->ofproto, false);
ofproto_set_max_backoff(br->ofproto, 1);
ofproto_set_probe_interval(br->ofproto, 5);