udpif_drop_key_clear(udpif);
}
+void
+udpif_get_memory_usage(struct udpif *udpif, struct simap *usage)
+{
+ size_t i;
+
+ simap_increase(usage, "dispatchers", 1);
+ simap_increase(usage, "flow_dumpers", 1);
+
+ simap_increase(usage, "handlers", udpif->n_handlers);
+ for (i = 0; i < udpif->n_handlers; i++) {
+ struct handler *handler = &udpif->handlers[i];
+ ovs_mutex_lock(&handler->mutex);
+ simap_increase(usage, "handler upcalls", handler->n_upcalls);
+ ovs_mutex_unlock(&handler->mutex);
+ }
+}
+
/* Destroys and deallocates 'upcall'. */
static void
upcall_destroy(struct upcall *upcall)
void udpif_wait(struct udpif *);
void udpif_revalidate(struct udpif *);
+
+void udpif_get_memory_usage(struct udpif *, struct simap *usage);
\f
/* udpif figures out how to forward packets, and does forward them, but it
* can't set up datapath flows on its own. This interface passes packet
simap_increase(usage, "subfacets", n_subfacets);
}
+static void
+type_get_memory_usage(const char *type, struct simap *usage)
+{
+ struct dpif_backer *backer;
+
+ backer = shash_find_data(&all_dpif_backers, type);
+ if (backer) {
+ udpif_get_memory_usage(backer->udpif, usage);
+ }
+}
+
static void
flush(struct ofproto *ofproto_)
{
run,
wait,
get_memory_usage,
+ type_get_memory_usage,
flush,
get_features,
get_tables,
void (*get_memory_usage)(const struct ofproto *ofproto,
struct simap *usage);
+ /* Adds some memory usage statistics for the implementation of 'type'
+ * into 'usage', for use with memory_report().
+ *
+ * This function is optional. */
+ void (*type_get_memory_usage)(const char *type, 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
connmgr_get_memory_usage(ofproto->connmgr, usage);
}
+void
+ofproto_type_get_memory_usage(const char *datapath_type, struct simap *usage)
+{
+ const struct ofproto_class *class;
+
+ datapath_type = ofproto_normalize_type(datapath_type);
+ class = ofproto_class_find__(datapath_type);
+
+ if (class && class->type_get_memory_usage) {
+ class->type_get_memory_usage(datapath_type, usage);
+ }
+}
+
void
ofproto_get_ofproto_controller_info(const struct ofproto *ofproto,
struct shash *info)
bool ofproto_is_alive(const struct ofproto *);
void ofproto_get_memory_usage(const struct ofproto *, struct simap *);
+void ofproto_type_get_memory_usage(const char *datapath_type, struct simap *);
/* A port within an OpenFlow switch.
*
bridge_get_memory_usage(struct simap *usage)
{
struct bridge *br;
+ struct sset types;
+ const char *type;
+
+ sset_init(&types);
+ ofproto_enumerate_types(&types);
+ SSET_FOR_EACH (type, &types) {
+ ofproto_type_get_memory_usage(type, usage);
+ }
+ sset_destroy(&types);
HMAP_FOR_EACH (br, node, &all_bridges) {
ofproto_get_memory_usage(br->ofproto, usage);