#include "poll-loop.h"
#include "shash.h"
#include "svec.h"
+#include "timeval.h"
#include "util.h"
#include "valgrind.h"
#include "vlog.h"
static void log_flow_message(const struct dpif *dpif, int error,
const char *operation,
const struct nlattr *key, size_t key_len,
- const struct odp_flow_stats *stats,
+ const struct dpif_flow_stats *stats,
const struct nlattr *actions, size_t actions_len);
static void log_operation(const struct dpif *, const char *operation,
int error);
return dpif->base_name;
}
-/* Enumerates all names that may be used to open 'dpif' into 'all_names'. The
- * Linux datapath, for example, supports opening a datapath both by number,
- * e.g. "dp0", and by the name of the datapath's local port. For some
- * datapaths, this might be an infinite set (e.g. in a file name, slashes may
- * be duplicated any number of times), in which case only the names most likely
- * to be used will be enumerated.
- *
- * The caller must already have initialized 'all_names'. Any existing names in
- * 'all_names' will not be disturbed. */
-int
-dpif_get_all_names(const struct dpif *dpif, struct svec *all_names)
-{
- if (dpif->dpif_class->get_all_names) {
- int error = dpif->dpif_class->get_all_names(dpif, all_names);
- if (error) {
- VLOG_WARN_RL(&error_rl,
- "failed to retrieve names for datpath %s: %s",
- dpif_name(dpif), strerror(error));
- }
- return error;
- } else {
- svec_add(all_names, dpif_base_name(dpif));
- return 0;
- }
-}
-
-
/* Destroys the datapath that 'dpif' is connected to, first removing all of its
* ports. After calling this function, it does not make sense to pass 'dpif'
* to any functions other than dpif_name() or dpif_close(). */
dpif->dpif_class->port_poll_wait(dpif);
}
+/* Appends a human-readable representation of 'stats' to 's'. */
+void
+dpif_flow_stats_format(const struct dpif_flow_stats *stats, struct ds *s)
+{
+ ds_put_format(s, "packets:%"PRIu64", bytes:%"PRIu64", used:",
+ stats->n_packets, stats->n_bytes);
+ if (stats->used) {
+ ds_put_format(s, "%.3fs", (time_msec() - stats->used) / 1000.0);
+ } else {
+ ds_put_format(s, "never");
+ }
+ /* XXX tcp_flags? */
+}
+
/* Deletes all flows from 'dpif'. Returns 0 if successful, otherwise a
* positive errno value. */
int
* If 'stats' is nonnull, then on success it will be updated with the flow's
* statistics. */
int
-dpif_flow_get(const struct dpif *dpif, int flags,
+dpif_flow_get(const struct dpif *dpif,
const struct nlattr *key, size_t key_len,
- struct ofpbuf **actionsp, struct odp_flow_stats *stats)
+ struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
{
int error;
COVERAGE_INC(dpif_flow_get);
- error = dpif->dpif_class->flow_get(dpif, flags, key, key_len, actionsp,
- stats);
+ error = dpif->dpif_class->flow_get(dpif, key, key_len, actionsp, stats);
if (error) {
if (actionsp) {
*actionsp = NULL;
/* Adds or modifies a flow in 'dpif'. The flow is specified by the Netlink
* attributes with types ODP_KEY_ATTR_* in the 'key_len' bytes starting at
* 'key'. The associated actions are specified by the Netlink attributes with
- * types ODPAT_* in the 'actions_len' bytes starting at 'actions'.
+ * types ODP_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 ODPPF_CREATE. Otherwise the operation will fail with
+ * 'flags' includes DPIF_FP_CREATE. Otherwise the operation will fail with
* ENOENT.
*
* If the operation succeeds, then 'stats', if nonnull, will be zeroed.
*
* - If the flow's key does exist in 'dpif', then the flow's actions will be
- * updated if 'flags' includes ODPPF_MODIFY. Otherwise the operation will
+ * updated if 'flags' includes DPIF_FP_MODIFY. Otherwise the operation will
* fail with EEXIST. If the flow's actions are updated, then its statistics
- * will be zeroed if 'flags' includes ODPPF_ZERO_STATS, and left as-is
+ * will be zeroed if 'flags' includes DPIF_FP_ZERO_STATS, and left as-is
* otherwise.
*
* If the operation succeeds, then 'stats', if nonnull, will be set to the
* flow's statistics before the update.
*/
int
-dpif_flow_put(struct dpif *dpif, int flags,
+dpif_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
const struct nlattr *key, size_t key_len,
const struct nlattr *actions, size_t actions_len,
- struct odp_flow_stats *stats)
+ struct dpif_flow_stats *stats)
{
int error;
COVERAGE_INC(dpif_flow_put);
+ assert(!(flags & ~(DPIF_FP_CREATE | DPIF_FP_MODIFY | DPIF_FP_ZERO_STATS)));
error = dpif->dpif_class->flow_put(dpif, flags, key, key_len,
actions, actions_len, stats);
memset(stats, 0, sizeof *stats);
}
if (should_log_flow_message(error)) {
- enum { ODPPF_ALL = ODPPF_CREATE | ODPPF_MODIFY | ODPPF_ZERO_STATS };
struct ds s;
ds_init(&s);
ds_put_cstr(&s, "put");
- if (flags & ODPPF_CREATE) {
+ if (flags & DPIF_FP_CREATE) {
ds_put_cstr(&s, "[create]");
}
- if (flags & ODPPF_MODIFY) {
+ if (flags & DPIF_FP_MODIFY) {
ds_put_cstr(&s, "[modify]");
}
- if (flags & ODPPF_ZERO_STATS) {
+ if (flags & DPIF_FP_ZERO_STATS) {
ds_put_cstr(&s, "[zero]");
}
- if (flags & ~ODPPF_ALL) {
- ds_put_format(&s, "[%x]", flags & ~ODPPF_ALL);
- }
log_flow_message(dpif, error, ds_cstr(&s), key, key_len, stats,
actions, actions_len);
ds_destroy(&s);
int
dpif_flow_del(struct dpif *dpif,
const struct nlattr *key, size_t key_len,
- struct odp_flow_stats *stats)
+ struct dpif_flow_stats *stats)
{
int error;
* On success, if 'key' and 'key_len' are nonnull then '*key' and '*key_len'
* will be set to Netlink attributes with types ODP_KEY_ATTR_* representing the
* dumped flow's key. If 'actions' and 'actions_len' are nonnull then they are
- * set to Netlink attributes with types ODPAT_* representing the dumped flow's
- * actions. If 'stats' is nonnull then it will be set to the dumped flow's
- * statistics.
+ * set to Netlink attributes with types ODP_ACTION_ATTR_* representing the
+ * dumped flow's actions. If 'stats' is nonnull then it will be set to the
+ * dumped flow's statistics.
*
* All of the returned data is owned by 'dpif', not by the caller, and the
* caller must not modify or free it. 'dpif' guarantees that it remains
dpif_flow_dump_next(struct dpif_flow_dump *dump,
const struct nlattr **key, size_t *key_len,
const struct nlattr **actions, size_t *actions_len,
- const struct odp_flow_stats **stats)
+ const struct dpif_flow_stats **stats)
{
const struct dpif *dpif = dump->dpif;
int error = dump->error;
return error;
}
-/* Retrieves 'dpif''s "listen mask" into '*listen_mask'. Each ODPL_* bit set
- * in '*listen_mask' indicates that dpif_recv() will receive messages of that
- * type. Returns 0 if successful, otherwise a positive errno value. */
+static bool OVS_UNUSED
+is_valid_listen_mask(int listen_mask)
+{
+ return !(listen_mask & ~((1u << DPIF_UC_MISS) |
+ (1u << DPIF_UC_ACTION) |
+ (1u << DPIF_UC_SAMPLE)));
+}
+
+/* Retrieves 'dpif''s "listen mask" into '*listen_mask'. A 1-bit of value 2**X
+ * set in '*listen_mask' indicates that dpif_recv() will receive messages of
+ * the type (from "enum dpif_upcall_type") with value X. Returns 0 if
+ * successful, otherwise a positive errno value. */
int
dpif_recv_get_mask(const struct dpif *dpif, int *listen_mask)
{
if (error) {
*listen_mask = 0;
}
+ assert(is_valid_listen_mask(*listen_mask));
log_operation(dpif, "recv_get_mask", error);
return error;
}
-/* Sets 'dpif''s "listen mask" to 'listen_mask'. Each ODPL_* bit set in
- * '*listen_mask' requests that dpif_recv() receive messages of that type.
- * Returns 0 if successful, otherwise a positive errno value. */
+/* Sets 'dpif''s "listen mask" to 'listen_mask'. A 1-bit of value 2**X set in
+ * '*listen_mask' requests that dpif_recv() will receive messages of the type
+ * (from "enum dpif_upcall_type") with value X. Returns 0 if successful,
+ * otherwise a positive errno value. */
int
dpif_recv_set_mask(struct dpif *dpif, int listen_mask)
{
- int error = dpif->dpif_class->recv_set_mask(dpif, listen_mask);
+ int error;
+
+ assert(is_valid_listen_mask(listen_mask));
+
+ error = dpif->dpif_class->recv_set_mask(dpif, listen_mask);
log_operation(dpif, "recv_set_mask", error);
return error;
}
}
/* Polls for an upcall from 'dpif'. If successful, stores the upcall into
- * '*upcall'. Only upcalls of the types selected with the set_listen_mask
+ * '*upcall'. Only upcalls of the types selected with dpif_recv_set_mask()
* member function will ordinarily be received (but if a message type is
* enabled and then later disabled, some stragglers might pop up).
*
odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
VLOG_DBG("%s: %s upcall on port %"PRIu16": %s", dpif_name(dpif),
- (upcall->type == _ODPL_MISS_NR ? "miss"
- : upcall->type == _ODPL_ACTION_NR ? "action"
- : upcall->type == _ODPL_SFLOW_NR ? "sFlow"
+ (upcall->type == DPIF_UC_MISS ? "miss"
+ : upcall->type == DPIF_UC_ACTION ? "action"
+ : upcall->type == DPIF_UC_SAMPLE ? "sample"
: "<unknown>"),
flow.in_port, s);
free(s);
}
/* Translates OpenFlow queue ID 'queue_id' (in host byte order) into a priority
- * value for use in the ODPAT_SET_PRIORITY action. On success, returns 0 and
- * stores the priority into '*priority'. On failure, returns a positive errno
- * value and stores 0 into '*priority'. */
+ * value for use in the ODP_ACTION_ATTR_SET_PRIORITY action. On success,
+ * returns 0 and stores the priority into '*priority'. On failure, returns a
+ * positive errno value and stores 0 into '*priority'. */
int
dpif_queue_to_priority(const struct dpif *dpif, uint32_t queue_id,
uint32_t *priority)
static void
log_flow_message(const struct dpif *dpif, int error, const char *operation,
const struct nlattr *key, size_t key_len,
- const struct odp_flow_stats *stats,
+ const struct dpif_flow_stats *stats,
const struct nlattr *actions, size_t actions_len)
{
struct ds ds = DS_EMPTY_INITIALIZER;
odp_flow_key_format(key, key_len, &ds);
if (stats) {
ds_put_cstr(&ds, ", ");
- format_odp_flow_stats(&ds, stats);
+ dpif_flow_stats_format(stats, &ds);
}
if (actions || actions_len) {
ds_put_cstr(&ds, ", actions:");