X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=lib%2Fdpif.c;h=1fff27f9003250ca0e2780f7eb72d57924f740c7;hb=ea7bd5973fb426f3a6ea66b0953c6000980e77ec;hp=b54ecaa9d765c291acefad44e3efd8b9ee4210f4;hpb=856081f683d3e7d5b5fa07af4233d285eb205c47;p=openvswitch diff --git a/lib/dpif.c b/lib/dpif.c index b54ecaa9..1fff27f9 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -492,17 +492,41 @@ dpif_port_del(struct dpif *dpif, uint16_t port_no) return error; } +/* Makes a deep copy of 'src' into 'dst'. */ +void +dpif_port_clone(struct dpif_port *dst, const struct dpif_port *src) +{ + dst->name = xstrdup(src->name); + dst->type = xstrdup(src->type); + dst->port_no = src->port_no; +} + +/* Frees memory allocated to members of 'dpif_port'. + * + * Do not call this function on a dpif_port obtained from + * dpif_port_dump_next(): that function retains ownership of the data in the + * dpif_port. */ +void +dpif_port_destroy(struct dpif_port *dpif_port) +{ + free(dpif_port->name); + free(dpif_port->type); +} + /* Looks up port number 'port_no' in 'dpif'. On success, returns 0 and * initializes '*port' appropriately; on failure, returns a positive errno - * value. */ + * value. + * + * The caller owns the data in 'port' and must free it with + * dpif_port_destroy() when it is no longer needed. */ int dpif_port_query_by_number(const struct dpif *dpif, uint16_t port_no, - struct odp_port *port) + struct dpif_port *port) { int error = dpif->dpif_class->port_query_by_number(dpif, port_no, port); if (!error) { VLOG_DBG_RL(&dpmsg_rl, "%s: port %"PRIu16" is device %s", - dpif_name(dpif), port_no, port->devname); + dpif_name(dpif), port_no, port->name); } else { memset(port, 0, sizeof *port); VLOG_WARN_RL(&error_rl, "%s: failed to query port %"PRIu16": %s", @@ -513,15 +537,18 @@ dpif_port_query_by_number(const struct dpif *dpif, uint16_t port_no, /* Looks up port named 'devname' in 'dpif'. On success, returns 0 and * initializes '*port' appropriately; on failure, returns a positive errno - * value. */ + * value. + * + * The caller owns the data in 'port' and must free it with + * dpif_port_destroy() when it is no longer needed. */ int dpif_port_query_by_name(const struct dpif *dpif, const char *devname, - struct odp_port *port) + struct dpif_port *port) { int error = dpif->dpif_class->port_query_by_name(dpif, devname, port); if (!error) { VLOG_DBG_RL(&dpmsg_rl, "%s: device %s is on port %"PRIu16, - dpif_name(dpif), devname, port->port); + dpif_name(dpif), devname, port->port_no); } else { memset(port, 0, sizeof *port); @@ -542,74 +569,81 @@ int dpif_port_get_name(struct dpif *dpif, uint16_t port_no, char *name, size_t name_size) { - struct odp_port port; + struct dpif_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); + ovs_strlcpy(name, port.name, name_size); + dpif_port_destroy(&port); } else { *name = '\0'; } return error; } -/* Obtains a list of all the ports in 'dpif'. +/* Initializes 'dump' to begin dumping the ports in a dpif. + * + * This function provides no status indication. An error status for the entire + * dump operation is provided when it is completed by calling + * dpif_port_dump_done(). + */ +void +dpif_port_dump_start(struct dpif_port_dump *dump, const struct dpif *dpif) +{ + dump->dpif = dpif; + dump->error = dpif->dpif_class->port_dump_start(dpif, &dump->state); + log_operation(dpif, "port_dump_start", dump->error); +} + +/* Attempts to retrieve another port from 'dump', which must have been + * initialized with dpif_port_dump_start(). On success, stores a new dpif_port + * into 'port' and returns true. On failure, returns false. * - * If successful, returns 0 and sets '*portsp' to point to an array of - * appropriately initialized port structures and '*n_portsp' to the number of - * ports in the array. The caller is responsible for freeing '*portp' by - * calling free(). + * Failure might indicate an actual error or merely that the last port has been + * dumped. An error status for the entire dump operation is provided when it + * is completed by calling dpif_port_dump_done(). * - * On failure, returns a positive errno value and sets '*portsp' to NULL and - * '*n_portsp' to 0. */ -int -dpif_port_list(const struct dpif *dpif, - struct odp_port **portsp, size_t *n_portsp) + * The dpif owns the data stored in 'port'. It will remain valid until at + * least the next time 'dump' is passed to dpif_port_dump_next() or + * dpif_port_dump_done(). */ +bool +dpif_port_dump_next(struct dpif_port_dump *dump, struct dpif_port *port) { - struct odp_port *ports; - size_t n_ports = 0; - int error; + const struct dpif *dpif = dump->dpif; - for (;;) { - struct odp_stats stats; - int retval; + if (dump->error) { + return false; + } - error = dpif_get_dp_stats(dpif, &stats); - if (error) { - goto exit; - } + dump->error = dpif->dpif_class->port_dump_next(dpif, dump->state, port); + if (dump->error == EOF) { + VLOG_DBG_RL(&dpmsg_rl, "%s: dumped all ports", dpif_name(dpif)); + } else { + log_operation(dpif, "port_dump_next", dump->error); + } - ports = xcalloc(stats.n_ports, sizeof *ports); - retval = dpif->dpif_class->port_list(dpif, ports, stats.n_ports); - if (retval < 0) { - /* Hard error. */ - error = -retval; - free(ports); - goto exit; - } else if (retval <= stats.n_ports) { - /* Success. */ - error = 0; - n_ports = retval; - goto exit; - } else { - /* Soft error: port count increased behind our back. Try again. */ - free(ports); - } + if (dump->error) { + dpif->dpif_class->port_dump_done(dpif, dump->state); + return false; } + return true; +} -exit: - if (error) { - *portsp = NULL; - *n_portsp = 0; - } else { - *portsp = ports; - *n_portsp = n_ports; +/* Completes port table dump operation 'dump', which must have been initialized + * with dpif_port_dump_start(). Returns 0 if the dump operation was + * error-free, otherwise a positive errno value describing the problem. */ +int +dpif_port_dump_done(struct dpif_port_dump *dump) +{ + const struct dpif *dpif = dump->dpif; + if (!dump->error) { + dump->error = dpif->dpif_class->port_dump_done(dpif, dump->state); + log_operation(dpif, "port_dump_done", dump->error); } - log_operation(dpif, "port_list", error); - return error; + return dump->error == EOF ? 0 : dump->error; } /* Polls for changes in the set of ports in 'dpif'. If the set of ports in