Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Spanning tree protocol; timer-related code
0004  *  Linux ethernet bridge
0005  *
0006  *  Authors:
0007  *  Lennert Buytenhek       <buytenh@gnu.org>
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/times.h>
0012 
0013 #include "br_private.h"
0014 #include "br_private_stp.h"
0015 
0016 /* called under bridge lock */
0017 static int br_is_designated_for_some_port(const struct net_bridge *br)
0018 {
0019     struct net_bridge_port *p;
0020 
0021     list_for_each_entry(p, &br->port_list, list) {
0022         if (p->state != BR_STATE_DISABLED &&
0023             !memcmp(&p->designated_bridge, &br->bridge_id, 8))
0024             return 1;
0025     }
0026 
0027     return 0;
0028 }
0029 
0030 static void br_hello_timer_expired(struct timer_list *t)
0031 {
0032     struct net_bridge *br = from_timer(br, t, hello_timer);
0033 
0034     br_debug(br, "hello timer expired\n");
0035     spin_lock(&br->lock);
0036     if (br->dev->flags & IFF_UP) {
0037         br_config_bpdu_generation(br);
0038 
0039         if (br->stp_enabled == BR_KERNEL_STP)
0040             mod_timer(&br->hello_timer,
0041                   round_jiffies(jiffies + br->hello_time));
0042     }
0043     spin_unlock(&br->lock);
0044 }
0045 
0046 static void br_message_age_timer_expired(struct timer_list *t)
0047 {
0048     struct net_bridge_port *p = from_timer(p, t, message_age_timer);
0049     struct net_bridge *br = p->br;
0050     const bridge_id *id = &p->designated_bridge;
0051     int was_root;
0052 
0053     if (p->state == BR_STATE_DISABLED)
0054         return;
0055 
0056     br_info(br, "port %u(%s) neighbor %.2x%.2x.%pM lost\n",
0057         (unsigned int) p->port_no, p->dev->name,
0058         id->prio[0], id->prio[1], &id->addr);
0059 
0060     /*
0061      * According to the spec, the message age timer cannot be
0062      * running when we are the root bridge. So..  this was_root
0063      * check is redundant. I'm leaving it in for now, though.
0064      */
0065     spin_lock(&br->lock);
0066     if (p->state == BR_STATE_DISABLED)
0067         goto unlock;
0068     was_root = br_is_root_bridge(br);
0069 
0070     br_become_designated_port(p);
0071     br_configuration_update(br);
0072     br_port_state_selection(br);
0073     if (br_is_root_bridge(br) && !was_root)
0074         br_become_root_bridge(br);
0075  unlock:
0076     spin_unlock(&br->lock);
0077 }
0078 
0079 static void br_forward_delay_timer_expired(struct timer_list *t)
0080 {
0081     struct net_bridge_port *p = from_timer(p, t, forward_delay_timer);
0082     struct net_bridge *br = p->br;
0083 
0084     br_debug(br, "port %u(%s) forward delay timer\n",
0085          (unsigned int) p->port_no, p->dev->name);
0086     spin_lock(&br->lock);
0087     if (p->state == BR_STATE_LISTENING) {
0088         br_set_state(p, BR_STATE_LEARNING);
0089         mod_timer(&p->forward_delay_timer,
0090               jiffies + br->forward_delay);
0091     } else if (p->state == BR_STATE_LEARNING) {
0092         br_set_state(p, BR_STATE_FORWARDING);
0093         if (br_is_designated_for_some_port(br))
0094             br_topology_change_detection(br);
0095         netif_carrier_on(br->dev);
0096     }
0097     rcu_read_lock();
0098     br_ifinfo_notify(RTM_NEWLINK, NULL, p);
0099     rcu_read_unlock();
0100     spin_unlock(&br->lock);
0101 }
0102 
0103 static void br_tcn_timer_expired(struct timer_list *t)
0104 {
0105     struct net_bridge *br = from_timer(br, t, tcn_timer);
0106 
0107     br_debug(br, "tcn timer expired\n");
0108     spin_lock(&br->lock);
0109     if (!br_is_root_bridge(br) && (br->dev->flags & IFF_UP)) {
0110         br_transmit_tcn(br);
0111 
0112         mod_timer(&br->tcn_timer, jiffies + br->bridge_hello_time);
0113     }
0114     spin_unlock(&br->lock);
0115 }
0116 
0117 static void br_topology_change_timer_expired(struct timer_list *t)
0118 {
0119     struct net_bridge *br = from_timer(br, t, topology_change_timer);
0120 
0121     br_debug(br, "topo change timer expired\n");
0122     spin_lock(&br->lock);
0123     br->topology_change_detected = 0;
0124     __br_set_topology_change(br, 0);
0125     spin_unlock(&br->lock);
0126 }
0127 
0128 static void br_hold_timer_expired(struct timer_list *t)
0129 {
0130     struct net_bridge_port *p = from_timer(p, t, hold_timer);
0131 
0132     br_debug(p->br, "port %u(%s) hold timer expired\n",
0133          (unsigned int) p->port_no, p->dev->name);
0134 
0135     spin_lock(&p->br->lock);
0136     if (p->config_pending)
0137         br_transmit_config(p);
0138     spin_unlock(&p->br->lock);
0139 }
0140 
0141 void br_stp_timer_init(struct net_bridge *br)
0142 {
0143     timer_setup(&br->hello_timer, br_hello_timer_expired, 0);
0144     timer_setup(&br->tcn_timer, br_tcn_timer_expired, 0);
0145     timer_setup(&br->topology_change_timer,
0146             br_topology_change_timer_expired, 0);
0147 }
0148 
0149 void br_stp_port_timer_init(struct net_bridge_port *p)
0150 {
0151     timer_setup(&p->message_age_timer, br_message_age_timer_expired, 0);
0152     timer_setup(&p->forward_delay_timer, br_forward_delay_timer_expired, 0);
0153     timer_setup(&p->hold_timer, br_hold_timer_expired, 0);
0154 }
0155 
0156 /* Report ticks left (in USER_HZ) used for API */
0157 unsigned long br_timer_value(const struct timer_list *timer)
0158 {
0159     return timer_pending(timer)
0160         ? jiffies_delta_to_clock_t(timer->expires - jiffies) : 0;
0161 }