On 2015-10-20 at 19:46:07 +0200, Vadim Kochan <vadi...@gmail.com> wrote:
> Calculate & print the rate of src/dst bytes & pkts.
> Also changed refresh flows time to 1s so the rate
> info will be not disappeared very soon.

Looks good to me in general and I like the idea. A few minor comments
below.

> Signed-off-by: Vadim Kochan <vadi...@gmail.com>
> ---
>  flowtop.c | 90 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 80 insertions(+), 10 deletions(-)
> 
> diff --git a/flowtop.c b/flowtop.c
> index 9df4bdb..c348e33 100644
> --- a/flowtop.c
> +++ b/flowtop.c
> @@ -19,6 +19,7 @@
>  #include <curses.h>
>  #include <dirent.h>
>  #include <sys/stat.h>
> +#include <sys/time.h>
>  #include <sys/fsuid.h>
>  #include <urcu.h>
>  #include <libgen.h>
> @@ -64,6 +65,11 @@ struct flow_entry {
>       unsigned int procnum;
>       bool is_visible;
>       struct nf_conntrack *ct;
> +     struct timeval last_update;
> +     double rate_bytes_src;
> +     double rate_bytes_dst;
> +     double rate_pkts_src;
> +     double rate_pkts_dst;
>  };
>  
>  struct flow_list {
> @@ -197,6 +203,18 @@ static const struct nfct_filter_ipv6 filter_ipv6 = {
>       .mask = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff },
>  };
>  
> +static double time_after_us(struct timeval *tv)

No need to return a double here. Make this an int64_t...

> +{
> +     struct timeval now;
> +
> +     gettimeofday(&now, NULL);
> +
> +     now.tv_sec  -= tv->tv_sec;
> +     now.tv_usec -= tv->tv_usec;
> +
> +     return (now.tv_sec * 1000000.0 + now.tv_usec);
> +}
> +
>  static void signal_handler(int number)
>  {
>       switch (number) {
> @@ -252,6 +270,28 @@ static void version(void)
>       die();
>  }
>  
> +static void flow_entry_update_time(struct flow_entry *n)
> +{
> +     gettimeofday(&n->last_update, NULL);
> +}
> +
> +static void flow_entry_calc_rate(struct flow_entry *n, struct nf_conntrack 
> *ct)
> +{
> +     uint64_t bytes_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_BYTES);
> +     uint64_t bytes_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_BYTES);
> +     uint64_t pkts_src  = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_PACKETS);
> +     uint64_t pkts_dst  = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_PACKETS);
> +     double sec         = time_after_us(&n->last_update) / 1000000.0;

...here it will become a double anyhow.

> +
> +     if (sec <= 0)
> +             return;
> +
> +     n->rate_bytes_src = (bytes_src - n->bytes_src) / sec;
> +     n->rate_bytes_dst = (bytes_dst - n->bytes_dst) / sec;
> +     n->rate_pkts_src  = (pkts_src  - n->pkts_src)  / sec;
> +     n->rate_pkts_dst  = (pkts_dst  - n->pkts_dst)  / sec;

I don't think we need the alignment here, it's readable enough without
the extra spaces.

> +}
> +
>  static inline struct flow_entry *flow_entry_xalloc(void)
>  {
>       return xzmalloc(sizeof(struct flow_entry));
> @@ -293,6 +333,7 @@ static void flow_list_new_entry(struct flow_list *fl, 
> struct nf_conntrack *ct)
>  
>       n->ct = nfct_clone(ct);
>  
> +     flow_entry_update_time(n);
>       flow_entry_from_ct(n, ct);
>       flow_entry_get_extended(n);
>  
> @@ -736,25 +777,48 @@ static uint16_t presenter_get_port(uint16_t src, 
> uint16_t dst, bool is_tcp)
>  static char *bandw2str(double bytes, char *buf, size_t len)
>  {
>       if (bytes > 1000000000.)
> -             snprintf(buf, len, "%.1fG", bytes / 1000000000.);
> +             snprintf(buf, len, "%.1fGb", bytes / 1000000000.);
>       else if (bytes > 1000000.)
> -             snprintf(buf, len, "%.1fM", bytes / 1000000.);
> +             snprintf(buf, len, "%.1fMb", bytes / 1000000.);
>       else if (bytes > 1000.)
> -             snprintf(buf, len, "%.1fK", bytes / 1000.);
> +             snprintf(buf, len, "%.1fKb", bytes / 1000.);
>       else
> -             snprintf(buf, len, "%g", bytes);
> +             snprintf(buf, len, "%g bytes", bytes);

Please split this change out into a separate preparatory patch as it is
not directly related to the rate change. This makes it easier to review
and bisect.

>  
>       return buf;
>  }
>  
> -static void presenter_print_counters(uint64_t bytes, uint64_t pkts, int 
> color)
> +static char *rate2str(double rate, char *buf, size_t len)
> +{
> +     if (rate > 1000000000.)
> +             snprintf(buf, len, "%.1fGb/s", rate / 1000000000.);
> +     else if (rate > 1000000.)
> +             snprintf(buf, len, "%.1fMb/s", rate / 1000000.);
> +     else if (rate > 1000.)
> +             snprintf(buf, len, "%.1fKb/s", rate / 1000.);
> +     else
> +             snprintf(buf, len, "%gB/s", rate);
> +
> +     return buf;
> +}
> +
> +static void presenter_print_counters(uint64_t bytes, uint64_t pkts,
> +                                  double rate_bytes, double rate_pkts,
> +                                  int color)
>  {
>       char bytes_str[64];
>  
>       printw(" -> (");
>       attron(COLOR_PAIR(color));
> -     printw("%"PRIu64" pkts, ", pkts);
> -     printw("%s bytes", bandw2str(bytes, bytes_str, sizeof(bytes_str) - 1));
> +     printw("%"PRIu64" pkts", pkts);
> +     if (rate_pkts) {
> +             printw("(%.1fpps)", rate_pkts);
> +     }

Omit the braces here.

> +     printw(", %s", bandw2str(bytes, bytes_str, sizeof(bytes_str) - 1));
> +     if (rate_bytes) {
> +             printw("(%s)", rate2str(rate_bytes, bytes_str,
> +                     sizeof(bytes_str) - 1));
> +     }

Same here.

>       attroff(COLOR_PAIR(color));
>       printw(")");
>  }
> @@ -872,7 +936,9 @@ static void presenter_screen_do_line(WINDOW *screen, 
> struct flow_entry *n,
>               }
>  
>               if (n->pkts_src > 0 && n->bytes_src > 0)
> -                     presenter_print_counters(n->bytes_src, n->pkts_src, 1);
> +                     presenter_print_counters(n->bytes_src, n->pkts_src,
> +                                              n->rate_bytes_src,
> +                                              n->rate_pkts_src, 1);
>  
>               printw(" => ");
>       }
> @@ -898,7 +964,9 @@ static void presenter_screen_do_line(WINDOW *screen, 
> struct flow_entry *n,
>       }
>  
>       if (n->pkts_dst > 0 && n->bytes_dst > 0)
> -             presenter_print_counters(n->bytes_dst, n->pkts_dst, 2);
> +             presenter_print_counters(n->bytes_dst, n->pkts_dst,
> +                                      n->rate_bytes_dst,
> +                                      n->rate_pkts_dst, 2);
>  }
>  
>  static inline bool presenter_flow_wrong_state(struct flow_entry *n)
> @@ -1176,6 +1244,8 @@ static int flow_update_cb(enum nf_conntrack_msg_type 
> type,
>       if (!n)
>               return NFCT_CB_CONTINUE;
>  
> +     flow_entry_calc_rate(n, ct);
> +     flow_entry_update_time(n);
>       flow_entry_from_ct(n, ct);
>  
>       return NFCT_CB_CONTINUE;
> @@ -1372,7 +1442,7 @@ static void *collector(void *null __maybe_unused)
>       while (!sigint) {
>               int status;
>  
> -             usleep(300000);
> +             usleep(1000000);
>  
>               collector_refresh_flows(ct_update);
>  
> -- 
> 2.4.2
> 

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to