#include "svec.h"
#include "util.h"
#include "valgrind.h"
-
+#include "fatal-signal.h"
#include "vlog.h"
-#define THIS_MODULE VLM_dpif
+
+VLOG_DEFINE_THIS_MODULE(dpif)
static const struct dpif_class *base_dpif_classes[] = {
+#ifdef HAVE_NETLINK
&dpif_linux_class,
+#endif
&dpif_netdev_class,
};
};
static struct shash dpif_classes = SHASH_INITIALIZER(&dpif_classes);
+
/* Rate limit for individual messages going to or from the datapath, output at
* DBG level. This is very high because, if these are enabled, it is because
* we really need to see them. */
static struct vlog_rate_limit dpmsg_rl = VLOG_RATE_LIMIT_INIT(600, 600);
/* Not really much point in logging many dpif errors. */
-static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5);
+static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5);
static void log_operation(const struct dpif *, const char *operation,
int error);
if (status < 0) {
int i;
+#ifdef THREADED
+ struct shash_node *node;
+#endif
status = 0;
for (i = 0; i < ARRAY_SIZE(base_dpif_classes); i++) {
dp_register_provider(base_dpif_classes[i]);
}
+
+#ifdef THREADED
+ /* register an exit handler for the registered classes */
+ SHASH_FOR_EACH(node, &dpif_classes) {
+ const struct registered_dpif_class *registered_class = node->data;
+ if (registered_class->dpif_class.exit_hook) {
+ fatal_signal_add_hook(registered_class->dpif_class.exit_hook,
+ NULL, NULL, true);
+ }
+ }
+#endif
}
}
+
+
/* Performs periodic work needed by all the various kinds of dpifs.
*
* If your program opens any dpifs, it must call both this function and
}
}
+#ifdef THREADED
+/* Start the datapath management.
+ *
+ * This function has been thought for a scenario in which the management of the
+ * datapath module and the ofproto module are performed in separate
+ * threads/processes module. */
+void
+dp_start(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.start) {
+ registered_class->dpif_class.start();
+ }
+ }
+}
+#endif
+
+
/* Registers a new datapath provider. After successful registration, new
* datapaths of that type can be opened using dpif_open(). */
int
dp_register_provider(const struct dpif_class *new_class)
{
struct registered_dpif_class *registered_class;
-
+
if (shash_find(&dpif_classes, new_class->type)) {
VLOG_WARN("attempted to register duplicate datapath provider: %s",
new_class->type);
if (dpif) {
struct registered_dpif_class *registered_class;
- registered_class = shash_find_data(&dpif_classes,
+ registered_class = shash_find_data(&dpif_classes,
dpif->dpif_class->type);
assert(registered_class);
assert(registered_class->refcount);
if (!error) {
error = flow->stats.error;
}
+ if (error) {
+ /* Make the results predictable on error. */
+ memset(&flow->stats, 0, sizeof flow->stats);
+ flow->n_actions = 0;
+ }
if (should_log_flow_message(error)) {
log_flow_operation(dpif, "flow_get", error, flow);
}
/* Attempts to receive a message from 'dpif'. If successful, stores the
* message into '*packetp'. The message, if one is received, will begin with
- * 'struct odp_msg' as a header. Only messages of the types selected with
+ * 'struct odp_msg' as a header, and will have at least DPIF_RECV_MSG_PADDING
+ * bytes of headroom. Only messages of the types selected with
* dpif_set_listen_mask() will ordinarily be received (but if a message type is
* enabled and then later disabled, some stragglers might pop up).
*
{
int error = dpif->dpif_class->recv(dpif, packetp);
if (!error) {
+ struct ofpbuf *buf = *packetp;
+
+ assert(ofpbuf_headroom(buf) >= DPIF_RECV_MSG_PADDING);
if (VLOG_IS_DBG_ENABLED()) {
- struct ofpbuf *buf = *packetp;
struct odp_msg *msg = buf->data;
void *payload = msg + 1;
size_t payload_len = buf->size - sizeof *msg;
*engine_type = dpif->netflow_engine_type;
*engine_id = dpif->netflow_engine_id;
}
+
+/* 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'. */
+int
+dpif_queue_to_priority(const struct dpif *dpif, uint32_t queue_id,
+ uint32_t *priority)
+{
+ int error = (dpif->dpif_class->queue_to_priority
+ ? dpif->dpif_class->queue_to_priority(dpif, queue_id,
+ priority)
+ : EOPNOTSUPP);
+ if (error) {
+ *priority = 0;
+ }
+ log_operation(dpif, "queue_to_priority", error);
+ return error;
+}
\f
void
dpif_init(struct dpif *dpif, const struct dpif_class *dpif_class,