[ovs-dev] [PATCH 2/4] ofproto-dpif: Run fast internally.

Ben Pfaff blp at nicira.com
Mon Apr 1 22:13:46 UTC 2013


On Sun, Mar 31, 2013 at 06:22:57PM -0700, Ethan Jackson wrote:
> ofproto-dpif is responsible for quite a few book keeping tasks in
> addition to handling flow misses.  Many of these tasks (flow
> expiration, flow revalidation, etc) can take many hundreds of
> milliseconds, during which no misses can be handled.  The ideal
> long term solution to this problem, is to isolate flow miss
> handling into it's own thread.  However, for now this patch
> provides a 5% increase in TCP_CRR performance, and smooths out
> results during revalidations.
> 
> Signed-off-by: Ethan Jackson <ethan at nicira.com>

I think the arithmetic on port_rl is overflow-prone.  If time_msec()
returns the value 12345, then 12345 - LLONG_MIN is roughly 12345 +
LLONG_MAX, which overflows to a negative number, which is less than
200.  Therefore I'm not certain that the port_run_fast() case ever
triggers.  So, it would be better to use "time_msec() >= port_rl" as
the condition and then reset port_rl to time_msec() + 200.

In run_fast_rl(), backer_rl is not a time value, so it doesn't need to
be a long long int.  An "unsigned int" is probably a better choice
since modulo is going to be cheaper on a 32-bit value than on a 64-bit
one (you could in fact just do something like "if (++backer_rl >= 10)
{ backer_rl = 0; .... }" and avoid the expensive modulo entirely).

Thanks,

Ben.

> +static void
> +run_fast_rl(void)
> +{
> +    static long long int port_rl = LLONG_MIN;
> +    static long long int backer_rl = 0;
> +    long long int now = time_msec();
> +    struct shash_node *node;
> +
> +    if (now - port_rl > 200) {
> +        struct ofproto_dpif *ofproto;
> +        struct ofport_dpif *ofport;
> +
> +        port_rl = now;
> +        HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
> +
> +            HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
> +                port_run_fast(ofport);
> +            }
> +        }
> +    }
> +
> +    /* XXX: We have to be careful not to do too much work in this function.  If
> +     * we call dpif_backer_run_fast() too often, or with too large a batch,
> +     * performance improves signifcantly, but at a cost.  It's possible for the
> +     * number of flows in the datapath to increase without bound, and for poll
> +     * loops to take 10s of seconds.   The correct solution to this problem,
> +     * long term, is to separate flow miss handling into it's own thread so it
> +     * isn't affected by revalidations, and expirations.  Until then, this is
> +     * the best we can do. */
> +    if (backer_rl++ % 10) {
> +        return;
> +    }
> +
> +    SHASH_FOR_EACH (node, &all_dpif_backers) {
> +        dpif_backer_run_fast(node->data, 1);
> +    }
> +}
> +
>  static void
>  type_wait(const char *type)
>  {
> @@ -4254,6 +4301,7 @@ update_stats(struct dpif_backer *backer)
>              delete_unexpected_flow(ofproto, key, key_len);
>              break;
>          }
> +        run_fast_rl();
>      }
>      dpif_flow_dump_done(&dump);
>  }
> @@ -5052,6 +5100,7 @@ push_all_stats(void)
>  
>          HMAP_FOR_EACH (facet, hmap_node, &ofproto->facets) {
>              facet_push_stats(facet);
> +            run_fast_rl();
>          }
>      }
>  }
> @@ -5222,6 +5271,7 @@ subfacet_destroy_batch(struct ofproto_dpif *ofproto,
>          subfacet_reset_dp_stats(subfacets[i], &stats[i]);
>          subfacets[i]->path = SF_NOT_INSTALLED;
>          subfacet_destroy(subfacets[i]);
> +        run_fast_rl();
>      }
>  }
>  
> -- 
> 1.7.9.5
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev



More information about the dev mailing list