Annotation of researchv9/sys/net/packet.c, revision 1.1.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.