The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/iscsi_initiator/iscsivar.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2005-2011 Daniel Braniss <danny@cs.huji.ac.il>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * $FreeBSD$
   29  */
   30 
   31 /*
   32  | $Id: iscsivar.h 743 2009-08-08 10:54:53Z danny $
   33  */
   34 #include <sys/lock.h>
   35 #include <sys/mutex.h>
   36 
   37 #define ISCSI_MAX_LUNS          128     // don't touch this
   38 #if ISCSI_MAX_LUNS > 8
   39 /*
   40  | for this to work 
   41  | sysctl kern.cam.cam_srch_hi=1
   42  */
   43 #endif
   44 
   45 #ifndef ISCSI_INITIATOR_DEBUG
   46 #define ISCSI_INITIATOR_DEBUG 1
   47 #endif
   48 
   49 #ifdef ISCSI_INITIATOR_DEBUG
   50 extern int iscsi_debug;
   51 #define debug(level, fmt, args...)      do {if(level <= iscsi_debug)\
   52         printf("%s: " fmt "\n", __func__ , ##args);} while(0)
   53 #define sdebug(level, fmt, args...)     do {if(level <= iscsi_debug)\
   54         printf("%d] %s: " fmt "\n", sp->sid, __func__ , ##args);} while(0)
   55 #define debug_called(level)             do {if(level <= iscsi_debug)\
   56         printf("%s: called\n",  __func__);} while(0)
   57 #else
   58 #define debug(level, fmt, args...)
   59 #define debug_called(level)
   60 #define sdebug(level, fmt, args...)
   61 #endif /* ISCSI_INITIATOR_DEBUG */
   62 
   63 #define xdebug(fmt, args...)    printf(">>> %s: " fmt "\n", __func__ , ##args)
   64 
   65 #define MAX_SESSIONS    ISCSI_MAX_TARGETS
   66 #define MAX_PDUS        (MAX_SESSIONS*256) // XXX: at the moment this is arbitrary
   67 
   68 typedef uint32_t digest_t(const void *, int len, uint32_t ocrc);
   69 
   70 MALLOC_DECLARE(M_ISCSI);
   71 MALLOC_DECLARE(M_ISCSIBUF);
   72 
   73 #define ISOK2DIG(dig, pp)       ((dig != NULL) && ((pp->ipdu.bhs.opcode & 0x1f) != ISCSI_LOGIN_CMD))
   74 
   75 #ifndef BIT
   76 #define BIT(n)  (1 <<(n))
   77 #endif
   78 
   79 #define ISC_SM_RUN      BIT(0)
   80 #define ISC_SM_RUNNING  BIT(1)
   81 
   82 #define ISC_LINK_UP     BIT(2)
   83 #define ISC_CON_RUN     BIT(3)
   84 #define ISC_CON_RUNNING BIT(4)
   85 #define ISC_KILL        BIT(5)
   86 #define ISC_OQNOTEMPTY  BIT(6)
   87 #define ISC_OWAITING    BIT(7)
   88 #define ISC_FFPHASE     BIT(8)
   89 
   90 #define ISC_CAMDEVS     BIT(9)
   91 #define ISC_SCANWAIT    BIT(10)
   92 
   93 #define ISC_MEMWAIT     BIT(11)
   94 #define ISC_SIGNALED    BIT(12)
   95 
   96 #define ISC_HOLD        BIT(15)
   97 #define ISC_HOLDED      BIT(16)
   98 
   99 #define ISC_SHUTDOWN    BIT(31)
  100 
  101 /*
  102  | some stats
  103  */
  104 struct i_stats {
  105      int        npdu;   // number of pdus malloc'ed.
  106      int        nrecv;  // unprocessed received pdus
  107      int        nsent;  // sent pdus
  108 
  109      int        nrsp, max_rsp;
  110      int        nrsv, max_rsv;
  111      int        ncsnd, max_csnd;
  112      int        nisnd, max_isnd;
  113      int        nwsnd, max_wsnd;
  114      int        nhld, max_hld;
  115 
  116      struct bintime t_sent;
  117      struct bintime t_recv;
  118 };
  119 
  120 /*
  121  | one per 'session'
  122  */
  123 
  124 typedef TAILQ_HEAD(, pduq) queue_t;
  125 
  126 typedef struct isc_session {
  127      TAILQ_ENTRY(isc_session)   sp_link;
  128      int                flags;
  129      struct cdev        *dev;
  130      struct socket      *soc;
  131      struct file        *fp;
  132      struct thread      *td;
  133 
  134      struct proc        *proc; // the userland process
  135      int                signal;
  136      struct proc        *soc_proc;
  137      struct proc        *stp;   // the sm thread
  138 
  139      struct isc_softc   *isc;
  140 
  141      digest_t           *hdrDigest;     // the digest alg. if any
  142      digest_t           *dataDigest;    // the digest alg. if any
  143 
  144      int                sid;            // Session ID
  145      sn_t               sn;             // sequence number stuff;
  146      int                cws;            // current window size
  147 
  148      int                target_nluns; // this and target_lun are
  149                                       // hopefully temporal till I
  150                                       // figure out a better way.
  151      int                target_lun[ISCSI_MAX_LUNS/(sizeof(int)*8) + 1];
  152 
  153      struct mtx         rsp_mtx;
  154      struct mtx         rsv_mtx;
  155      struct mtx         snd_mtx;
  156      struct mtx         hld_mtx;
  157      struct mtx         io_mtx;
  158      queue_t            rsp;
  159      queue_t            rsv;
  160      queue_t            csnd;
  161      queue_t            isnd;
  162      queue_t            wsnd;
  163      queue_t            hld;                            
  164 
  165      isc_opt_t          opt;    // negotiable values
  166 
  167      struct i_stats     stats;
  168      bhs_t              bhs;
  169      struct uio         uio;
  170      struct iovec       iov;
  171      /*
  172       | cam stuff
  173       */
  174      struct cam_sim     *cam_sim;
  175      struct cam_path    *cam_path;
  176      struct mtx         cam_mtx;
  177      /*
  178       | sysctl stuff
  179       */
  180      struct sysctl_ctx_list     clist;
  181      struct sysctl_oid  *oid;
  182      int        douio;  //XXX: turn on/off uio on read
  183 } isc_session_t;
  184 
  185 typedef struct pduq {
  186      TAILQ_ENTRY(pduq)  pq_link;
  187 
  188      caddr_t            buf;
  189      u_int              len;    // the total length of the pdu
  190      pdu_t              pdu;
  191      union ccb          *ccb;
  192 
  193      struct uio         uio;
  194      struct iovec       iov[5]; // XXX: careful ...
  195      struct mbuf        *mp;
  196      struct bintime     ts;
  197      queue_t            *pduq;          
  198 } pduq_t;
  199 /*
  200  */
  201 struct isc_softc {
  202      struct mtx         isc_mtx;
  203      TAILQ_HEAD(,isc_session)   isc_sess;
  204      int                nsess;
  205      struct cdev        *dev;
  206      char               isid[6];        // Initiator Session ID (48 bits)
  207      struct unrhdr      *unit;
  208      struct sx          unit_sx;
  209 
  210      uma_zone_t         pdu_zone;       // pool of free pdu's
  211      TAILQ_HEAD(,pduq)  freepdu;
  212 
  213 #ifdef  ISCSI_INITIATOR_DEBUG
  214      int                 npdu_alloc, npdu_max; // for instrumentation
  215 #endif
  216 #ifdef DO_EVENTHANDLER
  217      eventhandler_tag   eh;
  218 #endif
  219      /*
  220       | sysctl stuff
  221       */
  222      struct sysctl_ctx_list     clist;
  223      struct sysctl_oid          *oid;
  224 };
  225 
  226 #ifdef  ISCSI_INITIATOR_DEBUG
  227 extern struct mtx iscsi_dbg_mtx;
  228 #endif
  229 
  230 void    isc_start_receiver(isc_session_t *sp);
  231 void    isc_stop_receiver(isc_session_t *sp);
  232 
  233 int     isc_sendPDU(isc_session_t *sp, pduq_t *pq);
  234 int     isc_qout(isc_session_t *sp, pduq_t *pq);
  235 int     i_prepPDU(isc_session_t *sp, pduq_t *pq);
  236 
  237 int     ism_fullfeature(struct cdev *dev, int flag);
  238 
  239 int     i_pdu_flush(isc_session_t *sc);
  240 int     i_setopt(isc_session_t *sp, isc_opt_t *opt);
  241 void    i_freeopt(isc_opt_t *opt);
  242 
  243 int     ic_init(isc_session_t *sp);
  244 void    ic_destroy(isc_session_t *sp);
  245 void    ic_lost_target(isc_session_t *sp, int target);
  246 int     ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp);
  247 
  248 void    ism_recv(isc_session_t *sp, pduq_t *pq);
  249 int     ism_start(isc_session_t *sp);
  250 void    ism_restart(isc_session_t *sp);
  251 void    ism_stop(isc_session_t *sp);
  252 
  253 int     scsi_encap(struct cam_sim *sim, union ccb *ccb);
  254 int     scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
  255 void    iscsi_r2t(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
  256 void    iscsi_done(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
  257 void    iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
  258 void    iscsi_async(isc_session_t *sp,  pduq_t *pq);
  259 void    iscsi_cleanup(isc_session_t *sp);
  260 int     iscsi_requeue(isc_session_t *sp);
  261 
  262 // Serial Number Arithmetic
  263 #define _MAXINCR        0x7FFFFFFF      // 2 ^ 31 - 1
  264 #define SNA_GT(i1, i2)  ((i1 != i2) && (\
  265         (i1 < i2 && i2 - i1 > _MAXINCR) ||\
  266         (i1 > i2 && i1 - i2 < _MAXINCR))?1: 0)
  267 
  268 /*
  269  | inlines
  270  */
  271 static __inline pduq_t *
  272 pdu_alloc(struct isc_softc *isc, int wait)
  273 {
  274      pduq_t     *pq;
  275 
  276      pq = (pduq_t *)uma_zalloc(isc->pdu_zone, wait /* M_WAITOK or M_NOWAIT*/);
  277      if(pq == NULL) {
  278           debug(7, "out of mem");
  279           return NULL;
  280      }
  281 #ifdef ISCSI_INITIATOR_DEBUG
  282      mtx_lock(&iscsi_dbg_mtx);
  283      isc->npdu_alloc++;
  284      if(isc->npdu_alloc > isc->npdu_max)
  285           isc->npdu_max = isc->npdu_alloc;
  286      mtx_unlock(&iscsi_dbg_mtx);
  287 #endif
  288      memset(pq, 0, sizeof(pduq_t));
  289 
  290      return pq;
  291 }
  292 
  293 static __inline void
  294 pdu_free(struct isc_softc *isc, pduq_t *pq)
  295 {
  296      if(pq->mp)
  297           m_freem(pq->mp);
  298 #ifdef NO_USE_MBUF
  299      if(pq->buf != NULL)
  300           free(pq->buf, M_ISCSIBUF);
  301 #endif
  302      uma_zfree(isc->pdu_zone, pq);
  303 #ifdef ISCSI_INITIATOR_DEBUG
  304      mtx_lock(&iscsi_dbg_mtx);
  305      isc->npdu_alloc--;
  306      mtx_unlock(&iscsi_dbg_mtx);
  307 #endif
  308 }
  309 
  310 static __inline void
  311 i_nqueue_rsp(isc_session_t *sp, pduq_t *pq)
  312 {
  313      mtx_lock(&sp->rsp_mtx);
  314      if(++sp->stats.nrsp > sp->stats.max_rsp)
  315           sp->stats.max_rsp = sp->stats.nrsp;
  316      TAILQ_INSERT_TAIL(&sp->rsp, pq, pq_link);
  317      mtx_unlock(&sp->rsp_mtx);
  318 }
  319 
  320 static __inline pduq_t *
  321 i_dqueue_rsp(isc_session_t *sp)
  322 {
  323      pduq_t *pq;
  324 
  325      mtx_lock(&sp->rsp_mtx);
  326      if((pq = TAILQ_FIRST(&sp->rsp)) != NULL) {
  327           sp->stats.nrsp--;
  328           TAILQ_REMOVE(&sp->rsp, pq, pq_link);
  329      }
  330      mtx_unlock(&sp->rsp_mtx);
  331 
  332      return pq;
  333 }
  334 
  335 static __inline void
  336 i_nqueue_rsv(isc_session_t *sp, pduq_t *pq)
  337 {
  338      mtx_lock(&sp->rsv_mtx);
  339      if(++sp->stats.nrsv > sp->stats.max_rsv)
  340           sp->stats.max_rsv = sp->stats.nrsv;
  341      TAILQ_INSERT_TAIL(&sp->rsv, pq, pq_link);
  342      mtx_unlock(&sp->rsv_mtx);
  343 }
  344 
  345 static __inline pduq_t *
  346 i_dqueue_rsv(isc_session_t *sp)
  347 {
  348      pduq_t *pq;
  349 
  350      mtx_lock(&sp->rsv_mtx);
  351      if((pq = TAILQ_FIRST(&sp->rsv)) != NULL) {
  352           sp->stats.nrsv--;
  353           TAILQ_REMOVE(&sp->rsv, pq, pq_link);
  354      }
  355      mtx_unlock(&sp->rsv_mtx);
  356 
  357      return pq;
  358 }
  359 
  360 static __inline void
  361 i_nqueue_csnd(isc_session_t *sp, pduq_t *pq)
  362 {
  363      mtx_lock(&sp->snd_mtx);
  364      if(++sp->stats.ncsnd > sp->stats.max_csnd)
  365           sp->stats.max_csnd = sp->stats.ncsnd;
  366      TAILQ_INSERT_TAIL(&sp->csnd, pq, pq_link);
  367      mtx_unlock(&sp->snd_mtx);
  368 }
  369 
  370 static __inline pduq_t *
  371 i_dqueue_csnd(isc_session_t *sp)
  372 {
  373      pduq_t *pq;
  374 
  375      mtx_lock(&sp->snd_mtx);
  376      if((pq = TAILQ_FIRST(&sp->csnd)) != NULL) {
  377           sp->stats.ncsnd--;
  378           TAILQ_REMOVE(&sp->csnd, pq, pq_link);
  379      }
  380      mtx_unlock(&sp->snd_mtx);
  381 
  382      return pq;
  383 }
  384 
  385 static __inline void
  386 i_nqueue_isnd(isc_session_t *sp, pduq_t *pq)
  387 {
  388      mtx_lock(&sp->snd_mtx);
  389      if(++sp->stats.nisnd > sp->stats.max_isnd)
  390           sp->stats.max_isnd = sp->stats.nisnd;
  391      TAILQ_INSERT_TAIL(&sp->isnd, pq, pq_link);
  392      mtx_unlock(&sp->snd_mtx);
  393 }
  394 
  395 static __inline pduq_t *
  396 i_dqueue_isnd(isc_session_t *sp)
  397 {
  398      pduq_t *pq;
  399 
  400      mtx_lock(&sp->snd_mtx);
  401      if((pq = TAILQ_FIRST(&sp->isnd)) != NULL) {
  402           sp->stats.nisnd--;
  403           TAILQ_REMOVE(&sp->isnd, pq, pq_link);
  404      }
  405      mtx_unlock(&sp->snd_mtx);
  406 
  407      return pq;
  408 }
  409 
  410 static __inline void
  411 i_nqueue_wsnd(isc_session_t *sp, pduq_t *pq)
  412 {
  413      mtx_lock(&sp->snd_mtx);
  414      if(++sp->stats.nwsnd > sp->stats.max_wsnd)
  415           sp->stats.max_wsnd = sp->stats.nwsnd;
  416      TAILQ_INSERT_TAIL(&sp->wsnd, pq, pq_link);
  417      mtx_unlock(&sp->snd_mtx);
  418 }
  419 
  420 static __inline pduq_t *
  421 i_dqueue_wsnd(isc_session_t *sp)
  422 {
  423      pduq_t *pq;
  424 
  425      mtx_lock(&sp->snd_mtx);
  426      if((pq = TAILQ_FIRST(&sp->wsnd)) != NULL) {
  427           sp->stats.nwsnd--;
  428           TAILQ_REMOVE(&sp->wsnd, pq, pq_link);
  429      }
  430      mtx_unlock(&sp->snd_mtx);
  431 
  432      return pq;
  433 }
  434 
  435 static __inline pduq_t *
  436 i_dqueue_snd(isc_session_t *sp, int which)
  437 {
  438      pduq_t *pq;
  439 
  440      pq = NULL;
  441      mtx_lock(&sp->snd_mtx);
  442      if((which & BIT(0)) && (pq = TAILQ_FIRST(&sp->isnd)) != NULL) {
  443           sp->stats.nisnd--;
  444           TAILQ_REMOVE(&sp->isnd, pq, pq_link);
  445           pq->pduq = &sp->isnd; // remember where you came from
  446      } else
  447      if((which & BIT(1)) && (pq = TAILQ_FIRST(&sp->wsnd)) != NULL) {
  448           sp->stats.nwsnd--;
  449           TAILQ_REMOVE(&sp->wsnd, pq, pq_link);
  450           pq->pduq = &sp->wsnd; // remember where you came from
  451      } else
  452      if((which & BIT(2)) && (pq = TAILQ_FIRST(&sp->csnd)) != NULL) {
  453           sp->stats.ncsnd--;
  454           TAILQ_REMOVE(&sp->csnd, pq, pq_link);
  455           pq->pduq = &sp->csnd; // remember where you came from
  456      }
  457      mtx_unlock(&sp->snd_mtx);
  458 
  459      return pq;
  460 }
  461 
  462 static __inline void
  463 i_rqueue_pdu(isc_session_t *sp, pduq_t *pq)
  464 {
  465      mtx_lock(&sp->snd_mtx);
  466      KASSERT(pq->pduq != NULL, ("pq->pduq is NULL"));
  467      TAILQ_INSERT_TAIL(pq->pduq, pq, pq_link);
  468      mtx_unlock(&sp->snd_mtx);     
  469 }
  470 
  471 /*
  472  | Waiting for ACK (or something :-)
  473  */
  474 static __inline void
  475 i_nqueue_hld(isc_session_t *sp, pduq_t *pq)
  476 {
  477      getbintime(&pq->ts);
  478      mtx_lock(&sp->hld_mtx);
  479      if(++sp->stats.nhld > sp->stats.max_hld)
  480           sp->stats.max_hld = sp->stats.nhld;
  481      TAILQ_INSERT_TAIL(&sp->hld, pq, pq_link);
  482      mtx_unlock(&sp->hld_mtx);
  483      return;
  484 }
  485 
  486 static __inline void
  487 i_remove_hld(isc_session_t *sp, pduq_t *pq)
  488 {
  489      mtx_lock(&sp->hld_mtx);
  490      sp->stats.nhld--;
  491      TAILQ_REMOVE(&sp->hld, pq, pq_link);
  492      mtx_unlock(&sp->hld_mtx);
  493 }
  494 
  495 static __inline pduq_t *
  496 i_dqueue_hld(isc_session_t *sp)
  497 {
  498      pduq_t *pq;
  499 
  500      mtx_lock(&sp->hld_mtx);
  501      if((pq = TAILQ_FIRST(&sp->hld)) != NULL) {
  502           sp->stats.nhld--;
  503           TAILQ_REMOVE(&sp->hld, pq, pq_link);
  504      }
  505      mtx_unlock(&sp->hld_mtx);
  506 
  507      return pq;
  508 }
  509 
  510 static __inline pduq_t *
  511 i_search_hld(isc_session_t *sp, int itt, int keep)
  512 {
  513      pduq_t     *pq, *tmp;
  514 
  515      pq = NULL;
  516 
  517      mtx_lock(&sp->hld_mtx);
  518      TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) {
  519           if(pq->pdu.ipdu.bhs.itt == itt) {
  520                if(!keep) {
  521                     sp->stats.nhld--;
  522                     TAILQ_REMOVE(&sp->hld, pq, pq_link);
  523                }
  524                break;
  525           }
  526      }
  527      mtx_unlock(&sp->hld_mtx);
  528 
  529      return pq;
  530 }
  531 
  532 static __inline void
  533 i_acked_hld(isc_session_t *sp, pdu_t *op)
  534 {
  535      pduq_t     *pq, *tmp;
  536      u_int exp = sp->sn.expCmd;
  537      
  538      pq = NULL;
  539      mtx_lock(&sp->hld_mtx);
  540      TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) {
  541           if((op && op->ipdu.bhs.itt == pq->pdu.ipdu.bhs.itt)
  542              || (pq->ccb == NULL
  543                  && (pq->pdu.ipdu.bhs.opcode != ISCSI_WRITE_DATA)
  544                  && SNA_GT(exp, ntohl(pq->pdu.ipdu.bhs.ExpStSN)))) {
  545                sp->stats.nhld--;
  546                TAILQ_REMOVE(&sp->hld, pq, pq_link);
  547                pdu_free(sp->isc, pq);
  548           }
  549      }
  550      mtx_unlock(&sp->hld_mtx);
  551 }
  552 
  553 static __inline void
  554 i_mbufcopy(struct mbuf *mp, caddr_t dp, int len)
  555 {
  556      struct mbuf *m;
  557      caddr_t bp;
  558 
  559      for(m = mp; m != NULL; m = m->m_next) {
  560           bp = mtod(m, caddr_t);
  561           /*
  562            | the pdu is word (4 octed) aligned
  563            | so len <= packet
  564            */
  565           memcpy(dp, bp, MIN(len, m->m_len));
  566           dp += m->m_len;
  567           len -= m->m_len;
  568           if(len <= 0)
  569                break;
  570      }
  571 }

Cache object: a5ccd1a7e6267271103ca465b6ca164f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.