M ip/devip.c => ip/devip.c +6 -3
@@ 916,11 916,14 @@ Fspcolstats(char *buf, int len)
int n;
n = 0;
- for(p = fs.p; *p; p++)
+ for(p = fs.p; *p; p++){
n += snprint(buf + n, len - n,
- "%s: csum %d hlen %d len %d order %d rexmit %d wc %d\n",
+ "%s: csum %d hlen %d len %d order %d rexmit %d\n",
(*p)->name, (*p)->csumerr, (*p)->hlenerr, (*p)->lenerr,
- (*p)->order, (*p)->rexmit, (*p)->wclosed);
+ (*p)->order, (*p)->rexmit);
+ if((*p)->stats)
+ n += (*(*p)->stats)(buf + n, len - n);
+ }
return n;
}
M ip/icmp.c => ip/icmp.c +31 -0
@@ 36,6 36,8 @@ enum { /* Packet Types */
TimestampReply = 14,
InfoRequest = 15,
InfoReply = 16,
+
+ Maxtype = 16,
};
enum {
@@ 47,6 49,12 @@ enum {
Proto icmp;
extern Fs fs;
+static struct Icmpstats
+{
+ ulong in[Maxtype+1];
+ ulong out[Maxtype+1];
+} stats;
+
static char*
icmpconnect(Conv *c, char **argv, int argc)
{
@@ 112,6 120,8 @@ icmpkick(Conv *c, int l)
return;
}
p = (Icmp *)(bp->rp);
+ if(p->type <= Maxtype)
+ stats.out[p->type]++;
hnputl(p->dst, c->raddr);
hnputl(p->src, c->laddr);
p->proto = IP_ICMPPROTO;
@@ 141,6 151,7 @@ icmpnoconv(Block *bp)
hnputs(np->seq, 0);
memset(np->cksum, 0, sizeof(np->cksum));
hnputs(np->cksum, ptclcsum(nbp, ICMP_IPSIZE, blocklen(nbp) - ICMP_IPSIZE));
+ stats.out[Unreachable]++;
ipoput(nbp, 0, MAXTTL);
}
@@ 221,9 232,12 @@ icmpiput(Media *m, Block *bp)
icmp.csumerr++;
goto raise;
}
+ if(p->type <= Maxtype)
+ stats.in[p->type]++;
switch(p->type) {
case EchoRequest:
r = mkechoreply(bp);
+ stats.out[EchoReply]++;
ipoput(r, 0, MAXTTL);
break;
case Unreachable:
@@ 299,6 313,22 @@ icmpadvise(Block *bp, char *msg)
freeblist(bp);
}
+int
+icmpstats(char *buf, int len)
+{
+ int i, n;
+
+ n = snprint(buf, len, "\trcvd ");
+ for(i = 0; i < Maxtype && len > n; i++)
+ n += snprint(buf+n, len-n, " %d", stats.in[i]);
+ n += snprint(buf+n, len - n, "\n\tsent ");
+ for(i = 0; i < Maxtype && len > n; i++)
+ n += snprint(buf+n, len-n, " %d", stats.out[i]);
+ if(n < len)
+ n += snprint(buf+n, len-n, "\n");
+ return n;
+}
+
void
icmpinit(Fs *fs)
{
@@ 310,6 340,7 @@ icmpinit(Fs *fs)
icmp.create = icmpcreate;
icmp.close = icmpclose;
icmp.rcv = icmpiput;
+ icmp.stats = icmpstats;
icmp.ctl = nil;
icmp.advise = icmpadvise;
icmp.ipproto = IP_ICMPPROTO;
M ip/igmp.c => ip/igmp.c +20 -0
@@ 68,6 68,14 @@ IGMP igmpalloc;
Proto igmp;
extern Fs fs;
+static struct Stats
+{
+ ulong inqueries;
+ ulong outqueries;
+ ulong inreports;
+ ulong outreports;
+} stats;
+
void
igmpsendreport(Media *m, byte *addr)
{
@@ 87,6 95,7 @@ igmpsendreport(Media *m, byte *addr)
memmove(p->group, addr, IPaddrlen);
hnputs(p->igmpcksum, ptclcsum(bp, IGMP_IPHDRSIZE, IGMP_HDRSIZE));
netlog(Logigmp, "igmpreport %I\n", p->group);
+ stats.outreports++;
ipoput(bp, 0, 1); /* TTL of 1 */
}
@@ 190,6 199,7 @@ igmpiput(Media *m, Block *bp)
/*
* start reporting groups that we're a member of.
*/
+ stats.inqueries++;
for(rp = igmpalloc.reports; rp; rp = rp->next)
if(rp->m == m)
break;
@@ 219,6 229,7 @@ igmpiput(Media *m, Block *bp)
/*
* find report list for this medium
*/
+ stats.inreports++;
lrp = &igmpalloc.reports;
for(rp = *lrp; rp; rp = *lrp){
if(rp->m == m)
@@ 250,6 261,14 @@ error:
freeb(bp);
}
+int
+igmpstats(char *buf, int len)
+{
+ return snprint(buf, len, "\trcvd %d %d\n\tsent %d %d\n",
+ stats.inqueries, stats.inreports,
+ stats.outqueries, stats.outreports);
+}
+
void
igmpinit(Fs *fs)
{
@@ 261,6 280,7 @@ igmpinit(Fs *fs)
igmp.state = nil;
igmp.close = nil;
igmp.rcv = igmpiput;
+ igmp.stats = igmpstats;
igmp.ipproto = IP_IGMPPROTO;
igmp.nc = 0;
igmp.ptclsize = 0;
M ip/il.c => ip/il.c +18 -1
@@ 122,6 122,12 @@ struct Ilhdr
byte ilack[4]; /* Acked sequence */
};
+static struct Ilstats
+{
+ ulong dup;
+ ulong dupb;
+} ilstats;
+
/* Always Acktime < Fasttime < Slowtime << Ackkeepalive */
enum
{
@@ 329,6 335,12 @@ ilcreate(Conv *c)
c->wq = qopen(64*1024, 0, 0, 0);
}
+int
+ilxstats(char *buf, int len)
+{
+ return snprint(buf, len, "\tdupp %d dupb %d\n", ilstats.dup, ilstats.dupb);
+}
+
void
ilinit(Fs *fs)
{
@@ 342,6 354,7 @@ ilinit(Fs *fs)
il.rcv = iliput;
il.ctl = nil;
il.advise = iladvise;
+ il.stats = ilxstats;
il.ipproto = IP_ILPROTO;
il.nc = Nchans;
il.ptclsize = sizeof(Ilcb);
@@ 819,8 832,10 @@ ilpullup(Conv *s)
freeblist(bp);
continue;
}
- if(oid != ic->recvd+1)
+ if(oid != ic->recvd+1){
+ il.order++;
break;
+ }
ic->recvd = oid;
ic->outoforder = bp->list;
@@ 871,6 886,8 @@ iloutoforder(Conv *s, Ilhdr *h, Block *bp)
newid = nhgetl(lid);
if(id <= newid) {
if(id == newid) {
+ ilstats.dup++;
+ ilstats.dupb += blocklen(bp);
qunlock(&ic->outo);
freeblist(bp);
return;
M ip/ip.c => ip/ip.c +12 -1
@@ 67,6 67,12 @@ ulong ipout, ippout; /* bytes, packets out */
*/
#define BKFG(xp) ((Ipfrag*)((xp)->base))
+static struct Stats
+{
+ ulong noroute;
+ ulong droppedfrag;
+} stats;
+
ushort ipcsum(byte*);
Block* ipreassemble(int, Block*, Iphdr*);
void ipfragfree(Fragment*);
@@ 109,6 115,7 @@ ipoput(Block *bp, int gating, int ttl)
} else
m = Mediaroute(eh->dst, gate);
if(m == nil){
+ stats.noroute++;
netlog(Logip, "no interface %I\n", eh->dst);
goto raise;
}
@@ 307,6 314,8 @@ ipstats(char *buf, int len)
n = snprint(buf, len, "ip: csum %lud inb %lud outb %lud inp %lud outp %lud\n",
ipcsumerr, ipin, ipout, ippin, ippout);
+ n += snprint(buf+n, len - n, "\tnoroute %lud droppedfrag %lud\n",
+ stats.noroute, stats.droppedfrag);
return n;
}
@@ 341,8 350,10 @@ ipreassemble(int offset, Block *bp, Iphdr *ip)
fnext = f->next; /* because ipfragfree changes the list */
if(f->src == src && f->dst == dst && f->id == id)
break;
- if(f->age < msec)
+ if(f->age < msec){
+ stats.droppedfrag++;
ipfragfree(f);
+ }
}
/*
M ip/ip.h => ip/ip.h +1 -1
@@ 169,6 169,7 @@ struct Proto
void (*rcv)(Media*, Block*);
char* (*ctl)(Conv*, char**, int);
void (*advise)(Block*, char*);
+ int (*stats)(char*, int);
Conv **conv; /* array of conversations */
int ptclsize; /* size of per protocol ctl block */
@@ 183,7 184,6 @@ struct Proto
ulong lenerr; /* short packet */
ulong order; /* out of order */
ulong rexmit; /* retransmissions */
- ulong wclosed; /* window closed */
};
struct Fs
M ip/tcp.c => ip/tcp.c +16 -1
@@ 186,6 186,12 @@ ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */
Timer *timers; /* List of active timers */
QLock tl; /* Protect timer list */
+static struct Tcpstats
+{
+ ulong dup; /* (partially) duplicated packets */
+ ulong dupb; /* duplicated bytes */
+} tstats;
+
void addreseq(Tcpctl*, Tcp*, Block*, ushort);
void getreseq(Tcpctl*, Tcp*, Block**, ushort*);
void localclose(Conv*, char*);
@@ 1250,6 1256,7 @@ tcpiput(Media *m, Block *bp)
if(seg.seq != tcb->rcv.nxt)
if(length != 0 || (seg.flags & (SYN|FIN))) {
update(s, &seg);
+ tcp.order++;
addreseq(tcb, &seg, bp, length);
tcb->flags |= FORCE;
goto output;
@@ 1469,7 1476,6 @@ tcpoutput(Conv *s)
* window probes to one
*/
if(tcb->snd.wnd == 0){
- tcp.wclosed++;
if(sent != 0) {
if ((tcb->flags&FORCE) == 0)
break;
@@ 1846,6 1852,8 @@ tcptrim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length)
dupcnt = tcb->rcv.nxt - seg->seq;
if(dupcnt > 0){
tcb->rerecv += dupcnt;
+ tstats.dup++;
+ tstats.dupb += dupcnt;
if(seg->flags & SYN){
seg->flags &= ~SYN;
seg->seq++;
@@ 1924,6 1932,12 @@ tcpctl(Conv* c, char** f, int n)
return "unknown control request";
}
+int
+tcpstats(char *buf, int len)
+{
+ return snprint(buf, len, "\tdupp %d dupb %d\n", tstats.dup, tstats.dupb);
+}
+
void
tcpinit(Fs *fs)
{
@@ 1937,6 1951,7 @@ tcpinit(Fs *fs)
tcp.close = tcpclose;
tcp.rcv = tcpiput;
tcp.advise = tcpadvise;
+ tcp.stats = tcpstats;
tcp.ipproto = IP_TCPPROTO;
tcp.nc = Nchans;
tcp.ptclsize = sizeof(Tcpctl);