diff --git a/tests/ovn-sbctl.at b/tests/ovn-sbctl.at
index f49134381..34ee452e5 100644
--- a/tests/ovn-sbctl.at
+++ b/tests/ovn-sbctl.at
@@ -175,4 +175,46 @@ inactivity_probe    : 30000
 
 OVN_SBCTL_TEST([ovn_sbctl_invalid_0x_flow], [invalid 0x flow], [
 check ovn-sbctl lflow-list 0x12345678
-])
\ No newline at end of file
+])
+
+dnl ---------------------------------------------------------------------
+
+AT_SETUP([ovn-sbctl --count lflow-list/dump-flows])
+OVN_SBCTL_TEST_START
+
+count_entries() {
+    ovn-sbctl --column=_uuid list   Logical_Flow | sed -r '/^\s*$/d'  | wc -l
+}
+
+count_pipeline() {
+    ovn-sbctl  --column=pipeline list  Logical_Flow | grep $1 | sed -r '/^\s*$/d'  | wc -l
+}
+
+# we start with empty Logical_Flow table
+# validate that the table is indeed empty
+AT_CHECK([count_entries], [0], [dnl
+0
+])
+
+AT_CHECK([ovn-sbctl --count lflow-list], [0], [dnl
+Total number of logical flows = 0
+])
+
+# create some logical flows
+check ovn-nbctl ls-add count-test
+total_lflows=`count_entries`
+egress_lflows=`count_pipeline egress`
+ingress_lflows=`count_pipeline ingress`
+
+AT_CHECK_UNQUOTED([ovn-sbctl --count lflow-list | grep "flows =" | awk 'NF>1{print $NF}'], [0], [dnl
+$total_lflows
+])
+AT_CHECK_UNQUOTED([ovn-sbctl --count lflow-list | grep Total | grep egress | awk 'NF>1{print $NF}'], [0], [dnl
+$egress_lflows
+])
+AT_CHECK_UNQUOTED([ovn-sbctl --count lflow-list | grep Total | grep ingress | awk 'NF>1{print $NF}'], [0], [dnl
+$ingress_lflows
+])
+
+OVN_SBCTL_TEST_STOP
+AT_CLEANUP
diff --git a/utilities/ovn-sbctl.8.xml b/utilities/ovn-sbctl.8.xml
index 4e6b21c47..2030bcda9 100644
--- a/utilities/ovn-sbctl.8.xml
+++ b/utilities/ovn-sbctl.8.xml
@@ -416,10 +416,20 @@
           <var>chassis</var>.  The <code>--ovs</code> and <code>--stats</code>
           can also be used in conjunction with <code>--vflows</code>.
         </p>
+       
+        <p>
+         <code>--count</code> <code>lflow-list</code> [<var>logical-datapath</var>]
+         prints numbers of logical flows per table and per datapath.
+        </p>
+
       </dd>
 
       <dt>[<code>--uuid</code>] <code>dump-flows</code> [<var>logical-datapath</var>]</dt>
       <dd>Alias for <code>lflow-list</code>.</dd>
+      
+      <dt><code>--count</code> <code>dump-flow</code> [<var>logical-datapath</var>]</dt>
+      <dd>Alias for <code>--count</code>  <code>lflow-list</code> [<var>logical-datapath</var>] </dd>
+      
     </dl>
 
     <h2>Remote Connectivity Commands</h2>
diff --git a/utilities/ovn-sbctl.c b/utilities/ovn-sbctl.c
index 53f10cdd8..ca9d21d52 100644
--- a/utilities/ovn-sbctl.c
+++ b/utilities/ovn-sbctl.c
@@ -898,11 +898,92 @@ sbctl_lflow_add(struct sbctl_lflow **lflows,
     if (*n_flows == *n_capacity) {
         *lflows = x2nrealloc(*lflows, n_capacity, sizeof **lflows);
     }
-    (*lflows)[*n_flows].lflow = lflow;
-    (*lflows)[*n_flows].dp = dp;
+    (*lflows)[ *n_flows ].lflow = lflow;
+    (*lflows)[ *n_flows ].dp = dp;
     (*n_flows)++;
 }
 
+static void
+print_datapath_prompt(const struct sbrec_datapath_binding *dp,
+                      const struct uuid *uuid,
+                      char *pipeline) {
+        printf("Datapath: ");
+        print_datapath_name(dp);
+        printf(" ("UUID_FMT") pipeline: %s\n", UUID_ARGS(uuid), pipeline);
+}
+
+static void
+print_datapath_sum(const struct sbrec_datapath_binding *dp,
+                   const struct uuid *uuid,
+                   char *pipeline,
+                   long lflows) {
+        printf("Total number of logical flows in the datapath ");
+        print_datapath_name(dp);
+        printf(" ("UUID_FMT") pipeline: %s = %ld\n\n",
+                UUID_ARGS(uuid), pipeline, lflows);
+}
+
+
+static void
+print_lflows_count(int64_t table_id, const char *name, long count) {
+    printf("  table=%-2"PRId64"(%-19s) lflows=%ld\n", \
+             table_id, name, count);
+}
+
+static void
+print_lflow_counters(size_t n_flows, struct sbctl_lflow *lflows)
+{
+    const struct sbctl_lflow *curr, *prev = NULL;
+    long table_lflows = 0;
+    long dp_lflows = 0;
+
+    for (size_t i = 0; i < n_flows; i++) {
+       bool new_datapath = false;
+       curr = &lflows[i];
+       if (!prev
+            || prev->dp != curr->dp
+            || strcmp(prev->lflow->pipeline, curr->lflow->pipeline)) {
+            new_datapath = true;
+        }
+
+        if (prev &&
+           (prev->lflow->table_id != curr->lflow->table_id || new_datapath)) {
+            print_lflows_count(prev->lflow->table_id,
+                smap_get_def(&prev->lflow->external_ids, "stage-name", ""),
+                table_lflows);
+            table_lflows = 1;
+            if (new_datapath) {
+                print_datapath_sum(prev->dp, &prev->dp->header_.uuid,
+                                  prev->lflow->pipeline, dp_lflows);
+                dp_lflows = 1;
+            } else {
+                dp_lflows++;
+            }
+        } else {
+            dp_lflows++;
+            table_lflows++;
+        }
+
+        if (new_datapath) {
+            print_datapath_prompt(curr->dp,
+                                  &curr->dp->header_.uuid,
+                                  curr->lflow->pipeline);
+        }
+        prev = curr;
+    }
+    if (n_flows > 0) {
+        print_lflows_count(prev->lflow->table_id,
+                           smap_get_def(&prev->lflow->external_ids,
+                                        "stage-name",
+                                        ""),
+                           table_lflows);
+        print_datapath_sum(prev->dp, &prev->dp->header_.uuid,
+                           prev->lflow->pipeline, dp_lflows);
+
+    }
+    printf("Total number of logical flows = %ld\n", n_flows);
+}
+
 static void
 cmd_lflow_list(struct ctl_context *ctx)
 {
@@ -966,6 +1047,10 @@ cmd_lflow_list(struct ctl_context *ctx)
         qsort(lflows, n_flows, sizeof *lflows, sbctl_lflow_cmp);
     }
 
+    if (shash_find(&ctx->options, "--count") != NULL) {
+        print_lflow_counters(n_flows, lflows);
+        goto cleanup;
+    }
     bool print_uuid = shash_find(&ctx->options, "--uuid") != NULL;
 
     const struct sbctl_lflow *curr, *prev = NULL;
@@ -997,11 +1082,7 @@ cmd_lflow_list(struct ctl_context *ctx)
         if (!prev
             || prev->dp != curr->dp
             || strcmp(prev->lflow->pipeline, curr->lflow->pipeline)) {
-            printf("Datapath: ");
-            print_datapath_name(curr->dp);
-            printf(" ("UUID_FMT")  Pipeline: %s\n",
-                   UUID_ARGS(&curr->dp->header_.uuid),
-                   curr->lflow->pipeline);
+                print_datapath_prompt(curr->dp, &curr->dp->header_.uuid, curr->lflow->pipeline);
         }
 
         /* Print the flow. */
@@ -1028,6 +1109,7 @@ cmd_lflow_list(struct ctl_context *ctx)
         cmd_lflow_list_load_balancers(ctx, vconn, datapath, stats, print_uuid);
     }
 
+cleanup:
     vconn_close(vconn);
     free(lflows);
 }
@@ -1375,10 +1457,10 @@ static const struct ctl_command_syntax sbctl_commands[] = {
     /* Logical flow commands */
     {"lflow-list", 0, INT_MAX, "[DATAPATH] [LFLOW...]",
      pre_get_info, cmd_lflow_list, NULL,
-     "--uuid,--ovs?,--stats,--vflows?", RO},
+     "--uuid,--ovs?,--stats,--vflows?,--count?", RO},
     {"dump-flows", 0, INT_MAX, "[DATAPATH] [LFLOW...]",
      pre_get_info, cmd_lflow_list, NULL,
-     "--uuid,--ovs?,--stats,--vflows?",
+     "--uuid,--ovs?,--stats,--vflows?,--count?",
      RO}, /* Friendly alias for lflow-list */
 
     /* IP multicast commands. */
