[ovs-dev] [PATCH V3] Add offload packets statistics

Simon Horman simon.horman at netronome.com
Tue Dec 3 16:58:59 UTC 2019


Hi Ben,

yes, will do.

On Mon, Dec 02, 2019 at 03:07:43PM -0800, Ben Pfaff wrote:
> Simon, would you mind taking a look at this too?
> 
> On Mon, Oct 28, 2019 at 08:19:48PM +0800, zhaozhanxu wrote:
> > Add argument '-m' or '--more' for command ovs-appctl bridge/dump-flows
> > to display the offloaded packets statistics.
> > 
> > The commands display as below:
> > 
> > orignal command:
> > 
> > ovs-appctl bridge/dump-flows br0
> > 
> > duration=574s, n_packets=1152, n_bytes=110768, priority=0,actions=NORMAL
> > table_id=254, duration=574s, n_packets=0, n_bytes=0, priority=2,recirc_id=0,actions=drop
> > table_id=254, duration=574s, n_packets=0, n_bytes=0, priority=0,reg0=0x1,actions=controller(reason=)
> > table_id=254, duration=574s, n_packets=0, n_bytes=0, priority=0,reg0=0x2,actions=drop
> > table_id=254, duration=574s, n_packets=0, n_bytes=0, priority=0,reg0=0x3,actions=drop
> > 
> > new command with argument '-m' or '--more'
> > 
> > Notice: 'n_offload_packets' are a subset of n_packets and 'n_offload_bytes' are
> > a subset of n_bytes.
> > 
> > ovs-appctl bridge/dump-flows -m br0
> > 
> > duration=576s, n_packets=1152, n_bytes=110768, n_offload_packets=1107, n_offload_bytes=107992, priority=0,actions=NORMAL
> > table_id=254, duration=576s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=2,recirc_id=0,actions=drop
> > table_id=254, duration=576s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x1,actions=controller(reason=)
> > table_id=254, duration=576s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x2,actions=drop
> > table_id=254, duration=576s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x3,actions=drop
> > 
> > ovs-appctl bridge/dump-flows --more br0
> > 
> > duration=582s, n_packets=1152, n_bytes=110768, n_offload_packets=1107, n_offload_bytes=107992, priority=0,actions=NORMAL
> > table_id=254, duration=582s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=2,recirc_id=0,actions=drop
> > table_id=254, duration=582s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x1,actions=controller(reason=)
> > table_id=254, duration=582s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x2,actions=drop
> > table_id=254, duration=582s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x3,actions=drop
> > 
> > Signed-off-by: zhaozhanxu <zhaozhanxu at 163.com>
> > ---
> >  NEWS                               |  2 ++
> >  lib/dpif.h                         | 10 ++++++
> >  ofproto/bond.c                     |  7 ++--
> >  ofproto/ofproto-dpif-upcall.c      | 11 +++---
> >  ofproto/ofproto-dpif-xlate-cache.c |  8 ++---
> >  ofproto/ofproto-dpif-xlate-cache.h |  6 ++--
> >  ofproto/ofproto-dpif-xlate.c       |  6 ++--
> >  ofproto/ofproto-dpif.c             | 29 ++++++++++------
> >  ofproto/ofproto-dpif.h             |  4 +--
> >  ofproto/ofproto-provider.h         | 11 ++++--
> >  ofproto/ofproto.c                  | 55 ++++++++++++++++++------------
> >  ofproto/ofproto.h                  |  2 +-
> >  vswitchd/bridge.c                  | 15 +++++---
> >  vswitchd/ovs-vswitchd.8.in         |  3 +-
> >  14 files changed, 108 insertions(+), 61 deletions(-)
> > 
> > diff --git a/NEWS b/NEWS
> > index 330ab3832..14023fcf7 100644
> > --- a/NEWS
> > +++ b/NEWS
> > @@ -81,6 +81,8 @@ v2.12.0 - 03 Sep 2019
> >       * Add support for conntrack zone-based timeout policy.
> >     - 'ovs-dpctl dump-flows' is no longer suitable for dumping offloaded flows.
> >       'ovs-appctl dpctl/dump-flows' should be used instead.
> > +   - Add new argument '-m | --more' for command 'ovs-appctl bridge/dump-flows',
> > +     so it can display offloaded packets statistics.
> >     - Add L2 GRE tunnel over IPv6 support.
> >  
> >  v2.11.0 - 19 Feb 2019
> > diff --git a/lib/dpif.h b/lib/dpif.h
> > index 289d574a0..7d82a28be 100644
> > --- a/lib/dpif.h
> > +++ b/lib/dpif.h
> > @@ -496,6 +496,16 @@ struct dpif_flow_stats {
> >      uint16_t tcp_flags;
> >  };
> >  
> > +/* more statistics info for offloaded packets and bytes */
> > +struct dpif_flow_detailed_stats {
> > +    uint64_t n_packets;     /* n_offload_packets are a subset of n_packets */
> > +    uint64_t n_bytes;       /* n_offload_bytes are a subset of n_bytes */
> > +    uint64_t n_offload_packets;
> > +    uint64_t n_offload_bytes;
> > +    long long int used;
> > +    uint16_t tcp_flags;
> > +};
> > +
> >  struct dpif_flow_attrs {
> >      bool offloaded;         /* True if flow is offloaded to HW. */
> >      const char *dp_layer;   /* DP layer the flow is handled in. */
> > diff --git a/ofproto/bond.c b/ofproto/bond.c
> > index c5d5f2c03..03de1eec9 100644
> > --- a/ofproto/bond.c
> > +++ b/ofproto/bond.c
> > @@ -946,13 +946,12 @@ bond_recirculation_account(struct bond *bond)
> >          struct rule *rule = entry->pr_rule;
> >  
> >          if (rule) {
> > -            uint64_t n_packets OVS_UNUSED;
> > +            struct pkts_stats stats;
> >              long long int used OVS_UNUSED;
> > -            uint64_t n_bytes;
> >  
> >              rule->ofproto->ofproto_class->rule_get_stats(
> > -                rule, &n_packets, &n_bytes, &used);
> > -            bond_entry_account(entry, n_bytes);
> > +                rule, &stats, &used);
> > +            bond_entry_account(entry, stats.n_bytes);
> >          }
> >      }
> >  }
> > diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
> > index 657aa7f79..5fdba5b65 100644
> > --- a/ofproto/ofproto-dpif-upcall.c
> > +++ b/ofproto/ofproto-dpif-upcall.c
> > @@ -2260,7 +2260,7 @@ static enum reval_result
> >  revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
> >                  const struct dpif_flow_stats *stats,
> >                  struct ofpbuf *odp_actions, uint64_t reval_seq,
> > -                struct recirc_refs *recircs)
> > +                struct recirc_refs *recircs, bool offloaded)
> >      OVS_REQUIRES(ukey->mutex)
> >  {
> >      bool need_revalidate = ukey->reval_seq != reval_seq;
> > @@ -2295,7 +2295,7 @@ revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
> >  
> >      /* Stats for deleted flows will be attributed upon flow deletion. Skip. */
> >      if (result != UKEY_DELETE) {
> > -        xlate_push_stats(ukey->xcache, &push);
> > +        xlate_push_stats(ukey->xcache, &push, offloaded);
> >          ukey->stats = *stats;
> >          ukey->reval_seq = reval_seq;
> >      }
> > @@ -2408,7 +2408,7 @@ push_dp_ops(struct udpif *udpif, struct ukey_op *ops, size_t n_ops)
> >              if (op->ukey) {
> >                  ovs_mutex_lock(&op->ukey->mutex);
> >                  if (op->ukey->xcache) {
> > -                    xlate_push_stats(op->ukey->xcache, push);
> > +                    xlate_push_stats(op->ukey->xcache, push, false);
> >                      ovs_mutex_unlock(&op->ukey->mutex);
> >                      continue;
> >                  }
> > @@ -2685,7 +2685,8 @@ revalidate(struct revalidator *revalidator)
> >                  result = UKEY_DELETE;
> >              } else {
> >                  result = revalidate_ukey(udpif, ukey, &f->stats, &odp_actions,
> > -                                         reval_seq, &recircs);
> > +                                         reval_seq, &recircs,
> > +                                         f->attrs.offloaded);
> >              }
> >              ukey->dump_seq = dump_seq;
> >  
> > @@ -2770,7 +2771,7 @@ revalidator_sweep__(struct revalidator *revalidator, bool purge)
> >                      COVERAGE_INC(revalidate_missed_dp_flow);
> >                      memset(&stats, 0, sizeof stats);
> >                      result = revalidate_ukey(udpif, ukey, &stats, &odp_actions,
> > -                                             reval_seq, &recircs);
> > +                                             reval_seq, &recircs, false);
> >                  }
> >                  if (result != UKEY_KEEP) {
> >                      /* Clears 'recircs' if filled by revalidate_ukey(). */
> > diff --git a/ofproto/ofproto-dpif-xlate-cache.c b/ofproto/ofproto-dpif-xlate-cache.c
> > index 2a2e77a42..dcc91cb38 100644
> > --- a/ofproto/ofproto-dpif-xlate-cache.c
> > +++ b/ofproto/ofproto-dpif-xlate-cache.c
> > @@ -90,7 +90,7 @@ xlate_cache_netdev(struct xc_entry *entry, const struct dpif_flow_stats *stats)
> >  /* Push stats and perform side effects of flow translation. */
> >  void
> >  xlate_push_stats_entry(struct xc_entry *entry,
> > -                       struct dpif_flow_stats *stats)
> > +                       struct dpif_flow_stats *stats, bool offloaded)
> >  {
> >      struct eth_addr dmac;
> >  
> > @@ -104,7 +104,7 @@ xlate_push_stats_entry(struct xc_entry *entry,
> >                                          ? 0 : stats->n_packets);
> >          break;
> >      case XC_RULE:
> > -        rule_dpif_credit_stats(entry->rule, stats);
> > +        rule_dpif_credit_stats(entry->rule, stats, offloaded);
> >          break;
> >      case XC_BOND:
> >          bond_account(entry->bond.bond, entry->bond.flow,
> > @@ -169,7 +169,7 @@ xlate_push_stats_entry(struct xc_entry *entry,
> >  
> >  void
> >  xlate_push_stats(struct xlate_cache *xcache,
> > -                 struct dpif_flow_stats *stats)
> > +                 struct dpif_flow_stats *stats, bool offloaded)
> >  {
> >      if (!stats->n_packets) {
> >          return;
> > @@ -178,7 +178,7 @@ xlate_push_stats(struct xlate_cache *xcache,
> >      struct xc_entry *entry;
> >      struct ofpbuf entries = xcache->entries;
> >      XC_ENTRY_FOR_EACH (entry, &entries) {
> > -        xlate_push_stats_entry(entry, stats);
> > +        xlate_push_stats_entry(entry, stats, offloaded);
> >      }
> >  }
> >  
> > diff --git a/ofproto/ofproto-dpif-xlate-cache.h b/ofproto/ofproto-dpif-xlate-cache.h
> > index e5dae6dc6..114aff8ea 100644
> > --- a/ofproto/ofproto-dpif-xlate-cache.h
> > +++ b/ofproto/ofproto-dpif-xlate-cache.h
> > @@ -142,8 +142,10 @@ struct xlate_cache {
> >  void xlate_cache_init(struct xlate_cache *);
> >  struct xlate_cache *xlate_cache_new(void);
> >  struct xc_entry *xlate_cache_add_entry(struct xlate_cache *, enum xc_type);
> > -void xlate_push_stats_entry(struct xc_entry *, struct dpif_flow_stats *);
> > -void xlate_push_stats(struct xlate_cache *, struct dpif_flow_stats *);
> > +void xlate_push_stats_entry(struct xc_entry *, struct dpif_flow_stats *,
> > +                            bool);
> > +void xlate_push_stats(struct xlate_cache *, struct dpif_flow_stats *,
> > +                      bool);
> >  void xlate_cache_clear_entry(struct xc_entry *);
> >  void xlate_cache_clear(struct xlate_cache *);
> >  void xlate_cache_uninit(struct xlate_cache *);
> > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> > index f92cb62c8..8db7b0e41 100644
> > --- a/ofproto/ofproto-dpif-xlate.c
> > +++ b/ofproto/ofproto-dpif-xlate.c
> > @@ -3697,7 +3697,7 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport,
> >           */
> >          if (backup_resubmit_stats) {
> >              struct dpif_flow_stats stats = *backup_resubmit_stats;
> > -            xlate_push_stats(ctx->xin->xcache, &stats);
> > +            xlate_push_stats(ctx->xin->xcache, &stats, false);
> >          }
> >          xlate_cache_steal_entries(backup_xcache, ctx->xin->xcache);
> >  
> > @@ -4263,7 +4263,7 @@ xlate_recursively(struct xlate_ctx *ctx, struct rule_dpif *rule,
> >      const struct rule_actions *actions;
> >  
> >      if (ctx->xin->resubmit_stats) {
> > -        rule_dpif_credit_stats(rule, ctx->xin->resubmit_stats);
> > +        rule_dpif_credit_stats(rule, ctx->xin->resubmit_stats, false);
> >      }
> >  
> >      ctx->resubmits++;
> > @@ -7589,7 +7589,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
> >              ctx.xin->resubmit_stats, &ctx.table_id,
> >              flow->in_port.ofp_port, true, true, ctx.xin->xcache);
> >          if (ctx.xin->resubmit_stats) {
> > -            rule_dpif_credit_stats(ctx.rule, ctx.xin->resubmit_stats);
> > +            rule_dpif_credit_stats(ctx.rule, ctx.xin->resubmit_stats, false);
> >          }
> >          if (ctx.xin->xcache) {
> >              struct xc_entry *entry;
> > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> > index 496a16c8a..425ca6b06 100644
> > --- a/ofproto/ofproto-dpif.c
> > +++ b/ofproto/ofproto-dpif.c
> > @@ -80,7 +80,7 @@ COVERAGE_DEFINE(packet_in_overflow);
> >  
> >  struct flow_miss;
> >  
> > -static void rule_get_stats(struct rule *, uint64_t *packets, uint64_t *bytes,
> > +static void rule_get_stats(struct rule *, struct pkts_stats *stats,
> >                             long long int *used);
> >  static struct rule_dpif *rule_dpif_cast(const struct rule *);
> >  static void rule_expire(struct rule_dpif *, long long now);
> > @@ -4115,7 +4115,7 @@ ofproto_dpif_execute_actions__(struct ofproto_dpif *ofproto,
> >      dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
> >  
> >      if (rule) {
> > -        rule_dpif_credit_stats(rule, &stats);
> > +        rule_dpif_credit_stats(rule, &stats, false);
> >      }
> >  
> >      uint64_t odp_actions_stub[1024 / 8];
> > @@ -4169,10 +4169,14 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto,
> >  static void
> >  rule_dpif_credit_stats__(struct rule_dpif *rule,
> >                           const struct dpif_flow_stats *stats,
> > -                         bool credit_counts)
> > +                         bool credit_counts, bool offloaded)
> >      OVS_REQUIRES(rule->stats_mutex)
> >  {
> >      if (credit_counts) {
> > +        if (offloaded) {
> > +            rule->stats.n_offload_packets += stats->n_packets;
> > +            rule->stats.n_offload_bytes += stats->n_bytes;
> > +        }
> >          rule->stats.n_packets += stats->n_packets;
> >          rule->stats.n_bytes += stats->n_bytes;
> >      }
> > @@ -4181,15 +4185,16 @@ rule_dpif_credit_stats__(struct rule_dpif *rule,
> >  
> >  void
> >  rule_dpif_credit_stats(struct rule_dpif *rule,
> > -                       const struct dpif_flow_stats *stats)
> > +                       const struct dpif_flow_stats *stats, bool offloaded)
> >  {
> >      ovs_mutex_lock(&rule->stats_mutex);
> >      if (OVS_UNLIKELY(rule->new_rule)) {
> >          ovs_mutex_lock(&rule->new_rule->stats_mutex);
> > -        rule_dpif_credit_stats__(rule->new_rule, stats, rule->forward_counts);
> > +        rule_dpif_credit_stats__(rule->new_rule, stats, rule->forward_counts,
> > +                                 offloaded);
> >          ovs_mutex_unlock(&rule->new_rule->stats_mutex);
> >      } else {
> > -        rule_dpif_credit_stats__(rule, stats, true);
> > +        rule_dpif_credit_stats__(rule, stats, true, offloaded);
> >      }
> >      ovs_mutex_unlock(&rule->stats_mutex);
> >  }
> > @@ -4640,17 +4645,19 @@ rule_destruct(struct rule *rule_)
> >  }
> >  
> >  static void
> > -rule_get_stats(struct rule *rule_, uint64_t *packets, uint64_t *bytes,
> > +rule_get_stats(struct rule *rule_, struct pkts_stats *stats,
> >                 long long int *used)
> >  {
> >      struct rule_dpif *rule = rule_dpif_cast(rule_);
> >  
> >      ovs_mutex_lock(&rule->stats_mutex);
> >      if (OVS_UNLIKELY(rule->new_rule)) {
> > -        rule_get_stats(&rule->new_rule->up, packets, bytes, used);
> > +        rule_get_stats(&rule->new_rule->up, stats, used);
> >      } else {
> > -        *packets = rule->stats.n_packets;
> > -        *bytes = rule->stats.n_bytes;
> > +        stats->n_packets = rule->stats.n_packets;
> > +        stats->n_bytes = rule->stats.n_bytes;
> > +        stats->n_offload_packets = rule->stats.n_offload_packets;
> > +        stats->n_offload_bytes = rule->stats.n_offload_bytes;
> >          *used = rule->stats.used;
> >      }
> >      ovs_mutex_unlock(&rule->stats_mutex);
> > @@ -4814,7 +4821,7 @@ ofproto_dpif_xcache_execute(struct ofproto_dpif *ofproto,
> >          case XC_GROUP:
> >          case XC_TNL_NEIGH:
> >          case XC_TUNNEL_HEADER:
> > -            xlate_push_stats_entry(entry, stats);
> > +            xlate_push_stats_entry(entry, stats, false);
> >              break;
> >          default:
> >              OVS_NOT_REACHED();
> > diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
> > index cd453636c..afdba0d49 100644
> > --- a/ofproto/ofproto-dpif.h
> > +++ b/ofproto/ofproto-dpif.h
> > @@ -76,7 +76,7 @@ struct rule_dpif {
> >       *   - Do include packets and bytes from datapath flows which have not
> >       *   recently been processed by a revalidator. */
> >      struct ovs_mutex stats_mutex;
> > -    struct dpif_flow_stats stats OVS_GUARDED;
> > +    struct dpif_flow_detailed_stats stats OVS_GUARDED;
> >  
> >     /* In non-NULL, will point to a new rule (for which a reference is held) to
> >      * which all the stats updates should be forwarded. This exists only
> > @@ -107,7 +107,7 @@ struct rule_dpif *rule_dpif_lookup_from_table(struct ofproto_dpif *,
> >                                                struct xlate_cache *);
> >  
> >  void rule_dpif_credit_stats(struct rule_dpif *,
> > -                            const struct dpif_flow_stats *);
> > +                            const struct dpif_flow_stats *, bool);
> >  
> >  void rule_set_recirc_id(struct rule *, uint32_t id);
> >  
> > diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
> > index c980e6bff..6a44e6a34 100644
> > --- a/ofproto/ofproto-provider.h
> > +++ b/ofproto/ofproto-provider.h
> > @@ -588,6 +588,13 @@ struct ofgroup {
> >      struct rule_collection rules OVS_GUARDED;   /* Referring rules. */
> >  };
> >  
> > +struct pkts_stats {
> > +    uint64_t n_packets; /* n_offload_packets are a subset n_packets */
> > +    uint64_t n_bytes;   /* n_offload_bytes are a subset of n_bytes */
> > +    uint64_t n_offload_packets;
> > +    uint64_t n_offload_bytes;
> > +};
> > +
> >  struct ofgroup *ofproto_group_lookup(const struct ofproto *ofproto,
> >                                       uint32_t group_id, ovs_version_t version,
> >                                       bool take_ref);
> > @@ -1348,8 +1355,8 @@ struct ofproto_class {
> >       * matched it in '*packet_count' and the number of bytes in those packets
> >       * in '*byte_count'.  UINT64_MAX indicates that the packet count or byte
> >       * count is unknown. */
> > -    void (*rule_get_stats)(struct rule *rule, uint64_t *packet_count,
> > -                           uint64_t *byte_count, long long int *used)
> > +    void (*rule_get_stats)(struct rule *rule, struct pkts_stats *stats,
> > +                           long long int *used)
> >          /* OVS_EXCLUDED(ofproto_mutex) */;
> >  
> >      /* Translates actions in 'opo->ofpacts', for 'opo->packet' in flow tables
> > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> > index b4249b0d8..b26e0f281 100644
> > --- a/ofproto/ofproto.c
> > +++ b/ofproto/ofproto.c
> > @@ -4640,6 +4640,7 @@ handle_flow_stats_request(struct ofconn *ofconn,
> >      RULE_COLLECTION_FOR_EACH (rule, &rules) {
> >          long long int now = time_msec();
> >          struct ofputil_flow_stats fs;
> > +        struct pkts_stats stats;
> >          long long int created, used, modified;
> >          const struct rule_actions *actions;
> >          enum ofputil_flow_mod_flags flags;
> > @@ -4655,8 +4656,9 @@ handle_flow_stats_request(struct ofconn *ofconn,
> >          flags = rule->flags;
> >          ovs_mutex_unlock(&rule->mutex);
> >  
> > -        ofproto->ofproto_class->rule_get_stats(rule, &fs.packet_count,
> > -                                               &fs.byte_count, &used);
> > +        ofproto->ofproto_class->rule_get_stats(rule, &stats, &used);
> > +        fs.packet_count = stats.n_packets;
> > +        fs.byte_count = stats.n_bytes;
> >  
> >          minimatch_expand(&rule->cr.match, &fs.match);
> >          fs.table_id = rule->table_id;
> > @@ -4681,14 +4683,14 @@ handle_flow_stats_request(struct ofconn *ofconn,
> >  }
> >  
> >  static void
> > -flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results)
> > +flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results,
> > +              bool verbosity)
> >  {
> > -    uint64_t packet_count, byte_count;
> > +    struct pkts_stats stats;
> >      const struct rule_actions *actions;
> >      long long int created, used;
> >  
> > -    rule->ofproto->ofproto_class->rule_get_stats(rule, &packet_count,
> > -                                                 &byte_count, &used);
> > +    rule->ofproto->ofproto_class->rule_get_stats(rule, &stats, &used);
> >  
> >      ovs_mutex_lock(&rule->mutex);
> >      actions = rule_get_actions(rule);
> > @@ -4699,8 +4701,17 @@ flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results)
> >          ds_put_format(results, "table_id=%"PRIu8", ", rule->table_id);
> >      }
> >      ds_put_format(results, "duration=%llds, ", (time_msec() - created) / 1000);
> > -    ds_put_format(results, "n_packets=%"PRIu64", ", packet_count);
> > -    ds_put_format(results, "n_bytes=%"PRIu64", ", byte_count);
> > +    if (verbosity) {
> > +        ds_put_format(results, "n_packets=%"PRIu64", ", stats.n_packets);
> > +        ds_put_format(results, "n_bytes=%"PRIu64", ", stats.n_bytes);
> > +        ds_put_format(results, "n_offload_packets=%"PRIu64", ",
> > +                      stats.n_offload_packets);
> > +        ds_put_format(results, "n_offload_bytes=%"PRIu64", ",
> > +                      stats.n_offload_bytes);
> > +    } else {
> > +        ds_put_format(results, "n_packets=%"PRIu64", ", stats.n_packets);
> > +        ds_put_format(results, "n_bytes=%"PRIu64", ", stats.n_bytes);
> > +    }
> >      cls_rule_format(&rule->cr, ofproto_get_tun_tab(ofproto), NULL, results);
> >      ds_put_char(results, ',');
> >  
> > @@ -4714,7 +4725,7 @@ flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results)
> >  /* Adds a pretty-printed description of all flows to 'results', including
> >   * hidden flows (e.g., set up by in-band control). */
> >  void
> > -ofproto_get_all_flows(struct ofproto *p, struct ds *results)
> > +ofproto_get_all_flows(struct ofproto *p, struct ds *results, bool verbosity)
> >  {
> >      struct oftable *table;
> >  
> > @@ -4722,7 +4733,7 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results)
> >          struct rule *rule;
> >  
> >          CLS_FOR_EACH (rule, cr, &table->cls) {
> > -            flow_stats_ds(p, rule, results);
> > +            flow_stats_ds(p, rule, results, verbosity);
> >          }
> >      }
> >  }
> > @@ -4810,23 +4821,21 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
> >  
> >      struct rule *rule;
> >      RULE_COLLECTION_FOR_EACH (rule, &rules) {
> > -        uint64_t packet_count;
> > -        uint64_t byte_count;
> > +        struct pkts_stats pkts_stats;
> >          long long int used;
> >  
> > -        ofproto->ofproto_class->rule_get_stats(rule, &packet_count,
> > -                                               &byte_count, &used);
> > +        ofproto->ofproto_class->rule_get_stats(rule, &pkts_stats, &used);
> >  
> > -        if (packet_count == UINT64_MAX) {
> > +        if (pkts_stats.n_packets == UINT64_MAX) {
> >              unknown_packets = true;
> >          } else {
> > -            stats.packet_count += packet_count;
> > +            stats.packet_count += pkts_stats.n_packets;
> >          }
> >  
> > -        if (byte_count == UINT64_MAX) {
> > +        if (pkts_stats.n_bytes == UINT64_MAX) {
> >              unknown_bytes = true;
> >          } else {
> > -            stats.byte_count += byte_count;
> > +            stats.byte_count += pkts_stats.n_bytes;
> >          }
> >  
> >          stats.flow_count++;
> > @@ -6017,6 +6026,7 @@ ofproto_rule_send_removed(struct rule *rule)
> >  {
> >      struct ofputil_flow_removed fr;
> >      long long int used;
> > +    struct pkts_stats stats;
> >  
> >      minimatch_expand(&rule->cr.match, &fr.match);
> >      fr.priority = rule->cr.priority;
> > @@ -6039,8 +6049,9 @@ ofproto_rule_send_removed(struct rule *rule)
> >      fr.idle_timeout = rule->idle_timeout;
> >      fr.hard_timeout = rule->hard_timeout;
> >      ovs_mutex_unlock(&rule->mutex);
> > -    rule->ofproto->ofproto_class->rule_get_stats(rule, &fr.packet_count,
> > -                                                 &fr.byte_count, &used);
> > +    rule->ofproto->ofproto_class->rule_get_stats(rule, &stats, &used);
> > +    fr.packet_count += stats.n_packets;
> > +    fr.byte_count += stats.n_bytes;
> >      connmgr_send_flow_removed(connmgr, &fr);
> >      ovs_mutex_unlock(&ofproto_mutex);
> >  }
> > @@ -8850,11 +8861,11 @@ rule_eviction_priority(struct ofproto *ofproto, struct rule *rule)
> >          expiration = modified + rule->hard_timeout * 1000;
> >      }
> >      if (rule->idle_timeout) {
> > -        uint64_t packets, bytes;
> > +        struct pkts_stats stats;
> >          long long int used;
> >          long long int idle_expiration;
> >  
> > -        ofproto->ofproto_class->rule_get_stats(rule, &packets, &bytes, &used);
> > +        ofproto->ofproto_class->rule_get_stats(rule, &stats, &used);
> >          idle_expiration = used + rule->idle_timeout * 1000;
> >          expiration = MIN(expiration, idle_expiration);
> >      }
> > diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
> > index 033c4cf93..8924baf29 100644
> > --- a/ofproto/ofproto.h
> > +++ b/ofproto/ofproto.h
> > @@ -541,7 +541,7 @@ void ofproto_configure_table(struct ofproto *, int table_id,
> >  /* Configuration querying. */
> >  bool ofproto_has_snoops(const struct ofproto *);
> >  void ofproto_get_snoops(const struct ofproto *, struct sset *);
> > -void ofproto_get_all_flows(struct ofproto *p, struct ds *);
> > +void ofproto_get_all_flows(struct ofproto *p, struct ds *, bool);
> >  void ofproto_get_netflow_ids(const struct ofproto *,
> >                               uint8_t *engine_type, uint8_t *engine_id);
> >  
> > diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
> > index 9095ebf5d..e700cb02c 100644
> > --- a/vswitchd/bridge.c
> > +++ b/vswitchd/bridge.c
> > @@ -514,7 +514,7 @@ bridge_init(const char *remote)
> >                               qos_unixctl_show_types, NULL);
> >      unixctl_command_register("qos/show", "interface", 1, 1,
> >                               qos_unixctl_show, NULL);
> > -    unixctl_command_register("bridge/dump-flows", "bridge", 1, 1,
> > +    unixctl_command_register("bridge/dump-flows", "[-m | --more] bridge", 1, 2,
> >                               bridge_unixctl_dump_flows, NULL);
> >      unixctl_command_register("bridge/reconnect", "[bridge]", 0, 1,
> >                               bridge_unixctl_reconnect, NULL);
> > @@ -3573,20 +3573,27 @@ bridge_lookup(const char *name)
> >  /* Handle requests for a listing of all flows known by the OpenFlow
> >   * stack, including those normally hidden. */
> >  static void
> > -bridge_unixctl_dump_flows(struct unixctl_conn *conn, int argc OVS_UNUSED,
> > +bridge_unixctl_dump_flows(struct unixctl_conn *conn, int argc,
> >                            const char *argv[], void *aux OVS_UNUSED)
> >  {
> >      struct bridge *br;
> >      struct ds results;
> >  
> > -    br = bridge_lookup(argv[1]);
> > +    br = bridge_lookup(argv[argc - 1]);
> >      if (!br) {
> >          unixctl_command_reply_error(conn, "Unknown bridge");
> >          return;
> >      }
> >  
> > +    bool verbosity = false;
> > +    for (int i = 1; i < argc - 1; i++) {
> > +        if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--more")) {
> > +            verbosity = true;
> > +        }
> > +    }
> > +
> >      ds_init(&results);
> > -    ofproto_get_all_flows(br->ofproto, &results);
> > +    ofproto_get_all_flows(br->ofproto, &results, verbosity);
> >  
> >      unixctl_command_reply(conn, ds_cstr(&results));
> >      ds_destroy(&results);
> > diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in
> > index a5cdc3aa4..2ab99db32 100644
> > --- a/vswitchd/ovs-vswitchd.8.in
> > +++ b/vswitchd/ovs-vswitchd.8.in
> > @@ -185,11 +185,12 @@ their controller connections and reconnect.
> >  .IP
> >  This command might be useful for debugging OpenFlow controller issues.
> >  .
> > -.IP "\fBbridge/dump\-flows\fR \fIbridge\fR"
> > +.IP "\fBbridge/dump\-flows\fR [\fB\-m\fR | \fB\-\-more\fR] \fIbridge\fR"
> >  Lists all flows in \fIbridge\fR, including those normally hidden to
> >  commands such as \fBovs\-ofctl dump\-flows\fR.  Flows set up by mechanisms
> >  such as in-band control and fail-open are hidden from the controller
> >  since it is not allowed to modify or override them.
> > +With \fB\-m\fR or \fB\-\-more\fR, also dump the offloaded packets and bytes.
> >  .SS "BOND COMMANDS"
> >  These commands manage bonded ports on an Open vSwitch's bridges.  To
> >  understand some of these commands, it is important to understand a
> > -- 
> > 2.20.1
> > 
> > 
> > _______________________________________________
> > dev mailing list
> > dev at openvswitch.org
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev


More information about the dev mailing list