diff --git a/NEWS b/NEWS
index 965facaf852d..55bd1255104d 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,9 @@ Post-v2.12.0
      * Add option to enable, disable and query TCP sequence checking in
        conntrack.
      * Add support for conntrack zone limits.
+     * New ovs-appctl "dpif-netdev/pmd-set-max-flow" and
+       "dpif-netdev/pmd-show-max-flow" commands for userspace datapath
+       change the max flows which support.
    - AF_XDP:
      * New option 'use-need-wakeup' for netdev-afxdp to control enabling
        of corresponding 'need_wakeup' flag in AF_XDP rings.  Enabled by default
diff --git a/lib/dpif-netdev-unixctl.man b/lib/dpif-netdev-unixctl.man
index 6c54f6f9cc3b..92cbcd07e984 100644
--- a/lib/dpif-netdev-unixctl.man
+++ b/lib/dpif-netdev-unixctl.man
@@ -217,3 +217,7 @@ with port names, which this thread polls.
 .
 .IP "\fBdpif-netdev/pmd-rxq-rebalance\fR [\fIdp\fR]"
 Reassigns rxqs to pmds in the datapath \fIdp\fR based on their current usage.
+.IP "\fBdpif-netdev/pmd-set-max-flow\fR [\fInumber\fR]"
+Sets the max flow which netdev datapath supports (default 65536).
+.IP "\fBdpif-netdev/pmd-show-max-flow"
+Shows the current max flow which netdev datapath supports.
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 24218210d4a8..f789ccf6cc8b 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -97,7 +97,6 @@ DEFINE_STATIC_PER_THREAD_DATA(uint32_t, recirc_depth, 0)
 #define DEFAULT_TX_FLUSH_INTERVAL 0
 
 /* Configuration parameters. */
-enum { MAX_FLOWS = 65536 };     /* Maximum number of flows in flow table. */
 enum { MAX_METERS = 65536 };    /* Maximum number of meters. */
 enum { MAX_BANDS = 8 };         /* Maximum number of bands / meter. */
 enum { N_METER_LOCKS = 64 };    /* Maximum number of meters. */
@@ -116,6 +115,9 @@ COVERAGE_DEFINE(datapath_drop_rx_invalid_packet);
 /* Protects against changes to 'dp_netdevs'. */
 static struct ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;
 
+/* Maximum number of flows in flow table. */
+static atomic_uint32_t netdev_max_flow = ATOMIC_VAR_INIT(65536);
+
 /* Contains all 'struct dp_netdev's. */
 static struct shash dp_netdevs OVS_GUARDED_BY(dp_netdev_mutex)
     = SHASH_INITIALIZER(&dp_netdevs);
@@ -1123,6 +1125,39 @@ pmd_info_show_perf(struct ds *reply,
     }
 }
 
+static void
+dpif_netdev_set_max_flow(struct unixctl_conn *conn,
+                         int argc OVS_UNUSED,
+                         const char *argv[],
+                         void *aux OVS_UNUSED)
+{
+    long long max_flow = atoll(argv[1]);
+
+    if (max_flow <= 0 || max_flow >= UINT32_MAX) {
+        unixctl_command_reply_error(conn,
+                                    "max-flow should: > 0 and < UINT32_MAX");
+        return;
+    }
+
+    atomic_store_relaxed(&netdev_max_flow, max_flow);
+    unixctl_command_reply(conn, NULL);
+}
+
+static void
+dpif_netdev_show_max_flow(struct unixctl_conn *conn,
+                          int argc OVS_UNUSED,
+                          const char *argv[] OVS_UNUSED,
+                          void *aux OVS_UNUSED)
+{
+    uint32_t max_flow;
+
+    atomic_read_relaxed(&netdev_max_flow, &max_flow);
+
+    char *reply = xasprintf("%u", max_flow);
+    unixctl_command_reply(conn, reply);
+    free(reply);
+}
+
 static int
 compare_poll_list(const void *a_, const void *b_)
 {
@@ -1427,6 +1462,14 @@ dpif_netdev_init(void)
                              "[-us usec] [-q qlen]",
                              0, 10, pmd_perf_log_set_cmd,
                              NULL);
+    unixctl_command_register("dpif-netdev/pmd-set-max-flow",
+                             "number",
+                             1, 1, dpif_netdev_set_max_flow,
+                             NULL);
+    unixctl_command_register("dpif-netdev/pmd-show-max-flow",
+                             "",
+                             0, 0, dpif_netdev_show_max_flow,
+                             NULL);
     return 0;
 }
 
@@ -3356,7 +3399,9 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
     netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL);
     if (!netdev_flow) {
         if (put->flags & DPIF_FP_CREATE) {
-            if (cmap_count(&pmd->flow_table) < MAX_FLOWS) {
+            uint32_t max_flow;
+            atomic_read_relaxed(&netdev_max_flow, &max_flow);
+            if (cmap_count(&pmd->flow_table) < max_flow) {
                 dp_netdev_flow_add(pmd, match, ufid, put->actions,
                                    put->actions_len);
                 error = 0;
