#include "vlog.h"
#define THIS_MODULE VLM_dpif
+/* A datapath interface. */
+struct dpif {
+ char *name;
+ unsigned int minor;
+ int fd;
+};
+
/* Rate limit for individual messages going to or from the datapath, output at
* DBG level. This is very high because, if these are enabled, it is because
* we really need to see them. */
static int get_minor_from_name(const char *name, unsigned int *minor);
static int name_to_minor(const char *name, unsigned int *minor);
static int lookup_minor(const char *name, unsigned int *minor);
-static int open_by_minor(unsigned int minor, struct dpif *);
+static int open_by_minor(unsigned int minor, struct dpif **dpifp);
static int make_openvswitch_device(unsigned int minor, char **fnp);
static void check_rw_odp_flow(struct odp_flow *);
int
-dpif_open(const char *name, struct dpif *dpif)
+dpif_open(const char *name, struct dpif **dpifp)
{
+ struct dpif *dpif;
+ unsigned int minor;
int listen_mask;
int error;
- dpif->fd = -1;
+ *dpifp = NULL;
- error = name_to_minor(name, &dpif->minor);
+ error = name_to_minor(name, &minor);
if (error) {
return error;
}
- error = open_by_minor(dpif->minor, dpif);
+ error = open_by_minor(minor, &dpif);
if (error) {
return error;
}
if (ioctl(dpif->fd, ODP_GET_LISTEN_MASK, &listen_mask)) {
error = errno;
if (error != ENODEV) {
- VLOG_WARN("dp%u: probe returned unexpected error: %s",
- dpif->minor, strerror(error));
+ VLOG_WARN("%s: probe returned unexpected error: %s",
+ dpif_name(dpif), strerror(error));
}
dpif_close(dpif);
return error;
}
+ *dpifp = dpif;
return 0;
}
dpif_close(struct dpif *dpif)
{
if (dpif) {
+ free(dpif->name);
close(dpif->fd);
- dpif->fd = -1;
+ free(dpif);
}
}
int error = ioctl(dpif->fd, cmd, arg) ? errno : 0;
if (cmd_name) {
if (error) {
- VLOG_WARN_RL(&error_rl, "dp%u: ioctl(%s) failed (%s)",
- dpif->minor, cmd_name, strerror(error));
+ VLOG_WARN_RL(&error_rl, "%s: ioctl(%s) failed (%s)",
+ dpif_name(dpif), cmd_name, strerror(error));
} else {
- VLOG_DBG_RL(&dpmsg_rl, "dp%u: ioctl(%s): success",
- dpif->minor, cmd_name);
+ VLOG_DBG_RL(&dpmsg_rl, "%s: ioctl(%s): success",
+ dpif_name(dpif), cmd_name);
}
}
return error;
}
int
-dpif_create(const char *name, struct dpif *dpif)
+dpif_create(const char *name, struct dpif **dpifp)
{
unsigned int minor;
int error;
+ *dpifp = NULL;
if (!get_minor_from_name(name, &minor)) {
/* Minor was specified in 'name', go ahead and create it. */
- error = open_by_minor(minor, dpif);
+ struct dpif *dpif;
+
+ error = open_by_minor(minor, &dpif);
if (error) {
return error;
}
} else {
error = ioctl(dpif->fd, ODP_DP_CREATE, name) < 0 ? errno : 0;
}
- if (error) {
+ if (!error) {
+ *dpifp = dpif;
+ } else {
dpif_close(dpif);
}
return error;
} else {
for (minor = 0; minor < ODP_MAX; minor++) {
- error = open_by_minor(minor, dpif);
+ struct dpif *dpif;
+
+ error = open_by_minor(minor, &dpif);
if (error) {
return error;
}
error = ioctl(dpif->fd, ODP_DP_CREATE, name) < 0 ? errno : 0;
if (!error) {
+ *dpifp = dpif;
return 0;
}
dpif_close(dpif);
}
}
-int
-dpif_get_name(struct dpif *dpif, char *name, size_t name_size)
+const char *
+dpif_name(const struct dpif *dpif)
{
- struct odp_port port;
- int error;
-
- assert(name_size > 0);
- *name = '\0';
-
- error = dpif_port_query_by_number(dpif, ODPP_LOCAL, &port);
- if (!error) {
- ovs_strlcpy(name, port.devname, name_size);
- }
- return error;
+ return dpif->name;
}
int
port.port = port_no;
port.flags = flags;
if (!ioctl(dpif->fd, ODP_PORT_ADD, &port)) {
- VLOG_DBG_RL(&dpmsg_rl, "dp%u: added %s as port %"PRIu16,
- dpif->minor, devname, port_no);
+ VLOG_DBG_RL(&dpmsg_rl, "%s: added %s as port %"PRIu16,
+ dpif_name(dpif), devname, port_no);
return 0;
} else {
- VLOG_WARN_RL(&error_rl, "dp%u: failed to add %s as port "
- "%"PRIu16": %s", dpif->minor, devname, port_no,
- strerror(errno));
+ VLOG_WARN_RL(&error_rl, "%s: failed to add %s as port %"PRIu16": %s",
+ dpif_name(dpif), devname, port_no, strerror(errno));
return errno;
}
}
memset(port, 0, sizeof *port);
port->port = port_no;
if (!ioctl(dpif->fd, ODP_PORT_QUERY, port)) {
- VLOG_DBG_RL(&dpmsg_rl, "dp%u: port %"PRIu16" is device %s",
- dpif->minor, port_no, port->devname);
+ VLOG_DBG_RL(&dpmsg_rl, "%s: port %"PRIu16" is device %s",
+ dpif_name(dpif), port_no, port->devname);
return 0;
} else {
- VLOG_WARN_RL(&error_rl, "dp%u: failed to query port %"PRIu16": %s",
- dpif->minor, port_no, strerror(errno));
+ VLOG_WARN_RL(&error_rl, "%s: failed to query port %"PRIu16": %s",
+ dpif_name(dpif), port_no, strerror(errno));
return errno;
}
}
memset(port, 0, sizeof *port);
strncpy(port->devname, devname, sizeof port->devname);
if (!ioctl(dpif->fd, ODP_PORT_QUERY, port)) {
- VLOG_DBG_RL(&dpmsg_rl, "dp%u: device %s is on port %"PRIu16,
- dpif->minor, devname, port->port);
+ VLOG_DBG_RL(&dpmsg_rl, "%s: device %s is on port %"PRIu16,
+ dpif_name(dpif), devname, port->port);
return 0;
} else {
- VLOG_WARN_RL(&error_rl, "dp%u: failed to query port %s: %s",
- dpif->minor, devname, strerror(errno));
+ /* Log level is DBG here because all the current callers are interested
+ * in whether 'dpif' actually has a port 'devname', so that it's not an
+ * issue worth logging if it doesn't. */
+ VLOG_DBG_RL(&error_rl, "%s: failed to query port %s: %s",
+ dpif_name(dpif), devname, strerror(errno));
return errno;
}
}
+int
+dpif_port_get_name(struct dpif *dpif, uint16_t port_no,
+ char *name, size_t name_size)
+{
+ struct odp_port port;
+ int error;
+
+ assert(name_size > 0);
+
+ error = dpif_port_query_by_number(dpif, port_no, &port);
+ if (!error) {
+ ovs_strlcpy(name, port.devname, name_size);
+ } else {
+ *name = '\0';
+ }
+ return error;
+}
+
int
dpif_port_list(const struct dpif *dpif,
struct odp_port **ports, size_t *n_ports)
const union odp_action *actions, size_t n_actions)
{
struct ds ds = DS_EMPTY_INITIALIZER;
- ds_put_format(&ds, "dp%u: ", dpif->minor);
+ ds_put_format(&ds, "%s: ", dpif_name(dpif));
if (error) {
ds_put_cstr(&ds, "failed to ");
}
error = do_ioctl(dpif, ODP_FLOW_LIST, NULL, &fv);
if (error) {
*n_out = 0;
- VLOG_WARN_RL(&error_rl, "dp%u: flow list failed (%s)",
- dpif->minor, strerror(error));
+ VLOG_WARN_RL(&error_rl, "%s: flow list failed (%s)",
+ dpif_name(dpif), strerror(error));
} else {
COVERAGE_ADD(dpif_flow_query_list_n, fv.n_flows);
*n_out = fv.n_flows;
- VLOG_DBG_RL(&dpmsg_rl, "dp%u: listed %zu flows", dpif->minor, *n_out);
+ VLOG_DBG_RL(&dpmsg_rl, "%s: listed %zu flows",
+ dpif_name(dpif), *n_out);
}
return error;
}
}
if (stats.n_flows != n_flows) {
- VLOG_WARN_RL(&error_rl, "dp%u: datapath stats reported %"PRIu32" "
+ VLOG_WARN_RL(&error_rl, "%s: datapath stats reported %"PRIu32" "
"flows but flow listing reported %zu",
- dpif->minor, stats.n_flows, n_flows);
+ dpif_name(dpif), stats.n_flows, n_flows);
}
*flowsp = flows;
*np = n_flows;
if (!(error ? VLOG_DROP_WARN(&error_rl) : VLOG_DROP_DBG(&dpmsg_rl))) {
struct ds ds = DS_EMPTY_INITIALIZER;
char *packet = ofp_packet_to_string(buf->data, buf->size, buf->size);
- ds_put_format(&ds, "dp%u: execute ", dpif->minor);
+ ds_put_format(&ds, "%s: execute ", dpif_name(dpif));
format_odp_actions(&ds, actions, n_actions);
if (error) {
ds_put_format(&ds, " failed (%s)", strerror(error));
if (retval < 0) {
error = errno;
if (error != EAGAIN) {
- VLOG_WARN_RL(&error_rl, "dp%u: read failed: %s",
- dpif->minor, strerror(error));
+ VLOG_WARN_RL(&error_rl, "%s: read failed: %s",
+ dpif_name(dpif), strerror(error));
}
} else if (retval >= sizeof(struct odp_msg)) {
struct odp_msg *msg = buf->data;
void *payload = msg + 1;
size_t length = buf->size - sizeof *msg;
char *s = ofp_packet_to_string(payload, length, length);
- VLOG_DBG_RL(&dpmsg_rl, "dp%u: received %s message of length "
- "%zu on port %"PRIu16": %s", dpif->minor,
+ VLOG_DBG_RL(&dpmsg_rl, "%s: received %s message of length "
+ "%zu on port %"PRIu16": %s", dpif_name(dpif),
(msg->type == _ODPL_MISS_NR ? "miss"
: msg->type == _ODPL_ACTION_NR ? "action"
: "<unknown>"),
COVERAGE_INC(dpif_recv);
return 0;
} else {
- VLOG_WARN_RL(&error_rl, "dp%u: discarding message truncated "
+ VLOG_WARN_RL(&error_rl, "%s: discarding message truncated "
"from %zu bytes to %d",
- dpif->minor, msg->length, retval);
+ dpif_name(dpif), msg->length, retval);
error = ERANGE;
}
} else if (!retval) {
- VLOG_WARN_RL(&error_rl, "dp%u: unexpected end of file", dpif->minor);
+ VLOG_WARN_RL(&error_rl, "%s: unexpected end of file", dpif_name(dpif));
error = EPROTO;
} else {
VLOG_WARN_RL(&error_rl,
- "dp%u: discarding too-short message (%d bytes)",
- dpif->minor, retval);
+ "%s: discarding too-short message (%d bytes)",
+ dpif_name(dpif), retval);
error = ERANGE;
}
{
poll_fd_wait(dpif->fd, POLLIN);
}
+
+void
+dpif_get_netflow_ids(const struct dpif *dpif,
+ uint8_t *engine_type, uint8_t *engine_id)
+{
+ *engine_type = *engine_id = dpif->minor;
+}
\f
struct dpifmon {
- struct dpif dpif;
+ struct dpif *dpif;
struct nl_sock *sock;
int local_ifindex;
};
if (error) {
goto error;
}
- error = dpif_get_name(&mon->dpif, local_name, sizeof local_name);
+ error = dpif_port_get_name(mon->dpif, ODPP_LOCAL,
+ local_name, sizeof local_name);
if (error) {
goto error_close_dpif;
}
return 0;
error_close_dpif:
- dpif_close(&mon->dpif);
+ dpif_close(mon->dpif);
error:
free(mon);
*monp = NULL;
dpifmon_destroy(struct dpifmon *mon)
{
if (mon) {
- dpif_close(&mon->dpif);
+ dpif_close(mon->dpif);
nl_sock_destroy(mon->sock);
}
}
uint32_t master_ifindex = nl_attr_get_u32(attrs[IFLA_MASTER]);
for_us = master_ifindex == mon->local_ifindex;
} else {
- /* It's for us if that device is one of our ports. This is
- * open-coded instead of using dpif_port_query_by_name() to
- * avoid logging a warning on failure. */
+ /* It's for us if that device is one of our ports. */
struct odp_port port;
- memset(&port, 0, sizeof port);
- strncpy(port.devname, devname, sizeof port.devname);
- for_us = !ioctl(mon->dpif.fd, ODP_PORT_QUERY, &port);
+ for_us = !dpif_port_query_by_name(mon->dpif, devname, &port);
}
if (!for_us) {
}
static int
-open_by_minor(unsigned int minor, struct dpif *dpif)
+open_by_minor(unsigned int minor, struct dpif **dpifp)
{
+ struct dpif *dpif;
int error;
char *fn;
int fd;
- dpif->minor = -1;
- dpif->fd = -1;
+ *dpifp = NULL;
error = make_openvswitch_device(minor, &fn);
if (error) {
return error;
free(fn);
return error;
}
-
free(fn);
+
+ dpif = xmalloc(sizeof *dpif);
+ dpif->name = xasprintf("dp%u", dpif->minor);
dpif->minor = minor;
dpif->fd = fd;
+ *dpifp = dpif;
return 0;
}
\f