> -----Original Message-----
> From: dev [mailto:dev-boun...@openvswitch.org] On Behalf Of Daniele Di
> Proietto
> Sent: Thursday, April 23, 2015 7:40 PM
> To: dev@openvswitch.org
> Subject: [ovs-dev] [PATCH 7/7] dpif-netdev: Share emc and fast path output
> batches.
> 
> Until now the exact match cache processing was able to handle only four
> megaflow.  The rest of the packets was passed to the megaflow
> classifier.
> 
> The limit was arbitraly set to four also because the algorithm used to
> group packets in output batches didn't perform well with a lot of
> megaflows.
> 
> After changing the algorithm and after some performance testing it seems
> much better just share the same output batches between the exact match
> cache and the megaflow classifier.
> 
> Signed-off-by: Daniele Di Proietto <diproiet...@vmware.com>
> ---
>  lib/dpif-netdev.c | 71 +++++++++++++++++++++++------------------------------
> --
>  1 file changed, 29 insertions(+), 42 deletions(-)
> 
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index 333f5a4..0c3f9e7 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -3063,7 +3063,6 @@ packet_batch_init(struct packet_batch *batch, struct
> dp_netdev_flow *flow)
>  static inline void
>  packet_batch_execute(struct packet_batch *batch,
>                       struct dp_netdev_pmd_thread *pmd,
> -                     enum dp_stat_type hit_type,
>                       long long now)
>  {
>      struct dp_netdev_actions *actions;
> @@ -3077,15 +3076,12 @@ packet_batch_execute(struct packet_batch *batch,
> 
>      dp_netdev_execute_actions(pmd, batch->packets, batch->packet_count,
> true,
>                                actions->actions, actions->size);
> -
> -    dp_netdev_count_packet(pmd, hit_type, batch->packet_count);
>  }
> 
>  static inline bool
>  dp_netdev_queue_batches(struct dp_packet *pkt,
>                          struct dp_netdev_flow *flow, const struct miniflow
> *mf,
> -                        struct packet_batch *batches, size_t *n_batches,
> -                        size_t max_batches)
> +                        struct packet_batch *batches, size_t *n_batches)
>  {
>      struct packet_batch *batch;
> 
> @@ -3100,10 +3096,6 @@ dp_netdev_queue_batches(struct dp_packet *pkt,
>          return true;
>      }
> 
> -    if (OVS_UNLIKELY(*n_batches >= max_batches)) {
> -        return false;
> -    }
> -
>      batch = &batches[(*n_batches)++];
>      packet_batch_init(batch, flow);
>      packet_batch_update(batch, pkt, mf);
> @@ -3119,24 +3111,22 @@ dp_packet_swap(struct dp_packet **a, struct dp_packet
> **b)
>  }
> 
>  /* Try to process all ('cnt') the 'packets' using only the exact match cache
> - * 'flow_cache'. If a flow is not found for a packet 'packets[i]', or if
> there
> - * is no matching batch for a packet's flow, the miniflow is copied into
> 'keys'
> - * and the packet pointer is moved at the beginning of the 'packets' array.
> + * 'flow_cache'. If a flow is not found for a packet 'packets[i]', the
> + * miniflow is copied into 'keys' and the packet pointer is moved at the
> + * beginning of the 'packets' array.
>   *
>   * The function returns the number of packets that needs to be processed in
> the
>   * 'packets' array (they have been moved to the beginning of the vector).
>   */
>  static inline size_t
>  emc_processing(struct dp_netdev_pmd_thread *pmd, struct dp_packet **packets,
> -               size_t cnt, struct netdev_flow_key *keys, long long now)
> +               size_t cnt, struct netdev_flow_key *keys,
> +               struct packet_batch batches[], size_t *n_batches)
>  {
> -    struct netdev_flow_key key;
> -    struct packet_batch batches[4];
>      struct emc_cache *flow_cache = &pmd->flow_cache;
> -    size_t n_batches, i;
> -    size_t notfound_cnt = 0;
> +    struct netdev_flow_key key;
> +    size_t i, notfound_cnt = 0;
> 
> -    n_batches = 0;
>      miniflow_initialize(&key.mf, key.buf);
>      for (i = 0; i < cnt; i++) {
>          struct dp_netdev_flow *flow;
> @@ -3152,8 +3142,7 @@ emc_processing(struct dp_netdev_pmd_thread *pmd, struct
> dp_packet **packets,
> 
>          flow = emc_lookup(flow_cache, &key);
>          if (OVS_UNLIKELY(!dp_netdev_queue_batches(packets[i], flow, &key.mf,
> -                                                  batches, &n_batches,
> -                                                  ARRAY_SIZE(batches)))) {
> +                                                  batches, n_batches))) {
>              if (i != notfound_cnt) {
>                  dp_packet_swap(&packets[i], &packets[notfound_cnt]);
>              }
> @@ -3162,9 +3151,7 @@ emc_processing(struct dp_netdev_pmd_thread *pmd, struct
> dp_packet **packets,
>          }
>      }
> 
> -    for (i = 0; i < n_batches; i++) {
> -        packet_batch_execute(&batches[i], pmd, DP_STAT_EXACT_HIT, now);
> -    }
> +    dp_netdev_count_packet(pmd, DP_STAT_EXACT_HIT, cnt - notfound_cnt);
> 
>      return notfound_cnt;
>  }
> @@ -3172,7 +3159,8 @@ emc_processing(struct dp_netdev_pmd_thread *pmd, struct
> dp_packet **packets,
>  static inline void
>  fast_path_processing(struct dp_netdev_pmd_thread *pmd,
>                       struct dp_packet **packets, size_t cnt,
> -                     struct netdev_flow_key *keys, long long now)
> +                     struct netdev_flow_key *keys,
> +                     struct packet_batch batches[], size_t *n_batches)
>  {
>  #if !defined(__CHECKER__) && !defined(_WIN32)
>      const size_t PKT_ARRAY_SIZE = cnt;
> @@ -3180,12 +3168,12 @@ fast_path_processing(struct dp_netdev_pmd_thread
> *pmd,
>      /* Sparse or MSVC doesn't like variable length array. */
>      enum { PKT_ARRAY_SIZE = NETDEV_MAX_RX_BATCH };
>  #endif
> -    struct packet_batch batches[PKT_ARRAY_SIZE];
>      struct dpcls_rule *rules[PKT_ARRAY_SIZE];
>      struct dp_netdev *dp = pmd->dp;
>      struct emc_cache *flow_cache = &pmd->flow_cache;
> -    size_t n_batches, i;
> +    int miss_cnt = 0, lost_cnt = 0;
>      bool any_miss;
> +    size_t i;
> 
>      for (i = 0; i < cnt; i++) {
>          /* Key length is needed in all the cases, hash computed on demand.
> */
> @@ -3195,7 +3183,6 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
>      if (OVS_UNLIKELY(any_miss) && !fat_rwlock_tryrdlock(&dp->upcall_rwlock))
> {
>          uint64_t actions_stub[512 / 8], slow_stub[512 / 8];
>          struct ofpbuf actions, put_actions;
> -        int miss_cnt = 0, lost_cnt = 0;
>          ovs_u128 ufid;
> 
>          ofpbuf_use_stub(&actions, actions_stub, sizeof actions_stub);
> @@ -3267,23 +3254,17 @@ fast_path_processing(struct dp_netdev_pmd_thread
> *pmd,
>          ofpbuf_uninit(&actions);
>          ofpbuf_uninit(&put_actions);
>          fat_rwlock_unlock(&dp->upcall_rwlock);
> -        dp_netdev_count_packet(pmd, DP_STAT_MISS, miss_cnt);
>          dp_netdev_count_packet(pmd, DP_STAT_LOST, lost_cnt);
>      } else if (OVS_UNLIKELY(any_miss)) {
> -        int dropped_cnt = 0;
> -
>          for (i = 0; i < cnt; i++) {
>              if (OVS_UNLIKELY(!rules[i])) {
>                  dp_packet_delete(packets[i]);
> -                dropped_cnt++;
> +                lost_cnt++;
> +                miss_cnt++;
>              }
>          }
> -
> -        dp_netdev_count_packet(pmd, DP_STAT_MISS, dropped_cnt);
> -        dp_netdev_count_packet(pmd, DP_STAT_LOST, dropped_cnt);
>      }
> 
> -    n_batches = 0;
>      for (i = 0; i < cnt; i++) {
>          struct dp_packet *packet = packets[i];
>          struct dp_netdev_flow *flow;
> @@ -3296,12 +3277,12 @@ fast_path_processing(struct dp_netdev_pmd_thread
> *pmd,
> 
>          emc_insert(flow_cache, &keys[i], flow);
>          dp_netdev_queue_batches(packet, flow, &keys[i].mf, batches,
> -                                &n_batches, ARRAY_SIZE(batches));
> +                                n_batches);
>      }
> 
> -    for (i = 0; i < n_batches; i++) {
> -        packet_batch_execute(&batches[i], pmd, DP_STAT_MASKED_HIT, now);
> -    }
> +    dp_netdev_count_packet(pmd, DP_STAT_MASKED_HIT, cnt - miss_cnt);
> +    dp_netdev_count_packet(pmd, DP_STAT_MISS, miss_cnt);
> +    dp_netdev_count_packet(pmd, DP_STAT_LOST, lost_cnt);
>  }
> 
>  static void
> @@ -3315,12 +3296,18 @@ dp_netdev_input(struct dp_netdev_pmd_thread *pmd,
>      enum { PKT_ARRAY_SIZE = NETDEV_MAX_RX_BATCH };
>  #endif
>      struct netdev_flow_key keys[PKT_ARRAY_SIZE];
> +    struct packet_batch batches[PKT_ARRAY_SIZE];
>      long long now = time_msec();
> -    size_t newcnt;
> +    size_t newcnt, n_batches, i;
> 
> -    newcnt = emc_processing(pmd, packets, cnt, keys, now);
> +    n_batches = 0;
> +    newcnt = emc_processing(pmd, packets, cnt, keys, batches, &n_batches);
>      if (OVS_UNLIKELY(newcnt)) {
> -        fast_path_processing(pmd, packets, newcnt, keys, now);
> +        fast_path_processing(pmd, packets, newcnt, keys, batches,
> &n_batches);
> +    }
> +
> +    for (i = 0; i < n_batches; i++) {
> +        packet_batch_execute(&batches[i], pmd, now);
>      }
>  }

By moving the packet_batch_execute() from emc_processing() and
combining here, you are holding up executing the packets that hit in
the EMC - potentially by a number of upcalls. On the other hand, you
could argue you are getting to the upcalls faster :-) I'm not sure how
significant it would be in reality, but just said I'd mention so you
could consider.

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

Reply via email to