[ovs-dev] [PATCH 2/2] Add support for tracking and logging daemon memory usage.

Ben Pfaff blp at nicira.com
Fri Jul 13 17:26:00 UTC 2012


Might as well.  I sent out a patch:
        http://openvswitch.org/pipermail/dev/2012-July/018971.html

On Wed, May 23, 2012 at 12:30:55AM -0700, Justin Pettit wrote:
> Do you think this is worth documenting in NEWS and adding a
> *-unixctl.man fragment like the other ovs-appctl commands?
> 
> --Justin
> 
> 
> On May 8, 2012, at 3:47 PM, Ben Pfaff wrote:
> 
> > Signed-off-by: Ben Pfaff <blp at nicira.com>
> > ---
> > 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
> > dev at openvswitch.org
> > http://openvswitch.org/mailman/listinfo/dev
> 



More information about the dev mailing list