> The problem must be that the port number and the hash value get out of sync, > i.e., when the port number is changed. Please try the patch below on top of > your patch and check if you still have the same problem.
With your modifications pertaining the hashmap those tests passed. I had to revert this change in ofproto-dpif: > - struct ofport_dpif *old_root; > - struct ofport_dpif *new_root; > if (rstp_shift_root_learned_address(ofproto->rstp)) { > - old_root = rstp_get_old_root_aux(ofproto->rstp); > - new_root = rstp_get_new_root_aux(ofproto->rstp); > - bundle_move(old_root->bundle, new_root->bundle); > + bundle_move(rstp_get_old_root_aux(ofproto->rstp), > + rstp_get_new_root_aux(ofproto->rstp)); > rstp_reset_root_changed(ofproto->rstp); > } since bundle_move() expects two “struct ofbundle" as arguments. Regards, Daniele > Il giorno 14/nov/2014, alle ore 22:56, Jarno Rajahalme > <jrajaha...@nicira.com> ha scritto: > > > On Nov 14, 2014, at 9:19 AM, Daniele Venturino <daniele.ventur...@m3s.it > <mailto:daniele.ventur...@m3s.it>> wrote: > >> Why lose the ‘_WITH_HASH’? It seems pointless to iterate over all the ports, >> when we just care of the port with the ‘port_number’? >> >> With the _WITH_HASH a test on learned addresses shifting fails. It seems >> like it doesn't even enter the FOR_EACH cycle when the port_number is not 1, >> maybe there is a problem with the hash lookup? >> > > The problem must be that the port number and the hash value get out of sync, > i.e., when the port number is changed. Please try the patch below on top of > your patch and check if you still have the same problem. > >> Can the bundles really be from different bridges, as they both are managed >> by the same RSTP state machine? If both ofproto’s are the same, then this >> function can be simplified. >> >> I guess they're from the same bridge. The shift is between two ports of the >> same bridge. Feel free to suggest any improvement on this. >> > > I’ll add an assert to that effect. > > Jarno > > diff --git a/lib/rstp-state-machines.c b/lib/rstp-state-machines.c > index 705ab61..02e3f98 100644 > --- a/lib/rstp-state-machines.c > +++ b/lib/rstp-state-machines.c > @@ -296,7 +296,7 @@ updt_roles_tree__(struct rstp *r) > > old_root_port_number = r->root_port_id & 0x00ff; > if (old_root_port_number) { > - r->old_root_aux = rstp_get_port_aux(r, old_root_port_number); > + r->old_root_aux = rstp_get_port_aux__(r, old_root_port_number); > } > vsel = -1; > best_vector = r->bridge_priority; > @@ -336,15 +336,15 @@ updt_roles_tree__(struct rstp *r) > RSTP_ID_ARGS(r->root_priority.root_bridge_id)); > new_root_port_number = r->root_port_id & 0x00ff; > if (new_root_port_number) { > - r->new_root_aux = rstp_get_port_aux(r, new_root_port_number); > + r->new_root_aux = rstp_get_port_aux__(r, new_root_port_number); > } > /* Shift learned MAC addresses from an old Root Port to an existing > * Alternate Port. */ > if (!r->root_changed > - && new_root_old_role == ROLE_ALTERNATE > - && new_root_port_number > - && old_root_port_number > - && new_root_port_number != old_root_port_number) { > + && new_root_old_role == ROLE_ALTERNATE > + && new_root_port_number > + && old_root_port_number > + && new_root_port_number != old_root_port_number) { > r->root_changed = true; > } > /* Letters d) e) */ > diff --git a/lib/rstp.c b/lib/rstp.c > index e2420e8..05fa634 100644 > --- a/lib/rstp.c > +++ b/lib/rstp.c > @@ -711,6 +711,8 @@ static void > rstp_port_set_port_number__(struct rstp_port *port, uint16_t port_number) > OVS_REQUIRES(rstp_mutex) > { > + int old_port_number = port->port_number; > + > /* If new_port_number is available, use it, otherwise use the first free > * available port number. */ > port->port_number = > @@ -718,14 +720,23 @@ rstp_port_set_port_number__(struct rstp_port *port, > uint16_t port_number) > ? port_number > : rstp_first_free_number__(port->rstp, port); > > - set_port_id__(port); > - /* [17.13] is not clear. I suppose that a port number change > - * should trigger reselection like a port priority change. */ > - port->selected = false; > - port->reselect = true; > + if (port->port_number != old_port_number) { > + set_port_id__(port); > + /* [17.13] is not clear. I suppose that a port number change > + * should trigger reselection like a port priority change. */ > + port->selected = false; > + port->reselect = true; > + > + /* Adjust the ports hmap. */ > + if (!hmap_node_is_null(&port->node)) { > + hmap_remove(&port->rstp->ports, &port->node); > + } > + hmap_insert(&port->rstp->ports, &port->node, > + hash_int(port->port_number, 0)); > > - VLOG_DBG("%s: set new RSTP port number %d", port->rstp->name, > - port->port_number); > + VLOG_DBG("%s: set new RSTP port number %d", port->rstp->name, > + port->port_number); > + } > } > > /* Converts the link speed to a port path cost [Table 17-3]. */ > @@ -780,7 +791,11 @@ rstp_get_root_path_cost(const struct rstp *rstp) > * pointer is returned if no port needs to flush its MAC learning table. > * '*port' needs to be NULL in the first call to start the iteration. If > * '*port' is passed as non-NULL, it must be the value set by the last > - * invocation of this function. */ > + * invocation of this function. > + * > + * This function may only be called by the thread that creates and deletes > + * ports. Otherwise this function is not thread safe, as the returned > + * '*port' could become stale before it is used in the next invocation. */ > void * > rstp_check_and_reset_fdb_flush(struct rstp *rstp, struct rstp_port **port) > OVS_EXCLUDED(rstp_mutex) > @@ -819,8 +834,9 @@ out: > (*port)->fdb_flush = false; > } > ovs_mutex_unlock(&rstp_mutex); > + > return aux; > - } > +} > > /* Finds a port whose state has changed, and returns the aux pointer set for > * the port. A NULL pointer is returned when no changed port is found. On > @@ -866,40 +882,49 @@ rstp_get_next_changed_port_aux(struct rstp *rstp, > struct rstp_port **portp) > *portp = NULL; > out: > ovs_mutex_unlock(&rstp_mutex); > + > return aux; > } > > bool > -rstp_shift_root_learned_address(struct rstp *rstp) { > - bool ret = false; > +rstp_shift_root_learned_address(struct rstp *rstp) > +{ > + bool ret; > + > ovs_mutex_lock(&rstp_mutex); > - if (rstp->root_changed) { > - ret = true; > - } > + ret = rstp->root_changed; > ovs_mutex_unlock(&rstp_mutex); > + > return ret; > } > > void * > -rstp_get_old_root_aux(struct rstp *rstp) { > - void *aux = NULL; > +rstp_get_old_root_aux(struct rstp *rstp) > +{ > + void *aux; > + > ovs_mutex_lock(&rstp_mutex); > aux = rstp->old_root_aux; > ovs_mutex_unlock(&rstp_mutex); > + > return aux; > } > > void * > -rstp_get_new_root_aux(struct rstp *rstp) { > - void *aux = NULL; > +rstp_get_new_root_aux(struct rstp *rstp) > +{ > + void *aux; > + > ovs_mutex_lock(&rstp_mutex); > aux = rstp->new_root_aux; > ovs_mutex_unlock(&rstp_mutex); > + > return aux; > } > > void > -rstp_reset_root_changed(struct rstp *rstp) { > +rstp_reset_root_changed(struct rstp *rstp) > +{ > ovs_mutex_lock(&rstp_mutex); > rstp->root_changed = false; > ovs_mutex_unlock(&rstp_mutex); > @@ -916,7 +941,8 @@ rstp_get_port__(struct rstp *rstp, uint16_t port_number) > > ovs_assert(rstp && port_number > 0 && port_number <= RSTP_MAX_PORTS); > > - HMAP_FOR_EACH (port, node, &rstp->ports) { > + HMAP_FOR_EACH_WITH_HASH (port, node, hash_int(port_number, 0), > + &rstp->ports) { > if (port->port_number == port_number) { > return port; > } > @@ -937,7 +963,7 @@ rstp_get_port(struct rstp *rstp, uint16_t port_number) > } > > void * > -rstp_get_port_aux(struct rstp *rstp, uint16_t port_number) > +rstp_get_port_aux__(struct rstp *rstp, uint16_t port_number) > OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *p; > @@ -1117,6 +1143,7 @@ rstp_add_port(struct rstp *rstp) > struct rstp_port *p = xzalloc(sizeof *p); > > ovs_refcount_init(&p->ref_cnt); > + hmap_node_nullify(&p->node); > > ovs_mutex_lock(&rstp_mutex); > p->rstp = rstp; > @@ -1128,7 +1155,6 @@ rstp_add_port(struct rstp *rstp) > p->port_id); > > rstp_port_set_state__(p, RSTP_DISCARDING); > - hmap_insert(&rstp->ports, &p->node, hash_int(p->port_number, 0)); > rstp->changes = true; > move_rstp__(rstp); > VLOG_DBG("%s: added port "RSTP_PORT_ID_FMT"", rstp->name, p->port_id); > @@ -1357,6 +1383,7 @@ rstp_get_root_port(struct rstp *rstp) > /* Returns the state of port 'p'. */ > enum rstp_state > rstp_port_get_state(const struct rstp_port *p) > + OVS_EXCLUDED(rstp_mutex) > { > enum rstp_state state; > > diff --git a/lib/rstp.h b/lib/rstp.h > index 3b40a00..8b57761 100644 > --- a/lib/rstp.h > +++ b/lib/rstp.h > @@ -164,15 +164,13 @@ void *rstp_get_next_changed_port_aux(struct rstp *, > struct rstp_port **) > void rstp_port_set_mac_operational(struct rstp_port *, > bool new_mac_operational) > OVS_EXCLUDED(rstp_mutex); > -bool > -rstp_shift_root_learned_address(struct rstp *rstp) > +bool rstp_shift_root_learned_address(struct rstp *) > OVS_EXCLUDED(rstp_mutex); > void *rstp_get_old_root_aux(struct rstp *) > OVS_EXCLUDED(rstp_mutex); > void *rstp_get_new_root_aux(struct rstp *) > OVS_EXCLUDED(rstp_mutex); > -void > -rstp_reset_root_changed(struct rstp *) > +void rstp_reset_root_changed(struct rstp *) > OVS_EXCLUDED(rstp_mutex); > > /* Bridge setters */ > @@ -242,8 +240,8 @@ void rstp_port_get_status(const struct rstp_port *, > uint16_t *id, > int *rx_count, int *error_count, int *uptime) > OVS_EXCLUDED(rstp_mutex); > > -void * rstp_get_port_aux(struct rstp *rstp, uint16_t port_number) > - OVS_EXCLUDED(rstp_mutex); > +void * rstp_get_port_aux__(struct rstp *rstp, uint16_t port_number) > + OVS_REQUIRES(rstp_mutex); > > > /* Internal API for rstp-state-machines.c */ > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index 0ec7b66..268aefa 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -2133,8 +2133,8 @@ update_rstp_port_state(struct ofport_dpif *ofport) > != rstp_learn_in_state(state)) { > /* XXX: Learning action flows should also be flushed. */ > if (ofport->bundle) { > - if(!rstp_shift_root_learned_address(ofproto->rstp) > - || ofport != rstp_get_old_root_aux(ofproto->rstp)) { > + if (!rstp_shift_root_learned_address(ofproto->rstp) > + || rstp_get_old_root_aux(ofproto->rstp) != ofport) { > bundle_flush_macs(ofport->bundle, false); > } > } > @@ -2184,20 +2184,16 @@ rstp_run(struct ofproto_dpif *ofproto) > */ > while ((ofport = rstp_check_and_reset_fdb_flush(ofproto->rstp, > &rp))) { > if (!rstp_shift_root_learned_address(ofproto->rstp) > - || ofport != rstp_get_old_root_aux(ofproto->rstp)) { > + || rstp_get_old_root_aux(ofproto->rstp) != ofport) { > bundle_flush_macs(ofport->bundle, false); > } > } > > - struct ofport_dpif *old_root; > - struct ofport_dpif *new_root; > if (rstp_shift_root_learned_address(ofproto->rstp)) { > - old_root = rstp_get_old_root_aux(ofproto->rstp); > - new_root = rstp_get_new_root_aux(ofproto->rstp); > - bundle_move(old_root->bundle, new_root->bundle); > + bundle_move(rstp_get_old_root_aux(ofproto->rstp), > + rstp_get_new_root_aux(ofproto->rstp)); > rstp_reset_root_changed(ofproto->rstp); > } > - > } > } > > @@ -2544,21 +2540,23 @@ bundle_flush_macs(struct ofbundle *bundle, bool > all_ofprotos) > ovs_rwlock_unlock(&ml->rwlock); > } > > -static void bundle_move(struct ofbundle *old, struct ofbundle *new) { > - struct ofproto_dpif *old_ofproto = old->ofproto; > - struct ofproto_dpif *new_ofproto = new->ofproto; > - struct mac_learning *old_ml = old_ofproto->ml; > +static void > +bundle_move(struct ofbundle *old, struct ofbundle *new) > +{ > + struct ofproto_dpif *ofproto = old->ofproto; > + struct mac_learning *ml = ofproto->ml; > struct mac_entry *mac, *next_mac; > > - old_ofproto->backer->need_revalidate = REV_RECONFIGURE; > - new_ofproto->backer->need_revalidate = REV_RECONFIGURE; > - ovs_rwlock_wrlock(&old_ml->rwlock); > - LIST_FOR_EACH_SAFE (mac, next_mac, lru_node, &old_ml->lrus) { > + ovs_assert(new->ofproto == old->ofproto); > + > + ofproto->backer->need_revalidate = REV_RECONFIGURE; > + ovs_rwlock_wrlock(&ml->rwlock); > + LIST_FOR_EACH_SAFE (mac, next_mac, lru_node, &ml->lrus) { > if (mac->port.p == old) { > mac->port.p = new; > } > } > - ovs_rwlock_unlock(&old_ml->rwlock); > + ovs_rwlock_unlock(&ml->rwlock); > } > > static struct ofbundle * > > > >> Daniele >> >> 2014-11-14 1:11 GMT+01:00 Jarno Rajahalme <jrajaha...@nicira.com >> <mailto:jrajaha...@nicira.com>>: >> Daniele, >> >> See comments inline. >> >> Thanks! >> >> Jarno >> >> On Nov 6, 2014, at 7:31 AM, Daniele Venturino <daniele.ventur...@m3s.it >> <mailto:daniele.ventur...@m3s.it>> wrote: >> >> > All MAC addresses previously learned on a Root Port can be moved to an >> > Alternate Port that becomes the new Root Port; i.e., Dynamic Filtering >> > Entries for those addresses may be modified to show the new Root Port >> > as >> > their source, reducing the need to flood frames when recovering from >> > some component failures. >> > >> >> Indentation... >> >> > Signed-off-by: Daniele Venturino <daniele.ventur...@m3s.it >> > <mailto:daniele.ventur...@m3s.it>> >> > --- >> > lib/rstp-common.h | 4 ++++ >> > lib/rstp-state-machines.c | 21 +++++++++++++++++++ >> > lib/rstp.c | 51 >> > ++++++++++++++++++++++++++++++++++++++--------- >> > lib/rstp.h | 10 ++++++++++ >> > ofproto/ofproto-dpif.c | 39 ++++++++++++++++++++++++++++++++++-- >> > 5 files changed, 114 insertions(+), 11 deletions(-) >> > >> > diff --git a/lib/rstp-common.h b/lib/rstp-common.h >> > index 6e56958..271db2a 100644 >> > --- a/lib/rstp-common.h >> > +++ b/lib/rstp-common.h >> > @@ -868,6 +868,10 @@ struct rstp { >> > /* Interface to client. */ >> > void (*send_bpdu)(struct ofpbuf *bpdu, void *port_aux, void *rstp_aux); >> > void *aux; >> > + >> > + bool root_changed; >> > + void *old_root_aux; >> > + void *new_root_aux; >> > }; >> > >> > #endif /* rstp-common.h */ >> > diff --git a/lib/rstp-state-machines.c b/lib/rstp-state-machines.c >> > index 516093f..40eeea5 100644 >> > --- a/lib/rstp-state-machines.c >> > +++ b/lib/rstp-state-machines.c >> > @@ -287,7 +287,14 @@ updt_roles_tree__(struct rstp *r) >> > struct rstp_port *p; >> > int vsel; >> > struct rstp_priority_vector best_vector, candidate_vector; >> > + enum rstp_port_role new_root_old_role = ROLE_DESIGNATED; >> > + uint16_t old_root_port_number = 0; >> > + uint16_t new_root_port_number = 0; >> > >> > + old_root_port_number = r->root_port_id & 0x00ff; >> > + if (old_root_port_number) { >> > + r->old_root_aux = rstp_get_port_aux(r, old_root_port_number); >> > + } >> > vsel = -1; >> > best_vector = r->bridge_priority; >> > /* Letter c1) */ >> > @@ -317,12 +324,26 @@ updt_roles_tree__(struct rstp *r) >> > r->root_times = p->port_times; >> > r->root_times.message_age++; >> > vsel = p->port_number; >> > + new_root_old_role = p->role; >> > } >> > } >> > r->root_priority = best_vector; >> > r->root_port_id = best_vector.bridge_port_id; >> > VLOG_DBG("%s: new Root is "RSTP_ID_FMT, r->name, >> > RSTP_ID_ARGS(r->root_priority.root_bridge_id)); >> > + new_root_port_number = r->root_port_id & 0x00ff; >> > + if (new_root_port_number) { >> > + r->new_root_aux = rstp_get_port_aux(r, new_root_port_number); >> > + } >> > + /* Shift learned MAC addresses from an old Root Port to an existing >> > + * Alternate Port. */ >> > + if (!r->root_changed >> > + && new_root_old_role == ROLE_ALTERNATE >> > + && new_root_port_number >> > + && old_root_port_number >> > + && new_root_port_number != old_root_port_number) { >> >> Indentation above is wrong, the lines should line right after the opening >> parenthesis above. >> >> > + r->root_changed = true; >> > + } >> > /* Letters d) e) */ >> > HMAP_FOR_EACH (p, node, &r->ports) { >> > p->designated_priority_vector.root_bridge_id = >> > diff --git a/lib/rstp.c b/lib/rstp.c >> > index fd42a7d..5256740 100644 >> > --- a/lib/rstp.c >> > +++ b/lib/rstp.c >> > @@ -867,6 +867,42 @@ out: >> > return aux; >> > } >> > >> > +bool >> > +rstp_shift_root_learned_address(struct rstp *rstp) { >> > + bool ret = false; >> > + ovs_mutex_lock(&rstp_mutex); >> > + if (rstp->root_changed) { >> > + ret = true; >> > + } >> > + ovs_mutex_unlock(&rstp_mutex); >> > + return ret; >> > +} >> > + >> >> Format function definitions like this: >> >> bool >> rstp_shift_root_learned_address(struct rstp *rstp) >> { >> bool ret; >> >> ovs_mutex_lock(&rstp_mutex); >> ret = rstp->root_changed; >> ovs_mutex_unlock(&rstp_mutex); >> >> return ret; >> } >> >> > +void * >> > +rstp_get_old_root_aux(struct rstp *rstp) { >> > + void *aux = NULL; >> > + ovs_mutex_lock(&rstp_mutex); >> > + aux = rstp->old_root_aux; >> > + ovs_mutex_unlock(&rstp_mutex); >> > + return aux; >> > +} >> > + >> > +void * >> > +rstp_get_new_root_aux(struct rstp *rstp) { >> > + void *aux = NULL; >> > + ovs_mutex_lock(&rstp_mutex); >> > + aux = rstp->new_root_aux; >> > + ovs_mutex_unlock(&rstp_mutex); >> > + return aux; >> > +} >> > + >> > +void >> > +rstp_reset_root_changed(struct rstp *rstp) { >> > + ovs_mutex_lock(&rstp_mutex); >> > + rstp->root_changed = false; >> > + ovs_mutex_unlock(&rstp_mutex); >> > +} >> > + >> > /* Returns the port in 'rstp' with number 'port_number'. >> > * >> > * XXX: May only be called while concurrent deletion of ports is excluded. >> > */ >> > @@ -878,8 +914,7 @@ rstp_get_port__(struct rstp *rstp, uint16_t >> > port_number) >> > >> > ovs_assert(rstp && port_number > 0 && port_number <= RSTP_MAX_PORTS); >> > >> > - HMAP_FOR_EACH_WITH_HASH (port, node, hash_int(port_number, 0), >> > - &rstp->ports) { >> > + HMAP_FOR_EACH (port, node, &rstp->ports) { >> >> Why lose the ‘_WITH_HASH’? It seems pointless to iterate over all the ports, >> when we just care of the port with the ‘port_number’? >> >> > if (port->port_number == port_number) { >> > return port; >> > } >> > @@ -901,16 +936,14 @@ rstp_get_port(struct rstp *rstp, uint16_t >> > port_number) >> > >> > void * >> > rstp_get_port_aux(struct rstp *rstp, uint16_t port_number) >> > - OVS_EXCLUDED(rstp_mutex) >> > + OVS_REQUIRES(rstp_mutex) >> > { >> > struct rstp_port *p; >> > - void *aux; >> > - >> > - ovs_mutex_lock(&rstp_mutex); >> > p = rstp_get_port__(rstp, port_number); >> > - aux = p->aux; >> > - ovs_mutex_unlock(&rstp_mutex); >> > - return aux; >> > + if (p) { >> > + return p->aux; >> > + } >> > + return NULL; >> > } >> > >> > /* Updates the port_enabled parameter. */ >> > diff --git a/lib/rstp.h b/lib/rstp.h >> > index b05cdf2..3b40a00 100644 >> > --- a/lib/rstp.h >> > +++ b/lib/rstp.h >> > @@ -164,6 +164,16 @@ void *rstp_get_next_changed_port_aux(struct rstp *, >> > struct rstp_port **) >> > void rstp_port_set_mac_operational(struct rstp_port *, >> > bool new_mac_operational) >> > OVS_EXCLUDED(rstp_mutex); >> > +bool >> > +rstp_shift_root_learned_address(struct rstp *rstp) >> > + OVS_EXCLUDED(rstp_mutex); >> >> Function declarations should have the return type and the function name on >> the same line. >> >> > +void *rstp_get_old_root_aux(struct rstp *) >> > + OVS_EXCLUDED(rstp_mutex); >> > +void *rstp_get_new_root_aux(struct rstp *) >> > + OVS_EXCLUDED(rstp_mutex); >> > +void >> > +rstp_reset_root_changed(struct rstp *) >> > + OVS_EXCLUDED(rstp_mutex); >> > >> >> Here, too. >> >> > /* Bridge setters */ >> > void rstp_set_bridge_address(struct rstp *, rstp_identifier bridge_address) >> > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c >> > index 2fd9896..2389a18 100644 >> > --- a/ofproto/ofproto-dpif.c >> > +++ b/ofproto/ofproto-dpif.c >> > @@ -141,6 +141,7 @@ static void bundle_del_port(struct ofport_dpif *); >> > static void bundle_run(struct ofbundle *); >> > static void bundle_wait(struct ofbundle *); >> > static void bundle_flush_macs(struct ofbundle *, bool); >> > +static void bundle_move(struct ofbundle *, struct ofbundle *); >> > >> > static void stp_run(struct ofproto_dpif *ofproto); >> > static void stp_wait(struct ofproto_dpif *ofproto); >> > @@ -2096,11 +2097,15 @@ update_rstp_port_state(struct ofport_dpif *ofport) >> > netdev_get_name(ofport->up.netdev), >> > rstp_state_name(ofport->rstp_state), >> > rstp_state_name(state)); >> > + >> > if (rstp_learn_in_state(ofport->rstp_state) >> > != rstp_learn_in_state(state)) { >> > /* xxx Learning action flows should also be flushed. */ >> > if (ofport->bundle) { >> > - bundle_flush_macs(ofport->bundle, false); >> > + if(!rstp_shift_root_learned_address(ofproto->rstp) >> > + || ofport != rstp_get_old_root_aux(ofproto->rstp)) { >> > + bundle_flush_macs(ofport->bundle, false); >> > + } >> > } >> > } >> > fwd_change = rstp_forward_in_state(ofport->rstp_state) >> > @@ -2147,8 +2152,21 @@ rstp_run(struct ofproto_dpif *ofproto) >> > * p->fdb_flush) and not periodically. >> > */ >> > while ((ofport = rstp_check_and_reset_fdb_flush(ofproto->rstp, >> > &rp))) { >> > - bundle_flush_macs(ofport->bundle, false); >> > + if (!rstp_shift_root_learned_address(ofproto->rstp) >> > + || ofport != rstp_get_old_root_aux(ofproto->rstp)) { >> > + bundle_flush_macs(ofport->bundle, false); >> > + } >> > + } >> > + >> > + struct ofport_dpif *old_root; >> > + struct ofport_dpif *new_root; >> > + if (rstp_shift_root_learned_address(ofproto->rstp)) { >> > + old_root = rstp_get_old_root_aux(ofproto->rstp); >> > + new_root = rstp_get_new_root_aux(ofproto->rstp); >> > + bundle_move(old_root->bundle, new_root->bundle); >> > + rstp_reset_root_changed(ofproto->rstp); >> > } >> >> Better write the latter part as: >> >> if (rstp_shift_root_learned_address(ofproto->rstp)) { >> bundle_move(rstp_get_old_root_aux(ofproto->rstp), >> rstp_get_new_root_aux(ofproto->rstp)); >> rstp_reset_root_changed(ofproto->rstp); >> } >> >> >> > + >> > } >> > } >> > >> > @@ -2495,6 +2513,23 @@ bundle_flush_macs(struct ofbundle *bundle, bool >> > all_ofprotos) >> > ovs_rwlock_unlock(&ml->rwlock); >> > } >> > >> > +static void bundle_move(struct ofbundle *old, struct ofbundle *new) { >> > + struct ofproto_dpif *old_ofproto = old->ofproto; >> > + struct ofproto_dpif *new_ofproto = new->ofproto; >> >> Can the bundles really be from different bridges, as they both are managed >> by the same RSTP state machine? If both ofproto’s are the same, then this >> function can be simplified. >> >> > + struct mac_learning *old_ml = old_ofproto->ml; >> > + struct mac_entry *mac, *next_mac; >> > + >> > + old_ofproto->backer->need_revalidate = REV_RECONFIGURE; >> > + new_ofproto->backer->need_revalidate = REV_RECONFIGURE; >> > + ovs_rwlock_wrlock(&old_ml->rwlock); >> > + LIST_FOR_EACH_SAFE (mac, next_mac, lru_node, &old_ml->lrus) { >> > + if (mac->port.p == old) { >> > + mac->port.p = new; >> > + } >> > + } >> > + ovs_rwlock_unlock(&old_ml->rwlock); >> > +} >> > + >> > static struct ofbundle * >> > bundle_lookup(const struct ofproto_dpif *ofproto, void *aux) >> > { >> > -- >> > 1.8.1.2 >> > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev