br_stp_if.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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. #include <linux/kernel.h>
  16. #include <linux/if_bridge.h>
  17. #include <linux/smp_lock.h>
  18. #include <asm/uaccess.h>
  19. #include "br_private.h"
  20. #include "br_private_stp.h"
  21. __u16 br_make_port_id(struct net_bridge_port *p)
  22. {
  23. return (p->priority << 8) | p->port_no;
  24. }
  25. /* called under bridge lock */
  26. void br_init_port(struct net_bridge_port *p)
  27. {
  28. p->port_id = br_make_port_id(p);
  29. br_become_designated_port(p);
  30. p->state = BR_STATE_BLOCKING;
  31. p->topology_change_ack = 0;
  32. p->config_pending = 0;
  33. br_timer_clear(&p->message_age_timer);
  34. br_timer_clear(&p->forward_delay_timer);
  35. br_timer_clear(&p->hold_timer);
  36. }
  37. /* called under bridge lock */
  38. void br_stp_enable_bridge(struct net_bridge *br)
  39. {
  40. struct net_bridge_port *p;
  41. struct timer_list *timer = &br->tick;
  42. init_timer(timer);
  43. timer->data = (unsigned long) br;
  44. timer->function = br_tick;
  45. timer->expires = jiffies + 1;
  46. add_timer(timer);
  47. br_timer_set(&br->hello_timer, jiffies);
  48. br_config_bpdu_generation(br);
  49. p = br->port_list;
  50. while (p != NULL) {
  51. if (p->dev->flags & IFF_UP)
  52. br_stp_enable_port(p);
  53. p = p->next;
  54. }
  55. br_timer_set(&br->gc_timer, jiffies);
  56. }
  57. /* called under bridge lock */
  58. void br_stp_disable_bridge(struct net_bridge *br)
  59. {
  60. struct net_bridge_port *p;
  61. br->topology_change = 0;
  62. br->topology_change_detected = 0;
  63. br_timer_clear(&br->hello_timer);
  64. br_timer_clear(&br->topology_change_timer);
  65. br_timer_clear(&br->tcn_timer);
  66. br_timer_clear(&br->gc_timer);
  67. br_fdb_cleanup(br);
  68. p = br->port_list;
  69. while (p != NULL) {
  70. if (p->state != BR_STATE_DISABLED)
  71. br_stp_disable_port(p);
  72. p = p->next;
  73. }
  74. del_timer(&br->tick);
  75. }
  76. /* called under bridge lock */
  77. void br_stp_enable_port(struct net_bridge_port *p)
  78. {
  79. br_init_port(p);
  80. br_port_state_selection(p->br);
  81. }
  82. /* called under bridge lock */
  83. void br_stp_disable_port(struct net_bridge_port *p)
  84. {
  85. struct net_bridge *br;
  86. int wasroot;
  87. br = p->br;
  88. printk(KERN_INFO "%s: port %i(%s) entering %s staten",
  89.        br->dev.name, p->port_no, p->dev->name, "disabled");
  90. wasroot = br_is_root_bridge(br);
  91. br_become_designated_port(p);
  92. p->state = BR_STATE_DISABLED;
  93. p->topology_change_ack = 0;
  94. p->config_pending = 0;
  95. br_timer_clear(&p->message_age_timer);
  96. br_timer_clear(&p->forward_delay_timer);
  97. br_timer_clear(&p->hold_timer);
  98. br_configuration_update(br);
  99. br_port_state_selection(br);
  100. if (br_is_root_bridge(br) && !wasroot)
  101. br_become_root_bridge(br);
  102. }
  103. /* called under bridge lock */
  104. static void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr)
  105. {
  106. unsigned char oldaddr[6];
  107. struct net_bridge_port *p;
  108. int wasroot;
  109. wasroot = br_is_root_bridge(br);
  110. memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
  111. memcpy(br->bridge_id.addr, addr, ETH_ALEN);
  112. memcpy(br->dev.dev_addr, addr, ETH_ALEN);
  113. p = br->port_list;
  114. while (p != NULL) {
  115. if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN))
  116. memcpy(p->designated_bridge.addr, addr, ETH_ALEN);
  117. if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN))
  118. memcpy(p->designated_root.addr, addr, ETH_ALEN);
  119. p = p->next;
  120. }
  121. br_configuration_update(br);
  122. br_port_state_selection(br);
  123. if (br_is_root_bridge(br) && !wasroot)
  124. br_become_root_bridge(br);
  125. }
  126. static unsigned char br_mac_zero[6] = {0,0,0,0,0,0};
  127. /* called under bridge lock */
  128. void br_stp_recalculate_bridge_id(struct net_bridge *br)
  129. {
  130. unsigned char *addr;
  131. struct net_bridge_port *p;
  132. addr = br_mac_zero;
  133. p = br->port_list;
  134. while (p != NULL) {
  135. if (addr == br_mac_zero ||
  136.     memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
  137. addr = p->dev->dev_addr;
  138. p = p->next;
  139. }
  140. if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))
  141. br_stp_change_bridge_id(br, addr);
  142. }
  143. /* called under bridge lock */
  144. void br_stp_set_bridge_priority(struct net_bridge *br, int newprio)
  145. {
  146. struct net_bridge_port *p;
  147. int wasroot;
  148. wasroot = br_is_root_bridge(br);
  149. p = br->port_list;
  150. while (p != NULL) {
  151. if (p->state != BR_STATE_DISABLED &&
  152.     br_is_designated_port(p)) {
  153. p->designated_bridge.prio[0] = (newprio >> 8) & 0xFF;
  154. p->designated_bridge.prio[1] = newprio & 0xFF;
  155. }
  156. p = p->next;
  157. }
  158. br->bridge_id.prio[0] = (newprio >> 8) & 0xFF;
  159. br->bridge_id.prio[1] = newprio & 0xFF;
  160. br_configuration_update(br);
  161. br_port_state_selection(br);
  162. if (br_is_root_bridge(br) && !wasroot)
  163. br_become_root_bridge(br);
  164. }
  165. /* called under bridge lock */
  166. void br_stp_set_port_priority(struct net_bridge_port *p, int newprio)
  167. {
  168. __u16 new_port_id;
  169. p->priority = newprio & 0xFF;
  170. new_port_id = br_make_port_id(p);
  171. if (br_is_designated_port(p))
  172. p->designated_port = new_port_id;
  173. p->port_id = new_port_id;
  174. if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) &&
  175.     p->port_id < p->designated_port) {
  176. br_become_designated_port(p);
  177. br_port_state_selection(p->br);
  178. }
  179. }
  180. /* called under bridge lock */
  181. void br_stp_set_path_cost(struct net_bridge_port *p, int path_cost)
  182. {
  183. p->path_cost = path_cost;
  184. br_configuration_update(p->br);
  185. br_port_state_selection(p->br);
  186. }