Index: kern/kern_mbuf.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_mbuf.c,v
retrieving revision 1.15
diff -u -p -r1.15 kern_mbuf.c
--- kern/kern_mbuf.c	6 Nov 2005 16:47:59 -0000	1.15
+++ kern/kern_mbuf.c	2 Dec 2005 14:19:08 -0000
@@ -95,6 +95,7 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_mb
  */
 
 int nmbclusters;		/* limits number of mbuf clusters */
+int nmbjumbo4;			/* limits number of 4k jumbo clusters */
 int nmbjumbo9;			/* limits number of 9k jumbo clusters */
 int nmbjumbo16;			/* limits number of 16k jumbo clusters */
 struct mbstat mbstat;
@@ -113,6 +114,8 @@ SYSCTL_DECL(_kern_ipc);
 /* XXX: These should be tuneables. Can't change UMA limits on the fly. */
 SYSCTL_INT(_kern_ipc, OID_AUTO, nmbclusters, CTLFLAG_RW, &nmbclusters, 0,
     "Maximum number of mbuf clusters allowed");
+SYSCTL_INT(_kern_ipc, OID_AUTO, nmbjumbo4, CTLFLAG_RW, &nmbjumbo4, 0,
+    "Maximum number of mbuf 4k jumbo clusters allowed");
 SYSCTL_INT(_kern_ipc, OID_AUTO, nmbjumbo9, CTLFLAG_RW, &nmbjumbo9, 0,
     "Maximum number of mbuf 9k jumbo clusters allowed");
 SYSCTL_INT(_kern_ipc, OID_AUTO, nmbjumbo16, CTLFLAG_RW, &nmbjumbo16, 0,
@@ -126,6 +129,7 @@ SYSCTL_STRUCT(_kern_ipc, OID_AUTO, mbsta
 uma_zone_t	zone_mbuf;
 uma_zone_t	zone_clust;
 uma_zone_t	zone_pack;
+uma_zone_t	zone_jumbo4;
 uma_zone_t	zone_jumbo9;
 uma_zone_t	zone_jumbo16;
 uma_zone_t	zone_ext_refcnt;
@@ -182,7 +186,18 @@ mbuf_init(void *dummy)
 	zone_pack = uma_zsecond_create(MBUF_PACKET_MEM_NAME, mb_ctor_pack,
 	    mb_dtor_pack, mb_zinit_pack, mb_zfini_pack, zone_mbuf);
 
-	/* Make jumbo frame zone too. 9k and 16k. */
+	/* Make jumbo frame zone too. 4k, 9k and 16k. */
+	zone_jumbo4 = uma_zcreate(MBUF_JUMBO4_MEM_NAME, MJUM4BYTES,
+	    mb_ctor_clust, mb_dtor_clust,
+#ifdef INVARIANTS
+	    trash_init, trash_fini,
+#else
+	    NULL, NULL,
+#endif
+	    UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
+	if (nmbjumbo4 > 0)
+		uma_zone_set_max(zone_jumbo4, nmbjumbo4);
+
 	zone_jumbo9 = uma_zcreate(MBUF_JUMBO9_MEM_NAME, MJUM9BYTES,
 	    mb_ctor_clust, mb_dtor_clust,
 #ifdef INVARIANTS
@@ -363,6 +378,9 @@ mb_ctor_clust(void *mem, int size, void 
 		case MCLBYTES:
 			type = EXT_CLUSTER;
 			break;
+		case MJUM4BYTES:
+			type = EXT_JUMBO4;
+			break;
 		case MJUM9BYTES:
 			type = EXT_JUMBO9;
 			break;
Index: kern/uipc_mbuf.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/uipc_mbuf.c,v
retrieving revision 1.158
diff -u -p -r1.158 uipc_mbuf.c
--- kern/uipc_mbuf.c	5 Nov 2005 19:43:55 -0000	1.158
+++ kern/uipc_mbuf.c	2 Dec 2005 14:19:09 -0000
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD: src/sys/kern/uipc_mb
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/kdb.h>	/* for m_sanity() */
 #include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/mac.h>
@@ -225,6 +226,9 @@ mb_free_ext(struct mbuf *m)
 		case EXT_CLUSTER:
 			uma_zfree(zone_clust, m->m_ext.ext_buf);
 			break;
+		case EXT_JUMBO4:
+			uma_zfree(zone_jumbo4, m->m_ext.ext_buf);
+			break;
 		case EXT_JUMBO9:
 			uma_zfree(zone_jumbo9, m->m_ext.ext_buf);
 			break;
Index: sys/mbuf.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/mbuf.h,v
retrieving revision 1.182
diff -u -p -r1.182 mbuf.h
--- sys/mbuf.h	18 Nov 2005 16:23:26 -0000	1.182
+++ sys/mbuf.h	2 Dec 2005 14:19:12 -0000
@@ -185,9 +185,10 @@ struct mbuf {
  */
 #define	EXT_CLUSTER	1	/* mbuf cluster */
 #define	EXT_SFBUF	2	/* sendfile(2)'s sf_bufs */
-#define	EXT_JUMBO9	3	/* jumbo cluster 9216 bytes */
-#define	EXT_JUMBO16	4	/* jumbo cluster 16184 bytes */
-#define	EXT_PACKET	5	/* mbuf+cluster from packet zone */
+#define	EXT_JUMBO4	3	/* jumbo cluster 4096 bytes */
+#define	EXT_JUMBO9	4	/* jumbo cluster 9216 bytes */
+#define	EXT_JUMBO16	5	/* jumbo cluster 16184 bytes */
+#define	EXT_PACKET	6	/* mbuf+cluster from packet zone */
 #define	EXT_NET_DRV	100	/* custom ext_buf provided by net driver(s) */
 #define	EXT_MOD_TYPE	200	/* custom module's ext_buf type */
 #define	EXT_DISPOSABLE	300	/* can throw this buffer away w/page flipping */
@@ -305,6 +306,7 @@ struct mbstat {
 #define	MBUF_MEM_NAME		"mbuf"
 #define	MBUF_CLUSTER_MEM_NAME	"mbuf_cluster"
 #define	MBUF_PACKET_MEM_NAME	"mbuf_packet"
+#define	MBUF_JUMBO4_MEM_NAME	"mbuf_jumbo_4k"
 #define	MBUF_JUMBO9_MEM_NAME	"mbuf_jumbo_9k"
 #define	MBUF_JUMBO16_MEM_NAME	"mbuf_jumbo_16k"
 #define	MBUF_TAG_MEM_NAME	"mbuf_tag"
@@ -331,6 +333,7 @@ struct mbstat {
 extern uma_zone_t	zone_mbuf;
 extern uma_zone_t	zone_clust;
 extern uma_zone_t	zone_pack;
+extern uma_zone_t	zone_jumbo4;
 extern uma_zone_t	zone_jumbo9;
 extern uma_zone_t	zone_jumbo16;
 extern uma_zone_t	zone_ext_refcnt;
@@ -338,9 +341,11 @@ extern uma_zone_t	zone_ext_refcnt;
 static __inline struct mbuf	*m_get(int how, short type);
 static __inline struct mbuf	*m_gethdr(int how, short type);
 static __inline struct mbuf	*m_getcl(int how, short type, int flags);
+static __inline struct mbuf	*m_getjcl(int how, short type, int flags, int size);
 static __inline struct mbuf	*m_getclr(int how, short type);	/* XXX */
 static __inline struct mbuf	*m_free(struct mbuf *m);
 static __inline void		 m_clget(struct mbuf *m, int how);
+static __inline void		*m_cljget(struct mbuf *m, int how, int size);
 static __inline void		 m_chtype(struct mbuf *m, short new_type);
 void				 mb_free_ext(struct mbuf *);
 
@@ -393,6 +398,47 @@ m_getcl(int how, short type, int flags)
 	return (uma_zalloc_arg(zone_pack, &args, how));
 }
 
+/*
+ * m_getjcl() returns an mbuf with a cluster of the specified size attached.
+ * For size it takes MCLBYTES, MJUM4BYTES, MJUM9BYTES, MJUM16BYTES.
+ */
+static __inline	/* XXX: This is rather large, should be real function maybe. */
+struct mbuf *
+m_getjcl(int how, short type, int flags, int size)
+{
+	struct mb_args args;
+	struct mbuf *m, *n;
+	uma_zone_t zone;
+
+	args.flags = flags;
+	args.type = type;
+
+	m = uma_zalloc_arg(zone_mbuf, &args, how);
+	if (m == NULL)
+		return NULL;
+
+	switch (size) {
+	case MCLBYTES:
+		zone = zone_clust;
+		break;
+	case MJUM4BYTES:
+		zone = zone_jumbo4;
+		break;
+	case MJUM9BYTES:
+		zone = zone_jumbo9;
+		break;
+	case MJUM16BYTES:
+		zone = zone_jumbo16;
+		break;
+	default:
+		panic("%s: m_getjcl: invalid cluster type", __func__);
+	}
+	n = uma_zalloc_arg(zone, m, how);
+	if (n == NULL)
+		uma_zfree(zone_mbuf, m);
+	return n;
+}
+
 static __inline
 struct mbuf *
 m_free(struct mbuf *m)
@@ -416,6 +462,45 @@ m_clget(struct mbuf *m, int how)
 	uma_zalloc_arg(zone_clust, m, how);
 }
 
+/*
+ * m_cljget() is different from m_clget() as it can allocate clusters
+ * without attaching them to an mbuf.  In that case the return value
+ * is the pointer to the cluster of the requested size.  If an mbuf was
+ * specified, it gets the cluster attached to it and the return value
+ * can be safely ignored.
+ * For size it takes MCLBYTES, MJUM4BYTES, MJUM9BYTES, MJUM16BYTES.
+ */
+static __inline
+void *
+m_cljget(struct mbuf *m, int how, int size)
+{
+	uma_zone_t zone;
+
+	if (m && m->m_flags & M_EXT)
+		printf("%s: %p mbuf already has cluster\n", __func__, m);
+	if (m != NULL)
+		m->m_ext.ext_buf = NULL;
+
+	switch (size) {
+	case MCLBYTES:
+		zone = zone_clust;
+		break;
+	case MJUM4BYTES:
+		zone = zone_jumbo4;
+		break;
+	case MJUM9BYTES:
+		zone = zone_jumbo9;
+		break;
+	case MJUM16BYTES:
+		zone = zone_jumbo16;
+		break;
+	default:
+		panic("%s: m_getjcl: invalid cluster type", __func__);
+	}
+	
+	return (uma_zalloc_arg(zone, m, how));
+}
+
 static __inline
 void
 m_chtype(struct mbuf *m, short new_type)
Index: sys/param.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/param.h,v
retrieving revision 1.253
diff -u -p -r1.253 param.h
--- sys/param.h	11 Nov 2005 16:04:59 -0000	1.253
+++ sys/param.h	2 Dec 2005 14:19:12 -0000
@@ -147,8 +147,9 @@
 
 #define MCLBYTES	(1 << MCLSHIFT)	/* size of an mbuf cluster */
 
-#define	MJUM9BYTES	(9 * 1024)	/* jumbo frame 9k */
-#define	MJUM16BYTES	(16 * 1024)	/* jumbo frame 16k */
+#define	MJUM4BYTES	(4 * 1024)	/* jumbo cluster 4k */
+#define	MJUM9BYTES	(9 * 1024)	/* jumbo cluster 9k */
+#define	MJUM16BYTES	(16 * 1024)	/* jumbo cluster 16k */
 
 /*
  * Some macros for units conversion
