* 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
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) {
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
{
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)
}
}
}
- ib->next_remote_refresh = time_now() + min_refresh;
return any_changes;
}
}
}
-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)
{
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
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)
{
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;
}
}
}
+/* 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
}
}
+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;
}