X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif.c;h=85d05bb714ce61df9078aa8654f71a183c02dab7;hb=f4ba4c4f954f565facc204c2f42947a37704eb1e;hp=646d2a73725ca27b834799290b87755d90f04e48;hpb=5c6d2a3f3a3649a7f1e7f1bbcd02139fff3bf433;p=openvswitch diff --git a/lib/dpif.c b/lib/dpif.c index 646d2a73..85d05bb7 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -49,6 +49,13 @@ #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. */ @@ -60,24 +67,26 @@ static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5); 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; } @@ -95,6 +104,7 @@ dpif_open(const char *name, struct dpif *dpif) dpif_close(dpif); return error; } + *dpifp = dpif; return 0; } @@ -103,9 +113,8 @@ dpif_close(struct dpif *dpif) { if (dpif) { free(dpif->name); - dpif->name = NULL; close(dpif->fd); - dpif->fd = -1; + free(dpif); } } @@ -127,38 +136,40 @@ do_ioctl(const struct dpif *dpif, int cmd, const char *cmd_name, } 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; } - if (!strncmp(name, "nl:", 3)) { - char devname[128]; - sprintf(devname, "of%u", minor); - error = ioctl(dpif->fd, ODP_DP_CREATE, devname) < 0 ? errno : 0; + error = ioctl(dpif->fd, ODP_DP_CREATE, name) < 0 ? errno : 0; + if (!error) { + *dpifp = dpif; } else { - error = ioctl(dpif->fd, ODP_DP_CREATE, name) < 0 ? errno : 0; - } - if (error) { 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); @@ -207,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; @@ -250,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 @@ -336,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; } @@ -380,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; } @@ -503,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 @@ -522,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); } @@ -630,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) { @@ -700,7 +765,7 @@ dpif_get_netflow_ids(const struct dpif *dpif, } struct dpifmon { - struct dpif dpif; + struct dpif *dpif; struct nl_sock *sock; int local_ifindex; }; @@ -718,7 +783,7 @@ dpifmon_create(const char *datapath_name, struct dpifmon **monp) if (error) { goto error; } - error = dpif_port_get_name(&mon->dpif, ODPP_LOCAL, + error = dpif_port_get_name(mon->dpif, ODPP_LOCAL, local_name, sizeof local_name); if (error) { goto error_close_dpif; @@ -741,7 +806,7 @@ dpifmon_create(const char *datapath_name, struct dpifmon **monp) return 0; error_close_dpif: - dpif_close(&mon->dpif); + dpif_close(mon->dpif); error: free(mon); *monp = NULL; @@ -752,7 +817,7 @@ void dpifmon_destroy(struct dpifmon *mon) { if (mon) { - dpif_close(&mon->dpif); + dpif_close(mon->dpif); nl_sock_destroy(mon->sock); } } @@ -1015,24 +1080,20 @@ get_minor_from_name(const char *name, unsigned int *minor) if (!strncmp(name, "dp", 2) && isdigit(name[2])) { *minor = atoi(name + 2); return 0; - } else if (!strncmp(name, "nl:", 3) && isdigit(name[3])) { - /* This is for compatibility only and will be dropped. */ - *minor = atoi(name + 3); - return 0; } else { return EINVAL; } } 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; @@ -1045,11 +1106,13 @@ open_by_minor(unsigned int minor, struct dpif *dpif) 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; }