「转」桥初始化(一)

前言

注:章节中的源代码,基于 linux 内核 4.7.4

网桥的背景到处都有,在这里就不浪费的时间说废话了。

桥接程序的初始化,桥接程序既可以集成在内核中,也可以编译成独立模块。初始化函数br_init和清理函数br_deinit的定义在/net/bridge/br.c中

在网桥设备初始化的时候,主要是做一些注册和初始化的操作。

桥初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
static int __init br_init(void)
{
int err;
/*注册协议生成树收包函数*/
err = stp_proto_register(&br_stp_proto);
if (err < 0) {
pr_err("bridge: can't register sap for STP\n");
return err;
}
/*转发数据库初始化*/
err = br_fdb_init();
if (err)
goto err_out;
/*在/proc目录下生成任何与bridge相关的目录,如果我们想在/proc下生成bridge相关的子目录或子文件*/
err = register_pernet_subsys(&br_net_ops);
if (err)
goto err_out1;
/*目前好像没有什么实际作用,在内核中所注册的函数为空*/
err = br_nf_core_init();
if (err)
goto err_out2;
/*注册相关网络设备的事件通知连*/
err = register_netdevice_notifier(&br_device_notifier);
if (err)
goto err_out3;

/*注册通知连,主要针对桥转发表事件的相关信息*/
err = register_switchdev_notifier(&br_switchdev_notifier);
if (err)
goto err_out4;
/*进行netlink的初始化*/
err = br_netlink_init();
if (err)
goto err_out5;

/*用来处理ioctl命令的函数,比如添加和删除网桥*/
brioctl_set(br_ioctl_deviceless_stub);

#if IS_ENABLED(CONFIG_ATM_LANE)
br_fdb_test_addr_hook = br_fdb_test_addr;
#endif
return 0;
}

具体的

了解了桥初始化大致要做的事情后,我们再来看看这些初始化或者注册的事情到底干了些什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1.注册协议生成树收包函数stp_proto_register
在桥初始化的时候,注册了一个br_stp_proto参数,此参数的具体模样是这样子的
static const struct stp_proto br_stp_proto = {
.rcv = br_stp_rcv,
};
br_stp_rcv函数在/net/bridge/br_stp_bpdu.c中主要针对网桥进行协议交换的帧(BPDU)进行配置操作。

2.桥转发数据库初始化br_fdb_init
此函数就是在内存中建立一块slab cache,以存放net_bridge_fdb_entry
其中:net_bridge_fdb_entry是一个结构体,用来转发数据库的记录项网桥所学到对的每个MAC地址都有这样一个记录

3.在proc目录下生成相关文件的注册函数register_pernet_subsys,初始化的时候给这个函数传递了一个参数br_net_ops,这个参数的模样是这样的
static struct pernet_operations br_net_ops = {
.exit = br_net_exit,
};
但是在桥初始化的时候,仅仅注册了br_net_exit,这个函数会将桥下面的所有文件全部清空。

4.通知链的相关函数注册register_netdevice_notifier这个注册函数主要针对设备信息的变化,注册参数br_device_notifier,具体如下:
static struct notifier_block br_device_notifier = {
.notifier_call = br_device_event
};
br_device_event函数是用来当桥上的设备状态或者设备信息发生改变时做相应的处理,该函数在/net/bridge/br.c中

5.注册通知连,主要针对桥转发表事件的相关信息register_switchdev_notifier,传入的参数br_switchdev_notifier详细信息如下:
static struct notifier_block br_switchdev_notifier = {
.notifier_call = br_switchdev_event,
};
br_switchdev_event,主要针对桥转发表的事件做出相应的处理该函数在/net/bridge/br.c中

6.brioctl_set用来处理ioctl命令的函数,比如添加和删除网桥,br_ioctl_deviceless_stub给回调函数br_ioctl_hook,而br_ioctl_hook在sock_ioctl中
使用,这样通过在应用层调用socket的ioctl函数,就能够进行网桥的添加与删除了,函数用来处理添加和删除网桥的相关操作,会在下一节详细介绍。

以上就是网桥初始化的相关操作 [1]

参考


  1. @不留你的名字 桥初始化 2010-12-01 ↩︎

0%