diff --git a/lib/odp-execute-private.c b/lib/odp-execute-private.c
index 92db2386c..25dbbfefc 100644
--- a/lib/odp-execute-private.c
+++ b/lib/odp-execute-private.c
@@ -27,12 +27,13 @@
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(odp_execute_impl);
+static int active_action_impl_index;
 
 static struct odp_execute_action_impl action_impls[] = {
     [ACTION_IMPL_SCALAR] = {
         .available = false,
         .name = "scalar",
-        .init_func = NULL,
+        .init_func = odp_action_scalar_init,
     },
 };
 
@@ -45,6 +46,21 @@ action_impl_copy_funcs(struct odp_execute_action_impl *src,
     }
 }
 
+int
+odp_execute_action_set(const char *name,
+                       struct odp_execute_action_impl *active)
+{
+    for (int i = 0; i < ACTION_IMPL_MAX; i++) {
+        /* String compare, and set ptrs atomically. */
+        if (!strcmp(action_impls[i].name, name)) {
+            action_impl_copy_funcs(active, &action_impls[i]);;
+            active_action_impl_index = i;
+            return 0;
+        }
+    }
+    return -EINVAL;
+}
+
 void
 odp_execute_action_init(void)
 {
diff --git a/lib/odp-execute-private.h b/lib/odp-execute-private.h
index 08d1faf38..c5ab00b07 100644
--- a/lib/odp-execute-private.h
+++ b/lib/odp-execute-private.h
@@ -71,4 +71,12 @@ BUILD_ASSERT_DECL(ACTION_IMPL_SCALAR == 0);
  */
 void odp_execute_action_init(void);
 
+/* Init functions for the action implementations. Initializes the function
+ * pointers for optimized action types.
+ */
+int odp_action_scalar_init(struct odp_execute_action_impl *self);
+
+int odp_execute_action_set(const char *name,
+                               struct odp_execute_action_impl *active);
+
 #endif /* ODP_EXTRACT_PRIVATE */
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 67ebbe195..eff80d93f 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -834,6 +834,30 @@ requires_datapath_assistance(const struct nlattr *a)
     return false;
 }
 
+static void
+action_pop_vlan(struct dp_packet_batch *batch,
+                const struct nlattr *a OVS_UNUSED)
+{
+    struct dp_packet *packet;
+
+    DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
+        eth_pop_vlan(packet);
+    }
+}
+
+/* Implementation of the scalar actions impl init function. Build up the
+ * array of func ptrs here.
+ */
+int
+odp_action_scalar_init(struct odp_execute_action_impl *self)
+{
+    /* Set function pointers for actions that can be applied directly, these
+     * are identified by OVS_ACTION_ATTR_*. */
+    self->funcs[OVS_ACTION_ATTR_POP_VLAN] = action_pop_vlan;
+
+    return 0;
+}
+
 /* The active function pointers on the datapath. ISA optimized implementations
  * are enabled by plugging them into this static arary, which is consulted when
  * applying actions on the datapath.
@@ -846,10 +870,22 @@ odp_execute_init(void)
     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
     if (ovsthread_once_start(&once)) {
         odp_execute_action_init();
+        odp_actions_impl_set("scalar");
         ovsthread_once_done(&once);
     }
 }
 
+int
+odp_actions_impl_set(const char *name)
+{
+
+    int err = odp_execute_action_set(name, &actions_active_impl);
+    if (err) {
+        VLOG_ERR("Failed setting action implementation to %s, error %d",
+                 name, err);
+    }
+    return err;
+}
 
 /* Executes all of the 'actions_len' bytes of datapath actions in 'actions' on
  * the packets in 'batch'.  If 'steal' is true, possibly modifies and
@@ -964,12 +1000,6 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
             break;
         }
 
-        case OVS_ACTION_ATTR_POP_VLAN:
-            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
-                eth_pop_vlan(packet);
-            }
-            break;
-
         case OVS_ACTION_ATTR_PUSH_MPLS: {
             const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
 
@@ -1120,6 +1150,8 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
         case OVS_ACTION_ATTR_CT:
         case OVS_ACTION_ATTR_UNSPEC:
         case __OVS_ACTION_ATTR_MAX:
+        /* The following actions are handled by the scalar implementation. */
+        case OVS_ACTION_ATTR_POP_VLAN:
             OVS_NOT_REACHED();
         }
 
diff --git a/lib/odp-execute.h b/lib/odp-execute.h
index 0921ee924..50d47b716 100644
--- a/lib/odp-execute.h
+++ b/lib/odp-execute.h
@@ -35,6 +35,8 @@ void odp_execute_init(void);
 typedef void (*odp_execute_action_cb)(struct dp_packet_batch *batch,
                                       const struct nlattr *action);
 
+int odp_actions_impl_set(const char *name);
+
 typedef void (*odp_execute_cb)(void *dp, struct dp_packet_batch *batch,
                                const struct nlattr *action, bool should_steal);
 
