Signed-off-by: Ben Pfaff <[email protected]>
---
lib/automake.mk | 2 +
lib/memory.c | 175 ++++++++++++++++++++
lib/memory.h | 60 +++++++
lib/rconn.c | 7 +
lib/rconn.h | 3 +-
ofproto/connmgr.c | 25 +++
ofproto/connmgr.h | 3 +
ofproto/ofproto-dpif.c | 11 ++
ofproto/ofproto-provider.h | 8 +
ofproto/ofproto.c | 26 +++
ofproto/ofproto.h | 3 +
ofproto/pinsched.c | 10 +-
ofproto/pinsched.h | 4 +-
ofproto/pktbuf.c | 22 +++-
ofproto/pktbuf.h | 4 +-
ovsdb/jsonrpc-server.c | 42 +++++
ovsdb/jsonrpc-server.h | 6 +-
ovsdb/ovsdb-server.c | 16 ++-
ovsdb/ovsdb.c | 22 +++-
ovsdb/ovsdb.h | 5 +-
utilities/bugtool/automake.mk | 1 +
utilities/bugtool/ovs-bugtool-memory-show | 19 ++
.../bugtool/plugins/network-status/openvswitch.xml | 1 +
vswitchd/bridge.c | 12 ++
vswitchd/bridge.h | 6 +-
vswitchd/ovs-vswitchd.c | 12 ++
26 files changed, 495 insertions(+), 10 deletions(-)
create mode 100644 lib/memory.c
create mode 100644 lib/memory.h
create mode 100755 utilities/bugtool/ovs-bugtool-memory-show
diff --git a/lib/automake.mk b/lib/automake.mk
index 920babd..29ac53c 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -79,6 +79,8 @@ lib_libopenvswitch_a_SOURCES = \
lib/lockfile.h \
lib/mac-learning.c \
lib/mac-learning.h \
+ lib/memory.c \
+ lib/memory.h \
lib/meta-flow.c \
lib/meta-flow.h \
lib/multipath.c \
diff --git a/lib/memory.c b/lib/memory.c
new file mode 100644
index 0000000..779860e
--- /dev/null
+++ b/lib/memory.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2012 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+#include "memory.h"
+#include <stdbool.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include "dynamic-string.h"
+#include "poll-loop.h"
+#include "simap.h"
+#include "timeval.h"
+#include "unixctl.h"
+#include "vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(memory);
+
+/* The number of milliseconds before the first report of daemon memory usage,
+ * and the number of milliseconds between checks for daemon memory growth. */
+#define MEMORY_CHECK_INTERVAL (10 * 1000)
+
+/* When we should next check memory usage and possibly trigger a report. */
+static long long int next_check;
+
+/* The last time at which we reported memory usage, and the usage we reported
+ * at that time. */
+static long long int last_report;
+static unsigned long int last_reported_maxrss;
+
+/* Are we expecting a call to memory_report()? */
+static bool want_report;
+
+/* Unixctl connections waiting for responses. */
+static struct unixctl_conn **conns;
+static size_t n_conns;
+
+static void memory_init(void);
+
+/* Runs the memory monitor.
+ *
+ * The client should call memory_should_report() afterward. */
+void
+memory_run(void)
+{
+ struct rusage usage;
+ long long int now;
+
+ memory_init();
+
+ /* Time for a check? */
+ now = time_msec();
+ if (now < next_check) {
+ return;
+ }
+ next_check = now + MEMORY_CHECK_INTERVAL;
+
+ /* Time for a report? */
+ getrusage(RUSAGE_SELF, &usage);
+ if (!last_reported_maxrss) {
+ VLOG_INFO("%lu kB peak resident set size after %.1f seconds",
+ (unsigned long int) usage.ru_maxrss,
+ (now - time_boot_msec()) / 1000.0);
+ } else if (usage.ru_maxrss >= last_reported_maxrss * 1.5) {
+ VLOG_INFO("peak resident set size grew %.0f%% in last %.1f seconds, "
+ "from %lu kB to %lu kB",
+ ((double) usage.ru_maxrss / last_reported_maxrss - 1) * 100,
+ (now - last_report) / 1000.0,
+ last_reported_maxrss, (unsigned long int) usage.ru_maxrss);
+ } else {
+ return;
+ }
+
+ /* Request a report. */
+ want_report = true;
+ last_report = now;
+ last_reported_maxrss = usage.ru_maxrss;
+}
+
+/* Causes the poll loop to wake up if the memory monitor needs to run. */
+void
+memory_wait(void)
+{
+ if (memory_should_report()) {
+ poll_immediate_wake();
+ }
+}
+
+/* Returns true if the caller should log some information about memory usage
+ * (with memory_report()), false otherwise. */
+bool
+memory_should_report(void)
+{
+ return want_report || n_conns > 0;
+}
+
+static void
+compose_report(const struct simap *usage, struct ds *s)
+{
+ const struct simap_node **nodes = simap_sort(usage);
+ size_t n = simap_count(usage);
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ const struct simap_node *node = nodes[i];
+
+ ds_put_format(s, "%s:%u ", node->name, node->data);
+ }
+ ds_chomp(s, ' ');
+}
+
+/* Logs the contents of 'usage', as a collection of name-count pairs.
+ *
+ * 'usage' should capture large-scale statistics that one might reasonably
+ * expect to correlate with memory usage. For example, each OpenFlow flow
+ * requires some memory, so ovs-vswitchd includes the total number of flows in
+ * 'usage'. */
+void
+memory_report(const struct simap *usage)
+{
+ struct ds s;
+ size_t i;
+
+ ds_init(&s);
+ compose_report(usage, &s);
+
+ if (want_report) {
+ VLOG_INFO("%s", ds_cstr(&s));
+ want_report = false;
+ }
+ if (n_conns) {
+ for (i = 0; i < n_conns; i++) {
+ unixctl_command_reply(conns[i], ds_cstr(&s));
+ }
+ free(conns);
+ conns = NULL;
+ n_conns = 0;
+ }
+
+ ds_destroy(&s);
+}
+
+static void
+memory_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
+{
+ conns = xrealloc(conns, (n_conns + 1) * sizeof *conns);
+ conns[n_conns++] = conn;
+}
+
+static void
+memory_init(void)
+{
+ static bool inited = false;
+
+ if (!inited) {
+ inited = true;
+ unixctl_command_register("memory/show", "", 0, 0,
+ memory_unixctl_show, NULL);
+
+ next_check = time_boot_msec() + MEMORY_CHECK_INTERVAL;
+ }
+}
diff --git a/lib/memory.h b/lib/memory.h
new file mode 100644
index 0000000..4edd956
--- /dev/null
+++ b/lib/memory.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEMORY_H
+#define MEMORY_H 1
+
+/* Memory usage monitor.
+ *
+ * This is intended to be called as part of a daemon's main loop. After some
+ * time to allow the daemon to allocate an initial memory usage, it logs some
+ * memory usage information (most of which must actually be provided by the
+ * client). At intervals, if the daemon's memory usage has grown
+ * significantly, it again logs information.
+ *
+ * The monitor also has a unixctl interface.
+ *
+ * Intended usage in the program's main loop is like this:
+ *
+ * for (;;) {
+ * memory_run();
+ * if (memory_should_report()) {
+ * struct simap usage;
+ *
+ * simap_init(&usage);
+ * ...fill in 'usage' with meaningful statistics...
+ * memory_report(&usage);
+ * simap_destroy(&usage);
+ * }
+ *
+ * ...
+ *
+ * memory_wait();
+ * poll_block();
+ * }
+ */
+
+#include <stdbool.h>
+
+struct simap;
+
+void memory_run(void);
+void memory_wait(void);
+
+bool memory_should_report(void);
+void memory_report(const struct simap *usage);
+
+#endif /* memory.h */
diff --git a/lib/rconn.c b/lib/rconn.c
index aa8b7e3..2ddfc69 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -855,6 +855,13 @@ rconn_get_last_error(const struct rconn *rc)
{
return rc->last_error;
}
+
+/* Returns the number of messages queued for transmission on 'rc'. */
+unsigned int
+rconn_count_txqlen(const struct rconn *rc)
+{
+ return list_size(&rc->txq);
+}
struct rconn_packet_counter *
rconn_packet_counter_create(void)
diff --git a/lib/rconn.h b/lib/rconn.h
index 2397640..2b1332c 100644
--- a/lib/rconn.h
+++ b/lib/rconn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,6 +91,7 @@ int rconn_get_backoff(const struct rconn *);
unsigned int rconn_get_state_elapsed(const struct rconn *);
unsigned int rconn_get_connection_seqno(const struct rconn *);
int rconn_get_last_error(const struct rconn *);
+unsigned int rconn_count_txqlen(const struct rconn *);
/* Counts the number of packets queued into an rconn by a given source. */
struct rconn_packet_counter {
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index e80d20c..a0315b2 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -33,6 +33,7 @@
#include "pktbuf.h"
#include "rconn.h"
#include "shash.h"
+#include "simap.h"
#include "stream.h"
#include "timeval.h"
#include "vconn.h"
@@ -338,6 +339,30 @@ connmgr_wait(struct connmgr *mgr, bool handling_openflow)
}
}
+/* Adds some memory usage statistics for 'mgr' into 'usage', for use with
+ * memory_report(). */
+void
+connmgr_get_memory_usage(const struct connmgr *mgr, struct simap *usage)
+{
+ const struct ofconn *ofconn;
+ unsigned int packets = 0;
+ unsigned int ofconns = 0;
+
+ LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
+ int i;
+
+ ofconns++;
+
+ packets += rconn_count_txqlen(ofconn->rconn);
+ for (i = 0; i < N_SCHEDULERS; i++) {
+ packets += pinsched_count_txqlen(ofconn->schedulers[i]);
+ }
+ packets += pktbuf_count_packets(ofconn->pktbuf);
+ }
+ simap_increase(usage, "ofconns", ofconns);
+ simap_increase(usage, "packets", packets);
+}
+
/* Returns the ofproto that owns 'ofconn''s connmgr. */
struct ofproto *
ofconn_get_ofproto(const struct ofconn *ofconn)
diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h
index 8ac0b8d..dec5b71 100644
--- a/ofproto/connmgr.h
+++ b/ofproto/connmgr.h
@@ -30,6 +30,7 @@ struct ofopgroup;
struct ofputil_flow_removed;
struct ofputil_packet_in;
struct ofputil_phy_port;
+struct simap;
struct sset;
/* ofproto supports two kinds of OpenFlow connections:
@@ -70,6 +71,8 @@ void connmgr_run(struct connmgr *,
struct ofpbuf *ofp_msg));
void connmgr_wait(struct connmgr *, bool handling_openflow);
+void connmgr_get_memory_usage(const struct connmgr *, struct simap *usage);
+
struct ofproto *ofconn_get_ofproto(const struct ofconn *);
void connmgr_retry(struct connmgr *);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 11bde38..988de61 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -47,6 +47,7 @@
#include "ofproto-dpif-governor.h"
#include "ofproto-dpif-sflow.h"
#include "poll-loop.h"
+#include "simap.h"
#include "timer.h"
#include "unaligned.h"
#include "unixctl.h"
@@ -954,6 +955,15 @@ wait(struct ofproto *ofproto_)
}
static void
+get_memory_usage(const struct ofproto *ofproto_, struct simap *usage)
+{
+ const struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+
+ simap_increase(usage, "facets", hmap_count(&ofproto->facets));
+ simap_increase(usage, "subfacets", hmap_count(&ofproto->subfacets));
+}
+
+static void
flush(struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
@@ -6808,6 +6818,7 @@ const struct ofproto_class ofproto_dpif_class = {
run,
run_fast,
wait,
+ get_memory_usage,
flush,
get_features,
get_tables,
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index a74bf9a..1f3ad37 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -30,6 +30,7 @@
#include "timeval.h"
struct ofputil_flow_mod;
+struct simap;
/* An OpenFlow switch.
*
@@ -396,6 +397,13 @@ struct ofproto_class {
* poll-loop.h. */
void (*wait)(struct ofproto *ofproto);
+ /* Adds some memory usage statistics for the implementation of 'ofproto'
+ * into 'usage', for use with memory_report().
+ *
+ * This function is optional. */
+ void (*get_memory_usage)(const struct ofproto *ofproto,
+ struct simap *usage);
+
/* Every "struct rule" in 'ofproto' is about to be deleted, one by one.
* This function may prepare for that, for example by clearing state in
* advance. It should *not* actually delete any "struct rule"s from
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 806e56b..23904a8 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -45,6 +45,7 @@
#include "poll-loop.h"
#include "random.h"
#include "shash.h"
+#include "simap.h"
#include "sset.h"
#include "timeval.h"
#include "unaligned.h"
@@ -1149,6 +1150,31 @@ ofproto_is_alive(const struct ofproto *p)
return connmgr_has_controllers(p->connmgr);
}
+/* Adds some memory usage statistics for 'ofproto' into 'usage', for use with
+ * memory_report(). */
+void
+ofproto_get_memory_usage(const struct ofproto *ofproto, struct simap *usage)
+{
+ const struct oftable *table;
+ unsigned int n_rules;
+
+ simap_increase(usage, "ports", hmap_count(&ofproto->ports));
+ simap_increase(usage, "ops",
+ ofproto->n_pending + hmap_count(&ofproto->deletions));
+
+ n_rules = 0;
+ OFPROTO_FOR_EACH_TABLE (table, ofproto) {
+ n_rules += classifier_count(&table->cls);
+ }
+ simap_increase(usage, "rules", n_rules);
+
+ if (ofproto->ofproto_class->get_memory_usage) {
+ ofproto->ofproto_class->get_memory_usage(ofproto, usage);
+ }
+
+ connmgr_get_memory_usage(ofproto->connmgr, usage);
+}
+
void
ofproto_get_ofproto_controller_info(const struct ofproto *ofproto,
struct shash *info)
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index c8d9857..ea988e7 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -39,6 +39,7 @@ struct netdev;
struct ofproto;
struct ofport;
struct shash;
+struct simap;
struct netdev_stats;
struct ofproto_controller_info {
@@ -153,6 +154,8 @@ int ofproto_run_fast(struct ofproto *);
void ofproto_wait(struct ofproto *);
bool ofproto_is_alive(const struct ofproto *);
+void ofproto_get_memory_usage(const struct ofproto *, struct simap *);
+
/* A port within an OpenFlow switch.
*
* 'name' and 'type' are suitable for passing to netdev_open(). */
diff --git a/ofproto/pinsched.c b/ofproto/pinsched.c
index 9053ea2..41e9c8d 100644
--- a/ofproto/pinsched.c
+++ b/ofproto/pinsched.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -320,3 +320,11 @@ pinsched_set_limits(struct pinsched *ps, int rate_limit,
int burst_limit)
drop_packet(ps);
}
}
+
+/* Returns the number of packets scheduled to be sent eventually by 'ps'.
+ * Returns 0 if 'ps' is null. */
+unsigned int
+pinsched_count_txqlen(const struct pinsched *ps)
+{
+ return ps ? ps->n_txq : 0;
+}
diff --git a/ofproto/pinsched.h b/ofproto/pinsched.h
index 26a4d7a..061cb01 100644
--- a/ofproto/pinsched.h
+++ b/ofproto/pinsched.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,4 +32,6 @@ void pinsched_send(struct pinsched *, uint16_t port_no,
struct ofpbuf *,
void pinsched_run(struct pinsched *, pinsched_tx_cb *, void *aux);
void pinsched_wait(struct pinsched *);
+unsigned int pinsched_count_txqlen(const struct pinsched *);
+
#endif /* pinsched.h */
diff --git a/ofproto/pktbuf.c b/ofproto/pktbuf.c
index acc0d34..71be34a 100644
--- a/ofproto/pktbuf.c
+++ b/ofproto/pktbuf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -232,3 +232,23 @@ pktbuf_discard(struct pktbuf *pb, uint32_t id)
p->buffer = NULL;
}
}
+
+/* Returns the number of packets buffered in 'pb'. Returns 0 if 'pb' is
+ * null. */
+unsigned int
+pktbuf_count_packets(const struct pktbuf *pb)
+{
+ int n = 0;
+
+ if (pb) {
+ int i;
+
+ for (i = 0; i < PKTBUF_CNT; i++) {
+ if (pb->packets[i].buffer) {
+ n++;
+ }
+ }
+ }
+
+ return n;
+}
diff --git a/ofproto/pktbuf.h b/ofproto/pktbuf.h
index 990f2ea..ec99aea 100644
--- a/ofproto/pktbuf.h
+++ b/ofproto/pktbuf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2011 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,4 +36,6 @@ enum ofperr pktbuf_retrieve(struct pktbuf *, uint32_t id,
struct ofpbuf **bufferp, uint16_t *in_port);
void pktbuf_discard(struct pktbuf *, uint32_t id);
+unsigned int pktbuf_count_packets(const struct pktbuf *);
+
#endif /* pktbuf.h */
diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index 0cc8bdf..bb887d0 100644
--- a/ovsdb/jsonrpc-server.c
+++ b/ovsdb/jsonrpc-server.c
@@ -31,6 +31,7 @@
#include "reconnect.h"
#include "row.h"
#include "server.h"
+#include "simap.h"
#include "stream.h"
#include "table.h"
#include "timeval.h"
@@ -51,6 +52,8 @@ static struct ovsdb_jsonrpc_session
*ovsdb_jsonrpc_session_create(
struct ovsdb_jsonrpc_remote *, struct jsonrpc_session *);
static void ovsdb_jsonrpc_session_run_all(struct ovsdb_jsonrpc_remote *);
static void ovsdb_jsonrpc_session_wait_all(struct ovsdb_jsonrpc_remote *);
+static void ovsdb_jsonrpc_session_get_memory_usage_all(
+ const struct ovsdb_jsonrpc_remote *, struct simap *usage);
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(
@@ -293,6 +296,22 @@ ovsdb_jsonrpc_server_wait(struct ovsdb_jsonrpc_server *svr)
ovsdb_jsonrpc_session_wait_all(remote);
}
}
+
+/* Adds some memory usage statistics for 'svr' into 'usage', for use with
+ * memory_report(). */
+void
+ovsdb_jsonrpc_server_get_memory_usage(const struct ovsdb_jsonrpc_server *svr,
+ struct simap *usage)
+{
+ struct shash_node *node;
+
+ simap_increase(usage, "sessions", svr->n_sessions);
+ SHASH_FOR_EACH (node, &svr->remotes) {
+ struct ovsdb_jsonrpc_remote *remote = node->data;
+
+ ovsdb_jsonrpc_session_get_memory_usage_all(remote, usage);
+ }
+}
/* JSON-RPC database server session. */
@@ -315,6 +334,8 @@ struct ovsdb_jsonrpc_session {
static void ovsdb_jsonrpc_session_close(struct ovsdb_jsonrpc_session *);
static int ovsdb_jsonrpc_session_run(struct ovsdb_jsonrpc_session *);
static void ovsdb_jsonrpc_session_wait(struct ovsdb_jsonrpc_session *);
+static void ovsdb_jsonrpc_session_get_memory_usage(
+ const struct ovsdb_jsonrpc_session *, struct simap *usage);
static void ovsdb_jsonrpc_session_set_options(
struct ovsdb_jsonrpc_session *, const struct ovsdb_jsonrpc_options *);
static void ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *,
@@ -429,6 +450,27 @@ ovsdb_jsonrpc_session_wait_all(struct ovsdb_jsonrpc_remote
*remote)
}
static void
+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));
+}
+
+static void
+ovsdb_jsonrpc_session_get_memory_usage_all(
+ const struct ovsdb_jsonrpc_remote *remote,
+ struct simap *usage)
+{
+ struct ovsdb_jsonrpc_session *s;
+
+ LIST_FOR_EACH (s, node, &remote->sessions) {
+ ovsdb_jsonrpc_session_get_memory_usage(s, usage);
+ }
+}
+
+static void
ovsdb_jsonrpc_session_close_all(struct ovsdb_jsonrpc_remote *remote)
{
struct ovsdb_jsonrpc_session *s, *next;
diff --git a/ovsdb/jsonrpc-server.h b/ovsdb/jsonrpc-server.h
index 8312a00..2dc0c78 100644
--- a/ovsdb/jsonrpc-server.h
+++ b/ovsdb/jsonrpc-server.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
struct ovsdb;
struct shash;
+struct simap;
struct ovsdb_jsonrpc_server *ovsdb_jsonrpc_server_create(struct ovsdb *);
void ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *);
@@ -59,4 +60,7 @@ void ovsdb_jsonrpc_server_reconnect(struct
ovsdb_jsonrpc_server *);
void ovsdb_jsonrpc_server_run(struct ovsdb_jsonrpc_server *);
void ovsdb_jsonrpc_server_wait(struct ovsdb_jsonrpc_server *);
+void ovsdb_jsonrpc_server_get_memory_usage(const struct ovsdb_jsonrpc_server *,
+ struct simap *usage);
+
#endif /* ovsdb/jsonrpc-server.h */
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index 28bf901..7f53e17 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
#include "jsonrpc-server.h"
#include "leak-checker.h"
#include "list.h"
+#include "memory.h"
#include "ovsdb.h"
#include "ovsdb-data.h"
#include "ovsdb-types.h"
@@ -39,6 +40,7 @@
#include "poll-loop.h"
#include "process.h"
#include "row.h"
+#include "simap.h"
#include "stream-ssl.h"
#include "stream.h"
#include "stress.h"
@@ -143,6 +145,17 @@ main(int argc, char *argv[])
exiting = false;
while (!exiting) {
+ memory_run();
+ if (memory_should_report()) {
+ struct simap usage;
+
+ simap_init(&usage);
+ ovsdb_jsonrpc_server_get_memory_usage(jsonrpc, &usage);
+ ovsdb_get_memory_usage(db, &usage);
+ memory_report(&usage);
+ simap_destroy(&usage);
+ }
+
reconfigure_from_db(jsonrpc, db, &remotes);
ovsdb_jsonrpc_server_run(jsonrpc);
unixctl_server_run(unixctl);
@@ -157,6 +170,7 @@ main(int argc, char *argv[])
update_remote_status(jsonrpc, &remotes, db);
}
+ memory_wait();
ovsdb_jsonrpc_server_wait(jsonrpc);
unixctl_server_wait(unixctl);
ovsdb_trigger_wait(db, time_msec());
diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c
index 584433c..6b53f4a 100644
--- a/ovsdb/ovsdb.c
+++ b/ovsdb/ovsdb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
#include "ovsdb-error.h"
#include "ovsdb-parser.h"
#include "ovsdb-types.h"
+#include "simap.h"
#include "table.h"
#include "transaction.h"
@@ -384,6 +385,25 @@ ovsdb_destroy(struct ovsdb *db)
}
}
+/* Adds some memory usage statistics for 'db' into 'usage', for use with
+ * memory_report(). */
+void
+ovsdb_get_memory_usage(const struct ovsdb *db, struct simap *usage)
+{
+ const struct shash_node *node;
+ unsigned int cells = 0;
+
+ SHASH_FOR_EACH (node, &db->tables) {
+ const struct ovsdb_table *table = node->data;
+ unsigned int n_columns = shash_count(&table->schema->columns);
+ unsigned int n_rows = hmap_count(&table->rows);
+
+ cells += n_rows * n_columns;
+ }
+
+ simap_increase(usage, "cells", cells);
+}
+
struct ovsdb_table *
ovsdb_get_table(const struct ovsdb *db, const char *name)
{
diff --git a/ovsdb/ovsdb.h b/ovsdb/ovsdb.h
index ea7a9c2..6e4ff79 100644
--- a/ovsdb/ovsdb.h
+++ b/ovsdb/ovsdb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ struct json;
struct ovsdb_log;
struct ovsdb_session;
struct ovsdb_txn;
+struct simap;
struct uuid;
/* Database schema. */
@@ -66,6 +67,8 @@ struct ovsdb {
struct ovsdb *ovsdb_create(struct ovsdb_schema *);
void ovsdb_destroy(struct ovsdb *);
+void ovsdb_get_memory_usage(const struct ovsdb *, struct simap *usage);
+
struct ovsdb_error *ovsdb_from_json(const struct json *, struct ovsdb **)
WARN_UNUSED_RESULT;
struct json *ovsdb_to_json(const struct ovsdb *);
diff --git a/utilities/bugtool/automake.mk b/utilities/bugtool/automake.mk
index 676a5a2..1045cee 100644
--- a/utilities/bugtool/automake.mk
+++ b/utilities/bugtool/automake.mk
@@ -15,6 +15,7 @@ bugtool_scripts = \
utilities/bugtool/ovs-bugtool-cfm-show \
utilities/bugtool/ovs-bugtool-coverage-show \
utilities/bugtool/ovs-bugtool-lacp-show \
+ utilities/bugtool/ovs-bugtool-memory-show \
utilities/bugtool/ovs-bugtool-tc-class-show \
utilities/bugtool/ovs-bugtool-vsctl-show \
utilities/bugtool/ovs-bugtool-ovsdb-dump \
diff --git a/utilities/bugtool/ovs-bugtool-memory-show
b/utilities/bugtool/ovs-bugtool-memory-show
new file mode 100755
index 0000000..3bad754
--- /dev/null
+++ b/utilities/bugtool/ovs-bugtool-memory-show
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General
+# Public License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+#
+# Copyright (C) 2012 Nicira, Inc.
+
+ovs-appctl memory/show
diff --git a/utilities/bugtool/plugins/network-status/openvswitch.xml
b/utilities/bugtool/plugins/network-status/openvswitch.xml
index 8ae498f..a8a906e 100644
--- a/utilities/bugtool/plugins/network-status/openvswitch.xml
+++ b/utilities/bugtool/plugins/network-status/openvswitch.xml
@@ -23,4 +23,5 @@
<command
label="ovs-lacp-show">/usr/share/openvswitch/scripts/ovs-bugtool-lacp-show</command>
<command
label="ovs-cfm-show">/usr/share/openvswitch/scripts/ovs-bugtool-cfm-show</command>
<command
label="ovs-coverage-show">/usr/share/openvswitch/scripts/ovs-bugtool-coverage-show</command>
+ <command
label="ovs-memory-show">/usr/share/openvswitch/scripts/ovs-bugtool-memory-show</command>
</collect>
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 13eb80b..c258fc3 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -2228,6 +2228,18 @@ bridge_wait(void)
}
}
}
+
+/* Adds some memory usage statistics for bridges into 'usage', for use with
+ * memory_report(). */
+void
+bridge_get_memory_usage(struct simap *usage)
+{
+ struct bridge *br;
+
+ HMAP_FOR_EACH (br, node, &all_bridges) {
+ ofproto_get_memory_usage(br->ofproto, usage);
+ }
+}
/* QoS unixctl user interface functions. */
diff --git a/vswitchd/bridge.h b/vswitchd/bridge.h
index ecd6ff5..c1b0a2b 100644
--- a/vswitchd/bridge.h
+++ b/vswitchd/bridge.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
+/* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
#ifndef VSWITCHD_BRIDGE_H
#define VSWITCHD_BRIDGE_H 1
+struct simap;
+
void bridge_init(const char *remote);
void bridge_exit(void);
@@ -23,4 +25,6 @@ void bridge_run(void);
void bridge_run_fast(void);
void bridge_wait(void);
+void bridge_get_memory_usage(struct simap *usage);
+
#endif /* bridge.h */
diff --git a/vswitchd/ovs-vswitchd.c b/vswitchd/ovs-vswitchd.c
index f97df8d..8ef3b10 100644
--- a/vswitchd/ovs-vswitchd.c
+++ b/vswitchd/ovs-vswitchd.c
@@ -34,12 +34,14 @@
#include "dpif.h"
#include "dummy.h"
#include "leak-checker.h"
+#include "memory.h"
#include "netdev.h"
#include "openflow/openflow.h"
#include "ovsdb-idl.h"
#include "poll-loop.h"
#include "process.h"
#include "signals.h"
+#include "simap.h"
#include "stream-ssl.h"
#include "stream.h"
#include "stress.h"
@@ -93,6 +95,15 @@ main(int argc, char *argv[])
if (signal_poll(sighup)) {
vlog_reopen_log_file();
}
+ memory_run();
+ if (memory_should_report()) {
+ struct simap usage;
+
+ simap_init(&usage);
+ bridge_get_memory_usage(&usage);
+ memory_report(&usage);
+ simap_destroy(&usage);
+ }
bridge_run_fast();
bridge_run();
bridge_run_fast();
@@ -100,6 +111,7 @@ main(int argc, char *argv[])
netdev_run();
signal_wait(sighup);
+ memory_wait();
bridge_wait();
unixctl_server_wait(unixctl);
netdev_wait();
--
1.7.2.5
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev