diff --git a/SOURCES/openvswitch-2.16.0.patch b/SOURCES/openvswitch-2.16.0.patch
index eb54fbe..ac3a700 100644
--- a/SOURCES/openvswitch-2.16.0.patch
+++ b/SOURCES/openvswitch-2.16.0.patch
@@ -1478,11 +1478,71 @@ index 7729a90608..fbdfc7ad83 100644
              const struct nlattr *ma = nl_attr_find__(mask, mask_len,
                                                       OVS_KEY_ATTR_ETHERTYPE);
              if (ma) {
+diff --git a/lib/ofp-flow.c b/lib/ofp-flow.c
+index ff0396845a..3bc744f78f 100644
+--- a/lib/ofp-flow.c
++++ b/lib/ofp-flow.c
+@@ -1254,7 +1254,16 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
+         OVS_NOT_REACHED();
+     }
+ 
+-    ofpmp_postappend(replies, start_ofs);
++    if ((reply->size - start_ofs) > (UINT16_MAX - ofpbuf_headersize(reply))) {
++        /* When this happens, the reply will not fit in a single OFP message,
++         * and we should not append it to the queue. We will log a warning
++         * and continue with the next flow stat entry. */
++        reply->size = start_ofs;
++        VLOG_WARN_RL(&rl, "Flow exceeded the maximum flow statistics reply "
++                     "size and was excluded from the response set");
++    } else {
++        ofpmp_postappend(replies, start_ofs);
++    }
+     fs_->match.flow.tunnel.metadata.tab = orig_tun_table;
+ }
+ 
 diff --git a/lib/ovsdb-cs.c b/lib/ovsdb-cs.c
-index 659d49dbf7..fcb6fe1b34 100644
+index 659d49dbf7..dead31275d 100644
 --- a/lib/ovsdb-cs.c
 +++ b/lib/ovsdb-cs.c
-@@ -1833,7 +1833,7 @@ server_column_get_string(const struct server_row *row,
+@@ -1109,6 +1109,23 @@ ovsdb_cs_db_sync_condition(struct ovsdb_cs_db *db)
+                 }
+                 table->req_cond = NULL;
+                 db->cond_changed = true;
++
++                /* There are two cases:
++                 * a. either the server already processed the requested monitor
++                 *    condition change but the FSM was restarted before the
++                 *    client was notified.  In this case the client should
++                 *    clear its local cache because it's out of sync with the
++                 *    monitor view on the server side.
++                 *
++                 * b. OR the server hasn't processed the requested monitor
++                 *    condition change yet.
++                 *
++                 * As there's no easy way to differentiate between the two,
++                 * and given that this condition should be rare, reset the
++                 * 'last_id', essentially flushing the local cached DB
++                 * contents.
++                 */
++                db->last_id = UUID_ZERO;
+             }
+         }
+     }
+@@ -1539,12 +1556,11 @@ ovsdb_cs_db_parse_monitor_reply(struct ovsdb_cs_db *db,
+     const struct json *table_updates;
+     bool clear;
+     if (version == 3) {
+-        struct uuid last_id;
+         if (result->type != JSON_ARRAY || result->array.n != 3
+             || (result->array.elems[0]->type != JSON_TRUE &&
+                 result->array.elems[0]->type != JSON_FALSE)
+             || result->array.elems[1]->type != JSON_STRING
+-            || !uuid_from_string(&last_id,
++            || !uuid_from_string(&db->last_id,
+                                  json_string(result->array.elems[1]))) {
+             struct ovsdb_error *error = ovsdb_syntax_error(
+                 result, NULL, "bad monitor_cond_since reply format");
+@@ -1833,7 +1849,7 @@ server_column_get_string(const struct server_row *row,
  {
      ovs_assert(server_columns[index].type.key.type == OVSDB_TYPE_STRING);
      const struct ovsdb_datum *d = &row->data[index];
@@ -2138,7 +2198,7 @@ index c5a80ee39f..f66ed3472c 100644
  void ovsdb_datum_remove_unsafe(struct ovsdb_datum *, size_t idx,
                                 const struct ovsdb_type *);
 diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
-index 2198c69c60..198ba5a828 100644
+index 2198c69c60..42d249212d 100644
 --- a/lib/ovsdb-idl.c
 +++ b/lib/ovsdb-idl.c
 @@ -1898,8 +1898,7 @@ ovsdb_idl_index_destroy_row(const struct ovsdb_idl_row *row_)
@@ -2215,6 +2275,17 @@ index 2198c69c60..198ba5a828 100644
  
      ovsdb_idl_txn_add_map_op(row, column, datum, op_type);
  }
+@@ -4112,6 +4108,10 @@ void
+ ovsdb_idl_loop_destroy(struct ovsdb_idl_loop *loop)
+ {
+     if (loop) {
++        if (loop->committing_txn) {
++            ovsdb_idl_txn_abort(loop->committing_txn);
++            ovsdb_idl_txn_destroy(loop->committing_txn);
++        }
+         ovsdb_idl_destroy(loop->idl);
+     }
+ }
 diff --git a/lib/pcap-file.c b/lib/pcap-file.c
 index b30a11c24b..41835f6f4d 100644
 --- a/lib/pcap-file.c
@@ -5262,6 +5333,33 @@ index 956a69e1fa..aadfbc8cc5 100644
  OVS_VSWITCHD_STOP
  AT_CLEANUP
  
+diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
+index 604f15c2d1..c93cb9f16c 100644
+--- a/tests/ovs-ofctl.at
++++ b/tests/ovs-ofctl.at
+@@ -3246,3 +3246,22 @@ dnl because we need ovs-vswitchd to have the controller config before starting
+ dnl the controller to 'snoop' the OpenFlow messages from beginning
+ OVS_VSWITCHD_STOP(["/connection failed (No such file or directory)/d"])
+ AT_CLEANUP
++
++
++AT_SETUP([ovs-ofctl show-flows - Oversized flow])
++OVS_VSWITCHD_START
++
++printf " priority=90,icmp,reg15=0x8005,metadata=0x1,nw_dst=11.0.0.1,icmp_type=8,icmp_code=0 actions=" > flow.txt
++for i in `seq 1 1022`; do printf "set_field:0x399->reg13,set_field:0x$i->reg15,resubmit(,39),"; done >> flow.txt
++printf "resubmit(,39)\n" >> flow.txt
++
++AT_CHECK([ovs-ofctl -O OpenFlow15 add-flows br0 flow.txt])
++
++AT_CHECK([ovs-ofctl -O OpenFlow10 dump-flows br0 | ofctl_strip | sed '/NXST_FLOW/d' | sort], [0], [])
++OVS_WAIT_UNTIL([grep -q "ofp_flow|WARN|Flow exceeded the maximum flow statistics reply size and was excluded from the response set" ovs-vswitchd.log])
++
++cat flow.txt > expout
++AT_CHECK([ovs-ofctl -O OpenFlow15 dump-flows br0 | ofctl_strip | sed '/OFPST_FLOW/d' | sort], [0], [expout])
++
++OVS_VSWITCHD_STOP(["/Flow exceeded the maximum flow statistics reply size and was excluded from the response set/d"])
++AT_CLEANUP
 diff --git a/tests/ovsdb-data.at b/tests/ovsdb-data.at
 index 8cd2a26cb3..25c6acdac6 100644
 --- a/tests/ovsdb-data.at
@@ -5333,7 +5431,7 @@ index 8cd2a26cb3..25c6acdac6 100644
  
  OVSDB_CHECK_NEGATIVE([generate and apply diff with map -- size error],
 diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
-index 1386f13770..cd28a587c6 100644
+index 1386f13770..91d34d0de6 100644
 --- a/tests/ovsdb-idl.at
 +++ b/tests/ovsdb-idl.at
 @@ -225,7 +225,7 @@ m4_define([OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PY],
@@ -5345,6 +5443,24 @@ index 1386f13770..cd28a587c6 100644
     SSL_PRESENT=$?
     AT_SKIP_IF([test $SSL_PRESENT != 0])
     AT_KEYWORDS([ovsdb server idl positive Python with ssl socket $5])
+@@ -2309,7 +2309,7 @@ OVSDB_CHECK_CLUSTER_IDL_C([simple idl, monitor_cond_since, cluster disconnect],
+     'condition simple [["i","==",2]]' \
+     'condition simple [["i","==",1]]' \
+     '+reconnect' \
+-    '["idltest",
++    '?["idltest",
+       {"op": "update",
+        "table": "simple",
+        "where": [["i", "==", 1]],
+@@ -2320,7 +2320,7 @@ OVSDB_CHECK_CLUSTER_IDL_C([simple idl, monitor_cond_since, cluster disconnect],
+ 003: table simple: i=2 r=1 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+ 004: change conditions
+ 005: reconnect
+-006: table simple: i=2 r=1 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
++006: table simple
+ 007: {"error":null,"result":[{"count":1}]}
+ 008: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+ 009: done
 diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
 index ac243d6a79..2b742f78b0 100644
 --- a/tests/ovsdb-server.at
@@ -5666,7 +5782,7 @@ index a7ee595e0b..072a537252 100644
 +
 +OVSTEST_REGISTER("json-string-benchmark", json_string_benchmark_main);
 diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
-index daa55dab7b..637271619f 100644
+index daa55dab7b..57572cd3ed 100644
 --- a/tests/test-ovsdb.c
 +++ b/tests/test-ovsdb.c
 @@ -512,6 +512,18 @@ do_diff_data(struct ovs_cmdl_context *ctx)
@@ -5700,7 +5816,282 @@ index daa55dab7b..637271619f 100644
          ovsdb_datum_destroy(&new, &type);
          ovsdb_datum_destroy(&old, &type);
          ovsdb_datum_destroy(&diff, &type);
-@@ -2727,13 +2744,15 @@ print_idl_row_simple2(const struct idltest_simple2 *s, int step)
+@@ -1862,7 +1879,8 @@ print_and_log(const char *format, ...)
+ }
+ 
+ static char *
+-format_idl_row(const struct ovsdb_idl_row *row, int step, const char *contents)
++format_idl_row(const struct ovsdb_idl_row *row, int step, const char *contents,
++               bool terse)
+ {
+     const char *change_str =
+         !ovsdb_idl_track_is_set(row->table)
+@@ -1873,9 +1891,13 @@ format_idl_row(const struct ovsdb_idl_row *row, int step, const char *contents)
+             ? "deleted row: "
+             : "";
+ 
+-    return xasprintf("%03d: table %s: %s%s uuid=" UUID_FMT,
+-                     step, row->table->class_->name, change_str, contents,
+-                     UUID_ARGS(&row->uuid));
++    if (terse) {
++        return xasprintf("%03d: table %s", step, row->table->class_->name);
++    } else {
++        return xasprintf("%03d: table %s: %s%s uuid=" UUID_FMT,
++                         step, row->table->class_->name, change_str,
++                         contents, UUID_ARGS(&row->uuid));
++    }
+ }
+ 
+ static void
+@@ -1998,7 +2020,7 @@ print_idl_row_updated_singleton(const struct idltest_singleton *sng, int step)
+ }
+ 
+ static void
+-print_idl_row_simple(const struct idltest_simple *s, int step)
++print_idl_row_simple(const struct idltest_simple *s, int step, bool terse)
+ {
+     struct ds msg = DS_EMPTY_INITIALIZER;
+     ds_put_format(&msg, "i=%"PRId64" r=%g b=%s s=%s u="UUID_FMT" ia=[",
+@@ -2025,7 +2047,7 @@ print_idl_row_simple(const struct idltest_simple *s, int step)
+     }
+     ds_put_cstr(&msg, "]");
+ 
+-    char *row_msg = format_idl_row(&s->header_, step, ds_cstr(&msg));
++    char *row_msg = format_idl_row(&s->header_, step, ds_cstr(&msg), terse);
+     print_and_log("%s", row_msg);
+     ds_destroy(&msg);
+     free(row_msg);
+@@ -2034,7 +2056,7 @@ print_idl_row_simple(const struct idltest_simple *s, int step)
+ }
+ 
+ static void
+-print_idl_row_link1(const struct idltest_link1 *l1, int step)
++print_idl_row_link1(const struct idltest_link1 *l1, int step, bool terse)
+ {
+     struct ds msg = DS_EMPTY_INITIALIZER;
+     ds_put_format(&msg, "i=%"PRId64" k=", l1->i);
+@@ -2053,7 +2075,7 @@ print_idl_row_link1(const struct idltest_link1 *l1, int step)
+         ds_put_format(&msg, "%"PRId64, l1->l2->i);
+     }
+ 
+-    char *row_msg = format_idl_row(&l1->header_, step, ds_cstr(&msg));
++    char *row_msg = format_idl_row(&l1->header_, step, ds_cstr(&msg), terse);
+     print_and_log("%s", row_msg);
+     ds_destroy(&msg);
+     free(row_msg);
+@@ -2062,7 +2084,7 @@ print_idl_row_link1(const struct idltest_link1 *l1, int step)
+ }
+ 
+ static void
+-print_idl_row_link2(const struct idltest_link2 *l2, int step)
++print_idl_row_link2(const struct idltest_link2 *l2, int step, bool terse)
+ {
+     struct ds msg = DS_EMPTY_INITIALIZER;
+     ds_put_format(&msg, "i=%"PRId64" l1=", l2->i);
+@@ -2070,7 +2092,7 @@ print_idl_row_link2(const struct idltest_link2 *l2, int step)
+         ds_put_format(&msg, "%"PRId64, l2->l1->i);
+     }
+ 
+-    char *row_msg = format_idl_row(&l2->header_, step, ds_cstr(&msg));
++    char *row_msg = format_idl_row(&l2->header_, step, ds_cstr(&msg), terse);
+     print_and_log("%s", row_msg);
+     ds_destroy(&msg);
+     free(row_msg);
+@@ -2079,7 +2101,7 @@ print_idl_row_link2(const struct idltest_link2 *l2, int step)
+ }
+ 
+ static void
+-print_idl_row_simple3(const struct idltest_simple3 *s3, int step)
++print_idl_row_simple3(const struct idltest_simple3 *s3, int step, bool terse)
+ {
+     struct ds msg = DS_EMPTY_INITIALIZER;
+     size_t i;
+@@ -2098,7 +2120,7 @@ print_idl_row_simple3(const struct idltest_simple3 *s3, int step)
+     }
+     ds_put_cstr(&msg, "]");
+ 
+-    char *row_msg = format_idl_row(&s3->header_, step, ds_cstr(&msg));
++    char *row_msg = format_idl_row(&s3->header_, step, ds_cstr(&msg), terse);
+     print_and_log("%s", row_msg);
+     ds_destroy(&msg);
+     free(row_msg);
+@@ -2107,12 +2129,12 @@ print_idl_row_simple3(const struct idltest_simple3 *s3, int step)
+ }
+ 
+ static void
+-print_idl_row_simple4(const struct idltest_simple4 *s4, int step)
++print_idl_row_simple4(const struct idltest_simple4 *s4, int step, bool terse)
+ {
+     struct ds msg = DS_EMPTY_INITIALIZER;
+     ds_put_format(&msg, "name=%s", s4->name);
+ 
+-    char *row_msg = format_idl_row(&s4->header_, step, ds_cstr(&msg));
++    char *row_msg = format_idl_row(&s4->header_, step, ds_cstr(&msg), terse);
+     print_and_log("%s", row_msg);
+     ds_destroy(&msg);
+     free(row_msg);
+@@ -2121,7 +2143,7 @@ print_idl_row_simple4(const struct idltest_simple4 *s4, int step)
+ }
+ 
+ static void
+-print_idl_row_simple6(const struct idltest_simple6 *s6, int step)
++print_idl_row_simple6(const struct idltest_simple6 *s6, int step, bool terse)
+ {
+     struct ds msg = DS_EMPTY_INITIALIZER;
+     ds_put_format(&msg, "name=%s ", s6->name);
+@@ -2132,7 +2154,7 @@ print_idl_row_simple6(const struct idltest_simple6 *s6, int step)
+     }
+     ds_put_cstr(&msg, "]");
+ 
+-    char *row_msg = format_idl_row(&s6->header_, step, ds_cstr(&msg));
++    char *row_msg = format_idl_row(&s6->header_, step, ds_cstr(&msg), terse);
+     print_and_log("%s", row_msg);
+     ds_destroy(&msg);
+     free(row_msg);
+@@ -2141,12 +2163,13 @@ print_idl_row_simple6(const struct idltest_simple6 *s6, int step)
+ }
+ 
+ static void
+-print_idl_row_singleton(const struct idltest_singleton *sng, int step)
++print_idl_row_singleton(const struct idltest_singleton *sng, int step,
++                        bool terse)
+ {
+     struct ds msg = DS_EMPTY_INITIALIZER;
+     ds_put_format(&msg, "name=%s", sng->name);
+ 
+-    char *row_msg = format_idl_row(&sng->header_, step, ds_cstr(&msg));
++    char *row_msg = format_idl_row(&sng->header_, step, ds_cstr(&msg), terse);
+     print_and_log("%s", row_msg);
+     ds_destroy(&msg);
+     free(row_msg);
+@@ -2155,7 +2178,7 @@ print_idl_row_singleton(const struct idltest_singleton *sng, int step)
+ }
+ 
+ static void
+-print_idl(struct ovsdb_idl *idl, int step)
++print_idl(struct ovsdb_idl *idl, int step, bool terse)
+ {
+     const struct idltest_simple3 *s3;
+     const struct idltest_simple4 *s4;
+@@ -2167,31 +2190,31 @@ print_idl(struct ovsdb_idl *idl, int step)
+     int n = 0;
+ 
+     IDLTEST_SIMPLE_FOR_EACH (s, idl) {
+-        print_idl_row_simple(s, step);
++        print_idl_row_simple(s, step, terse);
+         n++;
+     }
+     IDLTEST_LINK1_FOR_EACH (l1, idl) {
+-        print_idl_row_link1(l1, step);
++        print_idl_row_link1(l1, step, terse);
+         n++;
+     }
+     IDLTEST_LINK2_FOR_EACH (l2, idl) {
+-        print_idl_row_link2(l2, step);
++        print_idl_row_link2(l2, step, terse);
+         n++;
+     }
+     IDLTEST_SIMPLE3_FOR_EACH (s3, idl) {
+-        print_idl_row_simple3(s3, step);
++        print_idl_row_simple3(s3, step, terse);
+         n++;
+     }
+     IDLTEST_SIMPLE4_FOR_EACH (s4, idl) {
+-        print_idl_row_simple4(s4, step);
++        print_idl_row_simple4(s4, step, terse);
+         n++;
+     }
+     IDLTEST_SIMPLE6_FOR_EACH (s6, idl) {
+-        print_idl_row_simple6(s6, step);
++        print_idl_row_simple6(s6, step, terse);
+         n++;
+     }
+     IDLTEST_SINGLETON_FOR_EACH (sng, idl) {
+-        print_idl_row_singleton(sng, step);
++        print_idl_row_singleton(sng, step, terse);
+         n++;
+     }
+     if (!n) {
+@@ -2200,7 +2223,7 @@ print_idl(struct ovsdb_idl *idl, int step)
+ }
+ 
+ static void
+-print_idl_track(struct ovsdb_idl *idl, int step)
++print_idl_track(struct ovsdb_idl *idl, int step, bool terse)
+ {
+     const struct idltest_simple3 *s3;
+     const struct idltest_simple4 *s4;
+@@ -2211,27 +2234,27 @@ print_idl_track(struct ovsdb_idl *idl, int step)
+     int n = 0;
+ 
+     IDLTEST_SIMPLE_FOR_EACH_TRACKED (s, idl) {
+-        print_idl_row_simple(s, step);
++        print_idl_row_simple(s, step, terse);
+         n++;
+     }
+     IDLTEST_LINK1_FOR_EACH_TRACKED (l1, idl) {
+-        print_idl_row_link1(l1, step);
++        print_idl_row_link1(l1, step, terse);
+         n++;
+     }
+     IDLTEST_LINK2_FOR_EACH_TRACKED (l2, idl) {
+-        print_idl_row_link2(l2, step);
++        print_idl_row_link2(l2, step, terse);
+         n++;
+     }
+     IDLTEST_SIMPLE3_FOR_EACH_TRACKED (s3, idl) {
+-        print_idl_row_simple3(s3, step);
++        print_idl_row_simple3(s3, step, terse);
+         n++;
+     }
+     IDLTEST_SIMPLE4_FOR_EACH_TRACKED (s4, idl) {
+-        print_idl_row_simple4(s4, step);
++        print_idl_row_simple4(s4, step, terse);
+         n++;
+     }
+     IDLTEST_SIMPLE6_FOR_EACH_TRACKED (s6, idl) {
+-        print_idl_row_simple6(s6, step);
++        print_idl_row_simple6(s6, step, terse);
+         n++;
+     }
+ 
+@@ -2634,6 +2657,13 @@ do_idl(struct ovs_cmdl_context *ctx)
+         char *arg = ctx->argv[i];
+         struct jsonrpc_msg *request, *reply;
+ 
++        bool terse = false;
++        if (*arg == '?') {
++            /* We're only interested in terse table contents. */
++            terse = true;
++            arg++;
++        }
++
+         if (*arg == '+') {
+             /* The previous transaction didn't change anything. */
+             arg++;
+@@ -2654,10 +2684,10 @@ do_idl(struct ovs_cmdl_context *ctx)
+ 
+             /* Print update. */
+             if (track) {
+-                print_idl_track(idl, step++);
++                print_idl_track(idl, step++, terse);
+                 ovsdb_idl_track_clear(idl);
+             } else {
+-                print_idl(idl, step++);
++                print_idl(idl, step++, terse);
+             }
+         }
+         seqno = ovsdb_idl_get_seqno(idl);
+@@ -2710,7 +2740,7 @@ do_idl(struct ovs_cmdl_context *ctx)
+         ovsdb_idl_wait(idl);
+         poll_block();
+     }
+-    print_idl(idl, step++);
++    print_idl(idl, step++, false);
+     ovsdb_idl_track_clear(idl);
+     ovsdb_idl_destroy(idl);
+     print_and_log("%03d: done", step);
+@@ -2727,13 +2757,15 @@ print_idl_row_simple2(const struct idltest_simple2 *s, int step)
      printf("%03d: name=%s smap=[",
             step, s->name);
      for (i = 0; i < smap->n; i++) {
@@ -5720,7 +6111,7 @@ index daa55dab7b..637271619f 100644
      }
      printf("]\n");
  }
-@@ -2802,8 +2821,8 @@ do_idl_partial_update_map_column(struct ovs_cmdl_context *ctx)
+@@ -2802,8 +2834,8 @@ do_idl_partial_update_map_column(struct ovs_cmdl_context *ctx)
      myTxn = ovsdb_idl_txn_create(idl);
      smap = idltest_simple2_get_smap(myRow, OVSDB_TYPE_STRING,
                                      OVSDB_TYPE_STRING);
@@ -5731,6 +6122,151 @@ index daa55dab7b..637271619f 100644
      ovsdb_idl_txn_commit_block(myTxn);
      ovsdb_idl_txn_destroy(myTxn);
      ovsdb_idl_get_initial_snapshot(idl);
+@@ -2829,7 +2861,7 @@ dump_simple3(struct ovsdb_idl *idl,
+              int step)
+ {
+     IDLTEST_SIMPLE3_FOR_EACH(myRow, idl) {
+-        print_idl_row_simple3(myRow, step);
++        print_idl_row_simple3(myRow, step, false);
+     }
+ }
+ 
+@@ -2971,7 +3003,7 @@ do_idl_compound_index_with_ref(struct ovs_cmdl_context *ctx)
+     idltest_simple3_index_set_uref(equal, &myRow2, 1);
+     printf("%03d: Query using index with reference\n", step++);
+     IDLTEST_SIMPLE3_FOR_EACH_EQUAL (myRow, equal, index) {
+-        print_idl_row_simple3(myRow, step++);
++        print_idl_row_simple3(myRow, step++, false);
+     }
+     idltest_simple3_index_destroy_row(equal);
+ 
+diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py
+index 5bc0bf6814..853264f22b 100644
+--- a/tests/test-ovsdb.py
++++ b/tests/test-ovsdb.py
+@@ -232,75 +232,87 @@ def get_singleton_table_printable_row(row):
+     return "name=%s" % row.name
+ 
+ 
+-def print_row(table, row, step, contents):
+-    s = "%03d: table %s: %s " % (step, table, contents)
+-    s += get_simple_printable_row_string(row, ["uuid"])
++def print_row(table, row, step, contents, terse):
++    if terse:
++        s = "%03d: table %s" % (step, table)
++    else:
++        s = "%03d: table %s: %s " % (step, table, contents)
++        s += get_simple_printable_row_string(row, ["uuid"])
+     print(s)
+ 
+ 
+-def print_idl(idl, step):
++def print_idl(idl, step, terse=False):
+     n = 0
+     if "simple" in idl.tables:
+         simple = idl.tables["simple"].rows
+         for row in simple.values():
+             print_row("simple", row, step,
+-                      get_simple_table_printable_row(row))
++                      get_simple_table_printable_row(row),
++                      terse)
+             n += 1
+ 
+     if "simple2" in idl.tables:
+         simple2 = idl.tables["simple2"].rows
+         for row in simple2.values():
+             print_row("simple2", row, step,
+-                      get_simple2_table_printable_row(row))
++                      get_simple2_table_printable_row(row),
++                      terse)
+             n += 1
+ 
+     if "simple3" in idl.tables:
+         simple3 = idl.tables["simple3"].rows
+         for row in simple3.values():
+             print_row("simple3", row, step,
+-                      get_simple3_table_printable_row(row))
++                      get_simple3_table_printable_row(row),
++                      terse)
+             n += 1
+ 
+     if "simple4" in idl.tables:
+         simple4 = idl.tables["simple4"].rows
+         for row in simple4.values():
+             print_row("simple4", row, step,
+-                      get_simple4_table_printable_row(row))
++                      get_simple4_table_printable_row(row),
++                      terse)
+             n += 1
+ 
+     if "simple5" in idl.tables:
+         simple5 = idl.tables["simple5"].rows
+         for row in simple5.values():
+             print_row("simple5", row, step,
+-                      get_simple5_table_printable_row(row))
++                      get_simple5_table_printable_row(row),
++                      terse)
+             n += 1
+ 
+     if "simple6" in idl.tables:
+         simple6 = idl.tables["simple6"].rows
+         for row in simple6.values():
+             print_row("simple6", row, step,
+-                      get_simple6_table_printable_row(row))
++                      get_simple6_table_printable_row(row),
++                      terse)
+             n += 1
+ 
+     if "link1" in idl.tables:
+         l1 = idl.tables["link1"].rows
+         for row in l1.values():
+             print_row("link1", row, step,
+-                      get_link1_table_printable_row(row))
++                      get_link1_table_printable_row(row),
++                      terse)
+             n += 1
+ 
+     if "link2" in idl.tables:
+         l2 = idl.tables["link2"].rows
+         for row in l2.values():
+             print_row("link2", row, step,
+-                      get_link2_table_printable_row(row))
++                      get_link2_table_printable_row(row),
++                      terse)
+             n += 1
+ 
+     if "singleton" in idl.tables:
+         sng = idl.tables["singleton"].rows
+         for row in sng.values():
+             print_row("singleton", row, step,
+-                      get_singleton_table_printable_row(row))
++                      get_singleton_table_printable_row(row),
++                      terse)
+             n += 1
+ 
+     if not n:
+@@ -701,6 +713,12 @@ def do_idl(schema_file, remote, *commands):
+         step += 1
+ 
+     for command in commands:
++        terse = False
++        if command.startswith("?"):
++            # We're only interested in terse table contents.
++            terse = True
++            command = command[1:]
++
+         if command.startswith("+"):
+             # The previous transaction didn't change anything.
+             command = command[1:]
+@@ -714,7 +732,7 @@ def do_idl(schema_file, remote, *commands):
+                 rpc.wait(poller)
+                 poller.block()
+ 
+-            print_idl(idl, step)
++            print_idl(idl, step, terse)
+             step += 1
+ 
+         seqno = idl.change_seqno
 diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
 index 59723e63b8..c7665a1aeb 100644
 --- a/tests/tunnel-push-pop-ipv6.at
diff --git a/SPECS/openvswitch2.16.spec b/SPECS/openvswitch2.16.spec
index 7010282..425ecd2 100644
--- a/SPECS/openvswitch2.16.spec
+++ b/SPECS/openvswitch2.16.spec
@@ -57,7 +57,7 @@ Summary: Open vSwitch
 Group: System Environment/Daemons daemon/database/utilities
 URL: http://www.openvswitch.org/
 Version: 2.16.0
-Release: 43%{?dist}
+Release: 44%{?dist}
 
 # Nearly all of openvswitch is ASL 2.0.  The bugtool is LGPLv2+, and the
 # lib/sflow*.[ch] files are SISSL
@@ -699,6 +699,15 @@ exit 0
 %endif
 
 %changelog
+* Mon Jan 31 2022 Open vSwitch CI <ovs-ci@redhat.com> - 2.16.0-44
+- Merging upstream branch-2.16 [RH git: d202cd6da1]
+    Commit list:
+    34c830c540 ovsdb-idl: ovsdb_idl_loop_destroy must also destroy the committing txn.
+    13009736b2 ovsdb-cs: Clear last_id on reconnect if condition changes in-flight.
+    017e2ae50e ofp-flow: Skip flow reply if it exceeds the maximum message size.
+    e0c6f92a95 ovsdb-cs: Fix ignoring of the last id from the initial monitor reply. (#2044624)
+
+
 * Fri Jan 28 2022 Ilya Maximets <i.maximets@redhat.com> - 2.16.0-43
 - ovsdb: storage: Randomize should_snapshot checks when the minimum time passed. [RH git: abe61535ca] (#2044614)
     commit 339f97044e3c2312fbb65b932fa14a181acf40d5