static void bridge_reconfigure_remotes(struct bridge *,
                                        const struct sockaddr_in *managers,
                                        size_t n_managers);
-static void bridge_get_all_ifaces(const struct bridge *, struct shash *ifaces);
-static void bridge_fetch_dp_ifaces(struct bridge *);
 static void bridge_flush(struct bridge *);
 static void bridge_pick_local_hw_addr(struct bridge *,
                                       uint8_t ea[ETH_ADDR_LEN],
                                         const uint8_t bridge_ea[ETH_ADDR_LEN],
                                         struct iface *hw_addr_iface);
 static uint64_t dpid_from_hash(const void *, size_t nbytes);
+static bool bridge_has_bond_fake_iface(const struct bridge *,
+                                       const char *name);
+static bool port_is_bond_fake_iface(const struct port *);
 
 static unixctl_cb_func bridge_unixctl_fdb_show;
 static unixctl_cb_func cfm_unixctl_show;
      * that port already belongs to a different datapath, so we must do all
      * port deletions before any port additions. */
     HMAP_FOR_EACH (br, node, &all_bridges) {
-        struct ofproto_port ofproto_port;
         struct ofproto_port_dump dump;
-        struct shash want_ifaces;
+        struct ofproto_port ofproto_port;
 
-        bridge_get_all_ifaces(br, &want_ifaces);
         OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, br->ofproto) {
-            if (!shash_find(&want_ifaces, ofproto_port.name)
-                && strcmp(ofproto_port.name, br->name)) {
-                int retval = ofproto_port_del(br->ofproto,
-                                              ofproto_port.ofp_port);
-                if (retval) {
-                    VLOG_WARN("bridge %s: failed to remove %s interface (%s)",
-                              br->name, ofproto_port.name, strerror(retval));
+            const char *name = ofproto_port.name;
+            struct iface *iface;
+            const char *type;
+            int error;
+
+            /* Ignore the local port.  We can't change it anyhow. */
+            if (!strcmp(name, br->name)) {
+                continue;
+            }
+
+            /* Get the type that 'ofproto_port' should have (ordinarily the
+             * type of its corresponding iface) or NULL if it should be
+             * deleted. */
+            iface = iface_lookup(br, name);
+            type = (iface ? iface->type
+                    : bridge_has_bond_fake_iface(br, name) ? "internal"
+                    : NULL);
+
+            /* If it's the wrong type then delete the ofproto port. */
+            if (type
+                && !strcmp(ofproto_port.type, type)
+                && (!iface || !iface->netdev
+                    || !strcmp(netdev_get_type(iface->netdev), type))) {
+                continue;
+            }
+            error = ofproto_port_del(br->ofproto, ofproto_port.ofp_port);
+            if (error) {
+                VLOG_WARN("bridge %s: failed to remove %s interface (%s)",
+                          br->name, name, strerror(error));
+            }
+            if (iface) {
+                if (iface->port->bond) {
+                    /* The bond has a pointer to the netdev, so remove it from
+                     * the bond before closing the netdev.  The slave will get
+                     * added back to the bond later, after a new netdev is
+                     * available. */
+                    bond_slave_unregister(iface->port->bond, iface);
                 }
+                netdev_close(iface->netdev);
+                iface->netdev = NULL;
             }
         }
-        shash_destroy(&want_ifaces);
     }
     HMAP_FOR_EACH (br, node, &all_bridges) {
-        struct shash cur_ifaces, want_ifaces;
         struct ofproto_port ofproto_port;
         struct ofproto_port_dump dump;
+        struct port *port, *next_port;
 
-        /* Get the set of interfaces currently in this datapath. */
-        shash_init(&cur_ifaces);
-        OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, br->ofproto) {
-            struct ofproto_port *port_info = xmalloc(sizeof *port_info);
-            ofproto_port_clone(port_info, &ofproto_port);
-            shash_add(&cur_ifaces, ofproto_port.name, port_info);
-        }
-
-        /* Get the set of interfaces we want on this datapath. */
-        bridge_get_all_ifaces(br, &want_ifaces);
-
+        /* Clear all the "dp_ifidx"es. */
         hmap_clear(&br->ifaces);
-        SHASH_FOR_EACH (node, &want_ifaces) {
-            const char *if_name = node->name;
-            struct iface *iface = node->data;
-            struct ofproto_port *ofproto_port;
-            const char *type;
-            int error;
+        HMAP_FOR_EACH (port, hmap_node, &br->ports) {
+            struct iface *iface;
 
-            type = iface ? iface->type : "internal";
-            ofproto_port = shash_find_data(&cur_ifaces, if_name);
-
-            /* If we have a port or a netdev already, and it's not the type we
-             * want, then delete the port (if any) and close the netdev (if
-             * any). */
-            if ((ofproto_port && strcmp(ofproto_port->type, type))
-                || (iface && iface->netdev
-                    && strcmp(type, netdev_get_type(iface->netdev)))) {
-                if (ofproto_port) {
-                    error = ofproto_port_del(br->ofproto,
-                                             ofproto_port->ofp_port);
-                    if (error) {
-                        continue;
-                    }
-                    ofproto_port = NULL;
-                }
-                if (iface) {
-                    if (iface->port->bond) {
-                        /* The bond has a pointer to the netdev, so remove it
-                         * from the bond before closing the netdev.  The slave
-                         * will get added back to the bond later, after a new
-                         * netdev is available. */
-                        bond_slave_unregister(iface->port->bond, iface);
-                    }
-                    netdev_close(iface->netdev);
-                    iface->netdev = NULL;
-                }
+            LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+                iface->dp_ifidx = -1;
             }
+        }
 
-            /* If the port doesn't exist or we don't have the netdev open,
-             * we need to do more work. */
-            if (!ofproto_port || (iface && !iface->netdev)) {
-                struct netdev_options options;
-                struct netdev *netdev;
-                struct shash args;
-
-                /* First open the network device. */
-                options.name = if_name;
-                options.type = type;
-                options.args = &args;
-                options.ethertype = NETDEV_ETH_TYPE_NONE;
-
-                shash_init(&args);
-                if (iface) {
-                    shash_from_ovs_idl_map(iface->cfg->key_options,
-                                           iface->cfg->value_options,
-                                           iface->cfg->n_options, &args);
-                }
-                error = netdev_open(&options, &netdev);
-                shash_destroy(&args);
-
-                if (error) {
-                    VLOG_WARN("could not open network device %s (%s)",
-                              if_name, strerror(error));
-                    continue;
+        /* Obtain the correct "dp_ifidx"es from ofproto. */
+        OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, br->ofproto) {
+            struct iface *iface = iface_lookup(br, ofproto_port.name);
+            if (iface) {
+                uint32_t odp_port;
+
+                odp_port = ofp_port_to_odp_port(ofproto_port.ofp_port);
+                if (iface->dp_ifidx >= 0) {
+                    VLOG_WARN("bridge %s: interface %s reported twice",
+                              br->name, ofproto_port.name);
+                } else if (iface_from_dp_ifidx(br, odp_port)) {
+                    VLOG_WARN("bridge %s: interface %"PRIu16" reported twice",
+                              br->name, odp_port);
+                } else {
+                    iface->dp_ifidx = odp_port;
+                    hmap_insert(&br->ifaces, &iface->dp_ifidx_node,
+                                hash_int(iface->dp_ifidx, 0));
                 }
+            }
+        }
 
-                /* Then add the port if we haven't already. */
-                if (!ofproto_port) {
-                    error = ofproto_port_add(br->ofproto, netdev, NULL);
-                    if (error) {
-                        netdev_close(netdev);
-                        if (error == EFBIG) {
-                            VLOG_ERR("bridge %s: out of valid port numbers",
-                                     br->name);
-                            break;
-                        } else {
-                            VLOG_WARN("bridge %s: failed to add %s interface "
-                                      "(%s)",
-                                      br->name, if_name, strerror(error));
-                            continue;
-                        }
-                    }
-                }
+        /* Add a dpif port for any "struct iface" that doesn't have one.
+         * Delete any "struct iface" for which this fails.
+         * Delete any "struct port" that thereby ends up with no ifaces. */
+        HMAP_FOR_EACH_SAFE (port, next_port, hmap_node, &br->ports) {
+            struct iface *iface, *next_iface;
 
-                /* Update 'iface'. */
-                if (iface) {
-                    iface->netdev = netdev;
-                }
-            } else if (iface && iface->netdev) {
+            LIST_FOR_EACH_SAFE (iface, next_iface, port_elem, &port->ifaces) {
                 struct shash args;
+                int error;
 
+                /* Open the netdev or reconfigure it. */
                 shash_init(&args);
                 shash_from_ovs_idl_map(iface->cfg->key_options,
                                        iface->cfg->value_options,
                                        iface->cfg->n_options, &args);
-                netdev_set_config(iface->netdev, &args);
+                if (!iface->netdev) {
+                    struct netdev_options options;
+                    options.name = iface->name;
+                    options.type = iface->type;
+                    options.args = &args;
+                    options.ethertype = NETDEV_ETH_TYPE_NONE;
+                    error = netdev_open(&options, &iface->netdev);
+                } else {
+                    error = netdev_set_config(iface->netdev, &args);
+                }
                 shash_destroy(&args);
-            }
-        }
-        shash_destroy(&want_ifaces);
-
-        SHASH_FOR_EACH (node, &cur_ifaces) {
-            struct ofproto_port *port_info = node->data;
-            ofproto_port_destroy(port_info);
-            free(port_info);
-        }
-        shash_destroy(&cur_ifaces);
-    }
-    sflow_bridge_number = 0;
-    HMAP_FOR_EACH (br, node, &all_bridges) {
-        uint8_t ea[ETH_ADDR_LEN];
-        uint64_t dpid;
-        struct iface *local_iface;
-        struct port *port, *next_port;
-        struct iface *hw_addr_iface;
-        char *dpid_string;
+                if (error) {
+                    VLOG_WARN("could not %s network device %s (%s)",
+                              iface->netdev ? "reconfigure" : "open",
+                              iface->name, strerror(error));
+                }
 
-        bridge_fetch_dp_ifaces(br);
+                /* Add the port, if necessary. */
+                if (iface->netdev && iface->dp_ifidx < 0) {
+                    uint16_t ofp_port;
+                    int error;
 
-        /* Delete interfaces that cannot be opened.
-         *
-         * Following this loop, every remaining "struct iface" has nonnull
-         * 'netdev' and correct 'dp_ifidx'. */
-        HMAP_FOR_EACH_SAFE (port, next_port, hmap_node, &br->ports) {
-            struct iface *iface, *next_iface;
+                    error = ofproto_port_add(br->ofproto, iface->netdev,
+                                             &ofp_port);
+                    if (!error) {
+                        iface->dp_ifidx = ofp_port_to_odp_port(ofp_port);
+                    } else {
+                        netdev_close(iface->netdev);
+                        iface->netdev = NULL;
+                    }
+                }
 
-            LIST_FOR_EACH_SAFE (iface, next_iface, port_elem, &port->ifaces) {
+                /* Delete the iface if  */
                 if (iface->netdev && iface->dp_ifidx >= 0) {
                     VLOG_DBG("bridge %s: interface %s is on port %d",
                              br->name, iface->name, iface->dp_ifidx);
                         /* We already reported a related error, don't bother
                          * duplicating it. */
                     }
-
                     iface_set_ofport(iface->cfg, -1);
                     iface_destroy(iface);
                 }
             }
-
             if (list_is_empty(&port->ifaces)) {
                 VLOG_WARN("%s port has no interfaces, dropping", port->name);
                 port_destroy(port);
+                continue;
+            }
+
+            /* Add bond fake iface if necessary. */
+            if (port_is_bond_fake_iface(port)) {
+                if (ofproto_port_query_by_name(br->ofproto, port->name,
+                                               &ofproto_port)) {
+                    struct netdev_options options;
+                    struct netdev *netdev;
+                    int error;
+
+                    options.name = port->name;
+                    options.type = "internal";
+                    options.args = NULL;
+                    options.ethertype = NETDEV_ETH_TYPE_NONE;
+                    error = netdev_open(&options, &netdev);
+                    if (!error) {
+                        ofproto_port_add(br->ofproto, netdev, NULL);
+                        netdev_close(netdev);
+                    } else {
+                        VLOG_WARN("could not open network device %s (%s)",
+                                  port->name, strerror(error));
+                    }
+                } else {
+                    /* Already exists, nothing to do. */
+                    ofproto_port_destroy(&ofproto_port);
+                }
             }
         }
+    }
+    sflow_bridge_number = 0;
+    HMAP_FOR_EACH (br, node, &all_bridges) {
+        uint8_t ea[ETH_ADDR_LEN];
+        uint64_t dpid;
+        struct iface *local_iface;
+        struct iface *hw_addr_iface;
+        char *dpid_string;
 
         /* Pick local port hardware address, datapath ID. */
         bridge_pick_local_hw_addr(br, ea, &hw_addr_iface);
     daemonize_complete();
 }
 
+static bool
+bridge_has_bond_fake_iface(const struct bridge *br, const char *name)
+{
+    const struct port *port = port_lookup(br, name);
+    return port && port_is_bond_fake_iface(port);
+}
+
+static bool
+port_is_bond_fake_iface(const struct port *port)
+{
+    return port->cfg->bond_fake_iface && !list_is_short(&port->ifaces);
+}
+
 static const char *
 get_ovsrec_key_value(const struct ovsdb_idl_row *row,
                      const struct ovsdb_idl_column *column,
     free(ocs[0].target); /* From bridge_ofproto_controller_for_mgmt(). */
     free(ocs);
 }
-
-static void
-bridge_get_all_ifaces(const struct bridge *br, struct shash *ifaces)
-{
-    struct port *port;
-
-    shash_init(ifaces);
-    HMAP_FOR_EACH (port, hmap_node, &br->ports) {
-        struct iface *iface;
-
-        LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
-            shash_add_once(ifaces, iface->name, iface);
-        }
-        if (!list_is_short(&port->ifaces) && port->cfg->bond_fake_iface) {
-            shash_add_once(ifaces, port->name, NULL);
-        }
-    }
-}
-
-/* For robustness, in case the administrator moves around datapath ports behind
- * our back, we re-check all the datapath port numbers here.
- *
- * This function will set the 'dp_ifidx' members of interfaces that have
- * disappeared to -1, so only call this function from a context where those
- * 'struct iface's will be removed from the bridge.  Otherwise, the -1
- * 'dp_ifidx'es will cause trouble later when we try to send them to the
- * datapath, which doesn't support UINT16_MAX+1 ports. */
-static void
-bridge_fetch_dp_ifaces(struct bridge *br)
-{
-    struct ofproto_port ofproto_port;
-    struct ofproto_port_dump dump;
-    struct port *port;
-
-    /* Reset all interface numbers. */
-    HMAP_FOR_EACH (port, hmap_node, &br->ports) {
-        struct iface *iface;
-
-        LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
-            iface->dp_ifidx = -1;
-        }
-    }
-    hmap_clear(&br->ifaces);
-
-    OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, br->ofproto) {
-        struct iface *iface = iface_lookup(br, ofproto_port.name);
-        if (iface) {
-            uint32_t odp_port = ofp_port_to_odp_port(ofproto_port.ofp_port);
-
-            if (iface->dp_ifidx >= 0) {
-                VLOG_WARN("bridge %s: interface %s reported twice",
-                          br->name, ofproto_port.name);
-            } else if (iface_from_dp_ifidx(br, odp_port)) {
-                VLOG_WARN("bridge %s: interface %"PRIu16" reported twice",
-                          br->name, odp_port);
-            } else {
-                iface->dp_ifidx = odp_port;
-                hmap_insert(&br->ifaces, &iface->dp_ifidx_node,
-                            hash_int(iface->dp_ifidx, 0));
-            }
-
-            iface_set_ofport(iface->cfg,
-                             (iface->dp_ifidx >= 0
-                              ? odp_port_to_ofp_port(iface->dp_ifidx)
-                              : -1));
-        }
-    }
-}
 \f
 /* Bridge packet processing functions. */