~kris/9p

9hist

42cf0bcab4a1100665ab131ca7c581881f777f10 — David du Colombier 34 years ago e4c372c
Plan 9 from Bell Labs 1992-04-06
3 files changed, 131 insertions(+), 75 deletions(-)

M pc/devether.c
M port/devip.c
M port/tcpinput.c
M pc/devether.c => pc/devether.c +63 -35
@@ 2,7 2,11 @@
 * Western Digital ethernet adapter
 * BUGS:
 *	no more than one controller
 * TODO:
 *	fix for different controller types
 *	output
 *	deal with stalling and restarting output on input overflow
 *	fix magic ring constants
 */
#include "u.h"
#include "../port/lib.h"


@@ 131,26 135,24 @@ static Ctlr ctlr[Nctlr];
static void
etheroput(Queue *q, Block *bp)
{
	Ctlr *c;
	Ctlr *cp;
	int len, n;
	Pktype *t;
	Pktype *pp;
	Etherpkt *p;
	Block *nbp;

panic("etheroput\n");
#ifdef notdef
	c = ((Pktype *)q->ptr)->ctlr;
	cp = ((Pktype *)q->ptr)->ctlr;
	if(bp->type == M_CTL){
		t = q->ptr;
		pp = q->ptr;
		if(streamparse("connect", bp))
			t->type = strtol((char *)bp->rptr, 0, 0);
			pp->type = strtol((char *)bp->rptr, 0, 0);
		else if(streamparse("promiscuous", bp)) {
			t->prom = 1;
			qlock(c);
			c->prom++;
			if(c->prom == 1)
				outb(c->iobase+Rcr, 0x14);	/* PRO|AB */
			qunlock(c);
			pp->prom = 1;
			qlock(cp);
			cp->prom++;
			if(cp->prom == 1)
				outb(cp->iobase+Rcr, 0x14);	/* PRO|AB */
			qunlock(cp);
		}
		freeb(bp);
		return;


@@ 160,33 162,30 @@ panic("etheroput\n");
	 * give packet a local address, return upstream if destined for
	 * this machine.
	 */
	if(BLEN(bp) < ETHERHDRSIZE){
		bp = pullup(bp, ETHERHDRSIZE);
		if(bp == 0)
			return;
	}
	if(BLEN(bp) < ETHERHDRSIZE && (bp = pullup(bp, ETHERHDRSIZE)) == 0)
		return;
	p = (Etherpkt *)bp->rptr;
	memmove(p->s, c->ea, sizeof(c->ea));
	if(memcmp(c->ea, p->d, sizeof(c->ea)) == 0){
	memmove(p->s, cp->ea, sizeof(cp->ea));
	if(memcmp(cp->ea, p->d, sizeof(cp->ea)) == 0){
		len = blen(bp);
		bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU);
		if(bp){
			putq(&c->rq, bp);
			wakeup(&c->rr);
		if (bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){
			putq(&cp->rq, bp);
			wakeup(&cp->rr);
		}
		return;
	}
	if(memcmp(c->ba, p->d, sizeof(c->ba)) == 0){
	if(memcmp(cp->ba, p->d, sizeof(cp->ba)) == 0){
		len = blen(bp);
		nbp = copyb(bp, len);
		nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU);
		if(nbp){
		if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){
			nbp->wptr = nbp->rptr+len;
			putq(&c->rq, nbp);
			wakeup(&c->rr);
			putq(&cp->rq, nbp);
			wakeup(&cp->rr);
		}
	}

panic("etheroput\n");
#ifdef notdef
	/*
	 * only one transmitter at a time
	 */


@@ 509,6 508,18 @@ etherup(Ctlr *cp, Etherpkt *p, int len)
	}
}

static void
printpkt(uchar bnry, ushort len, Etherpkt *p)
{
	int i;

	print("%.2ux: %.4d d(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)s(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)t(%.2ux %.2ux)\n",
		bnry, len,
		p->d[0], p->d[1], p->d[2], p->d[3], p->d[4], p->d[5],
		p->s[0], p->s[1], p->s[2], p->s[3], p->s[4], p->s[5],
		p->type[0], p->type[1]);
}

static int
isinput(void *arg)
{


@@ 534,17 545,34 @@ etherkproc(void *arg)
	cp->kproc = 1;
	for(;;){
		sleep(&cp->rr, isinput, cp);
		/*
		 * process any internal loopback packets
		 */
		while(bp = getq(&cp->rq)){
			cp->inpackets++;
			etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp));
			freeb(bp);
		}
#ifdef foo
			bnry = inb(cp->iobase+Bnry);
			while(bnry != cp->curr){
				rp = &((Ring *)RAMbase)[bnry];
			}
#endif
		/*
		 * process any received packets
		 */
		bnry = inb(cp->iobase+Bnry);
		while(bnry != cp->curr){
			rp = &((Ring*)RAMbase)[bnry];
printpkt(bnry, rp->len, (Etherpkt*)rp->data);
			cp->inpackets++;
			etherup(cp, (Etherpkt*)rp->data, rp->len-4);
			bnry = rp->next;
			outb(cp->iobase+Bnry, bnry);
		}
		/*
		 * if we idled input because of overflow,
		 * restart
		 */
		if(cp->ovw){
			cp->ovw = 0;
			outb(cp->iobase+Tcr, 0);
		}
	}
}


M port/devip.c => port/devip.c +3 -0
@@ 883,6 883,9 @@ portused(Ipconv *ic, Port port)
{
	Ipconv *ifc, *etab;

	if(port == 0)
		return 0;

	etab = &ic[conf.ip];
	for(ifc = ic; ifc < etab; ifc++)
		if(ifc->psrc == port) 

M port/tcpinput.c => port/tcpinput.c +65 -40
@@ 79,10 79,43 @@ reset(Ipaddr source, Ipaddr dest, char tos, ushort length, Tcp *seg)
	PUTNEXT(Ipoutput, hbp);
}

Ipconv*
tcpincoming(Ipconv *ipc, Ipconv *s, Tcp *segp, Ipaddr source)
{
	Ipconv *new;

	if(s->curlog >= s->backlog)
		return 0;

	new = ipincoming(ipc, s);
	if(new == 0)
		return 0;

	qlock(s);
	s->curlog++;
	qunlock(s);
	new->psrc = segp->dest;
	new->pdst = segp->source;
	new->dst = source;
	memmove(&new->tcpctl, &s->tcpctl, sizeof(Tcpctl));
	new->tcpctl.flags &= ~CLONE;
	new->tcpctl.timer.arg = new;
	new->tcpctl.timer.state = TIMER_STOP;
	new->tcpctl.acktimer.arg = new;
	new->tcpctl.acktimer.state = TIMER_STOP;
	new->newcon = 1;
	new->ipinterface = s->ipinterface;

	s->ipinterface->ref++;
	wakeup(&s->listenr);
	return new;
}

void
tcp_input(Ipconv *ipc, Block *bp)
{
	Ipconv *s, *e, *new;
	Ipconv *s, *e;
	Ipconv *spec, *gen;
	Tcpctl *tcb;		
	Tcphdr *h;
	Tcp seg;


@@ 117,48 150,40 @@ tcp_input(Ipconv *ipc, Block *bp)
	/* Look for a connection, failing that attempt to establish a listen */
	s = ip_conn(ipc, seg.dest, seg.source, source, IP_TCPPROTO);
	if (s == 0) {
		if((seg.flags & SYN) == 0)
			goto clear;

		e = &ipc[conf.ip];
		for(s = ipc; s < e; s++) {
			if(s->tcpctl.state == Listen)
			if(s->pdst == 0)
			if(s->dst == 0) {
				if(s->curlog >= s->backlog)
					goto clear;

				new = ipincoming(ipc, s);
				if(new == 0)
					goto clear;

				qlock(s);
				s->curlog++;
				qunlock(s);
				new->psrc = seg.dest;
				new->pdst = seg.source;
				new->dst = source;
				memmove(&new->tcpctl, &s->tcpctl, sizeof(Tcpctl));
				new->tcpctl.flags &= ~CLONE;
				new->tcpctl.timer.arg = new;
				new->tcpctl.timer.state = TIMER_STOP;
				new->tcpctl.acktimer.arg = new;
				new->tcpctl.acktimer.state = TIMER_STOP;
				new->newcon = 1;
				new->ipinterface = s->ipinterface;

				s->ipinterface->ref++;
				wakeup(&s->listenr);
				s = new;
				goto process;
		if(seg.flags & SYN){
			/*
			 *  find a listener specific to this port (spec) or,
			 *  failing that, a general one (gen)
			 */
			spec = 0;
			gen = 0;
			e = &ipc[conf.ip];
			for(s = ipc; s < e; s++) {
				if(s->tcpctl.state == Listen)
				if(s->pdst == 0)
				if(s->dst == 0) {
					if(s->psrc == seg.dest){
						spec = s;
						break;
					}
					if(s->psrc == 0)
						gen = s;
				}
			}
			if(spec)
				s = tcpincoming(ipc, spec, &seg, source);
			else if(gen)
				s = tcpincoming(ipc, gen, &seg, source);
			else
				s = 0;
		}
		if(s == 0){
			freeb(bp);   
			reset(source, dest, tos, length, &seg);
			return;
		}
	clear:
		freeb(bp);   
		reset(source, dest, tos, length, &seg);
		return;
	}
process:

	/* The rest of the input state machine is run with the control block
	 * locked
	 */