Пример #1
0
static void *
writer(void *aport)
{
	Port *port = (Port *)aport;
	Buffer *bp;
	int nwr, nref;

	for(;;){
		bp = qget(&port->xmitq);
		if(bp == NULL)
			break;
		if(bp->len > 0){
			*(uint32_t *)bp->buf = 0;
			nwr = write(port->fd, bp->buf, bp->len);
			if(nwr != bp->len){
				fprintf(stderr, "%s: short write, got %d wanted %d\n", portname(port), nwr, bp->len);
				break;
			}
		}
		nref = bdecref(bp);
		if(nref == 0)
			qput(bp->freeq, bp);
	}
	fprintf(stderr, "%s: writer exiting\n", portname(port));
	return port;
}
Пример #2
0
Block*
netifbread(Netif *nif, Chan *c, long n, vlong offset)
{
	Netfile *f;
	Block *bp;

	if((c->qid.type & QTDIR) || NETTYPE(c->qid.path) != Ndataqid)
		return devbread(c, n, offset);

	f = nif->f[NETID(c->qid.path)];
	if(f->fat){
		/*
		 * Frame at a time (fat) allows us to provide
		 * non-blocking performance with blocking semantics
		 * for consumers that know ahead of time data is
		 * contained within a single frame.  Once empty, we
		 * get in line with other blocking reads and wait our
		 * turn.
		 */
		for(;;){
			if(bp = qget(f->iq))
				return bp;
			if(waserror())
				return nil;
			qsleep(f->iq);
			poperror();
		}
	}
	return qbread(f->iq, n);
}
Пример #3
0
/*
 *  called when a process writes to an interface's 'data'
 */
static void
ipifckick(void *x)
{
	Proc *up = externup();
	Conv *c = x;
	Block *bp;
	Ipifc *ifc;

	bp = qget(c->wq);
	if(bp == nil)
		return;

	ifc = (Ipifc*)c->ptcl;
	if(!canrlock(ifc)){
		freeb(bp);
		return;
	}
	if(waserror()){
		runlock(ifc);
		nexterror();
	}
	if(ifc->medium == nil || ifc->medium->pktin == nil)
		freeb(bp);
	else
		(*ifc->medium->pktin)(c->p->f, ifc, bp);
	runlock(ifc);
	poperror();
}
Пример #4
0
static void *
reader(void *aport)
{
	Buffer *bp;
	Port *port;
	Cam *cam;
	uint8_t *dstmac, *srcmac;
	int i, nrd, nref;

	port = (Port *)aport;
	for(;;){
		bp = qget(&port->freeq);

		nrd = read(port->fd, bp->buf, bp->cap);
		if(port->state != PortOpen){
			qput(bp->freeq, bp);
			break;
		}
		bp->len = nrd;

		dstmac = (uint8_t *)bp->buf + 4;
		srcmac = (uint8_t *)bp->buf + 10;

		nref = 0;
		cam = camlook(g_cams, dstmac);
		if(cam != NULL && cam->port != NULL){
			// port found in cam, forward only there...
			nref = bincref(bp);
			if(qput(&cam->port->xmitq, bp) == -1)
				nref = bdecref(bp);
		} else {
			// broadcast..
			for(i = 0; i < nports; i++){
				if(port == (ports+i))
					continue;
				nref = bincref(bp);
				if(qput(&ports[i].xmitq, bp) == -1)
					nref = bdecref(bp);
			}
		}

		// teach the switch about the source address we just saw
		cam = camlook(g_cams, srcmac);
		if(cam != NULL){
			// always update the port, so if an address moves to a different port
			// the cam will point to that port right away.
			copymac(cam->mac, srcmac);
			cam->age = 0;
			cam->port = port;
		} else {
			fprintf(stderr, "cam presumably full..\n");
		}

		// ref is zero after the forward loop. it didn't go anywhere, so drop it.
		if(nref == 0)
			qput(bp->freeq, bp);
	}
	fprintf(stderr, "%s: reader exiting..\n", portname(port));
	return port;
}
Пример #5
0
int main(int argc, char * argv[]){
	
	int cclients = 10;
	int sentMsg = 0;
	printf("Server iniciado para %d clientes.\n", cclients);

	message_t incomingMsg;
	message_t msgsent;
	char * word = "Mensaje del Server";
	
	ipc_t server = (ipc_t) fifoServe(cclients);
	server->stop = 0;

	while(sentMsg != 1000){
		if((incomingMsg = qget(server->inbox)) != NULL){
			printf("%d. Server recibio: %s\n", sentMsg, incomingMsg->data);
			
			printf("Manda mensaje a:%d.\n", incomingMsg->header.from);
			qput(server->outbox, (msgsent = mnew(0,incomingMsg->header.from, strlen(word) + 1, word)));
			mdel(msgsent);

			mdel(incomingMsg);
			sentMsg++;
		}
	}
	stopServer(server);
}
Пример #6
0
void * mq_clientLoop(void* ipcarg)
{
	ipc_t ipc;
	ipc = (ipc_t) ipcarg;
	message_t msg;
	
	if(ipc->status == IPCSTAT_DISCONNECTED)
	{
		return NULL;
	}
	
	ipc->status = IPCSTAT_CONNECTED;
	
	
    while (ipc->stop != 1) {
    	
    	msg = mq_getData(ipc, ipc->ipcdata->queuedata.recvPrior);
    	
    	if(msg != NULL)
    	{
    	
			qput(ipc->inbox, msg);
    	}
    	
    	msg = qget(ipc->outbox);
        if(msg != NULL)
        {
        	mq_sendData(ipc,msg,SERVERKEY);
        }
    }
    
    mq_disconnect(ipc);
    free(msg);
    return NULL;
}
Пример #7
0
/*
 *  called when a process writes to an interface's 'data'
 */
static void ipifckick(void *x)
{
	ERRSTACK(1);
	struct conv *c = x;
	struct block *bp;
	struct Ipifc *ifc;

	bp = qget(c->wq);
	if (bp == NULL)
		return;

	ifc = (struct Ipifc *)c->ptcl;
	if (!canrlock(&ifc->rwlock)) {
		freeb(bp);
		return;
	}
	if (waserror()) {
		runlock(&ifc->rwlock);
		nexterror();
	}
	if (ifc->m == NULL || ifc->m->pktin == NULL)
		freeb(bp);
	else
		(*ifc->m->pktin) (c->p->f, ifc, bp);
	runlock(&ifc->rwlock);
	poperror();
}
Пример #8
0
Файл: ether.c Проект: 8l/inferno
int
etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
{
	int n;
	Ctlr *ctlr;
	Block *b;
	ulong start;

	if((ctlr = attach(ctlrno)) == 0)
		return 0;

	start = m->ticks;
	while((b = qget(ctlr->iq)) == 0){
		if(TK2MS(m->ticks - start) >= timo){
			/*
			print("ether%d: rx timeout\n", ctlrno);
			 */
			return 0;
		}
		//delay(1);
	}

	n = BLEN(b);
	memmove(pkt, b->rp, n);
	freeb(b);

	return n;
}
Пример #9
0
/*
 * transmit strategy: fill the output ring as far as possible,
 * perhaps leaving a few spare; kick off the output and take
 * an interrupt only when the transmit queue is empty.
 */
static void
transmit(Ether *ether)
{
	int i, kick, len;
	Block *b;
	Ctlr *ctlr = ether->ctlr;
	Gbereg *reg = ctlr->reg;
	Tx *t;

	ethercheck(ether);
	ilock(ctlr);
	txreplenish(ether);			/* reap old packets */

	/* queue new packets; use at most half the tx descs to avoid livelock */
	kick = 0;
	for (i = Ntx/2 - 2; i > 0; i--) {
		t = &ctlr->tx[ctlr->txhead];	/* *t is uncached */
		assert(((uintptr)t & (Descralign - 1)) == 0);
		if(t->cs & TCSdmaown) {		/* descriptor busy? */
			ctlr->txringfull++;
			break;
		}

		b = qget(ether->oq);		/* outgoing packet? */
		if (b == nil)
			break;
		len = BLEN(b);
		if(len < ether->minmtu || len > ether->maxmtu) {
			freeb(b);
			continue;
		}
		ctlr->txb[ctlr->txhead] = b;

		/* make sure the whole packet is in memory */
		cachedwbse(b->rp, len);
		l2cacheuwbse(b->rp, len);

		/* set up the transmit descriptor */
		t->buf = PADDR(b->rp);
		t->countchk = len << 16;
		coherence();

		/* and fire */
		t->cs = TCSpadding | TCSfirst | TCSlast | TCSdmaown |
			TCSenableintr;
		coherence();

		kick++;
		ctlr->txhead = NEXT(ctlr->txhead, Ntx);
	}
	if (kick) {
		txkick(ctlr);

		reg->irqmask  |= Itxendq(Qno);
		reg->irqemask |= IEtxerrq(Qno) | IEtxunderrun;
	}
	iunlock(ctlr);
}
Пример #10
0
static void
txstart(Ether* ether)
{
	int port;
	Smc91xx* ctlr;
	Block* bp;
	int len, npages;
	int pno;

	/* assumes ctlr is locked and bank 2 is selected */
	/* leaves bank 2 selected on return */
	port = ether->port;
	ctlr = ether->ctlr;

	if (ctlr->txbp) {
		bp = ctlr->txbp;
		ctlr->txbp = 0;
	} else {
		bp = qget(ether->oq);
		if (bp == 0)
			return;

		len = BLEN(bp);
		npages = (len + HdrSize) / PageSize;
		outs(port + MmuCmd, McAlloc | npages);
	}

	pno = inb(port + AllocRes);
	if (pno & ArFailed) {
		outb(port + IntrMask, inb(port + IntrMask) | IntAlloc);
		ctlr->txbp = bp;
		ctlr->txtime = MACHP(0)->ticks;
		return;
	}

	outb(port + PktNo, pno);
	outs(port + Pointer, PtrAutoInc);

	len = BLEN(bp);
	outs(port + Data1, 0);
	outb(port + Data1, (len + HdrSize) & 0xFF);
	outb(port + Data1, (len + HdrSize) >> 8);
	outss(port + Data1, bp->rp, len / 2);
	if ((len & 1) == 0) {
		outs(port + Data1, 0);
	} else {
		outb(port + Data1, bp->rp[len - 1]);
		outb(port + Data1, 0x20);	/* no info what 0x20 means */
	}

	outb(port + IntrMask, inb(port + IntrMask) |
			IntTxError | IntTxEmpty);

	outs(port + MmuCmd, McEnqueue);
	freeb(bp);
}
Пример #11
0
/* runs in its own thread so the main thread won't block */
void *fd_log(void *data){
	char *line;

	while(1){
		while( (line = (char *) qget(log_queue)) != NULL ){
			fprintf(log_file, line);
			fflush(log_file);
		}
	}
}
Пример #12
0
static void traverse(STri *t, int op) {
	STri tnew,tr;
	qinit();
	qput(t,op);
	while(qany()) {
		op = qget(&tr);
		if (!reg_stri(&tr)) continue;
		if (op!=Q_OP) { Q_refl(&tr,&tnew);  qput(&tnew,Q_OP);	}
		if (op!=P_OP) { P_refl(&tr,&tnew);  qput(&tnew,P_OP);	}
		if (op!=R_OP) { R_refl(&tr,&tnew);  qput(&tnew,R_OP);	}
		}
	}
Пример #13
0
static void
w_txstart(Ether* ether)
{
	Etherpkt *pkt;
	Ctlr *ctlr;
	Block *bp;
	int len, off;

	if((ctlr = ether->ctlr) == nil || (ctlr->state & (Attached|Power)) != (Attached|Power) || ctlr->txbusy)
		return;

	if((bp = qget(ether->oq)) == nil)
		return;
	pkt = (Etherpkt*)bp->rp;

	//
	// If the packet header type field is > 1500 it is an IP or
	// ARP datagram, otherwise it is an 802.3 packet. See RFC1042.
	//
	memset(&ctlr->txf, 0, sizeof(ctlr->txf));
	if(((pkt->type[0]<<8)|pkt->type[1]) > 1500){
		ctlr->txf.framectl = WF_Data;
		memmove(ctlr->txf.addr1, pkt->d, Eaddrlen);
		memmove(ctlr->txf.addr2, pkt->s, Eaddrlen);
		memmove(ctlr->txf.dstaddr, pkt->d, Eaddrlen);
		memmove(ctlr->txf.srcaddr, pkt->s, Eaddrlen);
		memmove(&ctlr->txf.type, pkt->type, 2);
		bp->rp += ETHERHDRSIZE;
		len = BLEN(bp);
		off = WF_802_11_Off;
		ctlr->txf.dlen = len+ETHERHDRSIZE-WSnapHdrLen;
		hnputs((uchar*)&ctlr->txf.dat[0], WSnap0);
		hnputs((uchar*)&ctlr->txf.dat[1], WSnap1);
		hnputs((uchar*)&ctlr->txf.len, len+ETHERHDRSIZE-WSnapHdrLen);
	}
	else{
		len = BLEN(bp);
		off = WF_802_3_Off;
		ctlr->txf.dlen = len;
	}
	w_write(ctlr, ctlr->txdid, 0, &ctlr->txf, sizeof(ctlr->txf));
	w_write(ctlr, ctlr->txdid, off, bp->rp, len+2);

	if(w_cmd(ctlr, WCmdReclaim|WCmdTx, ctlr->txdid)){
		DEBUG("wavelan: transmit failed\n");
		ctlr->ntxerr++;
	}
	else{
		ctlr->txbusy = 1;
		ctlr->txtmout = 2;
	}
	freeb(bp);
}
Пример #14
0
static int qget_uint64(leveldb::DB* db, const Bytes &name, uint64_t seq, uint64_t *ret){
	std::string val;
	*ret = 0;
	int s = qget(db, name, seq, &val);
	if(s == 1){
		if(val.size() != sizeof(uint64_t)){
			return -1;
		}
		*ret = *(uint64_t *)val.data();
	}
	return s;
}
Пример #15
0
void* lqget(void *qp){
    if(NULL != qp){
        pthread_mutex_t *q_lock = &(((lqtype *)qp)->q_lock);
        int rc = pthread_mutex_lock(q_lock);
        void * ret = qget(((lqtype *)qp)->queue);
        rc = pthread_mutex_unlock(q_lock);
        return ret;
    } else {
	printf("should open queue before using it\n");
	return NULL;
    }
}
Пример #16
0
// @return 0: empty queue, 1: item peeked, -1: error
int SSDB::qfront(const Bytes &name, std::string *item){
	int ret = 0;
	uint64_t seq;
	ret = qget_uint64(this->db, name, QFRONT_SEQ, &seq);
	if(ret == -1){
		return -1;
	}
	if(ret == 0){
		return 0;
	}
	ret = qget(this->db, name, seq, item);
	return ret;
}
Пример #17
0
/*
 * application entry point
 *
 */
int main(int argc, char *argv[])
{
    char *p;

    struct queue *q = qalloc();

    while (argc--) qput(q, *argv++);

    while ((p = qget(q))) printf("%s\n", p);

    qfree(q);

    return 0;
}
Пример #18
0
// @return 0: empty queue, 1: item popped, -1: error
int SSDB::qpop(const Bytes &name, std::string *item){
	Transaction trans(binlogs);
	
	int ret;
	uint64_t seq;
	ret = qget_uint64(this->db, name, QFRONT_SEQ, &seq);
	if(ret == -1){
		return -1;
	}
	if(ret == 0){
		seq = QITEM_MIN_SEQ;
	}
	
	ret = qget(this->db, name, seq, item);
	if(ret == -1){
		return -1;
	}
	if(ret == 0){
		return 0;
	}

	// delete item
	ret = qdel_one(this, name, seq);
	if(ret == -1){
		return -1;
	}

	// update size
	int64_t size = incr_qsize(this, name, -1);
	if(size == -1){
		return -1;
	}
		
	// update front
	if(size > 0){
		seq += 1;
		//log_debug("seq: %" PRIu64 ", ret: %d", seq, ret);
		ret = qset_one(this, name, QFRONT_SEQ, Bytes(&seq, sizeof(seq)));
		if(ret == -1){
			return -1;
		}
	}
		
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("Write error!");
		return -1;
	}
	return 1;
}
Пример #19
0
void * mq_serverLoop(void* ipcarg)
{
	ipc_t ipc;
	ipc = (ipc_t) ipcarg;
	message_t msg;
	
	if(ipc->status == IPCSTAT_DISCONNECTED)
	{
		return NULL;
	}
	
	ipc->status = IPCSTAT_SERVING;
	
    while (ipc->stop != 1) {
    	
        msg = mq_getData(ipc, SERVERKEY);
        if(msg != NULL)
        {
			if(msg->header.to == SERVERKEY)
		    {
		    /*
		    	//[TODO] ver que pasa si hay un mensaje con to = 0
		    	//pero hay que cambiar el to.. 0 no existe*/
		    	
		    	/* Es esto lo que tiene que hacer?*/
		    	qput(ipc->inbox, msg);
		    }
		    else 
		    {
		    	mq_sendData(ipc,msg,msg->header.to);
		    }
        }
        
        msg = qget(ipc->outbox);
        if(msg != NULL)
        {
        	mq_sendData(ipc,msg,SERVERKEY);
        }
    }
    
    mq_disconnect(ipc);
    free(msg);
    return NULL;
}
Пример #20
0
static void
txstart(Ether *ether)
{
	int len;
	Ctlr *ctlr;
	Block *b;
	BD *dre;

	ctlr = ether->ctlr;
	if(ctlr->init)
		return;
	while(ctlr->ntq < Ntdre-1){
		b = qget(ether->oq);
		if(b == 0)
			break;

		dre = &ctlr->tdr[ctlr->tdrh];
		dczap(dre, sizeof(BD));
		if(dre->status & BDReady)
			panic("ether: txstart");

		/*
		 * Give ownership of the descriptor to the chip, increment the
		 * software ring descriptor pointer and tell the chip to poll.
		 */
		len = BLEN(b);
		if(ctlr->txb[ctlr->tdrh] != nil)
			panic("fcc/ether: txstart");
		ctlr->txb[ctlr->tdrh] = b;
		if((ulong)b->rp&1)
			panic("fcc/ether: txstart align");	/* TO DO: ensure alignment */
		dre->addr = PADDR(b->rp);
		dre->length = len;
		dcflush(b->rp, len);
		dcflush(dre, sizeof(BD));
		dre->status = (dre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
		dcflush(dre, sizeof(BD));
/*		ctlr->fcc->ftodr = 1<<15;	/* transmit now; Don't do this according to errata */
		ctlr->ntq++;
		ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
	}
}
Пример #21
0
static void *cruncher(void *args) {
    double val;
    int f_depth;
    QueueElement_t *qe;
    CruncherInput_t *input = (CruncherInput_t *)args;
    // Wait loop
    while (!(output.calc_complete && !input->queue->num_elements)) {
        // CRITICAL SECTION
        // Grab element
        pthread_mutex_lock(&q_lock);
        qe = (QueueElement_t *)qget(input->queue->qp);
        // END CRITICAL SECTION

        if (qe == NULL) {
            pthread_mutex_unlock(&q_lock);
            sleep(CRUNCHER_WAIT_TIME);
            continue;

        }
        else {
            input->queue->num_elements--;
            //printf("Item taken from queue, queue now holds %d\n", input->queue->num_elements);
            //fflush(stdout);
            pthread_mutex_unlock(&q_lock);

        }
        // Crunch division
        val = integrate(qe->fp, qe->a, qe->b, qe->p, 0, 0, &f_depth);
        
        // Grab lock
        pthread_mutex_lock(&a_lock);
        // CRITICAL SECTION
        // Add result to accumulator
        output.accumulator += val;
        output.depth += f_depth;
        pthread_mutex_unlock(&a_lock);
        // END CRITICAL SECTION
    }
    return NULL;
}
Пример #22
0
static void
txfill(Ether*ether, Ctlr*ctlr)
{
	int len;
	Block *b;
	ushort*dst;

	while(ctlr->ntx<Ntx){
		if((b=qget(ether->oq)) == nil)
			break;

		len = BLEN(b);
		dst = (ushort*)(Ethermem+(ctlr->txempty+Nrx)*Etherfsize);
		*dst = len;
		memmove(&dst[1], b->rp, len);
		ctlr->ntx++;
		ctlr->txempty++;
		if(ctlr->txempty==Ntx)
			ctlr->txempty = 0;
		freeb(b);
	}
}
Пример #23
0
static void
txstart(Ether* ether)
{
	Ctlr *ctlr;
	Block *bp;
	Des *des;
	int control;

	ctlr = ether->ctlr;
	while(ctlr->ntq < (ctlr->ntdr-1)){
		if(ctlr->setupbp){
			bp = ctlr->setupbp;
			ctlr->setupbp = 0;
			control = Ic|Set|BLEN(bp);
		}
		else{
			bp = qget(ether->oq);
			if(bp == nil)
				break;
			control = Ic|Lseg|Fseg|BLEN(bp);
		}

		ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;
		des = &ctlr->tdr[ctlr->tdrh];
		des->bp = bp;
		des->addr = PCIWADDR(bp->rp);
		des->control |= control;
		ctlr->ntq++;
		coherence();
		des->status = Own;
		csr32w(ctlr, 1, 0);
		ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
	}

	if(ctlr->ntq > ctlr->ntqmax)
		ctlr->ntqmax = ctlr->ntq;
}
Пример #24
0
/* Consumer thread, take from queue and execute user callback */
static void *recthread2(void *arg)
{
	header *hdr;
	signal *sig;
	char *msg;

	for (;;) {
		msg = qget(queue_index);
		hdr = (header *) msg;
		print(LOG_INFO, "Taking msg from queue with msg_type %d\n",
		      hdr->msg_type);
		switch (hdr->msg_type) {
		case DATA:
			if (callbackdata != NULL) {
				callbackdata(hdr->proc_name,
					     (msg + SIZEOF_HEADER),
					     hdr->msg_len);
				free(msg);
			} else {
				print(LOG_WARNING,
				      "No callback for msg_type %d\n", DATA);
			}
			break;

		case SIGNAL1:
			sig = (signal *) (msg + SIZEOF_HEADER);
			if (callback1 != NULL) {
				callback1(hdr->proc_name, sig->signal1);
				free(msg);
			} else {
				print(LOG_WARNING,
				      "No callback for msg_type %d\n", SIGNAL1);
			}
			break;

		case SIGNAL2:
			sig = (signal *) (msg + SIZEOF_HEADER);
			if (callback2 != NULL) {
				callback2(hdr->proc_name, sig->signal1,
					  sig->signal2);
				free(msg);
			} else {
				print(LOG_WARNING,
				      "No callback for msg_type %d\n", SIGNAL2);
			}
			break;

		case SIGNAL3:
			sig = (signal *) (msg + SIZEOF_HEADER);
			if (callback3 != NULL) {
				callback3(hdr->proc_name, sig->signal1,
					  sig->signal2, sig->signal3);
				free(msg);
			} else {
				print(LOG_WARNING,
				      "No callback for msg_type %d\n", SIGNAL3);
			}
			break;

		default:
			print(LOG_ERR, "Illeagal msg_type %d\n", hdr->msg_type);
			free(msg);
			break;
		}
	}
	return (void *)0;
}
Пример #25
0
/*
 * move blocks between queues if they are ready.
 * schedule an interrupt for the next interesting time.
 *
 * must be called with the link ilocked.
 */
static void
pushlink(Link *link, vlong now)
{
	Block *bp;
	vlong tout, tin;

	/*
	 * put another block in the link queue
	 */
	ilock(link);
	if(link->iq == nil || link->oq == nil){
		iunlock(link);
		return;

	}
	timerdel(&link->ci);

	/*
	 * put more blocks into the xmit queue
	 * use the time the last packet was supposed to go out
	 * as the start time for the next packet, rather than
	 * the current time.  this more closely models a network
	 * device which can queue multiple output packets.
	 */
	tout = link->tout;
	if(!tout)
		tout = now;
	while(tout <= now){
		bp = qget(link->oq);
		if(bp == nil){
			tout = 0;
			break;
		}

		/*
		 * can't send the packet before it gets queued
		 */
		tin = gtime(bp->rp);
		if(tin > tout)
			tout = tin;
		tout = tout + (BLEN(bp) - Tmsize) * link->delayn;

		/*
		 * drop packets
		 */
		if(link->droprate && nrand(link->droprate) == 0)
			link->drops++;
		else{
			ptime(bp->rp, tout + link->delay0ns);
			if(link->tq == nil)
				link->tq = bp;
			else
				link->tqtail->next = bp;
			link->tqtail = bp;
		}
	}

	/*
	 * record the next time a packet can be sent,
	 * but don't schedule an interrupt if none is waiting
	 */
	link->tout = tout;
	if(!qcanread(link->oq))
		tout = 0;

	/*
	 * put more blocks into the receive queue
	 */
	tin = 0;
	while(bp = link->tq){
		tin = gtime(bp->rp);
		if(tin > now)
			break;
		bp->rp += Tmsize;
		link->tq = bp->next;
		bp->next = nil;
		if(!link->indrop)
			qpassnolim(link->iq, bp);
		else if(qpass(link->iq, bp) < 0)
			link->soverflows++;
		tin = 0;
	}
	if(bp == nil && qisclosed(link->oq) && !qcanread(link->oq) && !qisclosed(link->iq))
		qhangup(link->iq, nil);
	link->tin = tin;
	if(!tin || tin > tout && tout)
		tin = tout;

	link->ci.ns = tin - now;
	if(tin){
		if(tin < now)
			panic("loopback unfinished business");
		timeradd(&link->ci);
	}
	iunlock(link);
}
Пример #26
0
Файл: esp.c Проект: 8l/inferno
static void
espkick(void *x)
{
	Conv *c = x;
	Esphdr *eh;
	Esptail *et;
	Userhdr *uh;
	Espcb *ecb;
	Block *bp;
	int nexthdr;
	int payload;
	int pad;
	int align;
	uchar *auth;

	bp = qget(c->wq);
	if(bp == nil)
		return;

	qlock(c);
	ecb = c->ptcl;

	if(ecb->header) {
		/* make sure the message has a User header */
		bp = pullupblock(bp, UserhdrSize);
		if(bp == nil) {
			qunlock(c);
			return;
		}
		uh = (Userhdr*)bp->rp;
		nexthdr = uh->nexthdr;
		bp->rp += UserhdrSize;
	} else {
		nexthdr = 0;  // what should this be?
	}

	payload = BLEN(bp) + ecb->espivlen;

	/* Make space to fit ip header */
	bp = padblock(bp, EsphdrSize + ecb->espivlen);

	align = 4;
	if(ecb->espblklen > align)
		align = ecb->espblklen;
	if(align % ecb->ahblklen != 0)
		panic("espkick: ahblklen is important after all");
	pad = (align-1) - (payload + EsptailSize-1)%align;

	/*
	 * Make space for tail
	 * this is done by calling padblock with a negative size
	 * Padblock does not change bp->wp!
	 */
	bp = padblock(bp, -(pad+EsptailSize+ecb->ahlen));
	bp->wp += pad+EsptailSize+ecb->ahlen;

	eh = (Esphdr *)(bp->rp);
	et = (Esptail*)(bp->rp + EsphdrSize + payload + pad);

	// fill in tail
	et->pad = pad;
	et->nexthdr = nexthdr;

	ecb->cipher(ecb, bp->rp+EsphdrSize, payload+pad+EsptailSize);
	auth = bp->rp + EsphdrSize + payload + pad + EsptailSize;

	// fill in head
	eh->vihl = IP_VER4;
	hnputl(eh->espspi, ecb->spi);
	hnputl(eh->espseq, ++ecb->seq);
	v6tov4(eh->espsrc, c->laddr);
	v6tov4(eh->espdst, c->raddr);
	eh->espproto = IP_ESPPROTO;
	eh->frag[0] = 0;
	eh->frag[1] = 0;

	ecb->auth(ecb, bp->rp+IphdrSize, (EsphdrSize-IphdrSize)+payload+pad+EsptailSize, auth);

	qunlock(c);
	//print("esp: pass down: %uld\n", BLEN(bp));
	ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c);
}
Пример #27
0
Файл: esp.c Проект: npe9/harvey
/*
 * encapsulate next IP packet on x's write queue in IP/ESP packet
 * and initiate output of the result.
 */
static void
espkick(void *x)
{
	int nexthdr, payload, pad, align;
	uint8_t *auth;
	Block *bp;
	Conv *c = x;
	Esp4hdr *eh4;
	Esp6hdr *eh6;
	Espcb *ecb;
	Esptail *et;
	Userhdr *uh;
	Versdep vers;

	getverslens(convipvers(c), &vers);
	bp = qget(c->wq);
	if(bp == nil)
		return;

	qlock(c);
	ecb = c->ptcl;

	if(ecb->header) {
		/* make sure the message has a User header */
		bp = pullupblock(bp, Userhdrlen);
		if(bp == nil) {
			qunlock(c);
			return;
		}
		uh = (Userhdr*)bp->rp;
		nexthdr = uh->nexthdr;
		bp->rp += Userhdrlen;
	} else {
		nexthdr = 0;	/* what should this be? */
	}

	payload = BLEN(bp) + ecb->espivlen;

	/* Make space to fit ip header */
	bp = padblock(bp, vers.hdrlen + ecb->espivlen);
	getpktspiaddrs(bp->rp, &vers);

	align = 4;
	if(ecb->espblklen > align)
		align = ecb->espblklen;
	if(align % ecb->ahblklen != 0)
		panic("espkick: ahblklen is important after all");
	pad = (align-1) - (payload + Esptaillen-1)%align;

	/*
	 * Make space for tail
	 * this is done by calling padblock with a negative size
	 * Padblock does not change bp->wp!
	 */
	bp = padblock(bp, -(pad+Esptaillen+ecb->ahlen));
	bp->wp += pad+Esptaillen+ecb->ahlen;

	et = (Esptail*)(bp->rp + vers.hdrlen + payload + pad);

	/* fill in tail */
	et->pad = pad;
	et->nexthdr = nexthdr;

	/* encrypt the payload */
	ecb->cipher(ecb, bp->rp + vers.hdrlen, payload + pad + Esptaillen);
	auth = bp->rp + vers.hdrlen + payload + pad + Esptaillen;

	/* fill in head; construct a new IP header and an ESP header */
	if (vers.version == V4) {
		eh4 = (Esp4hdr *)bp->rp;
		eh4->vihl = IP_VER4;
		v6tov4(eh4->espsrc, c->laddr);
		v6tov4(eh4->espdst, c->raddr);
		eh4->espproto = IP_ESPPROTO;
		eh4->frag[0] = 0;
		eh4->frag[1] = 0;

		hnputl(eh4->espspi, ecb->spi);
		hnputl(eh4->espseq, ++ecb->seq);
	} else {
		eh6 = (Esp6hdr *)bp->rp;
		eh6->vcf[0] = IP_VER6;
		ipmove(eh6->src, c->laddr);
		ipmove(eh6->dst, c->raddr);
		eh6->proto = IP_ESPPROTO;

		hnputl(eh6->espspi, ecb->spi);
		hnputl(eh6->espseq, ++ecb->seq);
	}

	/* compute secure hash */
	ecb->auth(ecb, bp->rp + vers.iphdrlen, (vers.hdrlen - vers.iphdrlen) +
		payload + pad + Esptaillen, auth);

	qunlock(c);
	/* print("esp: pass down: %uld\n", BLEN(bp)); */
	if (vers.version == V4)
		ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c);
	else
		ipoput6(c->p->f, bp, 0, c->ttl, c->tos, c);
}
Пример #28
0
static void
vt6102transmit(Ether* edev)
{
	Block *bp;
	Ctlr *ctlr;
	Ds *ds, *next;
	int control, i, o, prefix, size, tdused, timeo;

	ctlr = edev->ctlr;

	ilock(&ctlr->tlock);

	/*
	 * Free any completed packets
	 */
	ds = ctlr->tdh;
	for(tdused = ctlr->tdused; tdused > 0; tdused--){
		/*
		 * For some errors the chip will turn the Tx engine
		 * off. Wait for that to happen.
		 * Could reset and re-init the chip here if it doesn't
		 * play fair.
		 * To do: adjust Tx FIFO threshold on underflow.
		 */
		if(ds->status & (Abt|Tbuff|Udf)){
			for(timeo = 0; timeo < 1000; timeo++){
				if(!(csr16r(ctlr, Cr) & Txon))
					break;
				microdelay(1);
			}
			ds->status = Own;
			csr32w(ctlr, Txdaddr, PCIWADDR(ds));
		}

		if(ds->status & Own)
			break;
		ds->addr = 0;
		ds->branch = 0;

		if(ds->bp != nil){
			freeb(ds->bp);
			ds->bp = nil;
		}
		for(i = 0; i < Ntxstats-1; i++){
			if(ds->status & (1<<i))
				ctlr->txstats[i]++;
		}
		ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT;

		ds = ds->next;
	}
	ctlr->tdh = ds;

	/*
	 * Try to fill the ring back up.
	 */
	ds = ctlr->tdt;
	while(tdused < ctlr->ntd-2){
		if((bp = qget(edev->oq)) == nil)
			break;
		tdused++;

		size = BLEN(bp);
		prefix = 0;

		if(o = (((int)bp->rp) & 0x03)){
			prefix = Txcopy-o;
			if(prefix > size)
				prefix = size;
			memmove(ds->bounce, bp->rp, prefix);
			ds->addr = PCIWADDR(ds->bounce);
			bp->rp += prefix;
			size -= prefix;
		}

		next = ds->next;
		ds->branch = PCIWADDR(ds->next);

		if(size){
			if(prefix){
				next->bp = bp;
				next->addr = PCIWADDR(bp->rp);
				next->branch = PCIWADDR(next->next);
				next->control = Edp|Chain|((size<<TbsSHIFT) & TbsMASK);

				control = Stp|Chain|((prefix<<TbsSHIFT) & TbsMASK);

				next = next->next;
				tdused++;
				ctlr->tsplit++;
			}
			else{
				ds->bp = bp;
				ds->addr = PCIWADDR(bp->rp);
				control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK);
				ctlr->taligned++;
			}
		}
		else{
			freeb(bp);
			control = Edp|Stp|((prefix<<TbsSHIFT) & TbsMASK);
			ctlr->tcopied++;
		}

		ds->control = control;
		if(tdused >= ctlr->ntd-2){
			ds->control |= Ic;
			ctlr->txdw++;
		}
		coherence();
		ds->status = Own;

		ds = next;
	}
	ctlr->tdt = ds;
	ctlr->tdused = tdused;
	if(ctlr->tdused)
		csr16w(ctlr, Cr, Tdmd|ctlr->cr);

	iunlock(&ctlr->tlock);
}
Пример #29
0
void
rudpkick(void *x)
{
	Proc *up = externup();
	Conv *c = x;
	Udphdr *uh;
	uint16_t rport;
	uint8_t laddr[IPaddrlen], raddr[IPaddrlen];
	Block *bp;
	Rudpcb *ucb;
	Rudphdr *rh;
	Reliable *r;
	int dlen, ptcllen;
	Rudppriv *upriv;
	Fs *f;

	upriv = c->p->priv;
	f = c->p->f;

	netlog(c->p->f, Logrudp, "rudp: kick\n");
	bp = qget(c->wq);
	if(bp == nil)
		return;

	ucb = (Rudpcb*)c->ptcl;
	switch(ucb->headers) {
	case 7:
		/* get user specified addresses */
		bp = pullupblock(bp, UDP_USEAD7);
		if(bp == nil)
			return;
		ipmove(raddr, bp->rp);
		bp->rp += IPaddrlen;
		ipmove(laddr, bp->rp);
		bp->rp += IPaddrlen;
		/* pick interface closest to dest */
		if(ipforme(f, laddr) != Runi)
			findlocalip(f, laddr, raddr);
		bp->rp += IPaddrlen;		/* Ignore ifc address */
		rport = nhgets(bp->rp);
		bp->rp += 2+2;			/* Ignore local port */
		break;
	default:
		ipmove(raddr, c->raddr);
		ipmove(laddr, c->laddr);
		rport = c->rport;
		break;
	}

	dlen = blocklen(bp);

	/* Make space to fit rudp & ip header */
	bp = padblock(bp, UDP_IPHDR+UDP_RHDRSIZE);
	if(bp == nil)
		return;

	uh = (Udphdr *)(bp->rp);
	uh->vihl = IP_VER4;

	rh = (Rudphdr*)uh;

	ptcllen = dlen + (UDP_RHDRSIZE-UDP_PHDRSIZE);
	uh->Unused = 0;
	uh->udpproto = IP_UDPPROTO;
	uh->frag[0] = 0;
	uh->frag[1] = 0;
	hnputs(uh->udpplen, ptcllen);
	switch(ucb->headers){
	case 7:
		v6tov4(uh->udpdst, raddr);
		hnputs(uh->udpdport, rport);
		v6tov4(uh->udpsrc, laddr);
		break;
	default:
		v6tov4(uh->udpdst, c->raddr);
		hnputs(uh->udpdport, c->rport);
		if(ipcmp(c->laddr, IPnoaddr) == 0)
			findlocalip(f, c->laddr, c->raddr);
		v6tov4(uh->udpsrc, c->laddr);
		break;
	}
	hnputs(uh->udpsport, c->lport);
	hnputs(uh->udplen, ptcllen);
	uh->udpcksum[0] = 0;
	uh->udpcksum[1] = 0;

	qlock(&ucb->ql);
	r = relstate(ucb, raddr, rport, "kick");
	r->sndseq = NEXTSEQ(r->sndseq);
	hnputl(rh->relseq, r->sndseq);
	hnputl(rh->relsgen, r->sndgen);

	hnputl(rh->relack, r->rcvseq);  /* ACK last rcvd packet */
	hnputl(rh->relagen, r->rcvgen);

	if(r->rcvseq != r->acksent)
		r->acksent = r->rcvseq;

	hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, dlen+UDP_RHDRSIZE));

	relackq(r, bp);
	qunlock(&ucb->ql);

	upriv->ustats.rudpOutDatagrams++;

	DPRINT("sent: %lud/%lud, %lud/%lud\n",
		r->sndseq, r->sndgen, r->rcvseq, r->rcvgen);

	doipoput(c, f, bp, 0, c->ttl, c->tos);

	if(waserror()) {
		relput(r);
		qunlock(&r->lock);
		nexterror();
	}

	/* flow control of sorts */
	qlock(&r->lock);
	if(UNACKED(r) > Maxunacked){
		r->blocked = 1;
		sleep(&r->vous, flow, r);
		r->blocked = 0;
	}

	qunlock(&r->lock);
	relput(r);
	poperror();
}
Пример #30
0
int main(void) {
    /* Create two empty queues */
    void *q1;
    void *q2;
    void *pt;
    int a,b,c,d,e,f,g,h,i,j,k;
    int x;
    int ii;
    a = 1;
    b = 4;
    c = 65;
    d = 34;
    f = 6;
    e = 9;
    g = 11;
    h = 23;
    i = 999;
    j = 234;
    k = 94;

    q1 = qopen();
    q2 = qopen();

    /* Fill both */
    qput(q1, &a);
    qput(q1, &b);
    qput(q1, &c);
    qput(q1, &d);
    qput(q1, &e);
    qput(q1, &f);
    qput(q2, &g);
    qput(q2, &h);
    qput(q2, &i);
    qput(q2, &j);
    qput(q2, &k);

    /* Get an item out of q1 */
    pt = qget(q1);
    if (*((int *)pt) != 1) {
        printf("Fail on qget; returned %d.\n", *((int *)pt));
        return -1;

    }

    /* Catenate */
    qconcat(q1, q2);

    /* Remove until null is returned, count number of iterations */
    for (ii = 0; pt != NULL; ii++) {
        pt = qget(q1);

    }
    if (ii != 11) {
        printf("Fail on catenate; queue was of size %d.\n", ii);
        return -1;

    }

    /* Use remove to take out a specified value  */
    qput(q1, &a);
    qput(q1, &b);
    qput(q1, &c);
    qput(q1, &d);
    qput(q1, &e);
    qput(q1, &f);
    qput(q1, &g);
    qput(q1, &h);
    qput(q1, &i);
    qput(q1, &j);
    qput(q1, &k);
    x = 999;
    pt = qremove(q1, searchfn, &x);
    if (pt == NULL || *((int *)pt) != 999) {
        if (pt == NULL) {
            printf("Fail on qsearch; value not found.\n");

        }
        else {
            printf("Fail on qremove / qsearch; removed value was %d.\n", *((int *)pt));

        }
    }
    /* Use qapply to print out remaining list */
    qapply(q1, printfn);
    return 1;

}