Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17-rc5 223 lines 5.6 kB view raw
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.4 2001/04/14 21:14:39 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/smp_lock.h> 18#include <linux/etherdevice.h> 19 20#include "br_private.h" 21#include "br_private_stp.h" 22 23 24/* Port id is composed of priority and port number. 25 * NB: least significant bits of priority are dropped to 26 * make room for more ports. 27 */ 28static inline port_id br_make_port_id(__u8 priority, __u16 port_no) 29{ 30 return ((u16)priority << BR_PORT_BITS) 31 | (port_no & ((1<<BR_PORT_BITS)-1)); 32} 33 34/* called under bridge lock */ 35void br_init_port(struct net_bridge_port *p) 36{ 37 p->port_id = br_make_port_id(p->priority, p->port_no); 38 br_become_designated_port(p); 39 p->state = BR_STATE_BLOCKING; 40 p->topology_change_ack = 0; 41 p->config_pending = 0; 42} 43 44/* called under bridge lock */ 45void br_stp_enable_bridge(struct net_bridge *br) 46{ 47 struct net_bridge_port *p; 48 49 spin_lock_bh(&br->lock); 50 mod_timer(&br->hello_timer, jiffies + br->hello_time); 51 mod_timer(&br->gc_timer, jiffies + HZ/10); 52 53 br_config_bpdu_generation(br); 54 55 list_for_each_entry(p, &br->port_list, list) { 56 if ((p->dev->flags & IFF_UP) && netif_carrier_ok(p->dev)) 57 br_stp_enable_port(p); 58 59 } 60 spin_unlock_bh(&br->lock); 61} 62 63/* NO locks held */ 64void br_stp_disable_bridge(struct net_bridge *br) 65{ 66 struct net_bridge_port *p; 67 68 spin_lock_bh(&br->lock); 69 list_for_each_entry(p, &br->port_list, list) { 70 if (p->state != BR_STATE_DISABLED) 71 br_stp_disable_port(p); 72 73 } 74 75 br->topology_change = 0; 76 br->topology_change_detected = 0; 77 spin_unlock_bh(&br->lock); 78 79 del_timer_sync(&br->hello_timer); 80 del_timer_sync(&br->topology_change_timer); 81 del_timer_sync(&br->tcn_timer); 82 del_timer_sync(&br->gc_timer); 83} 84 85/* called under bridge lock */ 86void br_stp_enable_port(struct net_bridge_port *p) 87{ 88 br_init_port(p); 89 br_port_state_selection(p->br); 90} 91 92/* called under bridge lock */ 93void br_stp_disable_port(struct net_bridge_port *p) 94{ 95 struct net_bridge *br; 96 int wasroot; 97 98 br = p->br; 99 printk(KERN_INFO "%s: port %i(%s) entering %s state\n", 100 br->dev->name, p->port_no, p->dev->name, "disabled"); 101 102 wasroot = br_is_root_bridge(br); 103 br_become_designated_port(p); 104 p->state = BR_STATE_DISABLED; 105 p->topology_change_ack = 0; 106 p->config_pending = 0; 107 108 del_timer(&p->message_age_timer); 109 del_timer(&p->forward_delay_timer); 110 del_timer(&p->hold_timer); 111 112 br_configuration_update(br); 113 114 br_port_state_selection(br); 115 116 if (br_is_root_bridge(br) && !wasroot) 117 br_become_root_bridge(br); 118} 119 120/* called under bridge lock */ 121void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) 122{ 123 unsigned char oldaddr[6]; 124 struct net_bridge_port *p; 125 int wasroot; 126 127 wasroot = br_is_root_bridge(br); 128 129 memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN); 130 memcpy(br->bridge_id.addr, addr, ETH_ALEN); 131 memcpy(br->dev->dev_addr, addr, ETH_ALEN); 132 133 list_for_each_entry(p, &br->port_list, list) { 134 if (!compare_ether_addr(p->designated_bridge.addr, oldaddr)) 135 memcpy(p->designated_bridge.addr, addr, ETH_ALEN); 136 137 if (!compare_ether_addr(p->designated_root.addr, oldaddr)) 138 memcpy(p->designated_root.addr, addr, ETH_ALEN); 139 140 } 141 142 br_configuration_update(br); 143 br_port_state_selection(br); 144 if (br_is_root_bridge(br) && !wasroot) 145 br_become_root_bridge(br); 146} 147 148static const unsigned char br_mac_zero[6]; 149 150/* called under bridge lock */ 151void br_stp_recalculate_bridge_id(struct net_bridge *br) 152{ 153 const unsigned char *addr = br_mac_zero; 154 struct net_bridge_port *p; 155 156 list_for_each_entry(p, &br->port_list, list) { 157 if (addr == br_mac_zero || 158 memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0) 159 addr = p->dev->dev_addr; 160 161 } 162 163 if (compare_ether_addr(br->bridge_id.addr, addr)) 164 br_stp_change_bridge_id(br, addr); 165} 166 167/* called under bridge lock */ 168void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio) 169{ 170 struct net_bridge_port *p; 171 int wasroot; 172 173 wasroot = br_is_root_bridge(br); 174 175 list_for_each_entry(p, &br->port_list, list) { 176 if (p->state != BR_STATE_DISABLED && 177 br_is_designated_port(p)) { 178 p->designated_bridge.prio[0] = (newprio >> 8) & 0xFF; 179 p->designated_bridge.prio[1] = newprio & 0xFF; 180 } 181 182 } 183 184 br->bridge_id.prio[0] = (newprio >> 8) & 0xFF; 185 br->bridge_id.prio[1] = newprio & 0xFF; 186 br_configuration_update(br); 187 br_port_state_selection(br); 188 if (br_is_root_bridge(br) && !wasroot) 189 br_become_root_bridge(br); 190} 191 192/* called under bridge lock */ 193void br_stp_set_port_priority(struct net_bridge_port *p, u8 newprio) 194{ 195 port_id new_port_id = br_make_port_id(newprio, p->port_no); 196 197 if (br_is_designated_port(p)) 198 p->designated_port = new_port_id; 199 200 p->port_id = new_port_id; 201 p->priority = newprio; 202 if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) && 203 p->port_id < p->designated_port) { 204 br_become_designated_port(p); 205 br_port_state_selection(p->br); 206 } 207} 208 209/* called under bridge lock */ 210void br_stp_set_path_cost(struct net_bridge_port *p, u32 path_cost) 211{ 212 p->path_cost = path_cost; 213 br_configuration_update(p->br); 214 br_port_state_selection(p->br); 215} 216 217ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id) 218{ 219 return sprintf(buf, "%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x\n", 220 id->prio[0], id->prio[1], 221 id->addr[0], id->addr[1], id->addr[2], 222 id->addr[3], id->addr[4], id->addr[5]); 223}