Skip to content

Commit

Permalink
dpif-netdev: Garbage collect the exact match cache periodically.
Browse files Browse the repository at this point in the history
On current master, the exact match cache entry can keep reference to
'struct dp_netdev_flow' even after the flow is removed from the flow
table.  This means the free of allocated memory of the flow is delayed
until the exact match cache entry is cleared or replaced.

If the allocated memory is ahead of chunks of freed memory on heap,
the delay will prevent the reclaim of those freed chunks, causing
falsely high memory utilization.

To fix the issue, this commit makes the owning thread conduct periodic
garbage collection on the exact match cache and clear dead entries.

Signed-off-by: Alex Wang <[email protected]>
Acked-by: Jarno Rajahalme <[email protected]>

---
PATCH -> V2:
- Adopt Jarno's suggestion and conduct slow sweep to avoid introducing
  jitter.
  • Loading branch information
yew011 committed Nov 21, 2014
1 parent 9abdfbe commit 67ad54c
Showing 1 changed file with 17 additions and 0 deletions.
17 changes: 17 additions & 0 deletions lib/dpif-netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ struct emc_entry {

struct emc_cache {
struct emc_entry entries[EM_FLOW_HASH_ENTRIES];
int sweep_idx; /* For emc_cache_slow_sweep(). */
};

/* Iterate in the exact match cache through every entry that might contain a
Expand Down Expand Up @@ -433,6 +434,7 @@ static void dp_netdev_del_pmds_on_numa(struct dp_netdev *dp, int numa_id);
static void dp_netdev_set_pmds_on_numa(struct dp_netdev *dp, int numa_id);
static void dp_netdev_reset_pmd_threads(struct dp_netdev *dp);

static inline bool emc_entry_alive(struct emc_entry *ce);
static void emc_clear_entry(struct emc_entry *ce);

static void
Expand All @@ -442,6 +444,7 @@ emc_cache_init(struct emc_cache *flow_cache)

BUILD_ASSERT(offsetof(struct miniflow, inline_values) == sizeof(uint64_t));

flow_cache->sweep_idx = 0;
for (i = 0; i < ARRAY_SIZE(flow_cache->entries); i++) {
flow_cache->entries[i].flow = NULL;
flow_cache->entries[i].key.hash = 0;
Expand All @@ -462,6 +465,19 @@ emc_cache_uninit(struct emc_cache *flow_cache)
}
}

/* Check and clear dead flow references slowly (one entry at each
* invocation). */
static void
emc_cache_slow_sweep(struct emc_cache *flow_cache)
{
struct emc_entry *entry = &flow_cache->entries[flow_cache->sweep_idx];

if (!emc_entry_alive(entry)) {
emc_clear_entry(entry);
}
flow_cache->sweep_idx = (flow_cache->sweep_idx + 1) & EM_FLOW_HASH_MASK;
}

static struct dpif_netdev *
dpif_netdev_cast(const struct dpif *dpif)
{
Expand Down Expand Up @@ -2332,6 +2348,7 @@ pmd_thread_main(void *f_)

lc = 0;

emc_cache_slow_sweep(&pmd->flow_cache);
ovsrcu_quiesce();

atomic_read_relaxed(&pmd->change_seq, &seq);
Expand Down

0 comments on commit 67ad54c

Please sign in to comment.