/* called under bridge lock */ void br_become_root_bridge(struct net_bridge *br) { br->max_age = br->bridge_max_age; br->hello_time = br->bridge_hello_time; br->forward_delay = br->bridge_forward_delay; br_topology_change_detection(br); br_timer_clear(&br->tcn_timer); br_config_bpdu_generation(br); br_timer_set(&br->hello_timer, jiffies); }
/* lock-safe */ void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu) { struct net_bridge *br; int was_root; if (p->state == BR_STATE_DISABLED) return; br = p->br; read_lock(&br->lock); was_root = br_is_root_bridge(br); if (br_supersedes_port_info(p, bpdu)) { br_record_config_information(p, bpdu); br_configuration_update(br); br_port_state_selection(br); if (!br_is_root_bridge(br) && was_root) { br_timer_clear(&br->hello_timer); if (br->topology_change_detected) { br_timer_clear(&br->topology_change_timer); br_transmit_tcn(br); br_timer_set(&br->tcn_timer, jiffies); } } if (p->port_no == br->root_port) { br_record_config_timeout_values(br, bpdu); br_config_bpdu_generation(br); if (bpdu->topology_change_ack) br_topology_change_acknowledged(br); } } else if (br_is_designated_port(p)) { br_reply(p); } read_unlock(&br->lock); }
/* called under bridge lock */ void br_stp_enable_bridge(struct net_bridge *br) { struct net_bridge_port *p; struct timer_list *timer = &br->tick; init_timer(timer); timer->data = (unsigned long) br; timer->function = br_tick; timer->expires = jiffies + 1; add_timer(timer); br_timer_set(&br->hello_timer, jiffies); br_config_bpdu_generation(br); p = br->port_list; while (p != NULL) { if (p->dev->flags & IFF_UP) br_stp_enable_port(p); p = p->next; } br_timer_set(&br->gc_timer, jiffies); }
/* called under bridge lock */ static void br_hello_timer_expired(struct net_bridge *br) { br_config_bpdu_generation(br); br_timer_set(&br->hello_timer, jiffies); }