X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=ab14ca15013671d7f3bae96c09749bf565172789;hb=4fa126216803df65814fa5f69b12a66b2541f808;hp=c54cc5f42bd922c91adecfb73ba58de6edef3c15;hpb=260ab6946aef1a3138e0ac3665f29a065cb402d2;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index c54cc5f42..ab14ca150 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -477,6 +477,7 @@ struct table_dpif { }; struct ofproto_dpif { + struct hmap_node all_ofproto_dpifs_node; /* In 'all_ofproto_dpifs'. */ struct ofproto up; struct dpif *dpif; int max_ports; @@ -522,6 +523,9 @@ struct ofproto_dpif { * for debugging the asynchronous flow_mod implementation.) */ static bool clogged; +/* All existing ofproto_dpif instances, indexed by ->up.name. */ +static struct hmap all_ofproto_dpifs = HMAP_INITIALIZER(&all_ofproto_dpifs); + static void ofproto_dpif_unixctl_init(void); static struct ofproto_dpif * @@ -667,6 +671,9 @@ construct(struct ofproto *ofproto_, int *n_tablesp) hmap_init(&ofproto->vlandev_map); hmap_init(&ofproto->realdev_vid_map); + hmap_insert(&all_ofproto_dpifs, &ofproto->all_ofproto_dpifs_node, + hash_string(ofproto->up.name, 0)); + *n_tablesp = N_TABLES; return 0; } @@ -691,6 +698,7 @@ destruct(struct ofproto *ofproto_) struct classifier *table; int i; + hmap_remove(&all_ofproto_dpifs, &ofproto->all_ofproto_dpifs_node); complete_operations(ofproto); OFPROTO_FOR_EACH_TABLE (table, &ofproto->up) { @@ -1388,10 +1396,17 @@ set_queues(struct ofport *ofport_, /* Bundles. */ -/* Expires all MAC learning entries associated with 'port' and forces ofproto - * to revalidate every flow. */ +/* Expires all MAC learning entries associated with 'bundle' and forces its + * ofproto to revalidate every flow. + * + * Normally MAC learning entries are removed only from the ofproto associated + * with 'bundle', but if 'all_ofprotos' is true, then the MAC learning entries + * are removed from every ofproto. When patch ports and SLB bonds are in use + * and a VM migration happens and the gratuitous ARPs are somehow lost, this + * avoids a MAC_ENTRY_IDLE_TIME delay before the migrated VM can communicate + * with the host from which it migrated. */ static void -bundle_flush_macs(struct ofbundle *bundle) +bundle_flush_macs(struct ofbundle *bundle, bool all_ofprotos) { struct ofproto_dpif *ofproto = bundle->ofproto; struct mac_learning *ml = ofproto->ml; @@ -1400,6 +1415,23 @@ bundle_flush_macs(struct ofbundle *bundle) ofproto->need_revalidate = true; LIST_FOR_EACH_SAFE (mac, next_mac, lru_node, &ml->lrus) { if (mac->port.p == bundle) { + if (all_ofprotos) { + struct ofproto_dpif *o; + + HMAP_FOR_EACH (o, all_ofproto_dpifs_node, &all_ofproto_dpifs) { + if (o != ofproto) { + struct mac_entry *e; + + e = mac_learning_lookup(o->ml, mac->mac, mac->vlan, + NULL); + if (e) { + tag_set_add(&o->revalidate_set, e->tag); + mac_learning_expire(o->ml, e); + } + } + } + } + mac_learning_expire(ml, mac); } } @@ -1533,7 +1565,7 @@ bundle_destroy(struct ofbundle *bundle) bundle_del_port(port); } - bundle_flush_macs(bundle); + bundle_flush_macs(bundle, true); hmap_remove(&ofproto->bundles, &bundle->hmap_node); free(bundle->name); free(bundle->trunks); @@ -1721,7 +1753,7 @@ bundle_set(struct ofproto *ofproto_, void *aux, /* If we changed something that would affect MAC learning, un-learn * everything on this port and force flow revalidation. */ if (need_flush) { - bundle_flush_macs(bundle); + bundle_flush_macs(bundle, false); } return 0; @@ -5464,10 +5496,15 @@ send_netflow_active_timeouts(struct ofproto_dpif *ofproto) static struct ofproto_dpif * ofproto_dpif_lookup(const char *name) { - struct ofproto *ofproto = ofproto_lookup(name); - return (ofproto && ofproto->ofproto_class == &ofproto_dpif_class - ? ofproto_dpif_cast(ofproto) - : NULL); + struct ofproto_dpif *ofproto; + + HMAP_FOR_EACH_WITH_HASH (ofproto, all_ofproto_dpifs_node, + hash_string(name, 0), &all_ofproto_dpifs) { + if (!strcmp(ofproto->up.name, name)) { + return ofproto; + } + } + return NULL; } static void