Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Oct 2007 15:17:58 +0900
From:      Pyun YongHyeon <pyunyh@gmail.com>
To:        freebsd-current@FreeBSD.org
Subject:   CFT: vr(4)
Message-ID:  <20071008061758.GF46694@cdnetworks.co.kr>

next in thread | raw e-mail | index | archive | help

--envbJBWh7q8WU6mo
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

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

--envbJBWh7q8WU6mo
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="vr.pad.patch"

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;

--envbJBWh7q8WU6mo--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20071008061758.GF46694>