虚拟设备之linux网桥

前言:网桥设备作为一个虚拟设备,用于连接多个端口,可以构建一个局域网。与之相似的是vlan设备,在linux中,vlan设备是为了处理802.1q的添加和去除TAG的问题,这和传统交换机中vlan的功能—划分局域网,不太一样,在这里仅仅是处理了消息头,只是实现了隔离功能,并未实现交换功能,如果需要vlan内的数据转发,可以把vlan子接口挂接在网桥设备下。

网桥设备中添加的接口,在同一个二层域中。网桥在Linux中的实现如下:

Bridge-utils工具的实现

先查看一下Bridge-utils工具的工作原理,它是用于用户态配置网桥的工具,可以用于添加/删除网桥,往网桥添加/删除接口等操作。

brctl.c的main()中,读取了参数列表,这里使用了getopt_long()函数,可以借鉴使用。之后进行br的初始化,主要就是创建一个socket接口,为之后IOCTL操作。然后调用command_lookup(),查找到参数命令,最后调用cmd->func(),执行命令。最后在内核中sock_ioctl()会收到,然后调用br_ioctl_hook(),从这里,就开始内核态的处理。

网桥设备的初始化

Br_init()br_init是注册到内核进行初始化的,module_init(br_init),在br_init中,主要做的事如下:

注册stp(生成树协议),初始化转发表,注册network namespace(暂不知啥用),注册通知连,netlink的初始化,设置br_ioctl_hook

网桥的建立和操作

br_ioctl_hook调用开始,在br_init中注册的br_ioctl_hook

br_ioctl_deviceless_stub,可以看到SIOCBRADDBR添加和删除网桥。添加网桥中alloc_netdev()分配了设备结构体,并进行了初始化设置br_dev_setup,在初始化设置的时候,就填充了netdev_ops->br_netdev_ops,这里就是对于设备的操作回调函数咯,重点关注br_dev_ioctl,在这里,会用添加和删除接口的操作。等再次添加从接口设备到网桥时,此时网桥设备已经存在,调用br_netdev_ops中的添加接口的回调函数,br_add_if中注册了接收数据的处理函数:netdev_rx_handler_register(dev, br_handle_frame, p);br_handle_frame就是处理函数咯。

网桥的数据流程

先附一张18摸公司的文章的图:

发送流程:

首先说一点是,网桥有自己的MAC地址,01:80:c2:00:00:0X,路由后发送函数dev_queue_xmit()发送数据出去,因为此时通过路由,skb->dev已经设置成为了br,所以,最后调用设备的发送回调ndo_start_xmit,在br初始化时,设置为br_dev_xmit,这样,最后的发送函数就是它咯。在发送中,确定目的地址是单播还是洪泛。

接收流程:

接收上,是从netif_receive_skb()中接收报文,因为只有在attach到网桥的从接口注册了rx_handle,即br_handle_frame,也就是只有这些接口才会把数据往网桥上送。接着调用br_handle_frame进行报文的处理,是consumed掉,还是转发等在这里完成。具体的代码就不分析咯。

注意事项:

网桥设备本身有自己的MAC,以及IP。发送和接收也正是通过路由后找到网桥接口的。
加入网桥的接口,其本身的IP和MAC地址都已经不再有效,路由并不会使用其中的地址,而是使用网桥的。

posted @ 2017-05-26 22:57  AISEED  阅读(4609)  评论(1编辑  收藏  举报