diff --git a/NEWS b/NEWS
index ba201cf..796ee38 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,8 @@
 Post-v2.5.0
 ---------------------
    - ovsdb-server:
-     * New "monitor2" and "update2" extensions to RFC 7047.
+     * New "monitor_cond" "monitor_cond_update" and "update2" extensions to
+     RFC 7047.
    - OpenFlow:
      * OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY.
      * OpenFlow 1.4+ OFPMP_QUEUE_DESC is now supported.
diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index b14bef2..170c171 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -79,8 +79,8 @@ enum ovsdb_idl_state {
     IDL_S_SCHEMA_REQUESTED,
     IDL_S_MONITOR_REQUESTED,
     IDL_S_MONITORING,
-    IDL_S_MONITOR2_REQUESTED,
-    IDL_S_MONITORING2,
+    IDL_S_MONITOR_COND_REQUESTED,
+    IDL_S_MONITORING_COND,
     IDL_S_NO_SCHEMA
 };
 
@@ -154,7 +154,7 @@ static struct vlog_rate_limit semantic_rl = VLOG_RATE_LIMIT_INIT(1, 5);
 static void ovsdb_idl_clear(struct ovsdb_idl *);
 static void ovsdb_idl_send_schema_request(struct ovsdb_idl *);
 static void ovsdb_idl_send_monitor_request(struct ovsdb_idl *);
-static void ovsdb_idl_send_monitor2_request(struct ovsdb_idl *);
+static void ovsdb_idl_send_monitor_cond_request(struct ovsdb_idl *);
 static void ovsdb_idl_parse_update(struct ovsdb_idl *, const struct json *,
                                    enum ovsdb_update_version);
 static struct ovsdb_error *ovsdb_idl_parse_update__(struct ovsdb_idl *,
@@ -413,20 +413,20 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
             case IDL_S_SCHEMA_REQUESTED:
                 /* Reply to our "get_schema" request. */
                 idl->schema = json_clone(msg->result);
-                ovsdb_idl_send_monitor2_request(idl);
-                idl->state = IDL_S_MONITOR2_REQUESTED;
+                ovsdb_idl_send_monitor_cond_request(idl);
+                idl->state = IDL_S_MONITOR_COND_REQUESTED;
                 break;
 
             case IDL_S_MONITOR_REQUESTED:
-            case IDL_S_MONITOR2_REQUESTED:
-                /* Reply to our "monitor" or "monitor2" request. */
+            case IDL_S_MONITOR_COND_REQUESTED:
+                /* Reply to our "monitor" or "monitor_cond" request. */
                 idl->change_seqno++;
                 ovsdb_idl_clear(idl);
                 if (idl->state == IDL_S_MONITOR_REQUESTED) {
                     idl->state = IDL_S_MONITORING;
                     ovsdb_idl_parse_update(idl, msg->result, OVSDB_UPDATE);
-                } else { /* IDL_S_MONITOR2_REQUESTED. */
-                    idl->state = IDL_S_MONITORING2;
+                } else { /* IDL_S_MONITOR_COND_REQUESTED. */
+                    idl->state = IDL_S_MONITORING_COND;
                     ovsdb_idl_parse_update(idl, msg->result, OVSDB_UPDATE2);
                 }
 
@@ -437,7 +437,7 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
                 break;
 
             case IDL_S_MONITORING:
-            case IDL_S_MONITORING2:
+            case IDL_S_MONITORING_COND:
             case IDL_S_NO_SCHEMA:
             default:
                 OVS_NOT_REACHED();
@@ -464,7 +464,7 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
             /* Someone else stole our lock. */
             ovsdb_idl_parse_lock_notify(idl, msg->params, false);
         } else if (msg->type == JSONRPC_ERROR
-                   && idl->state == IDL_S_MONITOR2_REQUESTED
+                   && idl->state == IDL_S_MONITOR_COND_REQUESTED
                    && idl->request_id
                    && json_equal(idl->request_id, msg->id)) {
             if (msg->error && !strcmp(json_string(msg->error),
@@ -1066,9 +1066,9 @@ log_parse_update_error(struct ovsdb_error *error)
 }
 
 static void
-ovsdb_idl_send_monitor2_request(struct ovsdb_idl *idl)
+ovsdb_idl_send_monitor_cond_request(struct ovsdb_idl *idl)
 {
-    ovsdb_idl_send_monitor_request__(idl, "monitor2");
+    ovsdb_idl_send_monitor_request__(idl, "monitor_cond");
 }
 
 static void
@@ -3246,7 +3246,7 @@ ovsdb_idl_update_has_lock(struct ovsdb_idl *idl, bool new_has_lock)
 {
     if (new_has_lock && !idl->has_lock) {
         if (idl->state == IDL_S_MONITORING ||
-            idl->state == IDL_S_MONITORING2) {
+            idl->state == IDL_S_MONITORING_COND) {
             idl->change_seqno++;
         } else {
             /* We're setting up a session, so don't signal that the database
diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index 536a044..864fb03 100644
--- a/ovsdb/jsonrpc-server.c
+++ b/ovsdb/jsonrpc-server.c
@@ -46,9 +46,9 @@ VLOG_DEFINE_THIS_MODULE(ovsdb_jsonrpc_server);
 struct ovsdb_jsonrpc_remote;
 struct ovsdb_jsonrpc_session;
 
-/* Set false to defeature monitor2, causing jsonrpc to respond to monitor2
- * method with an error.  */
-static bool monitor2_enable__ = true;
+/* Set false to defeature monitor_cond, causing jsonrpc to respond to
+ * monitor_cond method with an error.  */
+static bool monitor_cond_enable__ = true;
 
 /* Message rate-limiting. */
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
@@ -873,8 +873,8 @@ ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
             reply = execute_transaction(s, db, request);
         }
     } else if (!strcmp(request->method, "monitor") ||
-               (monitor2_enable__ && !strcmp(request->method, "monitor2")) ||
-               !strcmp(request->method, "monitor_cond")) {
+               (monitor_cond_enable__ && !strcmp(request->method,
+                                                 "monitor_cond"))) {
         struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply);
         if (!reply) {
             int l = strlen(request->method) - strlen("monitor");
@@ -1559,8 +1559,8 @@ ovsdb_jsonrpc_monitor_flush_all(struct ovsdb_jsonrpc_session *s)
 }
 
 void
-ovsdb_jsonrpc_disable_monitor2(void)
+ovsdb_jsonrpc_disable_monitor_cond(void)
 {
     /* Once disabled, it is not possible to re-enable it. */
-    monitor2_enable__ = false;
+    monitor_cond_enable__ = false;
 }
diff --git a/ovsdb/jsonrpc-server.h b/ovsdb/jsonrpc-server.h
index 7a0bd31..ea50ff6 100644
--- a/ovsdb/jsonrpc-server.h
+++ b/ovsdb/jsonrpc-server.h
@@ -71,6 +71,6 @@ void ovsdb_jsonrpc_server_get_memory_usage(const struct ovsdb_jsonrpc_server *,
 
 struct ovsdb_jsonrpc_monitor;
 void ovsdb_jsonrpc_monitor_destroy(struct ovsdb_jsonrpc_monitor *);
-void ovsdb_jsonrpc_disable_monitor2(void);
+void ovsdb_jsonrpc_disable_monitor_cond(void);
 
 #endif /* ovsdb/jsonrpc-server.h */
diff --git a/ovsdb/ovsdb-client.1.in b/ovsdb/ovsdb-client.1.in
index 5d99f59..444937c 100644
--- a/ovsdb/ovsdb-client.1.in
+++ b/ovsdb/ovsdb-client.1.in
@@ -33,10 +33,8 @@ ovsdb\-client \- command-line interface to \fBovsdb-server\fR(1)
 .br
 \fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR
 .br
-\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR
-[\fIcolumn\fR[\fB,\fIcolumn\fR]...]...
-.br
-\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR
+\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor-cond\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fIconditions
+\fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]...
 .br
 \fBovsdb\-client help\fR
 .IP "Output formatting options:"
@@ -113,12 +111,12 @@ specified, only that table is retrieved.  If at least one \fIcolumn\fR
 is specified, only those columns are retrieved.
 .
 .IP "\fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..."
-.IQ "\fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..."
-Connects to \fIserver\fR and monitors the contents of \fItable\fR in
-\fIdatabase\fR.  By default, the initial contents of \fItable\fR are
-printed, followed by each change as it occurs.  If at least one
-\fIcolumn\fR is specified, only those columns are monitored.  The
-following \fIcolumn\fR names have special meanings:
+.IQ "\fBmonitor-cond\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fIconditions\fR \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..."
+Connects to \fIserver\fR and monitors the contents of rows that match conditions in
+\fItable\fR in \fIdatabase\fR. By default, the initial contents of \fItable\fR are
+printed, followed by each change as it occurs.  If conditions empty,
+all rows will be monitored. If at least one \fIcolumn\fR is specified, only those
+columns are monitored.  The following \fIcolumn\fR names have special meanings:
 .RS
 .IP "\fB!initial\fR"
 Do not print the initial contents of the specified columns.
@@ -136,16 +134,18 @@ each group.  Whether multiple groups or only a single group is
 specified, any given column may only be mentioned once on the command
 line.
 .IP
-If \fB\-\-detach\fR is used with \fBmonitor\fR or \fBmointor2\fR, then
+\fBconditions\fR is a JSON array of <condition> as defined in RFC 7047 5.1
+with the following change: A condition can be either a 3-element JSON array
+as deescribed in the RFC or a boolean value..
+.IP
+If \fB\-\-detach\fR is used with \fBmonitor\fR or \fBmonitor-cond\fR, then
 \fBovsdb\-client\fR detaches after it has successfully received and
 printed the initial contents of \fItable\fR.
 .IP
 The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor
-session with the server. The \fBmonitor2\fR command uses RFC 7047
-extension "monitor2" method. See \fBovsdb\-server\fR(1) for details.
-.
+session with the server. The \fBmonitor-cond\fR command uses RFC 7047
+extension "monitor_cond" method. See \fBovsdb\-server\fR(1) for details.
 .IP "\fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR"
-.IQ "\fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR"
 Connects to \fIserver\fR and monitors the contents of all tables in
 \fIdatabase\fR.  Prints initial values and all kinds of changes to all
 columns in the database.  The \fB\-\-detach\fR option causes
@@ -153,8 +153,7 @@ columns in the database.  The \fB\-\-detach\fR option causes
 prints the initial database contents.
 .IP
 The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor
-session with the server. The \fBmonitor2\fR command uses RFC 7047
-extension "monitor2" method. See \fBovsdb\-server\fR(1) for details.
+session with the server.
 .
 .SH OPTIONS
 .SS "Output Formatting Options"
@@ -165,13 +164,13 @@ The following options controlling output formatting:
 .so lib/table.man
 .
 .IP "\fB\-\-timestamp\fR"
-For the \fBmonitor\fR and \fBmonitor2\fR commands, add a timestamp to each
+For the \fBmonitor\fR and \fBmonitor-cond\fR commands, add a timestamp to each
 table update.  Most output formats add the timestamp on a line of its own
 just above the table.  The JSON output format puts the timestamp in a
 member of the top-level JSON object named \fBtime\fR.
 .
 .SS "Daemon Options"
-The daemon options apply only to the \fBmonitor\fR and \fBmonitor2\fR commands.
+The daemon options apply only to the \fBmonitor\fR and \fBmonitor-cond\fR commands.
 With any other command, they have no effect.
 .ds DD
 .so lib/daemon.man
diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c
index 80819a8..da4de75 100644
--- a/ovsdb/ovsdb-client.c
+++ b/ovsdb/ovsdb-client.c
@@ -45,6 +45,7 @@
 #include "stream-ssl.h"
 #include "table.h"
 #include "monitor.h"
+#include "condition.h"
 #include "timeval.h"
 #include "unixctl.h"
 #include "util.h"
@@ -257,12 +258,14 @@ usage(void)
            "    monitor contents of COLUMNs in TABLE in DATABASE on SERVER.\n"
            "    COLUMNs may include !initial, !insert, !delete, !modify\n"
            "    to avoid seeing the specified kinds of changes.\n"
+           "\n  monitor-cond [SERVER] [DATABASE] CONDITION TABLE [COLUMN,...]...\n"
+           "    monitor contents that match CONDITION of COLUMNs in TABLE in\n"
+           "    DATABASE on SERVER.\n"
+           "    COLUMNs may include !initial, !insert, !delete, !modify\n"
+           "    to avoid seeing the specified kinds of changes.\n"
            "\n  monitor [SERVER] [DATABASE] ALL\n"
            "    monitor all changes to all columns in all tables\n"
            "    in DATBASE on SERVER.\n"
-           "\n  monitor2 [SERVER] [DATABASE] ALL\n"
-           "    same usage as monitor, but uses \"monitor2\" method over"
-           "    the wire."
            "\n  dump [SERVER] [DATABASE]\n"
            "    dump contents of DATABASE on SERVER to stdout\n"
            "\nThe default SERVER is unix:%s/db.sock.\n"
@@ -839,14 +842,41 @@ ovsdb_client_unblock(struct unixctl_conn *conn, int argc OVS_UNUSED,
 }
 
 static void
+ovsdb_client_cond_change(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                     const char *argv[], void *rpc_)
+{
+    struct jsonrpc *rpc = rpc_;
+    struct json *monitor_cond_update_requests = json_object_create();
+    struct json *monitor_cond_update_request = json_object_create();
+    struct json *params;
+    struct jsonrpc_msg *request;
+
+    json_object_put(monitor_cond_update_request, "where",
+                    json_from_string(argv[2]));
+    json_object_put(monitor_cond_update_requests,
+                    argv[1],
+                    json_array_create_1(monitor_cond_update_request));
+
+    params = json_array_create_3(json_null_create(),json_null_create(),
+                                 monitor_cond_update_requests);
+
+    request = jsonrpc_create_request("monitor_cond_change", params, NULL);
+    jsonrpc_send(rpc, request);
+
+    VLOG_DBG("cond change %s %s", argv[1], argv[2]);
+    unixctl_command_reply(conn, "condiiton changed");
+}
+
+static void
 add_monitored_table(int argc, char *argv[],
                     const char *server, const char *database,
+                    struct json *condition,
                     struct ovsdb_table_schema *table,
                     struct json *monitor_requests,
                     struct monitored_table **mts,
                     size_t *n_mts, size_t *allocated_mts)
 {
-    struct json *monitor_request_array;
+    struct json *monitor_request_array, *mr;
     struct monitored_table *mt;
 
     if (*n_mts >= *allocated_mts) {
@@ -861,19 +891,24 @@ add_monitored_table(int argc, char *argv[],
         int i;
 
         for (i = 1; i < argc; i++) {
-            json_array_add(
-                monitor_request_array,
-                parse_monitor_columns(argv[i], server, database, table,
-                                      &mt->columns));
+            mr = parse_monitor_columns(argv[i], server, database, table,
+                                       &mt->columns);
+            if (i == 1 && condition) {
+                json_object_put(mr, "where", condition);
+            }
+            json_array_add(monitor_request_array, mr);
         }
     } else {
         /* Allocate a writable empty string since parse_monitor_columns()
          * is going to strtok() it and that's risky with literal "". */
         char empty[] = "";
-        json_array_add(
-            monitor_request_array,
-            parse_monitor_columns(empty, server, database,
-                                  table, &mt->columns));
+
+        mr = parse_monitor_columns(empty, server, database,
+                                   table, &mt->columns);
+        if (condition) {
+            json_object_put(mr, "where", condition);
+        }
+        json_array_add(monitor_request_array, mr);
     }
 
     json_object_put(monitor_requests, table->name, monitor_request_array);
@@ -895,7 +930,7 @@ destroy_monitored_table(struct monitored_table *mts, size_t n)
 static void
 do_monitor__(struct jsonrpc *rpc, const char *database,
              enum ovsdb_monitor_version version,
-             int argc, char *argv[])
+             int argc, char *argv[], struct json *condition)
 {
     const char *server = jsonrpc_get_name(rpc);
     const char *table_name = argv[0];
@@ -927,6 +962,8 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
                                  ovsdb_client_block, &blocked);
         unixctl_command_register("ovsdb-client/unblock", "", 0, 0,
                                  ovsdb_client_unblock, &blocked);
+        unixctl_command_register("ovsdb-client/cond_change", "TABLE COND", 2, 2,
+                                 ovsdb_client_cond_change, rpc);
     } else {
         unixctl = NULL;
     }
@@ -946,17 +983,21 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
                       server, database, table_name);
         }
 
-        add_monitored_table(argc, argv, server, database, table,
+        add_monitored_table(argc, argv, server, database, condition, table,
                             monitor_requests, &mts, &n_mts, &allocated_mts);
     } else {
         size_t n = shash_count(&schema->tables);
         const struct shash_node **nodes = shash_sort(&schema->tables);
         size_t i;
 
+        if (condition) {
+            ovs_fatal(0, "ALL tables are not allowed with condition");
+        }
+
         for (i = 0; i < n; i++) {
             struct ovsdb_table_schema *table = nodes[i]->data;
 
-            add_monitored_table(argc, argv, server, database, table,
+            add_monitored_table(argc, argv, server, database, NULL, table,
                                 monitor_requests,
                                 &mts, &n_mts, &allocated_mts);
         }
@@ -965,7 +1006,7 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
 
     monitor = json_array_create_3(json_string_create(database),
                                   json_null_create(), monitor_requests);
-    const char *method = version == OVSDB_MONITOR_V2 ? "monitor2"
+    const char *method = version == OVSDB_MONITOR_V2 ? "monitor_cond"
                                                      : "monitor";
 
     request = jsonrpc_create_request(method, monitor, NULL);
@@ -1049,14 +1090,31 @@ static void
 do_monitor(struct jsonrpc *rpc, const char *database,
            int argc, char *argv[])
 {
-    do_monitor__(rpc, database, OVSDB_MONITOR_V1, argc, argv);
+    do_monitor__(rpc, database, OVSDB_MONITOR_V1, argc, argv, NULL);
 }
 
 static void
-do_monitor2(struct jsonrpc *rpc, const char *database,
+do_monitor_cond(struct jsonrpc *rpc, const char *database,
            int argc, char *argv[])
 {
-    do_monitor__(rpc, database, OVSDB_MONITOR_V2, argc, argv);
+    struct ovsdb_condition cnd;
+    struct json *condition = NULL;
+    struct ovsdb_schema *schema;
+    struct ovsdb_table_schema *table;
+    const char *table_name = argv[1];
+
+    ovs_assert(argc > 1);
+    schema = fetch_schema(rpc, database);
+    table = shash_find_data(&schema->tables, table_name);
+    if (!table) {
+        ovs_fatal(0, "%s does not have a table named \"%s\"",
+                  database, table_name);
+    }
+    condition = parse_json(argv[0]);
+    check_ovsdb_error(ovsdb_condition_from_json(table, condition,
+                                                    NULL, &cnd));
+    ovsdb_condition_destroy(&cnd);
+    do_monitor__(rpc, database, OVSDB_MONITOR_V2, --argc, ++argv, condition);
 }
 
 struct dump_table_aux {
@@ -1329,7 +1387,7 @@ static const struct ovsdb_client_command all_commands[] = {
     { "list-columns",       NEED_DATABASE, 0, 1,       do_list_columns },
     { "transact",           NEED_RPC,      1, 1,       do_transact },
     { "monitor",            NEED_DATABASE, 1, INT_MAX, do_monitor },
-    { "monitor2",           NEED_DATABASE, 1, INT_MAX, do_monitor2 },
+    { "monitor-cond",       NEED_DATABASE, 2, 3,       do_monitor_cond },
     { "dump",               NEED_DATABASE, 0, INT_MAX, do_dump },
     { "help",               NEED_NONE,     0, INT_MAX, do_help },
 
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index 0ec3053..128bc15 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -80,7 +80,7 @@ static unixctl_cb_func ovsdb_server_compact;
 static unixctl_cb_func ovsdb_server_reconnect;
 static unixctl_cb_func ovsdb_server_perf_counters_clear;
 static unixctl_cb_func ovsdb_server_perf_counters_show;
-static unixctl_cb_func ovsdb_server_disable_monitor2;
+static unixctl_cb_func ovsdb_server_disable_monitor_cond;
 
 struct server_config {
     struct sset *remotes;
@@ -335,9 +335,9 @@ main(int argc, char *argv[])
                              ovsdb_server_perf_counters_clear, NULL);
 
     /* Simulate the behavior of OVS release prior to version 2.5 that
-     * does not support the monitor2 method.  */
-    unixctl_command_register("ovsdb-server/disable-monitor2", "", 0, 0,
-                             ovsdb_server_disable_monitor2, jsonrpc);
+     * does not support the monitor_cond method.  */
+    unixctl_command_register("ovsdb-server/disable-monitor-cond", "", 0, 0,
+                             ovsdb_server_disable_monitor_cond, jsonrpc);
 
     main_loop(jsonrpc, &all_dbs, unixctl, &remotes, run_process, &exiting);
 
@@ -1062,16 +1062,18 @@ ovsdb_server_perf_counters_clear(struct unixctl_conn *conn, int argc OVS_UNUSED,
     unixctl_command_reply(conn, NULL);
 }
 
-/* "ovsdb-server/disable-monitor2": makes ovsdb-server drop all of its
+/* "ovsdb-server/disable-monitor-cond": makes ovsdb-server drop all of its
  * JSON-RPC connections and reconnect. New sessions will not recognize
- * the 'monitor2' method.   */
+ * the 'monitor_cond' method.   */
 static void
-ovsdb_server_disable_monitor2(struct unixctl_conn *conn, int argc OVS_UNUSED,
-                              const char *argv[] OVS_UNUSED, void *jsonrpc_)
+ovsdb_server_disable_monitor_cond(struct unixctl_conn *conn,
+                                  int argc OVS_UNUSED,
+                                  const char *argv[] OVS_UNUSED,
+                                  void *jsonrpc_)
 {
     struct ovsdb_jsonrpc_server *jsonrpc = jsonrpc_;
 
-    ovsdb_jsonrpc_disable_monitor2();
+    ovsdb_jsonrpc_disable_monitor_cond();
     ovsdb_jsonrpc_server_reconnect(jsonrpc);
     unixctl_command_reply(conn, NULL);
 }
diff --git a/tests/ovs-vswitchd.at b/tests/ovs-vswitchd.at
index 816d0a2..a3129c2 100644
--- a/tests/ovs-vswitchd.at
+++ b/tests/ovs-vswitchd.at
@@ -167,14 +167,14 @@ OVS_VSWITCHD_STOP(["/Not adding Unix domain socket controller/d"])
 AT_CLEANUP
 
 dnl ----------------------------------------------------------------------
-dnl OVSDB server before release version 2.5 does not support the monitor2
+dnl OVSDB server before release version 2.5 does not support the monitor_cond
 dnl method.  This test defeatures the OVSDB server to simulate an older
 dnl OVSDB server and make sure ovs-vswitchd can still work with it
-AT_SETUP([ovs-vswitchd -- Compatible with OVSDB server - w/o monitor2])
+AT_SETUP([ovs-vswitchd -- Compatible with OVSDB server - w/o monitor_cond])
 OVS_VSWITCHD_START
 
-dnl defeature OVSDB server -- no monitor2
-AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/disable-monitor2])
+dnl defeature OVSDB server -- no monitor_cond
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/disable-monitor-cond])
 
 sleep 1
 
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index 057d09f..dd3bbdf 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -649,13 +649,13 @@ test-ovsdb|ovsdb_idl|link1 table in idltest database lacks l2 column (database n
 # Check that ovsdb-idl sent on "monitor" request and that it didn't
 # mention that table or column, and (for paranoia) that it did mention another
 # table and column.
-AT_CHECK([grep -c '"monitor\|monitor2"' stderr], [0], [1
+AT_CHECK([grep -c '"monitor\|monitor_cond"' stderr], [0], [1
 ])
-AT_CHECK([grep '"monitor\|monitor2"' stderr | grep link2], [1])
-AT_CHECK([grep '"monitor\|monitor2"' stderr | grep l2], [1])
-AT_CHECK([grep '"monitor\|monitor2"' stderr | grep -c '"link1"'], [0], [1
+AT_CHECK([grep '"monitor\|monitor_cond"' stderr | grep link2], [1])
+AT_CHECK([grep '"monitor\|monitor_cond"' stderr | grep l2], [1])
+AT_CHECK([grep '"monitor\|monitor_cond"' stderr | grep -c '"link1"'], [0], [1
 ])
-AT_CHECK([grep '"monitor\|monitor2"' stderr | grep -c '"ua"'], [0], [1
+AT_CHECK([grep '"monitor\|monitor_cond"' stderr | grep -c '"ua"'], [0], [1
 ])
 OVSDB_SERVER_SHUTDOWN
 AT_CLEANUP
diff --git a/tests/ovsdb-monitor.at b/tests/ovsdb-monitor.at
index 37383fa..0a3cc58 100644
--- a/tests/ovsdb-monitor.at
+++ b/tests/ovsdb-monitor.at
@@ -44,6 +44,54 @@ m4_define([OVSDB_CHECK_MONITOR],
    AT_CHECK([${PERL} $srcdir/ovsdb-monitor-sort.pl < output | ${PERL} $srcdir/uuidfilt.pl], [0], [$7], [ignore])
    AT_CLEANUP])
 
+# OVSDB_CHECK_MONITOR_COND(TITLE, SCHEMA, [PRE-MONITOR-TXN], DB, TABLE,
+#                     TRANSACTIONS, OUTPUT, CONDITIONS, [COLUMNS], [KEYWORDS],
+#                     [CONDITIONS_CHANGE])
+#
+# Creates a database with the given SCHEMA, starts an ovsdb-server on
+# that database, and runs each of the TRANSACTIONS (which should be a
+# quoted list of quoted strings) against it with ovsdb-client one at a
+# time.  COLUMNS, if specified, is passed to ovsdb-client as the set
+# of columns and operations to select.
+#
+# Checks that the overall output is OUTPUT, but UUIDs in the output
+# are replaced by markers of the form <N> where N is a number.  The
+# first unique UUID is replaced by <0>, the next by <1>, and so on.
+# If a given UUID appears more than once it is always replaced by the
+# same marker.
+#
+# TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
+m4_define([OVSDB_CHECK_MONITOR_COND],
+  [AT_SETUP([$1])
+   AT_KEYWORDS([ovsdb server monitor monitor-cond positive $10])
+   $2 > schema
+   AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
+   m4_foreach([txn], [$3],
+     [AT_CHECK([ovsdb-tool transact db 'txn'], [0], [ignore], [ignore])])
+   AT_CAPTURE_FILE([ovsdb-server-log])
+   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/server-pid --remote=punix:socket --unixctl="`pwd`"/unixctl --log-file="`pwd`"/ovsdb-server-log db >/dev/null 2>&1],
+            [0], [], [])
+   if test "$IS_WIN32" = "yes"; then
+     AT_CHECK([ovsdb-client -vjsonrpc --pidfile="`pwd`"/client-pid -d json monitor-cond --format=csv unix:socket $4 '[$8]' $5 $9 > output &],
+              [0], [ignore], [ignore], [kill `cat server-pid`])
+     sleep 1
+   else
+     AT_CHECK([ ovsdb-client -vjsonrpc --detach --no-chdir --pidfile="`pwd`"/client-pid -d json monitor-cond --format=csv unix:socket $4 '[$8]' $5 $9 > output],
+            [0], [ignore], [ignore], [kill `cat server-pid`])
+   fi
+   m4_foreach([txn], [$6],
+     [AT_CHECK([ovsdb-client transact unix:socket 'txn'], [0],
+                     [ignore], [ignore], [kill `cat server-pid client-pid`])])
+   CLIENT_PID=`cat "$OVS_RUNDIR"/client-pid 2>/dev/null`
+   m4_foreach([cond], [$10],
+     [AT_CHECK([ovs-appctl -t "`pwd`"/ovsdb-client.$CLIENT_PID.ctl ovsdb-client/cond_change $5 'cond'], [0], [ignore], [ignore])])
+   AT_CHECK([ovsdb-client transact unix:socket '[["$4"]]'], [0],
+            [ignore], [ignore], [kill `cat server-pid client-pid`])
+   AT_CHECK([ovs-appctl -t "`pwd`"/unixctl -e exit], [0], [ignore], [ignore])
+   OVS_WAIT_UNTIL([test ! -e server-pid && test ! -e client-pid])
+   AT_CHECK([${PERL} $srcdir/ovsdb-monitor-sort.pl < output | ${PERL} $srcdir/uuidfilt.pl], [0], [$7], [ignore])
+   AT_CLEANUP])
+
 OVSDB_CHECK_MONITOR([monitor insert into empty table],
   [ordinal_schema],
   [],
@@ -322,3 +370,206 @@ OVSDB_CHECK_MONITOR([monitor modify only],
 <0>,old,"""five""",,"[""uuid"",""<1>""]"
 ,new,"""FIVE""",5,"[""uuid"",""<2>""]"
 ]], [!initial,!insert,!delete])
+
+AT_BANNER([ovsdb -- ovsdb-monitor-cond conditional monitor only some operations])
+
+OVSDB_CHECK_MONITOR_COND([monitor-cond empty condition],
+  [ordinal_schema],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 0, "name": "zero"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 1, "name": "one"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 2, "name": "two"}}]]]],
+  [ordinals], [ordinals],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 10, "name": "ten"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 11, "name": "eleven"}}]]]],
+  [[row,action,name,number,_version
+<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
+<2>,initial,"""two""",2,"[""uuid"",""<3>""]"
+<4>,initial,"""zero""",,"[""uuid"",""<5>""]"
+
+row,action,name,number,_version
+<6>,insert,"""eleven""",11,"[""uuid"",""<7>""]"
+<8>,insert,"""ten""",10,"[""uuid"",""<9>""]"
+]],
+  [[]])
+
+OVSDB_CHECK_MONITOR_COND([monitor-cond multiple conditions],
+  [ordinal_schema],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 0, "name": "zero"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 1, "name": "one"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 2, "name": "two"}}]]]],
+  [ordinals], [ordinals],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 10, "name": "ten"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 11, "name": "eleven"}}]]]],
+  [[row,action,name,number,_version
+<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
+
+row,action,name,number,_version
+<2>,insert,"""ten""",10,"[""uuid"",""<3>""]"
+]],
+  [[["name","==","one"],["name","==","ten"]]])
+
+OVSDB_CHECK_MONITOR_COND([monitor-cond delete from populated table],
+  [ordinal_schema],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 0, "name": "zero"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 1, "name": "one"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 2, "name": "two"}}]]]],
+  [ordinals], [ordinals],
+  [[[["ordinals",
+      {"op": "delete",
+       "table": "ordinals",
+       "where": []}]]]],
+  [[row,action,name,number,_version
+<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
+
+row,action,name,number,_version
+<0>,delete,,,
+]],
+  [[["name","==","one"],["name","==","ten"]]])
+
+OVSDB_CHECK_MONITOR_COND([monitor-cond insert due to modify],
+  [ordinal_schema],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 0, "name": "zero"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 1, "name": "one"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 2, "name": "two"}}]]]],
+  [ordinals], [ordinals],
+  [[[["ordinals",
+      {"op": "update",
+       "table": "ordinals",
+       "where": [["name", "==", "one"]],
+       "row": {"name": "ONE"}}]]]],
+  [[row,action,name,number,_version
+<0>,insert,"""ONE""",1,"[""uuid"",""<1>""]"
+]],
+  [[["name","==","ONE"]]],
+  [!initial,!delete,!modify])
+
+OVSDB_CHECK_MONITOR_COND([monitor-cond delete due to modify],
+  [ordinal_schema],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 0, "name": "zero"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 1, "name": "one"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 2, "name": "two"}}]]]],
+  [ordinals], [ordinals],
+  [[[["ordinals",
+      {"op": "update",
+       "table": "ordinals",
+       "where": [["name", "==", "one"]],
+       "row": {"name": "ONE"}}]]]],
+  [[row,action,name,number,_version
+<0>,delete,,,
+]],
+  [[["name","==","one"]]],
+  [!initial,!insert,!modify])
+
+OVSDB_CHECK_MONITOR_COND([monitor-cond condition non-monitored columns],
+  [ordinal_schema],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 0, "name": "zero"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 1, "name": "one"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 2, "name": "two"}}]]]],
+  [ordinals], [ordinals],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 10, "name": "ten"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 11, "name": "eleven"}}]]]],
+  [[row,action,number
+<0>,initial,1
+
+row,action,number
+<1>,insert,10
+]],
+  [[["name","==","one"],["name","==","ten"]]],
+  ["number"])
+
+OVSDB_CHECK_MONITOR_COND([monitor-cond-change],
+  [ordinal_schema],
+  [[[["ordinals",
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 0, "name": "zero"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 1, "name": "one"}},
+      {"op": "insert",
+       "table": "ordinals",
+       "row": {"number": 2, "name": "two"}}]]]],
+  [ordinals], [ordinals],
+  [],
+  [[row,action,name,number,_version
+<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
+<2>,initial,"""two""",2,"[""uuid"",""<3>""]"
+<4>,initial,"""zero""",,"[""uuid"",""<5>""]"
+
+row,action,name,number,_version
+<4>,delete,,,
+
+row,action,name,number,_version
+<2>,delete,,,
+
+row,action,name,number,_version
+<0>,delete,,,
+
+row,action,name,number,_version
+<0>,insert,"""one""",1,"[""uuid"",""<1>""]"
+<2>,insert,"""two""",2,"[""uuid"",""<3>""]"
+<4>,insert,"""zero""",,"[""uuid"",""<5>""]"
+]],
+  [[]],
+  [],
+  [[[[["name","==","one"],["name","==","two"]]]],
+   [[[["name","==","one"]]]],
+    [[[false]]],
+    [[[true]]]])
