br_if.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

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