软件定义网络

我的未来我决定 提交于 2019-11-26 17:00:57

软件定义网络(SDN)

主要有以下三个特点:

  • 控制与转发分离:转发平面就是一个个虚拟或者物理的网络设备,就像小区里面的一条条路。控制平面就是统一的控制中心,就像小区物业的监控室。它们原来是一起的,物业管理员要从监控室出来,到路上去管理设备,现在是分离的,路就是走人的,控制都在监控室。
  • 控制平面与转发平面之间的开放接口:控制器向上提供接口,被应用层调用,就像总控室提供按钮,让物业管理员使用。控制器向下调用接口,来控制网络设备,就像总控室会远程控制电梯的速度。这里经常使用两个名词,前面这个接口称为北向接口,后面这个接口称为南向接口,上北下南嘛。
  • 逻辑上的集中控制:逻辑上集中的控制平面可以控制多个转发面设备,也就是控制整个物理网络,因而可以获得全局的网络状态视图,并根据该全局网络状态视图实现对网络的优化控制,就像物业管理员在监控室能够看到整个小区的情况,并根据情况优化出入方案

如下图:

image



OpenFlow和OpenvSwitch

      OpenFlow是SDN控制器和网络设备之间互通的南向接口协议,OpenvSwitch用于创建软件的虚拟交换机。OpenvSwitch是支持OpenFlow协议的,当然也有一些硬件交换机也支持OpenFlow
协议。它们都可以被统一的SDN控制器管理,从而实现物理机和虚拟机的网络连通。

如下图:

image

   

    在OpenvSwitch里面,有一个流表规则,任何通过这个交换机的包,都会经过这些规则进行处理,从而接收、转发、放弃。每个表格好多行,每行都是一条规则。每条规则都有优先级,先看高优先级的规则,再看低优先级的规则。

image

      每一条规则,要看是否满足匹配条件。这些条件包括,从哪个端口进来的,网络包头里面有什么等等。满足了条件的网络包,就要执行一个动作,对这个网络包进行处理。可以修改包头里的内容,可以跳到任何一个表格,可以转发到某个网口出去,也可以丢弃。

image

对于物理层:

  •       匹配规则包括由从哪个口进来;
  •       执行动作包括从哪个口出去。

对于MAC层:

  • 匹配规则包括:源MAC地址是多少?(dl_src),目标MAC是多少?(dl_dst),所属vlan是多少?(dl_vlan);
  • 执行动作包括:修改源MAC(mod_dl_src),修改目标MAC(mod_dl_dst),修改VLAN(mod_vlan_vid),删除VLAN(strip_vlan),MAC地址学习(learn)。

对于网络层:

  • 匹配规则包括:源IP地址是多少?(nw_src),目标IP是多少?(nw_dst)。
  • 执行动作包括:修改源IP地址(mod_nw_src),修改目标IP地址(mod_nw_dst)。

对于传输层:

  • 匹配规则包括:源端口是多少?(tp_src),目标端口是多少?(tp_dst)。
  • 执行动作包括:修改源端口(mod_tp_src),修改目标端口(mod_tp_dst)。

总而言之,对于OpenvSwitch来讲,网络包到了我手里,就是一个Buffer,我想怎么改怎么改,想发到哪个端口就发送到哪个端口。


openvswitch实验

创建交换机

ovs-vsctl add-br ubuntu_br


实验一:用OpenvSwitch实现VLAN的功能

下面我们实验一下通过OpenvSwitch实现VLAN的功能,在OpenvSwitch中端口port分两种。
第一类是access port:

  • 这个端口配置tag,从这个端口进来的包会被打上这个tag;
  • 如果网络包本身带有的VLAN ID等于tag,则会从这个port发出;
  • 从access port发出的包不带VLAN ID。

第二类是trunk port:

  • 这个port不配置tag,配置trunks;
  • 如果trunks为空,则所有的VLAN都trunk,也就意味着对于所有VLAN的包,本身带什么VLAN ID,就是携带者什么VLAN ID,如果没有设置VLAN,就属于VLAN 0,全部允许通过;
  • 如果trunks不为空,则仅仅带着这些VLAN ID的包通过。


我们通过以下命令创建如下的环境:

ovs-vsctl add-port ubuntu_br first_br
ovs-vsctl add-port ubuntu_br second_br
ovs-vsctl add-port ubuntu_br third_br
ovs-vsctl set Port vnet0 tag=101
ovs-vsctl set Port vnet1 tag=102
ovs-vsctl set Port vnet2 tag=103
ovs-vsctl set Port first_br tag=103
ovs-vsctl clear Port second_br tag
ovs-vsctl set Port third_br trunks=101,102


另外要配置禁止MAC地址学习。

vs-vsctl set bridge ubuntu_br flood-vlans=101,102,103

实验拓扑:

image



创建好了环境以后,我们来做这个实验。
1. 从192.168.100.102来ping 192.168.100.103,然后用tcpdump进行抓包。first_if收到包了,从first_br出来的包头是没有VLAN ID的。second_if也收到包了,由于second_br是trunk
port,因而出来的包头是有VLAN ID的,third_if收不到包。
2. 从192.168.100.100来ping 192.168.100.105, 则second_if和third_if可以收到包,当然ping不通,因为third_if不属于某个VLAN。first_if是收不到包的。second_if能够收到包,而且包里
面是VLAN ID=101。third_if也能收到包,而且包头里面是VLAN ID=101。
3. 从192.168.100.101来ping 192.168.100.104, 则second_if和third_if可以收到包。first_if是收不到包的。second_br能够收到包,而且包头里面是VLAN ID=102。third_if也能收到包,而且包头里面是VLAN ID=102。




实验二:用OpenvSwitch模拟网卡绑定,连接交换机


在OpenvSwitch里面,有个bond_mode,可以设置为以下三个值:

  • active-backup:一个连接是active,其他的是backup,当active失效的时候,backup顶上;
  • balance-slb:流量安装源MAC和output VLAN进行负载均衡;
  • balance-tcp:必须在支持LACP协议的情况下才可以,可根据L2, L3, L4进行负载均衡。

拓扑结构:

image


创建bond

ovs-vsctl add-bond br0 bond0 first_br second_br
ovs-vsctl add-bond br1 bond1 first_if second_if
ovs-vsctl set Port bond0 lacp=active
ovs-vsctl set Port bond1 lacp=active


默认情况下bond_mode是active-backup模式,一开始active的是first_br和first_if

    测试192.168.100.100 ping 192.168.100.102,以及从192.168.100.101 ping 192.168.100.103的时候,tcpdump可以看到所有的包都是从first_if通过。
    如果把first_if设成down,则包的走向会变,发现second_if开始有流量,对于192.168.100.100和192.168.100.101似乎没有收到影响。
   如果我们通过以下命令,把bond_mode设为balance-slb。然后我们同时在192.168.100.100 ping 192.168.100.102,在192.168.100.101 ping 192.168.100.103,我们通过tcpdump现包已经被分流了。

ovs-vsctl set Port bond0 bond_mode=balance-slb
ovs-vsctl set Port bond1 bond_mode=balance-slb

OpenvSwitch的架构图

image

OpenvSwitch包含很多的模块,在用户态有两个重要的进程,也有两个重要的命令行工具。

  • 第一个进程是OVSDB进程。ovs-vsctl命令行会和这个进程通信,去创建虚拟交换机,创建端口,将端口添加到虚拟交换机上,OVSDB会将这些拓扑信息保存在一个本地的文件中。
  • 第二个进程是vswitchd进程。ovs-ofctl命令行会和这个进程通信,去下发流表规则,规则里面会规定如何对网络包进行处理,vswitchd会将流表放在用户态Flow Table中

在内核态,OpenvSwitch有内核模块OpenvSwitch.ko,对应图中的Datapath部分。在网卡上注册一个函数,每当有网络包到达网卡的时候,这个函数就会被调用。
在内核的这个函数里面,会拿到网络包,将各个层次的重要信息拿出来,例如:

  • 在物理层,in_port即包进入的网口的ID;
  • 在MAC层,源和目的MAC地址;
  • 在IP层,源和目的IP地址;
  • 在传输层,源和目的端口号。

      在内核中,有一个内核态Flow Table。接下来内核模块在这个内核流表中匹配规则,如果匹配上了,则执行操作、修改包,或者转发或者放弃。如果内核没有匹配上,则需要进入用户态,用户态和内核态之间通过Linux的一个机制Netlink相互通信。
      内核通过upcall,告知用户态进程vswitchd在用户态Flow Table里面去匹配规则,这里面的规则是全量的流表规则,而内核Flow Table里面的只是为了快速处理,保留了部分规则,内核里面的规则过一阵就会过期。
     当在用户态匹配到了流表规则之后,就在用户态执行操作,同时将这个匹配成功的流表通过reinject下发到内核,从而接下来的包都能在内核找到这个规则。这里调用openflow协议的,是本地的命令行工具,也可以是远程的SDN控制器,一个重要的SDN控制器是OpenDaylight。


OpenDaylight拓扑图


image

我们可以通过在OpenDaylight里,将两个交换机之间配置通,也可以配置不通,还可以配置一个虚拟IP地址VIP,在不同的机器之间实现负载均衡等等,所有的策略都可以灵活配置。

云中openvswitch场景拓扑(VLAN)

image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!