/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <ctype.h>#include <auth.h>#include <fcall.h>#include <draw.h>#include <event.h>#include <ip.h>#include "icmp.h" #define MAXNUM 8 /* maximum number of numbers on data line */ typedef struct Graph Graph;typedef struct Machine Machine;typedef struct Req Req; enum { Gmsglen = 16,}; struct Graph{ int colindex; Rectangle r; long *data; int ndata; char *label; void (*newvalue)(Machine*, long*, long*, long*); void (*update)(Graph*, long, long, long); Machine *mach; int overflow; Image *overtmp; int overtmplen; char msg[Gmsglen]; int cursor; int vmax;}; enum{ MSGLEN = 64, Rttmax = 50,}; struct Req{ int seq; /* sequence number */ vlong time; /* time sent */// int rtt; Req *next;}; struct Machine{ Lock; char *name; int pingfd; int nproc; int rttmsgs; ulong rttsum; ulong lastrtt; int lostmsgs; int rcvdmsgs; ulong lostavg; int unreachable; ushort seq; Req *first; Req *last; Req *rcvd; char buf[1024]; char *bufp; char *ebufp;}; enum{ Ncolor = 6, Ysqueeze = 2, /* vertical squeezing of label text */ Labspace = 2, /* room around label */ Dot = 2, /* height of dot */ Opwid = 5, /* strlen("add ") or strlen("drop ") */ NPROC = 128, NMACH = 32,}; enum Menu2{ Mrtt, Mlost, Nmenu2,}; char *menu2str[Nmenu2+1] = { "add sec rtt", "add % lost ", nil,}; void rttval(Machine*, long*, long*, long*);void lostval(Machine*, long*, long*, long*); Menu menu2 = {menu2str, nil};int present[Nmenu2];void (*newvaluefn[Nmenu2])(Machine*, long*, long*, long*) = { rttval, lostval,}; Image *cols[Ncolor][3];Graph *graph;Machine mach[NMACH];Font *mediumfont;int pids[NPROC];int npid;int parity; /* toggled to avoid patterns in textured background */int nmach;int ngraph; /* totaly number is ngraph*nmach */long starttime;int pinginterval; void dropgraph(int);void addgraph(int);void startproc(void (*)(void*), void*);void resize(void);long rttscale(long);int which2index(int);int index2which(int); voidkillall(char *s){ int i, pid; pid = getpid(); for(i=0; i<NPROC; i++) if(pids[i] && pids[i]!=pid) postnote(PNPROC, pids[i], "kill"); exits(s);} void*emalloc(ulong sz){ void *v; v = malloc(sz); if(v == nil) { fprint(2, "%s: out of memory allocating %ld: %r\n", argv0, sz); killall("mem"); } memset(v, 0, sz); return v;} void*erealloc(void *v, ulong sz){ v = realloc(v, sz); if(v == nil) { fprint(2, "%s: out of memory reallocating %ld: %r\n", argv0, sz); killall("mem"); } return v;} char*estrdup(char *s){ char *t; if((t = strdup(s)) == nil) { fprint(2, "%s: out of memory in strdup(%.10s): %r\n", argv0, s); killall("mem"); } return t;} voidmkcol(int i, int c0, int c1, int c2){ cols[i][0] = allocimagemix(display, c0, DWhite); cols[i][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c1); cols[i][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c2);} voidcolinit(void){ mediumfont = openfont(display, "/lib/font/bit/pelm/latin1.8.font"); if(mediumfont == nil) mediumfont = font; /* Peach */ mkcol(0, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF); /* Aqua */ mkcol(1, DPalebluegreen, DPalegreygreen, DPurpleblue); /* Yellow */ mkcol(2, DPaleyellow, DDarkyellow, DYellowgreen); /* Green */ mkcol(3, DPalegreen, DMedgreen, DDarkgreen); /* Blue */ mkcol(4, 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF); /* Grey */ cols[5][0] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF); cols[5][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF); cols[5][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x888888FF);} intloadbuf(Machine *m, int *fd){ int n; if(*fd < 0) return 0; seek(*fd, 0, 0); n = read(*fd, m->buf, sizeof m->buf); if(n <= 0){ close(*fd); *fd = -1; return 0; } m->bufp = m->buf; m->ebufp = m->buf+n; return 1;} voidlabel(Point p, int dy, char *text){ char *s; Rune r[2]; int w, maxw, maxy; p.x += Labspace; maxy = p.y+dy; maxw = 0; r[1] = '\0'; for(s=text; *s; ){ if(p.y+mediumfont->height-Ysqueeze > maxy) break; w = chartorune(r, s); s += w; w = runestringwidth(mediumfont, r); if(w > maxw) maxw = w; runestring(screen, p, display->black, ZP, mediumfont, r); p.y += mediumfont->height-Ysqueeze; }} voidhashmark(Point p, int dy, long v, long vmax, char *label){ int y; int x; x = p.x + Labspace; y = p.y + (dy*(vmax-v))/vmax; draw(screen, Rect(p.x, y-1, p.x+Labspace, y+1), display->black, nil, ZP); if(dy > 5*mediumfont->height) string(screen, Pt(x, y-mediumfont->height/2), display->black, ZP, mediumfont, label);} voidhashmarks(Point p, int dy, int which){ switch(index2which(which)){ case Mrtt: hashmark(p, dy, rttscale(1000000), Rttmax, "1."); hashmark(p, dy, rttscale(100000), Rttmax, "0.1"); hashmark(p, dy, rttscale(10000), Rttmax, "0.01"); hashmark(p, dy, rttscale(1000), Rttmax, "0.001"); break; case Mlost: hashmark(p, dy, 75, 100, " 75%"); hashmark(p, dy, 50, 100, " 50%"); hashmark(p, dy, 25, 100, " 25%"); break; }} Pointparitypt(int x){ return Pt(x+parity, 0);} Pointdatapoint(Graph *g, int x, long v, long vmax){ Point p; p.x = x; p.y = g->r.max.y - Dy(g->r)*v/vmax - Dot; if(p.y < g->r.min.y) p.y = g->r.min.y; if(p.y > g->r.max.y-Dot) p.y = g->r.max.y-Dot; return p;} voiddrawdatum(Graph *g, int x, long prev, long v, long vmax){ int c; Point p, q; c = g->colindex; p = datapoint(g, x, v, vmax); q = datapoint(g, x, prev, vmax); if(p.y < q.y){ draw(screen, Rect(p.x, g->r.min.y, p.x+1, p.y), cols[c][0], nil, paritypt(p.x)); draw(screen, Rect(p.x, p.y, p.x+1, q.y+Dot), cols[c][2], nil, ZP); draw(screen, Rect(p.x, q.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP); }else{ draw(screen, Rect(p.x, g->r.min.y, p.x+1, q.y), cols[c][0], nil, paritypt(p.x)); draw(screen, Rect(p.x, q.y, p.x+1, p.y+Dot), cols[c][2], nil, ZP); draw(screen, Rect(p.x, p.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP); } g->vmax = vmax;} voiddrawmark(Graph *g, int x){ int c; c = (g->colindex+1)&Ncolor; draw(screen, Rect(x, g->r.min.y, x+1, g->r.max.y), cols[c][2], nil, ZP);} voidredraw(Graph *g, int vmax){ int i, c; c = g->colindex; draw(screen, g->r, cols[c][0], nil, paritypt(g->r.min.x)); for(i=1; i<Dx(g->r); i++) drawdatum(g, g->r.max.x-i, g->data[i-1], g->data[i], vmax); drawdatum(g, g->r.min.x, g->data[i], g->data[i], vmax);} voidclearmsg(Graph *g){ if(g->overtmp != nil) draw(screen, g->overtmp->r, g->overtmp, nil, g->overtmp->r.min); g->overflow = 0;} voiddrawmsg(Graph *g, char *msg){ if(g->overtmp == nil) return; /* save previous contents of screen */ draw(g->overtmp, g->overtmp->r, screen, nil, g->overtmp->r.min); /* draw message */ if(strlen(msg) > g->overtmplen) msg[g->overtmplen] = 0; string(screen, g->overtmp->r.min, display->black, ZP, mediumfont, msg);} voidclearcursor(Graph *g){ int x; long prev; if(g->overtmp == nil) return; if(g->cursor > 0 && g->cursor < g->ndata){ x = g->r.max.x - g->cursor; prev = 0; if(g->cursor > 0) prev = g->data[g->cursor-1]; drawdatum(g, x, prev, g->data[g->cursor], g->vmax); g->cursor = -1; }} voiddrawcursor(Graph *g, int x){ if(g->overtmp == nil) return; draw(screen, Rect(x, g->r.min.y, x+1, g->r.max.y), cols[g->colindex][2], nil, ZP);} voidupdate1(Graph *g, long v, long vmax, long mark){ char buf[Gmsglen]; /* put back screen value sans message */ if(g->overflow || *g->msg){ clearmsg(g); g->overflow = 0; } draw(screen, g->r, screen, nil, Pt(g->r.min.x+1, g->r.min.y)); drawdatum(g, g->r.max.x-1, g->data[0], v, vmax); if(mark) drawmark(g, g->r.max.x-1); memmove(g->data+1, g->data, (g->ndata-1)*sizeof(g->data[0])); g->data[0] = v; if(v>vmax){ g->overflow = 1; sprint(buf, "%ld", v); drawmsg(g, buf); } else if(*g->msg) drawmsg(g, g->msg); if(g->cursor >= 0){ g->cursor++; if(g->cursor >= g->ndata){ g->cursor = -1; if(*g->msg){ clearmsg(g); *g->msg = 0; } } } } voidpinglost(Machine *m, Req*){ m->lostmsgs++;} voidpingreply(Machine *m, Req *r){ ulong x; x = r->time/1000LL; m->rttsum += x; m->rcvdmsgs++; m->rttmsgs++;} voidpingclean(Machine *m, ushort seq, vlong now, int){ Req **l, *r; vlong x, y; y = 10LL*1000000000LL; for(l = &m->first; *l; ){ r = *l; x = now - r->time; if(x > y || r->seq == seq){ *l = r->next; r->time = x; if(r->seq != seq) pinglost(m, r); else pingreply(m, r); free(r); } else l = &(r->next); }} /* IPv4 only */voidpingsend(Machine *m){ int i; char buf[128], err[ERRMAX]; Icmphdr *ip; Req *r; ip = (Icmphdr *)(buf + IPV4HDR_LEN); memset(buf, 0, sizeof buf); r = malloc(sizeof *r);Lines 1–500 of 1072. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h> #include <libc.h> #include <ctype.h> #include <auth.h> #include <fcall.h> #include <draw.h> #include <event.h> #include <ip.h> #include "icmp.h" #define MAXNUM 8 /* maximum number of numbers on data line */ typedef struct Graph Graph; typedef struct Machine Machine; typedef struct Req Req; enum { Gmsglen = 16, }; struct Graph { int colindex; Rectangle r; long *data; int ndata; char *label; void (*newvalue)(Machine*, long*, long*, long*); void (*update)(Graph*, long, long, long); Machine *mach; int overflow; Image *overtmp; int overtmplen; char msg[Gmsglen]; int cursor; int vmax; }; enum { MSGLEN = 64, Rttmax = 50, }; struct Req { int seq; /* sequence number */ vlong time; /* time sent */ // int rtt; Req *next; }; struct Machine { Lock; char *name; int pingfd; int nproc; int rttmsgs; ulong rttsum; ulong lastrtt; int lostmsgs; int rcvdmsgs; ulong lostavg; int unreachable; ushort seq; Req *first; Req *last; Req *rcvd; char buf[1024]; char *bufp; char *ebufp; }; enum { Ncolor = 6, Ysqueeze = 2, /* vertical squeezing of label text */ Labspace = 2, /* room around label */ Dot = 2, /* height of dot */ Opwid = 5, /* strlen("add ") or strlen("drop ") */ NPROC = 128, NMACH = 32, }; enum Menu2 { Mrtt, Mlost, Nmenu2, }; char *menu2str[Nmenu2+1] = { "add sec rtt", "add % lost ", nil, }; void rttval(Machine*, long*, long*, long*); void lostval(Machine*, long*, long*, long*); Menu menu2 = {menu2str, nil}; int present[Nmenu2]; void (*newvaluefn[Nmenu2])(Machine*, long*, long*, long*) = { rttval, lostval, }; Image *cols[Ncolor][3]; Graph *graph; Machine mach[NMACH]; Font *mediumfont; int pids[NPROC]; int npid; int parity; /* toggled to avoid patterns in textured background */ int nmach; int ngraph; /* totaly number is ngraph*nmach */ long starttime; int pinginterval; void dropgraph(int); void addgraph(int); void startproc(void (*)(void*), void*); void resize(void); long rttscale(long); int which2index(int); int index2which(int); void killall(char *s) { int i, pid; pid = getpid(); for(i=0; i<NPROC; i++) if(pids[i] && pids[i]!=pid) postnote(PNPROC, pids[i], "kill"); exits(s); } void* emalloc(ulong sz) { void *v; v = malloc(sz); if(v == nil) { fprint(2, "%s: out of memory allocating %ld: %r\n", argv0, sz); killall("mem"); } memset(v, 0, sz); return v; } void* erealloc(void *v, ulong sz) { v = realloc(v, sz); if(v == nil) { fprint(2, "%s: out of memory reallocating %ld: %r\n", argv0, sz); killall("mem"); } return v; } char* estrdup(char *s) { char *t; if((t = strdup(s)) == nil) { fprint(2, "%s: out of memory in strdup(%.10s): %r\n", argv0, s); killall("mem"); } return t; } void mkcol(int i, int c0, int c1, int c2) { cols[i][0] = allocimagemix(display, c0, DWhite); cols[i][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c1); cols[i][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c2); } void colinit(void) { mediumfont = openfont(display, "/lib/font/bit/pelm/latin1.8.font"); if(mediumfont == nil) mediumfont = font; /* Peach */ mkcol(0, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF); /* Aqua */ mkcol(1, DPalebluegreen, DPalegreygreen, DPurpleblue); /* Yellow */ mkcol(2, DPaleyellow, DDarkyellow, DYellowgreen); /* Green */ mkcol(3, DPalegreen, DMedgreen, DDarkgreen); /* Blue */ mkcol(4, 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF); /* Grey */ cols[5][0] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF); cols[5][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF); cols[5][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x888888FF); } int loadbuf(Machine *m, int *fd) { int n; if(*fd < 0) return 0; seek(*fd, 0, 0); n = read(*fd, m->buf, sizeof m->buf); if(n <= 0){ close(*fd); *fd = -1; return 0; } m->bufp = m->buf; m->ebufp = m->buf+n; return 1; } void label(Point p, int dy, char *text) { char *s; Rune r[2]; int w, maxw, maxy; p.x += Labspace; maxy = p.y+dy; maxw = 0; r[1] = '\0'; for(s=text; *s; ){ if(p.y+mediumfont->height-Ysqueeze > maxy) break; w = chartorune(r, s); s += w; w = runestringwidth(mediumfont, r); if(w > maxw) maxw = w; runestring(screen, p, display->black, ZP, mediumfont, r); p.y += mediumfont->height-Ysqueeze; } } void hashmark(Point p, int dy, long v, long vmax, char *label) { int y; int x; x = p.x + Labspace; y = p.y + (dy*(vmax-v))/vmax; draw(screen, Rect(p.x, y-1, p.x+Labspace, y+1), display->black, nil, ZP); if(dy > 5*mediumfont->height) string(screen, Pt(x, y-mediumfont->height/2), display->black, ZP, mediumfont, label); } void hashmarks(Point p, int dy, int which) { switch(index2which(which)){ case Mrtt: hashmark(p, dy, rttscale(1000000), Rttmax, "1."); hashmark(p, dy, rttscale(100000), Rttmax, "0.1"); hashmark(p, dy, rttscale(10000), Rttmax, "0.01"); hashmark(p, dy, rttscale(1000), Rttmax, "0.001"); break; case Mlost: hashmark(p, dy, 75, 100, " 75%"); hashmark(p, dy, 50, 100, " 50%"); hashmark(p, dy, 25, 100, " 25%"); break; } } Point paritypt(int x) { return Pt(x+parity, 0); } Point datapoint(Graph *g, int x, long v, long vmax) { Point p; p.x = x; p.y = g->r.max.y - Dy(g->r)*v/vmax - Dot; if(p.y < g->r.min.y) p.y = g->r.min.y; if(p.y > g->r.max.y-Dot) p.y = g->r.max.y-Dot; return p; } void drawdatum(Graph *g, int x, long prev, long v, long vmax) { int c; Point p, q; c = g->colindex; p = datapoint(g, x, v, vmax); q = datapoint(g, x, prev, vmax); if(p.y < q.y){ draw(screen, Rect(p.x, g->r.min.y, p.x+1, p.y), cols[c][0], nil, paritypt(p.x)); draw(screen, Rect(p.x, p.y, p.x+1, q.y+Dot), cols[c][2], nil, ZP); draw(screen, Rect(p.x, q.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP); }else{ draw(screen, Rect(p.x, g->r.min.y, p.x+1, q.y), cols[c][0], nil, paritypt(p.x)); draw(screen, Rect(p.x, q.y, p.x+1, p.y+Dot), cols[c][2], nil, ZP); draw(screen, Rect(p.x, p.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP); } g->vmax = vmax; } void drawmark(Graph *g, int x) { int c; c = (g->colindex+1)&Ncolor; draw(screen, Rect(x, g->r.min.y, x+1, g->r.max.y), cols[c][2], nil, ZP); } void redraw(Graph *g, int vmax) { int i, c; c = g->colindex; draw(screen, g->r, cols[c][0], nil, paritypt(g->r.min.x)); for(i=1; i<Dx(g->r); i++) drawdatum(g, g->r.max.x-i, g->data[i-1], g->data[i], vmax); drawdatum(g, g->r.min.x, g->data[i], g->data[i], vmax); } void clearmsg(Graph *g) { if(g->overtmp != nil) draw(screen, g->overtmp->r, g->overtmp, nil, g->overtmp->r.min); g->overflow = 0; } void drawmsg(Graph *g, char *msg) { if(g->overtmp == nil) return; /* save previous contents of screen */ draw(g->overtmp, g->overtmp->r, screen, nil, g->overtmp->r.min); /* draw message */ if(strlen(msg) > g->overtmplen) msg[g->overtmplen] = 0; string(screen, g->overtmp->r.min, display->black, ZP, mediumfont, msg); } void clearcursor(Graph *g) { int x; long prev; if(g->overtmp == nil) return; if(g->cursor > 0 && g->cursor < g->ndata){ x = g->r.max.x - g->cursor; prev = 0; if(g->cursor > 0) prev = g->data[g->cursor-1]; drawdatum(g, x, prev, g->data[g->cursor], g->vmax); g->cursor = -1; } } void drawcursor(Graph *g, int x) { if(g->overtmp == nil) return; draw(screen, Rect(x, g->r.min.y, x+1, g->r.max.y), cols[g->colindex][2], nil, ZP); } void update1(Graph *g, long v, long vmax, long mark) { char buf[Gmsglen]; /* put back screen value sans message */ if(g->overflow || *g->msg){ clearmsg(g); g->overflow = 0; } draw(screen, g->r, screen, nil, Pt(g->r.min.x+1, g->r.min.y)); drawdatum(g, g->r.max.x-1, g->data[0], v, vmax); if(mark) drawmark(g, g->r.max.x-1); memmove(g->data+1, g->data, (g->ndata-1)*sizeof(g->data[0])); g->data[0] = v; if(v>vmax){ g->overflow = 1; sprint(buf, "%ld", v); drawmsg(g, buf); } else if(*g->msg) drawmsg(g, g->msg); if(g->cursor >= 0){ g->cursor++; if(g->cursor >= g->ndata){ g->cursor = -1; if(*g->msg){ clearmsg(g); *g->msg = 0; } } } } void pinglost(Machine *m, Req*) { m->lostmsgs++; } void pingreply(Machine *m, Req *r) { ulong x; x = r->time/1000LL; m->rttsum += x; m->rcvdmsgs++; m->rttmsgs++; } void pingclean(Machine *m, ushort seq, vlong now, int) { Req **l, *r; vlong x, y; y = 10LL*1000000000LL; for(l = &m->first; *l; ){ r = *l; x = now - r->time; if(x > y || r->seq == seq){ *l = r->next; r->time = x; if(r->seq != seq) pinglost(m, r); else pingreply(m, r); free(r); } else l = &(r->next); } } /* IPv4 only */ void pingsend(Machine *m) { int i; char buf[128], err[ERRMAX]; Icmphdr *ip; Req *r; ip = (Icmphdr *)(buf + IPV4HDR_LEN); memset(buf, 0, sizeof buf); r = malloc(sizeof *r);