`
m635674608
  • 浏览: 4929422 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Linux下的虚拟Bridge实现

 
阅读更多

 Linux下的Bridge也是一种虚拟设备,这多少和vlan有点相似,它依赖于一个或多个从设备。与VLAN不同的是,它不是虚拟出和从设备同一层次的镜像设备,而是虚拟出一个高一层次的设备,并把从设备虚拟化为端口port,且同时处理各个从设备的数据收发及转发,再加上netfilter框架的一些东西,使得它的实现相比vlan复杂得多。

1.Bridge的功能框图

    它是Linux下虚拟出来bridge设备,Linux下可用brctl命令创建br设备,如下

brctl addbr brname

然后添加port,并进行相应配置,就可以使用了

brctl addif brname eth0

brctl addif brname eth1

ifconfig brname IP up

ifconfig eth0 0.0.0.0 up

ifconfig eth1 0.0.0.0 up

可见br设备是建立在从设备之上的(这些从设备可以是实际设备,也可以是vlan设备等),并且可以为br准备一个IP(br设备的MAC地址是它所有从设备中最小的MAC地址),这样该主机就可以通过这个br设备与网络中的其它主机通信了(详见发送功能框图)。

另外它的从设备被虚拟化为端口port,它们的IP及MAC都不再可用,且它们被设置为接收任何包,最终由bridge设备来决定数据包的去向:接收到本机、转发、丢弃(详见接收功能框图)。

        发送功能                                        接收功能

 

    简单的数据结构框图如下所示。

2.Bridge设备的创建

    和Vlan一样,bridge也被当成一个module加载进内核,它的module_init()函数和vlan差不多,进行一些namespace的注册,特殊的是它还注册了一个netfilter_ops,在内核全局的HOOK函数表中增加了7个函数,其中5个的pf=Bridge,另两个的pf分别为INET、INET6,它们主要用于bridge中的netfilter操作(后面会细讲)。

    最后,也是我们这最关心的是,它注册了一个ioctl函数br_ioctl_deviceless_stub(),该ioctl函数和vlan的一样,都会作为sock_ioctl()的特殊情况被调用。映射到应用层,它应该是对某个socket插口进行ioctl操作,详见brctl源码。该ioctl函数中最主要的就是br_add_bridge(net,buf),用于创建bridge设备,如下图所示:

该函数调用netdev_alloc(),申请net_device(),并分配私有空间net_bridge()结构,指明初始化函数为br_dev_setup(),最后register_netdev()把该设备组册进内核,可见bridge设备和一般的设备差不多。

主要看其中br_dev_setup(),首先初始化设备的type、flags为bridge,然后最关键的是设置其dev->netdev_ops = br_netdev_ops,即内核为bridge设备准备好了一套通用的驱动函数,这个直接关系到bridge的工作方法,后面再细讲。然后初始化私有空间net_bridge()结构,设置bridge的本地设备及从设备的list(当然这是还没有从设备加进来),然后设置了桥的group_address,即上一节所说的特殊的MAC地址,最后还初始化了timer相关的。

 

    这时bridge还不完整,还需添加port从设备,由命令brctl addif brname portdev完成,但要注意,虽然还是brctl命令,但此时的操作对象是已经存在的bridge设备,映射到内核中就是br_netdev_ops->ioctl()中的br_add_if()(它是br设备的ioctl操作,和之前那个sock_ioctl的分支不是一个层次上的)。至于怎么从应用层直接操作底层的net_device设备的,可以参见brctl源码,以后再看吧,先看看这里的br_add_if(),如下图:

    首先判断dev从设备必须不是loopback,不是bridge,不是其他bridge的port,且要是ethernet设备,才能继续;然后根据br、dev选择一个index号,并分配一个新的net_bridge_port结构,初始化之,并将它加入bridge的port_list中;最后br的一些物理参数,其MAC地址为所有从设备中MAC最小的(由上一节知,从设备被设置成全接收模式,其IP和MAC都没有了),且其MTU也为所有从设备中最小的。

    上面设置br的相关参数,下面还要设置从设备,首先使dev->master=br_dev(实际上就是构成上一节数据结构中的索引关系);然后设置dev->prive_flags加上IFF_BRIDGE_PORT,这样它就不能再作为其他br的从设备了;最后也是最关键的,设置dev->rx_handler为br_handler_frame(),为数据接收作准备。

3.Bridge设备的发送流程

    前面也讲过了,Linux下的bridge设备,对下层而言是一个桥设备,进行数据的转发(实际上对下也有接收能力,下一节讲)。而对上层而言,它就像普通的ethernet设备一样,有自己的IP和MAC地址,那么上层当然可以把它加入路由系统,并利用它发送数据啦,并且很容易想到,它的发射函数最终肯定是利用某个从设备的驱动去完成实际的发送的,这个和VLAN是相通的。具体看代码:

    上层根据目的IP地址,路由选择了该br_dev设备发送,并且由ARP缓存中得到了对应的目的MAC,填写在了skb中,然后启动了发送流程dev_queue_xmit(skb)。因为此时的skb->dev为br_dev,无queue,直接去调用br设备的发送函数,该函数就是br_netdev_ops中定义的br_dev_xmit(skb,br_dev)。

    该函数首先根据目的MAC地址,确定是广播还是单播,这里仅讨论单播时,根据DMAC在net_bridge的fdb_hash中找到相应的net_bridge_fdb_entry项,并索引到对应的端口net_bridge_port。最后利用该端口的从设备来发送数据,注意,这里是直接调用dev->ops->ndo_start_xmit(skb,dev)的,一放面这里的dev已经是从设备了,另一方面,这里没有像VLAN中那样重定位skb->dev,并重启发送流程dev_queue_xmit(),是因为一个从设备只能作为一个bridge的port,没有其它身份,不存在竞争问题。

4.Bridge设备的接收流程

    和VLAN一样,实际接收由硬件设备完成,最终通过netif_receive_skb(skb)函数提交给上层,而在该函数中会处理vlan、bridge这类特殊设备。与LVAN的仅是把skb设备重定位以实现对上层透明的要求不同,Bridge接受过程复杂得多,因此专门注册了一个函数来处理,即前面提到的rx_handler(),它被注册在port设备的net_device结构中(这算是port设备失去自身IP、MAC的一个补偿吧J),如下图所示。只有作为bridge的从设备才会注册rx_handler(),并在这里执行,处理桥接,普通的设备不会执行到这里。

    这里两种典型的返回值是RX_CONSUMED、RX_PASS,后者表示处理了一下回来,继续之前的流程,实际上就是对应的接收功能框图中的第一种情况;前者表示该skb已不再属于这个从设备了,而是被提交给了br设备,所以本次netif_receive_skb()就不用管啦,直接goto out,这里还要再分两种情况,一是转发的,这时br就真的充当了桥的角色,二是由br提交给上层的,这时br充当的是一个以太网设备,如前面所述。

要处理这么多情况,代码需设计得很巧妙,这里的rx_handler被设置为br_handle_frame(**pskb),看具体代码:

    功能框架清楚了,代码流程就清楚了,就不细看了,有几个注意的地方:一是bridge的端口处于FORWARD或LEARNING状态没多大区别,只是FORWARD要多执行一个二层防火墙,所有用了一个中间没有break的switch结构;二是要时刻记着,bridge本身除了有转发端口外,自己也是一个设备,广播(多播)时也要发一份给自己,且是以br_dev的身份递交上层;三是所有的HOOK函数都会比较复杂,因为内核的netfilter框架建立在网络层,而bridge在链路层就转发了,相当于跳过了netfilter,所以在这些hook中都会去调用INET域的hook函数。

5.小结

    通过对Bridge和vlan的学习,了解了网络栈底层的工作方式,发送这个主动过程相对简单,而接收过程则相对复杂,用到BH模型,NAPI等。

    Vlan和bridge功能有所不同,但相似处很多,更重要的是:它们都对上层透明,所以不会牵扯到协议域的问题。

 

http://www.cnblogs.com/zmkeil/archive/2013/04/21/3034733.html

分享到:
评论

相关推荐

    虚拟交换技术和linux网桥

    对linux下的3类虚拟交换技术(bridge、openswitch、macvlan)进行了浅显易懂的介绍,对于想了解虚拟机中支持网卡类型以及虚拟机与外部组网方式很有帮助~!

    Linux bridge桥接两个VirtualBox虚拟网络的方法步骤

    主要介绍了Linux bridge桥接两个VirtualBox虚拟网络的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    kvm-practice:kvm虚拟化实践,包含nat、bridge方式创建windows、linux虚拟机详细步骤

    3、bridge方式创建linux虚拟机 使用ssh访问虚拟机 4、nat方式创建linux虚拟机 配置iptables端口转发,使用使用远程连接访问虚拟机 5、VMWare三种网络模式 三种模式描述,适用场景 实际生产部署模式 5、iptables学习...

    linux内核结构图

    linux内核结构图,从硬件,到设备控制,再到bridge,虚拟成,用户接口层等,用图形把内核结构描述出来,是不可多得的了解linux内核的好图片。

    Docker与iptables及实现bridge方式网络隔离与通信操作

    Docker提供了bridge, host, overlay等多种网络。同一个Docker宿主机上同时存在多个不同类型的网络,位于不同网络中的容器,彼此...当 Docker 启动时,会自动在主机上创建一个 docker0 虚拟网桥,实际上是 Linux 的一个

    understanding linux network internals

    Kernel Infrastructure for Component Initialization 组件初始化的底层内核(实现) Section 7.1. Boot-Time Kernel Options 内核启动选项 Section 7.2. Module Initialization Code 模块初始化 Section 7.3. ...

    10-动手实践虚拟网络 1

    本节将演示如何在实验环境中实现下图所示的虚拟网络配置 Linux Bridge br0编辑 /etc/network/interfaces,配置 br0。ven

    OpenStack网络实现(上)

    bridge:网桥,Linux中用于表示一个能连接不同网络设备的虚拟设备,linux中传统实现的网桥类似一个hub设备,而ovs管理的网桥一般类似交换机。br-int:bridge-integration,综合网桥,常用于表示实现主要内部网络功能...

    fog05-networking-linux:使用Linux网桥实现的网络管理器插件

    Linux Bridge网络管理器插件该插件允许fog05使用网桥工具管理网络支持的操作: 创建虚拟桥梁创建虚拟网络添加网络接口删除虚拟接口删除虚拟网桥删除虚拟网络去做: 创建虚拟界面从网络上删除接口

    KVM虚拟化管理平台VManagePlatform.zip

    Web Console等等)设备资源控制(如:在线调整内存、CPU资源、热添加、删除硬盘)存储池管理增减卷,支持主流类型存储类型资源利用率网络管理支持SDN,底层网络使用OpenVSwitch/Linux Bridge,支持子网隔离,IP地址...

    VMware网络连接设置技巧

     默认使用vmnet0,这种方式最简单,直接将虚拟网卡桥接到一个物理网卡上面,和linux下一个网卡绑定两个不同地址类似,实际上是将网卡设置为混杂模式,从而达到侦听多个IP的能力。  将虚拟机的ip设置与主机同网段未...

    Docker网络原理分析

    Docker使用linux的bridge和veth虚拟网络设备,以及network namespace对网络进行虚拟化。Bridge看其名字是网桥,但实际上它的功能和交换机(switch)相似。

    linux下配置和安装KVM虚拟机的步骤

    最近要在外网搞一套监控系统,正好有一台服务器配置比较高,也没跑什么重要的业务,就拿来划了一个KVM虚拟机,可能是平时各种虚拟机用的比较多,配置起来感觉比想象中简单的多,简单记录下过程 准备工作 宿主机为...

    Docker 默认bridge网络中配置DNS的方法

    当您安装Docker时,就会自动创建一个名为bridge 的桥接网络。 注意 : Docker网络功能 允许您创建除默认网桥之外的用户自定义网络。 有关用户自定义网络中DNS配置的更多信息,请参阅Docker嵌入式DNS 部分。 Docker...

    container-lab:containerlab支持基于容器的网络实验室

    例如:除了本地容器化的NOS,containerlab还可以使用启动基于传统虚拟机的路由器: 而且,当然,containerlab具有完美的功能,可以连接任意的linux容器,这些容器可以承载您的网络应用程序,虚拟功能或仅仅是测试...

    tvnviewer.2.8.11

    用于在linux系统上部署kvm虚拟系统的时候,安装虚拟机的时候使用。 虚拟机安装方法: virt-install \ --virt-type=kvm \ --name=centos7-base \ --vcpus=4 --memory=4096 \ --os-variant=generic \ --cdrom=/data/...

    解决Mac下 docker 无法 ping 通宿主机的问题

    我们实现的方式,就是利用这个虚拟网卡。 使用docker-machine创建默认linux虚拟机,命令docker-machine create 切换docker环境,使用eval $(docker-machine env)命令 查看创建的虚拟机的ip地址:docker-machine ip ...

Global site tag (gtag.js) - Google Analytics