X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fdpif.c;h=18ef790afac4d74abad7651e21166fa67b826848;hb=85b20fd6ee585f462e012fbcc7f966a81edab2ed;hp=30e9b55bbe72f45c1b3f428cc443082b795ea8a6;hpb=399c91552a13a5215bb1ed79917ee61ecd107f6b;p=sliver-openvswitch.git diff --git a/lib/dpif.c b/lib/dpif.c index 30e9b55bb..18ef790af 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,7 +58,7 @@ COVERAGE_DEFINE(dpif_execute); COVERAGE_DEFINE(dpif_purge); static const struct dpif_class *base_dpif_classes[] = { -#ifdef HAVE_NETLINK +#ifdef LINUX_DATAPATH &dpif_linux_class, #endif &dpif_netdev_class, @@ -373,6 +373,13 @@ dpif_base_name(const struct dpif *dpif) return dpif->base_name; } +/* Returns the type of datapath 'dpif'. */ +const char * +dpif_type(const struct dpif *dpif) +{ + return dpif->dpif_class->type; +} + /* Returns the fully spelled out name for the given datapath 'type'. * * Normalized type string can be compared with strcmp(). Unnormalized type @@ -411,27 +418,52 @@ dpif_get_dp_stats(const struct dpif *dpif, struct dpif_dp_stats *stats) return error; } -/* Attempts to add 'netdev' as a port on 'dpif'. If successful, returns 0 and - * sets '*port_nop' to the new port's port number (if 'port_nop' is non-null). - * On failure, returns a positive errno value and sets '*port_nop' to - * UINT16_MAX (if 'port_nop' is non-null). */ +const char * +dpif_port_open_type(const char *datapath_type, const char *port_type) +{ + struct registered_dpif_class *registered_class; + + datapath_type = dpif_normalize_type(datapath_type); + + registered_class = shash_find_data(&dpif_classes, datapath_type); + if (!registered_class + || !registered_class->dpif_class->port_open_type) { + return port_type; + } + + return registered_class->dpif_class->port_open_type( + registered_class->dpif_class, port_type); +} + +/* Attempts to add 'netdev' as a port on 'dpif'. If 'port_nop' is + * non-null and its value is not UINT32_MAX, then attempts to use the + * value as the port number. + * + * If successful, returns 0 and sets '*port_nop' to the new port's port + * number (if 'port_nop' is non-null). On failure, returns a positive + * errno value and sets '*port_nop' to UINT32_MAX (if 'port_nop' is + * non-null). */ int -dpif_port_add(struct dpif *dpif, struct netdev *netdev, uint16_t *port_nop) +dpif_port_add(struct dpif *dpif, struct netdev *netdev, uint32_t *port_nop) { const char *netdev_name = netdev_get_name(netdev); - uint16_t port_no; + uint32_t port_no = UINT32_MAX; int error; COVERAGE_INC(dpif_port_add); + if (port_nop) { + port_no = *port_nop; + } + error = dpif->dpif_class->port_add(dpif, netdev, &port_no); if (!error) { - VLOG_DBG_RL(&dpmsg_rl, "%s: added %s as port %"PRIu16, + VLOG_DBG_RL(&dpmsg_rl, "%s: added %s as port %"PRIu32, dpif_name(dpif), netdev_name, port_no); } else { VLOG_WARN_RL(&error_rl, "%s: failed to add %s as port: %s", dpif_name(dpif), netdev_name, strerror(error)); - port_no = UINT16_MAX; + port_no = UINT32_MAX; } if (port_nop) { *port_nop = port_no; @@ -442,7 +474,7 @@ dpif_port_add(struct dpif *dpif, struct netdev *netdev, uint16_t *port_nop) /* Attempts to remove 'dpif''s port number 'port_no'. Returns 0 if successful, * otherwise a positive errno value. */ int -dpif_port_del(struct dpif *dpif, uint16_t port_no) +dpif_port_del(struct dpif *dpif, uint32_t port_no) { int error; @@ -450,7 +482,7 @@ dpif_port_del(struct dpif *dpif, uint16_t port_no) error = dpif->dpif_class->port_del(dpif, port_no); if (!error) { - VLOG_DBG_RL(&dpmsg_rl, "%s: port_del(%"PRIu16")", + VLOG_DBG_RL(&dpmsg_rl, "%s: port_del(%"PRIu32")", dpif_name(dpif), port_no); } else { log_operation(dpif, "port_del", error); @@ -479,6 +511,20 @@ dpif_port_destroy(struct dpif_port *dpif_port) free(dpif_port->type); } +/* Checks if port named 'devname' exists in 'dpif'. If so, returns + * true; otherwise, returns false. */ +bool +dpif_port_exists(const struct dpif *dpif, const char *devname) +{ + int error = dpif->dpif_class->port_query_by_name(dpif, devname, NULL); + if (error != 0 && error != ENOENT && error != ENODEV) { + VLOG_WARN_RL(&error_rl, "%s: failed to query port %s: %s", + dpif_name(dpif), devname, strerror(error)); + } + + return !error; +} + /* Looks up port number 'port_no' in 'dpif'. On success, returns 0 and * initializes '*port' appropriately; on failure, returns a positive errno * value. @@ -486,16 +532,16 @@ dpif_port_destroy(struct dpif_port *dpif_port) * 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, +dpif_port_query_by_number(const struct dpif *dpif, uint32_t port_no, 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", + VLOG_DBG_RL(&dpmsg_rl, "%s: port %"PRIu32" is device %s", 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", + VLOG_WARN_RL(&error_rl, "%s: failed to query port %"PRIu32": %s", dpif_name(dpif), port_no, strerror(error)); } return error; @@ -513,7 +559,7 @@ dpif_port_query_by_name(const struct dpif *dpif, const char *devname, { 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, + VLOG_DBG_RL(&dpmsg_rl, "%s: device %s is on port %"PRIu32, dpif_name(dpif), devname, port->port_no); } else { memset(port, 0, sizeof *port); @@ -542,13 +588,16 @@ dpif_get_max_ports(const struct dpif *dpif) * as the OVS_USERSPACE_ATTR_PID attribute's value, for use in flows whose * packets arrived on port 'port_no'. * + * A 'port_no' of UINT32_MAX is a special case: it returns a reserved PID, not + * allocated to any port, that the client may use for special purposes. + * * The return value is only meaningful when DPIF_UC_ACTION has been enabled in * the 'dpif''s listen mask. It is allowed to change when DPIF_UC_ACTION is * disabled and then re-enabled, so a client that does that must be prepared to * update all of the flows that it installed that contain * OVS_ACTION_ATTR_USERSPACE actions. */ uint32_t -dpif_port_get_pid(const struct dpif *dpif, uint16_t port_no) +dpif_port_get_pid(const struct dpif *dpif, uint32_t port_no) { return (dpif->dpif_class->port_get_pid ? (dpif->dpif_class->port_get_pid)(dpif, port_no) @@ -560,7 +609,7 @@ dpif_port_get_pid(const struct dpif *dpif, uint16_t port_no) * result is null-terminated. On failure, returns a positive errno value and * makes 'name' the empty string. */ int -dpif_port_get_name(struct dpif *dpif, uint16_t port_no, +dpif_port_get_name(struct dpif *dpif, uint32_t port_no, char *name, size_t name_size) { struct dpif_port port; @@ -675,15 +724,16 @@ dpif_port_poll_wait(const struct dpif *dpif) } /* Extracts the flow stats for a packet. The 'flow' and 'packet' - * arguments must have been initialized through a call to flow_extract(). */ + * arguments must have been initialized through a call to flow_extract(). + * 'used' is stored into stats->used. */ void dpif_flow_stats_extract(const struct flow *flow, const struct ofpbuf *packet, - struct dpif_flow_stats *stats) + long long int used, struct dpif_flow_stats *stats) { stats->tcp_flags = packet_get_tcp_flags(packet, flow); stats->n_bytes = packet->size; stats->n_packets = 1; - stats->used = time_msec(); + stats->used = used; } /* Appends a human-readable representation of 'stats' to 's'. */ @@ -966,7 +1016,7 @@ dpif_execute__(struct dpif *dpif, const struct dpif_execute *execute) * the Ethernet frame specified in 'packet' taken from the flow specified in * the 'key_len' bytes of 'key'. ('key' is mostly redundant with 'packet', but * it contains some metadata that cannot be recovered from 'packet', such as - * tun_id and in_port.) + * tunnel and in_port.) * * Returns 0 if successful, otherwise a positive errno value. */ int