~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/bridge/br_stp_timer.c

Version: ~ [ linux-5.6-rc3 ] ~ [ linux-5.5.6 ] ~ [ linux-5.4.22 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.106 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.171 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.214 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.214 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp