X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif.c;h=85d05bb714ce61df9078aa8654f71a183c02dab7;hb=f4ba4c4f954f565facc204c2f42947a37704eb1e;hp=877cfc823d1577e710b8b2d45025563d5a3f97ad;hpb=f7ef6533d8e48565f21a67021e8477b6f5a59ae3;p=openvswitch diff --git a/lib/dpif.c b/lib/dpif.c index 877cfc82..85d05bb7 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -218,25 +218,7 @@ dpif_set_drop_frags(struct dpif *dpif, bool drop_frags) } 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; @@ -261,25 +243,33 @@ dpif_purge(struct dpif *dpif) } 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 @@ -347,33 +337,48 @@ dpif_port_get_name(struct dpif *dpif, uint16_t port_no, 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; } @@ -391,21 +396,39 @@ dpif_port_group_set(struct dpif *dpif, uint16_t group, 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; } @@ -514,10 +537,23 @@ dpif_flow_del(struct dpif *dpif, struct odp_flow *flow) 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 @@ -533,7 +569,7 @@ dpif_flow_get_multiple(const struct dpif *dpif, 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); } @@ -641,6 +677,24 @@ dpif_execute(struct dpif *dpif, uint16_t in_port, 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) {