Commit c0ac27fb authored by robertdavidgraham's avatar robertdavidgraham
Browse files

fixes

parent 4cb17c28
Loading
Loading
Loading
Loading
+32 −3
Original line number Diff line number Diff line
@@ -2,6 +2,26 @@

    Event timeout

    This is for the user-mode TCP stack. We need to mark timeouts in the
    future when we'll re-visit a connection/tcb. For example, when we
    send a packet, we need to resend it in the future in case we don't
    get a response.

    This design creates a large "ring" of timeouts, and then cycles
    again and again through the ring. This is a fairly high granularity,
    just has hundreds, thousands, or 10 thousand entries per second.
    (I keep adjusting the granularity up and down). Not that at any
    slot in the ring, there may be entries from the far future.

    NOTE: a big feature of this system is that the structure that tracks
    the timeout is actually held within the TCB structure. In other
    words, each TCB can have one-and-only-one timeout.

    NOTE: a recurring bug is that the TCP code removes a TCB from the 
    timeout ring and forgets to put it back somewhere else. Since the
    TCB is cleaned up on a timeout, such TCBs never get cleaned up,
    leading to a memory leak. I keep fixing this bug, then changing the
    code and causing the bug to come back again.
*/
#include "event-timeout.h"
#include <stdint.h>
@@ -13,10 +33,21 @@
/***************************************************************************
 ***************************************************************************/
struct Timeouts {
    /**
     * This index is a monotonically increasing number, modulus the mask.
     * Every time we check timeouts, we simply move it foreward in time.
     */
    uint64_t current_index;

    /**
     * The number of slots is a power-of-2, so the mask is just this
     * number minus 1
     */
    unsigned mask;
    
    struct TimeoutEntry *freed_list;
    /**
     * The ring of entries.
     */
    struct TimeoutEntry *slots[1024*1024];
};

@@ -52,8 +83,6 @@ timeouts_add(struct Timeouts *timeouts, struct TimeoutEntry *entry,
    entry->timestamp = timestamp;
    entry->offset = (unsigned)offset;

    
    
    /* Link it into it's new location */
    index = timestamp & timeouts->mask;
    entry->next = timeouts->slots[index];
+21 −1
Original line number Diff line number Diff line
@@ -13,14 +13,26 @@ struct Timeouts;
 ***************************************************************************/
struct TimeoutEntry {
    /** 
     * In units of 1/10000 of a second
     * In units of 1/16384 of a second. We use power-of-two units here
     * to make the "modulus" operatation a simple binary "and".
     * See the TICKS_FROM_TV() macro for getting the timestamp from
     * the current time.
     */
    uint64_t timestamp;

    /** we build a doubly-linked list */
    struct TimeoutEntry *next;
    struct TimeoutEntry **prev;

    /** The timeout entry is never allocated by itself, but instead
     * lives inside another data structure. This stores the value of
     * 'offsetof()', so given a pointer to this structure, we can find
     * the original structure that contains it */
    unsigned offset;
};

/***************************************************************************
 ***************************************************************************/
static inline void
timeout_unlink(struct TimeoutEntry *entry)
{
@@ -34,6 +46,8 @@ timeout_unlink(struct TimeoutEntry *entry)
    entry->timestamp = 0;
}

/***************************************************************************
 ***************************************************************************/
static inline void
timeout_init(struct TimeoutEntry *entry)
{
@@ -49,7 +63,13 @@ void timeouts_add(struct Timeouts *timeouts, struct TimeoutEntry *entry,

void *timeouts_remove(struct Timeouts *timeouts, uint64_t timestamp);

/*
 * This macros convert a normal "timeval" structure into the timestamp
 * that we use for timeouts. The timeval structure probably will come
 * from the packets that we are capturing.
 */
#define TICKS_FROM_SECS(secs) ((secs)*16384ULL)
#define TICKS_FROM_USECS(usecs) ((usecs)/16384ULL)
#define TICKS_FROM_TV(secs,usecs) (TICKS_FROM_SECS(secs)+TICKS_FROM_USECS(usecs))

#endif
+2 −2
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ main_listscan(struct Masscan *masscan)
    end = range;
    if (masscan->resume.count && end > start + masscan->resume.count)
        end = start + masscan->resume.count;
    end += masscan->retries * masscan->max_rate;
    end += (uint64_t)(masscan->retries * masscan->max_rate);

    
    for (i=start; i<end; ) {
@@ -46,7 +46,7 @@ main_listscan(struct Masscan *masscan)
        unsigned port;
        
        
        xXx = (i + (r--) * masscan->max_rate);
        xXx = (i + (uint64_t)((r--) * masscan->max_rate));
        while (xXx >= range)
            xXx -= range;
        xXx = blackrock_shuffle(&blackrock,  xXx);
+25 −2
Original line number Diff line number Diff line
@@ -111,14 +111,37 @@ again:

        /* calculate waittime, in seconds */
        waittime = (current_rate - max_rate) / throttler->max_rate;

        /* At higher rates of speed, we don't actually need to wait the full
         * interval. It's better to have a much smaller interval, so that
         * we converge back on the true rate faster */
        waittime *= 0.1;

        /* This is in case of gross failure of the system. This should never
         * actually happen, unless there is a bug. Really, I ought to make
         * this an 'assert()' instead to fail and fix the bug rather than
         * silently continueing, but I'm too lazy */
        if (waittime > 0.1)
            waittime = 0.1;

        /* Since we've exceeded the speed limit, we should reduce the 
         * batch size slightly. We don't do it only by a little bit to
         * avoid over-correcting. We want to converge on the correct
         * speed gradually. Note that since this happens hundres or
         * thousands of times a second, the convergence is very fast
         * even with 0.1% adjustment */
        throttler->batch_size *= 0.999;

        /* Now we wait for a bit */
        pixie_usleep((uint64_t)(waittime * 1000000.0));

        throttler->batch_size *= 0.999;
        return (uint64_t)throttler->batch_size;
        /* There are two choices here. We could either return immediately,
         * or we can loop around again. Right now, the code loops around
         * again in order to support very slow rates, such as 0.5 packets
         * per second. Nobody would want to run a scanner that slowly of
         * course, but it's great for testing */
        //return (uint64_t)throttler->batch_size;
        goto again;
    }

    /*
+4 −4
Original line number Diff line number Diff line
@@ -221,7 +221,7 @@ transmit_thread(void *v) /*aka. scanning_thread() */
    uint64_t packets_sent = 0;
    unsigned increment = masscan->shard.of + masscan->nic_count;

    LOG(1, "xmit: starting transmit thread #%u\n", parms->my_index);
    LOG(1, "xmit: starting transmit thread #%u\n", parms->nic_index);

    /* Create the shuffler/randomizer. This creates the 'range' variable,
     * which is simply the number of IP addresses times the number of
@@ -360,7 +360,7 @@ transmit_thread(void *v) /*aka. scanning_thread() */

    /* Thread is about to exit */
    parms->done_transmitting = 1;
    LOG(1, "xmit: stopping transmit thread #%u\n", parms->my_index);
    LOG(1, "xmit: stopping transmit thread #%u\n", parms->nic_index);
}


@@ -404,7 +404,7 @@ receive_thread(void *v)
    struct TCP_ConnectionTable *tcpcon = 0;


    LOG(1, "recv: start receive thread#%u\n", parms->my_index);
    LOG(1, "recv: start receive thread #%u\n", parms->nic_index);

    /*
     * If configured, open a --pcap file for saving raw packets. This is
@@ -680,7 +680,7 @@ receive_thread(void *v)
    }


    LOG(1, "recv: end receive thread#%u\n", parms->my_index);
    LOG(1, "recv: end receive thread #%u\n", parms->nic_index);

    /*
     * cleanup
Loading