datapath: Always use generic stats for devices (vports)
[sliver-openvswitch.git] / lib / dpif.c
index 3786bb7..ad143c8 100644 (file)
@@ -101,38 +101,6 @@ dp_initialize(void)
     }
 }
 
-/* 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
@@ -232,8 +200,10 @@ dp_enumerate_names(const char *type, struct sset *names)
     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)
 {
@@ -244,10 +214,10 @@ 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));
     }
 }
 
@@ -345,6 +315,25 @@ dpif_close(struct dpif *dpif)
     }
 }
 
+/* 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 *
@@ -389,7 +378,7 @@ dpif_delete(struct dpif *dpif)
 /* 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) {
@@ -701,7 +690,7 @@ dpif_flow_flush(struct dpif *dpif)
 }
 
 /* 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
@@ -750,9 +739,9 @@ dpif_flow_get(const struct dpif *dpif,
 }
 
 /* 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
@@ -808,7 +797,7 @@ dpif_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
 
 /* 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. */
@@ -854,9 +843,9 @@ dpif_flow_dump_start(struct dpif_flow_dump *dump, const struct dpif *dpif)
  * 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.
  *
@@ -924,11 +913,15 @@ dpif_flow_dump_done(struct dpif_flow_dump *dump)
 }
 
 /* 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)
 {
@@ -936,7 +929,8 @@ dpif_execute(struct dpif *dpif,
 
     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;
     }
@@ -957,6 +951,18 @@ dpif_execute(struct dpif *dpif,
     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_UC_SAMPLE: return "sample";
+    case DPIF_N_UC_TYPES: default: return "<unknown>";
+    }
+}
+
 static bool OVS_UNUSED
 is_valid_listen_mask(int listen_mask)
 {
@@ -1050,20 +1056,22 @@ dpif_recv(struct dpif *dpif, struct dpif_upcall *upcall)
 {
     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;
 }
@@ -1098,7 +1106,7 @@ dpif_get_netflow_ids(const struct dpif *dpif,
 }
 
 /* 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