【OVS2.5.0源码分析】datapath之流表创建过程
来源:互联网 发布:天天炫斗刷钻石软件 编辑:程序博客网 时间:2024/05/21 22:28
上一篇分析了流表查找过程,支撑流表查询的相关信息是什么时候建立,是怎么建立的将在本篇分析。 datapath流表更新的入口函数都定义在dp_flow_genl_ops中,流表创建的入口函数是ovs_flow_cmd_new函数,通过该函数,我们可以一窥流表相关信息的建立。
1、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_key key;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];/* Must have key and actions. */error = -EINVAL;if (!a[OVS_FLOW_ATTR_KEY]) {OVS_NLERR(log, "Flow key attr not present in new flow.");goto error;}if (!a[OVS_FLOW_ATTR_ACTIONS]) {OVS_NLERR(log, "Flow actions attr not present in new flow.");goto error;}/* Most of the time we need to allocate a new flow, do it before * locking. */new_flow = ovs_flow_alloc();if (IS_ERR(new_flow)) {error = PTR_ERR(new_flow);goto error;}/* Extract key. */ovs_match_init(&match, &key, &mask);error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], //完成key和match的信息设置 a[OVS_FLOW_ATTR_MASK], log);if (error)goto err_kfree_flow;ovs_flow_mask_key(&new_flow->key, &key, true, &mask); //根据key和mask,生成masked key/* Extract flow identifier. */error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID], &key, log);if (error)goto err_kfree_flow;/* Validate actions. */error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS], &new_flow->key, &acts, log);if (error) {OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");goto err_kfree_flow;}reply = ovs_flow_cmd_alloc_info(acts, &new_flow->id, info, false,ufid_flags);if (IS_ERR(reply)) {error = PTR_ERR(reply);goto err_kfree_acts;}ovs_lock();dp = get_dp(net, ovs_header->dp_ifindex); if (unlikely(!dp)) {error = -ENODEV;goto err_unlock_ovs;}/* Check if this is a duplicate flow */if (ovs_identifier_is_ufid(&new_flow->id))flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id);if (!flow)flow = ovs_flow_tbl_lookup(&dp->table, &key); //查找流表,正常情况是查不到的if (likely(!flow)) {rcu_assign_pointer(new_flow->sf_acts, acts);/* Put flow in bucket. */error = ovs_flow_tbl_insert(&dp->table, new_flow, &mask); //插入流表if (unlikely(error)) {acts = NULL;goto err_unlock_ovs;}if (unlikely(reply)) {error = ovs_flow_cmd_fill_info(new_flow, ovs_header->dp_ifindex, reply, info->snd_portid, info->snd_seq, 0, OVS_FLOW_CMD_NEW, ufid_flags);BUG_ON(error < 0);}ovs_unlock();} else {struct sw_flow_actions *old_acts;/* Bail out if we're not allowed to modify an existing flow. * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL * because Generic Netlink treats the latter as a dump * request. We also accept NLM_F_EXCL in case that bug ever * gets fixed. */if (unlikely(info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL))) {error = -EEXIST;goto err_unlock_ovs;}/* The flow identifier has to be the same for flow updates. * Look for any overlapping flow. */if (unlikely(!ovs_flow_cmp(flow, &match))) {if (ovs_identifier_is_key(&flow->id))flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);else /* UFID matches but key is different */flow = NULL;if (!flow) {error = -ENOENT;goto err_unlock_ovs;}}/* Update actions. */old_acts = ovsl_dereference(flow->sf_acts);rcu_assign_pointer(flow->sf_acts, acts);if (unlikely(reply)) {error = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex, reply, info->snd_portid, info->snd_seq, 0, OVS_FLOW_CMD_NEW, ufid_flags);BUG_ON(error < 0);}ovs_unlock();ovs_nla_free_flow_actions_rcu(old_acts);ovs_flow_free(new_flow, false);}if (reply)ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info);return 0;err_unlock_ovs:ovs_unlock();kfree_skb(reply);err_kfree_acts:ovs_nla_free_flow_actions(acts);err_kfree_flow:ovs_flow_free(new_flow, false);error:return error;}2、ovs_flow_tbl_insert函数
/* Must be called with OVS mutex held. */int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,const struct sw_flow_mask *mask){int err;err = flow_mask_insert(table, flow, mask); //插入maskif (err)return err;flow_key_insert(table, flow); //插入flowif (ovs_identifier_is_ufid(&flow->id))flow_ufid_insert(table, flow);return 0;}3、flow_mask_insert函数
static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow, const struct sw_flow_mask *new){struct sw_flow_mask *mask;mask = flow_mask_find(tbl, new);if (!mask) {struct mask_array *ma;int i;/* Allocate a new mask if none exsits. */mask = mask_alloc(); //新创建maskif (!mask)return -ENOMEM;mask->key = new->key; //mask复制mask->range = new->range; //mask复制/* Add mask to mask-list. */ma = ovsl_dereference(tbl->mask_array);if (ma->count >= ma->max) {int err;err = tbl_mask_array_realloc(tbl, ma->max + MASK_ARRAY_SIZE_MIN);if (err) {kfree(mask);return err;}ma = ovsl_dereference(tbl->mask_array);}for (i = 0; i < ma->max; i++) {struct sw_flow_mask *t;t = ovsl_dereference(ma->masks[i]);if (!t) {rcu_assign_pointer(ma->masks[i], mask); //maks保存到mask_array中,流表查找中的mask_array构造完成ma->count++;break;}}} else {BUG_ON(!mask->ref_count);mask->ref_count++;}flow->mask = mask; //flow的mask指针指向新的maskreturn 0;}4、flow_key_insert函数
static void flow_key_insert(struct flow_table *table, struct sw_flow *flow){struct table_instance *new_ti = NULL;struct table_instance *ti;flow->flow_table.hash = flow_hash(&flow->key, &flow->mask->range); //计算hash值ti = ovsl_dereference(table->ti);table_instance_insert(ti, flow);//flow插入到ti中table->count++;/* Expand table, if necessary, to make room. */if (table->count > ti->n_buckets)new_ti = table_instance_expand(ti, false);else if (time_after(jiffies, table->last_rehash + REHASH_INTERVAL))new_ti = table_instance_rehash(ti, ti->n_buckets, false); //为什么要刷新,还不是很清晰,希望等整体分析完成后能够解答if (new_ti) {rcu_assign_pointer(table->ti, new_ti);call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);table->last_rehash = jiffies;}}5、table_instance_insert函数
static void table_instance_insert(struct table_instance *ti, struct sw_flow *flow){struct hlist_head *head;head = find_bucket(ti, flow->flow_table.hash); //通过hash值找到flow list headhlist_add_head_rcu(&flow->flow_table.node[ti->node_ver], head); //flow插入到队列前头}
到这,datapath中流表查询的数据已经建立完成。
0 0
- 【OVS2.5.0源码分析】datapath之流表创建过程
- 【OVS2.5.0源码分析】datapath之流表查询
- 【OVS2.5.0源码分析】datapath之netlink
- 【OVS2.5.0源码分析】datapath之主流程分析
- 【OVS2.5.0源码分析】datapath之action分析(1)
- 【OVS2.5.0源码分析】datapath之action分析(2)
- 【OVS2.5.0源码分析】datapath之action分析(3)
- 【OVS2.5.0源码分析】datapath之action分析(4)
- 【OVS2.5.0源码分析】datapath之action分析(5)
- 【OVS2.5.0源码分析】datapath之action分析(6)
- 【OVS2.5.0源码分析】datapath之action分析(7)
- 【OVS2.5.0源码分析】datapath之action分析(8)
- 【OVS2.5源码解读】datapath主流程分析
- 【OVS2.5.0源码分析】vxlan端口创建流程分析
- 【OVS2.5.0源码分析】enqueue action精确流表生成过程分析
- 【OVS2.5.0源码分析】normal action精确流表生成和刷新过程分析
- 【OVS2.5.0源码分析】ofpbuf数据结构分析
- 【OVS2.5.0源码分析】nlattr数据结构分析
- Oracle:SQL语句--撤销用户权限
- 关于Oracle的PARALLEL_MAX_SEVERS参数
- LeetCode: Super Ugly Number
- java.lang.NullPointerException
- QtCreator2.8.0+QtOpenSource4.8.5环境配置(初学者必看)
- 【OVS2.5.0源码分析】datapath之流表创建过程
- iBator 数据库操作
- Android 捕获全局异常
- 背包实现
- ip 子网数目 网络号 主机号 广播地址 可用IP地址范围
- 高级Bash脚本编程指南(2):带着一个Sha-Bang出发
- java 多线程2
- ScrollView与RelativeLayout一起用,显示有问题的解决方法
- ReadImport