+
+/*
+ * return a list of mbuf hdrs that point to clusters...
+ * try for num_needed, if this can't be met, return whatever
+ * number were available... set up the first num_with_pkthdrs
+ * with mbuf hdrs configured as packet headers... these are
+ * chained on the m_nextpkt field... any packets requested beyond
+ * this are chained onto the last packet header's m_next field.
+ */
+struct mbuf *
+m_getpackets(int num_needed, int num_with_pkthdrs, int how)
+{
+ struct mbuf *m;
+ struct mbuf **np, *top;
+
+ top = NULL;
+ np = ⊤
+
+ m_clalloc(num_needed, how); /* takes the MBUF_LOCK, but doesn't release it... */
+
+ while (num_needed--) {
+ if (mfree && mclfree) { /* mbuf + cluster are available */
+ m = mfree;
+ MCHECK(m);
+ mfree = m->m_next;
+ ++mclrefcnt[mtocl(m)];
+ mbstat.m_mtypes[MT_FREE]--;
+ mbstat.m_mtypes[MT_DATA]++;
+ m->m_ext.ext_buf = (caddr_t)mclfree; /* get the cluster */
+ ++mclrefcnt[mtocl(m->m_ext.ext_buf)];
+ mbstat.m_clfree--;
+ mclfree = ((union mcluster *)(m->m_ext.ext_buf))->mcl_next;
+
+ m->m_next = m->m_nextpkt = 0;
+ m->m_type = MT_DATA;
+ m->m_data = m->m_ext.ext_buf;
+ m->m_ext.ext_free = 0;
+ m->m_ext.ext_size = MCLBYTES;
+ m->m_ext.ext_refs.forward = m->m_ext.ext_refs.backward = &m->m_ext.ext_refs;
+
+ if (num_with_pkthdrs == 0)
+ m->m_flags = M_EXT;
+ else {
+ m->m_flags = M_PKTHDR | M_EXT;
+ m->m_pkthdr.len = 0;
+ m->m_pkthdr.rcvif = NULL;
+ m->m_pkthdr.header = NULL;
+ m->m_pkthdr.csum_flags = 0;
+ m->m_pkthdr.csum_data = 0;
+ m->m_pkthdr.aux = (struct mbuf *)NULL;
+ m->m_pkthdr.reserved1 = NULL;
+ m->m_pkthdr.reserved2 = NULL;
+
+ num_with_pkthdrs--;
+ }
+
+ } else {
+
+ MBUF_UNLOCK();
+
+ if (num_with_pkthdrs == 0) {
+ MGET(m, how, MT_DATA );
+ } else {
+ MGETHDR(m, how, MT_DATA);
+
+ num_with_pkthdrs--;
+ }
+ if (m == 0)
+ return(top);
+
+ MCLGET(m, how);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_free(m);
+ return(top);
+ }
+ MBUF_LOCK();
+ }
+ *np = m;
+
+ if (num_with_pkthdrs)
+ np = &m->m_nextpkt;
+ else
+ np = &m->m_next;
+ }
+ MBUF_UNLOCK();
+
+ return (top);
+}
+
+
+/*
+ * return a list of mbuf hdrs set up as packet hdrs
+ * chained together on the m_nextpkt field
+ */
+struct mbuf *
+m_getpackethdrs(int num_needed, int how)
+{
+ struct mbuf *m;
+ struct mbuf **np, *top;
+
+ top = NULL;
+ np = ⊤
+
+ MBUF_LOCK();
+
+ while (num_needed--) {
+ if (m = mfree) { /* mbufs are available */
+ MCHECK(m);
+ mfree = m->m_next;
+ ++mclrefcnt[mtocl(m)];
+ mbstat.m_mtypes[MT_FREE]--;
+ mbstat.m_mtypes[MT_DATA]++;
+
+ m->m_next = m->m_nextpkt = 0;
+ m->m_type = MT_DATA;
+ m->m_flags = M_PKTHDR;
+ m->m_data = m->m_pktdat;
+ m->m_pkthdr.len = 0;
+ m->m_pkthdr.rcvif = NULL;
+ m->m_pkthdr.header = NULL;
+ m->m_pkthdr.csum_flags = 0;
+ m->m_pkthdr.csum_data = 0;
+ m->m_pkthdr.aux = (struct mbuf *)NULL;
+ m->m_pkthdr.reserved1 = NULL;
+ m->m_pkthdr.reserved2 = NULL;
+
+ } else {
+
+ MBUF_UNLOCK();
+
+ m = m_retryhdr(how, MT_DATA);
+
+ if (m == 0)
+ return(top);
+
+ MBUF_LOCK();
+ }
+ *np = m;
+ np = &m->m_nextpkt;
+ }
+ MBUF_UNLOCK();
+
+ return (top);
+}
+
+