Looks good.

--Justin


On Nov 22, 2011, at 3:12 PM, Ben Pfaff wrote:

> This yields a 27% improvement in netperf CRR results in my tests
> versus the previous commit, which is a 52% improvement versus
> the baseline from just before the poll_fd_woke() optimization was
> removed.
> ---
> ofproto/ofproto-dpif.c |   95 +++++++++++++++++++++++++++++-------------------
> 1 files changed, 57 insertions(+), 38 deletions(-)
> 
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index afdd085..ac1e44d 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -415,10 +415,7 @@ static void update_learning_table(struct ofproto_dpif *,
>                                   struct ofbundle *);
> /* Upcalls. */
> #define FLOW_MISS_MAX_BATCH 50
> -
> -static void handle_upcall(struct ofproto_dpif *, struct dpif_upcall *);
> -static void handle_miss_upcalls(struct ofproto_dpif *,
> -                                struct dpif_upcall *, size_t n);
> +static int handle_upcalls(struct ofproto_dpif *, unsigned int max_batch);
> 
> /* Flow expiration. */
> static int expire(struct ofproto_dpif *);
> @@ -588,40 +585,36 @@ static int
> run(struct ofproto *ofproto_)
> {
>     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
> -    struct dpif_upcall misses[FLOW_MISS_MAX_BATCH];
>     struct ofport_dpif *ofport;
>     struct ofbundle *bundle;
> -    size_t n_misses;
> -    int i;
> +    unsigned int work;
> 
>     if (!clogged) {
>         complete_operations(ofproto);
>     }
>     dpif_run(ofproto->dpif);
> 
> -    n_misses = 0;
> -    for (i = 0; i < FLOW_MISS_MAX_BATCH; i++) {
> -        struct dpif_upcall *upcall = &misses[n_misses];
> -        int error;
> -
> -        error = dpif_recv(ofproto->dpif, upcall);
> -        if (error) {
> -            if (error == ENODEV && n_misses == 0) {
> -                return error;
> -            }
> +    /* Handle one or more batches of upcalls, until there's nothing left to 
> do
> +     * or until we do a fixed total amount of work.
> +     *
> +     * We do work in batches because it can be much cheaper to set up a 
> number
> +     * of flows and fire off their patches all at once.  We do multiple 
> batches
> +     * because in some cases handling a packet can cause another packet to be
> +     * queued almost immediately as part of the return flow.  Both
> +     * optimizations can make major improvements on some benchmarks and
> +     * presumably for real traffic as well. */
> +    work = 0;
> +    while (work < FLOW_MISS_MAX_BATCH) {
> +        int retval = handle_upcalls(ofproto, FLOW_MISS_MAX_BATCH - work);
> +        if (retval < 0) {
> +            return -retval;
> +        } else if (!retval) {
>             break;
> -        }
> -
> -        if (upcall->type == DPIF_UC_MISS) {
> -            /* Handle it later. */
> -            n_misses++;
>         } else {
> -            handle_upcall(ofproto, upcall);
> +            work += retval;
>         }
>     }
> 
> -    handle_miss_upcalls(ofproto, misses, n_misses);
> -
>     if (timer_expired(&ofproto->next_expiration)) {
>         int delay = expire(ofproto);
>         timer_set_duration(&ofproto->next_expiration, delay);
> @@ -2380,23 +2373,49 @@ handle_userspace_upcall(struct ofproto_dpif *ofproto,
>     }
> }
> 
> -static void
> -handle_upcall(struct ofproto_dpif *ofproto, struct dpif_upcall *upcall)
> +static int
> +handle_upcalls(struct ofproto_dpif *ofproto, unsigned int max_batch)
> {
> -    switch (upcall->type) {
> -    case DPIF_UC_ACTION:
> -        handle_userspace_upcall(ofproto, upcall);
> -        break;
> +    struct dpif_upcall misses[FLOW_MISS_MAX_BATCH];
> +    int n_misses;
> +    int i;
> 
> -    case DPIF_UC_MISS:
> -        /* The caller handles these. */
> -        NOT_REACHED();
> +    assert (max_batch <= FLOW_MISS_MAX_BATCH);
> 
> -    case DPIF_N_UC_TYPES:
> -    default:
> -        VLOG_WARN_RL(&rl, "upcall has unexpected type %"PRIu32, 
> upcall->type);
> -        break;
> +    n_misses = 0;
> +    for (i = 0; i < max_batch; i++) {
> +        struct dpif_upcall *upcall = &misses[n_misses];
> +        int error;
> +
> +        error = dpif_recv(ofproto->dpif, upcall);
> +        if (error) {
> +            if (error == ENODEV && n_misses == 0) {
> +                return -ENODEV;
> +            }
> +            break;
> +        }
> +
> +        switch (upcall->type) {
> +        case DPIF_UC_ACTION:
> +            handle_userspace_upcall(ofproto, upcall);
> +            break;
> +
> +        case DPIF_UC_MISS:
> +            /* Handle it later. */
> +            n_misses++;
> +            break;
> +
> +        case DPIF_N_UC_TYPES:
> +        default:
> +            VLOG_WARN_RL(&rl, "upcall has unexpected type %"PRIu32,
> +                         upcall->type);
> +            break;
> +        }
>     }
> +
> +    handle_miss_upcalls(ofproto, misses, n_misses);
> +
> +    return i;
> }
> 
> /* Flow expiration. */
> -- 
> 1.7.4.4
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to