1.datapath的底层数据结构关系
流表采用hash的方式排列存放,流表的hash头结点存储数据结构如下
该hash 桶的初始化函数alloc_buckets (),生成的数据格式可参考如下
2 流表创建流程分析
2.1 flow table数据结构
1> flow_table
流表结构, 每个datapath
都有一个流表
2> table_instance
流表实例, 其中的 buckets 用来存放具体的 flow 条目,存储方式参见FlexArray
3> sw_flow
flow条目, 其中 key 表示报文的特征, 在进行匹配时, 便是从收到的报文中提取 key , 与flow 条目的 key进行比较
4> sw_flow_key
报文特征. 提取报文特征时,会提取每一层的特征.
5> mask_array
流表掩码集合. 老版本OVS只支持exact flow
, 即报文特征必须和flow中描述完全相同才算匹配,而在较新的版本中,支持wildcarded flow
. 可以为 flow中的特征添加掩码。最常见的例子,可以设置 flow条目中源 IP 和 IP 掩码, 只要进行匹配的报文 IP 在掩码作用后的网段内,就认为是通过匹配的。
6> sw_flow_mask
掩码条目。其中 refcount 表明有多少个 flow 正在关联它。
7> sw_flow_match
在匹配过程中使用的结构
2.2 创建流表
用户态通过netlink 进行datapath 流表更新的入口函数都定义在dp_flow_genl_ops中,流表创建的入口函数是ovs_flow_cmd_new 函数,代码分析如下:
static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = sock_net(skb->sk);
struct nlattr **a = info->attrs;
struct ovs_header *ovs_header = info->userhdr;
struct sw_flow *flow = NULL, *new_flow;
struct sw_flow_mask mask;
struct sk_buff *reply;
struct datapath *dp;
struct sw_flow_actions *acts;
struct sw_flow_match match;
u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
int error;
bool log = !a[OVS_FLOW_ATTR_PROBE];