diff options
Diffstat (limited to 'datapath/datapath.c')
-rw-r--r-- | datapath/datapath.c | 130 |
1 files changed, 29 insertions, 101 deletions
diff --git a/datapath/datapath.c b/datapath/datapath.c index da96e3ee..0f59e9ae 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -779,7 +779,6 @@ static void get_stats(struct sw_flow *flow, struct odp_flow_stats *stats) stats->n_bytes = flow->byte_count; stats->reserved = 0; stats->tcp_flags = flow->tcp_flags; - stats->error = 0; } static void clear_stats(struct sw_flow *flow) @@ -1017,55 +1016,25 @@ static int del_flow(struct datapath *dp, struct odp_flow __user *ufp) return error; } -static int do_query_flows(struct datapath *dp, const struct odp_flowvec *flowvec) +static int query_flow(struct datapath *dp, struct odp_flow __user *uflow) { struct tbl *table = get_table_protected(dp); - u32 i; - - for (i = 0; i < flowvec->n_flows; i++) { - struct odp_flow __user *ufp = (struct odp_flow __user __force *)&flowvec->flows[i]; - struct sw_flow_key key; - struct odp_flow uf; - struct tbl_node *flow_node; - int error; - - if (copy_from_user(&uf, ufp, sizeof(uf))) - return -EFAULT; - - error = flow_copy_from_user(&key, (const struct nlattr __force __user *)uf.key, uf.key_len); - if (error) - return error; - - flow_node = tbl_lookup(table, &uf.key, flow_hash(&key), flow_cmp); - if (!flow_node) - error = put_user(ENOENT, &ufp->stats.error); - else - error = answer_query(dp, flow_cast(flow_node), uf.flags, ufp); - if (error) - return -EFAULT; - } - return flowvec->n_flows; -} - -static int do_flowvec_ioctl(struct datapath *dp, unsigned long argp, - int (*function)(struct datapath *, - const struct odp_flowvec *)) -{ - struct odp_flowvec __user *uflowvec; - struct odp_flowvec flowvec; - int retval; + struct tbl_node *flow_node; + struct sw_flow_key key; + struct odp_flow flow; + int error; - uflowvec = (struct odp_flowvec __user *)argp; - if (copy_from_user(&flowvec, uflowvec, sizeof(flowvec))) + if (copy_from_user(&flow, uflow, sizeof(flow))) return -EFAULT; - if (flowvec.n_flows > INT_MAX / sizeof(struct odp_flow)) - return -EINVAL; + error = flow_copy_from_user(&key, (const struct nlattr __force __user *)flow.key, flow.key_len); + if (error) + return error; - retval = function(dp, &flowvec); - return (retval < 0 ? retval - : retval == flowvec.n_flows ? 0 - : put_user(retval, &uflowvec->n_flows)); + flow_node = tbl_lookup(table, &flow.key, flow_hash(&key), flow_cmp); + if (!flow_node) + return -ENOENT; + return answer_query(dp, flow_cast(flow_node), flow.flags, uflow); } static struct sw_flow *do_dump_flow(struct datapath *dp, u32 __user *state) @@ -1769,7 +1738,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, break; case ODP_FLOW_GET: - err = do_flowvec_ioctl(dp, argp, do_query_flows); + err = query_flow(dp, (struct odp_flow __user *)argp); break; case ODP_FLOW_DUMP: @@ -1870,37 +1839,25 @@ static int compat_del_flow(struct datapath *dp, struct compat_odp_flow __user *u return error; } -static int compat_query_flows(struct datapath *dp, - struct compat_odp_flow __user *flows, - u32 n_flows) +static int compat_query_flow(struct datapath *dp, struct compat_odp_flow __user *uflow) { struct tbl *table = get_table_protected(dp); - u32 i; - - for (i = 0; i < n_flows; i++) { - struct compat_odp_flow __user *ufp = &flows[i]; - struct odp_flow uf; - struct tbl_node *flow_node; - struct sw_flow_key key; - int error; + struct tbl_node *flow_node; + struct sw_flow_key key; + struct odp_flow flow; + int error; - if (compat_get_flow(&uf, ufp)) - return -EFAULT; + if (compat_get_flow(&flow, uflow)) + return -EFAULT; - error = flow_copy_from_user(&key, (const struct nlattr __force __user *) uf.key, uf.key_len); - if (error) - return error; + 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) - error = put_user(ENOENT, &ufp->stats.error); - else - error = compat_answer_query(dp, flow_cast(flow_node), - uf.flags, ufp); - if (error) - return -EFAULT; - } - return n_flows; + 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) @@ -1936,35 +1893,6 @@ static int compat_dump_flow(struct datapath *dp, struct compat_odp_flow_dump __u return compat_answer_query(dp, flow, 0, uflowp); } -static int compat_flowvec_ioctl(struct datapath *dp, unsigned long argp, - int (*function)(struct datapath *, - struct compat_odp_flow __user *, - u32 n_flows)) -{ - struct compat_odp_flowvec __user *uflowvec; - struct compat_odp_flow __user *flows; - struct compat_odp_flowvec flowvec; - int retval; - - uflowvec = compat_ptr(argp); - if (!access_ok(VERIFY_WRITE, uflowvec, sizeof(*uflowvec)) || - copy_from_user(&flowvec, uflowvec, sizeof(flowvec))) - return -EFAULT; - - if (flowvec.n_flows > INT_MAX / sizeof(struct compat_odp_flow)) - return -EINVAL; - - flows = compat_ptr(flowvec.flows); - if (!access_ok(VERIFY_WRITE, flows, - flowvec.n_flows * sizeof(struct compat_odp_flow))) - return -EFAULT; - - retval = function(dp, flows, flowvec.n_flows); - return (retval < 0 ? retval - : retval == flowvec.n_flows ? 0 - : put_user(retval, &uflowvec->n_flows)); -} - static int compat_execute(struct datapath *dp, const struct compat_odp_execute __user *uexecute) { struct odp_execute execute; @@ -2028,7 +1956,7 @@ static long openvswitch_compat_ioctl(struct file *f, unsigned int cmd, unsigned break; case ODP_FLOW_GET32: - err = compat_flowvec_ioctl(dp, argp, compat_query_flows); + err = compat_query_flow(dp, compat_ptr(argp)); break; case ODP_FLOW_DUMP32: |