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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Spanning tree protocol; timer-related code
  3.  * Linux ethernet bridge
  4.  *
  5.  * Authors:
  6.  * Lennert Buytenhek <buytenh@gnu.org>
  7.  *
  8.  * $Id: br_stp_timer.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. #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. static void dump_bridge_id(bridge_id *id)
  22. {
  23. printk("%.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", id->prio[0],
  24.        id->prio[1], id->addr[0], id->addr[1], id->addr[2], id->addr[3],
  25.        id->addr[4], id->addr[5]);
  26. }
  27. /* called under bridge lock */
  28. static int br_is_designated_for_some_port(struct net_bridge *br)
  29. {
  30. struct net_bridge_port *p;
  31. p = br->port_list;
  32. while (p != NULL) {
  33. if (p->state != BR_STATE_DISABLED &&
  34.     !memcmp(&p->designated_bridge, &br->bridge_id, 8))
  35. return 1;
  36. p = p->next;
  37. }
  38. return 0;
  39. }
  40. /* called under bridge lock */
  41. static void br_hello_timer_expired(struct net_bridge *br)
  42. {
  43. br_config_bpdu_generation(br);
  44. br_timer_set(&br->hello_timer, jiffies);
  45. }
  46. /* called under bridge lock */
  47. static void br_message_age_timer_expired(struct net_bridge_port *p)
  48. {
  49. struct net_bridge *br;
  50. int was_root;
  51. br = p->br;
  52. printk(KERN_INFO "%s: ", br->dev.name);
  53. printk("neighbour ");
  54. dump_bridge_id(&p->designated_bridge);
  55. printk(" lost on port %i(%s)n", p->port_no, p->dev->name);
  56. /*
  57.  * According to the spec, the message age timer cannot be
  58.  * running when we are the root bridge. So..  this was_root
  59.  * check is redundant. I'm leaving it in for now, though.
  60.  */
  61. was_root = br_is_root_bridge(br);
  62. br_become_designated_port(p);
  63. br_configuration_update(br);
  64. br_port_state_selection(br);
  65. if (br_is_root_bridge(br) && !was_root)
  66. br_become_root_bridge(br);
  67. }
  68. /* called under bridge lock */
  69. static void br_forward_delay_timer_expired(struct net_bridge_port *p)
  70. {
  71. if (p->state == BR_STATE_LISTENING) {
  72. printk(KERN_INFO "%s: port %i(%s) entering %s staten",
  73.        p->br->dev.name, p->port_no, p->dev->name, "learning");
  74. p->state = BR_STATE_LEARNING;
  75. br_timer_set(&p->forward_delay_timer, jiffies);
  76. } else if (p->state == BR_STATE_LEARNING) {
  77. printk(KERN_INFO "%s: port %i(%s) entering %s staten",
  78.        p->br->dev.name, p->port_no, p->dev->name, "forwarding");
  79. p->state = BR_STATE_FORWARDING;
  80. if (br_is_designated_for_some_port(p->br))
  81. br_topology_change_detection(p->br);
  82. }
  83. }
  84. /* called under bridge lock */
  85. static void br_tcn_timer_expired(struct net_bridge *br)
  86. {
  87. printk(KERN_INFO "%s: retransmitting tcn bpdun", br->dev.name);
  88. br_transmit_tcn(br);
  89. br_timer_set(&br->tcn_timer, jiffies);
  90. }
  91. /* called under bridge lock */
  92. static void br_topology_change_timer_expired(struct net_bridge *br)
  93. {
  94. br->topology_change_detected = 0;
  95. br->topology_change = 0;
  96. }
  97. /* called under bridge lock */
  98. static void br_hold_timer_expired(struct net_bridge_port *p)
  99. {
  100. if (p->config_pending)
  101. br_transmit_config(p);
  102. }
  103. /* called under bridge lock */
  104. static void br_check_port_timers(struct net_bridge_port *p)
  105. {
  106. if (br_timer_has_expired(&p->message_age_timer, p->br->max_age)) {
  107. br_timer_clear(&p->message_age_timer);
  108. br_message_age_timer_expired(p);
  109. }
  110. if (br_timer_has_expired(&p->forward_delay_timer, p->br->forward_delay)) {
  111. br_timer_clear(&p->forward_delay_timer);
  112. br_forward_delay_timer_expired(p);
  113. }
  114. if (br_timer_has_expired(&p->hold_timer, BR_HOLD_TIME)) {
  115. br_timer_clear(&p->hold_timer);
  116. br_hold_timer_expired(p);
  117. }
  118. }
  119. /* called under bridge lock */
  120. static void br_check_timers(struct net_bridge *br)
  121. {
  122. struct net_bridge_port *p;
  123. if (br_timer_has_expired(&br->gc_timer, br->gc_interval)) {
  124. br_timer_set(&br->gc_timer, jiffies);
  125. br_fdb_cleanup(br);
  126. }
  127. if (br_timer_has_expired(&br->hello_timer, br->hello_time)) {
  128. br_timer_clear(&br->hello_timer);
  129. br_hello_timer_expired(br);
  130. }
  131. if (br_timer_has_expired(&br->tcn_timer, br->bridge_hello_time)) {
  132. br_timer_clear(&br->tcn_timer);
  133. br_tcn_timer_expired(br);
  134. }
  135. if (br_timer_has_expired(&br->topology_change_timer, br->bridge_forward_delay + br->bridge_max_age)) {
  136. br_timer_clear(&br->topology_change_timer);
  137. br_topology_change_timer_expired(br);
  138. }
  139. p = br->port_list;
  140. while (p != NULL) {
  141. if (p->state != BR_STATE_DISABLED)
  142. br_check_port_timers(p);
  143. p = p->next;
  144. }
  145. }
  146. void br_tick(unsigned long __data)
  147. {
  148. struct net_bridge *br = (struct net_bridge *)__data;
  149. read_lock(&br->lock);
  150. br_check_timers(br);
  151. read_unlock(&br->lock);
  152. br->tick.expires = jiffies + 1;
  153. add_timer(&br->tick);
  154. }