summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ring.h4
-rw-r--r--ring_rx.c53
2 files changed, 45 insertions, 12 deletions
diff --git a/ring.h b/ring.h
index 3b02c76..afc8b08 100644
--- a/ring.h
+++ b/ring.h
@@ -145,6 +145,10 @@ static inline void set_sockopt_tpacket_v3(int sock)
{
__set_sockopt_tpacket(sock, TPACKET_V3);
}
+#else
+static inline void set_sockopt_tpacket_v3(int sock __maybe_unused)
+{
+}
#endif
static inline int get_sockopt_tpacket(int sock)
diff --git a/ring_rx.c b/ring_rx.c
index 6f130ee..8ad64d1 100644
--- a/ring_rx.c
+++ b/ring_rx.c
@@ -21,6 +21,10 @@
#include "ring_rx.h"
#include "built_in.h"
+/*
+ * tpacket v3 data structures and constants are not available for older kernel
+ * versions which only support tpacket v2, thus we need protect access to them.
+ */
#ifdef HAVE_TPACKET3
static inline bool is_tpacket_v3(int sock)
{
@@ -54,6 +58,24 @@ static inline size_t rx_ring_get_size(struct ring *ring, bool v3)
{
return v3 ? ring->layout3.tp_block_size : ring->layout.tp_frame_size;
}
+
+static int get_rx_net_stats(int sock, uint64_t *packets, uint64_t *drops, bool v3)
+{
+ int ret;
+ union {
+ struct tpacket_stats k2;
+ struct tpacket_stats_v3 k3;
+ } stats;
+ socklen_t slen = v3 ? sizeof(stats.k3) : sizeof(stats.k2);
+
+ memset(&stats, 0, sizeof(stats));
+ ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &stats, &slen);
+ if (ret == 0) {
+ *packets = stats.k3.tp_packets;
+ *drops = stats.k3.tp_drops;
+ }
+ return ret;
+}
#else
static inline bool is_tpacket_v3(int sock __maybe_unused)
{
@@ -78,6 +100,21 @@ static inline size_t rx_ring_get_size(struct ring *ring, bool v3 __maybe_unused)
{
return ring->layout.tp_frame_size;
}
+
+static int get_rx_net_stats(int sock, uint64_t *packets, uint64_t *drops, bool v3 __maybe_unused)
+{
+ int ret;
+ struct tpacket_stats stats;
+ socklen_t slen = sizeof(stats);
+
+ memset(&stats, 0, sizeof(stats));
+ ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &stats, &slen);
+ if (ret == 0) {
+ *packets = stats.tp_packets;
+ *drops = stats.tp_drops;
+ }
+ return ret;
+}
#endif /* HAVE_TPACKET3 */
void destroy_rx_ring(int sock, struct ring *ring)
@@ -188,24 +225,16 @@ void ring_rx_setup(struct ring *ring, int sock, size_t size, int ifindex,
void sock_rx_net_stats(int sock, unsigned long seen)
{
int ret;
+ uint64_t packets, drops;
bool v3 = is_tpacket_v3(sock);
- union {
- struct tpacket_stats k2;
- struct tpacket_stats_v3 k3;
- } stats;
- socklen_t slen = v3 ? sizeof(stats.k3) : sizeof(stats.k2);
-
- memset(&stats, 0, sizeof(stats));
- ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &stats, &slen);
- if (ret > -1) {
- uint64_t packets = stats.k3.tp_packets;
- uint64_t drops = stats.k3.tp_drops;
+ ret = get_rx_net_stats(sock, &packets, &drops, v3);
+ if (ret == 0) {
printf("\r%12"PRIu64" packets incoming (%"PRIu64" unread on exit)\n",
v3 ? (uint64_t)seen : packets, v3 ? packets - seen : 0);
printf("\r%12"PRIu64" packets passed filter\n", packets - drops);
printf("\r%12"PRIu64" packets failed filter (out of space)\n", drops);
- if (stats.k3.tp_packets > 0)
+ if (packets > 0)
printf("\r%12.4lf%% packet droprate\n",
(1.0 * drops / packets) * 100.0);
}