[ovs-dev] [netlink v4 40/52] datapath: Convert ODP_FLOW_* and ODP_EXECUTE to put dp_idx into message.
Ben Pfaff
blp at nicira.com
Wed Jan 12 05:49:52 UTC 2011
When the datapath moves to the Netlink protocol it won't have a minor
number to use, so we have to put the dp_idx in the message.
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
datapath/datapath.c | 268 +++++++++++++++++++------------
datapath/odp-compat.h | 4 +
include/openvswitch/datapath-protocol.h | 4 +
lib/dpif-linux.c | 13 ++-
4 files changed, 184 insertions(+), 105 deletions(-)
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 4456ec8..ff2a6b8 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -641,20 +641,34 @@ err:
return err;
}
-static int flush_flows(struct datapath *dp)
+static int flush_flows(int dp_idx)
{
- struct tbl *old_table = get_table_protected(dp);
+ struct tbl *old_table;
struct tbl *new_table;
+ struct datapath *dp;
+ int err;
+
+ dp = get_dp_locked(dp_idx);
+ err = -ENODEV;
+ if (!dp)
+ goto exit;
+ old_table = get_table_protected(dp);
new_table = tbl_create(TBL_MIN_BUCKETS);
+ err = -ENOMEM;
if (!new_table)
- return -ENOMEM;
+ goto exit_unlock;
rcu_assign_pointer(dp->table, new_table);
tbl_deferred_destroy(old_table, flow_free_tbl);
- return 0;
+ err = 0;
+
+exit_unlock:
+ mutex_unlock(&dp->mutex);
+exit:
+ return err;
}
static int validate_actions(const struct nlattr *actions, u32 actions_len)
@@ -904,24 +918,29 @@ error:
return error;
}
-static int put_flow(struct datapath *dp, struct odp_flow_put __user *ufp)
+static int put_flow(struct odp_flow_put __user *ufp)
{
struct odp_flow_stats stats;
struct odp_flow_put uf;
+ struct datapath *dp;
int error;
if (copy_from_user(&uf, ufp, sizeof(struct odp_flow_put)))
return -EFAULT;
- error = do_put_flow(dp, &uf, &stats);
- if (error)
- return error;
+ dp = get_dp_locked(uf.flow.dp_idx);
+ if (!dp)
+ return -ENODEV;
- if (copy_to_user(&ufp->flow.stats, &stats,
- sizeof(struct odp_flow_stats)))
- return -EFAULT;
+ error = do_put_flow(dp, &uf, &stats);
+ if (!error) {
+ if (copy_to_user(&ufp->flow.stats, &stats,
+ sizeof(struct odp_flow_stats)))
+ error = -EFAULT;
+ }
+ mutex_unlock(&dp->mutex);
- return 0;
+ return error;
}
static int do_answer_query(struct datapath *dp, struct sw_flow *flow,
@@ -992,90 +1011,106 @@ static struct sw_flow *do_del_flow(struct datapath *dp, const struct nlattr __us
return flow_cast(flow_node);
}
-static int del_flow(struct datapath *dp, struct odp_flow __user *ufp)
+static int del_flow(struct odp_flow __user *ufp)
{
struct sw_flow *flow;
+ struct datapath *dp;
struct odp_flow uf;
int error;
if (copy_from_user(&uf, ufp, sizeof uf))
return -EFAULT;
+ dp = get_dp_locked(uf.dp_idx);
+ if (!dp)
+ return -ENODEV;
+
flow = do_del_flow(dp, (const struct nlattr __force __user *)uf.key, uf.key_len);
- if (IS_ERR(flow))
- return PTR_ERR(flow);
+ error = PTR_ERR(flow);
+ if (!IS_ERR(flow)) {
+ error = answer_query(dp, flow, ufp);
+ flow_deferred_free(flow);
+ }
+ mutex_unlock(&dp->mutex);
- error = answer_query(dp, flow, ufp);
- flow_deferred_free(flow);
return error;
}
-static int query_flow(struct datapath *dp, struct odp_flow __user *uflow)
+static int query_flow(struct 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;
+ struct datapath *dp;
int error;
if (copy_from_user(&flow, uflow, sizeof flow))
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, &flow.key, flow_hash(&key), flow_cmp);
- if (!flow_node)
- return -ENOENT;
- return answer_query(dp, flow_cast(flow_node), uflow);
-}
-
-static struct sw_flow *do_dump_flow(struct datapath *dp, u32 __user *state)
-{
- struct tbl *table = get_table_protected(dp);
- struct tbl_node *tbl_node;
- u32 bucket, obj;
-
- if (get_user(bucket, &state[0]) || get_user(obj, &state[1]))
- return ERR_PTR(-EFAULT);
-
- tbl_node = tbl_next(table, &bucket, &obj);
+ dp = get_dp_locked(flow.dp_idx);
+ if (!dp)
+ return -ENODEV;
- if (put_user(bucket, &state[0]) || put_user(obj, &state[1]))
- return ERR_PTR(-EFAULT);
+ error = flow_copy_from_user(&key, (const struct nlattr __force __user *)flow.key, flow.key_len);
+ if (!error) {
+ flow_node = tbl_lookup(dp->table, &flow.key, flow_hash(&key), flow_cmp);
+ if (flow_node)
+ error = answer_query(dp, flow_cast(flow_node), uflow);
+ else
+ error = -ENOENT;
+ }
+ mutex_unlock(&dp->mutex);
- return tbl_node ? flow_cast(tbl_node) : NULL;
+ return error;
}
-static int dump_flow(struct datapath *dp, struct odp_flow_dump __user *udumpp)
+static int dump_flow(struct datapath *dp, struct odp_flow_dump __user *udump)
{
- struct odp_flow __user *uflowp;
+ struct odp_flow __user *uflow;
struct nlattr __user *ukey;
+ struct tbl_node *tbl_node;
+ struct odp_flow_dump dump;
struct sw_flow *flow;
u32 key_len;
+ int err;
- flow = do_dump_flow(dp, udumpp->state);
- if (IS_ERR(flow))
- return PTR_ERR(flow);
+ err = -EFAULT;
+ if (copy_from_user(&dump, udump, sizeof(struct odp_flow_dump)))
+ goto exit;
+ uflow = (struct odp_flow __user __force *)dump.flow;
- if (get_user(uflowp, (struct odp_flow __user *__user*)&udumpp->flow))
- return -EFAULT;
+ dp = get_dp_locked(dump.dp_idx);
+ err = -ENODEV;
+ if (!dp)
+ goto exit;
- if (!flow)
- return put_user(0, &uflowp->key_len);
+ tbl_node = tbl_next(dp->table, &dump.state[0], &dump.state[1]);
+ if (!tbl_node) {
+ err = put_user(0, &uflow->key_len);
+ goto exit_unlock;
+ }
+ flow = flow_cast(tbl_node);
- if (get_user(ukey, (struct nlattr __user * __user*)&uflowp->key) ||
- get_user(key_len, &uflowp->key_len))
- return -EFAULT;
+ err = -EFAULT;
+ if (copy_to_user(udump->state, dump.state, 2 * sizeof(uint32_t)) ||
+ get_user(ukey, (struct nlattr __user * __user*)&uflow->key) ||
+ get_user(key_len, &uflow->key_len))
+ goto exit_unlock;
key_len = flow_copy_to_user(ukey, &flow->key, key_len);
+ err = key_len;
if (key_len < 0)
- return key_len;
- if (put_user(key_len, &uflowp->key_len))
- return -EFAULT;
+ goto exit_unlock;
+ err = -EFAULT;
+ if (put_user(key_len, &uflow->key_len))
+ goto exit_unlock;
+
+ err = answer_query(dp, flow, uflow);
- return answer_query(dp, flow, uflowp);
+exit_unlock:
+ mutex_unlock(&dp->mutex);
+exit:
+ return err;
}
static int do_execute(struct datapath *dp, const struct odp_execute *execute)
@@ -1147,14 +1182,22 @@ error:
return err;
}
-static int execute_packet(struct datapath *dp, const struct odp_execute __user *executep)
+static int execute_packet(const struct odp_execute __user *executep)
{
struct odp_execute execute;
+ struct datapath *dp;
+ int error;
if (copy_from_user(&execute, executep, sizeof execute))
return -EFAULT;
- return do_execute(dp, &execute);
+ dp = get_dp_locked(execute.dp_idx);
+ if (!dp)
+ return -ENODEV;
+ error = do_execute(dp, &execute);
+ mutex_unlock(&dp->mutex);
+
+ return error;
}
static int get_dp_stats(struct datapath *dp, struct odp_stats __user *statsp)
@@ -1619,6 +1662,30 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
case ODP_VPORT_DUMP:
err = dump_vport((struct odp_vport __user *)argp);
goto exit;
+
+ case ODP_FLOW_FLUSH:
+ err = flush_flows(argp);
+ goto exit;
+
+ case ODP_FLOW_PUT:
+ err = put_flow((struct odp_flow_put __user *)argp);
+ goto exit;
+
+ case ODP_FLOW_DEL:
+ err = del_flow((struct odp_flow __user *)argp);
+ goto exit;
+
+ case ODP_FLOW_GET:
+ err = query_flow((struct odp_flow __user *)argp);
+ goto exit;
+
+ case ODP_FLOW_DUMP:
+ err = dump_flow(dp, (struct odp_flow_dump __user *)argp);
+ goto exit;
+
+ case ODP_EXECUTE:
+ err = execute_packet((struct odp_execute __user *)argp);
+ goto exit;
}
dp = get_dp_locked(dp_idx);
@@ -1671,30 +1738,6 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
dp->sflow_probability = sflow_probability;
break;
- case ODP_FLOW_FLUSH:
- err = flush_flows(dp);
- break;
-
- case ODP_FLOW_PUT:
- err = put_flow(dp, (struct odp_flow_put __user *)argp);
- break;
-
- case ODP_FLOW_DEL:
- err = del_flow(dp, (struct odp_flow __user *)argp);
- break;
-
- case ODP_FLOW_GET:
- err = query_flow(dp, (struct odp_flow __user *)argp);
- break;
-
- case ODP_FLOW_DUMP:
- err = dump_flow(dp, (struct odp_flow_dump __user *)argp);
- break;
-
- case ODP_EXECUTE:
- err = execute_packet(dp, (struct odp_execute __user *)argp);
- break;
-
default:
err = -ENOIOCTLCMD;
break;
@@ -1804,36 +1847,53 @@ static int compat_query_flow(struct datapath *dp, struct compat_odp_flow __user
return compat_answer_query(dp, flow_cast(flow_node), uflow);
}
-static int compat_dump_flow(struct datapath *dp, struct compat_odp_flow_dump __user *udumpp)
+static int compat_dump_flow(struct datapath *dp, struct compat_odp_flow_dump __user *udump)
{
- struct compat_odp_flow __user *uflowp;
- compat_uptr_t compat_ufp;
+ struct compat_odp_flow_dump dump;
+ struct compat_odp_flow __user *uflow;
+ struct nlattr __user *ukey;
+ struct tbl_node *tbl_node;
struct sw_flow *flow;
- compat_uptr_t ukey;
u32 key_len;
+ int err;
- flow = do_dump_flow(dp, udumpp->state);
- if (IS_ERR(flow))
- return PTR_ERR(flow);
+ err = -EFAULT;
+ if (copy_from_user(&dump, udump, sizeof(struct compat_odp_flow_dump)))
+ goto exit;
+ uflow = compat_ptr(dump.flow);
- if (get_user(compat_ufp, &udumpp->flow))
- return -EFAULT;
- uflowp = compat_ptr(compat_ufp);
+ dp = get_dp_locked(dump.dp_idx);
+ err = -ENODEV;
+ if (!dp)
+ goto exit;
- if (!flow)
- return put_user(0, &uflowp->key_len);
+ tbl_node = tbl_next(dp->table, &dump.state[0], &dump.state[1]);
+ if (!tbl_node) {
+ err = put_user(0, &uflow->key_len);
+ goto exit_unlock;
+ }
+ flow = flow_cast(tbl_node);
- if (get_user(ukey, &uflowp->key) ||
- get_user(key_len, &uflowp->key_len))
- return -EFAULT;
+ err = -EFAULT;
+ if (copy_to_user(udump->state, dump.state, 2 * sizeof(uint32_t)) ||
+ get_user(ukey, (struct nlattr __user * __user*)&uflow->key) ||
+ get_user(key_len, &uflow->key_len))
+ goto exit_unlock;
- key_len = flow_copy_to_user(compat_ptr(ukey), &flow->key, key_len);
+ key_len = flow_copy_to_user(ukey, &flow->key, key_len);
+ err = key_len;
if (key_len < 0)
- return key_len;
- if (put_user(key_len, &uflowp->key_len))
- return -EFAULT;
+ goto exit_unlock;
+ err = -EFAULT;
+ if (put_user(key_len, &uflow->key_len))
+ goto exit_unlock;
+
+ err = compat_answer_query(dp, flow, uflow);
- return compat_answer_query(dp, flow, uflowp);
+exit_unlock:
+ mutex_unlock(&dp->mutex);
+exit:
+ return err;
}
static int compat_execute(struct datapath *dp, const struct compat_odp_execute __user *uexecute)
diff --git a/datapath/odp-compat.h b/datapath/odp-compat.h
index bccfaf9..2f595db 100644
--- a/datapath/odp-compat.h
+++ b/datapath/odp-compat.h
@@ -23,6 +23,7 @@
#define ODP_FLOW_DEL32 _IOWR('O', 17, struct compat_odp_flow)
struct compat_odp_flow {
+ int32_t dp_idx;
struct odp_flow_stats stats;
compat_uptr_t key;
u32 key_len;
@@ -36,11 +37,14 @@ struct compat_odp_flow_put {
};
struct compat_odp_flow_dump {
+ int32_t dp_idx;
compat_uptr_t flow;
uint32_t state[2];
};
struct compat_odp_execute {
+ int32_t dp_idx;
+
compat_uptr_t actions;
u32 actions_len;
diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h
index f852345..fbd32d1 100644
--- a/include/openvswitch/datapath-protocol.h
+++ b/include/openvswitch/datapath-protocol.h
@@ -272,6 +272,7 @@ struct odp_key_arp {
};
struct odp_flow {
+ int32_t dp_idx;
struct odp_flow_stats stats;
struct nlattr *key;
uint32_t key_len;
@@ -301,6 +302,7 @@ struct odp_flow_put {
* unspecified.
*/
struct odp_flow_dump {
+ int32_t dp_idx;
struct odp_flow *flow;
uint32_t state[2];
};
@@ -329,6 +331,8 @@ enum odp_action_type {
#define ODPAT_MAX (__ODPAT_MAX - 1)
struct odp_execute {
+ int32_t dp_idx;
+
struct nlattr *actions;
uint32_t actions_len;
diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index 13967b3..852b468 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -473,11 +473,13 @@ dpif_linux_flow_get(const struct dpif *dpif_,
const struct nlattr *key, size_t key_len,
struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
struct ofpbuf *actions = NULL;
struct odp_flow odp_flow;
int error;
memset(&odp_flow, 0, sizeof odp_flow);
+ odp_flow.dp_idx = dpif->minor;
odp_flow.key = (struct nlattr *) key;
odp_flow.key_len = key_len;
if (actionsp) {
@@ -509,10 +511,12 @@ dpif_linux_flow_put(struct dpif *dpif_, enum dpif_flow_put_flags flags,
const struct nlattr *actions, size_t actions_len,
struct dpif_flow_stats *stats)
{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
struct odp_flow_put put;
int error;
memset(&put, 0, sizeof put);
+ put.flow.dp_idx = dpif->minor;
put.flow.key = (struct nlattr *) key;
put.flow.key_len = key_len;
put.flow.actions = (struct nlattr *) actions;
@@ -539,10 +543,12 @@ dpif_linux_flow_del(struct dpif *dpif_,
const struct nlattr *key, size_t key_len,
struct dpif_flow_stats *stats)
{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
struct odp_flow odp_flow;
int error;
memset(&odp_flow, 0, sizeof odp_flow);
+ odp_flow.dp_idx = dpif->minor;
odp_flow.key = (struct nlattr *) key;
odp_flow.key_len = key_len;
error = do_ioctl(dpif_, ODP_FLOW_DEL, &odp_flow);
@@ -561,11 +567,13 @@ struct dpif_linux_flow_state {
};
static int
-dpif_linux_flow_dump_start(const struct dpif *dpif OVS_UNUSED, void **statep)
+dpif_linux_flow_dump_start(const struct dpif *dpif_, void **statep)
{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
struct dpif_linux_flow_state *state;
*statep = state = xmalloc(sizeof *state);
+ state->dump.dp_idx = dpif->minor;
state->dump.state[0] = 0;
state->dump.state[1] = 0;
state->dump.flow = &state->flow;
@@ -623,8 +631,11 @@ dpif_linux_execute(struct dpif *dpif_,
const struct nlattr *actions, size_t actions_len,
const struct ofpbuf *buf)
{
+ struct dpif_linux *dpif = dpif_linux_cast(dpif_);
struct odp_execute execute;
+
memset(&execute, 0, sizeof execute);
+ execute.dp_idx = dpif->minor;
execute.actions = (struct nlattr *) actions;
execute.actions_len = actions_len;
execute.data = buf->data;
--
1.7.1
More information about the dev
mailing list