6838710 mac_pkt_hash does not consider IP fragmentation which may result in out of order packets
authorBaban Kenkre <Baban.Kenkre@Sun.COM>
Sun, 17 Jan 2010 02:10:54 -0800
changeset 11528 31f6cde5edcb
parent 11527 24f8e55830c4
child 11529 0396f567d7e1
6838710 mac_pkt_hash does not consider IP fragmentation which may result in out of order packets
usr/src/uts/common/io/mac/mac_flow.c
usr/src/uts/common/io/mac/mac_sched.c
usr/src/uts/common/io/mac/mac_util.c
usr/src/uts/common/sys/mac_impl.h
--- a/usr/src/uts/common/io/mac/mac_flow.c	Sat Jan 16 16:04:55 2010 -0800
+++ b/usr/src/uts/common/io/mac/mac_flow.c	Sun Jan 17 02:10:54 2010 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1890,7 +1890,7 @@
 		uint8_t	 nexthdr;
 
 		if (!mac_ip_hdr_length_v6(s->fs_mp, ip6h, &ip6_hdrlen,
-		    &nexthdr)) {
+		    &nexthdr, NULL, NULL)) {
 			return (ENOBUFS);
 		}
 		l3info->l3_hdrsize = ip6_hdrlen;
--- a/usr/src/uts/common/io/mac/mac_sched.c	Sat Jan 16 16:04:55 2010 -0800
+++ b/usr/src/uts/common/io/mac/mac_sched.c	Sun Jan 17 02:10:54 2010 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -796,7 +796,7 @@
 		 * pullupmsg().
 		 */
 		if (mac_src_ipv6_fanout || !mac_ip_hdr_length_v6(mp, ip6h,
-		    &hdr_len, &nexthdr)) {
+		    &hdr_len, &nexthdr, NULL, NULL)) {
 			goto src_based_fanout;
 		}
 		whereptr = (uint8_t *)ip6h + hdr_len;
--- a/usr/src/uts/common/io/mac/mac_util.c	Sat Jan 16 16:04:55 2010 -0800
+++ b/usr/src/uts/common/io/mac/mac_util.c	Sun Jan 17 02:10:54 2010 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -462,7 +462,7 @@
  */
 boolean_t
 mac_ip_hdr_length_v6(mblk_t *mp, ip6_t *ip6h, uint16_t *hdr_length,
-    uint8_t *next_hdr)
+    uint8_t *next_hdr, boolean_t *ip_fragmented, uint32_t *ip_frag_ident)
 {
 	uint16_t length;
 	uint_t	ehdrlen;
@@ -480,6 +480,9 @@
 	length = IPV6_HDR_LEN;
 	whereptr = ((uint8_t *)&ip6h[1]); /* point to next hdr */
 
+	if (ip_fragmented != NULL)
+		*ip_fragmented = B_FALSE;
+
 	nexthdrp = &ip6h->ip6_nxt;
 	while (whereptr < endptr) {
 		/* Is there enough left for len + nexthdr? */
@@ -509,6 +512,10 @@
 			if ((uchar_t *)&fraghdr[1] > endptr)
 				return (B_FALSE);
 			nexthdrp = &fraghdr->ip6f_nxt;
+			if (ip_fragmented != NULL)
+				*ip_fragmented = B_TRUE;
+			if (ip_frag_ident != NULL)
+				*ip_frag_ident = fraghdr->ip6f_ident;
 			break;
 		case IPPROTO_NONE:
 			/* No next header means we're finished */
@@ -833,6 +840,7 @@
 	return ((void *)mip->mi_dip);
 }
 
+#define	PKT_HASH_2BYTES(x) ((x)[0] ^ (x)[1])
 #define	PKT_HASH_4BYTES(x) ((x)[0] ^ (x)[1] ^ (x)[2] ^ (x)[3])
 #define	PKT_HASH_MAC(x) ((x)[0] ^ (x)[1] ^ (x)[2] ^ (x)[3] ^ (x)[4] ^ (x)[5])
 
@@ -844,6 +852,7 @@
 	uint16_t sap;
 	uint_t skip_len;
 	uint8_t proto;
+	boolean_t ip_fragmented;
 
 	/*
 	 * We may want to have one of these per MAC type plugin in the
@@ -925,7 +934,16 @@
 		proto = iphp->ipha_protocol;
 		skip_len += IPH_HDR_LENGTH(iphp);
 
-		if ((policy & MAC_PKT_HASH_L3) != 0) {
+		/* Check if the packet is fragmented. */
+		ip_fragmented = ntohs(iphp->ipha_fragment_offset_and_flags) &
+		    IPH_OFFSET;
+
+		/*
+		 * For fragmented packets, use addresses in addition to
+		 * the frag_id to generate the hash inorder to get
+		 * better distribution.
+		 */
+		if (ip_fragmented || (policy & MAC_PKT_HASH_L3) != 0) {
 			uint8_t *ip_src = (uint8_t *)&(iphp->ipha_src);
 			uint8_t *ip_dst = (uint8_t *)&(iphp->ipha_dst);
 
@@ -933,11 +951,18 @@
 			    PKT_HASH_4BYTES(ip_dst));
 			policy &= ~MAC_PKT_HASH_L3;
 		}
+
+		if (ip_fragmented) {
+			uint8_t *identp = (uint8_t *)&iphp->ipha_ident;
+			hash ^= PKT_HASH_2BYTES(identp);
+			goto done;
+		}
 		break;
 	}
 	case ETHERTYPE_IPV6: {
 		ip6_t *ip6hp;
 		uint16_t hdr_length;
+		uint32_t ip_frag_ident;
 
 		/*
 		 * If the header is not aligned or the header doesn't fit
@@ -950,11 +975,17 @@
 		    !OK_32PTR((char *)ip6hp))
 			goto done;
 
-		if (!mac_ip_hdr_length_v6(mp, ip6hp, &hdr_length, &proto))
+		if (!mac_ip_hdr_length_v6(mp, ip6hp, &hdr_length, &proto,
+		    &ip_fragmented, &ip_frag_ident))
 			goto done;
 		skip_len += hdr_length;
 
-		if ((policy & MAC_PKT_HASH_L3) != 0) {
+		/*
+		 * For fragmented packets, use addresses in addition to
+		 * the frag_id to generate the hash inorder to get
+		 * better distribution.
+		 */
+		if (ip_fragmented || (policy & MAC_PKT_HASH_L3) != 0) {
 			uint8_t *ip_src = &(ip6hp->ip6_src.s6_addr8[12]);
 			uint8_t *ip_dst = &(ip6hp->ip6_dst.s6_addr8[12]);
 
@@ -962,6 +993,12 @@
 			    PKT_HASH_4BYTES(ip_dst));
 			policy &= ~MAC_PKT_HASH_L3;
 		}
+
+		if (ip_fragmented) {
+			uint8_t *identp = (uint8_t *)&ip_frag_ident;
+			hash ^= PKT_HASH_4BYTES(identp);
+			goto done;
+		}
 		break;
 	}
 	default:
--- a/usr/src/uts/common/sys/mac_impl.h	Sat Jan 16 16:04:55 2010 -0800
+++ b/usr/src/uts/common/sys/mac_impl.h	Sun Jan 17 02:10:54 2010 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -610,7 +610,7 @@
 extern void	mac_ndd_ioctl(mac_impl_t *, queue_t *, mblk_t *);
 extern void	mac_create_soft_ring_kstats(mac_impl_t *, int32_t);
 extern boolean_t mac_ip_hdr_length_v6(mblk_t *, ip6_t *, uint16_t *,
-    uint8_t *);
+    uint8_t *, boolean_t *, uint32_t *);
 
 extern mblk_t *mac_copymsgchain_cksum(mblk_t *);
 extern mblk_t *mac_fix_cksum(mblk_t *);