~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to net/bridge/br_stp_timer.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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) 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) 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->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) 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_to_clock_t(timer->expires - jiffies) : 0;
 
174
}