(1) bridge ioctl
int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct net_bridge *br = netdev_priv(dev);
switch(cmd) {
case SIOCDEVPRIVATE:
return old_dev_ioctl(dev, rq, cmd);
case SIOCBRADDIF:
case SIOCBRDELIF:
return add_del_if(br, rq->ifr_ifindex, cmd == SIOCBRADDIF);
}
pr_debug("Bridge does not support ioctl 0x%x\n", cmd);
return -EOPNOTSUPP;
}
static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
通过这个可以看出来,在调用add_del_if的时候,使用了cmd==SIOCBRADDIF. 在函数声明里面用了 int isadd.
这样当函数和调用者在不同的文件里面的时候,用这种方法,可以不需要让add_def_if()所在的文件里面包含
SIOCBRADDIF的声明。
(2)设置网桥
转自21CN
网桥工具的安装:
默认Ubuntu是没有网桥设置工具(brctl)的。你需要安装bridge-utils,这里在我的pc2上:
SYSHUNTER-UBUNTU# apt-get install bridge-utils
配置网桥:
先创建一个网桥接口:
SYSHUNTER-UBUNTU# brctl addbr br0
将两块已有的网卡添加到网桥:
SYSHUNTER-UBUNTU# brctl addif br0 eth0
SYSHUNTER-UBUNTU# brctl addif br0 eth1
将两块网卡IP设置为0,它们已经不再需要了:
SYSHUNTER-UBUNTU# ifconfig eth0 0.0.0.0
SYSHUNTER-UBUNTU# ifconfig eth1 0.0.0.0
给新网桥设置一个IP:
SYSHUNTER-UBUNTU# ifconfig br0 192.168.1.10
(3)用户空间工具
ifconfig工具在包net-tools里面,查看其源代码,发现ifconfig使用的是ioctl来与内核空间交互的。
fd=socket(.....);
ret=ioctl(fd,cmd,XXX);
由于用的socket文件句柄所以调用sock_ioctl( );
(4)bridge默认不编译到内核里面,可以设置其编译进内核。
bridge相关初始化代码在net/bridge/br.c
int (*br_should_route_hook) (struct sk_buff **pskb) = NULL;
static int __init br_init(void)
{
br_fdb_init();
#ifdef CONFIG_BRIDGE_NETFILTER
if (br_netfilter_init())
return 1;
#endif
brioctl_set(br_ioctl_deviceless_stub);
br_handle_frame_hook = br_handle_frame;
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
br_fdb_get_hook = br_fdb_get;
br_fdb_put_hook = br_fdb_put;
#endif
register_netdevice_notifier(&br_device_notifier);
return 0;
}
module_init(br_init)
可以看到bridge模块的初始化函数是br_init.
他做了几件事情:(netfilter的部分先不管)
1)初始化forwarding database.
2) 设置bridge相关的ioctl
3)设置收包函数
4)注册bridge模块的notifier.
(5)
当用户调用 ### brctl addbr br0
建一个新的bridge.
用户空间程序会调用ioctl,并最终调用到br_ioctl_deviceless_stub()
这个函数从用户空间得到bridge的名字,并调用br_add_bridge( )添加该bridge.
br_add_bridge()主要做几件事情:
1)建一个net_bridge结构和一个net_device结构,这2个结构相对应,代表了这个bridge.
net_bridge br;
net_device dev;
dev->priv = br;
br->dev = dev;
2)register_netdevice(dev);
3)ret = br_sysfs_addbr(dev);
4)初始化一些与stp相关的东西。
(6)当用户调用 ### brctl addif br0 eth0
把eth0添加到bridge里面,成为bridge的一个端口。
会调用br_dev_ioctl( )。
并最终调用ret = br_add_if(br, dev);来添加这个端口。
会做下面几件事:1)生成一个net_bridge_port结构,表示这个端口。
2)由于该端口本身就是一个实际的设备,如一块网卡,所以他本身有一个net_device结构。
net_bridge_port port;
net_device dev;
net_bridge br;
port->dev = dev;
port->br = br;
dev->br_port = port;
add_list(br->portlist,port);