Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2762183
  • 博文数量: 79
  • 博客积分: 30130
  • 博客等级: 大将
  • 技术积分: 2608
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-22 14:58
个人简介

博所搬至http://xiaogr.com

文章存档

2015年(2)

2009年(3)

2008年(56)

2007年(18)

分类: LINUX

2007-10-25 18:26:43

------------------------------------------

本文系本站原创,欢迎转载!

转载请注明出处:http://ericxiao.cublog.cn/

------------------------------------------

 

新建网桥:

从上面的分析可以知道,在用户空间调用ioctl(br_socket_fd, SIOCBRADDBR, brname).进入到br_ioctl_deviceless_stub,可以看到它的相关处理:

int br_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg)

{

         switch (cmd) {

         case SIOCGIFBR:

         case SIOCSIFBR:

                   return old_deviceless(uarg);

         //新建网桥

         case SIOCBRADDBR:

         //删除网桥

         case SIOCBRDELBR:

         {

                   char buf[IFNAMSIZ];

                   if (!capable(CAP_NET_ADMIN))

                            return -EPERM;

                   //copy_from_user:把用户空间的数据拷入内核空间

                   if (copy_from_user(buf, uarg, IFNAMSIZ))

                            return -EFAULT;

                   buf[IFNAMSIZ-1] = 0;

                   if (cmd == SIOCBRADDBR)

                            return br_add_bridge(buf);

                   return br_del_bridge(buf);

         }

         }

         return -EOPNOTSUPP;

}

在这里,我们传入的cmdSIOCBRADDBR.转入br_add_bridge(buf)中进行:

int br_add_bridge(const char *name)

{

         struct net_device *dev;

         int ret;

         //为虚拟桥新建一个net_device

         //在前面“网络设备的管理”经讲述此结构

         dev = new_bridge_dev(name);

         if (!dev)

                   return -ENOMEM;

 

         rtnl_lock();

         //由内核确定接口名字,例如eth0 eth1

         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();

         //sysfs中建立相关信息

         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;

}

网桥的注册跟我们以前看到的物理网络设备注册是一样的。我们关心的是网桥对应的net_device结构是什么样的,继续跟踪进new_bridge_dev

static struct net_device *new_bridge_dev(const char *name)

{

         struct net_bridge *br;

         struct net_device *dev;

         //分配net_device

         dev = alloc_netdev(sizeof(struct net_bridge), name,

                               br_dev_setup);

         if (!dev)

                   return NULL;

         网桥的私区结构为net_bridge

         br = netdev_priv(dev);

         //私区结构中的dev字段指向它本身

         br->dev = dev;

         br->lock = SPIN_LOCK_UNLOCKED;

         //队列初始化。在port_list中保存了这个桥上的端口列表

         INIT_LIST_HEAD(&br->port_list);

         br->hash_lock = SPIN_LOCK_UNLOCKED;

         //下面这部份代码跟stp协议相关,我们暂不关心

         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;

}

br_dev_setup中还做了一些另外在函数指针初始化:

void br_dev_setup(struct net_device *dev)

{

         //将桥的MAC地址设为零

         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;

}

这一部份,对桥设备的私区空间进行了初始化。在这里,有必要给桥的net_device对应的私区结构:

struct net_bridge

{

         //读写锁

         spinlock_t                    lock;

         //端口列表

         struct list_head             port_list;

         //网桥对应的虚拟设备

         struct net_device          *dev;

         //网桥对应的虚拟网卡的统计数据

         struct net_device_stats                   statistics;

         //hash表的锁

         spinlock_t                    hash_lock;

         //MAC PORT对应表,即CAM

         struct hlist_head           hash[BR_HASH_SIZE];

         struct list_head             age_list;

 

         /* STP */

         //stp 协议对应的数据

         bridge_id                       designated_root;

         bridge_id                       bridge_id;

         u32                               root_path_cost;

         unsigned long                         max_age;

         unsigned long                         hello_time;

         unsigned long                         forward_delay;

         unsigned long                         bridge_max_age;

         unsigned long                         ageing_time;

         unsigned long                         bridge_hello_time;

         unsigned long                         bridge_forward_delay;

 

         u16                               root_port;

         unsigned char                         stp_enabled;

         unsigned char                         topology_change;

         unsigned char                         topology_change_detected;

管理员在2009年8月13日编辑了该文章文章。

-->
阅读(3361) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~