-make_openvswitch_device(unsigned int minor, char **fnp)
-{
- dev_t dev = makedev(get_openvswitch_major(), minor);
- const char dirname[] = "/dev/net";
- struct stat s;
- char fn[128];
-
- *fnp = NULL;
- sprintf(fn, "%s/dp%d", dirname, minor);
- if (!stat(fn, &s)) {
- if (!S_ISCHR(s.st_mode)) {
- VLOG_WARN_RL(&error_rl, "%s is not a character device, fixing",
- fn);
- } else if (s.st_rdev != dev) {
- VLOG_WARN_RL(&error_rl,
- "%s is device %u:%u instead of %u:%u, fixing",
- fn, major(s.st_rdev), minor(s.st_rdev),
- major(dev), minor(dev));
- } else {
- goto success;
+dpif_flow_del__(struct dpif *dpif, struct dpif_flow_del *del)
+{
+ int error;
+
+ COVERAGE_INC(dpif_flow_del);
+
+ error = dpif->dpif_class->flow_del(dpif, del);
+ if (error && del->stats) {
+ memset(del->stats, 0, sizeof *del->stats);
+ }
+ log_flow_del_message(dpif, del, error);
+ return error;
+}
+
+/* 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 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. */
+int
+dpif_flow_del(struct dpif *dpif,
+ const struct nlattr *key, size_t key_len,
+ struct dpif_flow_stats *stats)
+{
+ struct dpif_flow_del del;
+
+ del.key = key;
+ del.key_len = key_len;
+ del.stats = stats;
+ return dpif_flow_del__(dpif, &del);
+}
+
+/* Allocates thread-local state for use with the 'flow_dump_next' function for
+ * 'dpif'. On return, initializes '*statep' with any private data needed for
+ * iteration. */
+void
+dpif_flow_dump_state_init(const struct dpif *dpif, void **statep)
+{
+ dpif->dpif_class->flow_dump_state_init(statep);
+}
+
+/* Releases 'state' which was initialized by a call to the
+ * 'flow_dump_state_init' function for 'dpif'. */
+void
+dpif_flow_dump_state_uninit(const struct dpif *dpif, void *state)
+{
+ dpif->dpif_class->flow_dump_state_uninit(state);
+}
+
+/* Initializes 'dump' to begin dumping the flows in a dpif. On sucess,
+ * initializes 'dump' with any data needed for iteration and returns 0.
+ * Otherwise, returns a positive errno value describing the problem. */
+int
+dpif_flow_dump_start(struct dpif_flow_dump *dump, const struct dpif *dpif)
+{
+ int error;
+ dump->dpif = dpif;
+ error = dpif->dpif_class->flow_dump_start(dpif, &dump->iter);
+ log_operation(dpif, "flow_dump_start", error);
+ return error;
+}
+
+/* Attempts to retrieve another flow from 'dump', using 'state' for
+ * thread-local storage. 'dump' must have been initialized with a successful
+ * call to dpif_flow_dump_start(), and 'state' must have been initialized with
+ * dpif_flow_state_init().
+ *
+ * On success, updates the output parameters as described below and returns
+ * true. Otherwise, returns false. Failure might indicate an actual error or
+ * merely the end of the flow table. An error status for the entire dump
+ * operation is provided when it is completed by calling dpif_flow_dump_done().
+ * Multiple threads may use the same 'dump' with this function, but all other
+ * parameters must not be shared.
+ *
+ * On success, if 'key' and 'key_len' are nonnull then '*key' and '*key_len'
+ * 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 OVS_ACTION_ATTR_* representing the
+ * dumped flow's actions. If 'stats' is nonnull then it will 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' guarantees that it remains
+ * accessible and unchanging until at least the next call to 'flow_dump_next'
+ * or 'flow_dump_done' for 'dump' and 'state'. */
+bool
+dpif_flow_dump_next(struct dpif_flow_dump *dump, 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)
+{
+ const struct dpif *dpif = dump->dpif;
+ int error;
+
+ error = dpif->dpif_class->flow_dump_next(dpif, dump->iter, state,
+ key, key_len, mask, mask_len,
+ actions, actions_len, stats);
+ if (error) {
+ if (key) {
+ *key = NULL;
+ *key_len = 0;