From 13ff952715c3298ee448c86d82f0e2443d8163bb Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 10 Mar 2009 17:01:52 -0700 Subject: [PATCH] vswitch: Choose the datapath ID more intelligently. The new algorithm needs to be documented (along with a lot of new vswitch settings). --- vswitchd/bridge.c | 69 ++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 6d0d6911..fc46d021 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -201,7 +201,7 @@ static void bridge_get_all_ifaces(const struct bridge *, struct svec *ifaces); 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 *); @@ -417,6 +417,10 @@ bridge_reconfigure(void) 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) { @@ -424,20 +428,47 @@ bridge_reconfigure(void) 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) { @@ -446,21 +477,8 @@ bridge_reconfigure(void) } 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; @@ -475,7 +493,6 @@ bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface) } 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; } } @@ -492,13 +509,14 @@ bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface) 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); } @@ -509,7 +527,7 @@ bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface) } } } - 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)); @@ -517,7 +535,6 @@ bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface) 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 @@ -809,9 +826,6 @@ bridge_reconfigure_one(struct bridge *br) || 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) { @@ -891,7 +905,6 @@ bridge_reconfigure_one(struct bridge *br) 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); -- 2.30.2