Acked-by: Daniele Venturino <daniele.ventur...@m3s.it> 2014-08-21 1:57 GMT+02:00 Jarno Rajahalme <jrajaha...@nicira.com>:
> Current code expects there to be a single thread that is responsible > for creating rstp and creating and deleting rstp_port objects. rstp > objects are also deleted from other threads, as managed by reference > counting. > > rstp port objects are not reference counted, which means that > references to rstp ports may only be held while holding the rstp > mutex, or by the thread that creates and deletes them. > > This patch adds reference counting to RSTP ports, which allows ports > to be passed from ofproto-dpif to ofproto-dpif-xlate without using the > RSTP port number. This simplifies RSTP port reconfiguration, as the > port need not be resynchronized with xlate if just the port number > changes. This also avoids lookups on the processing of RSTP BPDUs. > > This patch also: > > 1. Exposes the rstp mutex so that related thread safety annotations > can be used also within rstp-state-machines.c. > > 2. Internal variants of most setter an getter functions are defined, > suffixed with two underscores. These are annotated to be callable > only when the mutex is held. > > 3. Port setters were only called in a specific pattern. The new external > port setter combines them in a single rspt_port_set() function. > > Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> > --- > lib/rstp-common.h | 202 +++++----- > lib/rstp-state-machines.c | 111 ++++-- > lib/rstp-state-machines.h | 12 +- > lib/rstp.c | 884 > +++++++++++++++++++++++++----------------- > lib/rstp.h | 174 ++++++--- > ofproto/ofproto-dpif-xlate.c | 53 +-- > ofproto/ofproto-dpif-xlate.h | 3 +- > ofproto/ofproto-dpif.c | 90 ++--- > tests/test-rstp.c | 36 +- > 9 files changed, 931 insertions(+), 634 deletions(-) > > diff --git a/lib/rstp-common.h b/lib/rstp-common.h > index a67115b..6852263 100644 > --- a/lib/rstp-common.h > +++ b/lib/rstp-common.h > @@ -261,10 +261,12 @@ enum rstp_rcvd_info { > }; > > struct rstp_port { > - struct rstp *rstp; > - struct list node; /* Node in rstp->ports list. */ > - void *aux; > - struct rstp_bpdu received_bpdu_buffer; > + struct ovs_refcount ref_cnt; > + > + struct rstp *rstp OVS_GUARDED_BY(rstp_mutex); > + struct list node OVS_GUARDED_BY(rstp_mutex); /* Node in rstp->ports > list. */ > + void *aux OVS_GUARDED_BY(rstp_mutex); > + struct rstp_bpdu received_bpdu_buffer OVS_GUARDED_BY(rstp_mutex); > > /************************************************************************* > * MAC status parameters > > ************************************************************************/ > @@ -273,10 +275,10 @@ struct rstp_port { > * to transmit and/or receive frames, and its use is permitted by > * management. > */ > - bool mac_operational; > + bool mac_operational OVS_GUARDED_BY(rstp_mutex); > > /* [14.8.2.2] Administrative Bridge Port State */ > - bool is_administrative_bridge_port; > + bool is_administrative_bridge_port OVS_GUARDED_BY(rstp_mutex); > > /* [6.4.3 - operPointToPointMAC] > * a) True. The MAC is connected to a point-to-point LAN; i.e., > there is > @@ -288,7 +290,7 @@ struct rstp_port { > * shall be set True. If adminPointToPointMAC is set to ForceFalse, > then > * operPointToPointMAC shall be set False. > */ > - bool oper_point_to_point_mac; > + bool oper_point_to_point_mac OVS_GUARDED_BY(rstp_mutex); > > /* [6.4.3 - adminPointToPointMAC] > * a) ForceTrue. The administrator requires the MAC to be treated as > if it > @@ -301,7 +303,7 @@ struct rstp_port { > * MAC to be determined in accordance with the specific MAC > procedures > * defined in 6.5. > */ > - enum rstp_admin_point_to_point_mac_state admin_point_to_point_mac; > + enum rstp_admin_point_to_point_mac_state admin_point_to_point_mac > OVS_GUARDED_BY(rstp_mutex); > > > > /************************************************************************* > @@ -312,12 +314,12 @@ struct rstp_port { > /* [17.13.1 - Admin Edge Port] > * The AdminEdgePort parameter for the Port (14.8.2). > */ > - bool admin_edge; > + bool admin_edge OVS_GUARDED_BY(rstp_mutex); > > /* [17.13.3 - AutoEdge] > * The AutoEdgePort parameter for the Port (14.8.2). > */ > - bool auto_edge; > + bool auto_edge OVS_GUARDED_BY(rstp_mutex); > > > > /************************************************************************* > @@ -327,18 +329,18 @@ struct rstp_port { > /* Port number and priority > * >=1 (max 12 bits [9.2.7]) > */ > - uint16_t port_number; > + uint16_t port_number OVS_GUARDED_BY(rstp_mutex); > > /* Port priority > * Range: 0-240 in steps of 16 (table 17-2) > */ > - uint8_t priority; > + uint8_t priority OVS_GUARDED_BY(rstp_mutex); > > /* [17.13.11 - PortPathCost] > * The Port's contribution, when it is the Root Port, to the Root > Path Cost > * (17.3.1, 17.5, 17.6) for the Bridge. > */ > - uint32_t port_path_cost; > + uint32_t port_path_cost OVS_GUARDED_BY(rstp_mutex); > > > /************************************************************************* > * The following variables are defined in [17.17 - State machine > timers] > @@ -347,19 +349,19 @@ struct rstp_port { > * The Edge Delay timer. The time remaining, in the absence of a > received > * BPDU, before this port is identified as an operEdgePort. > */ > - uint16_t edge_delay_while; > + uint16_t edge_delay_while OVS_GUARDED_BY(rstp_mutex); > > /* [17.17.2 - fdWhile] > * The Forward Delay timer. Used to delay Port State transitions until > * other Bridges have received spanning tree information. > */ > - uint16_t fd_while; > + uint16_t fd_while OVS_GUARDED_BY(rstp_mutex); > > /* [17.17.3 - helloWhen] > * The Hello timer. Used to ensure that at least one BPDU is > transmitted by > * a Designated Port in each HelloTime period. > */ > - uint16_t hello_when; > + uint16_t hello_when OVS_GUARDED_BY(rstp_mutex); > > /* [17.17.4 - mdelayWhile] > * The Migration Delay timer. Used by the Port Protocol Migration > state > @@ -368,13 +370,13 @@ struct rstp_port { > * BPDU can cause this Port to change the BPDU types it transmits. > * Initialized to MigrateTime (17.13.9). > */ > - uint16_t mdelay_while; > + uint16_t mdelay_while OVS_GUARDED_BY(rstp_mutex); > > /* [17.17.5 - rbWhile] > * The Recent Backup timer. Maintained at its initial value, twice > * HelloTime, while the Port is a Backup Port. > */ > - uint16_t rb_while; > + uint16_t rb_while OVS_GUARDED_BY(rstp_mutex); > > /* [17.17.6 - rcvdInfoWhile] > * The Received Info timer. The time remaining before the spanning > tree > @@ -382,18 +384,18 @@ struct rstp_port { > * (17.19.22)] is aged out if not refreshed by the receipt of a > further > * Configuration Message. > */ > - uint16_t rcvd_info_while; > + uint16_t rcvd_info_while OVS_GUARDED_BY(rstp_mutex); > > /* [17.17.7 - rrWhile] > * The Recent Root timer. > */ > - uint16_t rr_while; > + uint16_t rr_while OVS_GUARDED_BY(rstp_mutex); > > /* [17.17.8 - tcWhile] > * The Topology Change timer. TCN Messages are sent while this timer > is > * running. > */ > - uint16_t tc_while; > + uint16_t tc_while OVS_GUARDED_BY(rstp_mutex); > > > > /************************************************************************* > @@ -409,7 +411,7 @@ struct rstp_port { > * fdbFlush (17.19.7) is set by the topology change state machine if > * stpVersion (17.19.7) is TRUE. > */ > - uint32_t ageing_time; > + uint32_t ageing_time OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.2 - agree] > * Set if synced is set for all other Ports. An RST BPDU with the > Agreement > @@ -417,7 +419,7 @@ struct rstp_port { > * and when proposed is set. > * Initialized by Port Information state machine. > */ > - bool agree; > + bool agree OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.3 - agreed] > * Set when an RST BPDU is received with a Port Role of Root, > Alternate, or > @@ -427,7 +429,7 @@ struct rstp_port { > * the Forwarding state without further delay. > * Initialized by Port Information state machine. > */ > - bool agreed; > + bool agreed OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.4 - designatedPriority] > * The first four components of the Port's designated priority vector > @@ -435,7 +437,7 @@ struct rstp_port { > * priority vector value is portId (17.19.19). > * (Fifth component of the structure must not be used) > */ > - struct rstp_priority_vector designated_priority_vector; > + struct rstp_priority_vector designated_priority_vector > OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.5 - designatedTimes] > * The designatedTimes variable comprises the set of timer parameter > values > @@ -443,10 +445,10 @@ struct rstp_port { > * update Port Times when updtInfo is set. Updated by the > updtRolesTree() > * procedure (17.21.25). > */ > - struct rstp_times designated_times; > + struct rstp_times designated_times OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.6 - disputed] */ > - bool disputed; > + bool disputed OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.7 - fdbFlush] > * A boolean. Set by the topology change state machine to instruct the > @@ -456,17 +458,17 @@ struct rstp_port { > * entries are > * removed if rstpVersion is TRUE, and immediately if stpVersion is > TRUE. > */ > - uint8_t fdb_flush; > + uint8_t fdb_flush OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.8 - forward] > * Initialized by Port State Transition state machine. > */ > - bool forward; > + bool forward OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.9 - forwarding] > * Initialized by Port State Transition state machine. > */ > - bool forwarding; > + bool forwarding OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.10 - infoIs] > * A variable that takes the values Mine, Aged, Received, or > Disabled, to > @@ -487,17 +489,17 @@ struct rstp_port { > * received BPDU is specified. > * d) Finally if the port is disabled, infoIs is Disabled. > */ > - enum rstp_info_is info_is; > + enum rstp_info_is info_is OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.11 - learn] > * Initialized by Port State Transition state machine. > */ > - bool learn; > + bool learn OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.12 - learning] > * Initialized by Port State Transition state machine. > */ > - bool learning; > + bool learning OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.13 - mcheck] > * A boolean. May be set by management to force the Port Protocol > Migration > @@ -507,32 +509,32 @@ struct rstp_port { > * has no effect if stpVersion (17.20.12) is TRUE, i.e., the Bridge is > * operating in STP Compatibility mode. > */ > - bool mcheck; > + bool mcheck OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.14 - msgPriority] > * The first four components of the message priority vector conveyed > in a > * received BPDU, as defined in 17.6. > * (Fifth component of the structure must not be used). > */ > - struct rstp_priority_vector msg_priority; > + struct rstp_priority_vector msg_priority OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.15 - msgTimes] > * The msgTimes variable comprises the timer parameter values > (Message Age, > * Max Age, Forward Delay, and Hello Time) conveyed in a received > BPDU. > */ > - struct rstp_times msg_times; > + struct rstp_times msg_times OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.16 - newInfo] > * A boolean. Set if a BPDU is to be transmitted. Reset by the Port > * Transmit state machine. > */ > - bool new_info; > + bool new_info OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.17 - operEdge] > * A boolean. The value of the operEdgePort parameter, as determined > by the > * operation of the Bridge Detection state machine (17.25). > */ > - bool oper_edge; > + bool oper_edge OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.18 - portEnabled] > * A boolean. Set if the Bridge's MAC Relay Entity and Spanning Tree > @@ -545,41 +547,41 @@ struct rstp_port { > * c) AuthControlledPortStatus is Authorized [if the port is a > network > * access port (IEEE Std 802.1X)]. > */ > - bool port_enabled; > + bool port_enabled OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.19 - portId] > * The Port Identifier. This variable forms the fifth component of > the port > * priority and designated priority vectors defined in 17.6. > */ > - uint16_t port_id; > + uint16_t port_id OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.21 - portPriority] > * The first four components of the Port's port priority vector > value, as > * defined in 17.6. > * (Fifth component of the structure must not be used) > */ > - struct rstp_priority_vector port_priority; > + struct rstp_priority_vector port_priority OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.22 - portTimes] > * The portTimes variable comprises the Port's timer parameter values > * (Message Age, Max Age, Forward Delay, and Hello Time). These timer > * values are used in BPDUs transmitted from the Port. > */ > - struct rstp_times port_times; > + struct rstp_times port_times OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.23 - proposed] > * Set when an RST BPDU with a Designated Port role and the Proposal > flag > * set is received. If agree is not set, proposed causes sync to be > set for > * all other Ports.of the Bridge. > */ > - bool proposed; > + bool proposed OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.24 - proposing] > * Set by a Designated Port that is not Forwarding, and conveyed to > the > * Root Port or Alternate Port of a neighboring Bridge in the > Proposal flag > * of an RST BPDU (9.3.3). > */ > - bool proposing; > + bool proposing OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.25 - rcvdBPDU] > * A boolean. Set by system dependent processes, this variable > notifies the > @@ -587,84 +589,84 @@ struct rstp_port { > * TCN, or RST BPDU (9.3.1, 9.3.2, 9.3.3) is received on the Port. > Reset > * by the Port Receive state machine. > */ > - bool rcvd_bpdu; > + bool rcvd_bpdu OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.26 - rcvdInfo] > * Set to the result of the rcvInfo() procedure (17.21.8). > */ > - enum rstp_rcvd_info rcvd_info; > + enum rstp_rcvd_info rcvd_info OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.27 - rcvdMsg] */ > - bool rcvd_msg; > + bool rcvd_msg OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.28 - rcvdRSTP] */ > - bool rcvd_rstp; > + bool rcvd_rstp OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.29 - rcvdSTP] */ > - bool rcvd_stp; > + bool rcvd_stp OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.30 - rcvdTc] */ > - bool rcvd_tc; > + bool rcvd_tc OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.31 - rcvdTcAck] */ > - bool rcvd_tc_ack; > + bool rcvd_tc_ack OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.32 - rcvdTcn] */ > - bool rcvd_tcn; > + bool rcvd_tcn OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.33 - reRoot] */ > - bool re_root; > + bool re_root OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.34 - reselect] */ > - bool reselect; > + bool reselect OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.35 - role] > * The assigned Port Role (17.7). > */ > - enum rstp_port_role role; > + enum rstp_port_role role OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.36 - selected] > * A boolean. See 17.28, 17.21.16. > */ > - bool selected; > + bool selected OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.37 - selectedRole] > * The newly computed role for the Port (17.7, 17.28, 17.21.25, > 17.19.35). > */ > - enum rstp_port_role selected_role; > + enum rstp_port_role selected_role OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.38 - sendRSTP] > * A boolean. See 17.24, 17.26. > */ > - bool send_rstp; > + bool send_rstp OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.39 - sync] > * A boolean. See 17.10. > */ > - bool sync; > + bool sync OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.40 - synced] > * A boolean. See 17.10. > */ > - bool synced; > + bool synced OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.41 - tcAck] > * A boolean. Set if a Configuration Message with a topology change > * acknowledge flag set is to be transmitted. > */ > - bool tc_ack; > + bool tc_ack OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.42 - tcProp] > * A boolean. Set by the Topology Change state machine of any other > Port, > * to indicate that a topology change should be propagated through > this > * Port. > */ > - bool tc_prop; > + bool tc_prop OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.43 - tick] > * A boolean. See 17.22. > */ > - bool tick; > + bool tick OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.44 - txCount] > * A counter. Incremented by the Port Transmission (17.26) state > machine on > @@ -672,58 +674,58 @@ struct rstp_port { > * machine (17.22) once a second. Transmissions are delayed if txCount > * reaches TxHoldCount (17.13.12). > */ > - uint16_t tx_count; > + uint16_t tx_count OVS_GUARDED_BY(rstp_mutex); > > /* [17.19.45 - updtInfo] > * A boolean. Set by the Port Role Selection state machine (17.28, > * 17.21.25) to tell the Port Information state machine that it > should copy > * designatedPriority to portPriority and designatedTimes to > portTimes. > */ > - bool updt_info; > + bool updt_info OVS_GUARDED_BY(rstp_mutex); > > /* Counter for RSTP received frames - for rstpd */ > uint32_t rx_rstp_bpdu_cnt; > > /* Counter for bad RSTP received frames */ > - uint32_t error_count; > + uint32_t error_count OVS_GUARDED_BY(rstp_mutex); > > /* [14.8.2.1.3] Outputs > * a) Uptime count in seconds of the time elapsed since the Port was > last > * reset or initialized. > */ > - uint32_t uptime; > + uint32_t uptime OVS_GUARDED_BY(rstp_mutex); > > - enum rstp_state rstp_state; > - bool state_changed; > + enum rstp_state rstp_state OVS_GUARDED_BY(rstp_mutex); > + bool state_changed OVS_GUARDED_BY(rstp_mutex); > > /* Per-port state machines state */ > - enum port_receive_state_machine port_receive_sm_state; > - enum port_protocol_migration_state_machine > port_protocol_migration_sm_state; > - enum bridge_detection_state_machine bridge_detection_sm_state; > - enum port_transmit_state_machine port_transmit_sm_state; > - enum port_information_state_machine port_information_sm_state; > - enum port_role_transition_state_machine port_role_transition_sm_state; > - enum port_state_transition_state_machine > port_state_transition_sm_state; > - enum topology_change_state_machine topology_change_sm_state; > + enum port_receive_state_machine port_receive_sm_state > OVS_GUARDED_BY(rstp_mutex); > + enum port_protocol_migration_state_machine > port_protocol_migration_sm_state OVS_GUARDED_BY(rstp_mutex); > + enum bridge_detection_state_machine bridge_detection_sm_state > OVS_GUARDED_BY(rstp_mutex); > + enum port_transmit_state_machine port_transmit_sm_state > OVS_GUARDED_BY(rstp_mutex); > + enum port_information_state_machine port_information_sm_state > OVS_GUARDED_BY(rstp_mutex); > + enum port_role_transition_state_machine port_role_transition_sm_state > OVS_GUARDED_BY(rstp_mutex); > + enum port_state_transition_state_machine > port_state_transition_sm_state OVS_GUARDED_BY(rstp_mutex); > + enum topology_change_state_machine topology_change_sm_state > OVS_GUARDED_BY(rstp_mutex); > }; > > struct rstp { > - struct list node; /* Node in rstp instances list */ > + struct list node OVS_GUARDED_BY(rstp_mutex); /* In rstp instances > list */ > char *name; /* Bridge name. */ > > /* Changes in last SM execution. */ > - bool changes; > + bool changes OVS_GUARDED_BY(rstp_mutex); > > /* Per-bridge state machines state */ > - enum port_role_selection_state_machine port_role_selection_sm_state; > + enum port_role_selection_state_machine port_role_selection_sm_state > OVS_GUARDED_BY(rstp_mutex); > > /* Bridge MAC address > * (stored in the least significant 48 bits of rstp_identifier). > */ > - rstp_identifier address; /* [7.12.5] */ > + rstp_identifier address OVS_GUARDED_BY(rstp_mutex); /* [7.12.5] */ > > /* Bridge priority */ > - uint16_t priority; /* Valid values: 0-61440 in steps of 4096 */ > + uint16_t priority OVS_GUARDED_BY(rstp_mutex); /* Valid values: > 0-61440 in steps of 4096 */ > > > /************************************************************************* > * [17.3 - RSTP performance parameters] > @@ -755,45 +757,45 @@ struct rstp { > /* [17.13.2 - Ageing Time] > * The Ageing Time parameter for the Bridge (7.9.2, Table 7-5). > */ > - uint32_t ageing_time; > + uint32_t ageing_time OVS_GUARDED_BY(rstp_mutex); > > /* [17.13.4 - Force Protocol Version] > * The Force Protocol Version parameter for the Bridge (17.4, 14.8.1). > * This can take the value 0 (STP Compatibility mode) or 2 (the > default, > * normal operation). > */ > - enum rstp_force_protocol_version force_protocol_version; > + enum rstp_force_protocol_version force_protocol_version > OVS_GUARDED_BY(rstp_mutex); > > /* [17.13.5 - Bridge Forward Delay] > * The delay used by STP Bridges (17.4) to transition Root and > Designated > * Ports to Forwarding (Table 17-1). > */ > - uint16_t bridge_forward_delay; > + uint16_t bridge_forward_delay OVS_GUARDED_BY(rstp_mutex); > > /* [17.13.6 - Bridge Hello Time] > * The interval between periodic transmissions of Configuration > Messages > * by Designated Ports (Table 17-1). > */ > - uint16_t bridge_hello_time; > + uint16_t bridge_hello_time OVS_GUARDED_BY(rstp_mutex); > > /* [17.13.8 - Bridge Max Age] > * The maximum age of the information transmitted by the Bridge when > it is > * the Root Bridge (Table 17-1). > */ > - uint16_t bridge_max_age; > + uint16_t bridge_max_age OVS_GUARDED_BY(rstp_mutex); > > /* [17.13.9 - Migrate Time] > * The initial value of the mdelayWhile and edgeDelayWhile timers > (17.17.4, > * 17.17.1), fixed for all RSTP implementations conforming to this > * specification (Table 17-1). > */ > - uint16_t migrate_time; > + uint16_t migrate_time OVS_GUARDED_BY(rstp_mutex); > > /* [17.13.12 - Transmit Hold Count] > * The Transmit Hold Count (Table 17-1) used by the Port Transmit > state > * machine to limit transmission rate. > */ > - uint16_t transmit_hold_count; > + uint16_t transmit_hold_count OVS_GUARDED_BY(rstp_mutex); > > > > /************************************************************************* > @@ -805,7 +807,7 @@ struct rstp { > * causes all state machines, including per Port state machines, to > * continuously execute their initial state. > */ > - bool begin; > + bool begin OVS_GUARDED_BY(rstp_mutex); > > /* [17.18.2 BridgeIdentifier] > * The unique Bridge Identifier assigned to this Bridge, comprising > two > @@ -815,33 +817,33 @@ struct rstp { > * Address (7.12.5), which guarantees uniqueness of the Bridge > Identifiers > * of different Bridges. > */ > - rstp_identifier bridge_identifier; > + rstp_identifier bridge_identifier OVS_GUARDED_BY(rstp_mutex); > > /* [17.8.3 BridgePriority] > * The bridge priority vector, as defined in 17.6. The first > (RootBridgeID) > * and third (DesignatedBridgeID) components are both equal to the > value > * of the Bridge Identifier (17.18.2). The other components are zero. > */ > - struct rstp_priority_vector bridge_priority; > + struct rstp_priority_vector bridge_priority > OVS_GUARDED_BY(rstp_mutex); > > /* [17.18.4 - BridgeTimes] > * BridgeTimes comprises four components: the current values of Bridge > * Forward Delay, Bridge Hello Time, Bridge Max Age (17.13, Table > 17-1), > * and a Message Age of zero. > */ > - struct rstp_times bridge_times; > + struct rstp_times bridge_times OVS_GUARDED_BY(rstp_mutex); > > /* [17.18.6 - rootPriority] > * The first four components of the Bridge's root priority vector, as > * defined in 17.6. > */ > - struct rstp_priority_vector root_priority; > + struct rstp_priority_vector root_priority OVS_GUARDED_BY(rstp_mutex); > > /* [17.18.5 - rootPortId] > * The Port Identifier of the Root Port. This is the fifth component > of > * the root priority vector, as defined in 17.6. > */ > - uint16_t root_port_id; > + uint16_t root_port_id OVS_GUARDED_BY(rstp_mutex); > > /* [17.18.7 - rootTimes] > * The rootTimes variable comprises the Bridge's operational timer > @@ -849,23 +851,23 @@ struct rstp { > * derived from the values stored in portTimes (17.19.22) for the > Root Port > * or from BridgeTimes (17.18.4). > */ > - struct rstp_times root_times; > + struct rstp_times root_times OVS_GUARDED_BY(rstp_mutex); > > /* 17.20 State machine conditions and parameters */ > > /* [17.20.11] rstpVersion > * TRUE if Force Protocol Version (17.13.4) is greater than or equal > to 2. > */ > - bool rstp_version; > + bool rstp_version OVS_GUARDED_BY(rstp_mutex); > > /* [17.20.12] stpVersion > * TRUE if Force Protocol Version (17.13.4) is less than 2. > */ > - bool stp_version; > + bool stp_version OVS_GUARDED_BY(rstp_mutex); > > /* Ports */ > - struct list ports; > - uint16_t ports_count; > + struct list ports OVS_GUARDED_BY(rstp_mutex); > + uint16_t ports_count OVS_GUARDED_BY(rstp_mutex); > > struct ovs_refcount ref_cnt; > > diff --git a/lib/rstp-state-machines.c b/lib/rstp-state-machines.c > index b70b9da..297f7ea 100644 > --- a/lib/rstp-state-machines.c > +++ b/lib/rstp-state-machines.c > @@ -69,8 +69,10 @@ enum vector_comparison { > }; > > static void decrement_timer(uint16_t *); > -static void rstp_send_bpdu(struct rstp_port *, const void *, size_t); > -static int validate_received_bpdu(struct rstp_port *, const void *, > size_t); > +static void rstp_send_bpdu(struct rstp_port *, const void *, size_t) > + OVS_REQUIRES(rstp_mutex); > +static int validate_received_bpdu(struct rstp_port *, const void *, > size_t) > + OVS_REQUIRES(rstp_mutex); > static ovs_be16 time_encode(uint8_t); > static uint8_t time_decode(ovs_be16); > static enum vector_comparison > @@ -79,20 +81,31 @@ compare_rstp_priority_vector(struct > rstp_priority_vector *, > static bool rstp_times_equal(struct rstp_times *, struct rstp_times *); > > /* Per-Bridge State Machine */ > -static int port_role_selection_sm(struct rstp *); > +static int port_role_selection_sm(struct rstp *) > + OVS_REQUIRES(rstp_mutex); > /* Per-Port State Machines */ > -static int port_receive_sm(struct rstp_port *); > -static int port_protocol_migration_sm(struct rstp_port *); > -static int bridge_detection_sm(struct rstp_port *); > -static int port_transmit_sm(struct rstp_port *); > -static int port_information_sm(struct rstp_port *); > -static int port_role_transition_sm(struct rstp_port *); > -static int port_state_transition_sm(struct rstp_port *); > -static int topology_change_sm(struct rstp_port *); > +static int port_receive_sm(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static int port_protocol_migration_sm(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static int bridge_detection_sm(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static int port_transmit_sm(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static int port_information_sm(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static int port_role_transition_sm(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static int port_state_transition_sm(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static int topology_change_sm(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > /* port_timers_sm() not defined as a state machine */ > > void > -process_received_bpdu(struct rstp_port *p, const void *bpdu, size_t > bpdu_size) > +process_received_bpdu__(struct rstp_port *p, const void *bpdu, > + size_t bpdu_size) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *rstp = p->rstp; > > @@ -108,9 +121,9 @@ process_received_bpdu(struct rstp_port *p, const void > *bpdu, size_t bpdu_size) > memcpy(&p->received_bpdu_buffer, bpdu, sizeof(struct rstp_bpdu)); > > rstp->changes = true; > - move_rstp(rstp); > + move_rstp__(rstp); > } else { > - VLOG_DBG("%s, port %u: Bad BPDU received", p->rstp->name, > + VLOG_DBG("%s, port %u: Bad RSTP BPDU received", p->rstp->name, > p->port_number); > p->error_count++; > } > @@ -118,6 +131,7 @@ process_received_bpdu(struct rstp_port *p, const void > *bpdu, size_t bpdu_size) > > static int > validate_received_bpdu(struct rstp_port *p, const void *bpdu, size_t > bpdu_size) > + OVS_REQUIRES(rstp_mutex) > { > /* Validation of received BPDU, see [9.3.4]. */ > const struct rstp_bpdu *temp; > @@ -154,8 +168,8 @@ validate_received_bpdu(struct rstp_port *p, const void > *bpdu, size_t bpdu_size) > } > > /* > - * move_rstp() > - * This method is invoked to move the State Machines. The SMs move only > if the > + * move_rstp__() > + * This method is invoked to move the State Machines. The SMs move only > if the > * boolean 'changes' is true, meaning that something changed and the SMs > need > * to work to process this change. > * The boolean 'changes' is set every time a SM modifies its state, a > BPDU is > @@ -164,7 +178,8 @@ validate_received_bpdu(struct rstp_port *p, const void > *bpdu, size_t bpdu_size) > */ > #define MAX_RSTP_ITERATIONS 1000 /* safeguard */ > int > -move_rstp(struct rstp *rstp) > +move_rstp__(struct rstp *rstp) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *p; > int num_iterations; > @@ -198,7 +213,8 @@ move_rstp(struct rstp *rstp) > return 0; > } > > -void decrease_rstp_port_timers(struct rstp *r) > +void decrease_rstp_port_timers__(struct rstp *r) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *p; > > @@ -217,7 +233,7 @@ void decrease_rstp_port_timers(struct rstp *r) > } > } > r->changes = true; > - move_rstp(r); > + move_rstp__(r); > } > > static void > @@ -233,6 +249,7 @@ decrement_timer(uint16_t *timer) > > static void > updt_role_disabled_tree(struct rstp *r) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *p; > > @@ -245,6 +262,7 @@ updt_role_disabled_tree(struct rstp *r) > > static void > clear_reselect_tree(struct rstp *r) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *p; > > @@ -256,7 +274,8 @@ clear_reselect_tree(struct rstp *r) > } > > void > -updt_roles_tree(struct rstp *r) > +updt_roles_tree__(struct rstp *r) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *p; > int vsel; > @@ -363,6 +382,7 @@ updt_roles_tree(struct rstp *r) > > static void > set_selected_tree(struct rstp *r) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *p; > > @@ -380,6 +400,7 @@ set_selected_tree(struct rstp *r) > > static int > port_role_selection_sm(struct rstp *r) > + OVS_REQUIRES(rstp_mutex) > { > enum port_role_selection_state_machine old_state; > struct rstp_port *p; > @@ -402,7 +423,7 @@ port_role_selection_sm(struct rstp *r) > break; > case PORT_ROLE_SELECTION_SM_ROLE_SELECTION_EXEC: > clear_reselect_tree(r); > - updt_roles_tree(r); > + updt_roles_tree__(r); > set_selected_tree(r); > r->port_role_selection_sm_state = > PORT_ROLE_SELECTION_SM_ROLE_SELECTION; > @@ -436,6 +457,7 @@ port_role_selection_sm(struct rstp *r) > > static void > updt_bpdu_version(struct rstp_port *p) /* [17.21.22] */ > + OVS_REQUIRES(rstp_mutex) > { > switch (p->received_bpdu_buffer.bpdu_type) { > case CONFIGURATION_BPDU: > @@ -455,6 +477,7 @@ updt_bpdu_version(struct rstp_port *p) /* [17.21.22] > */ > > static int > port_receive_sm(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum port_receive_state_machine old_state; > struct rstp *r; > @@ -507,6 +530,7 @@ port_receive_sm(struct rstp_port *p) > /* [17.24 - Port Protocol Migration state machine] */ > static int > port_protocol_migration_sm(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum port_protocol_migration_state_machine old_state; > struct rstp *r; > @@ -582,6 +606,7 @@ port_protocol_migration_sm(struct rstp_port *p) > /* [17.25 - Bridge Detection state machine] */ > static int > bridge_detection_sm(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum bridge_detection_state_machine old_state; > struct rstp *r; > @@ -631,6 +656,7 @@ bridge_detection_sm(struct rstp_port *p) > /* [17.26 - Port Transmit state machine] */ > static void > rstp_send_bpdu(struct rstp_port *p, const void *bpdu, size_t bpdu_size) > + OVS_REQUIRES(rstp_mutex) > { > struct eth_header *eth; > struct llc_header *llc; > @@ -652,11 +678,12 @@ rstp_send_bpdu(struct rstp_port *p, const void > *bpdu, size_t bpdu_size) > llc->llc_dsap = STP_LLC_DSAP; > llc->llc_ssap = STP_LLC_SSAP; > llc->llc_cntl = STP_LLC_CNTL; > - p->rstp->send_bpdu(pkt, rstp_port_number(p), p->rstp->aux); > + p->rstp->send_bpdu(pkt, p->port_number, p->rstp->aux); > } > > static void > record_agreement(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *r; > > @@ -672,6 +699,7 @@ record_agreement(struct rstp_port *p) > > static void > set_tc_flags(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > /* Sets rcvd_tc and/or rcvd_tc_ack if the Topology Change and/or > Topology > * Change Acknowledgment flags, respectively, are set in a ConfigBPDU > or > @@ -695,6 +723,7 @@ set_tc_flags(struct rstp_port *p) > > static void > record_dispute(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > if ((p->received_bpdu_buffer.flags & BPDU_FLAG_LEARNING) != 0) { > p->agreed = true; > @@ -704,6 +733,7 @@ record_dispute(struct rstp_port *p) > > static void > record_proposal(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum port_flag role = > ((p->received_bpdu_buffer.flags) & ROLE_FLAG_MASK) >> > ROLE_FLAG_SHIFT; > @@ -715,6 +745,7 @@ record_proposal(struct rstp_port *p) > > static void > record_priority(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > p->port_priority.root_bridge_id = p->msg_priority.root_bridge_id; > p->port_priority.root_path_cost = p->msg_priority.root_path_cost; > @@ -725,6 +756,7 @@ record_priority(struct rstp_port *p) > > static void > record_times(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > p->port_times = p->msg_times; > if (p->msg_times.hello_time == 0) { > @@ -734,6 +766,7 @@ record_times(struct rstp_port *p) > > static void > updt_rcvd_info_while(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > /* [17.21.23] > * The value assigned to rcvdInfoWhile is the three times the Hello > Time, > @@ -766,6 +799,7 @@ time_decode(ovs_be16 encoded) > /* [17.21.19] */ > static void > tx_config(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_bpdu bpdu; > > @@ -795,6 +829,7 @@ tx_config(struct rstp_port *p) > /* [17.21.20] */ > static void > tx_rstp(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_bpdu bpdu; > > @@ -852,6 +887,7 @@ tx_rstp(struct rstp_port *p) > /* [17.21.21] */ > static void > tx_tcn(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_bpdu bpdu; > > @@ -865,6 +901,7 @@ tx_tcn(struct rstp_port *p) > > static int > port_transmit_sm(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum port_transmit_state_machine old_state; > struct rstp *r; > @@ -971,6 +1008,7 @@ port_transmit_sm(struct rstp_port *p) > > static int > rcv_info(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum vector_comparison cp; > bool ct; > @@ -1048,6 +1086,7 @@ rcv_info(struct rstp_port *p) > > static int > better_or_same_info(struct rstp_port *p, int new_info_is) > + OVS_REQUIRES(rstp_mutex) > { > /* >= SUPERIOR means that the vector is better or the same. */ > return ((new_info_is == RECEIVED && p->info_is == INFO_IS_RECEIVED && > @@ -1060,6 +1099,7 @@ better_or_same_info(struct rstp_port *p, int > new_info_is) > > static int > port_information_sm(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum port_information_state_machine old_state; > struct rstp *r; > @@ -1237,6 +1277,7 @@ port_information_sm(struct rstp_port *p) > > static void > set_re_root_tree(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *r; > struct rstp_port *p1; > @@ -1251,6 +1292,7 @@ set_re_root_tree(struct rstp_port *p) > > static void > set_sync_tree(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *r; > struct rstp_port *p1; > @@ -1265,18 +1307,21 @@ set_sync_tree(struct rstp_port *p) > > static int > hello_time(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > return p->designated_times.hello_time; > } > > static int > fwd_delay(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > return p->designated_times.forward_delay; > } > > static int > forward_delay(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > if (p->send_rstp) { > return hello_time(p); > @@ -1287,6 +1332,7 @@ forward_delay(struct rstp_port *p) > > static int > edge_delay(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *r; > > @@ -1300,6 +1346,7 @@ edge_delay(struct rstp_port *p) > > static int > check_selected_role_change(struct rstp_port *p, int current_role_state) > + OVS_REQUIRES(rstp_mutex) > { > if (p->selected && !p->updt_info && (p->role != p->selected_role) && > (p->selected_role != current_role_state)) { > @@ -1335,6 +1382,7 @@ check_selected_role_change(struct rstp_port *p, int > current_role_state) > > static int > re_rooted(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *r; > struct rstp_port *p1; > @@ -1352,6 +1400,7 @@ re_rooted(struct rstp_port *p) > > static int > all_synced(struct rstp *r) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *p; > > @@ -1368,6 +1417,7 @@ all_synced(struct rstp *r) > > static int > port_role_transition_sm(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum port_role_transition_state_machine old_state; > struct rstp *r; > @@ -1689,50 +1739,55 @@ port_role_transition_sm(struct rstp_port *p) > > static void > enable_learning(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > /* [17.21.6 enableLearning()] An implementation dependent procedure > that > * causes the Learning Process (7.8) to start learning from frames > received > * on the Port. The procedure does not complete until learning has > been > * enabled. > */ > - rstp_port_set_state(p, RSTP_LEARNING); > + rstp_port_set_state__(p, RSTP_LEARNING); > } > > static void > enable_forwarding(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > /* [17.21.5 enableForwarding()] An implementation dependent procedure > that > * causes the Forwarding Process (7.7) to start forwarding frames > through > * the Port. The procedure does not complete until forwarding has been > * enabled. > */ > - rstp_port_set_state(p, RSTP_FORWARDING); > + rstp_port_set_state__(p, RSTP_FORWARDING); > } > > static void > disable_learning(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > /* [17.21.4 - disableLearning()] An implementation dependent > procedure that > * causes the Learning Process (7.8) to stop learning from the source > * address of frames received on the Port. The procedure does not > complete > * until learning has stopped. > */ > - rstp_port_set_state(p, RSTP_DISCARDING); > + rstp_port_set_state__(p, RSTP_DISCARDING); > } > > static void > disable_forwarding(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > /* [17.21.3 - disableForwarding()] An implementation dependent > procedure > * that causes the Forwarding Process (7.7) to stop forwarding frames > * through the Port. The procedure does not complete until forwarding > has > * stopped. > */ > - rstp_port_set_state(p, RSTP_DISCARDING); > + rstp_port_set_state__(p, RSTP_DISCARDING); > } > > static int > port_state_transition_sm(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum port_state_transition_state_machine old_state; > struct rstp *r; > @@ -1805,6 +1860,7 @@ port_state_transition_sm(struct rstp_port *p) > > static void > new_tc_while(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *r; > > @@ -1823,6 +1879,7 @@ new_tc_while(struct rstp_port *p) > */ > static void > set_tc_prop_tree(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *r; > struct rstp_port *p1; > @@ -1842,12 +1899,14 @@ set_tc_prop_tree(struct rstp_port *p) > > static void > set_tc_prop_bridge(struct rstp_port *p) /* not specified in 802.1D-2004. > */ > + OVS_REQUIRES(rstp_mutex) > { > set_tc_prop_tree(p); /* see 802.1w-2001. */ > } > > static int > topology_change_sm(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > enum topology_change_state_machine old_state; > struct rstp *r; > diff --git a/lib/rstp-state-machines.h b/lib/rstp-state-machines.h > index 7b9f8bc..c43e83f 100644 > --- a/lib/rstp-state-machines.h > +++ b/lib/rstp-state-machines.h > @@ -33,10 +33,14 @@ > #include "rstp-common.h" > > /* Methods called by the Forwarding Layer, through functions of rstp.h. */ > -int move_rstp(struct rstp *); > -void decrease_rstp_port_timers(struct rstp *); > -void process_received_bpdu(struct rstp_port *, const void *, size_t); > +int move_rstp__(struct rstp *) > + OVS_REQUIRES(rstp_mutex); > +void decrease_rstp_port_timers__(struct rstp *) > + OVS_REQUIRES(rstp_mutex); > +void process_received_bpdu__(struct rstp_port *, const void *, size_t) > + OVS_REQUIRES(rstp_mutex); > > -void updt_roles_tree(struct rstp *); > +void updt_roles_tree__(struct rstp *) > + OVS_REQUIRES(rstp_mutex); > > #endif /* rstp-state-machines.h */ > diff --git a/lib/rstp.c b/lib/rstp.c > index 80479fb..72b5f38 100644 > --- a/lib/rstp.c > +++ b/lib/rstp.c > @@ -48,19 +48,72 @@ > > VLOG_DEFINE_THIS_MODULE(rstp); > > -static struct ovs_mutex mutex; > +struct ovs_mutex rstp_mutex; > + > static struct list all_rstps__ = LIST_INITIALIZER(&all_rstps__); > -static struct list *const all_rstps OVS_GUARDED_BY(mutex) = &all_rstps__; > - > -/* Internal use only */ > -static void set_port_id__(struct rstp_port *); > -static void update_port_enabled__(struct rstp_port *); > -static void set_bridge_priority__(struct rstp *); > -static void reinitialize_rstp__(struct rstp *); > -static bool is_port_number_available__(struct rstp *, int, struct > rstp_port *); > -static uint16_t rstp_first_free_number__(struct rstp *, struct rstp_port > *); > -static void rstp_initialize_port_defaults__(struct rstp_port *); > -static void reinitialize_port__(struct rstp_port *); > +static struct list *const all_rstps OVS_GUARDED_BY(rstp_mutex) = > &all_rstps__; > + > +/* Internal use only. */ > +static void rstp_set_bridge_address__(struct rstp *, rstp_identifier) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_set_bridge_priority__(struct rstp *, int new_priority) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_set_bridge_ageing_time__(struct rstp *, int > new_ageing_time) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_set_bridge_force_protocol_version__(struct rstp *, > + enum > rstp_force_protocol_version) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_set_bridge_hello_time__(struct rstp *) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_set_bridge_max_age__(struct rstp *, int new_max_age) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_set_bridge_forward_delay__(struct rstp *, int > new_forward_delay) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_set_bridge_transmit_hold_count__(struct rstp *, > + int > new_transmit_hold_count) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_set_bridge_migrate_time__(struct rstp *) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_set_bridge_times__(struct rstp *, int new_forward_delay, > + int new_hello_time, int new_max_age, > + int new_message_age) > + OVS_REQUIRES(rstp_mutex); > + > +static struct rstp_port *rstp_get_port__(struct rstp *rstp, > + uint16_t port_number) > + OVS_REQUIRES(rstp_mutex); > +static void set_port_id__(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static void update_port_enabled__(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static void set_bridge_priority__(struct rstp *) > + OVS_REQUIRES(rstp_mutex); > +static void reinitialize_rstp__(struct rstp *) > + OVS_REQUIRES(rstp_mutex); > +static bool is_port_number_available__(struct rstp *, int, struct > rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static uint16_t rstp_first_free_number__(struct rstp *, struct rstp_port > *) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_initialize_port_defaults__(struct rstp_port *) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_port_set_priority__(struct rstp_port *, int priority) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_port_set_port_number__(struct rstp_port *, > + uint16_t port_number) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_port_set_path_cost__(struct rstp_port *, uint32_t > path_cost) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_port_set_administrative_bridge_port__(struct rstp_port *, > + uint8_t > admin_port_state) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_port_set_admin_edge__(struct rstp_port *, bool > admin_edge) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_port_set_auto_edge__(struct rstp_port *, bool auto_edge) > + OVS_REQUIRES(rstp_mutex); > +static void rstp_port_set_mcheck__(struct rstp_port *, bool mcheck) > + OVS_REQUIRES(rstp_mutex); > +void reinitialize_port__(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex); > > const char * > rstp_state_name(enum rstp_state state) > @@ -99,9 +152,10 @@ rstp_port_role_name(enum rstp_port_role role) > } > > /* Caller has to hold a reference to prevent 'rstp' from being deleted > - * while we are taking a new reference. */ > + * while taking a new reference. */ > struct rstp * > rstp_ref(struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > if (rstp) { > ovs_refcount_ref(&rstp->ref_cnt); > @@ -109,21 +163,23 @@ rstp_ref(struct rstp *rstp) > return rstp; > } > > -/* Frees RSTP struct */ > +/* Frees RSTP struct when reference count reaches zero. */ > void > rstp_unref(struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > if (rstp && ovs_refcount_unref(&rstp->ref_cnt) == 1) { > - ovs_mutex_lock(&mutex); > - if (rstp->ports_count > 0) { > - struct rstp_port *p; > + ovs_mutex_lock(&rstp_mutex); > + > + /* Each RSTP port poits back to struct rstp without holding a > + * reference for that pointer. This is OK as we never move > + * ports from one bridge to another, and holders always > + * release their ports before releasing the bridge. This > + * means that there should be not ports at this time. */ > + ovs_assert(rstp->ports_count == 0); > > - LIST_FOR_EACH (p, node, &rstp->ports) { > - rstp_delete_port(p); > - } > - } > list_remove(&rstp->node); > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > free(rstp->name); > free(rstp); > } > @@ -133,13 +189,15 @@ rstp_unref(struct rstp *rstp) > * concurrent reinitialization (which can temporarily clear the > * port_number). */ > int > -rstp_port_number(const struct rstp_port *p) > +rstp_port_get_number(const struct rstp_port *p) > + OVS_EXCLUDED(rstp_mutex) > { > int number; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > number = p->port_number; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > + > return number; > } > > @@ -149,24 +207,33 @@ static void rstp_unixctl_tcn(struct unixctl_conn *, > int argc, > /* Decrements the State Machines' timers. */ > void > rstp_tick_timers(struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > - ovs_mutex_lock(&mutex); > - decrease_rstp_port_timers(rstp); > - ovs_mutex_unlock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > + decrease_rstp_port_timers__(rstp); > + ovs_mutex_unlock(&rstp_mutex); > } > > /* Processes an incoming BPDU. */ > void > -rstp_received_bpdu(struct rstp_port *p, const void *bpdu, size_t > bpdu_size) > +rstp_port_received_bpdu(struct rstp_port *rp, const void *bpdu, > + size_t bpdu_size) > + OVS_EXCLUDED(rstp_mutex) > { > - ovs_mutex_lock(&mutex); > - process_received_bpdu(p, bpdu, bpdu_size); > - ovs_mutex_unlock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > + /* Only process packets on ports that have RSTP enabled. */ > + if (rp && rp->rstp_state != RSTP_DISABLED) { > + process_received_bpdu__(rp, bpdu, bpdu_size); > + } > + ovs_mutex_unlock(&rstp_mutex); > } > > void > rstp_init(void) > + OVS_EXCLUDED(rstp_mutex) > { > + ovs_mutex_init_recursive(&rstp_mutex); > + > unixctl_command_register("rstp/tcn", "[bridge]", 0, 1, > rstp_unixctl_tcn, > NULL); > } > @@ -176,33 +243,31 @@ struct rstp * > rstp_create(const char *name, rstp_identifier bridge_address, > void (*send_bpdu)(struct ofpbuf *bpdu, int port_no, void > *aux), > void *aux) > + OVS_EXCLUDED(rstp_mutex) > { > - static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; > struct rstp *rstp; > > VLOG_DBG("Creating RSTP instance"); > - if (ovsthread_once_start(&once)) { > - ovs_mutex_init_recursive(&mutex); > - ovsthread_once_done(&once); > - } > > rstp = xzalloc(sizeof *rstp); > rstp->name = xstrdup(name); > + > + ovs_mutex_lock(&rstp_mutex); > /* Set bridge address. */ > - rstp_set_bridge_address(rstp, bridge_address); > + rstp_set_bridge_address__(rstp, bridge_address); > /* Set default parameters values. */ > - rstp_set_bridge_priority(rstp, RSTP_DEFAULT_PRIORITY); > - rstp_set_bridge_ageing_time(rstp, RSTP_DEFAULT_AGEING_TIME); > - rstp_set_bridge_force_protocol_version(rstp, FPV_DEFAULT); > - rstp_set_bridge_forward_delay(rstp, > RSTP_DEFAULT_BRIDGE_FORWARD_DELAY); > - rstp_set_bridge_hello_time(rstp); > - rstp_set_bridge_max_age(rstp, RSTP_DEFAULT_BRIDGE_MAX_AGE); > - rstp_set_bridge_migrate_time(rstp); > - rstp_set_bridge_transmit_hold_count(rstp, > - RSTP_DEFAULT_TRANSMIT_HOLD_COUNT); > - rstp_set_bridge_times(rstp, RSTP_DEFAULT_BRIDGE_FORWARD_DELAY, > - RSTP_BRIDGE_HELLO_TIME, > RSTP_DEFAULT_BRIDGE_MAX_AGE, > - 0); > + rstp_set_bridge_priority__(rstp, RSTP_DEFAULT_PRIORITY); > + rstp_set_bridge_ageing_time__(rstp, RSTP_DEFAULT_AGEING_TIME); > + rstp_set_bridge_force_protocol_version__(rstp, FPV_DEFAULT); > + rstp_set_bridge_forward_delay__(rstp, > RSTP_DEFAULT_BRIDGE_FORWARD_DELAY); > + rstp_set_bridge_hello_time__(rstp); > + rstp_set_bridge_max_age__(rstp, RSTP_DEFAULT_BRIDGE_MAX_AGE); > + rstp_set_bridge_migrate_time__(rstp); > + rstp_set_bridge_transmit_hold_count__(rstp, > + > RSTP_DEFAULT_TRANSMIT_HOLD_COUNT); > + rstp_set_bridge_times__(rstp, RSTP_DEFAULT_BRIDGE_FORWARD_DELAY, > + RSTP_BRIDGE_HELLO_TIME, > + RSTP_DEFAULT_BRIDGE_MAX_AGE, 0); > rstp->send_bpdu = send_bpdu; > rstp->aux = aux; > rstp->changes = false; > @@ -212,9 +277,8 @@ rstp_create(const char *name, rstp_identifier > bridge_address, > list_init(&rstp->ports); > ovs_refcount_init(&rstp->ref_cnt); > > - ovs_mutex_lock(&mutex); > list_push_back(all_rstps, &rstp->node); > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > > VLOG_DBG("RSTP instance creation done"); > return rstp; > @@ -226,7 +290,7 @@ rstp_create(const char *name, rstp_identifier > bridge_address, > */ > static void > set_bridge_priority__(struct rstp *rstp) > - OVS_REQUIRES(mutex) > + OVS_REQUIRES(rstp_mutex) > { > rstp->bridge_priority.root_bridge_id = rstp->bridge_identifier; > rstp->bridge_priority.designated_bridge_id = rstp->bridge_identifier; > @@ -245,48 +309,61 @@ set_bridge_priority__(struct rstp *rstp) > } > } > rstp->changes = true; > - updt_roles_tree(rstp); > + updt_roles_tree__(rstp); > } > > /* Sets the bridge address. */ > void > -rstp_set_bridge_address(struct rstp *rstp, rstp_identifier bridge_address) > +rstp_set_bridge_address__(struct rstp *rstp, rstp_identifier > bridge_address) > + OVS_REQUIRES(rstp_mutex) > { > VLOG_DBG("%s: set bridge address to: "RSTP_ID_FMT"", rstp->name, > RSTP_ID_ARGS(bridge_address)); > > - ovs_mutex_lock(&mutex); > rstp->address = bridge_address; > rstp->bridge_identifier = bridge_address; > set_bridge_priority__(rstp); > - ovs_mutex_unlock(&mutex); > +} > + > +/* Sets the bridge address. */ > +void > +rstp_set_bridge_address(struct rstp *rstp, rstp_identifier bridge_address) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + rstp_set_bridge_address__(rstp, bridge_address); > + ovs_mutex_unlock(&rstp_mutex); > } > > const char * > rstp_get_name(const struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > char *name; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > name = rstp->name; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > return name; > } > > rstp_identifier > rstp_get_bridge_id(const struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > rstp_identifier bridge_id; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > bridge_id = rstp->bridge_identifier; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > + > return bridge_id; > } > > /* Sets the bridge priority. */ > -void > -rstp_set_bridge_priority(struct rstp *rstp, int new_priority) > +static void > +rstp_set_bridge_priority__(struct rstp *rstp, int new_priority) > + OVS_REQUIRES(rstp_mutex) > { > new_priority = ROUND_DOWN(new_priority, RSTP_PRIORITY_STEP); > > @@ -294,35 +371,50 @@ rstp_set_bridge_priority(struct rstp *rstp, int > new_priority) > && new_priority <= RSTP_MAX_PRIORITY) { > VLOG_DBG("%s: set bridge priority to %d", rstp->name, > new_priority); > > - ovs_mutex_lock(&mutex); > rstp->priority = new_priority; > rstp->bridge_identifier &= 0x0000ffffffffffffULL; > rstp->bridge_identifier |= (uint64_t)new_priority << 48; > set_bridge_priority__(rstp); > - ovs_mutex_unlock(&mutex); > } > } > > +void > +rstp_set_bridge_priority(struct rstp *rstp, int new_priority) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + rstp_set_bridge_priority__(rstp, new_priority); > + ovs_mutex_unlock(&rstp_mutex); > +} > + > /* Sets the bridge ageing time. */ > void > -rstp_set_bridge_ageing_time(struct rstp *rstp, int new_ageing_time) > +rstp_set_bridge_ageing_time__(struct rstp *rstp, int new_ageing_time) > + OVS_REQUIRES(rstp_mutex) > { > if (new_ageing_time >= RSTP_MIN_AGEING_TIME > && new_ageing_time <= RSTP_MAX_AGEING_TIME) { > VLOG_DBG("%s: set ageing time to %d", rstp->name, > new_ageing_time); > > - ovs_mutex_lock(&mutex); > rstp->ageing_time = new_ageing_time; > - ovs_mutex_unlock(&mutex); > } > } > > +void > +rstp_set_bridge_ageing_time(struct rstp *rstp, int new_ageing_time) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + rstp_set_bridge_ageing_time__(rstp, new_ageing_time); > + ovs_mutex_unlock(&rstp_mutex); > +} > + > /* Reinitializes RSTP when switching from RSTP mode to STP mode > * or vice versa. > */ > static void > reinitialize_rstp__(struct rstp *rstp) > - OVS_REQUIRES(mutex) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp temp; > static struct list ports; > @@ -337,19 +429,19 @@ reinitialize_rstp__(struct rstp *rstp) > /* Initialize rstp. */ > rstp->name = temp.name; > /* Set bridge address. */ > - rstp_set_bridge_address(rstp, temp.address); > + rstp_set_bridge_address__(rstp, temp.address); > /* Set default parameters values. */ > - rstp_set_bridge_priority(rstp, RSTP_DEFAULT_PRIORITY); > - rstp_set_bridge_ageing_time(rstp, RSTP_DEFAULT_AGEING_TIME); > - rstp_set_bridge_forward_delay(rstp, > RSTP_DEFAULT_BRIDGE_FORWARD_DELAY); > - rstp_set_bridge_hello_time(rstp); > - rstp_set_bridge_max_age(rstp, RSTP_DEFAULT_BRIDGE_MAX_AGE); > - rstp_set_bridge_migrate_time(rstp); > - rstp_set_bridge_transmit_hold_count(rstp, > - RSTP_DEFAULT_TRANSMIT_HOLD_COUNT); > - rstp_set_bridge_times(rstp, RSTP_DEFAULT_BRIDGE_FORWARD_DELAY, > - RSTP_BRIDGE_HELLO_TIME, > RSTP_DEFAULT_BRIDGE_MAX_AGE, > - 0); > + rstp_set_bridge_priority__(rstp, RSTP_DEFAULT_PRIORITY); > + rstp_set_bridge_ageing_time__(rstp, RSTP_DEFAULT_AGEING_TIME); > + rstp_set_bridge_forward_delay__(rstp, > RSTP_DEFAULT_BRIDGE_FORWARD_DELAY); > + rstp_set_bridge_hello_time__(rstp); > + rstp_set_bridge_max_age__(rstp, RSTP_DEFAULT_BRIDGE_MAX_AGE); > + rstp_set_bridge_migrate_time__(rstp); > + rstp_set_bridge_transmit_hold_count__(rstp, > + > RSTP_DEFAULT_TRANSMIT_HOLD_COUNT); > + rstp_set_bridge_times__(rstp, RSTP_DEFAULT_BRIDGE_FORWARD_DELAY, > + RSTP_BRIDGE_HELLO_TIME, > + RSTP_DEFAULT_BRIDGE_MAX_AGE, 0); > > rstp->send_bpdu = temp.send_bpdu; > rstp->aux = temp.aux; > @@ -370,16 +462,17 @@ reinitialize_rstp__(struct rstp *rstp) > } > > /* Sets the force protocol version parameter. */ > -void > -rstp_set_bridge_force_protocol_version(struct rstp *rstp, > +static void > +rstp_set_bridge_force_protocol_version__(struct rstp *rstp, > enum rstp_force_protocol_version > new_force_protocol_version) > + OVS_REQUIRES(rstp_mutex) > { > if (new_force_protocol_version != rstp->force_protocol_version && > (new_force_protocol_version == FPV_STP_COMPATIBILITY || > new_force_protocol_version == FPV_DEFAULT)) { > VLOG_DBG("%s: set bridge Force Protocol Version to %d", > rstp->name, > new_force_protocol_version); > - ovs_mutex_lock(&mutex); > + > /* [17.13] The Spanning Tree Protocol Entity shall be > reinitialized, > * as specified by the assertion of BEGIN (17.18.1) in the state > * machine specification. > @@ -394,26 +487,35 @@ rstp_set_bridge_force_protocol_version(struct rstp > *rstp, > rstp->rstp_version = true; > } > rstp->changes = true; > - move_rstp(rstp); > - ovs_mutex_unlock(&mutex); > + move_rstp__(rstp); > } > } > > -/* Sets the bridge Hello Time parameter. */ > void > -rstp_set_bridge_hello_time(struct rstp *rstp) > +rstp_set_bridge_force_protocol_version(struct rstp *rstp, > + enum rstp_force_protocol_version > new_force_protocol_version) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + rstp_set_bridge_force_protocol_version__(rstp, > new_force_protocol_version); > + ovs_mutex_unlock(&rstp_mutex); > +} > + > +/* Sets the bridge Hello Time parameter. */ > +static void > +rstp_set_bridge_hello_time__(struct rstp *rstp) > + OVS_REQUIRES(rstp_mutex) > { > VLOG_DBG("%s: set RSTP Hello Time to %d", rstp->name, > RSTP_BRIDGE_HELLO_TIME); > /* 2 is the only acceptable value. */ > - ovs_mutex_lock(&mutex); > rstp->bridge_hello_time = RSTP_BRIDGE_HELLO_TIME; > - ovs_mutex_unlock(&mutex); > } > > /* Sets the bridge max age parameter. */ > -void > -rstp_set_bridge_max_age(struct rstp *rstp, int new_max_age) > +static void > +rstp_set_bridge_max_age__(struct rstp *rstp, int new_max_age) > + OVS_REQUIRES(rstp_mutex) > { > if (new_max_age >= RSTP_MIN_BRIDGE_MAX_AGE && > new_max_age <= RSTP_MAX_BRIDGE_MAX_AGE) { > @@ -422,35 +524,52 @@ rstp_set_bridge_max_age(struct rstp *rstp, int > new_max_age) > && (new_max_age >= 2 * rstp->bridge_hello_time)) { > VLOG_DBG("%s: set RSTP bridge Max Age to %d", rstp->name, > new_max_age); > - ovs_mutex_lock(&mutex); > + > rstp->bridge_max_age = new_max_age; > rstp->bridge_times.max_age = new_max_age; > - ovs_mutex_unlock(&mutex); > } > } > } > > -/* Sets the bridge forward delay parameter. */ > void > -rstp_set_bridge_forward_delay(struct rstp *rstp, int new_forward_delay) > +rstp_set_bridge_max_age(struct rstp *rstp, int new_max_age) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + rstp_set_bridge_max_age__(rstp, new_max_age); > + ovs_mutex_unlock(&rstp_mutex); > +} > + > +/* Sets the bridge forward delay parameter. */ > +static void > +rstp_set_bridge_forward_delay__(struct rstp *rstp, int new_forward_delay) > + OVS_REQUIRES(rstp_mutex) > { > if (new_forward_delay >= RSTP_MIN_BRIDGE_FORWARD_DELAY > && new_forward_delay <= RSTP_MAX_BRIDGE_FORWARD_DELAY) { > if (2 * (new_forward_delay - 1) >= rstp->bridge_max_age) { > VLOG_DBG("%s: set RSTP Forward Delay to %d", rstp->name, > new_forward_delay); > - ovs_mutex_lock(&mutex); > rstp->bridge_forward_delay = new_forward_delay; > rstp->bridge_times.forward_delay = new_forward_delay; > - ovs_mutex_unlock(&mutex); > } > } > } > > -/* Sets the bridge transmit hold count parameter. */ > void > -rstp_set_bridge_transmit_hold_count(struct rstp *rstp, > - int new_transmit_hold_count) > +rstp_set_bridge_forward_delay(struct rstp *rstp, int new_forward_delay) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + rstp_set_bridge_forward_delay__(rstp, new_forward_delay); > + ovs_mutex_unlock(&rstp_mutex); > +} > + > +/* Sets the bridge transmit hold count parameter. */ > +static void > +rstp_set_bridge_transmit_hold_count__(struct rstp *rstp, > + int new_transmit_hold_count) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *p; > > @@ -459,34 +578,43 @@ rstp_set_bridge_transmit_hold_count(struct rstp > *rstp, > VLOG_DBG("%s: set RSTP Transmit Hold Count to %d", rstp->name, > new_transmit_hold_count); > /* Resetting txCount on all ports [17.13]. */ > - ovs_mutex_lock(&mutex); > + > rstp->transmit_hold_count = new_transmit_hold_count; > if (rstp->ports_count > 0) { > LIST_FOR_EACH (p, node, &rstp->ports) { > p->tx_count = 0; > } > } > - ovs_mutex_unlock(&mutex); > } > } > > -/* Sets the bridge migrate time parameter. */ > void > -rstp_set_bridge_migrate_time(struct rstp *rstp) > +rstp_set_bridge_transmit_hold_count(struct rstp *rstp, > + int new_transmit_hold_count) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + rstp_set_bridge_transmit_hold_count__(rstp, new_transmit_hold_count); > + ovs_mutex_unlock(&rstp_mutex); > +} > + > +/* Sets the bridge migrate time parameter. */ > +static void > +rstp_set_bridge_migrate_time__(struct rstp *rstp) > + OVS_REQUIRES(rstp_mutex) > { > VLOG_DBG("%s: set RSTP Migrate Time to %d", rstp->name, > RSTP_MIGRATE_TIME); > /* 3 is the only acceptable value */ > - ovs_mutex_lock(&mutex); > rstp->migrate_time = RSTP_MIGRATE_TIME; > - ovs_mutex_unlock(&mutex); > } > > /* Sets the bridge times. */ > -void > -rstp_set_bridge_times(struct rstp *rstp, int new_forward_delay, > - int new_hello_time, int new_max_age, > - int new_message_age) > +static void > +rstp_set_bridge_times__(struct rstp *rstp, int new_forward_delay, > + int new_hello_time, int new_max_age, > + int new_message_age) > + OVS_REQUIRES(rstp_mutex) > { > VLOG_DBG("%s: set RSTP times to (%d, %d, %d, %d)", rstp->name, > new_forward_delay, new_hello_time, new_max_age, > new_message_age); > @@ -504,11 +632,12 @@ rstp_set_bridge_times(struct rstp *rstp, int > new_forward_delay, > rstp->bridge_times.message_age = new_message_age; > } > > -/* Sets the port id, it is called by rstp_port_set_port_number() or > - * rstp_port_set_priority(). > +/* Sets the port id, it is called by rstp_port_set_port_number__() or > + * rstp_port_set_priority__(). > */ > static void > set_port_id__(struct rstp_port *p) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *rstp; > > @@ -520,32 +649,30 @@ set_port_id__(struct rstp_port *p) > } > > /* Sets the port priority. */ > -void > -rstp_port_set_priority(struct rstp_port *rstp_port, int new_port_priority) > +static void > +rstp_port_set_priority__(struct rstp_port *port, int priority) > + OVS_REQUIRES(rstp_mutex) > { > - struct rstp *rstp; > - > - rstp = rstp_port->rstp; > - if (new_port_priority >= RSTP_MIN_PORT_PRIORITY > - && new_port_priority <= RSTP_MAX_PORT_PRIORITY) { > - VLOG_DBG("%s, port %u: set RSTP port priority to %d", rstp->name, > - rstp_port->port_number, new_port_priority); > - ovs_mutex_lock(&mutex); > - new_port_priority -= new_port_priority % RSTP_STEP_PORT_PRIORITY; > - rstp_port->priority = new_port_priority; > - set_port_id__(rstp_port); > - rstp_port->selected = false; > - rstp_port->reselect = true; > - ovs_mutex_unlock(&mutex); > + if (priority >= RSTP_MIN_PORT_PRIORITY > + && priority <= RSTP_MAX_PORT_PRIORITY) { > + VLOG_DBG("%s, port %u: set RSTP port priority to %d", > port->rstp->name, > + port->port_number, priority); > + > + priority -= priority % RSTP_STEP_PORT_PRIORITY; > + port->priority = priority; > + set_port_id__(port); > + port->selected = false; > + port->reselect = true; > } > } > > /* Checks if a port number is available. */ > static bool > is_port_number_available__(struct rstp *rstp, int n, struct rstp_port > *port) > + OVS_REQUIRES(rstp_mutex) > { > if (n >= 1 && n <= RSTP_MAX_PORTS) { > - struct rstp_port *p = rstp_get_port(rstp, n); > + struct rstp_port *p = rstp_get_port__(rstp, n); > > return p == NULL || p == port; > } > @@ -554,46 +681,40 @@ is_port_number_available__(struct rstp *rstp, int n, > struct rstp_port *port) > > static uint16_t > rstp_first_free_number__(struct rstp *rstp, struct rstp_port *rstp_port) > + OVS_REQUIRES(rstp_mutex) > { > int free_number = 1; > > - ovs_mutex_lock(&mutex); > while (free_number <= RSTP_MAX_PORTS) { > if (is_port_number_available__(rstp, free_number, rstp_port)) { > - ovs_mutex_unlock(&mutex); > return free_number; > } > free_number++; > } > - ovs_mutex_unlock(&mutex); > VLOG_DBG("%s, No free port number available.", rstp->name); > return 0; > } > > /* Sets the port number. */ > -void > -rstp_port_set_port_number(struct rstp_port *rstp_port, > - uint16_t new_port_number) > +static void > +rstp_port_set_port_number__(struct rstp_port *port, uint16_t port_number) > + OVS_REQUIRES(rstp_mutex) > { > - struct rstp *rstp; > - > - ovs_mutex_lock(&mutex); > - rstp = rstp_port->rstp; > /* If new_port_number is available, use it, otherwise use the first > free > * available port number. */ > - rstp_port->port_number = > - is_port_number_available__(rstp_port->rstp, new_port_number, > rstp_port) > - ? new_port_number > - : rstp_first_free_number__(rstp, rstp_port); > + port->port_number = > + is_port_number_available__(port->rstp, port_number, port) > + ? port_number > + : rstp_first_free_number__(port->rstp, port); > > - set_port_id__(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. */ > - rstp_port->selected = false; > - rstp_port->reselect = true; > - ovs_mutex_unlock(&mutex); > - VLOG_DBG("%s: set new RSTP port number %d", rstp->name, > - rstp_port->port_number); > + port->selected = false; > + port->reselect = true; > + > + 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]. */ > @@ -616,34 +737,31 @@ rstp_convert_speed_to_cost(unsigned int speed) > } > > /* Sets the port path cost. */ > -void > -rstp_port_set_path_cost(struct rstp_port *rstp_port, > - uint32_t new_port_path_cost) > +static void > +rstp_port_set_path_cost__(struct rstp_port *port, uint32_t path_cost) > + OVS_REQUIRES(rstp_mutex) > { > - if (new_port_path_cost >= RSTP_MIN_PORT_PATH_COST && > - new_port_path_cost <= RSTP_MAX_PORT_PATH_COST) { > - struct rstp *rstp; > - > - ovs_mutex_lock(&mutex); > - rstp = rstp_port->rstp; > - VLOG_DBG("%s, port %u, set RSTP port path cost to %d", rstp->name, > - rstp_port->port_number, new_port_path_cost); > - rstp_port->port_path_cost = new_port_path_cost; > - rstp_port->selected = false; > - rstp_port->reselect = true; > - ovs_mutex_unlock(&mutex); > + if (path_cost >= RSTP_MIN_PORT_PATH_COST > + && path_cost <= RSTP_MAX_PORT_PATH_COST) { > + VLOG_DBG("%s, port %u, set RSTP port path cost to %d", > + port->rstp->name, port->port_number, path_cost); > + > + port->port_path_cost = path_cost; > + port->selected = false; > + port->reselect = true; > } > } > > /* Gets the root path cost. */ > uint32_t > rstp_get_root_path_cost(const struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > uint32_t cost; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > cost = rstp->root_priority.root_path_cost; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > return cost; > } > > @@ -652,13 +770,14 @@ rstp_get_root_path_cost(const struct rstp *rstp) > */ > bool > rstp_check_and_reset_fdb_flush(struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > bool needs_flush; > struct rstp_port *p; > > needs_flush = false; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > if (rstp->ports_count > 0){ > LIST_FOR_EACH (p, node, &rstp->ports) { > if (p->fdb_flush) { > @@ -670,67 +789,108 @@ rstp_check_and_reset_fdb_flush(struct rstp *rstp) > } > } > } > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > return needs_flush; > } > > -/* Finds a port whose state has changed. If successful, stores the port > whose > - * state changed in '*portp' and returns true. If no port has changed, > stores > - * NULL in '*portp' and returns false. > +/* 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 > + * return '*portp' contains the pointer to the rstp port that changed, or > NULL > + * if no changed port can be found. > * > - * XXX: This function is only called by the main thread, which is also > the one > - * that creates and deletes ports. Otherwise this function is not thread > safe, > - * as the returned '*portp' could become stale before it is referenced by > the > - * caller. */ > -bool > -rstp_get_changed_port(struct rstp *rstp, struct rstp_port **portp) > + * If '*portp' is passed as non-NULL, it must be the value set by the last > + * 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 > + * '*portp' could become stale before it is used in the next invocation. > */ > +void * > +rstp_get_next_changed_port_aux(struct rstp *rstp, struct rstp_port > **portp) > { > - bool changed = false; > + void *aux = NULL; > > - ovs_mutex_lock(&mutex); > - if (rstp->ports_count > 0) { > + ovs_mutex_lock(&rstp_mutex); > + if (*portp == NULL) { > struct rstp_port *p; > > LIST_FOR_EACH (p, node, &rstp->ports) { > if (p->state_changed) { > p->state_changed = false; > + aux = p->aux; > + *portp = p; > + goto out; > + } > + } > + } else { /* continue */ > + struct rstp_port *p = *portp; > + > + LIST_FOR_EACH_CONTINUE (p, node, &rstp->ports) { > + if (p->state_changed) { > + p->state_changed = false; > + aux = p->aux; > *portp = p; > - changed = true; > - ovs_mutex_unlock(&mutex); > - return changed; > + goto out; > } > } > } > + /* No changed port found. */ > *portp = NULL; > - ovs_mutex_unlock(&mutex); > - return changed; > +out: > + ovs_mutex_unlock(&rstp_mutex); > + return aux; > } > > /* Returns the port in 'rstp' with number 'port_number'. > * > * XXX: May only be called while concurrent deletion of ports is > excluded. */ > -struct rstp_port * > -rstp_get_port(struct rstp *rstp, int port_number) > +static struct rstp_port * > +rstp_get_port__(struct rstp *rstp, uint16_t port_number) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port *port; > > - ovs_mutex_lock(&mutex); > + ovs_assert(rstp && port_number > 0 && port_number <= RSTP_MAX_PORTS); > + > if (rstp->ports_count > 0) { > LIST_FOR_EACH (port, node, &rstp->ports) { > if (port->port_number == port_number) { > - ovs_mutex_unlock(&mutex); > return port; > } > } > } > - ovs_mutex_unlock(&mutex); > return NULL; > } > > +struct rstp_port * > +rstp_get_port(struct rstp *rstp, uint16_t port_number) > + OVS_EXCLUDED(rstp_mutex) > +{ > + struct rstp_port *p; > + > + ovs_mutex_lock(&rstp_mutex); > + p = rstp_get_port__(rstp, port_number); > + ovs_mutex_unlock(&rstp_mutex); > + return p; > +} > + > +void * > +rstp_get_port_aux(struct rstp *rstp, uint16_t port_number) > + OVS_EXCLUDED(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; > +} > + > /* Updates the port_enabled parameter. */ > static void > update_port_enabled__(struct rstp_port *p) > - OVS_REQUIRES(mutex) > + OVS_REQUIRES(rstp_mutex) > { > if (p->mac_operational && p->is_administrative_bridge_port > == RSTP_ADMIN_BRIDGE_PORT_STATE_ENABLED) { > @@ -743,68 +903,61 @@ update_port_enabled__(struct rstp_port *p) > /* Sets the port MAC_Operational parameter [6.4.2]. */ > void > rstp_port_set_mac_operational(struct rstp_port *p, bool > new_mac_operational) > + OVS_EXCLUDED(rstp_mutex) > { > struct rstp *rstp; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > rstp = p->rstp; > - p->mac_operational = new_mac_operational; > - update_port_enabled__(p); > - rstp->changes = true; > - move_rstp(rstp); > - ovs_mutex_unlock(&mutex); > -} > - > -/* Gets the port MAC_Operational parameter [6.4.2]. */ > -bool > -rstp_port_get_mac_operational(struct rstp_port *p) > -{ > - bool value; > - > - ovs_mutex_lock(&mutex); > - value = p->mac_operational; > - ovs_mutex_unlock(&mutex); > - return value; > + if (p->mac_operational != new_mac_operational) { > + p->mac_operational = new_mac_operational; > + update_port_enabled__(p); > + rstp->changes = true; > + move_rstp__(rstp); > + } > + ovs_mutex_unlock(&rstp_mutex); > } > > /* Sets the port Administrative Bridge Port parameter. */ > -void > -rstp_port_set_administrative_bridge_port(struct rstp_port *p, > - uint8_t new_admin_port_state) > +static void > +rstp_port_set_administrative_bridge_port__(struct rstp_port *p, > + uint8_t admin_port_state) > + OVS_REQUIRES(rstp_mutex) > { > - if (new_admin_port_state == RSTP_ADMIN_BRIDGE_PORT_STATE_DISABLED > - || new_admin_port_state == RSTP_ADMIN_BRIDGE_PORT_STATE_ENABLED) { > - ovs_mutex_lock(&mutex); > - p->is_administrative_bridge_port = new_admin_port_state; > + if (admin_port_state == RSTP_ADMIN_BRIDGE_PORT_STATE_DISABLED > + || admin_port_state == RSTP_ADMIN_BRIDGE_PORT_STATE_ENABLED) { > + > + p->is_administrative_bridge_port = admin_port_state; > update_port_enabled__(p); > - ovs_mutex_unlock(&mutex); > } > } > > /* Sets the port oper_point_to_point_mac parameter. */ > -void > -rstp_port_set_oper_point_to_point_mac(struct rstp_port *p, > - uint8_t new_oper_p2p_mac) > +static void > +rstp_port_set_oper_point_to_point_mac__(struct rstp_port *p, > + uint8_t new_oper_p2p_mac) > + OVS_REQUIRES(rstp_mutex) > { > if (new_oper_p2p_mac == RSTP_OPER_P2P_MAC_STATE_DISABLED > || new_oper_p2p_mac == RSTP_OPER_P2P_MAC_STATE_ENABLED) { > - ovs_mutex_lock(&mutex); > + > p->oper_point_to_point_mac = new_oper_p2p_mac; > update_port_enabled__(p); > - ovs_mutex_unlock(&mutex); > } > } > > /* Initializes a port with the defaults values for its parameters. */ > static void > rstp_initialize_port_defaults__(struct rstp_port *p) > - OVS_REQUIRES(mutex) > + OVS_REQUIRES(rstp_mutex) > { > - rstp_port_set_administrative_bridge_port(p, > - RSTP_ADMIN_BRIDGE_PORT_STATE_ENABLED); > - rstp_port_set_oper_point_to_point_mac(p, 1); > - rstp_port_set_path_cost(p, RSTP_DEFAULT_PORT_PATH_COST); > - rstp_port_set_auto_edge(p, true); > + rstp_port_set_administrative_bridge_port__(p, > + > RSTP_ADMIN_BRIDGE_PORT_STATE_ENABLED); > + rstp_port_set_oper_point_to_point_mac__(p, 1); > + rstp_port_set_path_cost__(p, RSTP_DEFAULT_PORT_PATH_COST); > + rstp_port_set_admin_edge__(p, false); > + rstp_port_set_auto_edge__(p, true); > + rstp_port_set_mcheck__(p, false); > > /* Initialize state machines. */ > p->port_receive_sm_state = PORT_RECEIVE_SM_INIT; > @@ -821,7 +974,7 @@ rstp_initialize_port_defaults__(struct rstp_port *p) > > void > reinitialize_port__(struct rstp_port *p) > - OVS_REQUIRES(mutex) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp_port temp_port; > struct rstp *rstp; > @@ -829,6 +982,8 @@ reinitialize_port__(struct rstp_port *p) > rstp = p->rstp; > temp_port = *p; > memset(p, 0, sizeof(struct rstp_port)); > + > + p->ref_cnt = temp_port.ref_cnt; > p->rstp = rstp; > p->node = temp_port.node; > p->aux = temp_port.aux; > @@ -845,16 +1000,17 @@ reinitialize_port__(struct rstp_port *p) > > void > reinitialize_port(struct rstp_port *p) > + OVS_EXCLUDED(rstp_mutex) > { > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > reinitialize_port__(p); > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > } > > /* Sets the port state. */ > void > -rstp_port_set_state(struct rstp_port *p, enum rstp_state state) > -OVS_REQUIRES(mutex) > +rstp_port_set_state__(struct rstp_port *p, enum rstp_state state) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *rstp; > > @@ -870,76 +1026,99 @@ OVS_REQUIRES(mutex) > p->rstp_state = state; > } > > +void > +rstp_port_set_state(struct rstp_port *p, enum rstp_state state) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + rstp_port_set_state__(p, state); > + ovs_mutex_unlock(&rstp_mutex); > +} > + > /* Adds a RSTP port. */ > struct rstp_port * > rstp_add_port(struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > struct rstp_port *p = xzalloc(sizeof *p); > > - ovs_mutex_lock(&mutex); > + ovs_refcount_init(&p->ref_cnt); > + > + ovs_mutex_lock(&rstp_mutex); > p->rstp = rstp; > - rstp_port_set_priority(p, RSTP_DEFAULT_PORT_PRIORITY); > - rstp_port_set_port_number(p, 0); > + rstp_port_set_priority__(p, RSTP_DEFAULT_PORT_PRIORITY); > + rstp_port_set_port_number__(p, 0); > p->aux = NULL; > rstp_initialize_port_defaults__(p); > VLOG_DBG("%s: RSTP port "RSTP_PORT_ID_FMT" initialized.", rstp->name, > p->port_id); > > - rstp_port_set_state(p, RSTP_DISCARDING); > + rstp_port_set_state__(p, RSTP_DISCARDING); > list_push_back(&rstp->ports, &p->node); > rstp->ports_count++; > rstp->changes = true; > - move_rstp(rstp); > - ovs_mutex_unlock(&mutex); > + move_rstp__(rstp); > VLOG_DBG("%s: added port "RSTP_PORT_ID_FMT"", rstp->name, p->port_id); > + ovs_mutex_unlock(&rstp_mutex); > return p; > } > > -/* Deletes a RSTP port. */ > -void > -rstp_delete_port(struct rstp_port *p) > +/* Caller has to hold a reference to prevent 'rstp_port' from being > deleted > + * while taking a new reference. */ > +struct rstp_port * > +rstp_port_ref(const struct rstp_port *rp_) > + OVS_EXCLUDED(rstp_mutex) > { > - struct rstp *rstp; > + struct rstp_port *rp = CONST_CAST(struct rstp_port *, rp_); > > - ovs_mutex_lock(&mutex); > - rstp = p->rstp; > - rstp_port_set_state(p, RSTP_DISABLED); > - list_remove(&p->node); > - rstp->ports_count--; > - VLOG_DBG("%s: removed port "RSTP_PORT_ID_FMT"", rstp->name, > p->port_id); > - ovs_mutex_unlock(&mutex); > - free(p); > + if (rp) { > + ovs_refcount_ref(&rp->ref_cnt); > + } > + return rp; > } > > -/* Sets the port Admin Edge parameter. */ > +/* Frees RSTP struct. This can be caller by any thread. */ > void > -rstp_port_set_admin_edge(struct rstp_port *rstp_port, bool new_admin_edge) > +rstp_port_unref(struct rstp_port *rp) > + OVS_EXCLUDED(rstp_mutex) > { > - if (rstp_port->admin_edge != new_admin_edge) { > + if (rp && ovs_refcount_unref(&rp->ref_cnt) == 1) { > struct rstp *rstp; > > - ovs_mutex_lock(&mutex); > - rstp = rstp_port->rstp; > - VLOG_DBG("%s, port %u: set RSTP Admin Edge to %d", rstp->name, > - rstp_port->port_number, new_admin_edge); > - rstp_port->admin_edge = new_admin_edge; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > + rstp = rp->rstp; > + rstp_port_set_state__(rp, RSTP_DISABLED); > + list_remove(&rp->node); > + rstp->ports_count--; > + VLOG_DBG("%s: removed port "RSTP_PORT_ID_FMT"", rstp->name, > rp->port_id); > + ovs_mutex_unlock(&rstp_mutex); > + free(rp); > + } > +} > + > +/* Sets the port Admin Edge parameter. */ > +static void > +rstp_port_set_admin_edge__(struct rstp_port *port, bool admin_edge) > + OVS_REQUIRES(rstp_mutex) > +{ > + if (port->admin_edge != admin_edge) { > + VLOG_DBG("%s, port %u: set RSTP Admin Edge to %d", > port->rstp->name, > + port->port_number, admin_edge); > + > + port->admin_edge = admin_edge; > } > } > > /* Sets the port Auto Edge parameter. */ > -void > -rstp_port_set_auto_edge(struct rstp_port *rstp_port, bool new_auto_edge) > +static void > +rstp_port_set_auto_edge__(struct rstp_port *port, bool auto_edge) > + OVS_REQUIRES(rstp_mutex) > { > - if (rstp_port->auto_edge != new_auto_edge) { > - struct rstp *rstp; > + if (port->auto_edge != auto_edge) { > + VLOG_DBG("%s, port %u: set RSTP Auto Edge to %d", > port->rstp->name, > + port->port_number, auto_edge); > > - ovs_mutex_lock(&mutex); > - rstp = rstp_port->rstp; > - VLOG_DBG("%s, port %u: set RSTP Auto Edge to %d", rstp->name, > - rstp_port->port_number, new_auto_edge); > - rstp_port->auto_edge = new_auto_edge; > - ovs_mutex_unlock(&mutex); > + port->auto_edge = auto_edge; > } > } > > @@ -949,32 +1128,32 @@ rstp_port_set_auto_edge(struct rstp_port > *rstp_port, bool new_auto_edge) > * test whether all STP Bridges (17.4) on the attached LAN have been > removed > * and the Port can continue to transmit RSTP BPDUs. Setting mcheck has no > * effect if stpVersion (17.20.12) is TRUE, i.e., the Bridge is operating > in > - * STP Compatibility. mode. > + * STP Compatibility mode. > */ > -void > -rstp_port_set_mcheck(struct rstp_port *rstp_port, bool new_mcheck) > +static void > +rstp_port_set_mcheck__(struct rstp_port *port, bool mcheck) > + OVS_REQUIRES(rstp_mutex) > { > - struct rstp *rstp; > + /* XXX: Should we also support setting this to false, i.e., when port > + * configuration is changed? */ > + if (mcheck == true && port->rstp->force_protocol_version >= 2) { > + port->mcheck = true; > > - ovs_mutex_lock(&mutex); > - rstp = rstp_port->rstp; > - if (new_mcheck == true && rstp_port->rstp->force_protocol_version >= > 2) { > - rstp_port->mcheck = true; > + VLOG_DBG("%s, port %u: set RSTP mcheck to %d", port->rstp->name, > + port->port_number, mcheck); > } > - VLOG_DBG("%s, port %u: set RSTP mcheck to %d", rstp->name, > - rstp_port->port_number, new_mcheck); > - ovs_mutex_unlock(&mutex); > } > > /* Returns the designated bridge id. */ > rstp_identifier > rstp_get_designated_id(const struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > rstp_identifier designated_id; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > designated_id = rstp->root_priority.designated_bridge_id; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > > return designated_id; > } > @@ -982,12 +1161,13 @@ rstp_get_designated_id(const struct rstp *rstp) > /* Returns the root bridge id. */ > rstp_identifier > rstp_get_root_id(const struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > rstp_identifier root_id; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > root_id = rstp->root_priority.root_bridge_id; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > > return root_id; > } > @@ -995,12 +1175,13 @@ rstp_get_root_id(const struct rstp *rstp) > /* Returns the designated port id. */ > uint16_t > rstp_get_designated_port_id(const struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > uint16_t designated_port_id; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > designated_port_id = rstp->root_priority.designated_port_id; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > > return designated_port_id; > } > @@ -1008,12 +1189,13 @@ rstp_get_designated_port_id(const struct rstp > *rstp) > /* Return the bridge port id. */ > uint16_t > rstp_get_bridge_port_id(const struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > uint16_t bridge_port_id; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > bridge_port_id = rstp->root_priority.bridge_port_id; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > > return bridge_port_id; > } > @@ -1023,13 +1205,14 @@ rstp_get_bridge_port_id(const struct rstp *rstp) > */ > bool > rstp_is_root_bridge(const struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > bool is_root; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > is_root = rstp->bridge_identifier == > rstp->root_priority.designated_bridge_id; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > > return is_root; > } > @@ -1037,12 +1220,13 @@ rstp_is_root_bridge(const struct rstp *rstp) > /* Returns the bridge ID of the bridge currently believed to be the root. > */ > rstp_identifier > rstp_get_designated_root(const struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > rstp_identifier designated_root; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > designated_root = rstp->root_priority.designated_bridge_id; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > > return designated_root; > } > @@ -1052,98 +1236,105 @@ rstp_get_designated_root(const struct rstp *rstp) > */ > struct rstp_port * > rstp_get_root_port(struct rstp *rstp) > + OVS_EXCLUDED(rstp_mutex) > { > struct rstp_port *p; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > if (rstp->ports_count > 0){ > LIST_FOR_EACH (p, node, &rstp->ports) { > if (p->port_id == rstp->root_port_id) { > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > return p; > } > } > } > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > return NULL; > } > > -/* Returns the port ID for 'p'. */ > -uint16_t > -rstp_port_get_id(const struct rstp_port *p) > -{ > - uint16_t port_id; > - > - ovs_mutex_lock(&mutex); > - port_id = p->port_id; > - ovs_mutex_unlock(&mutex); > - > - return port_id; > -} > - > /* Returns the state of port 'p'. */ > enum rstp_state > rstp_port_get_state(const struct rstp_port *p) > { > enum rstp_state state; > > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > state = p->rstp_state; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > > return state; > } > > -/* Returns the role of port 'p'. */ > -enum rstp_port_role > -rstp_port_get_role(const struct rstp_port *p) > -{ > - enum rstp_port_role role; > - > - ovs_mutex_lock(&mutex); > - role = p->role; > - ovs_mutex_unlock(&mutex); > - > - return role; > -} > - > -/* Retrieves BPDU transmit and receive counts for 'p'. */ > +/* Retrieves port status. */ > void > -rstp_port_get_counts(const struct rstp_port *p, > - int *tx_count, int *rx_count, int *error_count, int *uptime) > +rstp_port_get_status(const struct rstp_port *p, uint16_t *id, > + enum rstp_state *state, enum rstp_port_role *role, > + int *tx_count, int *rx_count, int *error_count, > + int *uptime) > + OVS_EXCLUDED(rstp_mutex) > { > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > + *id = p->port_id; > + *state = p->rstp_state; > + *role = p->role; > + > *tx_count = p->tx_count; > *rx_count = p->rx_rstp_bpdu_cnt; > *error_count = p->error_count; > *uptime = p->uptime; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > } > > void > -rstp_port_set_aux(struct rstp_port *p, void *aux) > +rstp_port_set(struct rstp_port *port, uint16_t port_num, int priority, > + uint32_t path_cost, bool is_admin_edge, bool is_auto_edge, > + bool do_mcheck, void *aux) > + OVS_EXCLUDED(rstp_mutex) > { > - ovs_mutex_lock(&mutex); > - p->aux = aux; > - ovs_mutex_unlock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > + port->aux = aux; > + rstp_port_set_priority__(port, priority); > + rstp_port_set_port_number__(port, port_num); > + rstp_port_set_path_cost__(port, path_cost); > + rstp_port_set_admin_edge__(port, is_admin_edge); > + rstp_port_set_auto_edge__(port, is_auto_edge); > + rstp_port_set_mcheck__(port, do_mcheck); > + ovs_mutex_unlock(&rstp_mutex); > } > > -void * > -rstp_port_get_aux(struct rstp_port *p) > +/* Individual setters only used by test-rstp.c. */ > +void > +rstp_port_set_priority(struct rstp_port *port, int priority) > + OVS_EXCLUDED(rstp_mutex) > { > - void *aux; > + ovs_mutex_lock(&rstp_mutex); > + rstp_port_set_priority__(port, priority); > + ovs_mutex_unlock(&rstp_mutex); > +} > > - ovs_mutex_lock(&mutex); > - aux = p->aux; > - ovs_mutex_unlock(&mutex); > +void > +rstp_port_set_path_cost(struct rstp_port *port, uint32_t path_cost) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + rstp_port_set_path_cost__(port, path_cost); > + ovs_mutex_unlock(&rstp_mutex); > +} > > - return aux; > +void > +rstp_port_set_aux(struct rstp_port *port, void *aux) > + OVS_EXCLUDED(rstp_mutex) > +{ > + ovs_mutex_lock(&rstp_mutex); > + port->aux = aux; > + ovs_mutex_unlock(&rstp_mutex); > } > > /* Unixctl. */ > static struct rstp * > rstp_find(const char *name) > - OVS_REQUIRES(mutex) > + OVS_REQUIRES(rstp_mutex) > { > struct rstp *rstp; > > @@ -1158,8 +1349,9 @@ rstp_find(const char *name) > static void > rstp_unixctl_tcn(struct unixctl_conn *conn, int argc, > const char *argv[], void *aux OVS_UNUSED) > + OVS_EXCLUDED(rstp_mutex) > { > - ovs_mutex_lock(&mutex); > + ovs_mutex_lock(&rstp_mutex); > if (argc > 1) { > struct rstp *rstp = rstp_find(argv[1]); > if (!rstp) { > @@ -1167,16 +1359,16 @@ rstp_unixctl_tcn(struct unixctl_conn *conn, int > argc, > goto out; > } > rstp->changes = true; > - move_rstp(rstp); > + move_rstp__(rstp); > } else { > struct rstp *rstp; > LIST_FOR_EACH (rstp, node, all_rstps) { > rstp->changes = true; > - move_rstp(rstp); > + move_rstp__(rstp); > } > } > unixctl_command_reply(conn, "OK"); > > out: > - ovs_mutex_unlock(&mutex); > + ovs_mutex_unlock(&rstp_mutex); > } > diff --git a/lib/rstp.h b/lib/rstp.h > index 0e8d101..c6c4a71 100644 > --- a/lib/rstp.h > +++ b/lib/rstp.h > @@ -35,6 +35,12 @@ > #include "compiler.h" > #include "util.h" > > +/* Thread Safety: Callers passing in RSTP and RSTP port object > + * pointers must hold a reference to the passed object to ensure that > + * the object does not become stale while it is being accessed. */ > + > +extern struct ovs_mutex rstp_mutex; > + > #define RSTP_MAX_PORTS 4095 > > struct ofpbuf; > @@ -119,86 +125,134 @@ struct rstp_port; > struct ofproto_rstp_settings; > > const char *rstp_state_name(enum rstp_state); > +const char *rstp_port_role_name(enum rstp_port_role); > static inline bool rstp_forward_in_state(enum rstp_state); > static inline bool rstp_learn_in_state(enum rstp_state); > static inline bool rstp_should_manage_bpdu(enum rstp_state state); > -const char *rstp_port_role_name(enum rstp_port_role); > > -void rstp_init(void); > +/* Must be called before any other rstp function is called. */ > +void rstp_init(void) > + OVS_EXCLUDED(rstp_mutex); > > struct rstp * rstp_create(const char *, rstp_identifier bridge_id, > void (*send_bpdu)(struct ofpbuf *, int port_no, > void *aux), > - void *aux); > + void *aux) > + OVS_EXCLUDED(rstp_mutex); > > -struct rstp *rstp_ref(struct rstp *); > -void rstp_unref(struct rstp *); > +struct rstp *rstp_ref(struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_unref(struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > > /* Functions used outside RSTP, to call functions defined in > rstp-state-machines.h */ > -void rstp_tick_timers(struct rstp *); > -void rstp_received_bpdu(struct rstp_port *, const void *, size_t); > - > -bool rstp_check_and_reset_fdb_flush(struct rstp *); > -bool rstp_get_changed_port(struct rstp *, struct rstp_port **); > +void rstp_tick_timers(struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_port_received_bpdu(struct rstp_port *, const void *bpdu, > + size_t bpdu_size) > + OVS_EXCLUDED(rstp_mutex); > +bool rstp_check_and_reset_fdb_flush(struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +void *rstp_get_next_changed_port_aux(struct rstp *, struct rstp_port **) > + OVS_EXCLUDED(rstp_mutex); > void rstp_port_set_mac_operational(struct rstp_port *, > - bool new_mac_operational); > -bool rstp_port_get_mac_operational(struct rstp_port *); > + bool new_mac_operational) > + OVS_EXCLUDED(rstp_mutex); > > /* Bridge setters */ > -void rstp_set_bridge_address(struct rstp *, rstp_identifier > bridge_address); > -void rstp_set_bridge_priority(struct rstp *, int new_priority); > -void rstp_set_bridge_ageing_time(struct rstp *, int new_ageing_time); > +void rstp_set_bridge_address(struct rstp *, rstp_identifier > bridge_address) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_set_bridge_priority(struct rstp *, int new_priority) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_set_bridge_ageing_time(struct rstp *, int new_ageing_time) > + OVS_EXCLUDED(rstp_mutex); > void rstp_set_bridge_force_protocol_version(struct rstp *, > - enum > rstp_force_protocol_version); > -void rstp_set_bridge_hello_time(struct rstp *); > -void rstp_set_bridge_max_age(struct rstp *, int new_max_age); > -void rstp_set_bridge_forward_delay(struct rstp *, int new_forward_delay); > + enum > rstp_force_protocol_version) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_set_bridge_max_age(struct rstp *, int new_max_age) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_set_bridge_forward_delay(struct rstp *, int new_forward_delay) > + OVS_EXCLUDED(rstp_mutex); > void rstp_set_bridge_transmit_hold_count(struct rstp *, > - int new_transmit_hold_count); > -void rstp_set_bridge_migrate_time(struct rstp *); > -void rstp_set_bridge_times(struct rstp *, int new_forward_delay, > - int new_hello_time, int new_max_age, > - int new_message_age); > - > -struct rstp_port * rstp_add_port(struct rstp *); > -void reinitialize_port(struct rstp_port *p); > -void rstp_delete_port(struct rstp_port *); > -/* Port setters */ > -void rstp_port_set_priority(struct rstp_port *, int new_port_priority); > -void rstp_port_set_port_number(struct rstp_port *, uint16_t > new_port_number); > -uint32_t rstp_convert_speed_to_cost(unsigned int speed); > -void rstp_port_set_path_cost(struct rstp_port *, uint32_t > new_port_path_cost); > -void rstp_port_set_admin_edge(struct rstp_port *, bool new_admin_edge); > -void rstp_port_set_auto_edge(struct rstp_port *, bool new_auto_edge); > -void rstp_port_set_state(struct rstp_port *, enum rstp_state new_state); > -void rstp_port_set_aux(struct rstp_port *, void *aux); > -void rstp_port_set_administrative_bridge_port(struct rstp_port *, > uint8_t); > -void rstp_port_set_oper_point_to_point_mac(struct rstp_port *, uint8_t); > -void rstp_port_set_mcheck(struct rstp_port *, bool new_mcheck); > + int new_transmit_hold_count) > + OVS_EXCLUDED(rstp_mutex); > > /* Bridge getters */ > -const char * rstp_get_name(const struct rstp *); > -rstp_identifier rstp_get_root_id(const struct rstp *); > -rstp_identifier rstp_get_bridge_id(const struct rstp *); > -rstp_identifier rstp_get_designated_id(const struct rstp *); > -uint32_t rstp_get_root_path_cost(const struct rstp *); > -uint16_t rstp_get_designated_port_id(const struct rstp *); > -uint16_t rstp_get_bridge_port_id(const struct rstp *); > -struct rstp_port * rstp_get_root_port(struct rstp *); > -rstp_identifier rstp_get_designated_root(const struct rstp *); > -bool rstp_is_root_bridge(const struct rstp *); > - > -/* Port getters */ > -int rstp_port_number(const struct rstp_port *); > -struct rstp_port *rstp_get_port(struct rstp *, int port_no); > -uint16_t rstp_port_get_id(const struct rstp_port *); > -enum rstp_state rstp_port_get_state(const struct rstp_port *); > -enum rstp_port_role rstp_port_get_role(const struct rstp_port *); > -void rstp_port_get_counts(const struct rstp_port *, int *tx_count, > - int *rx_count, int *error_count, int *uptime); > -void * rstp_port_get_aux(struct rstp_port *); > +const char * rstp_get_name(const struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +rstp_identifier rstp_get_root_id(const struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +rstp_identifier rstp_get_bridge_id(const struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +rstp_identifier rstp_get_designated_id(const struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +uint32_t rstp_get_root_path_cost(const struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +uint16_t rstp_get_designated_port_id(const struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +uint16_t rstp_get_bridge_port_id(const struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +struct rstp_port * rstp_get_root_port(struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +rstp_identifier rstp_get_designated_root(const struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +bool rstp_is_root_bridge(const struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > + > +/* RSTP ports */ > +struct rstp_port * rstp_add_port(struct rstp *) > + OVS_EXCLUDED(rstp_mutex); > +struct rstp_port *rstp_port_ref(const struct rstp_port *) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_port_unref(struct rstp_port *) > + OVS_EXCLUDED(rstp_mutex); > + > +uint32_t rstp_convert_speed_to_cost(unsigned int speed); > > +void rstp_port_set(struct rstp_port *, uint16_t port_num, int priority, > + uint32_t path_cost, bool is_admin_edge, bool > is_auto_edge, > + bool do_mcheck, void *aux) > + OVS_EXCLUDED(rstp_mutex); > + > +enum rstp_state rstp_port_get_state(const struct rstp_port *) > + OVS_EXCLUDED(rstp_mutex); > + > +void rstp_port_get_status(const struct rstp_port *, uint16_t *id, > + enum rstp_state *state, enum rstp_port_role > *role, > + int *tx_count, 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); > + > + > +/* Internal API for rstp-state-machines.c */ > + > +void rstp_port_set_state__(struct rstp_port *, enum rstp_state state) > + OVS_REQUIRES(rstp_mutex); > + > + > +/* Internal API for test-rstp.c */ > + > +struct rstp_port *rstp_get_port(struct rstp *rstp, uint16_t port_number) > + OVS_EXCLUDED(rstp_mutex); > +void reinitialize_port(struct rstp_port *p) > + OVS_EXCLUDED(rstp_mutex); > + > +int rstp_port_get_number(const struct rstp_port *) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_port_set_priority(struct rstp_port *port, int priority) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_port_set_aux(struct rstp_port *p, void *aux) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_port_set_path_cost(struct rstp_port *port, uint32_t path_cost) > + OVS_EXCLUDED(rstp_mutex); > +void rstp_port_set_state(struct rstp_port *p, enum rstp_state state) > + OVS_EXCLUDED(rstp_mutex); > + > + > /* Inline functions. */ > /* Returns true if 'state' is one in which BPDU packets should be received > * and transmitted on a port, false otherwise. > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > index 187a3a4..f4d8de2 100644 > --- a/ofproto/ofproto-dpif-xlate.c > +++ b/ofproto/ofproto-dpif-xlate.c > @@ -150,7 +150,7 @@ struct xport { > enum ofputil_port_config config; /* OpenFlow port configuration. */ > enum ofputil_port_state state; /* OpenFlow port state. */ > int stp_port_no; /* STP port number or -1 if not in > use. */ > - int rstp_port_no; /* RSTP port number or -1 if not in > use. */ > + struct rstp_port *rstp_port; /* RSTP port or null. */ > > struct hmap skb_priorities; /* Map of 'skb_priority_to_dscp's. */ > > @@ -376,7 +376,7 @@ static void xlate_xbundle_set(struct xbundle *xbundle, > static void xlate_xport_set(struct xport *xport, odp_port_t odp_port, > const struct netdev *netdev, const struct cfm > *cfm, > const struct bfd *bfd, int stp_port_no, > - int rstp_port_no, > + const struct rstp_port *rstp_port, > enum ofputil_port_config config, > enum ofputil_port_state state, bool is_tunnel, > bool may_enable); > @@ -514,18 +514,23 @@ xlate_xbundle_set(struct xbundle *xbundle, > static void > xlate_xport_set(struct xport *xport, odp_port_t odp_port, > const struct netdev *netdev, const struct cfm *cfm, > - const struct bfd *bfd, int stp_port_no, int rstp_port_no, > + const struct bfd *bfd, int stp_port_no, > + const struct rstp_port* rstp_port, > enum ofputil_port_config config, enum ofputil_port_state > state, > bool is_tunnel, bool may_enable) > { > xport->config = config; > xport->state = state; > xport->stp_port_no = stp_port_no; > - xport->rstp_port_no = rstp_port_no; > xport->is_tunnel = is_tunnel; > xport->may_enable = may_enable; > xport->odp_port = odp_port; > > + if (xport->rstp_port != rstp_port) { > + rstp_port_unref(xport->rstp_port); > + xport->rstp_port = rstp_port_ref(rstp_port); > + } > + > if (xport->cfm != cfm) { > cfm_unref(xport->cfm); > xport->cfm = cfm_ref(cfm); > @@ -604,7 +609,7 @@ xlate_xport_copy(struct xbridge *xbridge, struct > xbundle *xbundle, > xlate_xport_init(new_xcfg, new_xport); > > xlate_xport_set(new_xport, xport->odp_port, xport->netdev, xport->cfm, > - xport->bfd, xport->stp_port_no, xport->rstp_port_no, > + xport->bfd, xport->stp_port_no, xport->rstp_port, > xport->config, xport->state, xport->is_tunnel, > xport->may_enable); > > @@ -843,7 +848,8 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct > ofbundle *ofbundle, > struct ofport_dpif *ofport, ofp_port_t ofp_port, > odp_port_t odp_port, const struct netdev *netdev, > const struct cfm *cfm, const struct bfd *bfd, > - struct ofport_dpif *peer, int stp_port_no, int > rstp_port_no, > + struct ofport_dpif *peer, int stp_port_no, > + const struct rstp_port *rstp_port, > const struct ofproto_port_queue *qdscp_list, size_t > n_qdscp, > enum ofputil_port_config config, > enum ofputil_port_state state, bool is_tunnel, > @@ -867,7 +873,7 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct > ofbundle *ofbundle, > ovs_assert(xport->ofp_port == ofp_port); > > xlate_xport_set(xport, odp_port, netdev, cfm, bfd, stp_port_no, > - rstp_port_no, config, state, is_tunnel, may_enable); > + rstp_port, config, state, is_tunnel, may_enable); > > if (xport->peer) { > xport->peer->peer = NULL; > @@ -1121,45 +1127,40 @@ stp_process_packet(const struct xport *xport, > const struct ofpbuf *packet) > } > } > > -static struct rstp_port * > -xport_get_rstp_port(const struct xport *xport) > +static enum rstp_state > +xport_get_rstp_port_state(const struct xport *xport) > { > - return xport->xbridge->rstp && xport->rstp_port_no != -1 > - ? rstp_get_port(xport->xbridge->rstp, xport->rstp_port_no) > - : NULL; > + return xport->rstp_port > + ? rstp_port_get_state(xport->rstp_port) > + : RSTP_DISABLED; > } > > static bool > xport_rstp_learn_state(const struct xport *xport) > { > - struct rstp_port *rp = xport_get_rstp_port(xport); > - return !rp || rstp_learn_in_state(rstp_port_get_state(rp)); > + return rstp_learn_in_state(xport_get_rstp_port_state(xport)); > } > > static bool > xport_rstp_forward_state(const struct xport *xport) > { > - struct rstp_port *rp = xport_get_rstp_port(xport); > - return !rp || rstp_forward_in_state(rstp_port_get_state(rp)); > + return rstp_forward_in_state(xport_get_rstp_port_state(xport)); > } > > static bool > xport_rstp_should_manage_bpdu(const struct xport *xport) > { > - struct rstp_port *rp = xport_get_rstp_port(xport); > - return rp && rstp_should_manage_bpdu(rstp_port_get_state(rp)); > + return rstp_should_manage_bpdu(xport_get_rstp_port_state(xport)); > } > > static void > rstp_process_packet(const struct xport *xport, const struct ofpbuf > *packet) > { > - struct rstp_port *rp = xport_get_rstp_port(xport); > struct ofpbuf payload = *packet; > struct eth_header *eth = ofpbuf_data(&payload); > > - /* Sink packets on ports that have RSTP disabled when the bridge has > - * RSTP enabled. */ > - if (!rp || rstp_port_get_state(rp) == RSTP_DISABLED) { > + /* Sink packets on ports that have no RSTP. */ > + if (!xport->rstp_port) { > return; > } > > @@ -1169,7 +1170,8 @@ rstp_process_packet(const struct xport *xport, const > struct ofpbuf *packet) > } > > if (ofpbuf_try_pull(&payload, ETH_HEADER_LEN + LLC_HEADER_LEN)) { > - rstp_received_bpdu(rp, ofpbuf_data(&payload), > ofpbuf_size(&payload)); > + rstp_port_received_bpdu(xport->rstp_port, ofpbuf_data(&payload), > + ofpbuf_size(&payload)); > } > } > > @@ -2410,8 +2412,9 @@ process_special(struct xlate_ctx *ctx, const struct > flow *flow, > } else if ((xbridge->stp || xbridge->rstp) && > stp_should_process_flow(flow, wc)) { > if (packet) { > - xbridge->stp ? stp_process_packet(xport, packet) : > - rstp_process_packet(xport, packet); > + xbridge->stp > + ? stp_process_packet(xport, packet) > + : rstp_process_packet(xport, packet); > } > return SLOW_STP; > } else { > diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h > index 9962629..3edb620 100644 > --- a/ofproto/ofproto-dpif-xlate.h > +++ b/ofproto/ofproto-dpif-xlate.h > @@ -167,7 +167,8 @@ void xlate_ofport_set(struct ofproto_dpif *, struct > ofbundle *, > struct ofport_dpif *, ofp_port_t, odp_port_t, > const struct netdev *, const struct cfm *, > const struct bfd *, struct ofport_dpif *peer, > - int stp_port_no, int rstp_port_no, > + int stp_port_no, > + const struct rstp_port *rstp_port, > const struct ofproto_port_queue *qdscp, > size_t n_qdscp, enum ofputil_port_config, > enum ofputil_port_state, bool is_tunnel, > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index 5d5aa09..207de1d 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -631,16 +631,14 @@ type_run(const char *type) > int stp_port = ofport->stp_port > ? stp_port_no(ofport->stp_port) > : -1; > - int rstp_port = ofport->rstp_port > - ? rstp_port_number(ofport->rstp_port) > - : -1; > xlate_ofport_set(ofproto, ofport->bundle, ofport, > ofport->up.ofp_port, ofport->odp_port, > ofport->up.netdev, ofport->cfm, > ofport->bfd, ofport->peer, stp_port, > - rstp_port, ofport->qdscp, > ofport->n_qdscp, > - ofport->up.pp.config, > ofport->up.pp.state, > - ofport->is_tunnel, ofport->may_enable); > + ofport->rstp_port, ofport->qdscp, > + ofport->n_qdscp, ofport->up.pp.config, > + ofport->up.pp.state, ofport->is_tunnel, > + ofport->may_enable); > } > xlate_txn_commit(); > } > @@ -1682,9 +1680,7 @@ port_destruct(struct ofport *port_) > if (port->stp_port) { > stp_port_disable(port->stp_port); > } > - if (port->rstp_port) { > - rstp_delete_port(port->rstp_port); > - } > + set_rstp_port(port_, NULL); > if (ofproto->sflow) { > dpif_sflow_del_port(ofproto->sflow, port->odp_port); > } > @@ -1911,10 +1907,9 @@ static void > rstp_send_bpdu_cb(struct ofpbuf *pkt, int port_num, void *ofproto_) > { > struct ofproto_dpif *ofproto = ofproto_; > - struct rstp_port *rp = rstp_get_port(ofproto->rstp, port_num); > struct ofport_dpif *ofport; > > - ofport = rstp_port_get_aux(rp); > + ofport = rstp_get_port_aux(ofproto->rstp, port_num); > if (!ofport) { > VLOG_WARN_RL(&rl, "%s: cannot send BPDU on unknown RSTP port %d", > ofproto->up.name, port_num); > @@ -2065,17 +2060,16 @@ rstp_run(struct ofproto_dpif *ofproto) > long long int now = time_msec(); > long long int elapsed = now - ofproto->rstp_last_tick; > struct rstp_port *rp; > + struct ofport_dpif *ofport; > > /* Every second, decrease the values of the timers. */ > if (elapsed >= 1000) { > rstp_tick_timers(ofproto->rstp); > ofproto->rstp_last_tick = now; > } > - while (rstp_get_changed_port(ofproto->rstp, &rp)) { > - struct ofport_dpif *ofport = rstp_port_get_aux(rp); > - if (ofport) { > - update_rstp_port_state(ofport); > - } > + rp = NULL; > + while ((ofport = rstp_get_next_changed_port_aux(ofproto->rstp, > &rp))) { > + update_rstp_port_state(ofport); > } > /* FIXME: This check should be done on-event (i.e., when setting > * p->fdb_flush) and not periodically. > @@ -2213,7 +2207,7 @@ set_stp_port(struct ofport *ofport_, > } > return 0; > } else if (sp && stp_port_no(sp) != s->port_num > - && ofport == stp_port_get_aux(sp)) { > + && ofport == stp_port_get_aux(sp)) { > /* The port-id changed, so disable the old one if it's not > * already in use by another port. */ > stp_port_disable(sp); > @@ -2323,59 +2317,23 @@ set_rstp_port(struct ofport *ofport_, > struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); > struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto); > struct rstp_port *rp = ofport->rstp_port; > - int stp_port; > > if (!s || !s->enable) { > if (rp) { > + rstp_port_unref(rp); > ofport->rstp_port = NULL; > - rstp_delete_port(rp); > update_rstp_port_state(ofport); > } > return; > - } else if (rp && rstp_port_number(rp) != s->port_num > - && ofport == rstp_port_get_aux(rp)) { > - /* The port-id changed, so disable the old one if it's not > - * already in use by another port. */ > - if (s->port_num != 0) { > - xlate_txn_start(); > - stp_port = ofport->stp_port ? stp_port_no(ofport->stp_port) : > -1; > - xlate_ofport_set(ofproto, ofport->bundle, ofport, > - ofport->up.ofp_port, ofport->odp_port, > - ofport->up.netdev, ofport->cfm, > - ofport->bfd, ofport->peer, stp_port, > - s->port_num, > - ofport->qdscp, ofport->n_qdscp, > - ofport->up.pp.config, ofport->up.pp.state, > - ofport->is_tunnel, ofport->may_enable); > - xlate_txn_commit(); > - } > - > - rstp_port_set_aux(rp, ofport); > - rstp_port_set_priority(rp, s->priority); > - rstp_port_set_port_number(rp, s->port_num); > - rstp_port_set_path_cost(rp, s->path_cost); > - rstp_port_set_admin_edge(rp, s->admin_edge_port); > - rstp_port_set_auto_edge(rp, s->auto_edge); > - rstp_port_set_mcheck(rp, s->mcheck); > - > - update_rstp_port_state(ofport); > - > - return; > } > - rp = ofport->rstp_port = rstp_get_port(ofproto->rstp, s->port_num); > - /* Enable RSTP on port */ > + > + /* Check if need to add a new port. */ > if (!rp) { > rp = ofport->rstp_port = rstp_add_port(ofproto->rstp); > } > - /* Setters */ > - rstp_port_set_aux(rp, ofport); > - rstp_port_set_priority(rp, s->priority); > - rstp_port_set_port_number(rp, s->port_num); > - rstp_port_set_path_cost(rp, s->path_cost); > - rstp_port_set_admin_edge(rp, s->admin_edge_port); > - rstp_port_set_auto_edge(rp, s->auto_edge); > - rstp_port_set_mcheck(rp, s->mcheck); > > + rstp_port_set(rp, s->port_num, s->priority, s->path_cost, > + s->admin_edge_port, s->auto_edge, s->mcheck, ofport); > update_rstp_port_state(ofport); > } > > @@ -2393,11 +2351,8 @@ get_rstp_port_status(struct ofport *ofport_, > } > > s->enabled = true; > - s->port_id = rstp_port_get_id(rp); > - s->state = rstp_port_get_state(rp); > - s->role = rstp_port_get_role(rp); > - rstp_port_get_counts(rp, &s->tx_count, &s->rx_count, > - &s->error_count, &s->uptime); > + rstp_port_get_status(rp, &s->port_id, &s->state, &s->role, > &s->tx_count, > + &s->rx_count, &s->error_count, &s->uptime); > } > > > @@ -3133,16 +3088,15 @@ port_run(struct ofport_dpif *ofport) > > if (ofport->may_enable != enable) { > struct ofproto_dpif *ofproto = > ofproto_dpif_cast(ofport->up.ofproto); > - ofproto->backer->need_revalidate = REV_PORT_TOGGLED; > - } > > - ofport->may_enable = enable; > + ofproto->backer->need_revalidate = REV_PORT_TOGGLED; > > - if (ofport->rstp_port) { > - if (rstp_port_get_mac_operational(ofport->rstp_port) != enable) { > + if (ofport->rstp_port) { > rstp_port_set_mac_operational(ofport->rstp_port, enable); > } > } > + > + ofport->may_enable = enable; > } > > static int > diff --git a/tests/test-rstp.c b/tests/test-rstp.c > index ad71f04..a365423 100644 > --- a/tests/test-rstp.c > +++ b/tests/test-rstp.c > @@ -66,6 +66,7 @@ static struct test_case * > new_test_case(void) > { > struct test_case *tc = xmalloc(sizeof *tc); > + > tc->n_bridges = 0; > tc->n_lans = 0; > return tc; > @@ -86,9 +87,11 @@ send_bpdu(struct ofpbuf *pkt, int port_no, void *b_) > > for (i = 0; i < lan->n_conns; i++) { > struct lan_conn *conn = &lan->conns[i]; > + > if (conn->bridge != b || conn->port_no != port_no) { > struct bridge *dst = conn->bridge; > struct bpdu *bpdu = &dst->rxq[dst->rxq_head++ % RXQ_SIZE]; > + > assert(dst->rxq_head - dst->rxq_tail <= RXQ_SIZE); > bpdu->data = xmemdup(data, size); > bpdu->size = size; > @@ -154,6 +157,7 @@ reconnect_port(struct bridge *b, int port_no, struct > lan *new_lan) > if (old_lan) { > for (j = 0; j < old_lan->n_conns; j++) { > struct lan_conn *c = &old_lan->conns[j]; > + > if (c->bridge == b && c->port_no == port_no) { > memmove(c, c + 1, sizeof *c * (old_lan->n_conns - j - 1)); > old_lan->n_conns--; > @@ -166,6 +170,7 @@ reconnect_port(struct bridge *b, int port_no, struct > lan *new_lan) > b->ports[port_no] = new_lan; > if (new_lan) { > int conn_no = new_lan->n_conns++; > + > assert(conn_no < ARRAY_SIZE(new_lan->conns)); > new_lan->conns[conn_no].bridge = b; > new_lan->conns[conn_no].port_no = port_no; > @@ -241,6 +246,7 @@ dump_bridge_tree(struct test_case *tc, struct bridge > *b, int level) > for (i = 0; i < b->n_ports; i++) { > struct lan *lan = b->ports[i]; > struct rstp_port *p = rstp_get_port(b->rstp, i); > + > if (rstp_port_get_state(p) == RSTP_FORWARDING && lan) { > dump_lan_tree(tc, lan, level + 1); > } > @@ -262,6 +268,7 @@ dump_lan_tree(struct test_case *tc, struct lan *lan, > int level) > printf("%s\n", lan->name); > for (i = 0; i < lan->n_conns; i++) { > struct bridge *b = lan->conns[i].bridge; > + > dump_bridge_tree(tc, b, level + 1); > } > } > @@ -273,15 +280,18 @@ tree(struct test_case *tc) > > for (i = 0; i < tc->n_bridges; i++) { > struct bridge *b = tc->bridges[i]; > + > b->reached = false; > } > for (i = 0; i < tc->n_lans; i++) { > struct lan *lan = tc->lans[i]; > + > lan->reached = false; > } > for (i = 0; i < tc->n_bridges; i++) { > struct bridge *b = tc->bridges[i]; > struct rstp *rstp = b->rstp; > + > if (rstp_is_root_bridge(rstp)) { > dump_bridge_tree(tc, b, 0); > } > @@ -292,6 +302,7 @@ static void > simulate(struct test_case *tc, int granularity) > { > int time, i, round_trips; > + > for (time = 0; time < 1000 * 180; time += granularity) { > > for (i = 0; i < tc->n_bridges; i++) { > @@ -299,12 +310,16 @@ simulate(struct test_case *tc, int granularity) > } > for (round_trips = 0; round_trips < granularity; round_trips++) { > bool any = false; > + > for (i = 0; i < tc->n_bridges; i++) { > struct bridge *b = tc->bridges[i]; > + > for (; b->rxq_tail != b->rxq_head; b->rxq_tail++) { > struct bpdu *bpdu = &b->rxq[b->rxq_tail % RXQ_SIZE]; > - rstp_received_bpdu(rstp_get_port(b->rstp, > bpdu->port_no), > - bpdu->data, bpdu->size); > + > + rstp_port_received_bpdu(rstp_get_port(b->rstp, > + bpdu->port_no), > + bpdu->data, bpdu->size); > free(bpdu->data); > any = true; > } > @@ -396,6 +411,7 @@ static bool > get_int(int *intp) > { > char *save_pos = pos; > + > if (token && isdigit((unsigned char) *token)) { > *intp = strtol(token, NULL, 0); > get_token(); > @@ -421,6 +437,7 @@ static int > must_get_int(void) > { > int x; > + > if (!get_int(&x)) { > err("expected integer"); > } > @@ -442,6 +459,8 @@ test_rstp_main(int argc, char *argv[]) > FILE *input_file; > int i; > > + rstp_init(); > + > vlog_set_pattern(VLF_CONSOLE, "%c|%p|%m"); > vlog_set_levels(NULL, VLF_SYSLOG, VLL_OFF); > > @@ -458,6 +477,7 @@ test_rstp_main(int argc, char *argv[]) > tc = new_test_case(); > for (i = 0; i < 26; i++) { > char name[2]; > + > name[0] = 'a' + i; > name[1] = '\0'; > new_lan(tc, name); > @@ -499,6 +519,7 @@ test_rstp_main(int argc, char *argv[]) > if (match("=")) { > for (port_no = 1; port_no < MAX_PORTS; port_no++) { > struct rstp_port *p = rstp_get_port(bridge->rstp, > port_no); > + > if (!token || match("X")) { > /* Disable port. */ > reinitialize_port(p); > @@ -565,6 +586,7 @@ test_rstp_main(int argc, char *argv[]) > > if (match("rootid")) { > uint64_t rootid; > + > must_match(":"); > rootid = must_get_int(); > if (match("^")) { > @@ -594,6 +616,7 @@ test_rstp_main(int argc, char *argv[]) > for (port_no = 1; port_no < b->n_active_ports; port_no++) > { > struct rstp_port *p = rstp_get_port(rstp, port_no); > enum rstp_state state = rstp_port_get_state(p); > + > if (state != RSTP_DISABLED && state != > RSTP_FORWARDING) { > warn("%s: root port %d in state %s", > rstp_get_name(b->rstp), port_no, > @@ -604,6 +627,7 @@ test_rstp_main(int argc, char *argv[]) > for (port_no = 1; port_no < b->n_active_ports; port_no++) > { > struct rstp_port *p = rstp_get_port(rstp, port_no); > enum rstp_state state; > + > if (token == NULL || match("D")) { > state = RSTP_DISABLED; > } else if (match("Di")) { > @@ -625,8 +649,10 @@ test_rstp_main(int argc, char *argv[]) > } > if (state == RSTP_FORWARDING) { > struct rstp_port *root_port = > rstp_get_root_port(rstp); > + > if (match(":")) { > int root_path_cost = must_get_int(); > + > if (p != root_port) { > warn("%s: port %d is not the root port", > rstp_get_name(rstp), port_no); > @@ -636,7 +662,7 @@ test_rstp_main(int argc, char *argv[]) > } else { > warn("%s: (port %d is the root port)", > rstp_get_name(rstp), > - rstp_port_number(root_port)); > + rstp_port_get_number(root_port)); > } > } else if (cost_value != root_path_cost) { > warn("%s: root path cost is %d, should be > %d", > @@ -666,14 +692,16 @@ test_rstp_main(int argc, char *argv[]) > > for (i = 0; i < tc->n_lans; i++) { > struct lan *lan = tc->lans[i]; > + > free(CONST_CAST(char *, lan->name)); > free(lan); > } > for (i = 0; i < tc->n_bridges; i++) { > struct bridge *bridge = tc->bridges[i]; > int j; > + > for (j = 1; j < MAX_PORTS; j++) { > - rstp_delete_port(rstp_get_port(bridge->rstp, j)); > + rstp_port_unref(rstp_get_port(bridge->rstp, j)); > } > rstp_unref(bridge->rstp); > free(bridge); > -- > 1.7.10.4 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev