summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-03-28 18:48:25 +0100
committerDaniel Borkmann <dborkman@redhat.com>2013-03-28 18:48:25 +0100
commit367efea8c9ba557a81158a69ecee267706a520eb (patch)
tree461ddf127e076a99d792e59006fd599ad1704c01
parentb55fde49e9f3e772b62e175cdbbec8f9fcc77567 (diff)
ring: purge timer before we unmap tx ring buffers
If we unmap TX ring buffers and still have timer shots that trigger the kernel to traverse the TX_RING, it can send out random crap in some situations. Prevent this by destroying the timer and flush the TX_RING first in wait mode. Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
-rw-r--r--netsniff-ng.c19
-rw-r--r--ring_rx.c2
-rw-r--r--ring_tx.c2
-rw-r--r--ring_tx.h5
-rw-r--r--trafgen.c20
5 files changed, 44 insertions, 4 deletions
diff --git a/netsniff-ng.c b/netsniff-ng.c
index 0f97acd..ecb9e9a 100644
--- a/netsniff-ng.c
+++ b/netsniff-ng.c
@@ -131,6 +131,21 @@ static void timer_elapsed(int unused)
setitimer(ITIMER_REAL, &itimer, NULL);
}
+static void timer_purge(void)
+{
+ int ret;
+
+ ret = pull_and_flush_tx_ring_wait(tx_sock);
+ if (unlikely(ret < 0)) {
+ if (errno != EBADF && errno != ENOBUFS)
+ panic("Flushing TX_RING failed: %s!\n", strerror(errno));
+ }
+
+ set_itimer_interval_value(&itimer, 0, 0);
+ setitimer(ITIMER_REAL, &itimer, NULL);
+}
+
+
static void timer_next_dump(int unused)
{
set_itimer_interval_value(&itimer, interval, 0);
@@ -289,6 +304,8 @@ static void pcap_to_xmit(struct ctx *ctx)
bug_on(gettimeofday(&end, NULL));
timersub(&end, &start, &diff);
+ timer_purge();
+
bpf_release(&bpf_ops);
dissector_cleanup_all();
@@ -455,6 +472,8 @@ static void receive_to_xmit(struct ctx *ctx)
out:
+ timer_purge();
+
sock_print_net_stats(rx_sock, 0);
bpf_release(&bpf_ops);
diff --git a/ring_rx.c b/ring_rx.c
index 5675a81..d89d762 100644
--- a/ring_rx.c
+++ b/ring_rx.c
@@ -30,7 +30,7 @@ void destroy_rx_ring(int sock, struct ring *ring)
ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->layout,
sizeof(ring->layout));
if (unlikely(ret))
- panic("Cannot destroy the RX_RING!\n");
+ panic("Cannot destroy the RX_RING: %s!\n", strerror(errno));
xfree(ring->frames);
}
diff --git a/ring_tx.c b/ring_tx.c
index 6804c43..2ad1de9 100644
--- a/ring_tx.c
+++ b/ring_tx.c
@@ -40,7 +40,7 @@ void destroy_tx_ring(int sock, struct ring *ring)
ret = setsockopt(sock, SOL_PACKET, PACKET_TX_RING, &ring->layout,
sizeof(ring->layout));
if (unlikely(ret))
- panic("Cannot destroy the TX_RING!\n");
+ panic("Cannot destroy the TX_RING: %s!\n", strerror(errno));
xfree(ring->frames);
}
diff --git a/ring_tx.h b/ring_tx.h
index 7970045..769f27e 100644
--- a/ring_tx.h
+++ b/ring_tx.h
@@ -37,4 +37,9 @@ static inline int pull_and_flush_tx_ring(int sock)
return sendto(sock, NULL, 0, MSG_DONTWAIT, NULL, 0);
}
+static inline int pull_and_flush_tx_ring_wait(int sock)
+{
+ return sendto(sock, NULL, 0, 0, NULL, 0);
+}
+
#endif /* TX_RING_H */
diff --git a/trafgen.c b/trafgen.c
index dc0c54b..fb41f45 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -127,11 +127,24 @@ static void signal_handler(int number)
static void timer_elapsed(int number)
{
- int ret;
+ int ret = pull_and_flush_tx_ring(sock);
+ if (unlikely(ret < 0)) {
+ /* We could hit EBADF if the socket has been closed before
+ * the timer was triggered.
+ */
+ if (errno != EBADF && errno != ENOBUFS)
+ panic("Flushing TX_RING failed: %s!\n", strerror(errno));
+ }
set_itimer_interval_value(&itimer, 0, interval);
+ setitimer(ITIMER_REAL, &itimer, NULL);
+}
- ret = pull_and_flush_tx_ring(sock);
+static void timer_purge(void)
+{
+ int ret;
+
+ ret = pull_and_flush_tx_ring_wait(sock);
if (unlikely(ret < 0)) {
/* We could hit EBADF if the socket has been closed before
* the timer was triggered.
@@ -140,6 +153,7 @@ static void timer_elapsed(int number)
panic("Flushing TX_RING failed: %s!\n", strerror(errno));
}
+ set_itimer_interval_value(&itimer, 0, 0);
setitimer(ITIMER_REAL, &itimer, NULL);
}
@@ -669,6 +683,8 @@ static void xmit_fastpath_or_die(struct ctx *ctx, int cpu, unsigned long orig_nu
bug_on(gettimeofday(&end, NULL));
timersub(&end, &start, &diff);
+ timer_purge();
+
destroy_tx_ring(sock, &tx_ring);
stats[cpu].tx_packets = tx_packets;