+struct dpif_execute_helper_aux {
+ struct dpif *dpif;
+ int error;
+};
+
+/* This is called for actions that need the context of the datapath to be
+ * meaningful. */
+static void
+dpif_execute_helper_cb(void *aux_, struct ofpbuf *packet,
+ const struct pkt_metadata *md,
+ const struct nlattr *action, bool may_steal OVS_UNUSED)
+{
+ struct dpif_execute_helper_aux *aux = aux_;
+ struct dpif_execute execute;
+ int type = nl_attr_type(action);
+
+ switch ((enum ovs_action_attr)type) {
+ case OVS_ACTION_ATTR_OUTPUT:
+ case OVS_ACTION_ATTR_USERSPACE:
+ execute.actions = action;
+ execute.actions_len = NLA_ALIGN(action->nla_len);
+ execute.packet = packet;
+ execute.md = *md;
+ execute.needs_help = false;
+ aux->error = aux->dpif->dpif_class->execute(aux->dpif, &execute);
+ break;
+
+ case OVS_ACTION_ATTR_PUSH_VLAN:
+ case OVS_ACTION_ATTR_POP_VLAN:
+ case OVS_ACTION_ATTR_PUSH_MPLS:
+ case OVS_ACTION_ATTR_POP_MPLS:
+ case OVS_ACTION_ATTR_SET:
+ case OVS_ACTION_ATTR_SAMPLE:
+ case OVS_ACTION_ATTR_UNSPEC:
+ case __OVS_ACTION_ATTR_MAX:
+ OVS_NOT_REACHED();
+ }
+}
+
+/* Executes 'execute' by performing most of the actions in userspace and
+ * passing the fully constructed packets to 'dpif' for output and userspace
+ * actions.
+ *
+ * This helps with actions that a given 'dpif' doesn't implement directly. */