}
}
-/* Performs periodic work needed by all the various kinds of dpifs.
- *
- * If your program opens any dpifs, it must call both this function and
- * netdev_run() within its main poll loop. */
-void
-dp_run(void)
-{
- struct shash_node *node;
- SHASH_FOR_EACH(node, &dpif_classes) {
- const struct registered_dpif_class *registered_class = node->data;
- if (registered_class->dpif_class->run) {
- registered_class->dpif_class->run();
- }
- }
-}
-
-/* Arranges for poll_block() to wake up when dp_run() needs to be called.
- *
- * If your program opens any dpifs, it must call both this function and
- * netdev_wait() within its main poll loop. */
-void
-dp_wait(void)
-{
- struct shash_node *node;
- SHASH_FOR_EACH(node, &dpif_classes) {
- const struct registered_dpif_class *registered_class = node->data;
- if (registered_class->dpif_class->wait) {
- registered_class->dpif_class->wait();
- }
- }
-}
-
/* Registers a new datapath provider. After successful registration, new
* datapaths of that type can be opened using dpif_open(). */
int
return error;
}
-/* Parses 'datapath name', which is of the form type@name into its
- * component pieces. 'name' and 'type' must be freed by the caller. */
+/* Parses 'datapath_name_', which is of the form [type@]name into its
+ * component pieces. 'name' and 'type' must be freed by the caller.
+ *
+ * The returned 'type' is normalized, as if by dpif_normalize_type(). */
void
dp_parse_name(const char *datapath_name_, char **name, char **type)
{
if (separator) {
*separator = '\0';
*type = datapath_name;
- *name = xstrdup(separator + 1);
+ *name = xstrdup(dpif_normalize_type(separator + 1));
} else {
*name = datapath_name;
- *type = NULL;
+ *type = xstrdup(dpif_normalize_type(NULL));
}
}
dp_initialize();
- if (!type || *type == '\0') {
- type = "system";
- }
+ type = dpif_normalize_type(type);
registered_class = shash_find_data(&dpif_classes, type);
if (!registered_class) {
}
}
+/* Performs periodic work needed by 'dpif'. */
+void
+dpif_run(struct dpif *dpif)
+{
+ if (dpif->dpif_class->run) {
+ dpif->dpif_class->run(dpif);
+ }
+}
+
+/* Arranges for poll_block() to wake up when dp_run() needs to be called for
+ * 'dpif'. */
+void
+dpif_wait(struct dpif *dpif)
+{
+ if (dpif->dpif_class->wait) {
+ dpif->dpif_class->wait(dpif);
+ }
+}
+
/* Returns the name of datapath 'dpif' prefixed with the type
* (for use in log messages). */
const char *
return dpif->base_name;
}
+/* Returns the fully spelled out name for the given datapath 'type'.
+ *
+ * Normalized type string can be compared with strcmp(). Unnormalized type
+ * string might be the same even if they have different spellings. */
+const char *
+dpif_normalize_type(const char *type)
+{
+ return type && type[0] ? type : "system";
+}
+
/* 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(). */
/* Retrieves statistics for 'dpif' into 'stats'. Returns 0 if successful,
* otherwise a positive errno value. */
int
-dpif_get_dp_stats(const struct dpif *dpif, struct odp_stats *stats)
+dpif_get_dp_stats(const struct dpif *dpif, struct ovs_dp_stats *stats)
{
int error = dpif->dpif_class->get_stats(dpif, stats);
if (error) {
} else {
memset(port, 0, sizeof *port);
- /* Log level is DBG here because all the current callers are interested
- * in whether 'dpif' actually has a port 'devname', so that it's not an
- * issue worth logging if it doesn't. */
- VLOG_DBG_RL(&error_rl, "%s: failed to query port %s: %s",
- dpif_name(dpif), devname, strerror(error));
+ /* For ENOENT or ENODEV we use DBG level because the caller is probably
+ * interested in whether 'dpif' actually has a port 'devname', so that
+ * it's not an issue worth logging if it doesn't. Other errors are
+ * uncommon and more likely to indicate a real problem. */
+ VLOG_RL(&error_rl,
+ error == ENOENT || error == ENODEV ? VLL_DBG : VLL_WARN,
+ "%s: failed to query port %s: %s",
+ dpif_name(dpif), devname, strerror(error));
}
return error;
}
}
/* Queries 'dpif' for a flow entry. The flow is specified by the Netlink
- * attributes with types ODP_KEY_ATTR_* in the 'key_len' bytes starting at
+ * attributes with types OVS_KEY_ATTR_* in the 'key_len' bytes starting at
* 'key'.
*
* Returns 0 if successful. If no flow matches, returns ENOENT. On other
}
/* 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
+ * 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 ODP_ACTION_ATTR_* in the 'actions_len' bytes starting at 'actions'.
+ * 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
/* Deletes a flow from 'dpif' and returns 0, or returns ENOENT if 'dpif' does
* not contain such a flow. The flow is specified by the Netlink attributes
- * with types ODP_KEY_ATTR_* in the 'key_len' bytes starting at 'key'.
+ * with types OVS_KEY_ATTR_* in the 'key_len' bytes starting at 'key'.
*
* If the operation succeeds, then 'stats', if nonnull, will be set to the
* flow's statistics before its deletion. */
* completed by calling dpif_flow_dump_done().
*
* 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
+ * will be set to Netlink attributes with types OVS_KEY_ATTR_* representing the
* dumped flow's key. If 'actions' and 'actions_len' are nonnull then they are
- * set to Netlink attributes with types ODP_ACTION_ATTR_* representing the
+ * set to Netlink attributes with types OVS_ACTION_ATTR_* representing the
* dumped flow's actions. If 'stats' is nonnull then it will be set to the
* dumped flow's statistics.
*
}
/* Causes 'dpif' to perform the 'actions_len' bytes of actions in 'actions' on
- * the Ethernet frame specified in 'packet'.
+ * 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.)
*
* Returns 0 if successful, otherwise a positive errno value. */
int
dpif_execute(struct dpif *dpif,
+ const struct nlattr *key, size_t key_len,
const struct nlattr *actions, size_t actions_len,
const struct ofpbuf *buf)
{
COVERAGE_INC(dpif_execute);
if (actions_len > 0) {
- error = dpif->dpif_class->execute(dpif, actions, actions_len, buf);
+ error = dpif->dpif_class->execute(dpif, key, key_len,
+ actions, actions_len, buf);
} else {
error = 0;
}
return error;
}
+/* Returns a string that represents 'type', for use in log messages. */
+const char *
+dpif_upcall_type_to_string(enum dpif_upcall_type type)
+{
+ switch (type) {
+ case DPIF_UC_MISS: return "miss";
+ case DPIF_UC_ACTION: return "action";
+ case DPIF_N_UC_TYPES: default: return "<unknown>";
+ }
+}
+
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)));
+ (1u << DPIF_UC_ACTION)));
}
/* Retrieves 'dpif''s "listen mask" into '*listen_mask'. A 1-bit of value 2**X
return error;
}
-/* Retrieve the sFlow sampling probability. '*probability' is expressed as the
- * number of packets out of UINT_MAX to sample, e.g. probability/UINT_MAX is
- * the probability of sampling a given packet.
- *
- * Returns 0 if successful, otherwise a positive errno value. EOPNOTSUPP
- * indicates that 'dpif' does not support sFlow sampling. */
-int
-dpif_get_sflow_probability(const struct dpif *dpif, uint32_t *probability)
-{
- int error = (dpif->dpif_class->get_sflow_probability
- ? dpif->dpif_class->get_sflow_probability(dpif, probability)
- : EOPNOTSUPP);
- if (error) {
- *probability = 0;
- }
- log_operation(dpif, "get_sflow_probability", error);
- return error;
-}
-
-/* Set the sFlow sampling probability. 'probability' is expressed as the
- * number of packets out of UINT_MAX to sample, e.g. probability/UINT_MAX is
- * the probability of sampling a given packet.
- *
- * Returns 0 if successful, otherwise a positive errno value. EOPNOTSUPP
- * indicates that 'dpif' does not support sFlow sampling. */
-int
-dpif_set_sflow_probability(struct dpif *dpif, uint32_t probability)
-{
- int error = (dpif->dpif_class->set_sflow_probability
- ? dpif->dpif_class->set_sflow_probability(dpif, probability)
- : EOPNOTSUPP);
- log_operation(dpif, "set_sflow_probability", error);
- return error;
-}
-
/* Polls for an upcall from 'dpif'. If successful, stores the upcall into
* '*upcall'. Only upcalls of the types selected with dpif_recv_set_mask()
* member function will ordinarily be received (but if a message type is
{
int error = dpif->dpif_class->recv(dpif, upcall);
if (!error && !VLOG_DROP_DBG(&dpmsg_rl)) {
- struct flow flow;
- char *s;
-
- s = ofp_packet_to_string(upcall->packet->data,
- upcall->packet->size, upcall->packet->size);
- 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 == DPIF_UC_MISS ? "miss"
- : upcall->type == DPIF_UC_ACTION ? "action"
- : upcall->type == DPIF_UC_SAMPLE ? "sample"
- : "<unknown>"),
- flow.in_port, s);
- free(s);
+ struct ds flow;
+ char *packet;
+
+ packet = ofp_packet_to_string(upcall->packet->data,
+ upcall->packet->size,
+ upcall->packet->size);
+
+ ds_init(&flow);
+ odp_flow_key_format(upcall->key, upcall->key_len, &flow);
+
+ VLOG_DBG("%s: %s upcall:\n%s\n%s",
+ dpif_name(dpif), dpif_upcall_type_to_string(upcall->type),
+ ds_cstr(&flow), packet);
+
+ ds_destroy(&flow);
+ free(packet);
}
return error;
}
}
/* Translates OpenFlow queue ID 'queue_id' (in host byte order) into a priority
- * value for use in the ODP_ACTION_ATTR_SET_PRIORITY action. On success,
+ * value for use in the OVS_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