- struct odp_port *port);
-
- /* Stores in 'ports' information about up to 'n' ports attached to 'dpif',
- * in no particular order. Returns the number of ports attached to 'dpif'
- * (not the number stored), if successful, otherwise a negative errno
- * value. */
- int (*port_list)(const struct dpif *dpif, struct odp_port *ports, int n);
-
- /* Stores in 'ports' the port numbers of up to 'n' ports that belong to
- * 'group' in 'dpif'. Returns the number of ports in 'group' (not the
- * number stored), if successful, otherwise a negative errno value. */
- int (*port_group_get)(const struct dpif *dpif, int group,
- uint16_t ports[], int n);
-
- /* Changes port group 'group' in 'dpif' to consist of the 'n' ports whose
- * numbers are given in 'ports'.
- *
- * Use the get_stats member function to obtain the number of supported port
- * groups. */
- int (*port_group_set)(struct dpif *dpif, int group,
- const uint16_t ports[], int n);
-
- /* For each flow 'flow' in the 'n' flows in 'flows':
- *
- * - If a flow matching 'flow->key' exists in 'dpif':
- *
- * Stores 0 into 'flow->stats.error' and stores statistics for the flow
- * into 'flow->stats'.
- *
- * If 'flow->n_actions' is zero, then 'flow->actions' is ignored. If
- * 'flow->n_actions' is nonzero, then 'flow->actions' should point to
- * an array of the specified number of actions. At most that many of
- * the flow's actions will be copied into that array.
- * 'flow->n_actions' will be updated to the number of actions actually
- * present in the flow, which may be greater than the number stored if
- * the flow has more actions than space available in the array.
- *
- * - Flow-specific errors are indicated by a positive errno value in
- * 'flow->stats.error'. In particular, ENOENT indicates that no flow
- * matching 'flow->key' exists in 'dpif'. When an error value is stored,
- * the contents of 'flow->key' are preserved but other members of 'flow'
- * should be treated as indeterminate.
- *
- * Returns 0 if all 'n' flows in 'flows' were updated (whether they were
- * individually successful or not is indicated by 'flow->stats.error',
- * however). Returns a positive errno value if an error that prevented
- * this update occurred, in which the caller must not depend on any
- * elements in 'flows' being updated or not updated.
- */
- int (*flow_get)(const struct dpif *dpif, struct odp_flow flows[], int n);
-
- /* Adds or modifies a flow in 'dpif' as specified in 'put':
+ struct dpif_port *port);
+
+ /* Returns one greater than the largest port number accepted in flow
+ * actions. */
+ int (*get_max_ports)(const struct dpif *dpif);
+
+ /* Attempts to begin dumping the ports in a dpif. On success, returns 0
+ * and initializes '*statep' with any data needed for iteration. On
+ * failure, returns a positive errno value. */
+ int (*port_dump_start)(const struct dpif *dpif, void **statep);
+
+ /* Attempts to retrieve another port from 'dpif' for 'state', which was
+ * initialized by a successful call to the 'port_dump_start' function for
+ * 'dpif'. On success, stores a new dpif_port into 'port' and returns 0.
+ * Returns EOF if the end of the port table has been reached, or a positive
+ * errno value on error. This function will not be called again once it
+ * returns nonzero once for a given iteration (but the 'port_dump_done'
+ * function will be called afterward).
+ *
+ * The dpif provider retains ownership of the data stored in 'port'. It
+ * must remain valid until at least the next call to 'port_dump_next' or
+ * 'port_dump_done' for 'state'. */
+ int (*port_dump_next)(const struct dpif *dpif, void *state,
+ struct dpif_port *port);
+
+ /* Releases resources from 'dpif' for 'state', which was initialized by a
+ * successful call to the 'port_dump_start' function for 'dpif'. */
+ int (*port_dump_done)(const struct dpif *dpif, void *state);
+
+ /* Polls for changes in the set of ports in 'dpif'. If the set of ports in
+ * 'dpif' has changed, then this function should do one of the
+ * following:
+ *
+ * - Preferably: store the name of the device that was added to or deleted
+ * from 'dpif' in '*devnamep' and return 0. The caller is responsible
+ * for freeing '*devnamep' (with free()) when it no longer needs it.
+ *
+ * - Alternatively: return ENOBUFS, without indicating the device that was
+ * added or deleted.
+ *
+ * Occasional 'false positives', in which the function returns 0 while
+ * indicating a device that was not actually added or deleted or returns
+ * ENOBUFS without any change, are acceptable.
+ *
+ * If the set of ports in 'dpif' has not changed, returns EAGAIN. May also
+ * return other positive errno values to indicate that something has gone
+ * wrong. */
+ int (*port_poll)(const struct dpif *dpif, char **devnamep);
+
+ /* Arranges for the poll loop to wake up when 'port_poll' will return a
+ * value other than EAGAIN. */
+ void (*port_poll_wait)(const 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
+ * 'key'.
+ *
+ * Returns 0 if successful. If no flow matches, returns ENOENT. On other
+ * failure, returns a positive errno value.