Acked-by: Jarno Rajahalme <jrajaha...@nicira.com> & merged to master,
Jarno On Nov 14, 2014, at 9:26 AM, Daniele Venturino <daniele.ventur...@m3s.it> wrote: > Global transitions are highest priority transitions. When the condition > associated with a global transition is met, it supersedes all other exit > conditions including UCT. > > Extracted from 802.1D-2004 standard (17.16): > > A transition that is global in nature (i.e., a transition that occurs from any > of the possible states if the condition attached to the arrow is met) is > denoted by an open arrow, i.e., no specific state is identified as the origin > of the transition. When the condition associated with a global transition is > met, it supersedes all other exit conditions including UCT. The special global > condition BEGIN supersedes all other global conditions, and once asserted > remains asserted until all state blocks have executed to the point that > variable assignments and other consequences of their execution remain > unchanged. > > Signed-off-by: Daniele Venturino <daniele.ventur...@m3s.it> > --- > lib/rstp-state-machines.c | 265 ++++++++++++++++++++++++++++++++-------------- > 1 file changed, 188 insertions(+), 77 deletions(-) > > diff --git a/lib/rstp-state-machines.c b/lib/rstp-state-machines.c > index ac66488..fda8a72 100644 > --- a/lib/rstp-state-machines.c > +++ b/lib/rstp-state-machines.c > @@ -518,7 +518,11 @@ port_receive_sm(struct rstp_port *p) > p->port_receive_sm_state = PORT_RECEIVE_SM_DISCARD; > /* no break */ > case PORT_RECEIVE_SM_DISCARD: > - if (p->rcvd_bpdu && p->port_enabled) { > + if ((p->rcvd_bpdu || (p->edge_delay_while != r->migrate_time)) > + && !p->port_enabled) { > + /* Global transition. */ > + p->port_receive_sm_state = PORT_RECEIVE_SM_DISCARD_EXEC; > + } else if (p->rcvd_bpdu && p->port_enabled) { > p->port_receive_sm_state = PORT_RECEIVE_SM_RECEIVE_EXEC; > } > break; > @@ -530,7 +534,11 @@ port_receive_sm(struct rstp_port *p) > p->port_receive_sm_state = PORT_RECEIVE_SM_RECEIVE; > /* no break */ > case PORT_RECEIVE_SM_RECEIVE: > - if (p->rcvd_bpdu && p->port_enabled && !p->rcvd_msg) { > + if ((p->rcvd_bpdu || (p->edge_delay_while != r->migrate_time)) > + && !p->port_enabled) { > + /* Global transition. */ > + p->port_receive_sm_state = PORT_RECEIVE_SM_DISCARD_EXEC; > + } else if (p->rcvd_bpdu && p->port_enabled && !p->rcvd_msg) { > p->port_receive_sm_state = PORT_RECEIVE_SM_RECEIVE_EXEC; > } > break; > @@ -1127,12 +1135,11 @@ port_information_sm(struct rstp_port *p) > old_state = p->port_information_sm_state; > r = p->rstp; > > - if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > - p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > - } > switch (p->port_information_sm_state) { > case PORT_INFORMATION_SM_INIT: > - if (r->begin) { > + if (r->begin > + || (!p->port_enabled && p->info_is != INFO_IS_DISABLED)) { > + /* Global transition. */ > p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > } > break; > @@ -1146,7 +1153,10 @@ port_information_sm(struct rstp_port *p) > p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED; > /* no break */ > case PORT_INFORMATION_SM_DISABLED: > - if (p->port_enabled) { > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else if (p->port_enabled) { > p->port_information_sm_state = PORT_INFORMATION_SM_AGED_EXEC; > } else if (p->rcvd_msg) { > p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > @@ -1159,7 +1169,10 @@ port_information_sm(struct rstp_port *p) > p->port_information_sm_state = PORT_INFORMATION_SM_AGED; > /* no break */ > case PORT_INFORMATION_SM_AGED: > - if (p->selected && p->updt_info) { > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else if (p->selected && p->updt_info) { > p->port_information_sm_state = PORT_INFORMATION_SM_UPDATE_EXEC; > } > break; > @@ -1183,13 +1196,21 @@ port_information_sm(struct rstp_port *p) > p->port_information_sm_state = PORT_INFORMATION_SM_UPDATE; > /* no break */ > case PORT_INFORMATION_SM_UPDATE: > - p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else { > + p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + } > break; > case PORT_INFORMATION_SM_CURRENT_EXEC: > p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT; > /* no break */ > case PORT_INFORMATION_SM_CURRENT: > - if (p->rcvd_msg && !p->updt_info) { > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else if (p->rcvd_msg && !p->updt_info) { > p->port_information_sm_state = PORT_INFORMATION_SM_RECEIVE_EXEC; > } else if (p->selected && p->updt_info) { > p->port_information_sm_state = PORT_INFORMATION_SM_UPDATE_EXEC; > @@ -1204,29 +1225,34 @@ port_information_sm(struct rstp_port *p) > p->port_information_sm_state = PORT_INFORMATION_SM_RECEIVE; > /* no break */ > case PORT_INFORMATION_SM_RECEIVE: > - switch (p->rcvd_info) { > - case SUPERIOR_DESIGNATED_INFO: > - p->port_information_sm_state = > - PORT_INFORMATION_SM_SUPERIOR_DESIGNATED_EXEC; > - break; > - case REPEATED_DESIGNATED_INFO: > - p->port_information_sm_state = > - PORT_INFORMATION_SM_REPEATED_DESIGNATED_EXEC; > - break; > - case INFERIOR_DESIGNATED_INFO: > - p->port_information_sm_state = > - PORT_INFORMATION_SM_INFERIOR_DESIGNATED_EXEC; > - break; > - case INFERIOR_ROOT_ALTERNATE_INFO: > - p->port_information_sm_state = > - PORT_INFORMATION_SM_NOT_DESIGNATED_EXEC; > - break; > - case OTHER_INFO: > - p->port_information_sm_state = PORT_INFORMATION_SM_OTHER_EXEC; > - break; > - default: > - OVS_NOT_REACHED(); > - /* no break */ > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else { > + switch (p->rcvd_info) { > + case SUPERIOR_DESIGNATED_INFO: > + p->port_information_sm_state = > + PORT_INFORMATION_SM_SUPERIOR_DESIGNATED_EXEC; > + break; > + case REPEATED_DESIGNATED_INFO: > + p->port_information_sm_state = > + PORT_INFORMATION_SM_REPEATED_DESIGNATED_EXEC; > + break; > + case INFERIOR_DESIGNATED_INFO: > + p->port_information_sm_state = > + PORT_INFORMATION_SM_INFERIOR_DESIGNATED_EXEC; > + break; > + case INFERIOR_ROOT_ALTERNATE_INFO: > + p->port_information_sm_state = > + PORT_INFORMATION_SM_NOT_DESIGNATED_EXEC; > + break; > + case OTHER_INFO: > + p->port_information_sm_state = > PORT_INFORMATION_SM_OTHER_EXEC; > + break; > + default: > + OVS_NOT_REACHED(); > + /* no break */ > + } > } > break; > case PORT_INFORMATION_SM_OTHER_EXEC: > @@ -1234,7 +1260,12 @@ port_information_sm(struct rstp_port *p) > p->port_information_sm_state = PORT_INFORMATION_SM_OTHER; > /* no break */ > case PORT_INFORMATION_SM_OTHER: > - p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else { > + p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + } > break; > case PORT_INFORMATION_SM_NOT_DESIGNATED_EXEC: > record_agreement(p); > @@ -1243,7 +1274,12 @@ port_information_sm(struct rstp_port *p) > p->port_information_sm_state = PORT_INFORMATION_SM_NOT_DESIGNATED; > /* no break */ > case PORT_INFORMATION_SM_NOT_DESIGNATED: > - p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else { > + p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + } > break; > case PORT_INFORMATION_SM_INFERIOR_DESIGNATED_EXEC: > record_dispute(p); > @@ -1251,7 +1287,12 @@ port_information_sm(struct rstp_port *p) > p->port_information_sm_state = > PORT_INFORMATION_SM_INFERIOR_DESIGNATED; > /* no break */ > case PORT_INFORMATION_SM_INFERIOR_DESIGNATED: > - p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else { > + p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + } > break; > case PORT_INFORMATION_SM_REPEATED_DESIGNATED_EXEC: > record_proposal(p); > @@ -1261,7 +1302,12 @@ port_information_sm(struct rstp_port *p) > p->port_information_sm_state = > PORT_INFORMATION_SM_REPEATED_DESIGNATED; > /* no break */ > case PORT_INFORMATION_SM_REPEATED_DESIGNATED: > - p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else { > + p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + } > break; > case PORT_INFORMATION_SM_SUPERIOR_DESIGNATED_EXEC: > p->agreed = p->proposing = false; > @@ -1279,7 +1325,12 @@ port_information_sm(struct rstp_port *p) > p->port_information_sm_state = > PORT_INFORMATION_SM_SUPERIOR_DESIGNATED; > /* no break */ > case PORT_INFORMATION_SM_SUPERIOR_DESIGNATED: > - p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + if (!p->port_enabled && p->info_is != INFO_IS_DISABLED) { > + /* Global transition. */ > + p->port_information_sm_state = PORT_INFORMATION_SM_DISABLED_EXEC; > + } else { > + p->port_information_sm_state = PORT_INFORMATION_SM_CURRENT_EXEC; > + } > break; > default: > OVS_NOT_REACHED(); > @@ -1465,7 +1516,7 @@ port_role_transition_sm(struct rstp_port *p) > /* no break */ > case PORT_ROLE_TRANSITION_SM_DISABLE_PORT: > if (check_selected_role_change(p, ROLE_DISABLED)) { > - break; > + /* Global transition. */ > } else if (p->selected && !p->updt_info && !p->learning > && !p->forwarding) { > p->port_role_transition_sm_state = > @@ -1482,7 +1533,7 @@ port_role_transition_sm(struct rstp_port *p) > /* no break */ > case PORT_ROLE_TRANSITION_SM_DISABLED_PORT: > if (check_selected_role_change(p, ROLE_DISABLED)) { > - break; > + /* Global transition. */ > } else if (p->selected && !p->updt_info > && (p->fd_while != p->designated_times.max_age || p->sync > || p->re_root || !p->synced)) { > @@ -1497,7 +1548,7 @@ port_role_transition_sm(struct rstp_port *p) > /* no break */ > case PORT_ROLE_TRANSITION_SM_ROOT_PORT: > if (check_selected_role_change(p, ROLE_ROOT)) { > - break; > + /* Global transition. */ > } else if (p->selected && !p->updt_info) { > if (p->rr_while != p->designated_times.forward_delay) { > p->port_role_transition_sm_state = > @@ -1536,38 +1587,62 @@ port_role_transition_sm(struct rstp_port *p) > } > break; > case PORT_ROLE_TRANSITION_SM_REROOT_EXEC: > - set_re_root_tree(p); > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_ROOT)) { > + /* Global transition. */ > + } else { > + set_re_root_tree(p); > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_ROOT_AGREED_EXEC: > - p->proposed = p->sync = false; > - p->agree = p->new_info = true; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_ROOT)) { > + /* Global transition. */ > + } else { > + p->proposed = p->sync = false; > + p->agree = p->new_info = true; > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_ROOT_PROPOSED_EXEC: > set_sync_tree(p); > p->proposed = false; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_ROOT)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_ROOT_FORWARD_EXEC: > p->fd_while = 0; > p->forward = true; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_ROOT)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_ROOT_LEARN_EXEC: > p->fd_while = forward_delay(p); > p->learn = true; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_ROOT)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_REROOTED_EXEC: > p->re_root = false; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_ROOT)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_ROOT_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC: > p->role = ROLE_DESIGNATED; > @@ -1576,7 +1651,7 @@ port_role_transition_sm(struct rstp_port *p) > /* no break */ > case PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT: > if (check_selected_role_change(p, ROLE_DESIGNATED)) { > - break; > + /* Global transition. */ > } else if (p->selected && !p->updt_info) { > if (((p->sync && !p->synced) > || (p->re_root && p->rr_while != 0) || p->disputed) > @@ -1611,41 +1686,65 @@ port_role_transition_sm(struct rstp_port *p) > break; > case PORT_ROLE_TRANSITION_SM_DESIGNATED_RETIRED_EXEC: > p->re_root = false; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_DESIGNATED)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_DESIGNATED_SYNCED_EXEC: > p->rr_while = 0; > p->synced = true; > p->sync = false; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_DESIGNATED)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_DESIGNATED_PROPOSE_EXEC: > p->proposing = true; > p->edge_delay_while = edge_delay(p); > p->new_info = true; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_DESIGNATED)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_DESIGNATED_FORWARD_EXEC: > p->forward = true; > p->fd_while = 0; > p->agreed = p->send_rstp; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_DESIGNATED)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_DESIGNATED_LEARN_EXEC: > p->learn = true; > p->fd_while = forward_delay(p); > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_DESIGNATED)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_DESIGNATED_DISCARD_EXEC: > p->learn = p->forward = p->disputed = false; > p->fd_while = forward_delay(p); > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_DESIGNATED)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_DESIGNATED_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_ALTERNATE_PORT_EXEC: > p->fd_while = p->designated_times.forward_delay; > @@ -1657,7 +1756,7 @@ port_role_transition_sm(struct rstp_port *p) > /* no break */ > case PORT_ROLE_TRANSITION_SM_ALTERNATE_PORT: > if (check_selected_role_change(p, ROLE_ALTERNATE)) { > - break; > + /* Global transition. */ > } else if (p->selected && !p->updt_info) { > if (p->rb_while != 2 * p->designated_times.hello_time > && p->role == ROLE_BACKUP) { > @@ -1681,14 +1780,22 @@ port_role_transition_sm(struct rstp_port *p) > p->proposed = false; > p->agree = true; > p->new_info = true; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_ALTERNATE_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_ALTERNATE)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_ALTERNATE_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_ALTERNATE_PROPOSED_EXEC: > set_sync_tree(p); > p->proposed = false; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_ALTERNATE_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_ALTERNATE)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_ALTERNATE_PORT_EXEC; > + } > break; > case PORT_ROLE_TRANSITION_SM_BLOCK_PORT_EXEC: > p->role = p->selected_role; > @@ -1697,7 +1804,7 @@ port_role_transition_sm(struct rstp_port *p) > /* no break */ > case PORT_ROLE_TRANSITION_SM_BLOCK_PORT: > if (check_selected_role_change(p, ROLE_ALTERNATE)) { > - break; > + /* Global transition. */ > } else if (p->selected && !p->updt_info && !p->learning && > !p->forwarding) { > p->port_role_transition_sm_state = > @@ -1706,8 +1813,12 @@ port_role_transition_sm(struct rstp_port *p) > break; > case PORT_ROLE_TRANSITION_SM_BACKUP_PORT_EXEC: > p->rb_while = 2 * p->designated_times.hello_time; > - p->port_role_transition_sm_state = > - PORT_ROLE_TRANSITION_SM_ALTERNATE_PORT_EXEC; > + if (check_selected_role_change(p, ROLE_ALTERNATE)) { > + /* Global transition. */ > + } else { > + p->port_role_transition_sm_state = > + PORT_ROLE_TRANSITION_SM_ALTERNATE_PORT_EXEC; > + } > break; > default: > OVS_NOT_REACHED(); > -- > 1.8.1.2 > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev