From 7fea0ec6f9c704a27db0c78c039bfd191f79d906 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Tue, 12 Apr 2016 11:46:43 +0200 Subject: [PATCH] af-packet: reset stats at start of capture We can loose packets during setup because we are reading nothing. So it is logical to discard the counter at start of capture to start from a clean state. This means we don't need to account the drop at start. But the stats call that will reset the drop counts will also return and reset the packets count. So we need to know how many packets we really have. This is in fact the number of packets coming from the stats call minus the number of discarded packets and the drop count. All the other packets will have to be read. --- src/source-af-packet.c | 70 ++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/src/source-af-packet.c b/src/source-af-packet.c index a993fddd70..7e1aa5444a 100644 --- a/src/source-af-packet.c +++ b/src/source-af-packet.c @@ -1113,7 +1113,8 @@ void AFPSwitchState(AFPThreadVars *ptv, int state) } } -static int AFPReadAndDiscard(AFPThreadVars *ptv, struct timeval *synctv) +static int AFPReadAndDiscard(AFPThreadVars *ptv, struct timeval *synctv, + uint64_t *discarded_pkts) { struct sockaddr_ll from; struct iovec iov; @@ -1155,7 +1156,8 @@ static int AFPReadAndDiscard(AFPThreadVars *ptv, struct timeval *synctv) return 0; } -static int AFPReadAndDiscardFromRing(AFPThreadVars *ptv, struct timeval *synctv) +static int AFPReadAndDiscardFromRing(AFPThreadVars *ptv, struct timeval *synctv, + uint64_t *discarded_pkts) { union thdr h; @@ -1163,26 +1165,30 @@ static int AFPReadAndDiscardFromRing(AFPThreadVars *ptv, struct timeval *synctv) return 1; } - /* Ignore system for tpacket_v3 */ if (ptv->flags & AFP_TPACKET_V3) { + struct tpacket_block_desc *pbd; + pbd = (struct tpacket_block_desc *) ptv->ring_v3[ptv->frame_offset].iov_base; + *discarded_pkts += pbd->hdr.bh1.num_pkts; + AFPFlushBlock(pbd); + ptv->frame_offset = (ptv->frame_offset + 1) % ptv->req3.tp_block_nr; return 1; - } - - /* Read packet from ring */ - h.raw = (((union thdr **)ptv->ring_v2)[ptv->frame_offset]); - if (h.raw == NULL) { - return -1; - } - - if (((time_t)h.h2->tp_sec > synctv->tv_sec) || - ((time_t)h.h2->tp_sec == synctv->tv_sec && - (suseconds_t) (h.h2->tp_nsec / 1000) > synctv->tv_usec)) { - return 1; - } + } else { + /* Read packet from ring */ + h.raw = (((union thdr **)ptv->ring_v2)[ptv->frame_offset]); + if (h.raw == NULL) { + return -1; + } + (*discarded_pkts)++; + if (((time_t)h.h2->tp_sec > synctv->tv_sec) || + ((time_t)h.h2->tp_sec == synctv->tv_sec && + (suseconds_t) (h.h2->tp_nsec / 1000) > synctv->tv_usec)) { + return 1; + } - h.h2->tp_status = TP_STATUS_KERNEL; - if (++ptv->frame_offset >= ptv->req.tp_frame_nr) { - ptv->frame_offset = 0; + h.h2->tp_status = TP_STATUS_KERNEL; + if (++ptv->frame_offset >= ptv->req.tp_frame_nr) { + ptv->frame_offset = 0; + } } @@ -1198,7 +1204,7 @@ static int AFPReadAndDiscardFromRing(AFPThreadVars *ptv, struct timeval *synctv) * * \retval r 1 = happy, otherwise unhappy */ -static int AFPSynchronizeStart(AFPThreadVars *ptv) +static int AFPSynchronizeStart(AFPThreadVars *ptv, uint64_t *discarded_pkts) { int r; struct timeval synctv; @@ -1223,9 +1229,9 @@ static int AFPSynchronizeStart(AFPThreadVars *ptv) gettimeofday(&synctv, NULL); } if (ptv->flags & AFP_RING_MODE) { - r = AFPReadAndDiscardFromRing(ptv, &synctv); + r = AFPReadAndDiscardFromRing(ptv, &synctv, discarded_pkts); } else { - r = AFPReadAndDiscard(ptv, &synctv); + r = AFPReadAndDiscard(ptv, &synctv, discarded_pkts); } SCLogDebug("Discarding on %s", ptv->tv->name); switch (r) { @@ -1292,6 +1298,7 @@ TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot) time_t last_dump = 0; struct timeval current_time; int (*AFPReadFunc) (AFPThreadVars *); + uint64_t discarded_pkts = 0; ptv->slot = s->slot_next; @@ -1331,8 +1338,25 @@ TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot) if (ptv->afp_state == AFP_STATE_UP) { SCLogDebug("Thread %s using socket %d", tv->name, ptv->socket); if ((ptv->flags & AFP_TPACKET_V3) != 0) { - AFPSynchronizeStart(ptv); + AFPSynchronizeStart(ptv, &discarded_pkts); } + /* let's reset counter as we will start the capture at the + * next function call */ +#ifdef PACKET_STATISTICS + struct tpacket_stats kstats; + socklen_t len = sizeof (struct tpacket_stats); + if (getsockopt(ptv->socket, SOL_PACKET, PACKET_STATISTICS, + &kstats, &len) > -1) { + uint64_t pkts = 0; + SCLogDebug("(%s) Kernel socket startup: Packets %" PRIu32 + ", dropped %" PRIu32 "", + ptv->tv->name, + kstats.tp_packets, kstats.tp_drops); + pkts = kstats.tp_packets - discarded_pkts - kstats.tp_drops; + StatsAddUI64(ptv->tv, ptv->capture_kernel_packets, pkts); + (void) SC_ATOMIC_ADD(ptv->livedev->pkts, pkts); + } +#endif } fds.fd = ptv->socket; -- 2.47.2