OVS里最重要的几个元素:vport,flow,datapath。
其中datapth是vport和flow的桥梁。
VPORT
内核包含多个datapath(brige),上面包含一个或者多个vport。
其中一个VPORT表示一个端口,一个vport只能归于一个特定的datapath。
每个vport有自己的type
, 对应不同的vport ops
.
每个内核网口被注册为vport的时候。
VPORT结构体
1 | 58 /** |
vport & netdevice:
- dev: 当一个网口
struct net_device
被加入到datapath的时候,会创建一个对应的vport,并通过vport->dev指向这个网口。 - 对应的网口的
rx_handler
被设置为netdev_frame_hook
,rx_handler_data
设置为vport本身。1
2102 err = netdev_rx_handler_register(vport->dev, netdev_frame_hook,
103 vport);
vport & datapath
- 一个datapath相当于一个bridge(OVS用户空间实现里,把多个用户空间的网桥整合到一个datapath里了)。
- 一个datapath下可以有多个vport,但一个vport只能归属于一个datapath。
- 同一个datapath下的所有vport通过vport下的
dp_hash_node
, 根据vport->port_no
组成一个hash桶. 这个hash桶的链表头放在了datapath下的struct hlist_head *ports
。详细过程见函数static struct vport *new_vport(const struct vport_parms *parms)
- 内核ovs下所有的vport还会有一个全局的hash链表。根据vport的名字做关键字计算hash,放到一个全局的hash链表
static struct hlist_head *dev_table
。注:(vport跟其对应的netdevice名字一致),
vport & struct vport_ops
每个vport在创建时候都需要指定其对应的port 类型,每个port类型都有其独有的port ops。通过vport->ops
指向其对应的 struct vport_ops
内核里有多种类型的vport,不同类型vport对应的port ops组成一个单链表vport_ops_list
。
flow
ovs 里的flow通过match-action的形式定义了报文的处理路径。
flow的match部分是通过一个key+mask的形式进行匹配的。
key有很多元素,比如vni,src ip,mac,tunnel等信息。
mask跟key差不多的,只是多了一个range,用于指明mask里的key具体那个范围的值有效。即key从start到end部分是有效信息。
ovs收到报文后会解析每个报文的key,然后根据报文的key和每个flow的相与,得到的掩过的key跟flow里的key进行比较,确定是不是满足flow的match条件。
1 | 161 struct sw_flow_key_range { |
1 | 166 struct sw_flow_mask { |
flow的管理
- 每个datapath下有一个flow table。
- 一个flow table相当于一个flow group,下面有多条flow
每个flow table下有个hash链,每个flow根据其key的hash,存放到对应的hash桶下的链表里。
内核版ovs跟dpdk ovs的一个区别是,table下的所有的flow放到一个hash链表里,没有根据mask再做区分。所有flow的mask类型被放到一个单独的链表里。
当报文来查找规则的时候,会根据mask list里的mask逐个做mask
操作,
根据掩后的key,做hash去hash链里查找对应的flow。
重复mask list
直到mask耗尽,或者找到匹配的flow。
1 | 205 struct sw_flow { |
datapath
datapath从管理上看类似传统的网桥,是ovs里用来链接vport和flow的一个汇聚点。
所有的vport和flow都会归属到某一个特定的网桥上。
如之前所述,
struct list_head list_node
:内核里所有的DP通过一个双向链接串接起来。struct hlist_head *ports
:通过一个hash链表管理当前dp下所有的vport。struct flow_table table
: 管理当前dp下的所有flow流。
1 | 49 /** |