acked-by: Andy Zhou <az...@nicira.com>

On Wed, Jul 17, 2013 at 3:58 PM, Ben Pfaff <b...@nicira.com> wrote:

> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
>  OPENFLOW-1.1+      |    3 ---
>  lib/netdev-linux.c |   11 ++++++++---
>  lib/netdev.c       |    8 ++++++--
>  lib/netdev.h       |    3 +++
>  lib/ofp-print.c    |   14 +++++++++++---
>  lib/ofp-util.c     |   44 ++++++++++++++++++++++++--------------------
>  lib/ofp-util.h     |   10 +++++++++-
>  ofproto/ofproto.c  |   19 ++++++++++++++-----
>  tests/ofp-print.at |   50
> ++++++++++++++++++++++++++------------------------
>  9 files changed, 101 insertions(+), 61 deletions(-)
>
> diff --git a/OPENFLOW-1.1+ b/OPENFLOW-1.1+
> index d08a46e..aea689e 100644
> --- a/OPENFLOW-1.1+
> +++ b/OPENFLOW-1.1+
> @@ -143,9 +143,6 @@ didn't compare the specs carefully yet.)
>      * Rework tag order.  I'm not sure whether we need to do anything
>        for this.
>
> -    * Duration for queue stats.  (Duration for port stats is already
> -      implemented.)
> -
>      * On-demand flow counters.  I think this might be a real
>        optimization in some cases for the software switch.
>
> diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
> index 8790f14..83d3d67 100644
> --- a/lib/netdev-linux.c
> +++ b/lib/netdev-linux.c
> @@ -148,6 +148,7 @@ struct tc {
>  struct tc_queue {
>      struct hmap_node hmap_node; /* In struct tc's "queues" hmap. */
>      unsigned int queue_id;      /* OpenFlow queue ID. */
> +    long long int created;      /* Time queue was created, in msecs. */
>  };
>
>  /* A particular kind of traffic control.  Each implementation generally
> maps to
> @@ -2010,9 +2011,11 @@ netdev_linux_get_queue_stats(const struct netdev
> *netdev_,
>          return EOPNOTSUPP;
>      } else {
>          const struct tc_queue *queue = tc_find_queue(netdev_, queue_id);
> -        return (queue
> -                ? netdev->tc->ops->class_get_stats(netdev_, queue, stats)
> -                : ENOENT);
> +        if (!queue) {
> +            return ENOENT;
> +        }
> +        stats->created = queue->created;
> +        return netdev->tc->ops->class_get_stats(netdev_, queue, stats);
>      }
>  }
>
> @@ -2819,6 +2822,7 @@ htb_update_queue__(struct netdev *netdev, unsigned
> int queue_id,
>          hcp = xmalloc(sizeof *hcp);
>          queue = &hcp->tc_queue;
>          queue->queue_id = queue_id;
> +        queue->created = time_msec();
>          hmap_insert(&htb->tc.queues, &queue->hmap_node, hash);
>      }
>
> @@ -3052,6 +3056,7 @@ hfsc_update_queue__(struct netdev *netdev, unsigned
> int queue_id,
>          hcp             = xmalloc(sizeof *hcp);
>          queue           = &hcp->tc_queue;
>          queue->queue_id = queue_id;
> +        queue->created  = time_msec();
>          hmap_insert(&hfsc->tc.queues, &queue->hmap_node, hash);
>      }
>
> diff --git a/lib/netdev.c b/lib/netdev.c
> index 727c538..6e2a92f 100644
> --- a/lib/netdev.c
> +++ b/lib/netdev.c
> @@ -1246,7 +1246,8 @@ netdev_delete_queue(struct netdev *netdev, unsigned
> int queue_id)
>  /* Obtains statistics about 'queue_id' on 'netdev'.  On success, returns
> 0 and
>   * fills 'stats' with the queue's statistics; individual members of
> 'stats' may
>   * be set to all-1-bits if the statistic is unavailable.  On failure,
> returns a
> - * positive errno value and fills 'stats' with all-1-bits. */
> + * positive errno value and fills 'stats' with values indicating
> unsupported
> + * statistics. */
>  int
>  netdev_get_queue_stats(const struct netdev *netdev, unsigned int queue_id,
>                         struct netdev_queue_stats *stats)
> @@ -1258,7 +1259,10 @@ netdev_get_queue_stats(const struct netdev *netdev,
> unsigned int queue_id,
>                ? class->get_queue_stats(netdev, queue_id, stats)
>                : EOPNOTSUPP);
>      if (retval) {
> -        memset(stats, 0xff, sizeof *stats);
> +        stats->tx_bytes = UINT64_MAX;
> +        stats->tx_packets = UINT64_MAX;
> +        stats->tx_errors = UINT64_MAX;
> +        stats->created = LLONG_MIN;
>      }
>      return retval;
>  }
> diff --git a/lib/netdev.h b/lib/netdev.h
> index b1cc319..eb1870b 100644
> --- a/lib/netdev.h
> +++ b/lib/netdev.h
> @@ -227,6 +227,9 @@ struct netdev_queue_stats {
>      uint64_t tx_bytes;
>      uint64_t tx_packets;
>      uint64_t tx_errors;
> +
> +    /* Time at which the queue was created, in msecs, LLONG_MIN if
> unknown. */
> +    long long int created;
>  };
>
>  int netdev_set_policing(struct netdev *, uint32_t kbits_rate,
> diff --git a/lib/ofp-print.c b/lib/ofp-print.c
> index 76bd09c..aabb168 100644
> --- a/lib/ofp-print.c
> +++ b/lib/ofp-print.c
> @@ -1737,9 +1737,17 @@ ofp_print_ofpst_queue_reply(struct ds *string,
> const struct ofp_header *oh,
>          ofp_print_queue_name(string, qs.queue_id);
>          ds_put_cstr(string, ": ");
>
> -        print_port_stat(string, "bytes=", qs.stats.tx_bytes, 1);
> -        print_port_stat(string, "pkts=", qs.stats.tx_packets, 1);
> -        print_port_stat(string, "errors=", qs.stats.tx_errors, 0);
> +        print_port_stat(string, "bytes=", qs.tx_bytes, 1);
> +        print_port_stat(string, "pkts=", qs.tx_packets, 1);
> +        print_port_stat(string, "errors=", qs.tx_errors, 1);
> +
> +        ds_put_cstr(string, "duration=");
> +        if (qs.duration_sec != UINT32_MAX) {
> +            ofp_print_duration(string, qs.duration_sec, qs.duration_nsec);
> +        } else {
> +            ds_put_char(string, '?');
> +        }
> +        ds_put_char(string, '\n');
>      }
>  }
>
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index f1ba19c..95eb3e0 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -5400,9 +5400,10 @@ ofputil_queue_stats_from_ofp10(struct
> ofputil_queue_stats *oqs,
>  {
>      oqs->port_no = u16_to_ofp(ntohs(qs10->port_no));
>      oqs->queue_id = ntohl(qs10->queue_id);
> -    oqs->stats.tx_bytes = ntohll(get_32aligned_be64(&qs10->tx_bytes));
> -    oqs->stats.tx_packets = ntohll(get_32aligned_be64(&qs10->tx_packets));
> -    oqs->stats.tx_errors = ntohll(get_32aligned_be64(&qs10->tx_errors));
> +    oqs->tx_bytes = ntohll(get_32aligned_be64(&qs10->tx_bytes));
> +    oqs->tx_packets = ntohll(get_32aligned_be64(&qs10->tx_packets));
> +    oqs->tx_errors = ntohll(get_32aligned_be64(&qs10->tx_errors));
> +    oqs->duration_sec = oqs->duration_nsec = UINT32_MAX;
>
>      return 0;
>  }
> @@ -5419,9 +5420,10 @@ ofputil_queue_stats_from_ofp11(struct
> ofputil_queue_stats *oqs,
>      }
>
>      oqs->queue_id = ntohl(qs11->queue_id);
> -    oqs->stats.tx_bytes = ntohll(qs11->tx_bytes);
> -    oqs->stats.tx_packets = ntohll(qs11->tx_packets);
> -    oqs->stats.tx_errors = ntohll(qs11->tx_errors);
> +    oqs->tx_bytes = ntohll(qs11->tx_bytes);
> +    oqs->tx_packets = ntohll(qs11->tx_packets);
> +    oqs->tx_errors = ntohll(qs11->tx_errors);
> +    oqs->duration_sec = oqs->duration_nsec = UINT32_MAX;
>
>      return 0;
>  }
> @@ -5430,11 +5432,10 @@ static enum ofperr
>  ofputil_queue_stats_from_ofp13(struct ofputil_queue_stats *oqs,
>                                 const struct ofp13_queue_stats *qs13)
>  {
> -    enum ofperr error
> -        = ofputil_queue_stats_from_ofp11(oqs, &qs13->qs);
> +    enum ofperr error = ofputil_queue_stats_from_ofp11(oqs, &qs13->qs);
>      if (!error) {
> -        /* FIXME: Get qs13->duration_sec and qs13->duration_nsec,
> -         * Add to netdev_queue_stats? */
> +        oqs->duration_sec = ntohl(qs13->duration_sec);
> +        oqs->duration_nsec = ntohl(qs13->duration_nsec);
>      }
>
>      return error;
> @@ -5506,9 +5507,9 @@ ofputil_queue_stats_to_ofp10(const struct
> ofputil_queue_stats *oqs,
>      qs10->port_no = htons(ofp_to_u16(oqs->port_no));
>      memset(qs10->pad, 0, sizeof qs10->pad);
>      qs10->queue_id = htonl(oqs->queue_id);
> -    put_32aligned_be64(&qs10->tx_bytes, htonll(oqs->stats.tx_bytes));
> -    put_32aligned_be64(&qs10->tx_packets, htonll(oqs->stats.tx_packets));
> -    put_32aligned_be64(&qs10->tx_errors, htonll(oqs->stats.tx_errors));
> +    put_32aligned_be64(&qs10->tx_bytes, htonll(oqs->tx_bytes));
> +    put_32aligned_be64(&qs10->tx_packets, htonll(oqs->tx_packets));
> +    put_32aligned_be64(&qs10->tx_errors, htonll(oqs->tx_errors));
>  }
>
>  static void
> @@ -5517,9 +5518,9 @@ ofputil_queue_stats_to_ofp11(const struct
> ofputil_queue_stats *oqs,
>  {
>      qs11->port_no = ofputil_port_to_ofp11(oqs->port_no);
>      qs11->queue_id = htonl(oqs->queue_id);
> -    qs11->tx_bytes = htonll(oqs->stats.tx_bytes);
> -    qs11->tx_packets = htonll(oqs->stats.tx_packets);
> -    qs11->tx_errors = htonll(oqs->stats.tx_errors);
> +    qs11->tx_bytes = htonll(oqs->tx_bytes);
> +    qs11->tx_packets = htonll(oqs->tx_packets);
> +    qs11->tx_errors = htonll(oqs->tx_errors);
>  }
>
>  static void
> @@ -5527,10 +5528,13 @@ ofputil_queue_stats_to_ofp13(const struct
> ofputil_queue_stats *oqs,
>                               struct ofp13_queue_stats *qs13)
>  {
>      ofputil_queue_stats_to_ofp11(oqs, &qs13->qs);
> -    /* OF 1.3 adds duration fields */
> -    /* FIXME: Need to implement queue alive duration (sec + nsec) */
> -    qs13->duration_sec = htonl(~0);
> -    qs13->duration_nsec = htonl(~0);
> +    if (oqs->duration_sec != UINT32_MAX) {
> +        qs13->duration_sec = htonl(oqs->duration_sec);
> +        qs13->duration_nsec = htonl(oqs->duration_nsec);
> +    } else {
> +        qs13->duration_sec = htonl(UINT32_MAX);
> +        qs13->duration_nsec = htonl(UINT32_MAX);
> +    }
>  }
>
>  /* Encode a queue stat for 'oqs' and append it to 'replies'. */
> diff --git a/lib/ofp-util.h b/lib/ofp-util.h
> index 0385a57..f94982d 100644
> --- a/lib/ofp-util.h
> +++ b/lib/ofp-util.h
> @@ -832,7 +832,15 @@ ofputil_encode_queue_stats_request(enum ofp_version
> ofp_version,
>  struct ofputil_queue_stats {
>      ofp_port_t port_no;
>      uint32_t queue_id;
> -    struct netdev_queue_stats stats;
> +
> +    /* Values of unsupported statistics are set to all-1-bits
> (UINT64_MAX). */
> +    uint64_t tx_bytes;
> +    uint64_t tx_packets;
> +    uint64_t tx_errors;
> +
> +    /* UINT32_MAX if unknown. */
> +    uint32_t duration_sec;
> +    uint32_t duration_nsec;
>  };
>
>  size_t ofputil_count_queue_stats(const struct ofp_header *);
> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> index 3f4b8a7..98155ac 100644
> --- a/ofproto/ofproto.c
> +++ b/ofproto/ofproto.c
> @@ -3170,18 +3170,26 @@ handle_aggregate_stats_request(struct ofconn
> *ofconn,
>  struct queue_stats_cbdata {
>      struct ofport *ofport;
>      struct list replies;
> +    long long int now;
>  };
>
>  static void
>  put_queue_stats(struct queue_stats_cbdata *cbdata, uint32_t queue_id,
>                  const struct netdev_queue_stats *stats)
>  {
> +    struct ofputil_queue_stats oqs;
>
> -    struct ofputil_queue_stats oqs = {
> -        .port_no = cbdata->ofport->pp.port_no,
> -        .queue_id = queue_id,
> -        .stats = *stats,
> -    };
> +    oqs.port_no = cbdata->ofport->pp.port_no;
> +    oqs.queue_id = queue_id;
> +    oqs.tx_bytes = stats->tx_bytes;
> +    oqs.tx_packets = stats->tx_packets;
> +    oqs.tx_errors = stats->tx_errors;
> +    if (stats->created != LLONG_MIN) {
> +        calc_duration(stats->created, cbdata->now,
> +                      &oqs.duration_sec, &oqs.duration_nsec);
> +    } else {
> +        oqs.duration_sec = oqs.duration_nsec = UINT32_MAX;
> +    }
>      ofputil_append_queue_stat(&cbdata->replies, &oqs);
>  }
>
> @@ -3228,6 +3236,7 @@ handle_queue_stats_request(struct ofconn *ofconn,
>      COVERAGE_INC(ofproto_queue_req);
>
>      ofpmp_init(&cbdata.replies, rq);
> +    cbdata.now = time_msec();
>
>      error = ofputil_decode_queue_stats_request(rq, &oqsr);
>      if (error) {
> diff --git a/tests/ofp-print.at b/tests/ofp-print.at
> index 63a89ec..986b931 100644
> --- a/tests/ofp-print.at
> +++ b/tests/ofp-print.at
> @@ -1512,12 +1512,12 @@ AT_CHECK([ovs-ofctl ofp-print "\
>  00 00 00 00 00 00 00 00 00 00 00 00 \
>  "], [0], [dnl
>  OFPST_QUEUE reply (xid=0x1): 6 queues
> -  port 3 queue 1: bytes=302, pkts=1, errors=0
> -  port 3 queue 2: bytes=0, pkts=0, errors=0
> -  port 2 queue 1: bytes=2100, pkts=20, errors=0
> -  port 2 queue 2: bytes=0, pkts=0, errors=0
> -  port 1 queue 1: bytes=0, pkts=0, errors=0
> -  port 1 queue 2: bytes=0, pkts=0, errors=0
> +  port 3 queue 1: bytes=302, pkts=1, errors=0, duration=?
> +  port 3 queue 2: bytes=0, pkts=0, errors=0, duration=?
> +  port 2 queue 1: bytes=2100, pkts=20, errors=0, duration=?
> +  port 2 queue 2: bytes=0, pkts=0, errors=0, duration=?
> +  port 1 queue 1: bytes=0, pkts=0, errors=0, duration=?
> +  port 1 queue 2: bytes=0, pkts=0, errors=0, duration=?
>  ])
>  AT_CLEANUP
>
> @@ -1546,12 +1546,12 @@ AT_CHECK([ovs-ofctl ofp-print "\
>  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
>  "], [0], [dnl
>  OFPST_QUEUE reply (OF1.1) (xid=0x1): 6 queues
> -  port 3 queue 1: bytes=302, pkts=1, errors=0
> -  port 3 queue 2: bytes=0, pkts=0, errors=0
> -  port 2 queue 1: bytes=2100, pkts=20, errors=0
> -  port 2 queue 2: bytes=0, pkts=0, errors=0
> -  port 1 queue 1: bytes=0, pkts=0, errors=0
> -  port 1 queue 2: bytes=0, pkts=0, errors=0
> +  port 3 queue 1: bytes=302, pkts=1, errors=0, duration=?
> +  port 3 queue 2: bytes=0, pkts=0, errors=0, duration=?
> +  port 2 queue 1: bytes=2100, pkts=20, errors=0, duration=?
> +  port 2 queue 2: bytes=0, pkts=0, errors=0, duration=?
> +  port 1 queue 1: bytes=0, pkts=0, errors=0, duration=?
> +  port 1 queue 2: bytes=0, pkts=0, errors=0, duration=?
>  ])
>  AT_CLEANUP
>
> @@ -1573,12 +1573,14 @@ AT_CHECK([ovs-ofctl ofp-print "\
>  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
>  "], [0], [dnl
>  OFPST_QUEUE reply (OF1.2) (xid=0x1): 6 queues
> -  port 3 queue 1: bytes=302, pkts=1, errors=0
> -  port 3 queue 2: bytes=0, pkts=0, errors=0
> -  port 2 queue 1: bytes=2100, pkts=20, errors=0
> -  port 2 queue 2: bytes=0, pkts=0, errors=0
> -  port 1 queue 1: bytes=0, pkts=0, errors=0
> -  port 1 queue 2: bytes=0, pkts=0, errors=0
> +  port 3 queue 1: bytes=302, pkts=1, errors=0, duration=?
> +  port 3 queue 2: bytes=0, pkts=0, errors=0, duration=?
> +  port 2 queue 1: bytes=2100, pkts=20, errors=0, duration=?
> +  port 2 queue 2: bytes=0, pkts=0, errors=0, duration=?
> +  port 1 queue 1: bytes=0, pkts=0, errors=0, duration=?
> +  port 1 queue 2: bytes=0, pkts=0, errors=0, duration=?
> +])
> +AT_CLEANUP
>
>  AT_SETUP([OFPST_QUEUE reply - OF1.3])
>  AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
> @@ -1604,12 +1606,12 @@ AT_CHECK([ovs-ofctl ofp-print "\
>  ff ff ff ff ff ff ff ff \
>  "], [0], [dnl
>  OFPST_QUEUE reply (OF1.3) (xid=0x1): 6 queues
> -  port 3 queue 1: bytes=302, pkts=1, errors=0
> -  port 3 queue 2: bytes=0, pkts=0, errors=0
> -  port 2 queue 1: bytes=2100, pkts=20, errors=0
> -  port 2 queue 2: bytes=0, pkts=0, errors=0
> -  port 1 queue 1: bytes=0, pkts=0, errors=0
> -  port 1 queue 2: bytes=0, pkts=0, errors=0
> +  port 3 queue 1: bytes=302, pkts=1, errors=0, duration=100.5s
> +  port 3 queue 2: bytes=0, pkts=0, errors=0, duration=100.5s
> +  port 2 queue 1: bytes=2100, pkts=20, errors=0, duration=100.5s
> +  port 2 queue 2: bytes=0, pkts=0, errors=0, duration=100.5s
> +  port 1 queue 1: bytes=0, pkts=0, errors=0, duration=100.5s
> +  port 1 queue 2: bytes=0, pkts=0, errors=0, duration=?
>  ])
>  AT_CLEANUP
>
> --
> 1.7.10.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