dpif-netdev: Allow multi-rx-queue, multi-pmd-thread configuration.
[cascardo/ovs.git] / lib / dpif.c
index 1f15840..bdefdcc 100644 (file)
@@ -59,8 +59,8 @@ COVERAGE_DEFINE(dpif_purge);
 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,
 };
@@ -98,6 +98,8 @@ static void log_flow_del_message(struct dpif *, const struct dpif_flow_del *,
                                  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)
@@ -829,59 +831,27 @@ dpif_flow_flush(struct dpif *dpif)
     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. */
@@ -1071,6 +1041,7 @@ dpif_execute_helper_cb(void *aux_, struct dpif_packet **packets, int cnt,
     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:
@@ -1177,6 +1148,18 @@ dpif_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops)
                     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;
 
@@ -1272,10 +1255,10 @@ dpif_handlers_set(struct dpif *dpif, uint32_t n_handlers)
 }
 
 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);
     }
 }
 
@@ -1317,6 +1300,24 @@ dpif_print_packet(struct dpif *dpif, struct dpif_upcall *upcall)
     }
 }
 
+/* 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
@@ -1541,7 +1542,7 @@ log_flow_del_message(struct dpif *dpif, const struct dpif_flow_del *del,
  * 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,
@@ -1574,3 +1575,16 @@ log_execute_message(struct dpif *dpif, const struct dpif_execute *execute,
         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);
+    }
+}