惠伟:openflow group实现vip主主模式zhuanlan.zhihu.com
接着这个写起,框框线线架构完成,但实践起来坑坑不息。
一条openflow group包含了几个bucket,每个bucket有watch_port, watch_group, weight和action,watch_port和watch_group用来检测bucket是不是live,weigh用于select类型的group,action是output等,甚至可以是resubmit(xxx)和group:xxx。
opeflow group有四种类型,all, select, indirect和fast_failover
类型 | 动作 | 用途 |
---|---|---|
all | 执行第一个bucket | 随便用 |
indirect | hash选择一个bucket执行 | 聚合,路由查找时的nexthop,也就是adj表 |
select | 只能有一个bucket,执行这个bucket | 负载均衡 |
fast_failover | 执行第一个live的bucket | 主备 |
对all,indirect和fast_failover来说实现起来都简单,只要遍历bucket找到一个就行,如果是fast_failover再加个是否live的检测,但是select就难了,必须要有hash算法,openflow spec也没说hash怎么实现,openvswitch中实现了两种hash,openvswitch hash和datapath hash。
datapatch把首包给了openvswitch,openvswitch根据fields进行hash计算选择一个bucket,然后给datapath安装流表,后续包直接在datapathp匹配安装的流表转发,这种hash算法可以理解了按流hash,hash计算了选择了哪些field,安装流时就匹配哪些field,其它都被mask掉了。
假如配置这样的一条group
group_id=1000,type=select,selection_method=hash,fields\(ip_src,ip_dst,ip_proto\),bucket=weight=1,watch_port="vxlan-0aa28f06",actions=output:"vxlan-0aa28f06",bucket=weight=1,watch_port="vxlan-0aa28f07",actions="vxlan-0aa28f07"
匹配完安装的流表是这样的
ufid:be0fea14-1670-4561-a970-301e3771c524, recirc_id(0),dp_hash(0/0),skb_priority(0/0),in_port(vxlan_net0_ip9),skb_mark(0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),eth(src=fa:16:3e:ec:85:09,dst=fa:16:3e:ec:85:10),eth_type(0x0800),ipv4(src=192.168.200.90,dst=192.168.200.5,proto=6,tos=0/0x3,ttl=0/0,frag=no),tcp(src=0/0,dst=0/0),tcp_flags(0/0), packets:346828, bytes:24346932, used:0.002s, flags:SFP., dp:ovs, actions:set(tunnel(tun_id=0x3e8,src=10.145.69.26,dst=10.162.143.7,ttl=64,tp_dst=4789,flags(df|key))),vxlan_sys_4789
如果流很多那么datapath就会被安装很多流,但是hash计算的工作量小,只有首包时计算一下。
datapath hash可以理解为按包hash,这个hash值是由datapath来计算的,根据包hash的结果选择bucket,openvswitch的实现是这样,计算出一个hash mask,把bucket平均分配到这些hash mask上,然后流表都安装到datapath,datapath每来一个包计算hash值,然后recirc从头开始匹配,第二次匹配时就多了个hash值和cecirc_id为0作为key,mask hash值匹配一条执行动作,第二次匹配时包的哪些字段都被全mask掉了,只靠hash值。
ufid:ee6e45b0-4e62-43e9-8a6c-87573ece1cc7, recirc_id(0x5a6),dp_hash(0x9/0xf),skb_priority(0/0),in_port(tap240cf299-12),skb_mark(0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),eth(src=00:00:00:00:00:00/00:00:00:00:00:00,dst=00:00:00:00:00:00/00:00:00:00:00:00),eth_type(0x8100),vlan(vid=30,pcp=0),encap(eth_type(0x0800),ipv4(src=0.0.0.0/0.0.0.0,dst=0.0.0.0/0.0.0.0,proto=0/0,tos=0/0x3,ttl=0/0,frag=no)), packets:7, bytes:816, used:1.971s, flags:P., dp:ovs, actions:set(tunnel(tun_id=0x3e8,src=10.145.69.26,dst=10.162.143.7,ttl=64,tp_dst=4789,flags(df|key))),pop_vlan,vxlan_sys_4789
ufid:693d3244-71f2-4b0a-a01a-ad8e293ef6b2, recirc_id(0x5a6),dp_hash(0x8/0xf),skb_priority(0/0),in_port(tap240cf299-12),skb_mark(0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),eth(src=00:00:00:00:00:00/00:00:00:00:00:00,dst=00:00:00:00:00:00/00:00:00:00:00:00),eth_type(0x8100),vlan(vid=30,pcp=0),encap(eth_type(0x0800),ipv4(src=0.0.0.0/0.0.0.0,dst=0.0.0.0/0.0.0.0,proto=0/0,tos=0/0x3,ttl=0/0,frag=no)), packets:0, bytes:0, used:never, dp:ovs, actions:set(tunnel(tun_id=0x3e8,src=10.145.69.26,dst=10.162.143.6,ttl=64,tp_dst=4789,flags(df|key))),pop_vlan,vxlan_sys_4789
ufid:f4352588-1396-47a7-aff7-98ce54931e72, recirc_id(0),dp_hash(0/0),skb_priority(0/0),in_port(tap240cf299-12),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),eth(src=fa:16:3e:e5:cb:19,dst=fa:16:3e:ec:85:20),eth_type(0x0800),ipv4(src=0.0.0.0/0.0.0.0,dst=0.0.0.0/0.0.0.0,proto=0/0,tos=0/0,ttl=0/0,frag=no), packets:9, bytes:978, used:1.972s, flags:P., dp:ovs, actions:push_vlan(vid=30,pcp=0),hash(l4(0)),recirc(0x5a6)
这儿前面两条流表key除了dp_hash值其它一模一样。
这种hash算法好处就是流表少,省了安装流表的时间,但datapath就计算包的hash值,如果没有硬件offload,软件实现费劲,而且还得recirc一次。
我们用的openvswitch版本是2.11.0,实现了SEL_METHOD_DEFAULT,SEL_METHOD_HASH和SEL_METHOD_DP_HASH,SEL_METHOD_DEFAULT就是采用了默认fields的SEL_METHOD_HASH。
openflow从1.5版本开始支持selection_method,可以是hash或者dp_hash,默认用dp_hash。配置hash时可以指定fields,如果不指定fields回退到SEL_METHOD_DEFAULT。配置dp_hash时没有weigh或者bucket weigh相关过大,回退到SEL_METHOD_DEFAULT。
ovs_ofctl支持selection_method,但os-ken python库不支持。
最终选择用hash,field采用ip_src, ip_dst和ip_proto,openvswitch-agent组装ovs_ofctl命令下配置。
datapath采用的是内核openvswitch模块,流量是从虚拟机出来的,没有硬件offload计算skb的hash值,每个包都计算太费cpu。
所以只能用hash算法,udp大包在ip层分片后,ovs不支持分片重组,所以不能匹配udp四层port。