⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pfilt.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Used in filter processing to avoid having to do an m_pullup */struct enpextent {	long	afterEnd;	/* pkt offset of first byte after extent */	long	offset;		/* pkt offset of first byte of extent */					/* LONG SIGNED TO MAKE IT RUN FAST */	char   *data;		/* memory address of first byte of extent */};#define	MAX_EXTENTS	16	/* enough for an ether pkt in mbufs */#define	MAX_OFFSET	(2<<ENF_NBPA)				/* guaranteed to be larger than any offset				   that can be embedded in a filter *//* #define	SELF_PROF	1 */#ifdef	SELF_PROFint	enSelfProf = 0;		/* set this non-zero for profiling */struct	timeval enPerPktProf = {0, 0};int	enPktCount = 0;struct	timeval enPerFiltProf = {0, 0};int	enFiltCount = 0;struct	timeval enCalibrateProf = {0, 0};int	enCalibrateCount = 0;#endif	SELF_PROF/**************************************************************** *								* *		Various Macros & Routines			* *								* ****************************************************************//* *  forAllOpenDescriptors(p) -- a macro for iterating *  over all currently open devices.  Use it in place of *      "for ( ...; ... ; ... )" *  and supply your own loop body.  The loop variable is the *  parameter p which is set to point to the descriptor for *  each open device in turn. */#define forAllOpenDescriptors(p)					\	for ((p) = (struct enOpenDescriptor *)enDesq.enQ_F;		\	      (struct Queue *)(&enDesq) != &((p)->enOD_Link);		\	      (p) = (struct enOpenDescriptor *)(p)->enOD_Link.F)/* *  enEnqueue - add an element to a queue */#define	PfiltEnqueue(q, elt)						\{									\	pfiltenqueue((struct Queue *)(q), (struct Queue *)(elt));		\	(q)->enQ_NumQueued++;						\}/* *  PfiltFlushQueue - release all packets from queue, freeing any *  whose reference counts drop to 0.  Assumes caller *  is at high IPL so that queue will not be modified while *  it is being flushed. */PfiltFlushQueue(q)register struct enQueue *q;{   register struct enPacket *qelt;    smp_lock(&lk_pfilt, LK_RETRY);    pfiltdequeue((struct Queue *)q, qelt);    /* "qelt" is filled in at the end of the call pfiltdequeue */    while(qelt != NULL)    {	if (0 == --(qelt->enP_RefCount))	{	    PfiltEnqueue(&enFreeq, qelt);	}	pfiltdequeue((struct Queue *)q, qelt);    }    q->enQ_NumQueued = 0;    smp_unlock(&lk_pfilt);}/* *  PfiltInitWaitQueue - initialize an empty packet wait queue */PfiltInitWaitQueue(wq)register struct enWaitQueue *wq;{			    wq->enWQ_Head = 0;    wq->enWQ_Tail = 0;    wq->enWQ_NumQueued = 0;    wq->enWQ_MaxWaiting = ENDEFWAITING;}/* *  PfiltEnWaitQueue - add a packet to a wait queue *  SMP: assumes lock held coming in */PfiltEnWaitQueue(wq, p)register struct enWaitQueue *wq;struct enPacket *p;{    if (smp_debug) {	if (!(smp_owner(&lk_pfilt)))		panic("PfiltEnWaitQueue: not lock owner");    }    wq->enWQ_Packets[wq->enWQ_Tail] = p;    wq->enWQ_NumQueued++;    PfiltNextWaitQueueIndex(wq->enWQ_Tail);}/* *  PfiltDeWaitQueue - remove a packet from a wait queue *  SMP: assumes lock held coming in */struct enPacket *PfiltDeWaitQueue(wq)register struct enWaitQueue *wq;{    struct enPacket *p;    if (smp_debug) {	if (!(smp_owner(&lk_pfilt)))		panic("PfiltDeWaitQueue: not lock owner");    }    if (wq->enWQ_NumQueued < 1)    	panic("PfiltDeWaitQueue");    wq->enWQ_NumQueued--;    p = wq->enWQ_Packets[wq->enWQ_Head];    PfiltNextWaitQueueIndex(wq->enWQ_Head);    return(p);}/* *  PfiltPutBack - undo the effect of PfiltDeWaitQueue; MUST be called *	immediately after corresponding PfiltDeWaitQueue with no *	intervening interrupts! *  SMP: assumes lock held coming in */PfiltPutBack(wq, p)register struct enWaitQueue *wq;struct enPacket *p;{    if (smp_debug) {	if (!(smp_owner(&lk_pfilt)))		panic("PfiltPutBack: not lock owner");    }    PfiltPrevWaitQueueIndex(wq->enWQ_Head);    wq->enWQ_Packets[wq->enWQ_Head] = p;    wq->enWQ_NumQueued++;}/* *  PfiltTrimWaitQueue - cut a wait queue back to size *  SMP: assumes lock held coming in */PfiltTrimWaitQueue(d, threshold)register struct enOpenDescriptor *d;int threshold;{    register struct enWaitQueue *wq = &(d->enOD_Waiting);    register int Counter = (wq->enWQ_NumQueued - threshold);    register struct enPacket *p;    if (smp_debug) {	if (!(smp_owner(&lk_pfilt)))		panic("PfiltTrimWaitQueue: not lock owner");    }#ifdef	DEBUG    Pfiltprintf(ENDBG_SCAV)    		("PfiltTrimWaitQueue(%x, %d): %d\n", d, threshold, Counter);#endif    while (Counter-- > 0)    {	wq->enWQ_NumQueued--;	PfiltPrevWaitQueueIndex(wq->enWQ_Tail);	p = wq->enWQ_Packets[wq->enWQ_Tail];	d->enOD_Drops += (1 + p->enP_Stamp.ens_dropped);	    /* dropped this packet and it might have recorded other drops. */	enScavDrops++;	if (0 == --(p->enP_RefCount))	{	    m_freem(p->enP_mbuf);	    PfiltEnqueue(&enFreeq, p);	}    }}/* *  PfiltFlushWaitQueue - remove all packets from wait queue */#define	PfiltFlushWaitQueue(wq)	PfiltTrimWaitQueue(wq, 0)/* *  scavenging thresholds: * *  index by number of active files;  for N open files, each queue may retain *  up to 1/Nth of the packets not guaranteed to be freed on scavenge.  The *  total number of available packets is computed less one for sending. *  (assumes high IPL) */unsigned short enScavLevel[NPACKETFILTER+1];/* *  PfiltInitScavenge -- set up ScavLevel table */PfiltInitScavenge(){    register int PoolSize = (ENPACKETS-ENMINSCAVENGE);    register int i = sizeof(enScavLevel)/sizeof(enScavLevel[0]);    PoolSize--;		/* leave one for transmitter */    while (--i>0)	enScavLevel[i] = (PoolSize / i);}/* *  PfiltScavenge -- scan all OpenDescriptors for all ethernets, releasing *    any queued buffers beyond the prescribed limit and freeing any whose *    refcounts drop to 0. *    Assumes caller is at high IPL so that it is safe to modify the queues. *    SMP: assumes lock held coming in */PfiltScavenge(){    register struct enOpenDescriptor *d;    register int threshold = 0;    register struct enState *enStatep;    register int unit;    if (smp_debug) {	if (!(smp_owner(&lk_pfilt)))		panic("PfiltScavenge: not lock owner");    }    for (unit = 0; unit < enUnits; unit++) {	enStatep = enStatePs[unit];	threshold += enCurOpens;    }    threshold = enScavLevel[threshold];    enScavenges++;#ifdef	DEBUG    Pfiltprintf(ENDBG_SCAV)("PfiltScavenge: %d\n", threshold);#endif    for (unit = 0; unit < enUnits; unit++) {	enStatep = enStatePs[unit];	if (enDesq.enQ_F == 0)	    continue;			/* never initialized */	forAllOpenDescriptors(d)	{	    PfiltTrimWaitQueue(d, threshold);	}    }}/* *  PfiltAllocatePacket - allocate the next packet from the free list *  Assumes IPL is at high priority so that it is safe to touch the *  packet queue.  If the queue is currently empty, scavenge for *  more packets. *  SMP: assumes lock held coming in */struct enPacket *PfiltAllocatePacket(){    register struct enPacket *p;    if (smp_debug) {	if (!(smp_owner(&lk_pfilt)))		panic("PfiltAllocatePacket: not lock owner");    }    if (0 == enFreeq.enQ_NumQueued)	PfiltScavenge();    pfiltdequeue((struct Queue *)&enFreeq, p);   /* "p" is filled in at the end of the call, pfiltdequeue */    if (p == NULL)	panic("PfiltAllocatePacket");    if (enFreeqMin > --enFreeq.enQ_NumQueued)	enFreeqMin = enFreeq.enQ_NumQueued;    p->enP_RefCount = 0;	/* just in case */    return(p);}/* *  PfiltDeallocatePacket - place the packet back on the free packet queue *  (High IPL assumed). */#define	PfiltDeallocatePacket(p)						\{									\	if (p->enP_RefCount) panic("PfiltDeallocatePacket: refcount != 0");\	pfiltenqueue((struct Queue *)&enFreeq, (struct Queue *)(p));		\	enFreeq.enQ_NumQueued++;					\}/**************************************************************** *								* *	    Routines to move uio data to/from mbufs		* *								* ****************************************************************//* * These two routines were inspired by/stolen from ../sys/uipc_socket.c *	   Both return error code (or 0 if success). *//* * read: return contents of mbufs to user.  DO NOT free them, since *	there may be multiple claims on the packet! */Pfiltrmove(p, uio, flags, padneeded, truncation)struct enPacket *p;register struct uio *uio;short flags;int *padneeded;			/* by reference, so we can change it */int truncation;{	register int len;	register int count;	register int error = 0;	register struct mbuf *m = p->enP_mbuf;	int total = 0;	int pn = *padneeded;		/* first, transfer header stamp */	if (flags & (ENTSTAMP|ENBATCH)) {	    if (uio->uio_resid >= (sizeof(struct enstamp) + pn)) {		error = uiomove((caddr_t)&(p->enP_Stamp) - pn,				    sizeof(struct enstamp) + pn,				    UIO_READ, uio);		if (error)		    return(error);	    }	    else {	/* no room for stamp */	    	uio->uio_resid = 0;	/* make sure Pfiltread() exits */		return(EMSGSIZE);	    }	}	count = min(p->enP_ByteCount, uio->uio_resid); /* # bytes to return */	if (count > truncation)	    count = truncation;	while ((count > 0) && m && (error == 0)) {	    len = min(count, m->m_len);	/* length of this transfer */	    count -= len;	    total += len;	    error = uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);	    	    m = m->m_next;	}#if	DEBUG	if ((error == 0) && (total != p->enP_ByteCount) &&		(truncation > p->enP_ByteCount) &&		(uio->uio_resid != 0)) {	    Pfiltprintf(ENDBG_MISC)("Pfiltrmove: %d != %d (resid %d)\n",					total, p->enP_ByteCount,					uio->uio_resid);	}#endif	DEBUG	    	/*	 * record how much padding is needed if another packet is batched	 * following this one in the same read()	 */	if ((total &= ENALIGNMASK) == 0) {	    *padneeded = 0;	/* already aligned */	}	else {	    *padneeded = ENALIGNMENT - total;	}	return(error);}Pfiltwmove(uio, mbufp)register struct uio *uio;register struct mbuf **mbufp;	/* top mbuf is returned by reference */{	struct mbuf *mtop = 0;	register struct mbuf *m;	register struct mbuf **mp = &mtop;	register struct iovec *iov;	register int len;	int error = 0;		while ((uio->uio_resid > 0) && (error == 0)) {	    iov = uio->uio_iov;	    	    if (iov->iov_len == 0) {	    	uio->uio_iov++;		uio->uio_iovcnt--;		if (uio->uio_iovcnt < 0)		    panic("Pfiltwmove: uio_iovcnt < 0 while uio_resid > 0");	    }	    MGET(m, M_WAIT, MT_DATA);	    if (m == NULL) {#ifdef	DEBUG		Pfiltprintf(ENDBG_NOMEM)("Pfiltwmove: MGET\n");#endif	    	error = ENOBUFS;		break;	    }	    if (iov->iov_len >= CLBYTES) {	/* big enough to use a page */		register struct mbuf *p;		MCLGET(m, p);		if (p == 0)		    goto nopages;		len = CLBYTES;	    }	    else {nopages:		len = MIN(MLEN, iov->iov_len);	    }	    error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);	    m->m_len = len;	    *mp = m;	    mp = &(m->m_next);	}	if (error) {		/* probably uiomove fouled up */	    if (mtop)		m_freem(mtop);	}	else {	    *mbufp = mtop;	/* return ptr to top mbuf */	}	return(error);}/* *  Pfilt_open - open ether net device * *  Errors:	ENXIO	- illegal minor device number *		EBUSY	- minor device already in use *		ENOBUFS	- KM_ALLOC failed *//* ARGSUSED */Pfilt_open(dev, flag, newmin)dev_t dev;int flag;int *newmin;{    register int md;    register int unit;    register struct enState *enStatep;    register int error;    int s;#ifdef	DEBUG    Pfiltprintf(ENDBG_TRACE)("Pfilt_open(%o, %x):\n", dev, flag);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -