CFT: vr(4)

Pyun YongHyeon pyunyh at gmail.com
Sun Oct 7 23:21:58 PDT 2007


It seems that there had been several stability issues in vr(4).
Here is mimimal patch that make vr(4) work reliably under heavy
network loads. The patch does the following:
 - Always check writability of mbuf before padding and make a
   writable copy of the mbuf if mbuf is marked as read-only.
 - Before padding is done check remaining bytes such that it can
   safely extend buffer size of the mbuf.
 - Before padding always check the return value of m_defrag(9).
 - Zero out pad space to avoid leaking data.

If you have vr(4) hardware please give it spin and let me know
the result.

-- 
Regards,
Pyun YongHyeon
-------------- next part --------------
Index: if_vr.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_vr.c,v
retrieving revision 1.126
diff -u -r1.126 if_vr.c
--- if_vr.c	23 Apr 2007 12:19:02 -0000	1.126
+++ if_vr.c	8 Oct 2007 06:14:41 -0000
@@ -1217,6 +1217,7 @@
 	struct vr_desc		*cur_tx, *n_tx;
 	struct vr_desc		*f = NULL;
 	uint32_t		cval;
+	int			padlen;
 
 	if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
 		return;
@@ -1250,11 +1251,33 @@
 		 * ourselves.
 		 */
 		if (m_head->m_pkthdr.len < VR_MIN_FRAMELEN) {
-			if (m_head->m_next != NULL) 
-				m_head = m_defrag(m_head, M_DONTWAIT);
-			m_head->m_pkthdr.len += VR_MIN_FRAMELEN - m_head->m_len;
+			padlen = VR_MIN_FRAMELEN - m_head->m_pkthdr.len;
+			if (M_WRITABLE(m_head) == 0) {
+				m = m_dup(m_head, M_DONTWAIT);
+				if (m == NULL) {
+					IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
+					break;
+				}
+				m_freem(m_head);
+				m_head = m;
+			}
+			if (m_head->m_next != NULL ||
+			    M_TRAILINGSPACE(m_head) < padlen) {
+				m = m_defrag(m_head, M_DONTWAIT);
+				if (m == NULL) {
+					IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
+					break;
+				}
+				m_head = m;
+			}
+			/*
+			 * Manually pad short frames, and zero the pad space
+			 * to avoid leaking data.
+			 */
+			bzero(mtod(m_head, char *) + m_head->m_pkthdr.len,
+			    padlen);
+			m_head->m_pkthdr.len += padlen;
 			m_head->m_len = m_head->m_pkthdr.len;
-			/* XXX: bzero the padding bytes */
 		}
 
 		n_tx = cur_tx;


More information about the freebsd-current mailing list