X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fdpif.c;h=bab1ffebfec706fc834caaa18b0009c96c8d8694;hb=9b1a48c210ffa95c6323d5db05958aba35802c49;hp=fa9b30a6abcb1609ef5dc864f3617d5e4258c9dc;hpb=361906b1e2c6482d77280f345d3e42048d8c2700;p=sliver-openvswitch.git diff --git a/lib/dpif.c b/lib/dpif.c index fa9b30a6a..bab1ffebf 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -17,7 +17,6 @@ #include #include "dpif-provider.h" -#include #include #include #include @@ -265,7 +264,7 @@ do_open(const char *name, const char *type, bool create, struct dpif **dpifp) error = registered_class->dpif_class->open(registered_class->dpif_class, name, create, &dpif); if (!error) { - assert(dpif->dpif_class == registered_class->dpif_class); + ovs_assert(dpif->dpif_class == registered_class->dpif_class); registered_class->refcount++; } @@ -329,8 +328,8 @@ dpif_close(struct dpif *dpif) registered_class = shash_find_data(&dpif_classes, dpif->dpif_class->type); - assert(registered_class); - assert(registered_class->refcount); + ovs_assert(registered_class); + ovs_assert(registered_class->refcount); registered_class->refcount--; dpif_uninit(dpif, true); @@ -372,6 +371,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 @@ -410,19 +416,36 @@ dpif_get_dp_stats(const struct dpif *dpif, struct dpif_dp_stats *stats) return error; } +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 UINT16_MAX, then attempts to use the + * non-null and its value is not ODPP_NONE, 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 UINT16_MAX (if 'port_nop' is + * errno value and sets '*port_nop' to ODPP_NONE (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, odp_port_t *port_nop) { const char *netdev_name = netdev_get_name(netdev); - uint16_t port_no = UINT16_MAX; + odp_port_t port_no = ODPP_NONE; int error; COVERAGE_INC(dpif_port_add); @@ -433,12 +456,12 @@ dpif_port_add(struct dpif *dpif, struct netdev *netdev, uint16_t *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 = ODPP_NONE; } if (port_nop) { *port_nop = port_no; @@ -449,7 +472,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, odp_port_t port_no) { int error; @@ -457,7 +480,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); @@ -486,6 +509,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. @@ -493,16 +530,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, odp_port_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; @@ -520,7 +557,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); @@ -539,7 +576,7 @@ dpif_port_query_by_name(const struct dpif *dpif, const char *devname, /* Returns one greater than the maximum port number accepted in flow * actions. */ -int +odp_port_t dpif_get_max_ports(const struct dpif *dpif) { return dpif->dpif_class->get_max_ports(dpif); @@ -549,7 +586,7 @@ 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 UINT16_MAX is a special case: it returns a reserved PID, not + * A 'port_no' of ODPP_NONE 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 @@ -558,7 +595,7 @@ dpif_get_max_ports(const struct dpif *dpif) * 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, odp_port_t port_no) { return (dpif->dpif_class->port_get_pid ? (dpif->dpif_class->port_get_pid)(dpif, port_no) @@ -570,13 +607,13 @@ 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, odp_port_t port_no, char *name, size_t name_size) { struct dpif_port port; int error; - assert(name_size > 0); + ovs_assert(name_size > 0); error = dpif_port_query_by_number(dpif, port_no, &port); if (!error) { @@ -783,8 +820,8 @@ dpif_flow_put__(struct dpif *dpif, const struct dpif_flow_put *put) int error; COVERAGE_INC(dpif_flow_put); - assert(!(put->flags & ~(DPIF_FP_CREATE | DPIF_FP_MODIFY - | DPIF_FP_ZERO_STATS))); + ovs_assert(!(put->flags & ~(DPIF_FP_CREATE | DPIF_FP_MODIFY + | DPIF_FP_ZERO_STATS))); error = dpif->dpif_class->flow_put(dpif, put); if (error && put->stats) { @@ -795,9 +832,11 @@ dpif_flow_put__(struct dpif *dpif, const struct dpif_flow_put *put) } /* Adds or modifies a flow in 'dpif'. The flow is specified by the Netlink - * attributes with types OVS_KEY_ATTR_* in the 'key_len' bytes starting at - * 'key'. The associated actions are specified by the Netlink attributes with - * types OVS_ACTION_ATTR_* in the 'actions_len' bytes starting at 'actions'. + * attribute OVS_FLOW_ATTR_KEY with types OVS_KEY_ATTR_* in the 'key_len' bytes + * starting at 'key', and OVS_FLOW_ATTR_MASK with types of OVS_KEY_ATTR_* in the + * 'mask_len' bytes starting at 'mask'. The associated actions are specified by + * the Netlink attributes with types OVS_ACTION_ATTR_* in the 'actions_len' + * bytes starting at 'actions'. * * - If the flow's key does not exist in 'dpif', then the flow will be added if * 'flags' includes DPIF_FP_CREATE. Otherwise the operation will fail with @@ -817,6 +856,7 @@ dpif_flow_put__(struct dpif *dpif, const struct dpif_flow_put *put) int dpif_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags, const struct nlattr *key, size_t key_len, + const struct nlattr *mask, size_t mask_len, const struct nlattr *actions, size_t actions_len, struct dpif_flow_stats *stats) { @@ -825,6 +865,8 @@ dpif_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags, put.flags = flags; put.key = key; put.key_len = key_len; + put.mask = mask; + put.mask_len = mask_len; put.actions = actions; put.actions_len = actions_len; put.stats = stats; @@ -900,6 +942,7 @@ dpif_flow_dump_start(struct dpif_flow_dump *dump, const struct dpif *dpif) bool dpif_flow_dump_next(struct dpif_flow_dump *dump, const struct nlattr **key, size_t *key_len, + const struct nlattr **mask, size_t *mask_len, const struct nlattr **actions, size_t *actions_len, const struct dpif_flow_stats **stats) { @@ -909,6 +952,7 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump, if (!error) { error = dpif->dpif_class->flow_dump_next(dpif, dump->state, key, key_len, + mask, mask_len, actions, actions_len, stats); if (error) { @@ -920,6 +964,10 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump, *key = NULL; *key_len = 0; } + if (mask) { + *mask = NULL; + *mask_len = 0; + } if (actions) { *actions = NULL; *actions_len = 0; @@ -1213,7 +1261,12 @@ log_operation(const struct dpif *dpif, const char *operation, int error) static enum vlog_level flow_message_log_level(int error) { - return error ? VLL_WARN : VLL_DBG; + /* If flows arrive in a batch, userspace may push down multiple + * unique flow definitions that overlap when wildcards are applied. + * Kernels that support flow wildcarding will reject these flows as + * duplicates (EEXIST), so lower the log level to debug for these + * types of messages. */ + return (error && error != EEXIST) ? VLL_WARN : VLL_DBG; } static bool