- /* Stores up to 'n' flows in 'dpif' into 'flows', updating their statistics
- * and actions as described under the flow_get member function. If
- * successful, returns the number of flows actually present in 'dpif',
- * which might be greater than the number stored (if 'dpif' has more than
- * 'n' flows). On failure, returns a negative errno value. */
- int (*flow_list)(const struct dpif *dpif, struct odp_flow flows[], int n);
-
- /* Performs the 'n_actions' actions in 'actions' on the Ethernet frame
- * specified in 'packet'.
- *
- * Pretends that the frame was originally received on the port numbered
- * 'in_port'. This affects only ODPAT_OUTPUT_GROUP actions, which will not
- * send a packet out their input port. Specify the number of an unused
- * port (e.g. UINT16_MAX is currently always unused) to avoid this
- * behavior. */
- int (*execute)(struct dpif *dpif, uint16_t in_port,
- const union odp_action actions[], int n_actions,
- const struct ofpbuf *packet);
-
- /* Retrieves 'dpif''s "listen mask" into '*listen_mask'. Each ODPL_* bit
- * set in '*listen_mask' indicates the 'dpif' will receive messages of the
- * corresponding type when it calls the recv member function. */
- int (*recv_get_mask)(const struct dpif *dpif, int *listen_mask);
-
- /* Sets 'dpif''s "listen mask" to 'listen_mask'. Each ODPL_* bit set in
- * 'listen_mask' indicates the 'dpif' will receive messages of the
- * corresponding type when it calls the recv member function. */
- int (*recv_set_mask)(struct dpif *dpif, int listen_mask);
-
- /* Attempts to receive a message from 'dpif'. If successful, stores the
- * message into '*packetp'. The message, if one is received, must begin
- * with 'struct odp_msg' as a header. Only messages of the types selected
- * with the set_listen_mask member function should be received.
- *
- * This function must not block. If no message is ready to be received
- * when it is called, it should return EAGAIN without blocking. */
- int (*recv)(struct dpif *dpif, struct ofpbuf **packetp);
-
- /* Arranges for the poll loop to wake up when 'dpif' has a message queued
- * to be received with the recv member function. */
- void (*recv_wait)(struct dpif *dpif);
+ /* Allocates thread-local state for use with the function 'flow_dump_next'.
+ * On return, initializes '*statep' with any private data needed for
+ * iteration. */
+ void (*flow_dump_state_init)(void **statep);
+
+ /* Attempts to begin dumping the flows in a dpif. On success, returns 0
+ * and initializes '*iterp' with any shared data needed for iteration.
+ * On failure, returns a positive errno value. */
+ int (*flow_dump_start)(const struct dpif *dpif, void **iterp);
+
+ /* Attempts to retrieve another flow from 'dpif' for 'iter', using
+ * 'state' for storage. 'iter' must have been initialized by a successful
+ * call to the 'flow_dump_start' function for 'dpif'. 'state' must have
+ * been initialised with a call to the 'flow_dump_state_init' function for
+ * 'dpif.
+ *
+ * On success, updates the output parameters as described below and returns
+ * 0. Returns EOF if the end of the flow table has been reached, or a
+ * positive errno value on error. Multiple threads may use the same 'dpif'
+ * and 'iter' with this function, but all other parameters must be
+ * different for each thread. If this function returns non-zero,
+ * subsequent calls with the same arguments will also return non-zero.
+ *
+ * On success:
+ *
+ * - If 'key' and 'key_len' are nonnull, then '*key' and '*key_len'
+ * must be set to Netlink attributes with types OVS_KEY_ATTR_*
+ * representing the dumped flow's key.
+ *
+ * - If 'mask' and 'mask_len' are nonnull then '*mask' and '*mask_len'
+ * must be set to Netlink attributes with types of OVS_KEY_ATTR_*
+ * representing the dumped flow's mask.
+ *
+ * - If 'actions' and 'actions_len' are nonnull then they should be set
+ * to Netlink attributes with types OVS_ACTION_ATTR_* representing
+ * the dumped flow's actions.
+ *
+ * - If 'stats' is nonnull then it should be set to the dumped flow's
+ * statistics.
+ *
+ * All of the returned data is owned by 'dpif', not by the caller, and the
+ * caller must not modify or free it. 'dpif' must guarantee that it
+ * remains accessible and unchanging until at least the next call to
+ * 'flow_dump_next' or 'flow_dump_done' for 'iter' and 'state'. */
+ int (*flow_dump_next)(const struct dpif *dpif, void *iter, void *state,
+ 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 struct dpif_flow_stats **stats);
+
+ /* Determines whether the next call to 'flow_dump_next' with 'state' will
+ * modify or free the keys that it previously returned. 'state' must have
+ * been initialized by a call to 'flow_dump_state_init' for 'dpif'.
+ *
+ * 'dpif' guarantees that data returned by flow_dump_next() will remain
+ * accessible and unchanging until the next call. This function provides a
+ * way for callers to determine whether that guarantee extends beyond the
+ * next call.
+ *
+ * Returns true if the next call to flow_dump_next() is expected to be
+ * destructive to previously returned keys for 'state', false otherwise. */
+ bool (*flow_dump_next_may_destroy_keys)(void *state);
+
+ /* Releases resources from 'dpif' for 'iter', which was initialized by a
+ * successful call to the 'flow_dump_start' function for 'dpif'. Callers
+ * must ensure that this function is called once within a given iteration,
+ * as the final flow dump operation. */
+ int (*flow_dump_done)(const struct dpif *dpif, void *iter);
+
+ /* Releases 'state' which was initialized by a call to the
+ * 'flow_dump_state_init' function for this 'dpif'. */
+ void (*flow_dump_state_uninit)(void *statep);
+
+ /* Performs the 'execute->actions_len' bytes of actions in
+ * 'execute->actions' on the Ethernet frame in 'execute->packet'
+ * and on the packet metadata in 'execute->md'.
+ * May modify both packet and metadata. */
+ int (*execute)(struct dpif *dpif, struct dpif_execute *execute);
+
+ /* Executes each of the 'n_ops' operations in 'ops' on 'dpif', in the order
+ * in which they are specified, placing each operation's results in the
+ * "output" members documented in comments.
+ *
+ * This function is optional. It is only worthwhile to implement it if
+ * 'dpif' can perform operations in batch faster than individually. */
+ void (*operate)(struct dpif *dpif, struct dpif_op **ops, size_t n_ops);
+
+ /* Enables or disables receiving packets with dpif_recv() for 'dpif'.
+ * Turning packet receive off and then back on is allowed to change Netlink
+ * PID assignments (see ->port_get_pid()). The client is responsible for
+ * updating flows as necessary if it does this. */
+ int (*recv_set)(struct dpif *dpif, bool enable);
+
+ /* Refreshes the poll loops and Netlink sockets associated to each port,
+ * when the number of upcall handlers (upcall receiving thread) is changed
+ * to 'n_handlers' and receiving packets for 'dpif' is enabled by
+ * recv_set().
+ *
+ * Since multiple upcall handlers can read upcalls simultaneously from
+ * 'dpif', each port can have multiple Netlink sockets, one per upcall
+ * handler. So, handlers_set() is responsible for the following tasks:
+ *
+ * When receiving upcall is enabled, extends or creates the
+ * configuration to support:
+ *
+ * - 'n_handlers' Netlink sockets for each port.
+ *
+ * - 'n_handlers' poll loops, one for each upcall handler.
+ *
+ * - registering the Netlink sockets for the same upcall handler to
+ * the corresponding poll loop.
+ * */
+ int (*handlers_set)(struct dpif *dpif, uint32_t n_handlers);
+
+ /* Translates OpenFlow queue ID 'queue_id' (in host byte order) into a
+ * priority value used for setting packet priority. */
+ int (*queue_to_priority)(const struct dpif *dpif, uint32_t queue_id,
+ uint32_t *priority);
+
+ /* Polls for an upcall from 'dpif' for an upcall handler. Since there
+ * can be multiple poll loops (see ->handlers_set()), 'handler_id' is
+ * needed as index to identify the corresponding poll loop. If
+ * successful, stores the upcall into '*upcall', using 'buf' for
+ * storage. Should only be called if 'recv_set' has been used to enable
+ * receiving packets from 'dpif'.
+ *
+ * The implementation should point 'upcall->key' and 'upcall->userdata'
+ * (if any) into data in the caller-provided 'buf'. The implementation may
+ * also use 'buf' for storing the data of 'upcall->packet'. If necessary
+ * to make room, the implementation may reallocate the data in 'buf'.
+ *
+ * The caller owns the data of 'upcall->packet' and may modify it. If
+ * packet's headroom is exhausted as it is manipulated, 'upcall->packet'
+ * will be reallocated. This requires the data of 'upcall->packet' to be
+ * released with ofpbuf_uninit() before 'upcall' is destroyed. However,
+ * when an error is returned, the 'upcall->packet' may be uninitialized
+ * and should not be released.
+ *
+ * This function must not block. If no upcall is pending when it is
+ * called, it should return EAGAIN without blocking. */
+ int (*recv)(struct dpif *dpif, uint32_t handler_id,
+ struct dpif_upcall *upcall, struct ofpbuf *buf);
+
+ /* Arranges for the poll loop for an upcall handler to wake up when 'dpif'
+ * has a message queued to be received with the recv member functions.
+ * Since there can be multiple poll loops (see ->handlers_set()),
+ * 'handler_id' is needed as index to identify the corresponding poll loop.
+ * */
+ void (*recv_wait)(struct dpif *dpif, uint32_t handler_id);
+
+ /* Throws away any queued upcalls that 'dpif' currently has ready to
+ * return. */
+ void (*recv_purge)(struct dpif *dpif);