基于 Open vSwitch 的 OpenFlow 实践
上一篇中简单介绍了 Open vSwitch,这篇展开讲讲,旨在说明 OVS 配合 OpenFlow 控制器的实际应用。
我的新书《LangChain编程从入门到实践》 已经开售!推荐正在学习AI应用开发的朋友购买阅读!
Open vSwitch 内部结构
简单说明:
ovs-vswitchd:OVS 守护进程,和 ovs-ofctl 通信遵从 OpenFlow 协议,与 ovsdb-server 通信使用 OVSDB 协议,和内核模块通过 netlink 通信,支持多个独立的 datapath
ovsdb-server:OVS 轻量级的数据库服务器,用于整个 OVS 的配置信息,包括接口,交换内容,VLAN 等,ovs-vswitchd 根据数据库中的配置信息工作
ovs-dpctl:用来配置 datapath,可以控制转发规则
ovs-vsctl:主要是获取或者更改 ovs-vswitchd 的配置信息,操作的同时会更新 ovsdb
ovs-appctl:a utility that sends commands to running Open vSwitch daemons (ovs-vswitchd)
ovs-ofctl
在没有配置 OpenFlow 控制器的模式下,可以使用 ovs-ofctl(OVS 提供的命令行工具)命令通过 OpenFlow 协议去连接 OVS,创建、修改或删除 OVS 中的流表项,并对 OVS 的运行状况进行动态监控。
Flow 语法说明
Flow 被定义为某个特定的网络流量,例如一个 TCP 连接就是一个 Flow,或者从某个 IP 地址发出来的数据包,都可以被认为是一个 Flow,支持 OpenFlow 协议的交换机应该包括一个或者多个流表,流表中的条目包含:数据包头的信息、匹配成功后要执行的指令和统计信息。
当数据包进入 OVS 后,会将数据包和流表中的流表项进行匹配,如果发现了匹配的流表项,则执行该流表项中的指令集。相反,如果数据包在流表中没有发现任何匹配,OVS 会通过控制通道把数据包发到 OpenFlow 控制器中。
流表常用字段
在 OVS 中,流表项作为 ovs-ofctl 的参数,采用如下的格式:字段=值。如果有多个字段,可以用逗号或者空格分开。一些常用的字段列举如下:
| 字段名称 | 说明 |
| :– | :– |
| in_port=port | 传递数据包的端口的 OpenFlow 端口编号 |
| dl_vlan=vlan | 数据包的 VLAN Tag 值,范围是 0-4095,0xffff 代表不包含 VLAN Tag 的数据包 |
| dl_src=<MAC>
dl_dst=<MAC> | 匹配源或者目标的 MAC 地址
01:00:00:00:00:00/01:00:00:00:00:00 代表广播地址
00:00:00:00:00:00/01:00:00:00:00:00 代表单播地址 |
| dl_type=ethertype | 匹配以太网协议类型,其中:
dl_type=0x0800 代表 IPv4 协议
dl_type=0x086dd 代表 IPv6 协议
dl_type=0x0806 代表 ARP 协议
完整的的类型列表可以参见以太网协议类型列表 |
| nw_src=ip[/netmask] nw_dst=ip[/netmask] | 当 dl_typ=0x0800 时,匹配源或者目标的 IPv4 地址,可以使用 IP 地址或者域名 |
| nw_proto=proto | 和 dl_type 字段协同使用
当 dl_type=0x0800 时匹配 IPv4 协议编号
当 dl_type=0x086dd 时匹配 IPv6 协议编号
完整的 IP 协议编号可以参见 IP 协议编号列表 |
| table=number | 指定要使用的流表的编号,范围是 0-254。在不指定的情况下,默认值为 0。通过使用流表编号,可以创建或者修改多个 Table 中的 Flow |
| reg<idx>=value[/mask] | 交换机中的寄存器的值。当一个数据包进入交换机时,所有的寄存器都被清零,用户可以通过 Action 的指令修改寄存器中的值 |
流表执行的动作
对于 add−flow,add−flows 和 mod−flows 这三个命令,还需要指定要执行的动作:actions=[target][,target…]
一个流规则中可能有多个动作,按照指定的先后顺序执行。
常见的操作有:
- output:port 输出数据包到指定的端口,port 是指端口的 openflow 端口编号
- group:group_id 输出数据包到 openflow group,group_id 是指openflow group的id
- enqueue:port:queue 将数据包放到 openflow port 端口的 queue 号队列中
- mod_vlan_vid:vlan_id 修改数据包中的 vlan tag 为 vlan_id,如果数据包中无 tag,则添加;如果数据包中已经是 vlan_id,同时调整 vlan 优先级为 0
- strip_vlan: 移除数据包中的 vlan tag
- mod_dl_src/ mod_dl_dest: 修改源或者目标的 MAC 地址信息
- mod_nw_src/mod_nw_dst: 修改源或者目标的 IPv4 地址信息
- mod_tp_src/mod_tp_dst: 将数据包的TCP/UDP/SCTP源或则目的端口
- drop 将数据包丢弃
- resubmit:port 替换流表的 in_port 字段,并重新进行匹配
- load:value−>dst[start..end] 写数据到指定的字段
- normal: 按照常规L2/L3处理流程处理数据包
- flood: 将数据包输出到除该数据包输入口外和不可被 flooding 端口外的所有物理端口
- all: 将数据包输出到除了该数据包的输入口外的所有物理口
- local: 将数据包输出到与 bridge 同名的端口
- in_port: 将数据包输出到其输入口
- controller(key=value): 将数据包以 “packet in” 消息形式发给 openflow 控制器
- max_len=nbytes: 将数据包的 nbytes 字节数据发给控制器
- reason=reason: 指明 “packet in” reason; 取值为 action(默认reason)、no_match、invalid_ttl
- id=controller-id: 指明要发送给的控制器 id
- mod_nw_tos:tos 修改 ip 头的服务类型 tos 中的高六位(修改数值为[0,255]之间 4 的倍数)
- mod_nw_ecn:ecn 修改 ip 头的服务类型 tos 中低两位
- mod_nw_ttl:ttl 修改 TTL,在[0,255]之间
- set_tunnel:id
- move:src[start..end]−>dst[start..end] 含义未探究清楚、待定
- learn(argument[,argument]…) 含义未探究清楚、待定
Flow Table 使用实例
创建网络拓扑
1 | +--------------+ +----------------+ |
1 | ovs-vsctl add-br br0 |
屏蔽数据包
屏蔽所有进入 OVS 的以太网广播数据包
1 | ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop" |
屏蔽 STP 协议的广播数据包
1 | ovs-ofctl add-flow ovs-switch "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop" |
修改数据包
修改从端口 first-br 收到的数据包的源地址为 1.1.1.4
1 | $ ovs-ofctl add-flow br0 "priority=1 idle_timeout=0,in_port=1,actions=mod_nw_src:1.1.1.4,normal" |
重定向数据包
重定向所有的 ICMP 数据包到端口 third-br
1 | $ ovs-ofctl add-flow br0 "idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:3" |
修改数据包的 VLAN Tag
OVS 提供的 ovs-appctl ofproto/trace 工具可以生成测试用的模拟数据包,并一步步的展示 OVS 对数据包的流处理过程,来跟踪转发状况。
1 | # 使端口 second-br 成为一个隶属于 VLAN 102 的端口 |
使用 ofproto/trace 生成一个从端口 first-br 发送到端口 second-br 的数据包,发现数据包进入端口 first-br 之后,会被加上 VLAN tag 102,同时转发到端口 second-br 上。
1 | $ ovs-appctl ofproto/trace br0 in_port=1,dl_src=2e:07:86:10:44:29,dl_dst=22:de:bf:73:db:b8 |
“Flow: ” 之后的字段描述了输入的流的信息。由于没有指定太多信息,所以多数字段 (例如 dl_type 和 vlan_tci)被 OVS 设置为空值
”Final flow: ” 之后的字段是整个处理过程的总结
“Datapath actions: ” 代表数据包在 datapath 的 1,4号端口添加 tag,在 3 号端口删除 tag
清除实验环境
1 | ovs-vsctl del-br br0 |
参考链接
基于 Open vSwitch 的 OpenFlow 实践