Ignore:
Timestamp:
02/18/15 17:41:48 (6 years ago)
Author:
Richard Sanger <rsangerarj@…>
Branches:
4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
Children:
e4f27d1
Parents:
8bcc925
Message:

Deprecate trace_get_filtered/accepted/recevied/dropped() in favour of a single function

Adds the single trace_get_statistics function. This allows the structure to be filled
at a point in time, rather than making multiple calls to the library during which state
might have changed.

This has been designed such that the structure can be added to in the future without
breaking old code.

The old internal get_captured_packets was removed from the formats as it was never used.
Eventually we should completely remove get_filtered and received from the formats and replace
them with get_statistics.

In additon some extra fields have added, such as error and captured and the pre-existing
fields are better defined.

The linux formats have been updated to use this new API, which combined with reading
/proc/net/dev returns a full set of statistics.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/format_linux_common.c

    red6304c5 r5ab626a  
    186186        FORMAT_DATA->filter = NULL;
    187187        FORMAT_DATA->stats_valid = 0;
     188        FORMAT_DATA->stats.tp_drops = 0;
     189        FORMAT_DATA->stats.tp_packets = 0;
    188190        FORMAT_DATA->max_order = MAX_ORDER;
    189191        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
     
    253255                             tmp_stats.if_name,
    254256                             &tmp_stats.rx_bytes,
    255                              &tmp_stats.rx_bytes,
     257                             &tmp_stats.rx_packets,
    256258                             &tmp_stats.rx_errors,
    257259                             &tmp_stats.rx_drops,
     
    402404                               sizeof(filter->filter)) == -1) {
    403405                        perror("setsockopt(SO_ATTACH_FILTER)");
    404                 } else {
    405                         /* The socket accepted the filter, so we need to
    406                          * consume any buffered packets that were received
    407                          * between opening the socket and applying the filter.
    408                          */
    409                         void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
    410                         while(recv(stream->fd,
    411                                    buf,
    412                                    (size_t)LIBTRACE_PACKET_BUFSIZE,
    413                                    MSG_DONTWAIT) != -1) { }
    414                         free(buf);
    415                 }
    416         }
    417 
    418         FORMAT_DATA->stats_valid = 0;
     406                }
     407        }
     408
     409        /* Consume any buffered packets that were received before the socket
     410         * was properly setup, including those which missed the filter and
     411         * bind()ing to an interface.
     412         *
     413         * If packet rate is high this could therotically hang forever. 4K
     414         * should be a large enough limit.
     415         */
     416        int count = 0;
     417        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
     418        while(count < 4096 &&
     419                recv(stream->fd,
     420                   buf,
     421                   (size_t)LIBTRACE_PACKET_BUFSIZE,
     422                   MSG_DONTWAIT) != -1) { count++; }
     423        free(buf);
     424        fprintf(stderr, "set offset %d", count);
     425
     426        /* Mark that the stats are valid and apply an offset */
     427        FORMAT_DATA->stats_valid = 1;
     428        /* Offset by number we ate for each stream */
     429        FORMAT_DATA->stats.tp_packets -= count;
     430
     431
    419432        if (linuxcommon_get_dev_statisitics(libtrace, &FORMAT_DATA->dev_stats) != 0) {
    420433                /* Mark this as bad */
     
    561574}
    562575
    563 /* Number of packets that passed filtering */
    564 uint64_t linuxcommon_get_captured_packets(libtrace_t *libtrace) {
     576#define DEV_DIFF(x) (dev_stats.x - FORMAT_DATA->dev_stats.x)
     577/* Note these statistics come from two different sources, the socket itself and
     578 * the linux device. As such this means it is highly likely that their is some
     579 * margin of error in the returned statisitics, we perform basic sanitising so
     580 * that these are not too noticable.
     581 */
     582void linuxcommon_get_statistics(libtrace_t *libtrace, libtrace_stat_t *stat) {
     583        struct linux_dev_stats dev_stats;
    565584        if (libtrace->format_data == NULL)
    566                 return UINT64_MAX;
     585                return;
     586        /* Do we need to consider the case after the trace is closed? */
    567587        if (FORMAT_DATA_FIRST->fd == -1) {
    568588                /* This is probably a 'dead' trace so obviously we can't query
    569589                 * the socket for capture counts, can we? */
    570                 return UINT64_MAX;
     590                return;
     591        }
     592
     593        dev_stats.if_name[0] = 0; /* This will be set if we retrive valid stats */
     594        /* Do we have starting stats to compare to? */
     595        if (FORMAT_DATA->dev_stats.if_name[0] != 0) {
     596                linuxcommon_get_dev_statisitics(libtrace, &dev_stats);
    571597        }
    572598        linuxcommon_update_socket_statistics(libtrace);
    573         if (FORMAT_DATA->stats_valid)
    574                 return FORMAT_DATA->stats.tp_packets;
    575         else
    576                 return UINT64_MAX;
    577 }
    578 
    579 /* Number of packets that got past filtering and were then dropped because
    580  * of lack of space.
    581  *
    582  * We could also try read from /sys/class/net/ethX/statistics/ to get
    583  * real drop counters and stuff.
    584  */
    585 uint64_t linuxcommon_get_dropped_packets(libtrace_t *libtrace) {
    586         struct linux_dev_stats dev_stats;
    587         uint64_t adjustment = 0;
    588         if (libtrace->format_data == NULL)
    589                 return UINT64_MAX;
    590         if (FORMAT_DATA_FIRST->fd == -1) {
    591                 /* This is probably a 'dead' trace so obviously we can't query
    592                  * the socket for drop counts, can we? */
    593                 return UINT64_MAX;
    594         }
    595         // Do we have starting stats to compare to?
    596         if (FORMAT_DATA->dev_stats.if_name[0] != 0) {
    597                 if (linuxcommon_get_dev_statisitics(libtrace, &dev_stats) == 0) {
    598                         adjustment = dev_stats.rx_drops - FORMAT_DATA->dev_stats.rx_drops;
    599                 }
    600         }
    601         linuxcommon_update_socket_statistics(libtrace);
    602         if (FORMAT_DATA->stats_valid)
    603                 return FORMAT_DATA->stats.tp_drops + adjustment;
    604         else
    605                 return UINT64_MAX;
    606 }
    607 
    608 /* Linux doesn't keep track how many packets were seen before filtering
    609  * so we can't tell how many packets were filtered.  Bugger.  So annoying.
    610  *
    611  * Since we tell libtrace that we do support filtering, if we don't declare
    612  * this here as failing, libtrace will happily report for us that it didn't
    613  * filter any packets, so don't lie -- return that we don't know.
    614  */
    615 uint64_t linuxcommon_get_filtered_packets(libtrace_t *trace UNUSED) {
    616         return UINT64_MAX;
     599
     600        /* filtered count == dev received - socket received */
     601        if (FORMAT_DATA->filter == NULL) {
     602                stat->filtered_valid = 1;
     603                stat->filtered = 0;
     604        } else if (FORMAT_DATA->stats_valid && dev_stats.if_name[0]) {
     605                stat->filtered_valid = 1;
     606                stat->filtered = DEV_DIFF(rx_packets) -
     607                                 FORMAT_DATA->stats.tp_packets;
     608                if (stat->filtered > UINT64_MAX - 100000) {
     609                        stat->filtered = 0;
     610                }
     611        }
     612
     613        /* dropped count == socket dropped + dev dropped */
     614        if (FORMAT_DATA->stats_valid) {
     615                stat->dropped_valid = 1;
     616                stat->dropped = FORMAT_DATA->stats.tp_drops;
     617                if (dev_stats.if_name[0]) {
     618                        stat->dropped += DEV_DIFF(rx_drops);
     619                }
     620        }
     621
     622        /* received count - All good packets even those dropped or filtered */
     623        if (dev_stats.if_name[0]) {
     624                stat->received_valid = 1;
     625                stat->received = DEV_DIFF(rx_packets) + DEV_DIFF(rx_drops);
     626        }
     627
     628        /* captured count - received and but not dropped */
     629        if (dev_stats.if_name[0] && FORMAT_DATA->stats_valid) {
     630                stat->captured_valid = 1;
     631                stat->captured = DEV_DIFF(rx_packets) - FORMAT_DATA->stats.tp_drops;
     632        }
     633
     634        /* errors */
     635        if (dev_stats.if_name[0]) {
     636                stat->errors_valid = 1;
     637                stat->errors = DEV_DIFF(rx_errors);
     638        }
     639
    617640}
    618641
     
    671694
    672695/* No NETPACKET - So this format is not live */
    673 uint64_t linuxcommon_get_filtered_packets(libtrace_t *trace UNUSED) {
    674         return UINT64_MAX;
    675 }
    676 
    677 uint64_t linuxcommon_get_captured_packets(libtrace_t *trace UNUSED) {
    678         return UINT64_MAX;
    679 }
    680 
    681 uint64_t linuxcommon_get_dropped_packets(libtrace_t *trace UNUSED) {
    682         return UINT64_MAX;
     696void linuxcommon_get_statistics(libtrace_t *libtrace UNUSED,
     697                                libtrace_stat_t *stat UNUSED) {
     698        return;
    683699}
    684700
Note: See TracChangeset for help on using the changeset viewer.