COVERAGE_DEFINE(dpif_execute_with_help);
static const struct dpif_class *base_dpif_classes[] = {
-#ifdef __linux__
- &dpif_linux_class,
+#if defined(__linux__) || defined(_WIN32)
+ &dpif_netlink_class,
#endif
&dpif_netdev_class,
};
int error);
static void log_execute_message(struct dpif *, const struct dpif_execute *,
bool subexecute, int error);
+static void log_flow_get_message(const struct dpif *,
+ const struct dpif_flow_get *, int error);
static void
dp_initialize(void)
return error;
}
-/* Queries 'dpif' for a flow entry. The flow is specified by the Netlink
- * 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
- * failure, returns a positive errno value.
- *
- * On success, '*bufp' will be set to an ofpbuf owned by the caller that
- * contains the response for 'flow->mask' and 'flow->actions'. The caller must
- * supply a valid pointer, and must free the ofpbuf (with ofpbuf_delete()) when
- * it is no longer needed.
- *
- * On success, 'flow' will be populated with the mask, actions and stats for
- * the datapath flow corresponding to 'key'. The mask and actions will point
- * within '*bufp'.
- *
- * Implementations may opt to point 'flow->mask' and/or 'flow->actions' at
- * RCU-protected data rather than making a copy of them. Therefore, callers
- * that wish to hold these over quiescent periods must make a copy of these
- * fields before quiescing. */
+/* A dpif_operate() wrapper for performing a single DPIF_OP_FLOW_GET. */
int
-dpif_flow_get(const struct dpif *dpif,
+dpif_flow_get(struct dpif *dpif,
const struct nlattr *key, size_t key_len,
- struct ofpbuf **bufp, struct dpif_flow *flow)
+ struct ofpbuf *buf, struct dpif_flow *flow)
{
- int error;
- struct nlattr *mask, *actions;
- size_t mask_len, actions_len;
- struct dpif_flow_stats stats;
+ struct dpif_op *opp;
+ struct dpif_op op;
- COVERAGE_INC(dpif_flow_get);
+ op.type = DPIF_OP_FLOW_GET;
+ op.u.flow_get.key = key;
+ op.u.flow_get.key_len = key_len;
+ op.u.flow_get.buffer = buf;
+ op.u.flow_get.flow = flow;
+ op.u.flow_get.flow->key = key;
+ op.u.flow_get.flow->key_len = key_len;
- *bufp = NULL;
- error = dpif->dpif_class->flow_get(dpif, key, key_len, bufp,
- &mask, &mask_len,
- &actions, &actions_len, &stats);
- if (error) {
- memset(flow, 0, sizeof *flow);
- ofpbuf_delete(*bufp);
- *bufp = NULL;
- } else {
- flow->mask = mask;
- flow->mask_len = mask_len;
- flow->actions = actions;
- flow->actions_len = actions_len;
- flow->stats = stats;
- }
- if (should_log_flow_message(error)) {
- log_flow_message(dpif, error, "flow_get", key, key_len,
- NULL, 0, &flow->stats,
- flow->actions, flow->actions_len);
- }
- return error;
+ opp = &op;
+ dpif_operate(dpif, &opp, 1);
+
+ return op.error;
}
/* A dpif_operate() wrapper for performing a single DPIF_OP_FLOW_PUT. */
case OVS_ACTION_ATTR_PUSH_MPLS:
case OVS_ACTION_ATTR_POP_MPLS:
case OVS_ACTION_ATTR_SET:
+ case OVS_ACTION_ATTR_SET_MASKED:
case OVS_ACTION_ATTR_SAMPLE:
case OVS_ACTION_ATTR_UNSPEC:
case __OVS_ACTION_ATTR_MAX:
break;
}
+ case DPIF_OP_FLOW_GET: {
+ struct dpif_flow_get *get = &op->u.flow_get;
+
+ COVERAGE_INC(dpif_flow_get);
+ log_flow_get_message(dpif, get, error);
+
+ if (error) {
+ memset(get->flow, 0, sizeof *get->flow);
+ }
+ break;
+ }
+
case DPIF_OP_FLOW_DEL: {
struct dpif_flow_del *del = &op->u.flow_del;
}
void
-dpif_register_upcall_cb(struct dpif *dpif, exec_upcall_cb *cb)
+dpif_register_upcall_cb(struct dpif *dpif, upcall_callback *cb, void *aux)
{
if (dpif->dpif_class->register_upcall_cb) {
- dpif->dpif_class->register_upcall_cb(dpif, cb);
+ dpif->dpif_class->register_upcall_cb(dpif, cb, aux);
}
}
}
}
+/* If 'dpif' creates its own I/O polling threads, refreshes poll threads
+ * configuration. */
+int
+dpif_poll_threads_set(struct dpif *dpif, unsigned int n_rxqs,
+ const char *cmask)
+{
+ int error = 0;
+
+ if (dpif->dpif_class->poll_threads_set) {
+ error = dpif->dpif_class->poll_threads_set(dpif, n_rxqs, cmask);
+ if (error) {
+ log_operation(dpif, "poll_threads_set", error);
+ }
+ }
+
+ return error;
+}
+
/* Polls for an upcall from 'dpif' for an upcall handler. Since there
* there can be multiple poll loops, 'handler_id' is needed as index to
* identify the corresponding poll loop. If successful, stores the upcall
* called after the dpif_provider's '->execute' function, which is allowed to
* modify execute->packet and execute->md. In practice, though:
*
- * - dpif-linux doesn't modify execute->packet or execute->md.
+ * - dpif-netlink doesn't modify execute->packet or execute->md.
*
* - dpif-netdev does modify them but it is less likely to have problems
* because it is built into ovs-vswitchd and cannot have version skew,
free(packet);
}
}
+
+static void
+log_flow_get_message(const struct dpif *dpif, const struct dpif_flow_get *get,
+ int error)
+{
+ if (should_log_flow_message(error)) {
+ log_flow_message(dpif, error, "flow_get",
+ get->key, get->key_len,
+ get->flow->mask, get->flow->mask_len,
+ &get->flow->stats,
+ get->flow->actions, get->flow->actions_len);
+ }
+}