- /* Compare against our current choice. */
- if (!eth_addr_is_multicast(iface_ea) &&
- !eth_addr_is_local(iface_ea) &&
- !eth_addr_is_reserved(iface_ea) &&
- !eth_addr_is_zero(iface_ea) &&
- eth_addr_compare_3way(iface_ea, ea) < 0)
- {
- memcpy(ea, iface_ea, ETH_ADDR_LEN);
- *hw_addr_iface = iface;
- }
- }
- if (eth_addr_is_multicast(ea)) {
- memcpy(ea, br->default_ea, ETH_ADDR_LEN);
- *hw_addr_iface = NULL;
- VLOG_WARN("bridge %s: using default bridge Ethernet "
- "address "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(ea));
- } else {
- VLOG_DBG("bridge %s: using bridge Ethernet address "ETH_ADDR_FMT,
- br->name, ETH_ADDR_ARGS(ea));
- }
-}
-
-/* Choose and returns the datapath ID for bridge 'br' given that the bridge
- * Ethernet address is 'bridge_ea'. If 'bridge_ea' is the Ethernet address of
- * an interface on 'br', then that interface must be passed in as
- * 'hw_addr_iface'; if 'bridge_ea' was derived some other way, then
- * 'hw_addr_iface' must be passed in as a null pointer. */
-static uint64_t
-bridge_pick_datapath_id(struct bridge *br,
- const uint8_t bridge_ea[ETH_ADDR_LEN],
- struct iface *hw_addr_iface)
-{
- /*
- * The procedure for choosing a bridge MAC address will, in the most
- * ordinary case, also choose a unique MAC that we can use as a datapath
- * ID. In some special cases, though, multiple bridges will end up with
- * the same MAC address. This is OK for the bridges, but it will confuse
- * the OpenFlow controller, because each datapath needs a unique datapath
- * ID.
- *
- * Datapath IDs must be unique. It is also very desirable that they be
- * stable from one run to the next, so that policy set on a datapath
- * "sticks".
- */
- const char *datapath_id;
- uint64_t dpid;
-
- datapath_id = bridge_get_other_config(br->cfg, "datapath-id");
- if (datapath_id && dpid_from_string(datapath_id, &dpid)) {
- return dpid;
- }
-
- if (hw_addr_iface) {
- int vlan;
- if (!netdev_get_vlan_vid(hw_addr_iface->netdev, &vlan)) {
- /*
- * A bridge whose MAC address is taken from a VLAN network device
- * (that is, a network device created with vconfig(8) or similar
- * tool) will have the same MAC address as a bridge on the VLAN
- * device's physical network device.
- *
- * Handle this case by hashing the physical network device MAC
- * along with the VLAN identifier.
- */
- uint8_t buf[ETH_ADDR_LEN + 2];
- memcpy(buf, bridge_ea, ETH_ADDR_LEN);
- buf[ETH_ADDR_LEN] = vlan >> 8;
- buf[ETH_ADDR_LEN + 1] = vlan;
- return dpid_from_hash(buf, sizeof buf);
- } else {
- /*
- * Assume that this bridge's MAC address is unique, since it
- * doesn't fit any of the cases we handle specially.
- */
- }
- } else {
- /*
- * A purely internal bridge, that is, one that has no non-virtual
- * network devices on it at all, is more difficult because it has no
- * natural unique identifier at all.
- *
- * When the host is a XenServer, we handle this case by hashing the
- * host's UUID with the name of the bridge. Names of bridges are
- * persistent across XenServer reboots, although they can be reused if
- * an internal network is destroyed and then a new one is later
- * created, so this is fairly effective.
- *
- * When the host is not a XenServer, we punt by using a random MAC
- * address on each run.
- */
- const char *host_uuid = xenserver_get_host_uuid();
- if (host_uuid) {
- char *combined = xasprintf("%s,%s", host_uuid, br->name);
- dpid = dpid_from_hash(combined, strlen(combined));
- free(combined);
- return dpid;
- }
- }
-
- return eth_addr_to_uint64(bridge_ea);
-}
-
-static uint64_t
-dpid_from_hash(const void *data, size_t n)
-{
- uint8_t hash[SHA1_DIGEST_SIZE];
-
- BUILD_ASSERT_DECL(sizeof hash >= ETH_ADDR_LEN);
- sha1_bytes(data, n, hash);
- eth_addr_mark_random(hash);
- return eth_addr_to_uint64(hash);
-}
-
-static void
-iface_refresh_status(struct iface *iface)
-{
- struct shash sh;
-
- enum netdev_flags flags;
- uint32_t current;
- int64_t bps;
- int mtu;
- int64_t mtu_64;
- int error;
-
- shash_init(&sh);
-
- if (!netdev_get_status(iface->netdev, &sh)) {
- size_t n;
- char **keys, **values;
-
- shash_to_ovs_idl_map(&sh, &keys, &values, &n);
- ovsrec_interface_set_status(iface->cfg, keys, values, n);
-
- free(keys);
- free(values);
- } else {
- ovsrec_interface_set_status(iface->cfg, NULL, NULL, 0);
- }
-
- shash_destroy_free_data(&sh);
-
- error = netdev_get_flags(iface->netdev, &flags);
- if (!error) {
- ovsrec_interface_set_admin_state(iface->cfg, flags & NETDEV_UP ? "up" : "down");
- }
- else {
- ovsrec_interface_set_admin_state(iface->cfg, NULL);
- }
-
- error = netdev_get_features(iface->netdev, ¤t, NULL, NULL, NULL);
- if (!error) {
- ovsrec_interface_set_duplex(iface->cfg,
- netdev_features_is_full_duplex(current)
- ? "full" : "half");
- /* warning: uint64_t -> int64_t conversion */
- bps = netdev_features_to_bps(current);
- ovsrec_interface_set_link_speed(iface->cfg, &bps, 1);
- }
- else {
- ovsrec_interface_set_duplex(iface->cfg, NULL);
- ovsrec_interface_set_link_speed(iface->cfg, NULL, 0);
- }
-
-
- ovsrec_interface_set_link_state(iface->cfg,
- netdev_get_carrier(iface->netdev)
- ? "up" : "down");
-
- error = netdev_get_mtu(iface->netdev, &mtu);
- if (!error) {
- mtu_64 = mtu;
- ovsrec_interface_set_mtu(iface->cfg, &mtu_64, 1);
- }
- else {
- ovsrec_interface_set_mtu(iface->cfg, NULL, 0);