Annotation of researchv9/sys/net/packet.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *            P A C K E T
        !             3:  *
        !             4:  * Utilities for working with "packets".  These are groups of (stream) data
        !             5:  * blocks terminated by a delimiter.  When these blocks are removed from a
        !             6:  * queue, they are kept as a chain of blocks, without the final M_DELIM, and
        !             7:  * are referred to as a dequeued packet.
        !             8:  *
        !             9:  *
        !            10:  * Written by Kurt Gollhardt  (Nirvonics, Inc.)
        !            11:  * Last update Wed Feb 12 21:24:10 1986
        !            12:  *
        !            13:  */
        !            14: 
        !            15: #include "../h/param.h"
        !            16: #include "../h/stream.h"
        !            17: 
        !            18: #define PKT_COMPLETE    0
        !            19: #define PKT_PARTIAL     1
        !            20: 
        !            21: 
        !            22: /*
        !            23:  * This routine does all the work for a server on a queue using packets.
        !            24:  * Arguments provide routines to do the application-specific operations:
        !            25:  *   'blocked' is called with a pointer to the queue;
        !            26:  *       it should return non-zero if the location which the first
        !            27:  *       packet on the queue would be sent to is full.  If it does
        !            28:  *       return non-zero, it must ensure that this queue will be
        !            29:  *       re-enabled when the blocking condition goes away.
        !            30:  *   'allow_partial' is called with a pointer to the queue;
        !            31:  *       it should return non-zero if this queue is allowed to receive
        !            32:  *       partial packets at any time.  (Any queue may be given partial
        !            33:  *       packets if not doing so would cause a deadlock.)
        !            34:  *   'process' is called with a pointer to the queue, a dequeued
        !            35:  *       packet (struct block *), and a flag which is non-zero if
        !            36:  *       this is a partial packet.
        !            37:  */
        !            38: packet_srvp(q, delim_count, blocked, allow_partial, process, other)
        !            39:      register struct queue    *q;      /* queue being serviced */
        !            40:      int           *delim_count;       /* ptr to count of delims on queue */
        !            41:      int           (*blocked)();       /* routine to see if a queue blocks */
        !            42:      int           (*allow_partial)(); /* routine to say if partial pkts ok */
        !            43:      int           (*process)();       /* routine to process a packet */
        !            44:      int           (*other)();         /* routine to handle misc blocks */
        !            45: {
        !            46:      register struct block    *bp, *first_bp, *prev_bp;
        !            47:      register int       processed = 0;
        !            48:      static check_other();
        !            49: 
        !            50:      check_other(q, other);
        !            51:      while (*delim_count > 0) {
        !            52:          if ((*blocked) (q))
        !            53:               return;
        !            54:          if ((bp = getq(q))->type == M_DELIM)
        !            55:               first_bp = NULL;
        !            56:          else {
        !            57:               first_bp = prev_bp = bp;
        !            58:               while ((bp = getq(q))->type != M_DELIM)
        !            59:                    prev_bp = bp;
        !            60:               prev_bp->next = NULL;
        !            61:          }
        !            62:          freeb(bp);
        !            63:          (*process) (q, first_bp, PKT_COMPLETE);
        !            64:          --*delim_count;
        !            65:          ++processed;
        !            66:          check_other(q, other);
        !            67:      }
        !            68: 
        !            69:      if (q->first != NULL) {
        !            70:          if ((*allow_partial) (q) || /* Huge partial packet */
        !            71:                    ((q->flag & QWANTW) && processed == 0)) {
        !            72:               if ((*blocked) (q))
        !            73:                    return;
        !            74:               first_bp = q->first;
        !            75:               while (getq(q))
        !            76:                    ;
        !            77:               (*process) (q, first_bp, PKT_PARTIAL);
        !            78:          } else
        !            79:               q->flag |= QWANTR;
        !            80:      }
        !            81: }
        !            82: 
        !            83: static check_other(q, other)
        !            84:      register struct queue    *q;
        !            85:      int           (*other)();
        !            86: {
        !            87:      register struct block    *bp;
        !            88: 
        !            89:      while (q->first && q->first->type != M_DATA && q->first->type != M_DELIM) {
        !            90:          bp = getq(q);
        !            91:          if (other)
        !            92:               (*other)(q, bp);
        !            93:          else
        !            94:               freeb(bp);
        !            95:      }
        !            96: }
        !            97: 
        !            98: 
        !            99: /*
        !           100:  * This routine does all the work for a put routine on a queue using packets.
        !           101:  * Arguments provide routines to do the application-specific operations:
        !           102:  *   'ioctl' (optional) is called with a pointer to the queue, and a pointer
        !           103:  *       to an M_IOCTL block.
        !           104:  *   'other' (optional) is called with a pointer to the queue, and a pointer
        !           105:  *       to a block of type other than M_DATA, M_DELIM, or M_IOCTL.
        !           106:  */
        !           107: packet_putp(q, bp, delim_count, ioctl, other)
        !           108:      register struct queue    *q;      /* queue being put onto */
        !           109:      register struct block    *bp;     /* block being put on */
        !           110:      int           *delim_count;       /* ptr to count of delims on queue */
        !           111:      int           (*ioctl)();         /* routine to handle an ioctl */
        !           112:      int           (*other)();         /* routine to handle misc blocks */
        !           113: {
        !           114:      register int   ps, (*func)();
        !           115: 
        !           116:      switch (bp->type) {
        !           117:          case M_DATA:
        !           118:               putq(q, bp);
        !           119:               return;
        !           120:          case M_DELIM:
        !           121:               ps = spl6();
        !           122:               putq(q, bp);
        !           123:               ++*delim_count;
        !           124:               qenable(q);
        !           125:               splx(ps);
        !           126:               return;
        !           127:          case M_IOCTL:
        !           128:               func = ioctl;
        !           129:               break;
        !           130:          default:
        !           131:               func = other;
        !           132:      }
        !           133: 
        !           134:      if (func)
        !           135:          (*func) (q, bp);
        !           136:      else if (q->next)
        !           137:          (*q->next->qinfo->putp) (q->next, bp);
        !           138:      else
        !           139:          freeb(bp);
        !           140: }
        !           141: 
        !           142: 
        !           143: #define BLEN(bp)    ((bp)->wptr - (bp)->rptr)
        !           144: #define BSZ(bp)            ((bp)->lim - (bp)->base)
        !           145: #undef MIN
        !           146: #define MIN(a,b)    ((a) > (b) ? (b) : (a))
        !           147: 
        !           148: /*
        !           149:  * This routine takes a dequeued packet and a length.
        !           150:  * It makes sure that the specified length of data appears in the first
        !           151:  * block of the packet, if possible.
        !           152:  */
        !           153: struct block *packet_pullup(bp, len)
        !           154:      register struct block    *bp;     /* the dequeued packet */
        !           155:      unsigned      len;                /* desired length */
        !           156:                         /* returns the new packet (the old one is invalid) */
        !           157: {
        !           158:      register struct block    *nbp;
        !           159:      register unsigned       count;
        !           160: 
        !           161: 
        !           162:      if (bp == NULL)
        !           163:           goto bad;
        !           164:      if (BLEN(bp) >= len)
        !           165:           return bp;
        !           166: 
        !           167:      nbp = allocb(len);
        !           168:      if (nbp == NULL || BSZ(nbp) < len) {
        !           169:          free_blocks(bp);
        !           170:           goto cleanup;
        !           171:      }
        !           172:      nbp->next = bp;
        !           173: 
        !           174:      while (bp && bp->type == M_DATA) {
        !           175:          count = BSZ(nbp) - BLEN(nbp);      /* space left in new block */
        !           176:           count = MIN(count, len);          /* clip to desired length */
        !           177:          count = MIN(count, BLEN(bp));      /* clip to length of this block */
        !           178:           bcopy(bp->rptr, nbp->wptr, count);
        !           179:           len -= count;
        !           180:           bp->rptr += count;
        !           181:           nbp->wptr += count;
        !           182:           if (BLEN(bp) > 0)
        !           183:                break;
        !           184:           nbp->next = bp->next;
        !           185:           freeb(bp);
        !           186:          bp = nbp->next;
        !           187:      }
        !           188: 
        !           189:      if (len == 0)
        !           190:           return nbp;
        !           191: 
        !           192: cleanup:
        !           193:      free_blocks(nbp);
        !           194: bad:
        !           195:      printf("packet_pullup bad\n");
        !           196:      return NULL;
        !           197: }
        !           198: 
        !           199: 
        !           200: /*
        !           201:  * Free space taken by a dequeued packet.
        !           202:  */
        !           203: free_blocks(bp)
        !           204:      register struct block    *bp;     /* dequeued packet */
        !           205: {
        !           206:      register struct block    *nbp;
        !           207: 
        !           208:      while (bp) {
        !           209:          nbp = bp->next;
        !           210:          freeb(bp);
        !           211:          bp = nbp;
        !           212:      }
        !           213: }
        !           214: 
        !           215: 
        !           216: /*
        !           217:  * This routine puts blocks from a dequeued packet onto a queue's successor.
        !           218:  */
        !           219: packet_put(q, bp)
        !           220:      register struct queue    *q;      /* Note that we put to q->next */
        !           221:      register struct block    *bp;
        !           222: {
        !           223:      register struct block    *bnext;
        !           224: 
        !           225:      while (bp != NULL) {     
        !           226:          bnext = bp->next;
        !           227:          if (bp->rptr >= bp->wptr)
        !           228:               freeb(bp);
        !           229:          else
        !           230:               (*q->next->qinfo->putp) (q->next, bp);
        !           231:          bp = bnext;
        !           232:      }
        !           233:      if (q->flag & QDELIM)
        !           234:          putctl(q->next, M_DELIM);
        !           235: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.