ring: purge timer before we unmap tx ring buffers
authorDaniel Borkmann <dborkman@redhat.com>
Thu, 28 Mar 2013 17:48:25 +0000 (28 18:48 +0100)
committerDaniel Borkmann <dborkman@redhat.com>
Thu, 28 Mar 2013 17:48:25 +0000 (28 18:48 +0100)
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>
netsniff-ng.c
ring_rx.c
ring_tx.c
ring_tx.h
trafgen.c

index 0f97acd..ecb9e9a 100644 (file)
@@ -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);
index 5675a81..d89d762 100644 (file)
--- 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);
 }
index 6804c43..2ad1de9 100644 (file)
--- 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);
 }
index 7970045..769f27e 100644 (file)
--- 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 */
index dc0c54b..fb41f45 100644 (file)
--- 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;