[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