此文已由作者徐城利授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
传统的网络架构中,网络流量的转发、处理都是由每个网络设备自己控制,在现在的网络环境中,限制越来越明显:
每个供应商在实现自己的设备时,都有各自不同的策略,导致采购新设备时对供应商有依赖
单独的网络设备缺乏足够的信息来保证全局上的优化
规划与管理上不利于扩容
网络的复杂导致运维人员更倾向于保持现状,不愿意做可能影响稳定性的变动
为了解决这些问题,业务引入了SDN (Software-defined networking),将网络功能从底层设备抽象出来,上层控制平面决定流量的最终路径,底层网络设备只进行转发工作 (数量平面)。通过SDN,能够在一定程度上简化网络复杂性,提高网络的灵活性和扩容能力。
由SDN的定义可以看出,在控制面和数据面之间需要一套标准的方法进行交互,其中使用比较广泛的一种便是OpenFlow。OpenFlow定义了访问网络转发设备 (交换机和路由器) 的标准通讯协议。现在OpenFlow标准由Open Networking Foundation (ONF)管理,当前最新的版本是1.4。
OpenFlow中定义了交换机和控制器之间的通讯接口、支持OpenFlow设备的要求等一系列标准,不过作为普通用户,可能更希望了解通过OpenFlow能做到什么,因此我们可以简单的看一下OpenFlow本身定义的一些流表规则。 为了方便起见,我们以Open vSwitch中使用的语法作为例子。
OpenFlow交换机可以有一个或多个流表(Flow Table),在每张流表中按优先级查找任务匹配的流规则,根据匹配的规则执行相应的指令 (转发到指定端口、修改包内容、提交到另外一张流表继续查找等),如果没有任何匹配规则就执行默认行为 (根据不同的设置,可能包被丢弃或作标准交换机转发行为)。
过程如上图所示 (图片来自于网络)
简单来说,每条流由流描述(Flow Description)和行为(Actions)组成,前者用于查找匹配,后者在匹配的执行相应的操作,例如:
table=1,priority=1,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21)
表示在流表1中查找匹配MAC地址是(01:00:00:00:00:00/01:00:00:00:00:00)的包,并转发到流表21继续查找。
在OpenFlow中,可以通过一系列field=value对来描述具体一类流量,常用的有:
Field | Value |
---|---|
in_port | 交换机上的OpenFlow端口号 |
dl_vlan | 包的VLAN ID |
dl_src / dl_dst | 数据链路层的源/目标地址 (以太网中的MAC地址) |
dl_type | 以太协议中的类型,如0x8000是IP包,0x8060是ARP包 |
nw_src / nw_dst | 网络层源/目标地址,如IP协议中就是源/目标地址,ARP中是SPA/TPA |
nw_proto | 网络层协议中的协议字段,跟dl_type配合决定L4协议,如dl_type=0x0800,nw_proto=6表示是TCP包 |
tp_src / tp_dst | L4包地址,如TCP协议中的源端口/目标端口 |
imcp_type / icmp_code | 当dl_type和nw_proto指定是ICMP时,匹配ICMP的类型和代码 |
table | 指定规则生效的流表 |
tun_id | 隧道ID |
tun_src / tun_dst | 隧道的源/目标地址 |
其他可参考OpenFlow协议规范,或Open vSwitch相应文档
匹配到具体一类流后,可以执行相应的行为,主要有:
Actions | Descriptions |
---|---|
output | 把包发往指定的端口 |
normal | 按交换机传统L2/L3过程处理 |
flood | 把包发住除输入端口和禁用Flood的端口外的所有端口 |
all | 把包发住输入端口外的所有端口 |
controller | 把包发住controller |
local | 把包发往Bridge对应的网络设备 |
in_port | 将包发回输入端口,原端口返回 |
drop | 直接丢弃包 |
mod_vlan_vid / strip_vlan / push_vlan | 在以太帧中修改/去除/增加VLAN ID |
mod_dl_src / mod_dl_dst / mod_nw_src / mod_nw_dst / mod_tp_src / mod_tp_dst | 修改L2/L3/L4的源/目标地址 |
resubmit([port],[table]) | 在指定的table重新查找,并将in_port调成指定的端口 |
set_tunnel | 设置隧道ID |
其他可参考OpenFlow协议,或Open vSwitch相应文档
Open vSwitch是一个满足生产环境要求的多层虚拟交换机,它支持大量传统交换机的功能,如L2转发、sFlow/NetFlow管理接口、LACP、802.1ag等,同时也支持OpenFlow,在不少系统中作为虚拟化的VEB使用。
Open vSwitch主要由以下几部分组成:
datapath:负责数据转发的快速通道(fast-path),有多种实现,用的比较多的是Linux内核模块,对应OpenFlow中的转发设备
vswitchd:Open vSwitch用户态的后台进程,主要根据Datapath上传的包,查找相应的流规则并下发到Datapath中,同时负责处理接口调用和给Datapath下发控制指令等。
ovsdb:保存了Open vSwitch中Bridge、Port、Interface等的信息
客户端:为了方便使用,Open vSwitch还提供了一些客户端工具,如ovs-vsctl、ovs-ofctl、ovs-appctl、ovs-dpctl等
这个例子中,我们创建一个简单的虚拟交换机来演示下Open vSwitch的用法
创建一个Bridge (虚拟交换机)
ovs-vsctl add-br br-test
并将一个网卡绑定到虚拟交换机上
ovs-vsctl add-port br-test eth0
或创建一个Internal类型的Port并连接到虚拟交换机上
sudo ovs-vsctl add-port br-test p1 -- set Interface p1 type=Internal
可以查询虚拟交换机的状态
% sudo ovs-vsctl show Bridge br-test Port br-test Interface br-test type: internal Port "p1" Interface "p1" type: Internal ovs_version: "2.0.2"
Open vSwitch可以在不使用外部Controller的情况下,给虚拟交换机设置OpenFlow规则
sudo ovs-ofctl add-flow br-test in_port=1,ip,nw_src=192.168.1.0/24,actions=drop
也可以通过ovs-ofctl查询现有的规则
% sudo ovs-ofctl dump-flows br-test NXST_FLOW reply (xid=0x4): cookie=0x0, duration=50.745s, table=0, n_packets=0, n_bytes=0, idle_age=50, ip,in_port=1,nw_src=192.168.1.0/24 actions=drop cookie=0x0, duration=497.698s, table=0, n_packets=8, n_bytes=648, idle_age=488, priority=0 actions=NORMAL
通过ovs-ofctl设置的规则都是保存在用户态的vswitchd中,只有当Datapath检测到无法匹配的流时才会查询,我们也可以通过ovs-dpctl查看Datapath中真正匹配生效的流
sudo ovs-dpctl dump-flows
Open vSwitch还通过ovs-appctl ofproto/trace提供了调试功能
admin@10-165-0-64:~$ sudo ovs-appctl ofproto/trace br-int in_port=716,dl_src=fa:16:3e:03:d8:36,dl_dst=00:07:b4:01:32:01,dl_type=0x0800,nw_src=10.165.136.72,nw_dst=172.17.2.144 Bridge: br-int Flow: ip,metadata=0,in_port=716,vlan_tci=0x0000,dl_src=fa:16:3e:03:d8:36,dl_dst=00:07:b4:01:32:01,nw_src=10.165.136.72,nw_dst=172.17.2.144,nw_tos=0,nw_ecn=0,nw_ttl=0 Rule: table=0 cookie=0 priority=1 OpenFlow actions=NORMAL no learned MAC for destination, flooding Resubmitted flow: ip,metadata=0,in_port=1,dl_vlan=7,dl_vlan_pcp=0,dl_src=fa:16:3e:03:d8:36,dl_dst=00:07:b4:01:32:01,nw_src=10.165.136.72,nw_dst=172.17.2.144,nw_tos=0,nw_ecn=0,nw_ttl=0 Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 Resubmitted odp: push_vlan(vid=7,pcp=0),11,pop_vlan,51,55,57,45,47,79,push_vlan(vid=7,pcp=0),12 Rule: table=0 cookie=0 priority=1,in_port=1 OpenFlow actions=resubmit(,1) Resubmitted flow: unchanged Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 Resubmitted odp: push_vlan(vid=7,pcp=0),11,pop_vlan,51,55,57,45,47,79,push_vlan(vid=7,pcp=0),12 Rule: table=1 cookie=0 priority=1,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 OpenFlow actions=resubmit(,20) Resubmitted flow: unchanged Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 Resubmitted odp: push_vlan(vid=7,pcp=0),11,pop_vlan,51,55,57,45,47,79,push_vlan(vid=7,pcp=0),12 Rule: table=20 cookie=0 priority=0 OpenFlow actions=resubmit(,21) Resubmitted flow: unchanged Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 Resubmitted odp: push_vlan(vid=7,pcp=0),11,pop_vlan,51,55,57,45,47,79,push_vlan(vid=7,pcp=0),12 Rule: table=21 cookie=0 priority=0 OpenFlow actions=drop Resubmitted flow: unchanged Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 Resubmitted odp: push_vlan(vid=7,pcp=0),11,pop_vlan,51,55,57,45,47,79,push_vlan(vid=7,pcp=0),12 Rule: table=0 cookie=0 priority=1,in_port=1,dl_vlan=7 OpenFlow actions=resubmit(,30) Resubmitted flow: unchanged Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 Resubmitted odp: push_vlan(vid=7,pcp=0),11,pop_vlan,51,55,57,45,47,79,push_vlan(vid=7,pcp=0),12 Rule: table=30 cookie=0 priority=1,ip,in_port=1,nw_src=10.165.136.64/26,nw_dst=172.17.0.0/20 OpenFlow actions=output:2 Resubmitted flow: unchanged Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 Resubmitted odp: push_vlan(vid=7,pcp=0),11,pop_vlan,51,55,57,45,47,79,push_vlan(vid=7,pcp=0),12 Rule: table=0 cookie=0 priority=2,in_port=1,dl_vlan=7 OpenFlow actions=mod_vlan_vid:306,NORMAL forwarding to learned port Final flow: ip,metadata=0,in_port=716,vlan_tci=0x0000,dl_src=fa:16:3e:03:d8:36,dl_dst=00:07:b4:01:32:01,nw_src=10.165.136.72,nw_dst=172.17.2.144,nw_tos=0,nw_ecn=0,nw_ttl=0 Relevant fields: skb_priority=0,ip,in_port=716,vlan_tci=0x0000,dl_src=fa:16:3e:03:d8:36,dl_dst=00:07:b4:01:32:01,nw_src=10.165.136.64/28,nw_dst=172.17.2.144,nw_proto=0,nw_frag=no Datapath actions: push_vlan(vid=7,pcp=0),11,pop_vlan,51,55,57,45,47,79,push_vlan(vid=7,pcp=0),12,pop_vlan,28
以上Open vSwitch一些简单的用法,更多功能请参考相应文档
网易云免费体验馆,0成本体验20+款云产品!
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 Android之高效率截图
【推荐】 微服务监控探索
【推荐】 nova状态同步