From patchwork Thu Feb 28 17:15:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 1049633 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="arDCsoMf"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 449KDh2qwvz9s4V for ; Fri, 1 Mar 2019 04:24:52 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0B277AB80; Thu, 28 Feb 2019 17:23:08 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id DC208AAF8 for ; Thu, 28 Feb 2019 17:15:39 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl1-f195.google.com (mail-pl1-f195.google.com [209.85.214.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id D045F806 for ; Thu, 28 Feb 2019 17:15:38 +0000 (UTC) Received: by mail-pl1-f195.google.com with SMTP id d15so10072994plr.1 for ; Thu, 28 Feb 2019 09:15:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=v4FqeuY5TjkXg+yZHYPg1xN/vf3hI/sZTN4A9Zsz6JM=; b=arDCsoMfEAPm2LhdNqHhKYxeztNbLsCvjpD7fad1BTqbwbSX/MmAOkBkqBwTXYrIM6 SWn7uW/PN9pZ1edvqX2Dl8KVSg0/xhMCer/CYSlhdDJuRtfH7BMyzym8VMr1vJGmM0+j 0/WZwKKtIDGQ1OeUrLVSG1Zc067SKU/1YNG0rs25Y88R/oRwOSXgXVtjpDNW62JEVe1w iA9FCHRrZhPY7/RQma8GqJ1iHHfXdSrc3R9b/qFkZZKF7IM/L4jxe8/KJ7FNSzE4yftI VTgv/8Ut86rxXnbkEgRFnrD6qmzVDKwX2VTR94dB1nlnM+pWSHyIUzHc0XvVDHoITKRU ZJsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=v4FqeuY5TjkXg+yZHYPg1xN/vf3hI/sZTN4A9Zsz6JM=; b=kPNGJD3teWVhmgS0jlmCbMzyUnk4AxKImVn5fOinj+1CuHiH8wYBeA8AurdhT1b8HD qM6AhVWmaOq3OE0GvvMwDU9JWrQLJiLKLflxI/lLdRsMrIOfXUtZNYcY+jZm9YY9q/ma G76bgHYAZtRvy8gu4Tj2w3F6pOeq6126ct9QmSJmSc4cyU7WmYjdcju4oDI+IpB7uSZz THWjB6/IxhHunsLsMy0CZ0v5dt49gDJae3w2vlGkRqv5DftMrMU/w2qhx+IWcTXCldYW r0/ou0ercURwlSqjzv9lmVVeovT27EYxU9l94e9TVxjmjDHzFPBbdTb7gnLRvcAh9Xh2 UprQ== X-Gm-Message-State: APjAAAViVq5w5TvjMqM/FPY3PYI/j1rtA3i5B/xJGpPHJvTCGTmR+6Ay Kqre3rsSMvfmVxlqgSf6wznuwnRp X-Google-Smtp-Source: APXvYqy731anBm7AIURWcRJU7DuppY64WsODZLX90GGl/kjlLOp+a3Z0/bySrak2sex3f6rvHGG17g== X-Received: by 2002:a17:902:28e9:: with SMTP id f96mr400212plb.169.1551374137943; Thu, 28 Feb 2019 09:15:37 -0800 (PST) Received: from localhost.localdomain.localdomain (c-76-21-108-74.hsd1.ca.comcast.net. [76.21.108.74]) by smtp.gmail.com with ESMTPSA id a4sm36972372pga.52.2019.02.28.09.15.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 28 Feb 2019 09:15:37 -0800 (PST) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 28 Feb 2019 09:15:19 -0800 Message-Id: <1551374120-44287-5-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1551374120-44287-1-git-send-email-hzhou8@ebay.com> References: <1551374120-44287-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v4 4/5] ovsdb-idl.c: Support monitor_cond_since method in C IDL. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Han Zhou Use monitor_cond_since in C IDL. If it is not supported by server, fall back to old method (monitor_cond, or monitor). Signed-off-by: Han Zhou --- lib/ovsdb-idl.c | 203 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 155 insertions(+), 48 deletions(-) diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index a7274de..5d86046 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -106,10 +106,10 @@ struct ovsdb_idl_arc { * connection. The next connection attempt has a chance at \ * picking a connected server. \ * \ - * * Otherwise, sends a "monitor_cond" request for the IDL \ + * * Otherwise, sends a "monitor_cond_since" request for the IDL \ * database whose details are informed by the schema \ * (obtained from the row), and transitions to \ - * IDL_S_DATA_MONITOR_COND_REQUESTED. \ + * IDL_S_DATA_MONITOR_COND_SINCE_REQUESTED. \ * \ * - If the reply indicates success, but the Database table does \ * not have a row for the IDL database, transitions to \ @@ -125,6 +125,13 @@ struct ovsdb_idl_arc { * transitions to IDL_S_DATA_MONITOR_COND_REQUESTED. */ \ OVSDB_IDL_STATE(DATA_SCHEMA_REQUESTED) \ \ + /* Waits for "monitor_cond_since" reply. If successful, replaces \ + * the IDL contents by the data carried in the reply and \ + * transitions to IDL_S_MONITORING. On failure, sends a \ + * "monitor_cond" request and transitions to \ + * IDL_S_DATA_MONITOR_COND_REQUESTED. */ \ + OVSDB_IDL_STATE(DATA_MONITOR_COND_SINCE_REQUESTED) \ + \ /* Waits for "monitor_cond" reply. If successful, replaces the \ * IDL contents by the data carried in the reply and transitions \ * to IDL_S_MONITORING. On failure, sends a "monitor" request \ @@ -136,9 +143,9 @@ struct ovsdb_idl_arc { * IDL_S_MONITORING. On failure, transitions to IDL_S_ERROR. */ \ OVSDB_IDL_STATE(DATA_MONITOR_REQUESTED) \ \ - /* State that processes "update" or "update2" notifications for \ - * the main database (and the Database table in _Server if \ - * available). \ + /* State that processes "update", "update2" or "update3" \ + * notifications for the main database (and the Database table \ + * in _Server if available). \ * \ * If we're monitoring the Database table and we get notified \ * that the IDL database has been deleted, we close the \ @@ -167,10 +174,18 @@ enum ovsdb_idl_state { static const char *ovsdb_idl_state_to_string(enum ovsdb_idl_state); +enum ovsdb_idl_monitor_method { + OVSDB_IDL_MM_MONITOR, + OVSDB_IDL_MM_MONITOR_COND, + OVSDB_IDL_MM_MONITOR_COND_SINCE +}; + enum ovsdb_idl_monitoring { OVSDB_IDL_NOT_MONITORING, /* Database is not being monitored. */ OVSDB_IDL_MONITORING, /* Database has "monitor" outstanding. */ OVSDB_IDL_MONITORING_COND, /* Database has "monitor_cond" outstanding. */ + OVSDB_IDL_MONITORING_COND_SINCE, /* Database has "monitor_cond_since" + outstanding. */ }; struct ovsdb_idl_db { @@ -220,7 +235,7 @@ static void ovsdb_idl_send_db_change_aware(struct ovsdb_idl *); static bool ovsdb_idl_check_server_db(struct ovsdb_idl *); static void ovsdb_idl_send_monitor_request(struct ovsdb_idl *, struct ovsdb_idl_db *, - bool use_monitor_cond); + enum ovsdb_idl_monitor_method); struct ovsdb_idl { struct ovsdb_idl_db server; @@ -287,8 +302,8 @@ static struct vlog_rate_limit other_rl = VLOG_RATE_LIMIT_INIT(1, 5); static void ovsdb_idl_clear(struct ovsdb_idl *); static void ovsdb_idl_db_parse_monitor_reply(struct ovsdb_idl_db *, - const struct json *result, - bool is_monitor_cond); + const struct json *result, + enum ovsdb_idl_monitor_method method); static bool ovsdb_idl_db_parse_update_rpc(struct ovsdb_idl_db *, const struct jsonrpc_msg *); static bool ovsdb_idl_handle_monitor_canceled(struct ovsdb_idl *, @@ -296,7 +311,7 @@ static bool ovsdb_idl_handle_monitor_canceled(struct ovsdb_idl *, const struct jsonrpc_msg *); static void ovsdb_idl_db_parse_update(struct ovsdb_idl_db *, const struct json *table_updates, - bool is_monitor_cond); + enum ovsdb_idl_monitor_method method); static bool ovsdb_idl_process_update(struct ovsdb_idl_table *, const struct uuid *, const struct json *old, @@ -674,7 +689,8 @@ ovsdb_idl_process_response(struct ovsdb_idl *idl, struct jsonrpc_msg *msg) if (!ok && idl->state != IDL_S_SERVER_SCHEMA_REQUESTED && idl->state != IDL_S_SERVER_MONITOR_COND_REQUESTED - && idl->state != IDL_S_DATA_MONITOR_COND_REQUESTED) { + && idl->state != IDL_S_DATA_MONITOR_COND_REQUESTED + && idl->state != IDL_S_DATA_MONITOR_COND_SINCE_REQUESTED) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); char *s = jsonrpc_msg_to_string(msg); VLOG_INFO_RL(&rl, "%s: received unexpected %s response in " @@ -692,7 +708,8 @@ ovsdb_idl_process_response(struct ovsdb_idl *idl, struct jsonrpc_msg *msg) if (ok) { json_destroy(idl->server.schema); idl->server.schema = json_clone(msg->result); - ovsdb_idl_send_monitor_request(idl, &idl->server, true); + ovsdb_idl_send_monitor_request(idl, &idl->server, + OVSDB_IDL_MM_MONITOR_COND); ovsdb_idl_transition(idl, IDL_S_SERVER_MONITOR_COND_REQUESTED); } else { ovsdb_idl_send_schema_request(idl, &idl->data); @@ -703,7 +720,8 @@ ovsdb_idl_process_response(struct ovsdb_idl *idl, struct jsonrpc_msg *msg) case IDL_S_SERVER_MONITOR_COND_REQUESTED: if (ok) { idl->server.monitoring = OVSDB_IDL_MONITORING_COND; - ovsdb_idl_db_parse_monitor_reply(&idl->server, msg->result, true); + ovsdb_idl_db_parse_monitor_reply(&idl->server, msg->result, + OVSDB_IDL_MM_MONITOR_COND); if (ovsdb_idl_check_server_db(idl)) { ovsdb_idl_send_db_change_aware(idl); } @@ -716,29 +734,48 @@ ovsdb_idl_process_response(struct ovsdb_idl *idl, struct jsonrpc_msg *msg) case IDL_S_DATA_SCHEMA_REQUESTED: json_destroy(idl->data.schema); idl->data.schema = json_clone(msg->result); - ovsdb_idl_send_monitor_request(idl, &idl->data, true); + ovsdb_idl_send_monitor_request(idl, &idl->data, + OVSDB_IDL_MM_MONITOR_COND); ovsdb_idl_transition(idl, IDL_S_DATA_MONITOR_COND_REQUESTED); break; + case IDL_S_DATA_MONITOR_COND_SINCE_REQUESTED: + if (!ok) { + /* "monitor_cond_since" not supported. Try "monitor_cond". */ + ovsdb_idl_send_monitor_request(idl, &idl->data, + OVSDB_IDL_MM_MONITOR_COND); + ovsdb_idl_transition(idl, IDL_S_DATA_MONITOR_COND_REQUESTED); + } else { + idl->data.monitoring = OVSDB_IDL_MONITORING_COND_SINCE; + ovsdb_idl_transition(idl, IDL_S_MONITORING); + ovsdb_idl_db_parse_monitor_reply(&idl->data, msg->result, + OVSDB_IDL_MM_MONITOR_COND_SINCE); + } + break; + case IDL_S_DATA_MONITOR_COND_REQUESTED: if (!ok) { /* "monitor_cond" not supported. Try "monitor". */ - ovsdb_idl_send_monitor_request(idl, &idl->data, false); + ovsdb_idl_send_monitor_request(idl, &idl->data, + OVSDB_IDL_MM_MONITOR); ovsdb_idl_transition(idl, IDL_S_DATA_MONITOR_REQUESTED); } else { idl->data.monitoring = OVSDB_IDL_MONITORING_COND; ovsdb_idl_transition(idl, IDL_S_MONITORING); - ovsdb_idl_db_parse_monitor_reply(&idl->data, msg->result, true); + ovsdb_idl_db_parse_monitor_reply(&idl->data, msg->result, + OVSDB_IDL_MM_MONITOR_COND); } break; case IDL_S_DATA_MONITOR_REQUESTED: idl->data.monitoring = OVSDB_IDL_MONITORING; ovsdb_idl_transition(idl, IDL_S_MONITORING); - ovsdb_idl_db_parse_monitor_reply(&idl->data, msg->result, false); + ovsdb_idl_db_parse_monitor_reply(&idl->data, msg->result, + OVSDB_IDL_MM_MONITOR); idl->data.change_seqno++; ovsdb_idl_clear(idl); - ovsdb_idl_db_parse_update(&idl->data, msg->result, false); + ovsdb_idl_db_parse_update(&idl->data, msg->result, + OVSDB_IDL_MM_MONITOR); break; case IDL_S_MONITORING: @@ -1564,7 +1601,7 @@ ovsdb_idl_send_cond_change(struct ovsdb_idl *idl) * conditional monitoring update request that we have not heard * from the server yet. Don't generate another request in this case. */ if (!jsonrpc_session_is_connected(idl->session) - || idl->data.monitoring != OVSDB_IDL_MONITORING_COND + || idl->data.monitoring == OVSDB_IDL_MONITORING || idl->request_id) { return; } @@ -1860,8 +1897,9 @@ ovsdb_idl_check_server_db(struct ovsdb_idl *idl) if (idl->state == IDL_S_SERVER_MONITOR_COND_REQUESTED) { json_destroy(idl->data.schema); idl->data.schema = json_from_string(database->schema); - ovsdb_idl_send_monitor_request(idl, &idl->data, true); - ovsdb_idl_transition(idl, IDL_S_DATA_MONITOR_COND_REQUESTED); + ovsdb_idl_send_monitor_request(idl, &idl->data, + OVSDB_IDL_MM_MONITOR_COND_SINCE); + ovsdb_idl_transition(idl, IDL_S_DATA_MONITOR_COND_SINCE_REQUESTED); } return true; } @@ -1951,7 +1989,7 @@ parse_schema(const struct json *schema_json) static void ovsdb_idl_send_monitor_request(struct ovsdb_idl *idl, struct ovsdb_idl_db *db, - bool use_monitor_cond) + enum ovsdb_idl_monitor_method monitor_method) { struct shash *schema = parse_schema(db->schema); struct json *monitor_requests = json_object_create(); @@ -2003,7 +2041,9 @@ ovsdb_idl_send_monitor_request(struct ovsdb_idl *idl, struct ovsdb_idl_db *db, json_object_put(monitor_request, "columns", columns); const struct ovsdb_idl_condition *cond = &table->condition; - if (use_monitor_cond && !ovsdb_idl_condition_is_true(cond)) { + if ((monitor_method == OVSDB_IDL_MM_MONITOR_COND || + monitor_method == OVSDB_IDL_MM_MONITOR_COND_SINCE) && + !ovsdb_idl_condition_is_true(cond)) { json_object_put(monitor_request, "where", ovsdb_idl_condition_to_json(cond)); table->cond_changed = false; @@ -2016,13 +2056,30 @@ ovsdb_idl_send_monitor_request(struct ovsdb_idl *idl, struct ovsdb_idl_db *db, db->cond_changed = false; - ovsdb_idl_send_request( - idl, - jsonrpc_create_request( - use_monitor_cond ? "monitor_cond" : "monitor", - json_array_create_3(json_string_create(db->class_->database), - json_clone(db->monitor_id), monitor_requests), - NULL)); + struct json *params = json_array_create_3( + json_string_create(db->class_->database), + json_clone(db->monitor_id), + monitor_requests); + const char *method; + switch (monitor_method) { + case OVSDB_IDL_MM_MONITOR: + method = "monitor"; + break; + case OVSDB_IDL_MM_MONITOR_COND: + method = "monitor_cond"; + break; + case OVSDB_IDL_MM_MONITOR_COND_SINCE: + method = "monitor_cond_since"; + struct uuid last_id = UUID_ZERO; + struct json *json_last_id = json_string_create_nocopy( + xasprintf(UUID_FMT, UUID_ARGS(&last_id))); + json_array_add(params, json_last_id); + break; + default: + OVS_NOT_REACHED(); + } + + ovsdb_idl_send_request(idl, jsonrpc_create_request(method, params, NULL)); } static void @@ -2039,30 +2096,68 @@ log_parse_update_error(struct ovsdb_error *error) static void ovsdb_idl_db_parse_monitor_reply(struct ovsdb_idl_db *db, const struct json *result, - bool is_monitor_cond) + enum ovsdb_idl_monitor_method method) { db->change_seqno++; + const struct json *table_updates = result; + if (method == OVSDB_IDL_MM_MONITOR_COND_SINCE) { + if (result->type != JSON_ARRAY || result->array.n != 3) { + struct ovsdb_error *error = ovsdb_syntax_error(result, NULL, + "Response of monitor_cond_since must " + "be an array with 3 elements."); + log_parse_update_error(error); + return; + } + + table_updates = result->array.elems[2]; + + } ovsdb_idl_db_clear(db); - ovsdb_idl_db_parse_update(db, result, is_monitor_cond); + ovsdb_idl_db_parse_update(db, table_updates, method); } static bool ovsdb_idl_db_parse_update_rpc(struct ovsdb_idl_db *db, const struct jsonrpc_msg *msg) { - if (msg->type == JSONRPC_NOTIFY) { - bool is_update = !strcmp(msg->method, "update"); - bool is_update2 = !strcmp(msg->method, "update2"); - if ((is_update || is_update2) - && msg->params->type == JSON_ARRAY - && msg->params->array.n == 2 - && json_equal(msg->params->array.elems[0], db->monitor_id)) { - ovsdb_idl_db_parse_update(db, msg->params->array.elems[1], - is_update2); - return true; - } + if (msg->type != JSONRPC_NOTIFY) { + return false; } - return false; + + enum ovsdb_idl_monitor_method mm; + uint8_t n; + if (!strcmp(msg->method, "update")) { + mm = OVSDB_IDL_MM_MONITOR; + n = 2; + } else if (!strcmp(msg->method, "update2")) { + mm = OVSDB_IDL_MM_MONITOR_COND; + n = 2; + } else if (!strcmp(msg->method, "update3")) { + mm = OVSDB_IDL_MM_MONITOR_COND_SINCE; + n = 3; + } else { + return false; + } + + struct json *params = msg->params; + if (params->type != JSON_ARRAY || params->array.n != n) { + struct ovsdb_error *error = ovsdb_syntax_error(params, NULL, + "%s must be an array with %u elements.", + msg->method, n); + log_parse_update_error(error); + return false; + } + + if (!json_equal(params->array.elems[0], db->monitor_id)) { + return false; + } + + struct json *table_updates = params->array.elems[1]; + if (!strcmp(msg->method, "update3")) { + table_updates = params->array.elems[2]; + } + ovsdb_idl_db_parse_update(db, table_updates, mm); + return true; } static bool @@ -2103,10 +2198,21 @@ ovsdb_idl_handle_monitor_canceled(struct ovsdb_idl *idl, static struct ovsdb_error * ovsdb_idl_db_parse_update__(struct ovsdb_idl_db *db, const struct json *table_updates, - bool is_monitor_cond) + enum ovsdb_idl_monitor_method method) { const struct shash_node *tables_node; - const char *version_suffix = is_monitor_cond ? "2" : ""; + const char *version_suffix; + switch (method) { + case OVSDB_IDL_MM_MONITOR: + version_suffix = ""; + break; + case OVSDB_IDL_MM_MONITOR_COND: + case OVSDB_IDL_MM_MONITOR_COND_SINCE: + version_suffix = "2"; + break; + default: + OVS_NOT_REACHED(); + } if (table_updates->type != JSON_OBJECT) { return ovsdb_syntax_error(table_updates, NULL, @@ -2155,7 +2261,8 @@ ovsdb_idl_db_parse_update__(struct ovsdb_idl_db *db, version_suffix, table_node->name); } - if (is_monitor_cond) { + if (method == OVSDB_IDL_MM_MONITOR_COND || + method == OVSDB_IDL_MM_MONITOR_COND_SINCE) { const char *ops[] = {"modify", "insert", "delete", "initial"}; const char *operation; const struct json *row; @@ -2216,10 +2323,10 @@ ovsdb_idl_db_parse_update__(struct ovsdb_idl_db *db, static void ovsdb_idl_db_parse_update(struct ovsdb_idl_db *db, const struct json *table_updates, - bool is_monitor_cond) + enum ovsdb_idl_monitor_method method) { struct ovsdb_error *error = ovsdb_idl_db_parse_update__(db, table_updates, - is_monitor_cond); + method); if (error) { log_parse_update_error(error); }