+/* 'udpif_key's are responsible for tracking the little bit of state udpif
+ * needs to do flow expiration which can't be pulled directly from the
+ * datapath. They may be created or maintained by any revalidator during
+ * the dump phase, but are owned by a single revalidator, and are destroyed
+ * by that revalidator during the garbage-collection phase.
+ *
+ * While some elements of a udpif_key are protected by a mutex, the ukey itself
+ * is not. Therefore it is not safe to destroy a udpif_key except when all
+ * revalidators are in garbage collection phase, or they aren't running. */
+struct udpif_key {
+ struct hmap_node hmap_node; /* In parent revalidator 'ukeys' map. */
+
+ /* These elements are read only once created, and therefore aren't
+ * protected by a mutex. */
+ const struct nlattr *key; /* Datapath flow key. */
+ size_t key_len; /* Length of 'key'. */
+
+ struct ovs_mutex mutex; /* Guards the following. */
+ struct dpif_flow_stats stats OVS_GUARDED; /* Last known stats.*/
+ long long int created OVS_GUARDED; /* Estimate of creation time. */
+ bool mark OVS_GUARDED; /* For mark and sweep garbage
+ collection. */
+ bool flow_exists OVS_GUARDED; /* Ensures flows are only deleted
+ once. */
+
+ struct xlate_cache *xcache OVS_GUARDED; /* Cache for xlate entries that
+ * are affected by this ukey.
+ * Used for stats and learning.*/
+ struct odputil_keybuf key_buf; /* Memory for 'key'. */
+};
+
+/* Flow miss batching.
+ *
+ * Some dpifs implement operations faster when you hand them off in a batch.
+ * To allow batching, "struct flow_miss" queues the dpif-related work needed
+ * for a given flow. Each "struct flow_miss" corresponds to sending one or
+ * more packets, plus possibly installing the flow in the dpif. */
+struct flow_miss {
+ struct hmap_node hmap_node;
+ struct ofproto_dpif *ofproto;
+
+ struct flow flow;
+ const struct nlattr *key;
+ size_t key_len;
+ enum dpif_upcall_type upcall_type;
+ struct dpif_flow_stats stats;
+ odp_port_t odp_in_port;
+
+ uint64_t slow_path_buf[128 / 8];
+ struct odputil_keybuf mask_buf;
+
+ struct xlate_out xout;
+
+ bool put;
+};
+
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+static struct list all_udpifs = LIST_INITIALIZER(&all_udpifs);
+
+static size_t read_upcalls(struct handler *,
+ struct upcall upcalls[FLOW_MISS_MAX_BATCH],
+ struct flow_miss miss_buf[FLOW_MISS_MAX_BATCH],
+ struct hmap *);
+static void handle_upcalls(struct handler *, struct hmap *, struct upcall *,
+ size_t n_upcalls);
+static void udpif_stop_threads(struct udpif *);
+static void udpif_start_threads(struct udpif *, size_t n_handlers,
+ size_t n_revalidators);
+static void *udpif_upcall_handler(void *);
+static void *udpif_revalidator(void *);
+static uint64_t udpif_get_n_flows(struct udpif *);
+static void revalidate(struct revalidator *);
+static void revalidator_sweep(struct revalidator *);
+static void revalidator_purge(struct revalidator *);
+static void upcall_unixctl_show(struct unixctl_conn *conn, int argc,
+ const char *argv[], void *aux);
+static void upcall_unixctl_disable_megaflows(struct unixctl_conn *, int argc,
+ const char *argv[], void *aux);
+static void upcall_unixctl_enable_megaflows(struct unixctl_conn *, int argc,
+ const char *argv[], void *aux);
+static void upcall_unixctl_set_flow_limit(struct unixctl_conn *conn, int argc,
+ const char *argv[], void *aux);
+
+static struct udpif_key *ukey_create(const struct nlattr *key, size_t key_len,
+ long long int used);
+static void ukey_delete(struct revalidator *, struct udpif_key *);
+
+static atomic_bool enable_megaflows = ATOMIC_VAR_INIT(true);