changeset 3392:2c3a1c7448cc

6471718 Polling capability corrupt IP header check before ip_input() 6501903 xge panics on recieving a packet
author yl150051
date Mon, 08 Jan 2007 23:36:56 -0800
parents 2e4fef544e31
children 660717ce3a70
files usr/src/uts/common/inet/ip/ip.c usr/src/uts/common/io/xge/drv/xgell.c usr/src/uts/common/io/xge/drv/xgell.h
diffstat 3 files changed, 40 insertions(+), 127 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip/ip.c	Mon Jan 08 22:48:10 2007 -0800
+++ b/usr/src/uts/common/inet/ip/ip.c	Mon Jan 08 23:36:56 2007 -0800
@@ -14674,7 +14674,6 @@
 ip_rput(queue_t *q, mblk_t *mp)
 {
 	ill_t	*ill;
-	mblk_t	 *dmp = NULL;
 
 	TRACE_1(TR_FAC_IP, TR_IP_RPUT_START, "ip_rput_start: q %p", q);
 
@@ -14766,23 +14765,6 @@
 		freemsg(mp);
 		mp = mp1;
 	}
-	if (DB_TYPE(mp) == M_DATA) {
-		dmp = mp;
-	} else if (DB_TYPE(mp) == M_PROTO &&
-	    *(t_uscalar_t *)mp->b_rptr == DL_UNITDATA_IND) {
-		dmp = mp->b_cont;
-	}
-	if (dmp != NULL) {
-		/*
-		 * IP header ptr not aligned?
-		 * OR IP header not complete in first mblk
-		 */
-		if (!OK_32PTR(dmp->b_rptr) ||
-		    (dmp->b_wptr - dmp->b_rptr) < IP_SIMPLE_HDR_LENGTH) {
-			if (!ip_check_and_align_header(q, dmp))
-				return;
-		}
-	}
 
 	TRACE_2(TR_FAC_IP, TR_IP_RPUT_END,
 	    "ip_rput_end: q %p (%S)", q, "end");
@@ -14805,7 +14787,9 @@
  *   - 'mp' is either an untagged or a special priority-tagged packet.
  *   - Any VLAN tag that was in the MAC header has been stripped.
  *
- * Thus, there is no need to adjust b_rptr in this function.
+ * If the IP header in packet is not 32-bit aligned, every message in the
+ * chain will be aligned before further operations. This is required on SPARC
+ * platform.
  */
 /* ARGSUSED */
 void
@@ -14827,6 +14811,7 @@
 	mblk_t			*tail = NULL;
 	mblk_t			*first_mp;
 	mblk_t 			*mp;
+	mblk_t			*dmp;
 	int			cnt = 0;
 
 	ASSERT(mp_chain != NULL);
@@ -14852,19 +14837,42 @@
 		prev_dst = dst;
 
 		/*
+		 * Check and align the IP header.
+		 */
+		if (DB_TYPE(mp) == M_DATA) {
+			dmp = mp;
+		} else if (DB_TYPE(mp) == M_PROTO &&
+		    *(t_uscalar_t *)mp->b_rptr == DL_UNITDATA_IND) {
+			dmp = mp->b_cont;
+		} else {
+			dmp = NULL;
+		}
+		if (dmp != NULL) {
+			/*
+			 * IP header ptr not aligned?
+			 * OR IP header not complete in first mblk
+			 */
+			if (!OK_32PTR(dmp->b_rptr) ||
+			    MBLKL(dmp) < IP_SIMPLE_HDR_LENGTH) {
+				if (!ip_check_and_align_header(q, dmp))
+					continue;
+			}
+		}
+
+		/*
 		 * ip_input fast path
 		 */
 
 		/* mblk type is not M_DATA */
-		if (mp->b_datap->db_type != M_DATA) {
+		if (DB_TYPE(mp) != M_DATA) {
 			if (ip_rput_process_notdata(q, &first_mp, ill,
 			    &ll_multicast, &mp))
 				continue;
 		}
 
 		/* Make sure its an M_DATA and that its aligned */
-		ASSERT(mp->b_datap->db_type == M_DATA);
-		ASSERT(mp->b_datap->db_ref == 1 && OK_32PTR(mp->b_rptr));
+		ASSERT(DB_TYPE(mp) == M_DATA);
+		ASSERT(DB_REF(mp) == 1 && OK_32PTR(mp->b_rptr));
 
 		ipha = (ipha_t *)mp->b_rptr;
 		len = mp->b_wptr - rptr;
--- a/usr/src/uts/common/io/xge/drv/xgell.c	Mon Jan 08 22:48:10 2007 -0800
+++ b/usr/src/uts/common/io/xge/drv/xgell.c	Mon Jan 08 23:36:56 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -47,10 +47,8 @@
 
 #define	HEADROOM		2	/* for DIX-only packets */
 
-#ifdef XGELL_L3_ALIGNED
 void header_free_func(void *arg) { }
 frtn_t header_frtn = {header_free_func, NULL};
-#endif
 
 /* DMA attributes used for Tx side */
 static struct ddi_dma_attr tx_dma_attr = {
@@ -633,68 +631,17 @@
     int pkt_length, xge_hal_dtr_info_t *ext_info, boolean_t *copyit)
 {
 	mblk_t *mp;
-	mblk_t *nmp = NULL;
 	char *vaddr;
-	int hdr_length = 0;
-
-#ifdef XGELL_L3_ALIGNED
-	boolean_t doalign = B_TRUE;
-	struct ip *ip;
-	struct tcphdr *tcp;
-	int tcp_off;
-	int mp_align_len;
-	int ip_off;
-#endif
 
 	vaddr = (char *)rx_buffer->vaddr + HEADROOM;
-#ifdef XGELL_L3_ALIGNED
-	ip_off = xgell_get_ip_offset(ext_info);
-
-	/* Check ip_off with HEADROOM */
-	if ((ip_off & 3) == HEADROOM) {
-		doalign = B_FALSE;
-	}
-
-	/*
-	 * Doalign? Check for types of packets.
-	 */
-	/* Is IPv4 or IPv6? */
-	if (doalign && !(ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4 ||
-	    ext_info->proto & XGE_HAL_FRAME_PROTO_IPV6)) {
-		doalign = B_FALSE;
-	}
-
-	/* Is TCP? */
-	if (doalign &&
-	    ((ip = (struct ip *)(vaddr + ip_off))->ip_p == IPPROTO_TCP)) {
-		tcp_off = ip->ip_hl * 4 + ip_off;
-		tcp = (struct tcphdr *)(vaddr + tcp_off);
-		hdr_length = tcp_off + tcp->th_off * 4;
-		if (pkt_length < (XGE_HAL_TCPIP_HEADER_MAX_SIZE +
-		    XGE_HAL_MAC_HEADER_MAX_SIZE)) {
-			hdr_length = pkt_length;
-		}
-	} else {
-		doalign = B_FALSE;
-	}
-#endif
-
 	/*
 	 * Copy packet into new allocated message buffer, if pkt_length
 	 * is less than XGELL_RX_DMA_LOWAT
 	 */
 	if (*copyit || pkt_length <= lldev->config.rx_dma_lowat) {
-		/* Keep room for alignment */
-		if ((mp = allocb(pkt_length + HEADROOM + 4, 0)) == NULL) {
+		if ((mp = allocb(pkt_length, 0)) == NULL) {
 			return (NULL);
 		}
-#ifdef XGELL_L3_ALIGNED
-		if (doalign) {
-			mp_align_len =
-			    (4 - ((uint64_t)(mp->b_rptr + ip_off) & 3));
-			mp->b_rptr += mp_align_len;
-		}
-#endif
 		bcopy(vaddr, mp->b_rptr, pkt_length);
 		mp->b_wptr = mp->b_rptr + pkt_length;
 		*copyit = B_TRUE;
@@ -704,53 +651,15 @@
 	/*
 	 * Just allocate mblk for current data buffer
 	 */
-	if ((nmp = (mblk_t *)desballoc((unsigned char *)vaddr, pkt_length, 0,
+	if ((mp = (mblk_t *)desballoc((unsigned char *)vaddr, pkt_length, 0,
 	    &rx_buffer->frtn)) == NULL) {
 		/* Drop it */
 		return (NULL);
 	}
-
 	/*
-	 * Adjust the b_rptr/b_wptr in the mblk_t structure to point to
-	 * payload.
+	 * Adjust the b_rptr/b_wptr in the mblk_t structure.
 	 */
-	nmp->b_rptr += hdr_length;
-	nmp->b_wptr += pkt_length;
-
-#ifdef XGELL_L3_ALIGNED
-	if (doalign) {
-		if ((mp = esballoc(rx_buffer->header, hdr_length + 4, 0,
-		    &header_frtn)) == NULL) {
-			/* can not align! */
-			mp = nmp;
-			mp->b_rptr = (u8 *)vaddr;
-			mp->b_wptr = mp->b_rptr + pkt_length;
-			mp->b_next = NULL;
-			mp->b_cont = NULL;
-		} else {
-			/* align packet's ip-header offset */
-			mp_align_len =
-			    (4 - ((uint64_t)(mp->b_rptr + ip_off) & 3));
-			mp->b_rptr += mp_align_len;
-			mp->b_wptr += mp_align_len + hdr_length;
-			mp->b_cont = nmp;
-			mp->b_next = NULL;
-			nmp->b_cont = NULL;
-			nmp->b_next = NULL;
-
-			bcopy(vaddr, mp->b_rptr, hdr_length);
-		}
-	} else {
-		/* no need to align */
-		mp = nmp;
-		mp->b_next = NULL;
-		mp->b_cont = NULL;
-	}
-#else
-	mp = nmp;
-	mp->b_next = NULL;
-	mp->b_cont = NULL;
-#endif
+	mp->b_wptr += pkt_length;
 
 	return (mp);
 }
@@ -2341,6 +2250,10 @@
 	if (mac_register(macp, &lldev->mh) != 0)
 		goto xgell_register_fail;
 
+	/* Always free the macp after register */
+	if (macp != NULL)
+		mac_free(macp);
+
 	/* Calculate tx_copied_max here ??? */
 	lldev->tx_copied_max = hldev->config.fifo.max_frags *
 		hldev->config.fifo.alignment_size *
--- a/usr/src/uts/common/io/xge/drv/xgell.h	Mon Jan 08 22:48:10 2007 -0800
+++ b/usr/src/uts/common/io/xge/drv/xgell.h	Mon Jan 08 23:36:56 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -76,10 +76,6 @@
 
 #include <xgehal.h>
 
-#if defined(__sparc) || defined(__amd64)
-#define	XGELL_L3_ALIGNED		1
-#endif
-
 /*
  * These default values can be overridden by vaules in xge.conf.
  * In xge.conf user has to specify actual (not percentages) values.
@@ -239,10 +235,6 @@
 	ddi_acc_handle_t		dma_acch;
 	void				*lldev;
 	frtn_t				frtn;
-#ifdef XGELL_L3_ALIGNED
-	unsigned char			header[XGE_HAL_TCPIP_HEADER_MAX_SIZE * 2
-					+ 8];
-#endif
 } xgell_rx_buffer_t;
 
 /* Buffer pool for all rings */