转:http://blog.csdn.net/nerdx/article/details/12224603
-
-
-
-
-
-
-
-
-
-
1.1 int br_add_bridge(const char *name)
-
{
-
struct net_device *dev;
-
int ret;
-
-
dev = new_bridge_dev(name);
-
if (!dev)
-
return -ENOMEM;
-
-
rtnl_lock();
-
if (strchr(dev->name, '%')) {
-
ret = dev_alloc_name(dev, dev->name);
-
if (ret < 0)
-
goto err1;
-
}
-
-
ret = register_netdevice(dev);
-
if (ret)
-
goto err2;
-
-
dev_hold(dev);
-
rtnl_unlock();
-
-
ret = br_sysfs_addbr(dev);
-
dev_put(dev);
-
-
if (ret)
-
unregister_netdev(dev);
-
out:
-
return ret;
-
-
err2:
-
free_netdev(dev);
-
err1:
-
rtnl_unlock();
-
goto out;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
1.2 static struct net_device *new_bridge_dev(const char *name)
-
{
-
struct net_bridge *br;
-
struct net_device *dev;
-
-
dev = alloc_netdev(sizeof(struct net_bridge), name,
-
br_dev_setup);
-
-
if (!dev)
-
return NULL;
-
-
br = netdev_priv(dev);
-
br->dev = dev;
-
-
spin_lock_init(&br->lock);
-
INIT_LIST_HEAD(&br->port_list);
-
spin_lock_init(&br->hash_lock);
-
-
br->bridge_id.prio[0] = 0x80;
-
br->bridge_id.prio[1] = 0x00;
-
memset(br->bridge_id.addr, 0, ETH_ALEN);
-
-
br->stp_enabled = 0;
-
br->designated_root = br->bridge_id;
-
br->root_path_cost = 0;
-
br->root_port = 0;
-
br->bridge_max_age = br->max_age = 20 * HZ;
-
br->bridge_hello_time = br->hello_time = 2 * HZ;
-
br->bridge_forward_delay = br->forward_delay = 15 * HZ;
-
br->topology_change = 0;
-
br->topology_change_detected = 0;
-
br->ageing_time = 300 * HZ;
-
INIT_LIST_HEAD(&br->age_list);
-
-
br_stp_timer_init(br);
-
-
return dev;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
1.3 void br_dev_setup(struct net_device *dev)
-
{
-
memset(dev->dev_addr, 0, ETH_ALEN);
-
-
ether_setup(dev);
-
-
dev->do_ioctl = br_dev_ioctl;
-
dev->get_stats = br_dev_get_stats;
-
dev->hard_start_xmit = br_dev_xmit;
-
dev->open = br_dev_open;
-
dev->set_multicast_list = br_dev_set_multicast_list;
-
dev->change_mtu = br_change_mtu;
-
dev->destructor = free_netdev;
-
SET_MODULE_OWNER(dev);
-
dev->stop = br_dev_stop;
-
dev->accept_fastpath = br_dev_accept_fastpath;
-
dev->tx_queue_len = 0;
-
dev->set_mac_address = NULL;
-
dev->priv_flags = IFF_EBRIDGE;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2.1 int br_del_bridge(const char *name)
-
{
-
struct net_device *dev;
-
int ret = 0;
-
-
rtnl_lock();
-
dev = __dev_get_by_name(name);
-
if (dev == NULL)
-
ret = -ENXIO;
-
-
else if (!(dev->priv_flags & IFF_EBRIDGE)) {
-
ret = -EPERM;
-
}
-
-
else if (dev->flags & IFF_UP) {
-
ret = -EBUSY;
-
}
-
-
else
-
del_br(netdev_priv(dev));
-
-
rtnl_unlock();
-
return ret;
-
}
-
-
-
-
-
-
-
-
2.2 static void del_br(struct net_bridge *br)
-
{
-
struct net_bridge_port *p, *n;
-
-
list_for_each_entry_safe(p, n, &br->port_list, list) {
-
br_sysfs_removeif(p);
-
del_nbp(p);
-
}
-
-
del_timer_sync(&br->gc_timer);
-
-
br_sysfs_delbr(br->dev);
-
unregister_netdevice(br->dev);
-
}
-
-
-
-
-
-
-
-
-
-
2.3 static void del_nbp(struct net_bridge_port *p)
-
{
-
struct net_bridge *br = p->br;
-
struct net_device *dev = p->dev;
-
-
dev_set_promiscuity(dev, -1);
-
-
spin_lock_bh(&br->lock);
-
br_stp_disable_port(p);
-
spin_unlock_bh(&br->lock);
-
-
br_fdb_delete_by_port(br, p);
-
-
list_del_rcu(&p->list);
-
-
del_timer_sync(&p->message_age_timer);
-
del_timer_sync(&p->forward_delay_timer);
-
del_timer_sync(&p->hold_timer);
-
-
call_rcu(&p->rcu, destroy_nbp_rcu);
-
}
-
-
-
-
-
-
-
3.1 static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
-
{
-
struct net_device *dev;
-
int ret;
-
-
if (!capable(CAP_NET_ADMIN))
-
return -EPERM;
-
-
dev = dev_get_by_index(ifindex);
-
if (dev == NULL)
-
return -EINVAL;
-
-
if (isadd)
-
ret = br_add_if(br, dev);
-
else
-
ret = br_del_if(br, dev);
-
-
dev_put(dev);
-
return ret;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
3.2 int br_add_if(struct net_bridge *br, struct net_device *dev)
-
{
-
struct net_bridge_port *p;
-
int err = 0;
-
-
if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
-
return -EINVAL;
-
-
-
if (dev->hard_start_xmit == br_dev_xmit)
-
return -ELOOP;
-
-
-
if (dev->br_port != NULL)
-
return -EBUSY;
-
-
-
if (IS_ERR(p = new_nbp(br, dev, br_initial_port_cost(dev))))
-
return PTR_ERR(p);
-
-
-
if ((err = br_fdb_insert(br, p, dev->dev_addr, 1)))
-
destroy_nbp(p);
-
-
else if ((err = br_sysfs_addif(p)))
-
del_nbp(p);
-
else {
-
dev_set_promiscuity(dev, 1);
-
-
list_add_rcu(&p->list, &br->port_list);
-
-
spin_lock_bh(&br->lock);
-
br_stp_recalculate_bridge_id(br);
-
if ((br->dev->flags & IFF_UP)
-
&& (dev->flags & IFF_UP) && netif_carrier_ok(dev))
-
br_stp_enable_port(p);
-
spin_unlock_bh(&br->lock);
-
-
dev_set_mtu(br->dev, br_min_mtu(br));
-
}
-
-
return err;
-
}
-
-
-
-
-
-
-
-
-
-
3.3 void br_stp_recalculate_bridge_id(struct net_bridge *br)
-
{
-
const unsigned char *addr = br_mac_zero;
-
struct net_bridge_port *p;
-
-
list_for_each_entry(p, &br->port_list, list) {
-
if (addr == br_mac_zero ||
-
memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
-
addr = p->dev->dev_addr;
-
-
}
-
-
if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))
-
br_stp_change_bridge_id(br, addr);
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
3.4 static void br_stp_change_bridge_id(struct net_bridge *br,
-
const unsigned char *addr)
-
{
-
unsigned char oldaddr[6];
-
struct net_bridge_port *p;
-
int wasroot;
-
-
wasroot = br_is_root_bridge(br);
-
-
memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
-
memcpy(br->bridge_id.addr, addr, ETH_ALEN);
-
memcpy(br->dev->dev_addr, addr, ETH_ALEN);
-
-
list_for_each_entry(p, &br->port_list, list) {
-
if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN))
-
memcpy(p->designated_bridge.addr, addr, ETH_ALEN);
-
-
if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN))
-
memcpy(p->designated_root.addr, addr, ETH_ALEN);
-
-
}
-
-
br_configuration_update(br);
-
br_port_state_selection(br);
-
if (br_is_root_bridge(br) && !wasroot)
-
br_become_root_bridge(br);
-
}
-
-
-
-
-
-
4.1 int br_del_if(struct net_bridge *br, struct net_device *dev)
-
{
-
struct net_bridge_port *p = dev->br_port;
-
-
if (!p || p->br != br)
-
return -EINVAL;
-
-
br_sysfs_removeif(p);
-
del_nbp(p);
-
-
spin_lock_bh(&br->lock);
-
br_stp_recalculate_bridge_id(br);
-
spin_unlock_bh(&br->lock);
-
-
return 0;
-
}
-
阅读(595) | 评论(0) | 转发(0) |