首页 > 代码库 > Openvswitch原理与代码分析(5): 内核中的流表flow table操作
Openvswitch原理与代码分析(5): 内核中的流表flow table操作
?
当一个数据包到达网卡的时候,首先要经过内核Openvswitch.ko,流表Flow Table在内核中有一份,通过key查找内核中的flow table,即可以得到action,然后执行action之后,直接发送这个包,只有在内核无法查找到流表项的时候,才会到用户态查找用户态的流表。仅仅查找内核中flow table的情况被称为fast path.
?
?
第一步:从数据包中提取出key
?
实现函数为int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, struct sk_buff *skb, struct sw_flow_key *key)
在这个函数中,首先提取的是物理层的信息,主要是从哪个网口进入的。
|
?
然后调用函数static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)提取其他的key
提取MAC层
|
?
提取网络层
|
?
提取传输层
|
?
第二步:根据key查找flow table
?
调用struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *tbl, const struct sw_flow_key *key, u32 skb_hash, u32 *n_mask_hit)进行查找。
?
?
在内核中,flow table的数据结构如上图所示。
每个虚拟交换机对应一个datapath,每个datapath有一个flow table,每个flow table分成N个桶,根据key进行哈希,不同的key分布在不同的桶里面。
每个桶的大小是一个内存页的大小,在内存页的头部保存了保存了多少个元素,每个元素的大小。每个元素都是sw_flow,里面有key,也有action。
?
ovs_flow_tbl_lookup_stats会调用static struct sw_flow *flow_lookup(struct flow_table *tbl, struct table_instance *ti, const struct mask_array *ma, const struct sw_flow_key *key, u32 *n_mask_hit, u32 *index)
会调用masked_flow_lookup如下
|
?
其中flow_hash计算哈希值,find_bucket根据哈希值查找桶,然后就是一个循环,逐个比较key是否相等,相等则返回flow。
?
第三步:执行action
?
调用int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb, const struct sw_flow_actions *acts,struct sw_flow_key *key)
调用static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, struct sw_flow_key *key, const struct nlattr *attr, int len)
在这个函数中,通过case语句,不同的action进行不同的操作。
|
?
如果可以直接输出,则调用static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, struct sw_flow_key *key)他调用void ovs_vport_send(struct vport *vport, struct sk_buff *skb)进行发送。
Openvswitch原理与代码分析(5): 内核中的流表flow table操作