Looks good, thanks.

Ethan

On Mon, Apr 16, 2012 at 17:18, Ben Pfaff <b...@nicira.com> wrote:
> This improves performance under heavy flow setup loads.
>
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
>  lib/dpif-linux.c       |    8 ++------
>  lib/dpif-netdev.c      |    6 +++++-
>  lib/dpif-provider.h    |   20 +++++++++-----------
>  lib/dpif.c             |   13 ++++++-------
>  lib/dpif.h             |    2 +-
>  ofproto/ofproto-dpif.c |   25 ++++++++++++++++---------
>  6 files changed, 39 insertions(+), 35 deletions(-)
>
> diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
> index a2908cf..932b36f 100644
> --- a/lib/dpif-linux.c
> +++ b/lib/dpif-linux.c
> @@ -1089,7 +1089,8 @@ parse_odp_packet(struct ofpbuf *buf, struct dpif_upcall 
> *upcall,
>  }
>
>  static int
> -dpif_linux_recv(struct dpif *dpif_, struct dpif_upcall *upcall)
> +dpif_linux_recv(struct dpif *dpif_, struct dpif_upcall *upcall,
> +                struct ofpbuf *buf)
>  {
>     struct dpif_linux *dpif = dpif_linux_cast(dpif_);
>     int read_tries = 0;
> @@ -1123,7 +1124,6 @@ dpif_linux_recv(struct dpif *dpif_, struct dpif_upcall 
> *upcall)
>         dpif->ready_mask &= ~(1u << indx);
>
>         for (;;) {
> -            struct ofpbuf *buf;
>             int dp_ifindex;
>             int error;
>
> @@ -1131,10 +1131,8 @@ dpif_linux_recv(struct dpif *dpif_, struct dpif_upcall 
> *upcall)
>                 return EAGAIN;
>             }
>
> -            buf = ofpbuf_new(2048);
>             error = nl_sock_recv(upcall_sock, buf, false);
>             if (error) {
> -                ofpbuf_delete(buf);
>                 if (error == EAGAIN) {
>                     break;
>                 }
> @@ -1145,8 +1143,6 @@ dpif_linux_recv(struct dpif *dpif_, struct dpif_upcall 
> *upcall)
>             if (!error && dp_ifindex == dpif->dp_ifindex) {
>                 return 0;
>             }
> -
> -            ofpbuf_delete(buf);
>             if (error) {
>                 return error;
>             }
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index a907722..a33fe23 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -935,7 +935,8 @@ find_nonempty_queue(struct dpif *dpif)
>  }
>
>  static int
> -dpif_netdev_recv(struct dpif *dpif, struct dpif_upcall *upcall)
> +dpif_netdev_recv(struct dpif *dpif, struct dpif_upcall *upcall,
> +                 struct ofpbuf *buf)
>  {
>     struct dp_netdev_queue *q = find_nonempty_queue(dpif);
>     if (q) {
> @@ -943,6 +944,9 @@ dpif_netdev_recv(struct dpif *dpif, struct dpif_upcall 
> *upcall)
>         *upcall = *u;
>         free(u);
>
> +        ofpbuf_uninit(buf);
> +        *buf = *u->packet;
> +
>         return 0;
>     } else {
>         return EAGAIN;
> diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
> index d694975..8c6ca1c 100644
> --- a/lib/dpif-provider.h
> +++ b/lib/dpif-provider.h
> @@ -308,21 +308,19 @@ struct dpif_class {
>                              uint32_t *priority);
>
>     /* Polls for an upcall from 'dpif'.  If successful, stores the upcall into
> -     * '*upcall'.  Should only be called if 'recv_set' has been used to 
> enable
> -     * receiving packets from 'dpif'.
> +     * '*upcall', using 'buf' for storage.  Should only be called if 
> 'recv_set'
> +     * has been used to enable receiving packets from 'dpif'.
>      *
> -     * The caller takes ownership of the data that 'upcall' points to.
> -     * 'upcall->key' and 'upcall->actions' (if nonnull) point into data owned
> -     * by 'upcall->packet', so their memory cannot be freed separately.  
> (This
> -     * is hardly a great way to do things but it works out OK for the dpif
> -     * providers that exist so far.)
> -     *
> -     * For greatest efficiency, 'upcall->packet' should have at least
> -     * offsetof(struct ofp_packet_in, data) bytes of headroom.
> +     * The implementation should point 'upcall->packet' and 'upcall->key' 
> into
> +     * data in the caller-provided 'buf'.  If necessary to make room, the
> +     * implementation may expand the data in 'buf'.  (This is hardly a great
> +     * way to do things but it works out OK for the dpif providers that exist
> +     * so far.)
>      *
>      * This function must not block.  If no upcall is pending when it is
>      * called, it should return EAGAIN without blocking. */
> -    int (*recv)(struct dpif *dpif, struct dpif_upcall *upcall);
> +    int (*recv)(struct dpif *dpif, struct dpif_upcall *upcall,
> +                struct ofpbuf *buf);
>
>     /* Arranges for the poll loop to wake up when 'dpif' has a message queued
>      * to be received with the recv member function. */
> diff --git a/lib/dpif.c b/lib/dpif.c
> index dc42a2d..02b10f1 100644
> --- a/lib/dpif.c
> +++ b/lib/dpif.c
> @@ -1070,21 +1070,20 @@ dpif_recv_set(struct dpif *dpif, bool enable)
>  }
>
>  /* Polls for an upcall from 'dpif'.  If successful, stores the upcall into
> - * '*upcall'.  Should only be called if dpif_recv_set() has been used to 
> enable
> - * receiving packets on 'dpif'.
> + * '*upcall', using 'buf' for storage.  Should only be called if
> + * dpif_recv_set() has been used to enable receiving packets on 'dpif'.
>  *
> - * The caller takes ownership of the data that 'upcall' points to.
> - * 'upcall->key' and 'upcall->actions' (if nonnull) point into data owned by
> - * 'upcall->packet', so their memory cannot be freed separately.  (This is
> + * 'upcall->packet' and 'upcall->key' point into data in the caller-provided
> + * 'buf', so their memory cannot be freed separately from 'buf'.  (This is
>  * hardly a great way to do things but it works out OK for the dpif providers
>  * and clients that exist so far.)
>  *
>  * Returns 0 if successful, otherwise a positive errno value.  Returns EAGAIN
>  * if no upcall is immediately available. */
>  int
> -dpif_recv(struct dpif *dpif, struct dpif_upcall *upcall)
> +dpif_recv(struct dpif *dpif, struct dpif_upcall *upcall, struct ofpbuf *buf)
>  {
> -    int error = dpif->dpif_class->recv(dpif, upcall);
> +    int error = dpif->dpif_class->recv(dpif, upcall, buf);
>     if (!error && !VLOG_DROP_DBG(&dpmsg_rl)) {
>         struct ds flow;
>         char *packet;
> diff --git a/lib/dpif.h b/lib/dpif.h
> index 768934b..bdd4fee 100644
> --- a/lib/dpif.h
> +++ b/lib/dpif.h
> @@ -251,7 +251,7 @@ struct dpif_upcall {
>  };
>
>  int dpif_recv_set(struct dpif *, bool enable);
> -int dpif_recv(struct dpif *, struct dpif_upcall *);
> +int dpif_recv(struct dpif *, struct dpif_upcall *, struct ofpbuf *);
>  void dpif_recv_purge(struct dpif *);
>  void dpif_recv_wait(struct dpif *);
>
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index 8c89b50..d0f4215 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -2770,7 +2770,6 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, 
> struct dpif_upcall *upcalls,
>                                                 &flow, &initial_tci,
>                                                 upcall->packet);
>         if (fitness == ODP_FIT_ERROR) {
> -            ofpbuf_delete(upcall->packet);
>             continue;
>         }
>         flow_extract(upcall->packet, flow.skb_priority, flow.tun_id,
> @@ -2780,7 +2779,6 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, 
> struct dpif_upcall *upcalls,
>         if (process_special(ofproto, &flow, upcall->packet)) {
>             ofproto_update_local_port_stats(&ofproto->up,
>                                             0, upcall->packet->size);
> -            ofpbuf_delete(upcall->packet);
>             ofproto->n_matches++;
>             continue;
>         }
> @@ -2829,7 +2827,6 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, 
> struct dpif_upcall *upcalls,
>         }
>     }
>     HMAP_FOR_EACH_SAFE (miss, next_miss, hmap_node, &todo) {
> -        ofpbuf_list_delete(&miss->packets);
>         hmap_remove(&todo, &miss->hmap_node);
>         free(miss);
>     }
> @@ -2851,7 +2848,6 @@ handle_userspace_upcall(struct ofproto_dpif *ofproto,
>                                             upcall->key_len, &flow,
>                                             &initial_tci, upcall->packet);
>     if (fitness == ODP_FIT_ERROR) {
> -        ofpbuf_delete(upcall->packet);
>         return;
>     }
>
> @@ -2863,31 +2859,39 @@ handle_userspace_upcall(struct ofproto_dpif *ofproto,
>     } else {
>         VLOG_WARN_RL(&rl, "invalid user cookie : 0x%"PRIx64, 
> upcall->userdata);
>     }
> -    ofpbuf_delete(upcall->packet);
>  }
>
>  static int
>  handle_upcalls(struct ofproto_dpif *ofproto, unsigned int max_batch)
>  {
>     struct dpif_upcall misses[FLOW_MISS_MAX_BATCH];
> +    struct ofpbuf miss_bufs[FLOW_MISS_MAX_BATCH];
> +    uint64_t miss_buf_stubs[FLOW_MISS_MAX_BATCH][4096 / 8];
> +    int n_processed;
>     int n_misses;
>     int i;
>
> -    assert (max_batch <= FLOW_MISS_MAX_BATCH);
> +    assert(max_batch <= FLOW_MISS_MAX_BATCH);
>
> +    n_processed = 0;
>     n_misses = 0;
> -    for (i = 0; i < max_batch; i++) {
> +    for (n_processed = 0; n_processed < max_batch; n_processed++) {
>         struct dpif_upcall *upcall = &misses[n_misses];
> +        struct ofpbuf *buf = &miss_bufs[n_misses];
>         int error;
>
> -        error = dpif_recv(ofproto->dpif, upcall);
> +        ofpbuf_use_stub(buf, miss_buf_stubs[n_misses],
> +                        sizeof miss_buf_stubs[n_misses]);
> +        error = dpif_recv(ofproto->dpif, upcall, buf);
>         if (error) {
> +            ofpbuf_uninit(buf);
>             break;
>         }
>
>         switch (upcall->type) {
>         case DPIF_UC_ACTION:
>             handle_userspace_upcall(ofproto, upcall);
> +            ofpbuf_uninit(buf);
>             break;
>
>         case DPIF_UC_MISS:
> @@ -2904,8 +2908,11 @@ handle_upcalls(struct ofproto_dpif *ofproto, unsigned 
> int max_batch)
>     }
>
>     handle_miss_upcalls(ofproto, misses, n_misses);
> +    for (i = 0; i < n_misses; i++) {
> +        ofpbuf_uninit(&miss_bufs[i]);
> +    }
>
> -    return i;
> +    return n_processed;
>  }
>
>  /* Flow expiration. */
> --
> 1.7.9
>
> _______________________________________________
> 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