diff --git a/NEWS b/NEWS
index 601023067..39c890efd 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ Post-v20.09.0
      server.
    - Support other_config:vlan-passthru=true to allow VLAN tagged incoming
      traffic.
+   - Add "fair" column in Meter table to allow multiple ACL logs to use the
+     same Meter while being rate-limited independently.
 
 OVN v20.09.0 - 28 Sep 2020
 --------------------------
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 4d4190cb9..cee8abce9 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -5353,8 +5353,45 @@ build_acl_hints(struct ovn_datapath *od, struct hmap *lflows)
     }
 }
 
+static bool
+is_a_fair_meter(const struct shash *meter_groups, const char *meter_name)
+{
+    const struct nbrec_meter *nb_meter =
+        shash_find_data(meter_groups, meter_name);
+    if (nb_meter && nb_meter->fair) {
+        return *nb_meter->fair;
+    }
+    return false;
+}
+
+static char*
+alloc_acl_log_unique_meter_name(const struct nbrec_acl *acl)
+{
+    return xasprintf("%s__" UUID_FMT,
+                     acl->meter, UUID_ARGS(&acl->header_.uuid));
+}
+
+static void
+build_acl_log_meter(struct ds *actions, const struct nbrec_acl *acl,
+                    const struct shash *meter_groups)
+{
+    if (!acl->meter) {
+        return;
+    }
+
+    /* If ACL log meter uses a fair meter, use unique Meter name. */
+    if (is_a_fair_meter(meter_groups, acl->meter)) {
+        char *meter_name = alloc_acl_log_unique_meter_name(acl);
+        ds_put_format(actions, "meter=\"%s\", ", meter_name);
+        free(meter_name);
+    } else {
+        ds_put_format(actions, "meter=\"%s\", ", acl->meter);
+    }
+}
+
 static void
-build_acl_log(struct ds *actions, const struct nbrec_acl *acl)
+build_acl_log(struct ds *actions, const struct nbrec_acl *acl,
+              const struct shash *meter_groups)
 {
     if (!acl->log) {
         return;
@@ -5382,9 +5419,7 @@ build_acl_log(struct ds *actions, const struct nbrec_acl *acl)
         ds_put_cstr(actions, "verdict=allow, ");
     }
 
-    if (acl->meter) {
-        ds_put_format(actions, "meter=\"%s\", ", acl->meter);
-    }
+    build_acl_log_meter(actions, acl, meter_groups);
 
     ds_chomp(actions, ' ');
     ds_chomp(actions, ',');
@@ -5395,7 +5430,8 @@ static void
 build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows,
                        enum ovn_stage stage, struct nbrec_acl *acl,
                        struct ds *extra_match, struct ds *extra_actions,
-                       const struct ovsdb_idl_row *stage_hint)
+                       const struct ovsdb_idl_row *stage_hint,
+                       const struct shash *meter_groups)
 {
     struct ds match = DS_EMPTY_INITIALIZER;
     struct ds actions = DS_EMPTY_INITIALIZER;
@@ -5407,7 +5443,7 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows,
                   ingress ? ovn_stage_get_table(S_SWITCH_OUT_QOS_MARK)
                           : ovn_stage_get_table(S_SWITCH_IN_L2_LKUP));
 
-    build_acl_log(&actions, acl);
+    build_acl_log(&actions, acl, meter_groups);
     if (extra_match->length > 0) {
         ds_put_format(&match, "(%s) && ", extra_match->string);
     }
@@ -5432,7 +5468,8 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows,
 
 static void
 consider_acl(struct hmap *lflows, struct ovn_datapath *od,
-             struct nbrec_acl *acl, bool has_stateful)
+             struct nbrec_acl *acl, bool has_stateful,
+             const struct shash *meter_groups)
 {
     bool ingress = !strcmp(acl->direction, "from-lport") ? true :false;
     enum ovn_stage stage = ingress ? S_SWITCH_IN_ACL : S_SWITCH_OUT_ACL;
@@ -5446,7 +5483,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
          * associated conntrack entry and would return "+invalid". */
         if (!has_stateful) {
             struct ds actions = DS_EMPTY_INITIALIZER;
-            build_acl_log(&actions, acl);
+            build_acl_log(&actions, acl, meter_groups);
             ds_put_cstr(&actions, "next;");
             ovn_lflow_add_with_hint(lflows, od, stage,
                                     acl->priority + OVN_ACL_PRI_OFFSET,
@@ -5472,7 +5509,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
             ds_put_format(&match, REGBIT_ACL_HINT_ALLOW_NEW " == 1 && (%s)",
                           acl->match);
             ds_put_cstr(&actions, REGBIT_CONNTRACK_COMMIT" = 1; ");
-            build_acl_log(&actions, acl);
+            build_acl_log(&actions, acl, meter_groups);
             ds_put_cstr(&actions, "next;");
             ovn_lflow_add_with_hint(lflows, od, stage,
                                     acl->priority + OVN_ACL_PRI_OFFSET,
@@ -5491,7 +5528,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
             ds_put_format(&match, REGBIT_ACL_HINT_ALLOW " == 1 && (%s)",
                           acl->match);
 
-            build_acl_log(&actions, acl);
+            build_acl_log(&actions, acl, meter_groups);
             ds_put_cstr(&actions, "next;");
             ovn_lflow_add_with_hint(lflows, od, stage,
                                     acl->priority + OVN_ACL_PRI_OFFSET,
@@ -5516,10 +5553,10 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
             ds_put_cstr(&match, REGBIT_ACL_HINT_DROP " == 1");
             if (!strcmp(acl->action, "reject")) {
                 build_reject_acl_rules(od, lflows, stage, acl, &match,
-                                       &actions, &acl->header_);
+                                       &actions, &acl->header_, meter_groups);
             } else {
                 ds_put_format(&match, " && (%s)", acl->match);
-                build_acl_log(&actions, acl);
+                build_acl_log(&actions, acl, meter_groups);
                 ds_put_cstr(&actions, "/* drop */");
                 ovn_lflow_add_with_hint(lflows, od, stage,
                                         acl->priority + OVN_ACL_PRI_OFFSET,
@@ -5543,10 +5580,10 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
             ds_put_cstr(&actions, "ct_commit { ct_label.blocked = 1; }; ");
             if (!strcmp(acl->action, "reject")) {
                 build_reject_acl_rules(od, lflows, stage, acl, &match,
-                                       &actions, &acl->header_);
+                                       &actions, &acl->header_, meter_groups);
             } else {
                 ds_put_format(&match, " && (%s)", acl->match);
-                build_acl_log(&actions, acl);
+                build_acl_log(&actions, acl, meter_groups);
                 ds_put_cstr(&actions, "/* drop */");
                 ovn_lflow_add_with_hint(lflows, od, stage,
                                         acl->priority + OVN_ACL_PRI_OFFSET,
@@ -5559,9 +5596,9 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
              * logical flow action in all cases. */
             if (!strcmp(acl->action, "reject")) {
                 build_reject_acl_rules(od, lflows, stage, acl, &match,
-                                       &actions, &acl->header_);
+                                       &actions, &acl->header_, meter_groups);
             } else {
-                build_acl_log(&actions, acl);
+                build_acl_log(&actions, acl, meter_groups);
                 ds_put_cstr(&actions, "/* drop */");
                 ovn_lflow_add_with_hint(lflows, od, stage,
                                         acl->priority + OVN_ACL_PRI_OFFSET,
@@ -5641,7 +5678,7 @@ build_port_group_lswitches(struct northd_context *ctx, struct hmap *pgs,
 
 static void
 build_acls(struct ovn_datapath *od, struct hmap *lflows,
-           struct hmap *port_groups)
+           struct hmap *port_groups, const struct shash *meter_groups)
 {
     bool has_stateful = (has_stateful_acl(od) || has_lb_vip(od));
 
@@ -5744,13 +5781,14 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows,
     /* Ingress or Egress ACL Table (Various priorities). */
     for (size_t i = 0; i < od->nbs->n_acls; i++) {
         struct nbrec_acl *acl = od->nbs->acls[i];
-        consider_acl(lflows, od, acl, has_stateful);
+        consider_acl(lflows, od, acl, has_stateful, meter_groups);
     }
     struct ovn_port_group *pg;
     HMAP_FOR_EACH (pg, key_node, port_groups) {
         if (ovn_port_group_ls_find(pg, &od->nbs->header_.uuid)) {
             for (size_t i = 0; i < pg->nb_pg->n_acls; i++) {
-                consider_acl(lflows, od, pg->nb_pg->acls[i], has_stateful);
+                consider_acl(lflows, od, pg->nb_pg->acls[i], has_stateful,
+                             meter_groups);
             }
         }
     }
@@ -7448,7 +7486,7 @@ build_lswitch_lflows_pre_acl_and_acl(struct ovn_datapath *od,
         build_pre_lb(od, lflows, meter_groups, lbs);
         build_pre_stateful(od, lflows);
         build_acl_hints(od, lflows);
-        build_acls(od, lflows, port_groups);
+        build_acls(od, lflows, port_groups, meter_groups);
         build_qos(od, lflows);
         build_lb(od, lflows);
         build_stateful(od, lflows, lbs);
@@ -11633,12 +11671,77 @@ done:
     return need_update;
 }
 
+static void
+sync_meters_iterate_nb_meter(struct northd_context *ctx,
+                             const char *meter_name,
+                             const struct nbrec_meter *nb_meter,
+                             struct shash *sb_meters)
+{
+    bool new_sb_meter = false;
+
+    const struct sbrec_meter *sb_meter = shash_find_and_delete(sb_meters,
+                                                               meter_name);
+    if (!sb_meter) {
+        sb_meter = sbrec_meter_insert(ctx->ovnsb_txn);
+        sbrec_meter_set_name(sb_meter, meter_name);
+        new_sb_meter = true;
+    }
+
+    if (new_sb_meter || bands_need_update(nb_meter, sb_meter)) {
+        struct sbrec_meter_band **sb_bands;
+        sb_bands = xcalloc(nb_meter->n_bands, sizeof *sb_bands);
+        for (size_t i = 0; i < nb_meter->n_bands; i++) {
+            const struct nbrec_meter_band *nb_band = nb_meter->bands[i];
+
+            sb_bands[i] = sbrec_meter_band_insert(ctx->ovnsb_txn);
+
+            sbrec_meter_band_set_action(sb_bands[i], nb_band->action);
+            sbrec_meter_band_set_rate(sb_bands[i], nb_band->rate);
+            sbrec_meter_band_set_burst_size(sb_bands[i],
+                                            nb_band->burst_size);
+        }
+        sbrec_meter_set_bands(sb_meter, sb_bands, nb_meter->n_bands);
+        free(sb_bands);
+    }
+
+    sbrec_meter_set_unit(sb_meter, nb_meter->unit);
+}
+
+static void
+sync_acl_fair_meters(struct northd_context *ctx,
+                       struct hmap *datapaths,
+                       const struct nbrec_meter *nb_meter,
+                       struct shash *sb_meters)
+{
+    if (!nb_meter->fair || *nb_meter->fair == false) {
+        return;
+    }
+
+    struct ovn_datapath *od;
+    HMAP_FOR_EACH (od, key_node, datapaths) {
+        if (!od->nbs) {
+            continue;
+        }
+        for (size_t i = 0; i < od->nbs->n_acls; i++) {
+            struct nbrec_acl *acl = od->nbs->acls[i];
+            if (!acl->meter || strcmp(nb_meter->name, acl->meter)) {
+                continue;
+            }
+
+            char *meter_name = alloc_acl_log_unique_meter_name(acl);
+            sync_meters_iterate_nb_meter(ctx, meter_name, nb_meter, sb_meters);
+            free(meter_name);
+        }
+    }
+}
+
 /* Each entry in the Meter and Meter_Band tables in OVN_Northbound have
  * a corresponding entries in the Meter and Meter_Band tables in
- * OVN_Southbound.
+ * OVN_Southbound. Additionally, ACL logs that use fair meters have
+ * a private copy of its meter in the SB table.
  */
 static void
-sync_meters(struct northd_context *ctx)
+sync_meters(struct northd_context *ctx, struct hmap *datapaths)
 {
     struct shash sb_meters = SHASH_INITIALIZER(&sb_meters);
 
@@ -11649,33 +11752,14 @@ sync_meters(struct northd_context *ctx)
 
     const struct nbrec_meter *nb_meter;
     NBREC_METER_FOR_EACH (nb_meter, ctx->ovnnb_idl) {
-        bool new_sb_meter = false;
-
-        sb_meter = shash_find_and_delete(&sb_meters, nb_meter->name);
-        if (!sb_meter) {
-            sb_meter = sbrec_meter_insert(ctx->ovnsb_txn);
-            sbrec_meter_set_name(sb_meter, nb_meter->name);
-            new_sb_meter = true;
-        }
-
-        if (new_sb_meter || bands_need_update(nb_meter, sb_meter)) {
-            struct sbrec_meter_band **sb_bands;
-            sb_bands = xcalloc(nb_meter->n_bands, sizeof *sb_bands);
-            for (size_t i = 0; i < nb_meter->n_bands; i++) {
-                const struct nbrec_meter_band *nb_band = nb_meter->bands[i];
-
-                sb_bands[i] = sbrec_meter_band_insert(ctx->ovnsb_txn);
-
-                sbrec_meter_band_set_action(sb_bands[i], nb_band->action);
-                sbrec_meter_band_set_rate(sb_bands[i], nb_band->rate);
-                sbrec_meter_band_set_burst_size(sb_bands[i],
-                                                nb_band->burst_size);
-            }
-            sbrec_meter_set_bands(sb_meter, sb_bands, nb_meter->n_bands);
-            free(sb_bands);
-        }
-
-        sbrec_meter_set_unit(sb_meter, nb_meter->unit);
+        sync_meters_iterate_nb_meter(ctx, nb_meter->name, nb_meter,
+                                     &sb_meters);
+        /*
+         * In addition to creating a 'non-fair' Meter in the SB from
+         * the line above, check and see if additional rows are needed
+         * to get ACLs logs individually rate-limited.
+         */
+        sync_acl_fair_meters(ctx, datapaths, nb_meter, &sb_meters);
     }
 
     struct shash_node *node, *next;
@@ -12168,7 +12252,7 @@ ovnnb_db_run(struct northd_context *ctx,
 
     sync_address_sets(ctx);
     sync_port_groups(ctx, &port_groups);
-    sync_meters(ctx);
+    sync_meters(ctx, datapaths);
     sync_dns_entries(ctx, datapaths);
     destroy_ovn_lbs(&lbs);
     hmap_destroy(&lbs);
diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
index 092322ab2..269e3a888 100644
--- a/ovn-nb.ovsschema
+++ b/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Northbound",
-    "version": "5.27.0",
-    "cksum": "3507518247 26773",
+    "version": "5.28.0",
+    "cksum": "610359755 26847",
     "tables": {
         "NB_Global": {
             "columns": {
@@ -264,6 +264,7 @@
                                            "refType": "strong"},
                                    "min": 1,
                                    "max": "unlimited"}},
+                "fair": {"type": {"key": "boolean", "min": 0, "max": 1}},
                 "external_ids": {
                     "type": {"key": "string", "value": "string",
                              "min": 0, "max": "unlimited"}}},
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 5e6c6c7a3..c49bb1332 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1785,7 +1785,9 @@
             The name of a meter to rate-limit log messages for the ACL.
             The string must match the <ref column="name" table="meter"/>
             column of a row in the <ref table="Meter"/> table.  By
-            default, log messages are not rate-limited.
+            default, log messages are not rate-limited. In order to ensure
+            that the same <ref table="Meter"/> rate limits multiple ACL logs
+            separately, set the <ref column="fair" table="meter"/> column.
         </p>
       </column>
     </group>
@@ -2082,6 +2084,18 @@
       </p>
     </column>
 
+    <column name="fair">
+      <p>
+        This column is used to further describe the desired behavior
+        of the meter when there are multiple references to it. If this
+        column is empty or is set to <code>false</code>, the rate will
+        be shared across all rows that refer to the same Meter
+        <ref column="name" table="meter"/>. Conversely, when this column
+        is set to <code>true</code>, each user of the same Meter will be
+        rate-limited on its own.
+      </p>
+    </column>
+
     <column name="external_ids">
       See <em>External IDs</em> at the beginning of this document.
     </column>
diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
index 79d580d3f..11091d8d0 100644
--- a/tests/ovn-nbctl.at
+++ b/tests/ovn-nbctl.at
@@ -346,7 +346,7 @@ OVN_NBCTL_TEST([ovn_nbctl_meters], [meters], [
 AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps])
 AT_CHECK([ovn-nbctl meter-add meter2 drop 3 kbps 2])
 AT_CHECK([ovn-nbctl meter-add meter3 drop 100 kbps 200])
-AT_CHECK([ovn-nbctl meter-add meter4 drop 10 pktps 30])
+AT_CHECK([ovn-nbctl --fair meter-add meter4 drop 10 pktps 30])
 
 dnl Add duplicate meter name
 AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps], [1], [], [stderr])
@@ -382,7 +382,7 @@ meter2: bands:
   drop: 3 kbps, 2 kb burst
 meter3: bands:
   drop: 100 kbps, 200 kb burst
-meter4: bands:
+meter4: (fair) bands:
   drop: 10 pktps, 30 packet burst
 ])
 
@@ -393,7 +393,7 @@ meter1: bands:
   drop: 10 kbps
 meter3: bands:
   drop: 100 kbps, 200 kb burst
-meter4: bands:
+meter4: (fair) bands:
   drop: 10 pktps, 30 packet burst
 ])
 
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 26376c367..03095047b 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -1813,6 +1813,103 @@ action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implici
 
 AT_CLEANUP
 
+AT_SETUP([ovn-northd -- ACL fair Meters])
+AT_KEYWORDS([acl log meter fair])
+ovn_start
+
+ovn-nbctl ls-add sw0
+ovn-nbctl lsp-add sw0 sw0-p1 -- lsp-set-addresses sw0-p1 "50:54:00:00:00:01 10.0.0.11"
+ovn-nbctl lsp-add sw0 sw0-p2 -- lsp-set-addresses sw0-p2 "50:54:00:00:00:02 10.0.0.12"
+ovn-nbctl lsp-add sw0 sw0-p3 -- lsp-set-addresses sw0-p3 "50:54:00:00:00:03 10.0.0.13"
+
+ovn-nbctl meter-add meter_me drop 1 pktps
+nb_meter_uuid=$(fetch_column nb:Meter _uuid name=meter_me)
+
+ovn-nbctl acl-add sw0 to-lport 1002 'outport == "sw0-p1" && ip4.src == 10.0.0.12' allow
+ovn-nbctl acl-add sw0 to-lport 1002 'outport == "sw0-p1" && ip4.src == 10.0.0.13' allow
+
+acl1=$(ovn-nbctl --bare --column _uuid,match find acl | grep -B1 '10.0.0.12' | head -1)
+acl2=$(ovn-nbctl --bare --column _uuid,match find acl | grep -B1 '10.0.0.13' | head -1)
+ovn-nbctl set acl $acl1 log=true severity=alert meter=meter_me name=acl_one
+ovn-nbctl set acl $acl2 log=true severity=info  meter=meter_me name=acl_two
+ovn-nbctl --wait=sb sync
+
+check_row_count nb:meter 1
+check_column meter_me nb:meter name
+
+check_acl_lflow() {
+    acl_log_name=$1
+    meter_name=$2
+    # echo checking that logical flow for acl log $acl_log_name has $meter_name
+    AT_CHECK([ovn-sbctl lflow-list | grep ls_out_acl | \
+              grep "\"${acl_log_name}\"" | \
+              grep -c "meter=\"${meter_name}\""], [0], [1
+])
+}
+
+check_meter_by_name() {
+    [test "$1" = "NOT"] && { expected_count=0; shift; } || expected_count=1
+    for meter_name in $* ; do
+        # echo checking for $expected_count $meter_name in sb meter table
+        check_row_count meter $expected_count name=$meter_name
+    done
+}
+
+# Make sure 'fair' value properly affects the Meters in SB
+check_meter_by_name meter_me
+check_meter_by_name NOT meter_me__${acl1} meter_me__${acl2}
+
+ovn-nbctl --wait=sb set Meter $nb_meter_uuid fair=true
+check_meter_by_name meter_me meter_me__${acl1} meter_me__${acl2}
+
+ovn-nbctl --wait=sb set Meter $nb_meter_uuid fair=false
+check_meter_by_name meter_me
+check_meter_by_name NOT meter_me__${acl1} meter_me__${acl2}
+
+ovn-nbctl --wait=sb set Meter $nb_meter_uuid fair=true
+check_meter_by_name meter_me meter_me__${acl1} meter_me__${acl2}
+
+# Change template meter and make sure that is reflected on acl meters as well
+template_band=$(fetch_column nb:meter bands name=meter_me)
+ovn-nbctl --wait=sb set meter_band $template_band rate=123
+# Make sure that every Meter_Band has the right rate.  (ovn-northd
+# creates 3 identical Meter_Band rows, all identical; ovn-northd-ddlog
+# creates just 1.  It doesn't matter, they work just as well.)
+n_meter_bands=$(count_rows meter_band)
+AT_FAIL_IF([test "$n_meter_bands" != 1 && test "$n_meter_bands" != 3])
+check_row_count meter_band $n_meter_bands rate=123
+
+# Check meter in logical flows for acl logs
+check_acl_lflow acl_one meter_me__${acl1}
+check_acl_lflow acl_two meter_me__${acl2}
+
+# Stop using meter for acl1
+ovn-nbctl --wait=sb clear acl $acl1 meter
+check_meter_by_name meter_me meter_me__${acl2}
+check_meter_by_name NOT meter_me__${acl1}
+check_acl_lflow acl_two meter_me__${acl2}
+
+# Remove template Meter should remove all others as well
+ovn-nbctl --wait=sb meter-del meter_me
+check_row_count meter 0
+# Check that logical flow remains but uses non-unique meter since fair
+# attribute is lost by the removal of the Meter row.
+check_acl_lflow acl_two meter_me
+
+# Re-add template meter and make sure acl2's meter is back in sb
+ovn-nbctl --wait=sb --fair meter-add meter_me drop 1 pktps
+check_meter_by_name meter_me meter_me__${acl2}
+check_meter_by_name NOT meter_me__${acl1}
+check_acl_lflow acl_two meter_me__${acl2}
+
+# Remove acl2
+sw0=$(fetch_column nb:logical_switch _uuid name=sw0)
+ovn-nbctl --wait=sb remove logical_switch $sw0 acls $acl2
+check_meter_by_name meter_me
+check_meter_by_name NOT meter_me__${acl1} meter_me__${acl2}
+
+AT_CLEANUP
+
 AT_SETUP([datapath requested-tnl-key])
 AT_KEYWORDS([requested tnl tunnel key keys])
 ovn_start
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index b5633c725..11c6b5576 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -617,6 +617,7 @@ QoS commands:\n\
   qos-list SWITCH           print QoS rules for SWITCH\n\
 \n\
 Meter commands:\n\
+  [--fair]\n\
   meter-add NAME ACTION RATE UNIT [BURST]\n\
                             add a meter\n\
   meter-del [NAME]          remove meters\n\
@@ -2693,7 +2694,12 @@ nbctl_meter_list(struct ctl_context *ctx)
 
     for (size_t i = 0; i < n_meters; i++) {
         meter = meters[i];
-        ds_put_format(&ctx->output, "%s: bands:\n", meter->name);
+        ds_put_format(&ctx->output, "%s:", meter->name);
+        if (meter->fair) {
+            ds_put_format(&ctx->output, " (%s)",
+                          *meter->fair ? "fair" : "shared");
+        }
+        ds_put_format(&ctx->output, " bands:\n");
 
         for (size_t j = 0; j < meter->n_bands; j++) {
             const struct nbrec_meter_band *band = meter->bands[j];
@@ -2770,6 +2776,12 @@ nbctl_meter_add(struct ctl_context *ctx)
     nbrec_meter_set_name(meter, name);
     nbrec_meter_set_unit(meter, unit);
     nbrec_meter_set_bands(meter, &band, 1);
+
+    /* Fair option */
+    bool fair = shash_find(&ctx->options, "--fair") != NULL;
+    if (fair) {
+        nbrec_meter_set_fair(meter, &fair, 1);
+    }
 }
 
 static void
@@ -6464,7 +6476,7 @@ static const struct ctl_command_syntax nbctl_commands[] = {
 
     /* meter commands. */
     { "meter-add", 4, 5, "NAME ACTION RATE UNIT [BURST]", NULL,
-      nbctl_meter_add, NULL, "", RW },
+      nbctl_meter_add, NULL, "--fair", RW },
     { "meter-del", 0, 1, "[NAME]", NULL, nbctl_meter_del, NULL, "", RW },
     { "meter-list", 0, 0, "", NULL, nbctl_meter_list, NULL, "", RO },
 
