odp-util: Format and scan multiple MPLS labels.
[cascardo/ovs.git] / lib / dpif.h
index f4a2a9e..97d5d06 100644 (file)
  *
  *      In Open vSwitch userspace, "struct flow" is the typical way to describe
  *      a flow, but the datapath interface uses a different data format to
- *      allow ABI forward- and backward-compatibility.  datapath/README
+ *      allow ABI forward- and backward-compatibility.  datapath/README.md
  *      describes the rationale and design.  Refer to OVS_KEY_ATTR_* and
  *      "struct ovs_key_*" in include/odp-netlink.h for details.
  *      lib/odp-util.h defines several functions for working with these flows.
 #include <stddef.h>
 #include <stdint.h>
 #include "netdev.h"
-#include "ofpbuf.h"
+#include "dp-packet.h"
 #include "openflow/openflow.h"
+#include "ovs-numa.h"
 #include "packets.h"
 #include "util.h"
 
@@ -399,12 +400,13 @@ extern "C" {
 #endif
 
 struct dpif;
+struct dpif_class;
+struct dpif_flow;
 struct ds;
 struct flow;
+struct flow_wildcards;
 struct nlattr;
 struct sset;
-struct dpif_class;
-struct dpif_flow;
 
 int dp_register_provider(const struct dpif_class *);
 int dp_unregister_provider(const char *type);
@@ -420,7 +422,7 @@ int dpif_create(const char *name, const char *type, struct dpif **);
 int dpif_create_and_open(const char *name, const char *type, struct dpif **);
 void dpif_close(struct dpif *);
 
-void dpif_run(struct dpif *);
+bool dpif_run(struct dpif *);
 void dpif_wait(struct dpif *);
 
 const char *dpif_name(const struct dpif *);
@@ -503,28 +505,36 @@ struct dpif_flow_stats {
     uint16_t tcp_flags;
 };
 
-void dpif_flow_stats_extract(const struct flow *, const struct ofpbuf *packet,
+void dpif_flow_stats_extract(const struct flow *, const struct dp_packet *packet,
                              long long int used, struct dpif_flow_stats *);
 void dpif_flow_stats_format(const struct dpif_flow_stats *, struct ds *);
 
 enum dpif_flow_put_flags {
     DPIF_FP_CREATE = 1 << 0,    /* Allow creating a new flow. */
     DPIF_FP_MODIFY = 1 << 1,    /* Allow modifying an existing flow. */
-    DPIF_FP_ZERO_STATS = 1 << 2 /* Zero the stats of an existing flow. */
+    DPIF_FP_ZERO_STATS = 1 << 2, /* Zero the stats of an existing flow. */
+    DPIF_FP_PROBE = 1 << 3      /* Suppress error messages, if any. */
 };
 
+bool dpif_probe_feature(struct dpif *, const char *name,
+                        const struct ofpbuf *key, const ovs_u128 *ufid);
+void dpif_flow_hash(const struct dpif *, const void *key, size_t key_len,
+                    ovs_u128 *hash);
 int dpif_flow_flush(struct dpif *);
 int dpif_flow_put(struct dpif *, enum dpif_flow_put_flags,
                   const struct nlattr *key, size_t key_len,
                   const struct nlattr *mask, size_t mask_len,
                   const struct nlattr *actions, size_t actions_len,
+                  const ovs_u128 *ufid, const unsigned pmd_id,
                   struct dpif_flow_stats *);
 int dpif_flow_del(struct dpif *,
                   const struct nlattr *key, size_t key_len,
+                  const ovs_u128 *ufid, const unsigned pmd_id,
                   struct dpif_flow_stats *);
-int dpif_flow_get(const struct dpif *,
+int dpif_flow_get(struct dpif *,
                   const struct nlattr *key, size_t key_len,
-                  struct ofpbuf **, struct dpif_flow *);
+                  const ovs_u128 *ufid, const unsigned pmd_id,
+                  struct ofpbuf *, struct dpif_flow *);
 \f
 /* Flow dumping interface
  * ======================
@@ -554,13 +564,15 @@ int dpif_flow_get(const struct dpif *,
  *
  * All error reporting is deferred to the call to dpif_flow_dump_destroy().
  */
-struct dpif_flow_dump *dpif_flow_dump_create(const struct dpif *);
+struct dpif_flow_dump *dpif_flow_dump_create(const struct dpif *, bool terse);
 int dpif_flow_dump_destroy(struct dpif_flow_dump *);
 
 struct dpif_flow_dump_thread *dpif_flow_dump_thread_create(
     struct dpif_flow_dump *);
 void dpif_flow_dump_thread_destroy(struct dpif_flow_dump_thread *);
 
+#define PMD_ID_NULL OVS_CORE_UNSPEC
+
 /* A datapath flow as dumped by dpif_flow_dump_next(). */
 struct dpif_flow {
     const struct nlattr *key;     /* Flow key, as OVS_KEY_ATTR_* attrs. */
@@ -569,10 +581,15 @@ struct dpif_flow {
     size_t mask_len;              /* 'mask' length in bytes. */
     const struct nlattr *actions; /* Actions, as OVS_ACTION_ATTR_ */
     size_t actions_len;           /* 'actions' length in bytes. */
+    ovs_u128 ufid;                /* Unique flow identifier. */
+    bool ufid_present;            /* True if 'ufid' was provided by datapath.*/
+    unsigned pmd_id;              /* Datapath poll mode driver id. */
     struct dpif_flow_stats stats; /* Flow statistics. */
 };
 int dpif_flow_dump_next(struct dpif_flow_dump_thread *,
                         struct dpif_flow *flows, int max_flows);
+
+#define DPIF_FLOW_BUFSIZE 2048
 \f
 /* Operation batching interface.
  *
@@ -584,8 +601,35 @@ enum dpif_op_type {
     DPIF_OP_FLOW_PUT = 1,
     DPIF_OP_FLOW_DEL,
     DPIF_OP_EXECUTE,
+    DPIF_OP_FLOW_GET,
 };
 
+/* Add or modify a flow.
+ *
+ * The flow is specified by the Netlink 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 OVS_ACTION_ATTR_* in the 'actions_len'
+ * bytes starting at 'actions'.
+ *
+ *   - If the flow's key does not exist in the dpif, then the flow will be
+ *     added if 'flags' includes DPIF_FP_CREATE.  Otherwise the operation will
+ *     fail with ENOENT.
+ *
+ *     If the operation succeeds, then 'stats', if nonnull, will be zeroed.
+ *
+ *   - If the flow's key does exist in the dpif, then the flow's actions will
+ *     be updated if 'flags' includes DPIF_FP_MODIFY.  Otherwise the operation
+ *     will fail with EEXIST.  If the flow's actions are updated, then its
+ *     statistics will be zeroed if 'flags' includes DPIF_FP_ZERO_STATS, and
+ *     left as-is otherwise.
+ *
+ *     If the operation succeeds, then 'stats', if nonnull, will be set to the
+ *     flow's statistics before the update.
+ *
+ *   - If the datapath implements multiple pmd thread with its own flow
+ *     table, 'pmd_id' should be used to specify the particular polling
+ *     thread for the operation.
+ */
 struct dpif_flow_put {
     /* Input. */
     enum dpif_flow_put_flags flags; /* DPIF_FP_*. */
@@ -595,35 +639,106 @@ struct dpif_flow_put {
     size_t mask_len;                /* Length of 'mask' in bytes. */
     const struct nlattr *actions;   /* Actions to perform on flow. */
     size_t actions_len;             /* Length of 'actions' in bytes. */
+    const ovs_u128 *ufid;           /* Optional unique flow identifier. */
+    unsigned pmd_id;                /* Datapath poll mode driver id. */
 
     /* Output. */
     struct dpif_flow_stats *stats;  /* Optional flow statistics. */
 };
 
+/* Delete a flow.
+ *
+ * The flow is specified by the Netlink attributes with types OVS_KEY_ATTR_* in
+ * the 'key_len' bytes starting at 'key', or the unique identifier 'ufid'. If
+ * the flow was created using 'ufid', then 'ufid' must be specified to delete
+ * the flow. If both are specified, 'key' will be ignored for flow deletion.
+ * Succeeds with status 0 if the flow is deleted, or fails with ENOENT if the
+ * dpif does not contain such a flow.
+ *
+ * Callers should always provide the 'key' to improve dpif logging in the event
+ * of errors or unexpected behaviour.
+ *
+ * If the datapath implements multiple polling thread with its own flow table,
+ * 'pmd_id' should be used to specify the particular polling thread for the
+ * operation.
+ *
+ * If the operation succeeds, then 'stats', if nonnull, will be set to the
+ * flow's statistics before its deletion. */
 struct dpif_flow_del {
     /* Input. */
     const struct nlattr *key;       /* Flow to delete. */
     size_t key_len;                 /* Length of 'key' in bytes. */
+    const ovs_u128 *ufid;           /* Unique identifier of flow to delete. */
+    bool terse;                     /* OK to skip sending/receiving full flow
+                                     * info? */
+    unsigned pmd_id;                /* Datapath poll mode driver id. */
 
     /* Output. */
     struct dpif_flow_stats *stats;  /* Optional flow statistics. */
 };
 
+/* Executes actions on a specified packet.
+ *
+ * Performs the 'actions_len' bytes of actions in 'actions' on the Ethernet
+ * frame in 'packet' and on the packet metadata in 'md'.  May modify both
+ * 'packet' and 'md'.
+ *
+ * Some dpif providers do not implement every action.  The Linux kernel
+ * datapath, in particular, does not implement ARP field modification.  If
+ * 'needs_help' is true, the dpif layer executes in userspace all of the
+ * actions that it can, and for OVS_ACTION_ATTR_OUTPUT and
+ * OVS_ACTION_ATTR_USERSPACE actions it passes the packet through to the dpif
+ * implementation.
+ *
+ * This works even if 'actions_len' is too long for a Netlink attribute. */
 struct dpif_execute {
-    /* Raw support for execute passed along to the provider. */
+    /* Input. */
     const struct nlattr *actions;   /* Actions to execute on packet. */
     size_t actions_len;             /* Length of 'actions' in bytes. */
-    struct ofpbuf *packet;          /* Packet to execute. */
-    struct pkt_metadata md;         /* Packet metadata. */
-
-    /* Some dpif providers do not implement every action.  The Linux kernel
-     * datapath, in particular, does not implement ARP field modification.
-     *
-     * If this member is set to true, the dpif layer executes in userspace all
-     * of the actions that it can, and for OVS_ACTION_ATTR_OUTPUT and
-     * OVS_ACTION_ATTR_USERSPACE actions it passes the packet through to the
-     * dpif implementation. */
     bool needs_help;
+    bool probe;                     /* Suppress error messages. */
+    unsigned int mtu;               /* Maximum transmission unit to fragment.
+                                       0 if not a fragmented packet */
+
+    /* Input, but possibly modified as a side effect of execution. */
+    struct dp_packet *packet;          /* Packet to execute. */
+};
+
+/* Queries the 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', or the unique identifier 'ufid'. If
+ * the flow was created using 'ufid', then 'ufid' must be specified to fetch
+ * the flow. If both are specified, 'key' will be ignored for the flow query.
+ * 'buffer' must point to an initialized buffer, with a recommended size of
+ * DPIF_FLOW_BUFSIZE bytes.
+ *
+ * On success, 'flow' will be populated with the mask, actions and stats for
+ * the datapath flow corresponding to 'key'. The mask and actions may point
+ * within '*buffer', or may point at RCU-protected data. Therefore, callers
+ * that wish to hold these over quiescent periods must make a copy of these
+ * fields before quiescing.
+ *
+ * Callers should always provide 'key' to improve dpif logging in the event of
+ * errors or unexpected behaviour.
+ *
+ * If the datapath implements multiple polling thread with its own flow table,
+ * 'pmd_id' should be used to specify the particular polling thread for the
+ * operation.
+ *
+ * Succeeds with status 0 if the flow is fetched, or fails with ENOENT if no
+ * such flow exists. Other failures are indicated with a positive errno value.
+ */
+struct dpif_flow_get {
+    /* Input. */
+    const struct nlattr *key;       /* Flow to get. */
+    size_t key_len;                 /* Length of 'key' in bytes. */
+    const ovs_u128 *ufid;           /* Unique identifier of flow to get. */
+    unsigned pmd_id;                /* Datapath poll mode driver id. */
+    struct ofpbuf *buffer;          /* Storage for output parameters. */
+
+    /* Output. */
+    struct dpif_flow *flow;         /* Resulting flow from datapath. */
 };
 
 int dpif_execute(struct dpif *, struct dpif_execute *);
@@ -635,6 +750,7 @@ struct dpif_op {
         struct dpif_flow_put flow_put;
         struct dpif_flow_del flow_del;
         struct dpif_execute execute;
+        struct dpif_flow_get flow_get;
     } u;
 };
 
@@ -662,24 +778,69 @@ const char *dpif_upcall_type_to_string(enum dpif_upcall_type);
 struct dpif_upcall {
     /* All types. */
     enum dpif_upcall_type type;
-    struct ofpbuf packet;       /* Packet data. */
+    struct dp_packet packet;       /* Packet data. */
     struct nlattr *key;         /* Flow key. */
     size_t key_len;             /* Length of 'key' in bytes. */
+    ovs_u128 ufid;              /* Unique flow identifier for 'key'. */
+    struct nlattr *mru;         /* Maximum receive unit. */
 
     /* DPIF_UC_ACTION only. */
     struct nlattr *userdata;    /* Argument to OVS_ACTION_ATTR_USERSPACE. */
+    struct nlattr *out_tun_key;    /* Output tunnel key. */
+    struct nlattr *actions;    /* Argument to OVS_ACTION_ATTR_USERSPACE. */
 };
 
-typedef void exec_upcall_cb(struct dpif *, struct dpif_upcall *,
-                            struct ofpbuf *, int cnt);
+/* A callback to notify higher layer of dpif about to be purged, so that
+ * higher layer could try reacting to this (e.g. grabbing all flow stats
+ * before they are gone).  This function is currently implemented only by
+ * dpif-netdev.
+ *
+ * The caller needs to provide the 'aux' pointer passed down by higher
+ * layer from the dpif_register_notify_cb() function and the 'pmd_id' of
+ * the polling thread.
+ */
+    typedef void dp_purge_callback(void *aux, unsigned pmd_id);
+
+void dpif_register_dp_purge_cb(struct dpif *, dp_purge_callback *, void *aux);
+
+/* A callback to process an upcall, currently implemented only by dpif-netdev.
+ *
+ * The caller provides the 'packet' and 'flow' to process, the corresponding
+ * 'ufid' as generated by dpif_flow_hash(), the polling thread id 'pmd_id',
+ * the 'type' of the upcall, and if 'type' is DPIF_UC_ACTION then the
+ * 'userdata' attached to the action.
+ *
+ * The callback must fill in 'actions' with the datapath actions to apply to
+ * 'packet'.  'wc' and 'put_actions' will either be both null or both nonnull.
+ * If they are nonnull, then the caller will install a flow entry to process
+ * all future packets that match 'flow' and 'wc'; the callback must store a
+ * wildcard mask suitable for that purpose into 'wc'.  If the actions to store
+ * into the flow entry are the same as 'actions', then the callback may leave
+ * 'put_actions' empty; otherwise it must store the desired actions into
+ * 'put_actions'.
+ *
+ * Returns 0 if successful, ENOSPC if the flow limit has been reached and no
+ * flow should be installed, or some otherwise a positive errno value. */
+typedef int upcall_callback(const struct dp_packet *packet,
+                            const struct flow *flow,
+                            ovs_u128 *ufid,
+                            unsigned pmd_id,
+                            enum dpif_upcall_type type,
+                            const struct nlattr *userdata,
+                            struct ofpbuf *actions,
+                            struct flow_wildcards *wc,
+                            struct ofpbuf *put_actions,
+                            void *aux);
+
+void dpif_register_upcall_cb(struct dpif *, upcall_callback *, void *aux);
 
 int dpif_recv_set(struct dpif *, bool enable);
 int dpif_handlers_set(struct dpif *, uint32_t n_handlers);
+int dpif_poll_threads_set(struct dpif *, const char *cmask);
 int dpif_recv(struct dpif *, uint32_t handler_id, struct dpif_upcall *,
               struct ofpbuf *);
 void dpif_recv_purge(struct dpif *);
 void dpif_recv_wait(struct dpif *, uint32_t handler_id);
-void dpif_register_upcall_cb(struct dpif *, exec_upcall_cb *);
 void dpif_enable_upcall(struct dpif *);
 void dpif_disable_upcall(struct dpif *);
 
@@ -693,6 +854,8 @@ void dpif_get_netflow_ids(const struct dpif *,
 int dpif_queue_to_priority(const struct dpif *, uint32_t queue_id,
                            uint32_t *priority);
 
+char *dpif_get_dp_version(const struct dpif *);
+bool dpif_supports_tnl_push_pop(const struct dpif *);
 #ifdef  __cplusplus
 }
 #endif