static void (*link_handler)(struct pkt *);
static struct pkt_stats stat_pcap_incomplete;
+static uns in_count, start_sec;
+
static int link_setup_handler(int dlt)
{
switch (dlt)
stat_pcap_incomplete.bytes += hdr->len - hdr->caplen;
return;
}
+ if (!(in_count % 1024))
+ {
+ if (!in_count)
+ start_sec = hdr->ts.tv_sec;
+ fprintf(stderr, "%d packets, %d seconds, %d conns (%d still open)\r",
+ in_count, (int)hdr->ts.tv_sec - start_sec,
+ tcp_total_flows, tcp_num_flows);
+ fflush(stderr);
+ }
+ in_count++;
struct pkt *p = pkt_new(0, hdr->len);
memcpy(pkt_append(p, hdr->len), pkt, hdr->len);
p->timestamp = (u64)hdr->ts.tv_sec * 1000000 + hdr->ts.tv_usec;
static byte *pipe_state_names[] = { "IDLE", "SYNSENT", "SYNACK", "ESTAB", "FINSENT", "FINISH" };
#endif
-static uns num_flows, max_flows;
+uns tcp_num_flows, tcp_max_flows;
static struct flow **flow_hash;
static struct flow **flow_heap;
daddr = (daddr >> 8) | (daddr << 24);
sport <<= 7;
dport <<= 21;
- return (saddr + daddr + sport + dport) % max_flows;
+ return (saddr + daddr + sport + dport) % tcp_max_flows;
}
#define FLOW_HEAP_LESS(a,b) (a->timeout < b->timeout)
static void flow_rehash(void)
{
- uns omax = max_flows;
+ uns omax = tcp_max_flows;
struct flow **ohash = flow_hash;
if (flow_heap)
xfree(flow_heap);
- if (max_flows)
- max_flows = nextprime(2*max_flows);
+ if (tcp_max_flows)
+ tcp_max_flows = nextprime(2*tcp_max_flows);
else
- max_flows = 3;
- // DBG("Rehashing to %d buckets\n", max_flows);
- flow_hash = xmalloc_zero(sizeof(struct flow *) * max_flows);
- flow_heap = xmalloc_zero(sizeof(struct flow *) * (max_flows+1));
- num_flows = 0;
+ tcp_max_flows = 3;
+ // DBG("Rehashing to %d buckets\n", tcp_max_flows);
+ flow_hash = xmalloc_zero(sizeof(struct flow *) * tcp_max_flows);
+ flow_heap = xmalloc_zero(sizeof(struct flow *) * (tcp_max_flows+1));
+ tcp_num_flows = 0;
for (uns i=0; i<omax; i++)
{
struct flow *f = ohash[i];
uns h = flow_calc_hash(f->saddr, f->daddr, f->sport, f->dport);
f->hash_next = flow_hash[h];
flow_hash[h] = f;
- flow_heap[++num_flows] = f;
- f->heap_pos = num_flows;
+ flow_heap[++tcp_num_flows] = f;
+ f->heap_pos = tcp_num_flows;
f = n;
}
}
if (ohash)
xfree(ohash);
- HEAP_INIT(struct flow *, flow_heap, num_flows, FLOW_HEAP_LESS, FLOW_HEAP_SWAP);
+ HEAP_INIT(struct flow *, flow_heap, tcp_num_flows, FLOW_HEAP_LESS, FLOW_HEAP_SWAP);
}
static struct flow *flow_lookup(u32 saddr, u32 daddr, u32 sport, u32 dport)
static struct flow *flow_create(u32 saddr, u32 daddr, u32 sport, u32 dport)
{
- if (num_flows >= max_flows)
+ if (tcp_num_flows >= tcp_max_flows)
flow_rehash();
uns h = flow_calc_hash(saddr, daddr, sport, dport);
struct flow *f = xmalloc_zero(sizeof(struct flow));
f->timeout = ~0U;
f->hash_next = flow_hash[h];
flow_hash[h] = f;
- flow_heap[++num_flows] = f;
- f->heap_pos = num_flows;
+ flow_heap[++tcp_num_flows] = f;
+ f->heap_pos = tcp_num_flows;
tcp_total_flows++;
return f;
}
static void flow_set_timeout(struct flow *f, u32 when)
{
f->timeout = when;
- HEAP_CHANGE(struct flow *, flow_heap, num_flows, FLOW_HEAP_LESS, FLOW_HEAP_SWAP, f->heap_pos);
+ HEAP_CHANGE(struct flow *, flow_heap, tcp_num_flows, FLOW_HEAP_LESS, FLOW_HEAP_SWAP, f->heap_pos);
}
static uns flow_now(struct pkt *p)
static void tcp_time_step(uns now)
{
- while (num_flows && flow_heap[1]->timeout <= now)
+ while (tcp_num_flows && flow_heap[1]->timeout <= now)
{
struct flow *f = flow_heap[1];
- HEAP_DELMIN(struct flow *, flow_heap, num_flows, FLOW_HEAP_LESS, FLOW_HEAP_SWAP);
+ HEAP_DELMIN(struct flow *, flow_heap, tcp_num_flows, FLOW_HEAP_LESS, FLOW_HEAP_SWAP);
DBG("TIMEOUT for flow %p(%s/%s)\n", f, pipe_state_names[f->pipe[0].state], pipe_state_names[f->pipe[1].state]);
if (f->pipe[0].state != FLOW_FINISHED || f->pipe[1].state != FLOW_FINISHED)
f->appl->close(f, (now == ~0U) ? CAUSE_DOOMSDAY : CAUSE_TIMEOUT, flow_now_to_time(now));
+ for (uns i=0; i<2; i++)
+ {
+ struct pkt *p;
+ while (p = list_head(&f->pipe[i].queue))
+ {
+ list_remove(&p->n);
+ pkt_free(p);
+ }
+ }
uns h = flow_calc_hash(f->saddr, f->daddr, f->sport, f->dport);
struct flow **gg = &flow_hash[h];
for(;;)
u32 last_seq;
DBG("DATA:");
- if (tcp_seq_lt(b->last_acked_seq, p->seq) && p->seq - b->last_acked_seq >= 0x40000)
+ if (tcp_seq_lt(b->queue_start_seq, p->seq) && p->seq - b->queue_start_seq >= 0x40000)
{
- DBG(" OUT OF WINDOW (last-ack=%u)\n", b->last_acked_seq);
+ DBG(" OUT OF WINDOW (q-start=%u)\n", b->queue_start_seq);
pkt_free(p);
return;
}