root/net/bridge/br_stp_timer.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. br_is_designated_for_some_port
  2. br_hello_timer_expired
  3. br_message_age_timer_expired
  4. br_forward_delay_timer_expired
  5. br_tcn_timer_expired
  6. br_topology_change_timer_expired
  7. br_hold_timer_expired
  8. br_stp_timer_init
  9. br_stp_port_timer_init
  10. br_timer_value

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *      Spanning tree protocol; timer-related code
   4  *      Linux ethernet bridge
   5  *
   6  *      Authors:
   7  *      Lennert Buytenhek               <buytenh@gnu.org>
   8  */
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/times.h>
  12 
  13 #include "br_private.h"
  14 #include "br_private_stp.h"
  15 
  16 /* called under bridge lock */
  17 static int br_is_designated_for_some_port(const struct net_bridge *br)
  18 {
  19         struct net_bridge_port *p;
  20 
  21         list_for_each_entry(p, &br->port_list, list) {
  22                 if (p->state != BR_STATE_DISABLED &&
  23                     !memcmp(&p->designated_bridge, &br->bridge_id, 8))
  24                         return 1;
  25         }
  26 
  27         return 0;
  28 }
  29 
  30 static void br_hello_timer_expired(struct timer_list *t)
  31 {
  32         struct net_bridge *br = from_timer(br, t, hello_timer);
  33 
  34         br_debug(br, "hello timer expired\n");
  35         spin_lock(&br->lock);
  36         if (br->dev->flags & IFF_UP) {
  37                 br_config_bpdu_generation(br);
  38 
  39                 if (br->stp_enabled == BR_KERNEL_STP)
  40                         mod_timer(&br->hello_timer,
  41                                   round_jiffies(jiffies + br->hello_time));
  42         }
  43         spin_unlock(&br->lock);
  44 }
  45 
  46 static void br_message_age_timer_expired(struct timer_list *t)
  47 {
  48         struct net_bridge_port *p = from_timer(p, t, message_age_timer);
  49         struct net_bridge *br = p->br;
  50         const bridge_id *id = &p->designated_bridge;
  51         int was_root;
  52 
  53         if (p->state == BR_STATE_DISABLED)
  54                 return;
  55 
  56         br_info(br, "port %u(%s) neighbor %.2x%.2x.%pM lost\n",
  57                 (unsigned int) p->port_no, p->dev->name,
  58                 id->prio[0], id->prio[1], &id->addr);
  59 
  60         /*
  61          * According to the spec, the message age timer cannot be
  62          * running when we are the root bridge. So..  this was_root
  63          * check is redundant. I'm leaving it in for now, though.
  64          */
  65         spin_lock(&br->lock);
  66         if (p->state == BR_STATE_DISABLED)
  67                 goto unlock;
  68         was_root = br_is_root_bridge(br);
  69 
  70         br_become_designated_port(p);
  71         br_configuration_update(br);
  72         br_port_state_selection(br);
  73         if (br_is_root_bridge(br) && !was_root)
  74                 br_become_root_bridge(br);
  75  unlock:
  76         spin_unlock(&br->lock);
  77 }
  78 
  79 static void br_forward_delay_timer_expired(struct timer_list *t)
  80 {
  81         struct net_bridge_port *p = from_timer(p, t, forward_delay_timer);
  82         struct net_bridge *br = p->br;
  83 
  84         br_debug(br, "port %u(%s) forward delay timer\n",
  85                  (unsigned int) p->port_no, p->dev->name);
  86         spin_lock(&br->lock);
  87         if (p->state == BR_STATE_LISTENING) {
  88                 br_set_state(p, BR_STATE_LEARNING);
  89                 mod_timer(&p->forward_delay_timer,
  90                           jiffies + br->forward_delay);
  91         } else if (p->state == BR_STATE_LEARNING) {
  92                 br_set_state(p, BR_STATE_FORWARDING);
  93                 if (br_is_designated_for_some_port(br))
  94                         br_topology_change_detection(br);
  95                 netif_carrier_on(br->dev);
  96         }
  97         rcu_read_lock();
  98         br_ifinfo_notify(RTM_NEWLINK, NULL, p);
  99         rcu_read_unlock();
 100         spin_unlock(&br->lock);
 101 }
 102 
 103 static void br_tcn_timer_expired(struct timer_list *t)
 104 {
 105         struct net_bridge *br = from_timer(br, t, tcn_timer);
 106 
 107         br_debug(br, "tcn timer expired\n");
 108         spin_lock(&br->lock);
 109         if (!br_is_root_bridge(br) && (br->dev->flags & IFF_UP)) {
 110                 br_transmit_tcn(br);
 111 
 112                 mod_timer(&br->tcn_timer, jiffies + br->bridge_hello_time);
 113         }
 114         spin_unlock(&br->lock);
 115 }
 116 
 117 static void br_topology_change_timer_expired(struct timer_list *t)
 118 {
 119         struct net_bridge *br = from_timer(br, t, topology_change_timer);
 120 
 121         br_debug(br, "topo change timer expired\n");
 122         spin_lock(&br->lock);
 123         br->topology_change_detected = 0;
 124         __br_set_topology_change(br, 0);
 125         spin_unlock(&br->lock);
 126 }
 127 
 128 static void br_hold_timer_expired(struct timer_list *t)
 129 {
 130         struct net_bridge_port *p = from_timer(p, t, hold_timer);
 131 
 132         br_debug(p->br, "port %u(%s) hold timer expired\n",
 133                  (unsigned int) p->port_no, p->dev->name);
 134 
 135         spin_lock(&p->br->lock);
 136         if (p->config_pending)
 137                 br_transmit_config(p);
 138         spin_unlock(&p->br->lock);
 139 }
 140 
 141 void br_stp_timer_init(struct net_bridge *br)
 142 {
 143         timer_setup(&br->hello_timer, br_hello_timer_expired, 0);
 144         timer_setup(&br->tcn_timer, br_tcn_timer_expired, 0);
 145         timer_setup(&br->topology_change_timer,
 146                     br_topology_change_timer_expired, 0);
 147 }
 148 
 149 void br_stp_port_timer_init(struct net_bridge_port *p)
 150 {
 151         timer_setup(&p->message_age_timer, br_message_age_timer_expired, 0);
 152         timer_setup(&p->forward_delay_timer, br_forward_delay_timer_expired, 0);
 153         timer_setup(&p->hold_timer, br_hold_timer_expired, 0);
 154 }
 155 
 156 /* Report ticks left (in USER_HZ) used for API */
 157 unsigned long br_timer_value(const struct timer_list *timer)
 158 {
 159         return timer_pending(timer)
 160                 ? jiffies_delta_to_clock_t(timer->expires - jiffies) : 0;
 161 }

/* [<][>][^][v][top][bottom][index][help] */