{{ v.name }}
{{ v.cls }}类
{{ v.price }} ¥{{ v.price }}
openvswitch(下面简称为ovs)是由niciranetworks主导的,运行在虚拟化平台(例如kvm,xen)上的虚拟交换机。在虚拟化平台上,ovs可以为动态变化的端点提供2层交换功能,很好的控制虚拟网络中的访问策略、网络隔离、流量监控等等。
ovs遵循apache2.0许可证,能同时支持多种标准的管理接口和协议。ovs也提供了对openflow协议的支持,用户可以使用任何支持openflow协议的控制器对ovs进行远程管理控制。
openvswitch概述
在ovs中,有几个非常重要的概念:
openvswitch实验环境配置
ovs可以安装在主流的linux操作系统中,用户可以选择直接安装编译好的软件包,或者下载源码进行编译安装。
在我们的实验环境中,使用的操作系统是64位ubuntuserver12.04.3lts,并通过源码编译的方式安装了openvswitch1.11.0
$lsb_release-anolsbmodulesareavailable.distributorid:ubuntudescription:ubuntu12.04.3ltsrelease:12.04codename:precise
ovs的源码编译安装方式可以参考官方文档howtoinstallopenvswitchonlinux,freebsdandnetbsd。
安装完毕后,检查ovs的运行情况:
$ps-ea|grepovs12533?00:00:00ovs_workq12549?00:00:04ovsdb-server12565?00:00:48ovs-vswitchd12566?00:00:00ovs-vswitchd
查看ovs的版本信息,我们安装版本的是1.11.0
$ovs-appctl--versionovs-appctl(openvswitch)1.11.0compiledoct28201314:17:16
查看ovs支持的openflow协议的版本
$ovs-ofctl--versionovs-ofctl(openvswitch)1.11.0compiledoct28201314:17:17openflowversions0x1:0x4基于openvswitch的openflow实践
openflow是用于管理交换机流表的协议,ovs-ofctl则是ovs提供的命令行工具。在没有配置openflow控制器的模式下,用户可以使用ovs-ofctl命令通过openflow协议去连接ovs,创建、修改或删除ovs中的流表项,并对ovs的运行状况进行动态监控。
flow语法说明
在openflow的白皮书中,flow被定义为某个特定的网络流量。例如,一个tcp连接就是一个flow,或者从某个ip地址发出来的数据包,都可以被认为是一个flow。支持openflow协议的交换机应该包括一个或者多个流表,流表中的条目包含:数据包头的信息、匹配成功后要执行的指令和统计信息。
当数据包进入ovs后,会将数据包和流表中的流表项进行匹配,如果发现了匹配的流表项,则执行该流表项中的指令集。相反,如果数据包在流表中没有发现任何匹配,ovs会通过控制通道把数据包发到openflow控制器中。
在ovs中,流表项作为ovs-ofctl的参数,采用如下的格式:字段=值。如果有多个字段,可以用逗号或者空格分开。一些常用的字段列举如下:
表1.流表常用字段
字段名称说明
in_port=port传递数据包的端口的openflow端口编号
dl_vlan=vlan数据包的vlantag值,范围是0-4095,0xffff代表不包含vlantag的数据包
dl_src=
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时,匹配ip协议编号当dl_type=0x086dd代表ipv6协议编号完整的ip协议编号可以参见ip协议编号列表
table=number指定要使用的流表的编号,范围是0-254。在不指定的情况下,默认值为0。通过使用流表编号,可以创建或者修改多个table中的flow
reg
对于add−flow,add−flows和mod−flows这三个命令,还需要指定要执行的动作:actions=[target][,target...]
一个流规则中可能有多个动作,按照指定的先后顺序执行。
常见的操作有:
实践操作openflow命令
在本例中,我们会创建一个不连接到任何控制器的ovs交换机,并演示如何使用ovs-octl命令操作openflow流表。
创建一个新的ovs交换机
$ovs-vsctladd-brovs-switch
创建一个端口p0,设置端口p0的openflow端口编号为100(如果在创建端口的时候没有指定openflow端口编号,ovs会自动生成一个)。
$ovs-vsctladd-portovs-switchp0--setinterfacep0ofport_request=100
设置网络接口设备的类型为“internal”。对于internal类型的的网络接口,ovs会同时在linux系统中创建一个可以用来收发数据的模拟网络设备。我们可以为这个网络设备配置ip地址、进行数据监听等等。
$ovs-vsctlsetinterfacep0type=internal$ethtool-ip0driver:openvswitchversion:firmware-version:bus-info:supports-statistics:nosupports-test:nosupports-eeprom-access:nosupports-register-dump:no
为了避免网络接口上的地址和本机已有网络地址冲突,我们可以创建一个虚拟网络空间ns0,把p0接口移入网络空间ns0,并配置ip地址为192.168.1.100
$ipnetnsaddns0$iplinksetp0netnsns0$ipnetnsexecns0ipaddradd192.168.1.100/24devp0$ipnetnsexecns0ifconfigp0promiscup
使用同样的方法创建端口p1、p2
表2.创建的端口信息
端口说明
p0ip地址:192.168.1.100/24网络名称空间:ns0网络接口mac地址:66:4e:cc:ae:4d:20openflowportnumber:100
p1ip地址:192.168.1.101/24网络名称空间:ns1网络接口mac地址:46:54:8a:95:dd:f8openflowportnumber:101
p2ip地址:192.168.1.102/24,网络名称空间:ns2网络接口mac地址:86:3b:c8:d0:44:10openflowportnumber:102
创建所有的端口之后,查看ovs交换机的信息
$ovs-vsctlshow30282710-d401-4187-8e13-52388f693df7bridgeovs-switchport"p0"interface"p0"type:internalport"p2"interface"p2"type:internalport"p1"interface"p1"type:internalportovs-switchinterfaceovs-switchtype:internal
使用ovs-ofctl创建并测试openflow命令
$ovs-ofctlshowovs-switchofpt_features_reply(xid=0x2):dpid:00001232a237ea45n_tables:254,n_buffers:256capabilities:flow_statstable_statsport_statsqueue_statsarp_match_ipactions:outputset_vlan_vidset_vlan_pcpstrip_vlanset_dl_srcset_dl_dstset_nw_srcset_nw_dstset_nw_tosset_tp_srcset_tp_dstenqueue100(p0):addr:54:01:00:00:00:00config:port_downstate:link_downspeed:0mbpsnow,0mbpsmax101(p1):addr:54:01:00:00:00:00config:port_downstate:link_downspeed:0mbpsnow,0mbpsmax102(p2):addr:54:01:00:00:00:00config:port_downstate:link_downspeed:0mbpsnow,0mbpsmaxlocal(ovs-switch):addr:12:32:a2:37:ea:45config:0state:0speed:0mbpsnow,0mbpsmaxofpt_get_config_reply(xid=0x4):frags=normalmiss_send_len=0
如果想获得网络接口的openflow编号,也可以在ovs的数据库中查询
$ovs-vsctlgetinterfacep0ofport100
查看datapath的信息
$ovs-dpctlshowsystem@ovs-system:lookups:hit:12173missed:712lost:0flows:0port0:ovs-system(internal)port1:ovs-switch(internal)port2:p0(internal)port3:p1(internal)port4:p2(internal)屏蔽数据包
屏蔽所有进入ovs的以太网广播数据包
$ovs-ofctladd-flowovs-switch"table=0,dl_src=01:00:00:00:00:00/01:00:00:00:00:00,actions=drop"
屏蔽stp协议的广播数据包
$ovs-ofctladd-flowovs-switch"table=0,dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0,actions=drop"修改数据包
添加新的openflow条目,修改从端口p0收到的数据包的源地址为9.181.137.1
$ovs-ofctladd-flowovs-switch"priority=1idle_timeout=0,in_port=100,actions=mod_nw_src:9.181.137.1,normal"
从端口p0(192.168.1.100)发送测试数据到端口p1(192.168.1.101)
$ipnetnsexecns0ping192.168.1.101
在接收端口p1监控数据,发现接收到的数据包的来源已经被修改为9.181.137.1
$ipnetnsexecns1tcpdump-ip1icmptcpdump:verboseoutputsuppressed,use-vor-vvforfullprotocoldecodelisteningonp1,link-typeen10mb(ethernet),capturesize65535bytes15:59:16.885770ip9.181.137.1>192.168.1.101:icmpechorequest,id23111,seq457,length6415:59:17.893809ip9.181.137.1>192.168.1.101:icmpechorequest,id23111,seq458,length64重定向数据包
添加新的openflow条目,重定向所有的icmp数据包到端口p2
$ovs-ofctladd-flowovs-switchidle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:102
从端口p0(192.168.1.100)发送数据到端口p1(192.168.1.101)
$ipnetnsexecns0ping192.168.1.101
在端口p2上监控数据,发现数据包已被转发到端口p2
$ipnetnsexecns3tcpdump-ip2icmptcpdump:verboseoutputsuppressed,use-vor-vvforfullprotocoldecodelisteningonp2,link-typeen10mb(ethernet),capturesize65535bytes16:07:35.677770ip192.168.1.100>192.168.1.101:icmpechorequest,id23147,seq25,length6416:07:36.685824ip192.168.1.100>192.168.1.101:icmpechorequest,id23147,seq26,length64修改数据包的vlantag
除了使用“ping”、“tcpdump”和“iperf”等linux命令以外,我们也可以使用ovs提供的ovs-appctlofproto/trace工具来测试ovs对数据包的转发状况。ovs-appctlofproto/trace可以用来生成测试用的模拟数据包,并一步步的展示ovs对数据包的流处理过程。在以下的例子中,我们演示一下如何使用这个命令:
修改端口p1的vlantag为101,使端口p1成为一个隶属于vlan101的端口
$ovs-vsctlsetportp1tag=101
现在由于端口p0和p1属于不同的vlan,它们之间无法进行数据交换。我们使用ovs-appctlofproto/trace生成一个从端口p0发送到端口p1的数据包,这个数据包不包含任何vlantag,并观察ovs的处理过程
$ovs-appctlofproto/traceovs-switchin_port=100,dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8-generateflow:metadata=0,in_port=100,vlan_tci=0x0000,dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000rule:table=0cookie=0priority=0openflowactions=normalnolearnedmacfordestination,floodingfinalflow:unchangedrelevantfields:skb_priority=0,in_port=100,vlan_tci=0x0000/0x1fff,dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000,nw_frag=nodatapathactions:4,1
在第一行输出中,“flow:”之后的字段描述了输入的流的信息。由于我们没有指定太多信息,所以多数字段(例如dl_type和vlan_tci)被ovs设置为空值。
在第二行的输出中,“rule:”之后的字段描述了匹配成功的流表项。
在第三行的输出中,“openflowactions”之后的字段描述了实际执行的操作。
最后一段以”finalflow”开始的字段是整个处理过程的总结,“datapathactions:4,1”代表数据包被发送到datapath的4和1号端口。
创建一条新的flow:对于从端口p0进入交换机的数据包,如果它不包含任何vlantag,则自动为它添加vlantag101
$ovs-ofctladd-flowovs-switch"priority=3,in_port=100,dl_vlan=0xffff,actions=mod_vlan_vid:101,normal"
再次尝试从端口p0发送一个不包含任何vlantag的数据包,发现数据包进入端口p0之后,会被加上vlantag101,同时转发到端口p1上
$ovs-appctlofproto/traceovs-switchin_port=100,dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8–generateflow:metadata=0,in_port=100,vlan_tci=0x0000,dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000rule:table=0cookie=0priority=3,in_port=100,vlan_tci=0x0000openflowactions=mod_vlan_vid:101,normalforwardingtolearnedportfinalflow:metadata=0,in_port=100,dl_vlan=101,dl_vlan_pcp=0,dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000relevantfields:skb_priority=0,in_port=100,vlan_tci=0x0000/0x1fff,dl_src=66:4e:cc:ae:4d:20,dl_dst=46:54:8a:95:dd:f8,dl_type=0x0000,nw_frag=nodatapathactions:3
反过来从端口p1发送数据包,由于p1现在是带有vlantag101的access类型的端口,所以数据包进入端口p1之后,会被ovs添加vlantag101并发送到端口p0
$ovs-appctlofproto/traceovs-switchin_port=101,dl_dst=66:4e:cc:ae:4d:20,dl_src=46:54:8a:95:dd:f8-generateflow:metadata=0,in_port=101,vlan_tci=0x0000,dl_src=46:54:8a:95:dd:f8,dl_dst=66:4e:cc:ae:4d:20,dl_type=0x0000rule:table=0cookie=0priority=0openflowactions=normalforwardingtolearnedportfinalflow:unchangedrelevantfields:skb_priority=0,in_port=101,vlan_tci=0x0000,dl_src=46:54:8a:95:dd:f8,dl_dst=66:4e:cc:ae:4d:20,dl_type=0x0000,nw_frag=nodatapathactions:push_vlan(vid=101,pcp=0),2其他openflow常用的操作
查看交换机中的所有table
ovs-ofctldump-tablesovs-switch
查看交换机中的所有流表项
ovs−ofctldump−flowsovs-switch
删除编号为100的端口上的所有流表项
ovs-ofctldel-flowsovs-switch"in_port=100"
查看交换机上的端口信息
ovs-ofctlshowovs-switch通过floodlight管理ovs
一方面,openflow控制器可以通过openflow协议连接到任何支持openflow的交换机,控制器通过和交换机交换流表规则来控制数据流向。另一方面,openflow控制器向用户提供的界面或者接口,用户可以通过界面对网络架构进行动态的修改,修改交换机的流表规则等等。floodlight是一个基于apache协议,使用java开发的企业级openflow控制器。我们在下面的例子中演示如何安装floodlight,并连接管理ovs的过程。
floodlight的安装过程非常简单,在另外一台机器上,下载floodlight源码并编译
$gitclonegit://github.com/floodlight/floodlight.git$cdfloodlight/$ant$java-jartarget/floodlight.jar
运行floodlight
$java-jarfloodlight.jar
在安装了ovs交换机的节点上,配置ovs交换机ovs-switch,使用floodlight作为控制器。默认情况下,floodlight在端口6633上进行监听,我们使用ovs-vsctl命令配置ovs交换机使用tcp协议连接到floodlight(ip地址为9.181.137.182,端口号6633)。对于一个ovs交换机来说,可以同时配置一个或者多个控制器
$ovs-vsctlset-controllerovs-switchtcp:9.181.137.182:6633
当ovs交换机连接到floodlight控制器后,理论上所有的流表规则应该交给控制器来建立。由于ovs交换机和控制器之间是通过网络通讯来传递数据的,所以网络连接失败会影响到flow的建立。针对这种情况,ovs提供了两种处理模式:
设置ovs的连接模式为secure模式
$ovs-vsctlsetbridgeovs-switchfail-mode=secure
查看ovs的状态,“is_connected:true”代表ovs已经成功连接到了floodlight
$ovs-vsctlshow30282710-d401-4187-8e13-52388f693df7bridgeovs-switchcontroller"tcp:9.181.137.182:6633"is_connected:trueportovs-switchinterfaceovs-switchtype:internalport"p0"interface"p0"type:internalport"p1"tag:101interface"p1"type:internalport"p2"interface"p2"type:internal
通过访问floodlight提供的web管理界面http://
floodlight主界面
选中某个openflow交换机,查看其中的端口列表和流表信息
查看openflow交换机的详细信息
通过floodlight的restapi,添加两条新的规则让端口p0和p1可以相互通讯。注意:替换命令行中的switch的id为交换机的datapathid
curl-d'{"switch":"00:00:0e:f9:05:6b:7c:44","name":"my-flow1","cookie":"0","priority":"32768","ingress-port":"100","active":"true","actions":"output=flood"}'http://9.181.137.182:8080/wm/staticflowentrypusher/jsoncurl-d'{"switch":"00:00:0e:f9:05:6b:7c:44","name":"my-flow2","cookie":"0","priority":"32768","ingress-port":"101","active":"true","actions":"output=flood"}'http://9.181.137.182:8080/wm/staticflowentrypusher/json
验证是否能从端口p0发送数据包到p1
$ipnetnsexecns0ping-c4192.168.1.101ping192.168.1.101(192.168.1.101)56(84)bytesofdata.64bytesfrom192.168.1.101:icmp_req=1ttl=64time=0.027ms64bytesfrom192.168.1.101:icmp_req=2ttl=64time=0.018ms64bytesfrom192.168.1.101:icmp_req=3ttl=64time=0.023ms64bytesfrom192.168.1.101:icmp_req=4ttl=64time=0.022ms---192.168.1.101pingstatistics---4packetstransmitted,4received,0%packetloss,time2998msrttmin/avg/max/mdev=0.018/0.022/0.027/0.005ms
在ovs端也可以看到,流表规则已经被ovs同步到本地。
$ovs-ofctldump-flowsovs-switchnxst_flowreply(xid=0x4):cookie=0xa0000000000000,duration=335.122s,table=0,n_packets=347,n_bytes=28070,idle_age=1,in_port=100actions=floodcookie=0xa0000000000000,duration=239.892s,table=0,n_packets=252,n_bytes=24080,idle_age=0,in_port=101actions=flood
通过floodlight的restapi,查看交换机上的流表规则
curlhttp://9.181.137.182:8080/wm/staticflowentrypusher/list/00:00:0e:f9:05:6b:7c:44/json
通过floodlight的restapi,删除交换机上的流表规则
curlhttp://9.181.137.182:8080/wm/staticflowentrypusher/clear/00:00:0e:f9:05:6b:7c:44/json总结