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@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
-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));
-
- 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;
-
- 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)
if (copy_from_user(&port, uport, sizeof(port)))
return -EFAULT;
if (port.devname[0]) {
if (copy_from_user(&port, uport, sizeof(port)))
return -EFAULT;
if (port.devname[0]) {
port.devname[IFNAMSIZ - 1] = '\0';
vport_lock();
vport = vport_locate(port.devname);
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;
vport_unlock();
if (!vport)
return -ENODEV;
- if (vport->dp != dp)
- return -ENOENT;
+ struct vport *vport;
+ struct datapath *dp;
+
if (port.port >= DP_MAX_PORTS)
return -EINVAL;
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);
vport = get_vport_protected(dp, port.port);
+ if (vport)
+ compose_odp_port(vport, &port);
+ mutex_unlock(&dp->mutex);
+
if (!vport)
return -ENOENT;
}
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)
}
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 = get_vport_protected(dp, port_no);
for (port_no = dump->port_no; port_no < DP_MAX_PORTS; port_no++) {
struct vport *vport = get_vport_protected(dp, 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]);
}
return put_user('\0', (char __force __user*)&dump->port->devname[0]);
err = detach_port(dp_idx, port_no);
goto exit;
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;
case ODP_VPORT_MOD:
err = vport_user_mod((struct odp_port __user *)argp);
goto exit;
dp->sflow_probability = sflow_probability;
break;
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;
case ODP_VPORT_DUMP:
err = dump_port(dp, (struct odp_vport_dump __user *)argp);
break;
char devname[16]; /* IFNAMSIZ */
char type[VPORT_TYPE_SIZE];
uint16_t port;
char devname[16]; /* IFNAMSIZ */
char type[VPORT_TYPE_SIZE];
uint16_t port;
uint32_t reserved2;
__aligned_u64 config[VPORT_CONFIG_SIZE / 8]; /* type-specific */
};
uint32_t reserved2;
__aligned_u64 config[VPORT_CONFIG_SIZE / 8]; /* type-specific */
};
-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 dpif_linux *dpif = dpif_linux_cast(dpif_);
+ int error;
+
memset(port, 0, sizeof *port);
strncpy(port->devname, devname, sizeof port->devname);
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;