}
int
-dpif_get_listen_mask(const struct dpif *dpif, int *listen_mask)
-{
- int error = do_ioctl(dpif, ODP_GET_LISTEN_MASK, "ODP_GET_LISTEN_MASK",
- listen_mask);
- if (error) {
- *listen_mask = 0;
- }
- return error;
-}
-
-int
-dpif_set_listen_mask(struct dpif *dpif, int listen_mask)
-{
- return do_ioctl(dpif, ODP_SET_LISTEN_MASK, "ODP_SET_LISTEN_MASK",
- &listen_mask);
-}
-
-int
-dpif_purge(struct dpif *dpif)
+dpif_recv_purge(struct dpif *dpif)
{
struct odp_stats stats;
unsigned int i;
}
int
-dpif_port_add(struct dpif *dpif, const char *devname, uint16_t port_no,
- uint16_t flags)
+dpif_port_add(struct dpif *dpif, const char *devname, uint16_t flags,
+ uint16_t *port_nop)
{
struct odp_port port;
+ uint16_t port_no;
+ int error;
COVERAGE_INC(dpif_port_add);
+
memset(&port, 0, sizeof port);
strncpy(port.devname, devname, sizeof port.devname);
- port.port = port_no;
port.flags = flags;
- if (!ioctl(dpif->fd, ODP_PORT_ADD, &port)) {
+
+ error = do_ioctl(dpif, ODP_PORT_ADD, NULL, &port);
+ if (!error) {
+ port_no = port.port;
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, "%s: failed to add %s as port %"PRIu16": %s",
- dpif_name(dpif), devname, port_no, strerror(errno));
- return errno;
+ port_no = UINT16_MAX;
+ VLOG_WARN_RL(&error_rl, "%s: failed to add %s as port: %s",
+ dpif_name(dpif), devname, strerror(errno));
+ }
+ if (port_nop) {
+ *port_nop = port_no;
}
+ return error;
}
int
int
dpif_port_list(const struct dpif *dpif,
- struct odp_port **ports, size_t *n_ports)
+ struct odp_port **portsp, size_t *n_portsp)
{
- struct odp_portvec pv;
- struct odp_stats stats;
+ struct odp_port *ports;
+ size_t n_ports;
int error;
- do {
+ for (;;) {
+ struct odp_stats stats;
+ struct odp_portvec pv;
+
error = dpif_get_dp_stats(dpif, &stats);
if (error) {
- goto error;
+ goto exit;
}
- *ports = xcalloc(1, stats.n_ports * sizeof **ports);
- pv.ports = *ports;
+ ports = xcalloc(stats.n_ports, sizeof *ports);
+ pv.ports = ports;
pv.n_ports = stats.n_ports;
error = do_ioctl(dpif, ODP_PORT_LIST, "ODP_PORT_LIST", &pv);
if (error) {
- free(*ports);
- goto error;
+ /* Hard error. */
+ free(ports);
+ goto exit;
+ } else if (pv.n_ports <= stats.n_ports) {
+ /* Success. */
+ error = 0;
+ n_ports = pv.n_ports;
+ goto exit;
+ } else {
+ /* Soft error: port count increased behind our back. Try again. */
+ free(ports);
}
- } while (pv.n_ports != stats.n_ports);
- *n_ports = pv.n_ports;
- return 0;
+ }
-error:
- *ports = NULL;
- *n_ports = 0;
+exit:
+ if (error) {
+ *portsp = NULL;
+ *n_portsp = 0;
+ } else {
+ *portsp = ports;
+ *n_portsp = n_ports;
+ }
return error;
}
return do_ioctl(dpif, ODP_PORT_GROUP_SET, "ODP_PORT_GROUP_SET", &pg);
}
-/* Careful: '*n_out' can be greater than 'n_ports' on return, if 'n_ports' is
- * less than the number of ports in 'group'. */
int
dpif_port_group_get(const struct dpif *dpif, uint16_t group,
- uint16_t ports[], size_t n_ports, size_t *n_out)
+ uint16_t **ports, size_t *n_ports)
{
- struct odp_port_group pg;
int error;
- assert(n_ports <= UINT16_MAX);
- pg.group = group;
- pg.ports = ports;
- pg.n_ports = n_ports;
- error = do_ioctl(dpif, ODP_PORT_GROUP_GET, "ODP_PORT_GROUP_GET", &pg);
- *n_out = error ? 0 : pg.n_ports;
+ *ports = NULL;
+ *n_ports = 0;
+ for (;;) {
+ struct odp_port_group pg;
+ pg.group = group;
+ pg.ports = *ports;
+ pg.n_ports = *n_ports;
+
+ error = do_ioctl(dpif, ODP_PORT_GROUP_GET, "ODP_PORT_GROUP_GET", &pg);
+ if (error) {
+ /* Hard error. */
+ free(*ports);
+ *ports = NULL;
+ *n_ports = 0;
+ break;
+ } else if (pg.n_ports <= *n_ports) {
+ /* Success. */
+ *n_ports = pg.n_ports;
+ break;
+ } else {
+ /* Soft error: there were more ports than we expected in the
+ * group. Try again. */
+ free(*ports);
+ *ports = xcalloc(pg.n_ports, sizeof **ports);
+ *n_ports = pg.n_ports;
+ }
+ }
return error;
}
int
dpif_flow_get(const struct dpif *dpif, struct odp_flow *flow)
{
- COVERAGE_INC(dpif_flow_query);
+ struct odp_flowvec fv;
+ int error;
+
+ COVERAGE_INC(dpif_flow_get);
+
check_rw_odp_flow(flow);
- memset(&flow->stats, 0, sizeof flow->stats);
- return do_flow_ioctl(dpif, ODP_FLOW_GET, flow, "get flow", true);
+ fv.flows = flow;
+ fv.n_flows = 1;
+ error = do_ioctl(dpif, ODP_FLOW_GET, "ODP_FLOW_GET", &fv);
+ if (!error) {
+ error = flow->stats.error;
+ if (error) {
+ VLOG_WARN_RL(&error_rl, "%s: ioctl(ODP_FLOW_GET) failed (%s)",
+ dpif_name(dpif), strerror(error));
+ }
+ }
+ return error;
}
int
for (i = 0; i < n; i++) {
check_rw_odp_flow(&flows[i]);
}
- return do_ioctl(dpif, ODP_FLOW_GET_MULTIPLE, "ODP_FLOW_GET_MULTIPLE",
+ return do_ioctl(dpif, ODP_FLOW_GET, "ODP_FLOW_GET",
&fv);
}
return error;
}
+int
+dpif_recv_get_mask(const struct dpif *dpif, int *listen_mask)
+{
+ int error = do_ioctl(dpif, ODP_GET_LISTEN_MASK, "ODP_GET_LISTEN_MASK",
+ listen_mask);
+ if (error) {
+ *listen_mask = 0;
+ }
+ return error;
+}
+
+int
+dpif_recv_set_mask(struct dpif *dpif, int listen_mask)
+{
+ return do_ioctl(dpif, ODP_SET_LISTEN_MASK, "ODP_SET_LISTEN_MASK",
+ &listen_mask);
+}
+
int
dpif_recv(struct dpif *dpif, struct ofpbuf **bufp)
{