X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto-dpif-governor.c;h=506dadb6df4fdb009937ef49be2d8cf461e5bd61;hb=a7752d4ab7a6e7e9aaf83678b57790fc1c56ac83;hp=3b15c38eb71a70790de13df90fe71f1de2f01ba1;hpb=9d6ac44e2b584b34bc7e14f2daa7bb0bdfab16ab;p=openvswitch diff --git a/ofproto/ofproto-dpif-governor.c b/ofproto/ofproto-dpif-governor.c index 3b15c38e..506dadb6 100644 --- a/ofproto/ofproto-dpif-governor.c +++ b/ofproto/ofproto-dpif-governor.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Nicira Networks. + * 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. @@ -93,7 +93,9 @@ governor_run(struct governor *g) void governor_wait(struct governor *g) { - poll_timer_wait_until(g->start + MAX_ELAPSED); + if (g->size > MIN_SIZE) { + poll_timer_wait_until(g->start + MAX_ELAPSED); + } } /* Returns true if 'g' has been doing only a minimal amount of work and thus @@ -114,9 +116,9 @@ governor_is_idle(struct governor *g) bool governor_should_install_flow(struct governor *g, uint32_t hash, int n) { + int old_count, new_count; bool install_flow; uint8_t *e; - int count; assert(n > 0); @@ -133,19 +135,38 @@ governor_should_install_flow(struct governor *g, uint32_t hash, int n) governor_new_generation(g, new_size); } + /* If we've set up most of the flows we've seen, then we're wasting time + * handling most packets one at a time, so in this case instead set up most + * flows directly and use the remaining flows as a sample set to adjust our + * criteria later. + * + * The definition of "most" is conservative, but the sample size is tuned + * based on a few experiments with TCP_CRR mode in netperf. */ + if (g->n_setups >= g->n_flows - g->n_flows / 16 + && g->n_flows >= 64 + && hash & 0x3f) { + g->n_shortcuts++; + return true; + } + /* Do hash table processing. * * Even-numbered hash values use high-order nibbles. * Odd-numbered hash values use low-order nibbles. */ e = &g->table[(hash >> 1) & (g->size - 1)]; - count = n + (hash & 1 ? *e >> 4 : *e & 0x0f); - if (count >= FLOW_SETUP_THRESHOLD) { + old_count = (hash & 1 ? *e >> 4 : *e & 0x0f); + if (!old_count) { + g->n_flows++; + } + new_count = n + old_count; + if (new_count >= FLOW_SETUP_THRESHOLD) { + g->n_setups++; install_flow = true; - count = 0; + new_count = 0; } else { install_flow = false; } - *e = hash & 1 ? (count << 4) | (*e & 0x0f) : (*e & 0xf0) | count; + *e = hash & 1 ? (new_count << 4) | (*e & 0x0f) : (*e & 0xf0) | new_count; return install_flow; } @@ -162,27 +183,33 @@ governor_new_generation(struct governor *g, unsigned int size) if (g->size != size) { if (!g->size) { VLOG_INFO("%s: engaging governor with %u kB hash table", - g->name, g->size / 1024); + g->name, size / 1024); } else { VLOG_INFO("%s: processed %u packets in %.2f s, " - "%s hash table to %u kB", + "%s hash table to %u kB " + "(%u hashes, %u setups, %u shortcuts)", g->name, g->n_packets, (time_msec() - g->start) / 1000.0, size > g->size ? "enlarging" : "shrinking", - size / 1024); + size / 1024, + g->n_flows, g->n_setups, g->n_shortcuts); } free(g->table); g->table = xmalloc(size * sizeof *g->table); g->size = size; } else { - VLOG_DBG("%s: processed %u packets in %.2f s with %u kB hash table", + VLOG_DBG("%s: processed %u packets in %.2f s with %u kB hash table " + "(%u hashes, %u setups, %u shortcuts)", g->name, g->n_packets, (time_msec() - g->start) / 1000.0, - size / 1024); + size / 1024, g->n_flows, g->n_setups, g->n_shortcuts); } /* Clear data for next generation. */ memset(g->table, 0, size * sizeof *g->table); g->start = time_msec(); g->n_packets = 0; + g->n_flows /= 2; + g->n_setups /= 2; + g->n_shortcuts = 0; }