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

Linux Cross Reference
Linux/net/bridge/br_stp_if.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *      Spanning tree protocol; interface code
  3  *      Linux ethernet bridge
  4  *
  5  *      Authors:
  6  *      Lennert Buytenhek               <buytenh@gnu.org>
  7  *
  8  *      $Id: br_stp_if.c,v 1.3 2000/05/05 02:17:17 davem Exp $
  9  *
 10  *      This program is free software; you can redistribute it and/or
 11  *      modify it under the terms of the GNU General Public License
 12  *      as published by the Free Software Foundation; either version
 13  *      2 of the License, or (at your option) any later version.
 14  */
 15 
 16 #include <linux/kernel.h>
 17 #include <linux/if_bridge.h>
 18 #include <linux/smp_lock.h>
 19 #include <asm/uaccess.h>
 20 #include "br_private.h"
 21 #include "br_private_stp.h"
 22 
 23 __u16 br_make_port_id(struct net_bridge_port *p)
 24 {
 25         return (p->priority << 8) | p->port_no;
 26 }
 27 
 28 /* called under bridge lock */
 29 void br_init_port(struct net_bridge_port *p)
 30 {
 31         p->port_id = br_make_port_id(p);
 32         br_become_designated_port(p);
 33         p->state = BR_STATE_BLOCKING;
 34         p->topology_change_ack = 0;
 35         p->config_pending = 0;
 36         br_timer_clear(&p->message_age_timer);
 37         br_timer_clear(&p->forward_delay_timer);
 38         br_timer_clear(&p->hold_timer);
 39 }
 40 
 41 /* called under bridge lock */
 42 void br_stp_enable_bridge(struct net_bridge *br)
 43 {
 44         struct net_bridge_port *p;
 45         struct timer_list *timer = &br->tick;
 46 
 47         init_timer(timer);
 48         timer->data = (unsigned long) br;
 49         timer->function = br_tick;
 50         timer->expires = jiffies + 1;
 51         add_timer(timer);
 52 
 53         br_timer_set(&br->hello_timer, jiffies);
 54         br_config_bpdu_generation(br);
 55 
 56         p = br->port_list;
 57         while (p != NULL) {
 58                 if (p->dev->flags & IFF_UP)
 59                         br_stp_enable_port(p);
 60 
 61                 p = p->next;
 62         }
 63 
 64         br_timer_set(&br->gc_timer, jiffies);
 65 }
 66 
 67 /* called under bridge lock */
 68 void br_stp_disable_bridge(struct net_bridge *br)
 69 {
 70         struct net_bridge_port *p;
 71 
 72         br->topology_change = 0;
 73         br->topology_change_detected = 0;
 74         br_timer_clear(&br->hello_timer);
 75         br_timer_clear(&br->topology_change_timer);
 76         br_timer_clear(&br->tcn_timer);
 77         br_timer_clear(&br->gc_timer);
 78         br_fdb_cleanup(br);
 79 
 80         p = br->port_list;
 81         while (p != NULL) {
 82                 if (p->state != BR_STATE_DISABLED)
 83                         br_stp_disable_port(p);
 84 
 85                 p = p->next;
 86         }
 87 
 88         del_timer(&br->tick);
 89 }
 90 
 91 /* called under bridge lock */
 92 void br_stp_enable_port(struct net_bridge_port *p)
 93 {
 94         br_init_port(p);
 95         br_port_state_selection(p->br);
 96 }
 97 
 98 /* called under bridge lock */
 99 void br_stp_disable_port(struct net_bridge_port *p)
100 {
101         struct net_bridge *br;
102         int wasroot;
103 
104         br = p->br;
105         printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
106                br->dev.name, p->port_no, p->dev->name, "disabled");
107 
108         wasroot = br_is_root_bridge(br);
109         br_become_designated_port(p);
110         p->state = BR_STATE_DISABLED;
111         p->topology_change_ack = 0;
112         p->config_pending = 0;
113         br_timer_clear(&p->message_age_timer);
114         br_timer_clear(&p->forward_delay_timer);
115         br_timer_clear(&p->hold_timer);
116         br_configuration_update(br);
117         br_port_state_selection(br);
118 
119         if (br_is_root_bridge(br) && !wasroot)
120                 br_become_root_bridge(br);
121 }
122 
123 /* called under bridge lock */
124 static void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr)
125 {
126         unsigned char oldaddr[6];
127         struct net_bridge_port *p;
128         int wasroot;
129 
130         wasroot = br_is_root_bridge(br);
131 
132         memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
133         memcpy(br->bridge_id.addr, addr, ETH_ALEN);
134         memcpy(br->dev.dev_addr, addr, ETH_ALEN);
135 
136         p = br->port_list;
137         while (p != NULL) {
138                 if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN))
139                         memcpy(p->designated_bridge.addr, addr, ETH_ALEN);
140 
141                 if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN))
142                         memcpy(p->designated_root.addr, addr, ETH_ALEN);
143 
144                 p = p->next;
145         }
146 
147         br_configuration_update(br);
148         br_port_state_selection(br);
149         if (br_is_root_bridge(br) && !wasroot)
150                 br_become_root_bridge(br);
151 }
152 
153 static unsigned char br_mac_zero[6] = {0,0,0,0,0,0};
154 
155 /* called under bridge lock */
156 void br_stp_recalculate_bridge_id(struct net_bridge *br)
157 {
158         unsigned char *addr;
159         struct net_bridge_port *p;
160 
161         addr = br_mac_zero;
162 
163         p = br->port_list;
164         while (p != NULL) {
165                 if (addr == br_mac_zero ||
166                     memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
167                         addr = p->dev->dev_addr;
168 
169                 p = p->next;
170         }
171 
172         if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))
173                 br_stp_change_bridge_id(br, addr);
174 }
175 
176 /* called under bridge lock */
177 void br_stp_set_bridge_priority(struct net_bridge *br, int newprio)
178 {
179         struct net_bridge_port *p;
180         int wasroot;
181 
182         wasroot = br_is_root_bridge(br);
183 
184         p = br->port_list;
185         while (p != NULL) {
186                 if (p->state != BR_STATE_DISABLED &&
187                     br_is_designated_port(p)) {
188                         p->designated_bridge.prio[0] = (newprio >> 8) & 0xFF;
189                         p->designated_bridge.prio[1] = newprio & 0xFF;
190                 }
191 
192                 p = p->next;
193         }
194 
195         br->bridge_id.prio[0] = (newprio >> 8) & 0xFF;
196         br->bridge_id.prio[1] = newprio & 0xFF;
197         br_configuration_update(br);
198         br_port_state_selection(br);
199         if (br_is_root_bridge(br) && !wasroot)
200                 br_become_root_bridge(br);
201 }
202 
203 /* called under bridge lock */
204 void br_stp_set_port_priority(struct net_bridge_port *p, int newprio)
205 {
206         int new_port_id = ((newprio & 0xFF) << 8) | p->port_no;
207 
208         if (br_is_designated_port(p))
209                 p->designated_port = new_port_id;
210 
211         p->port_id = new_port_id;
212         if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) &&
213             p->port_id < p->designated_port) {
214                 br_become_designated_port(p);
215                 br_port_state_selection(p->br);
216         }
217 }
218 
219 /* called under bridge lock */
220 void br_stp_set_path_cost(struct net_bridge_port *p, int path_cost)
221 {
222         p->path_cost = path_cost;
223         br_configuration_update(p->br);
224         br_port_state_selection(p->br);
225 }
226 

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

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.