[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