X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fin-band.c;h=9f4bc597144b9f0263604bac4e4875d2a0f44f5c;hb=1c6d11a82e7a48c26a6676ddecfcf29c2e853654;hp=82e51c726897cba787bbb834d9523fc8c3a4151b;hpb=0ade584ebe8ca1a1de92fb7422566726f276918c;p=openvswitch diff --git a/ofproto/in-band.c b/ofproto/in-band.c index 82e51c72..9f4bc597 100644 --- a/ofproto/in-band.c +++ b/ofproto/in-band.c @@ -175,11 +175,6 @@ * problems and amount of processing, we decided to hold off for * the time-being. * - * - Multiple Controllers. There is nothing intrinsic in the high- - * level design that prevents using multiple (known) controllers, - * however, the current implementation's data structures assume - * only one. - * * - Differing Controllers for Switches. All switches must know * the L3 addresses for all the controllers that other switches * may use, since rules need to be set up to allow traffic related @@ -257,12 +252,19 @@ refresh_remote(struct in_band *ib, struct in_band_remote *r) char *next_hop_dev; int retval; + memset(r->remote_mac, 0, sizeof r->remote_mac); + /* Get remote IP address. */ r->remote_ip = rconn_get_remote_ip(r->rconn); + if (!r->remote_ip) { + /* No remote IP address means that this rconn is probably either + * configured for a non-IP based protocol (e.g. "unix:") or + * misconfigured entirely. No point in refreshing quickly. */ + return 10; + } /* Find the next-hop IP address. */ remote_inaddr.s_addr = r->remote_ip; - memset(r->remote_mac, 0, sizeof r->remote_mac); retval = netdev_get_next_hop(ib->local_netdev, &remote_inaddr, &next_hop_inaddr, &next_hop_dev); if (retval) { @@ -300,10 +302,10 @@ refresh_remote(struct in_band *ib, struct in_band_remote *r) IP_ARGS(&next_hop_inaddr.s_addr), strerror(retval)); } - /* If we have an IP address but not a MAC address, then refresh quickly, - * since we probably will get a MAC address soon (via ARP). Otherwise, we - * can afford to wait a little while. */ - return r->remote_ip && eth_addr_is_zero(r->remote_mac) ? 1 : 10; + /* If we don't have a MAC address, then refresh quickly, since we probably + * will get a MAC address soon (via ARP). Otherwise, we can afford to wait + * a little while. */ + return eth_addr_is_zero(r->remote_mac) ? 1 : 10; } static bool @@ -311,35 +313,25 @@ refresh_remotes(struct in_band *ib) { struct in_band_remote *r; bool any_changes; - int min_refresh; if (time_now() < ib->next_remote_refresh) { return false; } any_changes = false; - min_refresh = 10; + ib->next_remote_refresh = TIME_MAX; for (r = ib->remotes; r < &ib->remotes[ib->n_remotes]; r++) { uint8_t old_remote_mac[ETH_ADDR_LEN]; - uint32_t old_remote_ip; - int refresh_interval; + time_t next_refresh; - /* Save old remote information. */ - old_remote_ip = r->remote_ip; + /* Save old MAC. */ memcpy(old_remote_mac, r->remote_mac, ETH_ADDR_LEN); /* Refresh remote information. */ - refresh_interval = refresh_remote(ib, r); - min_refresh = MIN(min_refresh, refresh_interval); + next_refresh = refresh_remote(ib, r) + time_now(); + ib->next_remote_refresh = MIN(ib->next_remote_refresh, next_refresh); - /* If anything changed, log the changes. */ - if (old_remote_ip != r->remote_ip) { - any_changes = true; - if (r->remote_ip) { - VLOG_DBG("remote IP address changed from "IP_FMT" to "IP_FMT, - IP_ARGS(&old_remote_ip), IP_ARGS(&r->remote_ip)); - } - } + /* If the MAC changed, log the changes. */ if (!eth_addr_equals(r->remote_mac, old_remote_mac)) { any_changes = true; if (!eth_addr_is_zero(r->remote_mac) @@ -352,7 +344,6 @@ refresh_remotes(struct in_band *ib) } } } - ib->next_remote_refresh = time_now() + min_refresh; return any_changes; } @@ -634,20 +625,6 @@ make_rules(struct in_band *ib, } } -static void -clear_rules(struct in_band *ib) -{ - memset(ib->installed_local_mac, 0, sizeof ib->installed_local_mac); - - free(ib->remote_ips); - ib->remote_ips = NULL; - ib->n_remote_ips = 0; - - free(ib->remote_macs); - ib->remote_macs = NULL; - ib->n_remote_macs = 0; -} - static void drop_rule(struct in_band *ib, const struct in_band_rule *rule) { @@ -655,11 +632,25 @@ drop_rule(struct in_band *ib, const struct in_band_rule *rule) rule->wildcards, rule->priority); } +/* Drops from the flow table all of the flows set up by 'ib', then clears out + * the information about the installed flows so that they can be filled in + * again if necessary. */ static void drop_rules(struct in_band *ib) { + /* Drop rules. */ make_rules(ib, drop_rule); - clear_rules(ib); + + /* Clear out state. */ + memset(ib->installed_local_mac, 0, sizeof ib->installed_local_mac); + + free(ib->remote_ips); + ib->remote_ips = NULL; + ib->n_remote_ips = 0; + + free(ib->remote_macs); + ib->remote_macs = NULL; + ib->n_remote_macs = 0; } static void @@ -675,6 +666,7 @@ add_rule(struct in_band *ib, const struct in_band_rule *rule) rule->priority, &action, 1, 0); } +/* Inserts flows into the flow table for the current state of 'ib'. */ static void add_rules(struct in_band *ib) { @@ -697,8 +689,11 @@ void in_band_run(struct in_band *ib) { struct in_band_remote *r; + bool local_change, remote_change; - if (!refresh_local(ib) && !refresh_remotes(ib)) { + local_change = refresh_local(ib); + remote_change = refresh_remotes(ib); + if (!local_change && !remote_change) { /* Nothing changed, nothing to do. */ return; } @@ -745,10 +740,12 @@ in_band_wait(struct in_band *in_band) } } +/* ofproto has flushed all flows from the flow table and it is calling us back + * to allow us to reinstall the ones that are important to us. */ void in_band_flushed(struct in_band *in_band) { - clear_rules(in_band); + add_rules(in_band); } int @@ -800,33 +797,48 @@ in_band_destroy(struct in_band *ib) } } +static bool +any_rconns_changed(const struct in_band *ib, struct rconn **remotes, size_t n) +{ + size_t i; + + if (n != ib->n_remotes) { + return true; + } + + for (i = 0; i < n; i++) { + if (ib->remotes[i].rconn != remotes[i]) { + return true; + } + } + + return false; +} + void in_band_set_remotes(struct in_band *ib, struct rconn **remotes, size_t n) { size_t i; /* Optimize the case where the rconns are the same as last time. */ - if (n == ib->n_remotes) { - for (i = 0; i < n; i++) { - if (ib->remotes[i].rconn != remotes[i]) { - goto different; - } - } + if (!any_rconns_changed(ib, remotes, n)) { return; - - different:; } + /* Clear old remotes. */ for (i = 0; i < ib->n_remotes; i++) { /* We don't own the rconn. */ netdev_close(ib->remotes[i].remote_netdev); } free(ib->remotes); - ib->next_remote_refresh = TIME_MIN; - ib->remotes = n ? xzalloc(n * sizeof *ib->remotes) : 0; + /* Set up new remotes. */ + ib->remotes = n ? xzalloc(n * sizeof *ib->remotes) : NULL; ib->n_remotes = n; for (i = 0; i < n; i++) { ib->remotes[i].rconn = remotes[i]; } + + /* Force refresh in next call to in_band_run(). */ + ib->next_remote_refresh = TIME_MIN; }