- return 0;
-}
-
-#ifdef CONFIG_COMPAT
-static int compat_get_flow(struct odp_flow *flow, const struct compat_odp_flow __user *compat)
-{
- compat_uptr_t key, actions;
-
- if (!access_ok(VERIFY_READ, compat, sizeof(struct compat_odp_flow)) ||
- __copy_from_user(&flow->stats, &compat->stats, sizeof(struct odp_flow_stats)) ||
- __get_user(key, &compat->key) ||
- __get_user(flow->key_len, &compat->key_len) ||
- __get_user(actions, &compat->actions) ||
- __get_user(flow->actions_len, &compat->actions_len) ||
- __get_user(flow->flags, &compat->flags))
- return -EFAULT;
-
- flow->key = (struct nlattr __force *)compat_ptr(key);
- flow->actions = (struct nlattr __force *)compat_ptr(actions);
- return 0;
-}
-
-static int compat_put_flow(struct datapath *dp, struct compat_odp_flow_put __user *ufp)
-{
- struct odp_flow_stats stats;
- struct odp_flow_put fp;
- int error;
-
- if (compat_get_flow(&fp.flow, &ufp->flow) ||
- get_user(fp.flags, &ufp->flags))
- return -EFAULT;
-
- error = do_put_flow(dp, &fp, &stats);
- if (error)
- return error;
-
- if (copy_to_user(&ufp->flow.stats, &stats,
- sizeof(struct odp_flow_stats)))
- return -EFAULT;
-
- return 0;
-}
-
-static int compat_answer_query(struct datapath *dp, struct sw_flow *flow,
- u32 query_flags,
- struct compat_odp_flow __user *ufp)
-{
- compat_uptr_t actions;
-
- if (get_user(actions, &ufp->actions))
- return -EFAULT;
-
- return do_answer_query(dp, flow, query_flags, &ufp->stats,
- compat_ptr(actions), &ufp->actions_len);
-}
-
-static int compat_del_flow(struct datapath *dp, struct compat_odp_flow __user *ufp)
-{
- struct sw_flow *flow;
- struct odp_flow uf;
- int error;
-
- if (compat_get_flow(&uf, ufp))
- return -EFAULT;
-
- flow = do_del_flow(dp, (const struct nlattr __force __user *)uf.key, uf.key_len);
- if (IS_ERR(flow))
- return PTR_ERR(flow);
-
- error = compat_answer_query(dp, flow, 0, ufp);
- flow_deferred_free(flow);
- return error;
-}
-
-static int compat_query_flow(struct datapath *dp, struct compat_odp_flow __user *uflow)
-{
- struct tbl *table = get_table_protected(dp);
- struct tbl_node *flow_node;
- struct sw_flow_key key;
- struct odp_flow flow;
- int error;
-
- if (compat_get_flow(&flow, uflow))
- return -EFAULT;
-
- error = flow_copy_from_user(&key, (const struct nlattr __force __user *)flow.key, flow.key_len);
- if (error)
- return error;
-
- flow_node = tbl_lookup(table, &key, flow_hash(&key), flow_cmp);
- if (!flow_node)
- return -ENOENT;
- return compat_answer_query(dp, flow_cast(flow_node), flow.flags, uflow);
-}
-
-static int compat_dump_flow(struct datapath *dp, struct compat_odp_flow_dump __user *udumpp)
-{
- struct compat_odp_flow __user *uflowp;
- compat_uptr_t compat_ufp;
- struct sw_flow *flow;
- compat_uptr_t ukey;
- u32 key_len;
-
- flow = do_dump_flow(dp, udumpp->state);
- if (IS_ERR(flow))
- return PTR_ERR(flow);
-
- if (get_user(compat_ufp, &udumpp->flow))
- return -EFAULT;
- uflowp = compat_ptr(compat_ufp);
-
- if (!flow)
- return put_user(ODPFF_EOF, &uflowp->flags);
-
- if (put_user(0, &uflowp->flags) ||
- get_user(ukey, &uflowp->key) ||
- get_user(key_len, &uflowp->key_len))
- return -EFAULT;