[ovs-dev] [netlink v3 09/16] datapath: Make it possible to query vports by name regardless of datapath.

Ben Pfaff blp at nicira.com
Thu Dec 30 00:56:30 UTC 2010


Until now it has only been possible to query a vport if you know what
datapath it is on.  This doesn't really make sense, so this commit removes
that restriction.  It is a little bigger than one might naturally expect
because locking changes are required.

This also allows us to get rid of the ETHTOOL_GDRVINFO kluge that has
bothered me for a long time.  The next commit does that.

Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 datapath/datapath.c                     |   56 ++++++++++++++++++-------------
 include/openvswitch/datapath-protocol.h |    2 +-
 lib/dpif-linux.c                        |   12 +++++-
 3 files changed, 44 insertions(+), 26 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index b0dfb80..d5791d9 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -1341,52 +1341,58 @@ void set_internal_devs_mtu(const struct datapath *dp)
 	}
 }
 
-static int put_port(const struct vport *p, struct odp_port __user *uop)
+static void compose_odp_port(const struct vport *vport, struct odp_port *odp_port)
 {
-	struct odp_port op;
-
-	memset(&op, 0, sizeof op);
-
 	rcu_read_lock();
-	strncpy(op.devname, vport_get_name(p), sizeof op.devname);
-	strncpy(op.type, vport_get_type(p), sizeof op.type);
-	vport_get_config(p, op.config);
+	strncpy(odp_port->devname, vport_get_name(vport), sizeof(odp_port->devname));
+	strncpy(odp_port->type, vport_get_type(vport), sizeof(odp_port->type));
+	vport_get_config(vport, odp_port->config);
+	odp_port->port = vport->port_no;
+	odp_port->dp_idx = vport->dp->dp_idx;
 	rcu_read_unlock();
-
-	op.port = p->port_no;
-
-	return copy_to_user(uop, &op, sizeof op) ? -EFAULT : 0;
 }
 
-static int query_port(struct datapath *dp, struct odp_port __user *uport)
+static int query_port(int dp_idx, struct odp_port __user *uport)
 {
 	struct odp_port port;
-	struct vport *vport;
 
 	if (copy_from_user(&port, uport, sizeof port))
 		return -EFAULT;
 
 	if (port.devname[0]) {
+		struct vport *vport;
+
 		port.devname[IFNAMSIZ - 1] = '\0';
 
 		vport_lock();
 		vport = vport_locate(port.devname);
+		if (vport)
+			compose_odp_port(vport, &port);
 		vport_unlock();
 
 		if (!vport)
 			return -ENODEV;
-		if (vport->dp != dp)
-			return -ENOENT;
 	} else {
+		struct vport *vport;
+		struct datapath *dp;
+
 		if (port.port >= DP_MAX_PORTS)
 			return -EINVAL;
 
+		dp = get_dp_locked(dp_idx);
+		if (!dp)
+			return -ENODEV;
+
 		vport = get_vport_protected(dp, port.port);
+		if (vport)
+			compose_odp_port(vport, &port);
+		mutex_unlock(&dp->mutex);
+
 		if (!vport)
 			return -ENOENT;
 	}
 
-	return put_port(vport, uport);
+	return copy_to_user(uport, &port, sizeof(struct odp_port));
 }
 
 static int do_dump_port(struct datapath *dp, struct odp_vport_dump *dump)
@@ -1395,8 +1401,12 @@ static int do_dump_port(struct datapath *dp, struct odp_vport_dump *dump)
 
 	for (port_no = dump->port_no; port_no < DP_MAX_PORTS; port_no++) {
 		struct vport *vport = dp->ports[port_no];
-		if (vport)
-			return put_port(vport, (struct odp_port __force __user*)dump->port);
+		if (vport) {
+			struct odp_port odp_port;
+
+			compose_odp_port(vport, &odp_port);
+			return copy_to_user((struct odp_port __force __user*)dump->port, &odp_port, sizeof(struct odp_port));
+		}
 	}
 
 	return put_user('\0', (char __force __user*)&dump->port->devname[0]);
@@ -1451,6 +1461,10 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
 			err = detach_port(dp_idx, port_no);
 		goto exit;
 
+	case ODP_VPORT_QUERY:
+		err = query_port(dp_idx, (struct odp_port __user *)argp);
+		goto exit;
+
 	case ODP_VPORT_MOD:
 		err = vport_user_mod((struct odp_port __user *)argp);
 		goto exit;
@@ -1530,10 +1544,6 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
 			dp->sflow_probability = sflow_probability;
 		break;
 
-	case ODP_VPORT_QUERY:
-		err = query_port(dp, (struct odp_port __user *)argp);
-		break;
-
 	case ODP_VPORT_DUMP:
 		err = dump_port(dp, (struct odp_vport_dump __user *)argp);
 		break;
diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h
index 5c0adbf..e4c850c 100644
--- a/include/openvswitch/datapath-protocol.h
+++ b/include/openvswitch/datapath-protocol.h
@@ -179,7 +179,7 @@ struct odp_port {
     char devname[16];           /* IFNAMSIZ */
     char type[VPORT_TYPE_SIZE];
     uint16_t port;
-    uint16_t reserved1;
+    uint16_t dp_idx;
     uint32_t reserved2;
     __aligned_u64 config[VPORT_CONFIG_SIZE / 8]; /* type-specific */
 };
diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index 2908964..5cfe336 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -308,12 +308,20 @@ dpif_linux_port_query_by_number(const struct dpif *dpif, uint16_t port_no,
 }
 
 static int
-dpif_linux_port_query_by_name(const struct dpif *dpif, const char *devname,
+dpif_linux_port_query_by_name(const struct dpif *dpif_, const char *devname,
                               struct odp_port *port)
 {
+    struct dpif_linux *dpif = dpif_linux_cast(dpif_);
+    int error;
+
     memset(port, 0, sizeof *port);
     strncpy(port->devname, devname, sizeof port->devname);
-    return dpif_linux_port_query__(dpif, port);
+    error = dpif_linux_port_query__(dpif_, port);
+    if (!error && port->dp_idx != dpif->minor) {
+        /* A vport named 'devname' exists but in some other datapath.  */
+        error = ENOENT;
+    }
+    return error;
 }
 
 static int
-- 
1.7.1





More information about the dev mailing list