Daniele,

Thanks for testing, pushed to master.

  Jarno

On Nov 17, 2014, at 9:13 AM, Daniele Venturino <daniele.ventur...@m3s.it> wrote:

>> 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> 
>> 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>:
>>> Daniele,
>>> 
>>> See comments inline.
>>> 
>>> Thanks!
>>> 
>>>   Jarno
>>> 
>>> On Nov 6, 2014, at 7:31 AM, Daniele Venturino <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>
>>> > ---
>>> > 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

Reply via email to