~kris/9p

9hist

98c387c2baab2f0f8bda32ad6623ba0eab985384 — David du Colombier 34 years ago 1944cfb
Plan 9 from Bell Labs 1991-10-29
7 files changed, 101 insertions(+), 140 deletions(-)

M pc/devfloppy.c
M pc/fns.h
M pc/main.c
M port/devarp.c
M port/devip.c
M port/ipdat.h
M port/stip.c
M pc/devfloppy.c => pc/devfloppy.c +4 -0
@@ 455,6 455,10 @@ floppywrite(Chan *c, void *a, long n)
		} else if(SNCMP(aa, "reset") == 0){
			fl.confused = 1;
			floppyon(dp);
		} else if(SNCMP(aa, "fast") == 0){
			cpuspeed(1);
		} else if(SNCMP(aa, "slow") == 0){
			cpuspeed(0);
		}
		qunlock(&fl);
		break;

M pc/fns.h => pc/fns.h +2 -0
@@ 5,6 5,7 @@ void	meminit(void);
void	clock(Ureg*);
void	clockinit(void);
void	config(int);
int	cpuspeed(int);
void	delay(int);
void	dmaend(int);
long	dmasetup(int, void*, long, int);


@@ 29,6 30,7 @@ void	mmuinit(void);
int	modem(int);
void	outb(int, int);
void	outss(int, void*, int);
int	pmuwrbit(int, int, int);
void	prhex(ulong);
void	procrestore(Proc*, uchar*);
void	procsave(uchar*, int);

M pc/main.c => pc/main.c +11 -0
@@ 476,6 476,17 @@ modem(int onoff)
	return pmuwrbit(1, 1^onoff, 5);
}

/*
 *  CPU speed
 *	onoff == 0 means 2 MHZ
 *	onoff == 1 means 20 MHZ
 */
int
cpuspeed(int speed)
{
	return pmuwrbit(0, speed, 0);
}

void
buzz(int f, int d)
{

M port/devarp.c => port/devarp.c +75 -128
@@ 9,36 9,42 @@

#include	"devtab.h"

#define ARP_FREE	0
#define ARP_OK		1
#define ARP_ASKED	2
#define ARP_TEMP	0
#define ARP_PERM	1
#define Arphashsize	32
#define ARPHASH(p)	arphash[((p[2]^p[3])%Arphashsize)]

typedef struct Arpcache Arpcache;
struct Arpcache {
	uchar	status;
	uchar	type;
	uchar	eip[4];
	uchar	et[6];
	Arpcache *hash;
	Arpcache **hashhd;
	Arpcache *frwd;
	Arpcache *prev;
};

Arpstats	arpstats;
Arpcache 	*arplruhead, *arplrutail;
Arpcache 	*arp, **arphash;
Queue		*Servq;
Lock		larphash;

void	arpiput(Queue *, Block *);
void	arpoput(Queue *, Block *);
void	arpopn(Queue *, Stream *);
void	arpcls(Queue *);
void	arpenter(Arpentry*, int);
void	arpflush(void);
int	arpdelete(char*);
void	arplinkhead(Arpcache*);
int	arplookup(uchar*, uchar*);

typedef struct Arpq Arpq;
struct Arpq
{
	uchar	ip[4];
	uchar	*etheraddr;
	Block	*bp;
	Queue	*put;
	ulong	time;
	Arpq	*next;
};

struct arpalloc
{
	Lock;
	Lock	list;
	Lock	hash;
	Arpq	*free;
	Arpq	*head;
	Arpq	*tail;
}arpalloc;

void		arpiput(Queue *, Block *);
void		arpoput(Queue *, Block *);
void		arpopn(Queue *, Stream *);
void		arpcls(Queue *);
Qinfo arpinfo = { arpiput, arpoput, arpopn, arpcls, "arp" };

#define ARP_ENTRYLEN	50


@@ 253,8 259,6 @@ arpwrite(Chan *c, char *a, long n, ulong offset)
void
arpopn(Queue *q, Stream *s)
{
	if(!Servq)
		Servq = RD(q);
}

void


@@ 273,7 277,40 @@ arpiput(Queue *q, Block *bp)
void
arpoput(Queue *q, Block *bp)
{
	PUTNEXT(q, bp);
	uchar ip[4];
	Etherhdr *eh;

	if(bp->type != M_DATA) {
		if(Servq == 0 && streamparse("arpd", bp)) {
print("setting arp channel\n");
			Servq = RD(q);
			freeb(bp);
		}
		else
			PUTNEXT(q, bp);
		return;
	}

	if(!Servq) {
		print("arp: No server, packet dropped\n");
		freeb(bp);
		return;
	}

	eh = (Etherhdr *)bp->rptr;
	iproute(eh->dst, ip);

	/* Send downstream to the ethernet */
	if(arplookup(ip, eh->d)) {
print("arp hit %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
		PUTNEXT(q, bp);
		return;
	}
print("arp miss %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);

	/* Return the packet to the arp server for address resolution */
	memmove(eh->d, ip, sizeof(ip));
	PUTNEXT(Servq, bp);
}

int


@@ 281,77 318,19 @@ arplookup(uchar *ip, uchar *et)
{
	Arpcache *ap;

	lock(&arpalloc.hash);
	lock(&larphash);
	for(ap = ARPHASH(ip); ap; ap = ap->hash) {
		if(ap->status == ARP_OK && memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) {
			memmove(et, ap->et, sizeof(ap->et));
			arplinkhead(ap);
			unlock(&arpalloc.hash);
			unlock(&larphash);
			arpstats.hit++;
			return 1;
		}
	}
	unlock(&arpalloc.hash);
	return 0;
}

void
arpsendpkt(uchar *unroutedip, uchar *ether, Queue *put, Block *bp)
{
	Arpq *aq;
	Block *nbp;
	uchar ip[4];

	if(!Servq) {
		print("arp: No server\n");
		freeb(bp);
		return;
	}

	iproute(unroutedip, ip);
	if(arplookup(ip, ether)) {
print("hit %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
		PUTNEXT(put, bp);
		return;
	}
print("miss %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);

	/* Send the request out to the user level arp daemon */
	nbp = allocb(sizeof(ip));
	memmove(nbp->rptr, ip, sizeof(ip));
	nbp->wptr += sizeof(ip);
	nbp->flags |= S_DELIM;
	PUTNEXT(Servq, nbp);
	arpstats.miss++;

	lock(&arpalloc);
	if(aq = arpalloc.free)
		arpalloc.free = aq->next;
	unlock(&arpalloc);

	if(aq == 0) {
		freeb(bp);
		return;
	}

	/* Stash the work away until the arp completes or times out */
	memmove(aq->ip, ip, sizeof(aq->ip));
	aq->etheraddr = ether;
	aq->bp = bp;
	aq->put = put;
	aq->time = MACHP(0)->ticks;

	lock(&arpalloc.list);
	if(arpalloc.head)  {
		arpalloc.tail->next = aq;
		arpalloc.tail = aq;
	}
	else {
		arpalloc.tail = aq;
		arpalloc.head = aq;
	}
	aq->next = 0;
	unlock(&arpalloc.list);
	unlock(&larphash);
	return 0;
}

void


@@ 371,7 350,7 @@ arpenter(Arpentry *ape, int type)

	/* Update an entry if we have one already */
	l = &ARPHASH(ape->ipaddr);
	lock(&arpalloc.hash);
	lock(&larphash);
	for(ap = *l; ap; ap = ap->hash) {
		if(ap->status == ARP_OK && memcmp(ap->eip, ape->ipaddr, sizeof(ap->eip)) == 0) {
			if(ap->type != ARP_PERM) {


@@ 379,7 358,7 @@ arpenter(Arpentry *ape, int type)
				memmove(ap->et, ape->etaddr, sizeof(ap->et));
				ap->status = ARP_OK;
			}
			unlock(&arpalloc.hash);
			unlock(&larphash);
			return;
		}
	}


@@ 390,7 369,7 @@ arpenter(Arpentry *ape, int type)

	if(!ap) {
		print("arp: too many permanent entries\n");
		unlock(&arpalloc.hash);
		unlock(&larphash);
		return;
	}



@@ 408,43 387,11 @@ arpenter(Arpentry *ape, int type)
	ap->status = ARP_OK;
	memmove(ap->eip, ape->ipaddr, sizeof(ape->ipaddr));
	memmove(ap->et, ape->etaddr, sizeof(ape->etaddr));
	ap->ip = nhgetl(ap->eip);
	ap->hashhd = l;
	ap->hash = *l;
	*l = ap;
	arplinkhead(ap);
	unlock(&arpalloc.hash);
	pusharpq();
}

void
pusharpq(void)
{
	int sent;
	Arpq *aq, *prev;

loop:	prev = 0;
	lock(&arpalloc.list);
	for(aq = arpalloc.head; aq; aq = aq->next) {
		if(arplookup(aq->ip, aq->etheraddr)) {
			if(prev)
				prev->next = aq->next;
			else
				arpalloc.head = 0;
			if(aq->next == 0)
				arpalloc.tail = prev;
			unlock(&arpalloc.list);
			PUTNEXT(aq->put, aq->bp);

			lock(&arpalloc);
			aq->next = arpalloc.free;
			arpalloc.free = aq;
			unlock(&arpalloc);
			goto loop;
		}
		prev = aq;
	}
	unlock(&arpalloc.list);
	unlock(&larphash);
}

int


@@ 464,14 411,14 @@ arpdelete(char *addr)
		ptr = strchr(ptr, ':')+1;
	}

	lock(&arpalloc.hash);
	lock(&larphash);
	for(ap = arplruhead; ap; ap = ap->frwd) {
		if(memcmp(ap->et, ptr, sizeof(ap->et)) == 0) {
			ap->status = ARP_FREE;
			break;
		}
	}
	unlock(&arpalloc.hash);
	unlock(&larphash);
}

void

M port/devip.c => port/devip.c +5 -2
@@ 176,14 176,14 @@ ipopen(Chan *c, int omode)
			error(Ebadarg);
		break;
	case iplistenqid:
		if(cp->stproto != &tcpinfo &&
		   cp->stproto != &ilinfo)
		if(cp->stproto != &tcpinfo && cp->stproto != &ilinfo)
			error(Eprotonosup);

		if(cp->backlog == 0)
			cp->backlog = 3;

		streamopen(c, &ipinfo);

		if(c->stream->devq->next->info != cp->stproto)
			pushq(c->stream, cp->stproto);



@@ 196,6 196,7 @@ ipopen(Chan *c, int omode)
		break;
	case Sdataqid:
		streamopen(c, &ipinfo);

		if(c->stream->devq->next->info != cp->stproto)
			pushq(c->stream, cp->stproto);



@@ 207,6 208,7 @@ ipopen(Chan *c, int omode)
		break;
	case Sctlqid:
		streamopen(c, &ipinfo);

		if(c->stream->devq->next->info != cp->stproto)
			pushq(c->stream, cp->stproto);
		break;


@@ 697,6 699,7 @@ print("listen awoke\n");
				new->newcon = 0;
				c->qid.path = CHDIR|STREAMQID(new-base, ipchanqid);
				devwalk(c, "ctl", 0, 0, streamgen);

				streamopen(c, &ipinfo);
				pushq(c->stream, new->stproto);
				new->ref--;

M port/ipdat.h => port/ipdat.h +1 -6
@@ 429,11 429,6 @@ Block	*btrim(Block*, int, int);
Block	*ip_reassemble(int, Block*, Etherhdr*);
Ipconv	*portused(Ipconv *, Port);
Port	nextport(Ipconv *, Port);
void	arpenter(Arpentry*, int);
void	arpflush(void);
int	arpdelete(char*);
void	pusharpq(void);
void	arplinkhead(Arpcache*);
Fragq   *ipfragallo(void);
void	ipfragfree(Fragq*);
void	iproute(uchar*, uchar*);


@@ 486,7 481,6 @@ void	tcp_acktimer(void *);
Ipconv  *ipclonecon(Chan *);
void	iplisten(Chan *, Ipconv *, Ipconv *);
void	iloutoforder(Ipconv*, Ilhdr*, Block*);
void	arpsendpkt(uchar*, uchar*, Queue*, Block*);

#define	fmtaddr(xx)	(xx>>24)&0xff,(xx>>16)&0xff,(xx>>8)&0xff,xx&0xff
#define	MIN(a, b)	((a) < (b) ? (a) : (b))


@@ 508,4 502,5 @@ extern Qinfo tcpinfo;
extern Qinfo ipinfo;
extern Qinfo udpinfo;
extern Qinfo ilinfo;
extern Qinfo arpinfo;
extern Queue *Ipoutput;

M port/stip.c => port/stip.c +3 -4
@@ 198,9 198,9 @@ ipetheroput(Queue *q, Block *bp)
		eh->cksum[1] = 0;
		hnputs(eh->cksum, ip_csum(&eh->vihl));

		/* Finally put in the ethernet level information */
		/* Finally put in the type and pass down to the arp layer */
		hnputs(eh->type, ET_IP);
		arpsendpkt(eh->dst, eh->d, Etherq, bp);
		PUTNEXT(Etherq, bp);
		return;
	}



@@ 263,9 263,8 @@ ipetheroput(Queue *q, Block *bp)
		feh->cksum[1] = 0;
		hnputs(feh->cksum, ip_csum(&feh->vihl));
		nb->flags |= S_DELIM;
		arpsendpkt(feh->dst, feh->d, Etherq, nb);
		PUTNEXT(Etherq, nb);
	}

drop:
	freeb(bp);	
}