+errno_t
+mbuf_attachcluster(mbuf_how_t how, mbuf_type_t type, mbuf_t *mbuf,
+ caddr_t extbuf, void (*extfree)(caddr_t , u_int, caddr_t),
+ size_t extsize, caddr_t extarg)
+{
+ if (extbuf == NULL || extfree == NULL || extsize == 0)
+ return (EINVAL);
+
+ if ((*mbuf = m_clattach(mbuf != NULL ? *mbuf : NULL, type, extbuf,
+ extfree, extsize, extarg, how)) == NULL)
+ return (ENOMEM);
+
+ return (0);
+}
+
+errno_t
+mbuf_alloccluster(mbuf_how_t how, size_t *size, caddr_t *addr)
+{
+ if (size == NULL || *size == 0 || addr == NULL)
+ return (EINVAL);
+
+ *addr = NULL;
+
+ /* Jumbo cluster pool not available? */
+ if (*size > NBPG && njcl == 0)
+ return (ENOTSUP);
+
+ if (*size <= MCLBYTES && (*addr = m_mclalloc(how)) != NULL)
+ *size = MCLBYTES;
+ else if (*size > MCLBYTES && *size <= NBPG &&
+ (*addr = m_bigalloc(how)) != NULL)
+ *size = NBPG;
+ else if (*size > NBPG && *size <= M16KCLBYTES &&
+ (*addr = m_16kalloc(how)) != NULL)
+ *size = M16KCLBYTES;
+ else
+ *size = 0;
+
+ if (*addr == NULL)
+ return (ENOMEM);
+
+ return (0);
+}
+
+void
+mbuf_freecluster(caddr_t addr, size_t size)
+{
+ if (size != MCLBYTES && size != NBPG && size != M16KCLBYTES)
+ panic("%s: invalid size (%ld) for cluster %p", __func__,
+ size, (void *)addr);
+
+ if (size == MCLBYTES)
+ m_mclfree(addr);
+ else if (size == NBPG)
+ m_bigfree(addr, NBPG, NULL);
+ else if (njcl > 0)
+ m_16kfree(addr, M16KCLBYTES, NULL);
+ else
+ panic("%s: freeing jumbo cluster to an empty pool", __func__);
+}