stp_process.c
来自「stp代码」· C语言 代码 · 共 1,383 行 · 第 1/3 页
C
1,383 行
}
}
/*
* Set port state to STP_FORWARDING (8.6.13)
*/
static void
make_blocking(spantree_t *stp, stp_port_t *port)
{
if ((port->state == STP_DISABLED) ||
(port->state == STP_BLOCKING)) { /* (8.6.13.3) */
return;
}
if (port->state == STP_FORWARDING || port->state == STP_LEARNING) {
if (port->change_detection_enabled == True) { /* (8.5.5.10) */
topology_change_detection(stp); /* (8.6.13.3 a) */
} /* (8.6.14.2.3) */
}
set_port_state(stp, port, STP_BLOCKING); /* (8.6.13.3 b) */
stop_forward_delay_timer(stp, port); /* (8.6.13.3 c) */
return;
}
/*
* Set port to some spanning tree state
*/
static void
set_port_state(spantree_t *stp, stp_port_t *port, stp_portstate_t state)
{
port->state = state;
/* Set stp state in the hardware */
stp_port_state_set(stp, port, state);
}
/*
* Record that a topology change has been detected so we can notify
* the root that things have changed (8.6.14)
*/
static void
topology_change_detection(spantree_t *stp)
{
if (root_bridge(stp)) { /* (8.6.14.3 a) */
stp->topology_change = True; /* (8.6.14.3 a1)*/
start_tc_timer(stp); /* (8.6.14.3 a2)*/
} else if (stp->topology_change_detected == False) { /* (8.6.14.3 b) */
transmit_tcn(stp); /* (8.6.14.3 b1)*/
start_tcn_timer(stp); /* (8.6.14.3 b2)*/
}
stp->topology_change_detected = True; /* (8.6.14.3 c) */
}
/*
* Acknowledge that a topology change has been answered (8.6.15).
*/
static void
topology_change_acknowledged(spantree_t *stp)
{
stp->topology_change_detected = False; /* (8.6.15.3 a) */
stop_tcn_timer(stp); /* (8.6.15.3 b) */
}
/*
* Reply to a topology change (8.6.16).
*/
static void
acknowledge_topology_change(spantree_t *stp, stp_port_t *port)
{
port->tc_acknowledge = True; /* (8.6.16.3 a) */
transmit_config(stp, port); /* (8.6.16.3 b) */
}
/*
* Operation of the Protocol, process IEEE config message (8.7.1)
*/
void
received_config_bpdu(spantree_t *stp, stp_port_t *port, Config_bpdu *config)
{
Boolean root;
root = root_bridge(stp);
if (port->state != STP_DISABLED) {
if (supersedes_port_info(stp, port, config)) { /* (8.7.1.1) */
record_config_information(stp, port, config); /* (8.7.1.1 a) */
configuration_update(stp); /* (8.7.1.1 b) */
port_state_selection(stp); /* (8.7.1.1 c) */
if ((!root_bridge(stp)) && root) { /* (8.7.1.1 d) */
stop_hello_timer(stp);
if (stp->topology_change_detected) { /* (8.7.1.1 e) */
stop_tc_timer(stp);
transmit_tcn(stp); /* (8.6.6.1) */
start_tcn_timer(stp);
}
}
if (port == stp->root_port) {
record_config_timeout_values(stp, config); /* (8.7.1.1 e) */
config_bpdu_generation(stp); /* (8.6.4.2 a) */
if (config->tc_acknowledgment) { /* (8.7.1.1 g) */
topology_change_acknowledged(stp); /* (8.6.15.2) */
}
}
} else if (is_designated_port(stp, port)) { /* (8.7.1.2) */
reply(stp, port); /* (8.7.1.2) */
}
}
}
/*
* Handle Topology Change Notification (8.7.2)
*/
void
received_tcn_bpdu(spantree_t *stp, stp_port_t *port, Tcn_bpdu *tcn)
{
if (port->state != STP_DISABLED) {
if (is_designated_port(stp, port)) {
topology_change_detection(stp); /* (8.7.2 a) */
acknowledge_topology_change(stp, port); /* (8.7.2 b) */
}
}
}
/*
* The hello timer expired, generation another hello (8.7.3).
*/
static void
hello_timer_expiry(spantree_t *stp)
{
config_bpdu_generation(stp);
start_hello_timer(stp);
}
/*
* The message age timer expired (8.7.4)
*/
static void
message_age_timer_expiry(spantree_t *stp, stp_port_t *port)
{
Boolean root;
root = root_bridge(stp);
become_designated_port(stp, port); /* (8.7.4 a) */
configuration_update(stp); /* (8.7.4 b) */
port_state_selection(stp); /* (8.7.4 c) */
if ((root_bridge(stp)) && (!root)) { /* (8.7.4 d) */
stp->max_age = stp->bridge_max_age; /* (8.7.4 d1) */
stp->hello_time = stp->bridge_hello_time;
stp->forward_delay = stp->bridge_forward_delay;
topology_change_detection(stp); /* (8.7.4 d2) */
stop_tcn_timer(stp); /* (8.7.4 d3) */
config_bpdu_generation(stp); /* (8.7.4 d4) */
start_hello_timer(stp);
}
}
/*
* The forward delay timer expired (8.7.5).
*/
static void
forward_delay_timer_expiry(spantree_t *stp, stp_port_t *port)
{
if (port->state == STP_LISTENING) { /* (8.7.5 a) */
set_port_state(stp, port, STP_LEARNING); /* (8.7.5 a1) */
start_forward_delay_timer(stp, port); /* (8.7.5 a2) */
} else if (port->state == STP_LEARNING) { /* (8.7.5 b) */
set_port_state(stp, port, STP_FORWARDING); /* (8.7.5 b1) */
if (designated_for_some_port(stp)) { /* (8.7.5 b2) */
if (port->change_detection_enabled == True) {
topology_change_detection(stp); /* (8.6.14.2.2) */
}
}
}
}
/*
* Is this designated bridge for any port ?
*/
static Boolean
designated_for_some_port(spantree_t *stp)
{
stp_port_t *port;
FOR_ALL_PORTS_IN_STP(stp, port) {
if (stp_cmpid(port->designated_bridge, stp->bridge_id, ID_BYTES)) {
return(True);
}
}
return(False);
}
/*
* Topology change notification timer expired (8.7.6)
*/
static void
tcn_timer_expiry(spantree_t *stp)
{
transmit_tcn(stp); /* (8.7.6 a) */
start_tcn_timer(stp); /* (8.7.6 b) */
}
/*
* Topology change timer expired (8.7.7)
*/
static void
tc_timer_expiry(spantree_t *stp)
{
stp->topology_change_detected = False; /* (8.7.7 a) */
stp->topology_change = False; /* (8.7.7 b) */
}
/*
* Hold timer expired (8.7.8)
*/
static void
hold_timer_expiry(spantree_t *stp, stp_port_t *port)
{
if (port->config_pending) {
transmit_config(stp, port); /* (8.6.1.2) */
}
}
/*
* Management of the Bridge Protocol Entity (8.8)
*/
void
activate_spantree(spantree_t *stp)
{
#if 0
stp_port_t *port;
#endif
sal_memcpy(stp->designated_root, stp->bridge_id, ID_BYTES);
stp->root_path_cost = 0;
stp->root_port = NULL;
stp->max_age = stp->bridge_max_age;
stp->hello_time = stp->bridge_hello_time;
stp->forward_delay = stp->bridge_forward_delay;
stp->topology_change_detected = False;
stp->topology_change = False;
stop_tcn_timer(stp);
stop_tc_timer(stp);
#if 0
FOR_ALL_PORTS_IN_STP(stp, port) { /* (8.8.1 d) */
/* We do this on link up and not at this point */
initialize_port(stp, port);
}
#endif
port_state_selection(stp); /* (8.8.1 e) */
config_bpdu_generation(stp); /* (8.8.1 f) */
start_hello_timer(stp);
stp->running = True;
}
/*
* deactivate a STP instance
*/
void
stp_deactivate_spantree(spantree_t *stp)
{
stp_port_t *port;
/* canonical STP deactivation */
stop_hello_timer(stp);
stop_tcn_timer(stp);
stop_tc_timer(stp);
stp->running = 0;
/* cancel all our timers active for all our ports */
FOR_ALL_PORTS_IN_STP(stp, port) {
stop_message_age_timer(stp, port);
stop_forward_delay_timer(stp, port);
stop_hold_timer(stp, port);
set_port_state(stp, port, STP_FORWARDING);
}
}
/*
* initialize a port in a STP instance for the API (8.8.1)
*/
static void
initialize_port(spantree_t *stp, stp_port_t *port)
{
become_designated_port(stp, port); /* (8.8.1 d1) */
set_port_state(stp, port, STP_BLOCKING); /* (8.8.1 d2) */
port->tc_acknowledge = False; /* (8.8.1 d3) */
port->config_pending = False; /* (8.8.1 d4) */
port->change_detection_enabled = True; /* (8.8.1 d8) */
stop_message_age_timer(stp, port); /* (8.8.1 d5) */
stop_forward_delay_timer(stp, port); /* (8.8.1 d6) */
stop_hold_timer(stp, port); /* (8.8.1 d7) */
}
/*
* enable a port due to a management command (8.8.2)
*/
void
enable_port(spantree_t *stp, stp_port_t *port)
{
initialize_port(stp, port);
port_state_selection(stp); /* (8.8.2 g) */
}
/*
* disable a port due to a management command (8.8.3)
*/
void
disable_port(spantree_t *stp, stp_port_t *port)
{
Boolean root;
root = root_bridge(stp);
become_designated_port(stp, port); /* (8.8.3 a) */
set_port_state(stp, port, STP_DISABLED); /* (8.8.3 b) */
port->tc_acknowledge = False; /* (8.8.3 c) */
port->config_pending = False; /* (8.8.3 d) */
stop_message_age_timer(stp, port); /* (8.8.3 e) */
stop_forward_delay_timer(stp, port); /* (8.8.3 f) */
configuration_update(stp); /* (8.8.3 g) */
port_state_selection(stp); /* (8.8.3 h) */
if ((root_bridge(stp)) && (!root)) { /* (8.8.3 i) */
stp->max_age = stp->bridge_max_age; /* (8.8.3 i1) */
stp->hello_time = stp->bridge_hello_time;
stp->forward_delay = stp->bridge_forward_delay;
topology_change_detection(stp); /* (8.8.3 i2) */
stop_tcn_timer(stp); /* (8.8.3 i3) */
config_bpdu_generation(stp); /* (8.8.3 i4) */
start_hello_timer(stp);
}
}
/*
* change a bridge ID (priority and mac address) (8.8.4)
*/
void
set_bridge_id_api(spantree_t *stp, uint8 *new_bridge_id)
{
stp_port_t *port;
Boolean root;
root = root_bridge(stp);
FOR_ALL_PORTS_IN_STP(stp, port) { /* (8.8.4 b) */
if (is_designated_port(stp, port)) {
sal_memcpy(port->designated_bridge, new_bridge_id, ID_BYTES);
}
}
sal_memcpy(stp->bridge_id, new_bridge_id, ID_BYTES);
configuration_update(stp); /* (8.8.4 d) */
port_state_selection(stp); /* (8.8.4 e) */
if ((root_bridge(stp)) && (!root)) { /* (8.8.4 f) */
stp->max_age = stp->bridge_max_age; /* (8.8.4 f1) */
stp->hello_time = stp->bridge_hello_time;
stp->forward_delay = stp->bridge_forward_delay;
topology_change_detection(stp); /* (8.8.4 f2) */
stop_tcn_timer(stp); /* (8.8.4 f3) */
config_bpdu_generation(stp); /* (8.8.4 f4) */
start_hello_timer(stp);
}
}
/*
* Adjust spanning tree topology after changing priority of a port (8.8.5)
*/
void
set_port_priority(spantree_t *stp, stp_port_t *port, uint16 new_port_id)
{
if (is_designated_port(stp, port)) { /* (8.8.5 b) */
port->designated_port = new_port_id;
}
port->port_id = new_port_id; /* (8.8.5 c) */
if ((stp_cmpid(stp->bridge_id, port->designated_bridge, ID_BYTES) == 0) &&
(port->port_id < port->designated_port)) {
become_designated_port(stp, port); /* (8.8.5 d1) */
port_state_selection(stp); /* (8.8.5 d2) */
}
}
/*
* Set path cost for a port (8.8.6)
*/
void
set_path_cost(spantree_t *stp, stp_port_t *port, uint32 path_cost)
{
port->path_cost = path_cost; /* (8.8.6 a) */
configuration_update(stp); /* (8.8.6 b) */
port_state_selection(stp); /* (8.8.6 c) */
}
/*
* Enable change detection (8.8.7)
*/
void
enable_change_detection(spantree_t *stp, stp_port_t *port)
{
port->change_detection_enabled = True;
}
/*
* Enable change detection (8.8.8)
*/
void
disable_change_detection(spantree_t *stp, stp_port_t *port)
{
port->change_detection_enabled = False;
}
/*
* pseudo-implementation-specific timer running support
*/
static void
stp_tick(spantree_t *stp)
{
stp_port_t *port;
if (hello_timer_expired(stp)) {
hello_timer_expiry(stp);
}
if (tcn_timer_expired(stp)) {
tcn_timer_expiry(stp);
}
if (tc_timer_expired(stp)) {
tc_timer_expiry(stp);
}
FOR_ALL_PORTS_IN_STP(stp, port) {
if (message_age_timer_expired(stp, port)) {
message_age_timer_expiry(stp, port);
}
}
FOR_ALL_PORTS_IN_STP(stp, port) {
if (forward_delay_timer_expired(stp, port)) {
forward_delay_timer_expiry(stp, port);
}
if (hold_timer_expired(stp, port)) {
hold_timer_expiry(stp, port);
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?