X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=ovsdb%2Fjsonrpc-server.c;h=caaf2bf497ad57574adda4ca7f9b7699bcac6fc4;hb=f76def2592cc5cb449a3360430ee9cc0f208765d;hp=05aaf871814714b93d666fda0f4bdeffc91ace1a;hpb=f1de87bb2f568ad126e77e85746ce63376ff0bd5;p=cascardo%2Fovs.git diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c index 05aaf8718..caaf2bf49 100644 --- a/ovsdb/jsonrpc-server.c +++ b/ovsdb/jsonrpc-server.c @@ -22,6 +22,7 @@ #include "bitmap.h" #include "column.h" #include "dynamic-string.h" +#include "monitor.h" #include "json.h" #include "jsonrpc.h" #include "ovsdb-error.h" @@ -37,7 +38,6 @@ #include "timeval.h" #include "transaction.h" #include "trigger.h" -#include "monitor.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovsdb_jsonrpc_server); @@ -45,6 +45,10 @@ 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; + /* Message rate-limiting. */ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); @@ -59,9 +63,12 @@ static void ovsdb_jsonrpc_session_close_all(struct ovsdb_jsonrpc_remote *); static void ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *); static void ovsdb_jsonrpc_session_set_all_options( struct ovsdb_jsonrpc_remote *, const struct ovsdb_jsonrpc_options *); -static bool ovsdb_jsonrpc_session_get_status( +static bool ovsdb_jsonrpc_active_session_get_status( const struct ovsdb_jsonrpc_remote *, struct ovsdb_jsonrpc_remote_status *); +static void ovsdb_jsonrpc_session_get_status( + const struct ovsdb_jsonrpc_session *, + struct ovsdb_jsonrpc_remote_status *); static void ovsdb_jsonrpc_session_unlock_all(struct ovsdb_jsonrpc_session *); static void ovsdb_jsonrpc_session_unlock__(struct ovsdb_lock_waiter *); static void ovsdb_jsonrpc_session_send(struct ovsdb_jsonrpc_session *, @@ -81,7 +88,7 @@ static void ovsdb_jsonrpc_trigger_complete_done( /* Monitors. */ static struct jsonrpc_msg *ovsdb_jsonrpc_monitor_create( struct ovsdb_jsonrpc_session *, struct ovsdb *, struct json *params, - const struct json *request_id); + enum ovsdb_monitor_version, const struct json *request_id); static struct jsonrpc_msg *ovsdb_jsonrpc_monitor_cancel( struct ovsdb_jsonrpc_session *, struct json_array *params, @@ -97,7 +104,7 @@ static struct json *ovsdb_jsonrpc_monitor_compose_update( struct ovsdb_jsonrpc_server { struct ovsdb_server up; - unsigned int n_sessions, max_sessions; + unsigned int n_sessions; struct shash remotes; /* Contains "struct ovsdb_jsonrpc_remote *"s. */ }; @@ -126,7 +133,6 @@ ovsdb_jsonrpc_server_create(void) { struct ovsdb_jsonrpc_server *server = xzalloc(sizeof *server); ovsdb_server_init(&server->up); - server->max_sessions = 330; /* Random limit. */ shash_init(&server->remotes); return server; } @@ -272,7 +278,7 @@ ovsdb_jsonrpc_server_del_remote(struct shash_node *node) /* Stores status information for the remote named 'target', which should have * been configured on 'svr' with a call to ovsdb_jsonrpc_server_set_remotes(), * into '*status'. On success returns true, on failure (if 'svr' doesn't have - * a remote named 'target' or if that remote is an inbound remote that has no + * a remote named 'target' or if that remote is an outbound remote that has no * active connections) returns false. On failure, 'status' will be zeroed. */ bool @@ -285,7 +291,19 @@ ovsdb_jsonrpc_server_get_remote_status( memset(status, 0, sizeof *status); remote = shash_find_data(&svr->remotes, target); - return remote && ovsdb_jsonrpc_session_get_status(remote, status); + + if (!remote) { + return false; + } + + if (remote->listener) { + status->bound_port = pstream_get_bound_port(remote->listener); + status->is_connected = !list_is_empty(&remote->sessions); + status->n_connections = list_size(&remote->sessions); + return true; + } + + return ovsdb_jsonrpc_active_session_get_status(remote, status); } void @@ -320,25 +338,19 @@ ovsdb_jsonrpc_server_run(struct ovsdb_jsonrpc_server *svr) struct ovsdb_jsonrpc_remote *remote = node->data; if (remote->listener) { - if (svr->n_sessions < svr->max_sessions) { - struct stream *stream; - int error; - - error = pstream_accept(remote->listener, &stream); - if (!error) { - struct jsonrpc_session *js; - js = jsonrpc_session_open_unreliably(jsonrpc_open(stream), - remote->dscp); - ovsdb_jsonrpc_session_create(remote, js); - } else if (error != EAGAIN) { - VLOG_WARN_RL(&rl, "%s: accept failed: %s", - pstream_get_name(remote->listener), - ovs_strerror(error)); - } - } else { - VLOG_WARN_RL(&rl, "%s: connection exceeded maximum (%d)", + struct stream *stream; + int error; + + error = pstream_accept(remote->listener, &stream); + if (!error) { + struct jsonrpc_session *js; + js = jsonrpc_session_open_unreliably(jsonrpc_open(stream), + remote->dscp); + ovsdb_jsonrpc_session_create(remote, js); + } else if (error != EAGAIN) { + VLOG_WARN_RL(&rl, "%s: accept failed: %s", pstream_get_name(remote->listener), - svr->max_sessions); + ovs_strerror(error)); } } @@ -354,7 +366,7 @@ ovsdb_jsonrpc_server_wait(struct ovsdb_jsonrpc_server *svr) SHASH_FOR_EACH (node, &svr->remotes) { struct ovsdb_jsonrpc_remote *remote = node->data; - if (remote->listener && svr->n_sessions < svr->max_sessions) { + if (remote->listener) { pstream_wait(remote->listener); } @@ -529,7 +541,6 @@ ovsdb_jsonrpc_session_get_memory_usage(const struct ovsdb_jsonrpc_session *s, struct simap *usage) { simap_increase(usage, "triggers", hmap_count(&s->triggers)); - simap_increase(usage, "monitors", hmap_count(&s->monitors)); simap_increase(usage, "backlog", jsonrpc_session_get_backlog(s->js)); } @@ -587,24 +598,37 @@ ovsdb_jsonrpc_session_set_all_options( } } +/* Sets the 'status' of for the 'remote' with an outgoing connection. */ static bool -ovsdb_jsonrpc_session_get_status(const struct ovsdb_jsonrpc_remote *remote, - struct ovsdb_jsonrpc_remote_status *status) +ovsdb_jsonrpc_active_session_get_status( + const struct ovsdb_jsonrpc_remote *remote, + struct ovsdb_jsonrpc_remote_status *status) { + const struct ovs_list *sessions = &remote->sessions; const struct ovsdb_jsonrpc_session *s; + + if (list_is_empty(sessions)) { + return false; + } + + ovs_assert(list_is_singleton(sessions)); + s = CONTAINER_OF(list_front(sessions), struct ovsdb_jsonrpc_session, node); + ovsdb_jsonrpc_session_get_status(s, status); + status->n_connections = 1; + + return true; +} + +static void +ovsdb_jsonrpc_session_get_status(const struct ovsdb_jsonrpc_session *session, + struct ovsdb_jsonrpc_remote_status *status) +{ + const struct ovsdb_jsonrpc_session *s = session; const struct jsonrpc_session *js; struct ovsdb_lock_waiter *waiter; struct reconnect_stats rstats; struct ds locks_held, locks_waiting, locks_lost; - status->bound_port = (remote->listener - ? pstream_get_bound_port(remote->listener) - : htons(0)); - - if (list_is_empty(&remote->sessions)) { - return false; - } - s = CONTAINER_OF(remote->sessions.next, struct ovsdb_jsonrpc_session, node); js = s->js; status->is_connected = jsonrpc_session_is_connected(js); @@ -634,10 +658,6 @@ ovsdb_jsonrpc_session_get_status(const struct ovsdb_jsonrpc_remote *remote, status->locks_held = ds_steal_cstr(&locks_held); status->locks_waiting = ds_steal_cstr(&locks_waiting); status->locks_lost = ds_steal_cstr(&locks_lost); - - status->n_connections = list_size(&remote->sessions); - - return true; } /* Examines 'request' to determine the database to which it relates, and then @@ -844,11 +864,15 @@ ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s, if (!reply) { reply = execute_transaction(s, db, request); } - } else if (!strcmp(request->method, "monitor")) { + } else if (!strcmp(request->method, "monitor") || + (monitor2_enable__ && !strcmp(request->method, "monitor2"))) { struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply); if (!reply) { + int l = strlen(request->method) - strlen("monitor"); + enum ovsdb_monitor_version version = l ? OVSDB_MONITOR_V2 + : OVSDB_MONITOR_V1; reply = ovsdb_jsonrpc_monitor_create(s, db, request->params, - request->id); + version, request->id); } } else if (!strcmp(request->method, "monitor_cancel")) { reply = ovsdb_jsonrpc_monitor_cancel(s, json_array(request->params), @@ -1039,6 +1063,7 @@ struct ovsdb_jsonrpc_monitor { struct ovsdb_monitor *dbmon; uint64_t unflushed; /* The first transaction that has not been flushed to the jsonrpc remote client. */ + enum ovsdb_monitor_version version; }; static struct ovsdb_jsonrpc_monitor * @@ -1154,9 +1179,11 @@ ovsdb_jsonrpc_parse_monitor_request(struct ovsdb_monitor *dbmon, static struct jsonrpc_msg * ovsdb_jsonrpc_monitor_create(struct ovsdb_jsonrpc_session *s, struct ovsdb *db, struct json *params, + enum ovsdb_monitor_version version, const struct json *request_id) { struct ovsdb_jsonrpc_monitor *m = NULL; + struct ovsdb_monitor *dbmon = NULL; struct json *monitor_id, *monitor_requests; struct ovsdb_error *error = NULL; struct shash_node *node; @@ -1184,6 +1211,7 @@ ovsdb_jsonrpc_monitor_create(struct ovsdb_jsonrpc_session *s, struct ovsdb *db, m->db = db; m->dbmon = ovsdb_monitor_create(db, m); m->unflushed = 0; + m->version = version; hmap_insert(&s->monitors, &m->node, json_hash(monitor_id, 0)); m->monitor_id = json_clone(monitor_id); @@ -1234,6 +1262,14 @@ ovsdb_jsonrpc_monitor_create(struct ovsdb_jsonrpc_session *s, struct ovsdb *db, } } + dbmon = ovsdb_monitor_add(m->dbmon); + if (dbmon != m->dbmon) { + /* Found an exisiting dbmon, reuse the current one. */ + ovsdb_monitor_remove_jsonrpc_monitor(m->dbmon, m, m->unflushed); + ovsdb_monitor_add_jsonrpc_monitor(dbmon, m); + m->dbmon = dbmon; + } + ovsdb_monitor_get_initial(m->dbmon); json = ovsdb_jsonrpc_monitor_compose_update(m, true); json = json ? json : json_object_create(); @@ -1282,11 +1318,15 @@ ovsdb_jsonrpc_monitor_remove_all(struct ovsdb_jsonrpc_session *s) } static struct json * -ovsdb_jsonrpc_monitor_compose_update( - struct ovsdb_jsonrpc_monitor *monitor, bool initial) +ovsdb_jsonrpc_monitor_compose_update(struct ovsdb_jsonrpc_monitor *m, + bool initial) { - return ovsdb_monitor_compose_update(monitor->dbmon, initial, - &monitor->unflushed); + if (!ovsdb_monitor_needs_flush(m->dbmon, m->unflushed)) { + return NULL; + } + + return ovsdb_monitor_get_update(m->dbmon, initial, &m->unflushed, + m->version); } static bool @@ -1308,10 +1348,31 @@ ovsdb_jsonrpc_monitor_destroy(struct ovsdb_jsonrpc_monitor *m) { json_destroy(m->monitor_id); hmap_remove(&m->session->monitors, &m->node); - ovsdb_monitor_remove_jsonrpc_monitor(m->dbmon, m); + ovsdb_monitor_remove_jsonrpc_monitor(m->dbmon, m, m->unflushed); free(m); } +static struct jsonrpc_msg * +ovsdb_jsonrpc_create_notify(const struct ovsdb_jsonrpc_monitor *m, + struct json *params) +{ + const char *method; + + switch(m->version) { + case OVSDB_MONITOR_V1: + method = "update"; + break; + case OVSDB_MONITOR_V2: + method = "update2"; + break; + case OVSDB_MONITOR_VERSION_MAX: + default: + OVS_NOT_REACHED(); + } + + return jsonrpc_create_notify(method, params); +} + static void ovsdb_jsonrpc_monitor_flush_all(struct ovsdb_jsonrpc_session *s) { @@ -1326,8 +1387,15 @@ ovsdb_jsonrpc_monitor_flush_all(struct ovsdb_jsonrpc_session *s) struct json *params; params = json_array_create_2(json_clone(m->monitor_id), json); - msg = jsonrpc_create_notify("update", params); + msg = ovsdb_jsonrpc_create_notify(m, params); jsonrpc_session_send(s->js, msg); } } } + +void +ovsdb_jsonrpc_disable_monitor2(void) +{ + /* Once disabled, it is not possible to re-enable it. */ + monitor2_enable__ = false; +}