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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Userspace interface
  3.  * Linux ethernet bridge
  4.  *
  5.  * Authors:
  6.  * Lennert Buytenhek <buytenh@gnu.org>
  7.  *
  8.  * $Id: br_if.c,v 1.6.2.1 2001/12/24 00:59:27 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_arp.h>
  17. #include <linux/if_bridge.h>
  18. #include <linux/inetdevice.h>
  19. #include <linux/rtnetlink.h>
  20. #include <asm/uaccess.h>
  21. #include "br_private.h"
  22. static struct net_bridge *bridge_list;
  23. static int br_initial_port_cost(struct net_device *dev)
  24. {
  25. if (!strncmp(dev->name, "lec", 3))
  26. return 7;
  27. if (!strncmp(dev->name, "eth", 3))
  28. return 100; /* FIXME handle 100Mbps */
  29. if (!strncmp(dev->name, "plip", 4))
  30. return 2500;
  31. return 100;
  32. }
  33. /* called under bridge lock */
  34. static int __br_del_if(struct net_bridge *br, struct net_device *dev)
  35. {
  36. struct net_bridge_port *p;
  37. struct net_bridge_port **pptr;
  38. if ((p = dev->br_port) == NULL)
  39. return -EINVAL;
  40. br_stp_disable_port(p);
  41. dev_set_promiscuity(dev, -1);
  42. dev->br_port = NULL;
  43. pptr = &br->port_list;
  44. while (*pptr != NULL) {
  45. if (*pptr == p) {
  46. *pptr = p->next;
  47. break;
  48. }
  49. pptr = &((*pptr)->next);
  50. }
  51. br_fdb_delete_by_port(br, p);
  52. kfree(p);
  53. dev_put(dev);
  54. return 0;
  55. }
  56. static struct net_bridge **__find_br(char *name)
  57. {
  58. struct net_bridge **b;
  59. struct net_bridge *br;
  60. b = &bridge_list;
  61. while ((br = *b) != NULL) {
  62. if (!strncmp(br->dev.name, name, IFNAMSIZ))
  63. return b;
  64. b = &(br->next);
  65. }
  66. return NULL;
  67. }
  68. static void del_ifs(struct net_bridge *br)
  69. {
  70. write_lock_bh(&br->lock);
  71. while (br->port_list != NULL)
  72. __br_del_if(br, br->port_list->dev);
  73. write_unlock_bh(&br->lock);
  74. }
  75. static struct net_bridge *new_nb(char *name)
  76. {
  77. struct net_bridge *br;
  78. struct net_device *dev;
  79. if ((br = kmalloc(sizeof(*br), GFP_KERNEL)) == NULL)
  80. return NULL;
  81. memset(br, 0, sizeof(*br));
  82. dev = &br->dev;
  83. strncpy(dev->name, name, IFNAMSIZ);
  84. dev->priv = br;
  85. ether_setup(dev);
  86. br_dev_setup(dev);
  87. br->lock = RW_LOCK_UNLOCKED;
  88. br->hash_lock = RW_LOCK_UNLOCKED;
  89. br->bridge_id.prio[0] = 0x80;
  90. br->bridge_id.prio[1] = 0x00;
  91. memset(br->bridge_id.addr, 0, ETH_ALEN);
  92. br->stp_enabled = 1;
  93. br->designated_root = br->bridge_id;
  94. br->root_path_cost = 0;
  95. br->root_port = 0;
  96. br->bridge_max_age = br->max_age = 20 * HZ;
  97. br->bridge_hello_time = br->hello_time = 2 * HZ;
  98. br->bridge_forward_delay = br->forward_delay = 15 * HZ;
  99. br->topology_change = 0;
  100. br->topology_change_detected = 0;
  101. br_timer_clear(&br->hello_timer);
  102. br_timer_clear(&br->tcn_timer);
  103. br_timer_clear(&br->topology_change_timer);
  104. br->ageing_time = 300 * HZ;
  105. br->gc_interval = 4 * HZ;
  106. return br;
  107. }
  108. /* called under bridge lock */
  109. static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device *dev)
  110. {
  111. int i;
  112. struct net_bridge_port *p;
  113. p = kmalloc(sizeof(*p), GFP_KERNEL);
  114. if (p == NULL)
  115. return p;
  116. memset(p, 0, sizeof(*p));
  117. p->br = br;
  118. p->dev = dev;
  119. p->path_cost = br_initial_port_cost(dev);
  120. p->priority = 0x80;
  121. dev->br_port = p;
  122. for (i=1;i<255;i++)
  123. if (br_get_port(br, i) == NULL)
  124. break;
  125. if (i == 255) {
  126. kfree(p);
  127. return NULL;
  128. }
  129. p->port_no = i;
  130. br_init_port(p);
  131. p->state = BR_STATE_DISABLED;
  132. p->next = br->port_list;
  133. br->port_list = p;
  134. return p;
  135. }
  136. int br_add_bridge(char *name)
  137. {
  138. struct net_bridge *br;
  139. if ((br = new_nb(name)) == NULL)
  140. return -ENOMEM;
  141. if (__dev_get_by_name(name) != NULL) {
  142. kfree(br);
  143. return -EEXIST;
  144. }
  145. br->next = bridge_list;
  146. bridge_list = br;
  147. br_inc_use_count();
  148. register_netdev(&br->dev);
  149. return 0;
  150. }
  151. int br_del_bridge(char *name)
  152. {
  153. struct net_bridge **b;
  154. struct net_bridge *br;
  155. if ((b = __find_br(name)) == NULL)
  156. return -ENXIO;
  157. br = *b;
  158. if (br->dev.flags & IFF_UP)
  159. return -EBUSY;
  160. del_ifs(br);
  161. *b = br->next;
  162. unregister_netdev(&br->dev);
  163. kfree(br);
  164. br_dec_use_count();
  165. return 0;
  166. }
  167. int br_add_if(struct net_bridge *br, struct net_device *dev)
  168. {
  169. struct net_bridge_port *p;
  170. if (dev->br_port != NULL)
  171. return -EBUSY;
  172. if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
  173. return -EINVAL;
  174. if (dev->hard_start_xmit == br_dev_xmit)
  175. return -ELOOP;
  176. dev_hold(dev);
  177. write_lock_bh(&br->lock);
  178. if ((p = new_nbp(br, dev)) == NULL) {
  179. write_unlock_bh(&br->lock);
  180. dev_put(dev);
  181. return -EXFULL;
  182. }
  183. dev_set_promiscuity(dev, 1);
  184. br_stp_recalculate_bridge_id(br);
  185. br_fdb_insert(br, p, dev->dev_addr, 1);
  186. if ((br->dev.flags & IFF_UP) && (dev->flags & IFF_UP))
  187. br_stp_enable_port(p);
  188. write_unlock_bh(&br->lock);
  189. return 0;
  190. }
  191. int br_del_if(struct net_bridge *br, struct net_device *dev)
  192. {
  193. int retval;
  194. write_lock_bh(&br->lock);
  195. retval = __br_del_if(br, dev);
  196. br_stp_recalculate_bridge_id(br);
  197. write_unlock_bh(&br->lock);
  198. return retval;
  199. }
  200. int br_get_bridge_ifindices(int *indices, int num)
  201. {
  202. struct net_bridge *br;
  203. int i;
  204. br = bridge_list;
  205. for (i=0;i<num;i++) {
  206. if (br == NULL)
  207. break;
  208. indices[i] = br->dev.ifindex;
  209. br = br->next;
  210. }
  211. return i;
  212. }
  213. /* called under ioctl_lock */
  214. void br_get_port_ifindices(struct net_bridge *br, int *ifindices)
  215. {
  216. struct net_bridge_port *p;
  217. p = br->port_list;
  218. while (p != NULL) {
  219. ifindices[p->port_no] = p->dev->ifindex;
  220. p = p->next;
  221. }
  222. }