+static void
+update_in_band_remotes(struct ofproto *ofproto)
+{
+ const struct ofconn *ofconn;
+ struct sockaddr_in *addrs;
+ size_t max_addrs, n_addrs;
+ bool discovery;
+ size_t i;
+
+ /* Allocate enough memory for as many remotes as we could possibly have. */
+ max_addrs = ofproto->n_extra_remotes + hmap_count(&ofproto->controllers);
+ addrs = xmalloc(max_addrs * sizeof *addrs);
+ n_addrs = 0;
+
+ /* Add all the remotes. */
+ discovery = false;
+ HMAP_FOR_EACH (ofconn, struct ofconn, hmap_node, &ofproto->controllers) {
+ struct sockaddr_in *sin = &addrs[n_addrs];
+
+ sin->sin_addr.s_addr = rconn_get_remote_ip(ofconn->rconn);
+ if (sin->sin_addr.s_addr) {
+ sin->sin_port = rconn_get_remote_port(ofconn->rconn);
+ n_addrs++;
+ }
+ if (ofconn->discovery) {
+ discovery = true;
+ }
+ }
+ for (i = 0; i < ofproto->n_extra_remotes; i++) {
+ addrs[n_addrs++] = ofproto->extra_in_band_remotes[i];
+ }
+
+ /* Create or update or destroy in-band.
+ *
+ * Ordinarily we only enable in-band if there's at least one remote
+ * address, but discovery needs the in-band rules for DHCP to be installed
+ * even before we know any remote addresses. */
+ if (n_addrs || discovery) {
+ if (!ofproto->in_band) {
+ in_band_create(ofproto, ofproto->dpif, ofproto->switch_status,
+ &ofproto->in_band);
+ }
+ in_band_set_remotes(ofproto->in_band, addrs, n_addrs);
+ ofproto->next_in_band_update = time_msec() + 1000;
+ } else {
+ in_band_destroy(ofproto->in_band);
+ ofproto->in_band = NULL;
+ }
+
+ /* Clean up. */
+ free(addrs);
+}
+
+void
+ofproto_set_controllers(struct ofproto *p,
+ const struct ofproto_controller *controllers,
+ size_t n_controllers)
+{
+ struct shash new_controllers;
+ enum ofproto_fail_mode fail_mode;
+ struct ofconn *ofconn, *next;
+ bool ss_exists;
+ size_t i;
+
+ shash_init(&new_controllers);
+ for (i = 0; i < n_controllers; i++) {
+ const struct ofproto_controller *c = &controllers[i];
+
+ shash_add_once(&new_controllers, c->target, &controllers[i]);
+ if (!find_controller_by_target(p, c->target)) {
+ add_controller(p, c);
+ }
+ }
+
+ fail_mode = OFPROTO_FAIL_STANDALONE;
+ ss_exists = false;
+ HMAP_FOR_EACH_SAFE (ofconn, next, struct ofconn, hmap_node,
+ &p->controllers) {
+ struct ofproto_controller *c;
+
+ c = shash_find_data(&new_controllers, ofconn_get_target(ofconn));
+ if (!c) {
+ ofconn_destroy(ofconn);
+ } else {
+ update_controller(ofconn, c);
+ if (ofconn->ss) {
+ ss_exists = true;