changeset 11951:8e81dc1bbfea

6915876 hermon is not handling timeout during flash correctly 6919684 ibt_get_ip_paths fails when source IP address is not the gateway for the IP subnet
author Shantkumar Hiremath<Shantkumar.Hiremath@Sun.COM>
date Thu, 18 Mar 2010 06:33:50 -0700
parents 27929c562084
children 23fffbb2918e
files usr/src/uts/common/io/ib/adapters/hermon/hermon_ioctl.c usr/src/uts/common/io/ib/mgt/ibcm/ibcm_arp.c usr/src/uts/common/io/ib/mgt/ibcm/ibcm_arp_link.c usr/src/uts/common/io/ib/mgt/ibcm/ibcm_path.c usr/src/uts/common/sys/ib/mgt/ibcm/ibcm_arp.h
diffstat 5 files changed, 164 insertions(+), 412 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_ioctl.c	Thu Mar 18 02:13:19 2010 -0400
+++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_ioctl.c	Thu Mar 18 06:33:50 2010 -0700
@@ -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.
  */
 
@@ -2275,6 +2275,14 @@
 		} while ((data & HERMON_HW_FLASH_CMD_MASK) &&
 		    (timeout < hermon_hw_flash_timeout_config));
 
+		if (timeout == hermon_hw_flash_timeout_config) {
+			cmn_err(CE_WARN, "hermon_flash_read: command timed "
+			    "out.\n");
+			*err = EIO;
+			hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
+			return (data);
+		}
+
 		data = hermon_flash_read_cfg(state, hdl, HERMON_HW_FLASH_DATA);
 		break;
 
@@ -2286,12 +2294,6 @@
 		break;
 	}
 
-	if (timeout == hermon_hw_flash_timeout_config) {
-		cmn_err(CE_WARN, "hermon_flash_read: command timed out.\n");
-		*err = EIO;
-		hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
-		return (data);
-	}
 
 	/* the FMA retry loop ends. */
 	hermon_pio_end(state, hdl, pio_error, fm_loop_cnt, fm_status, fm_test);
--- a/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_arp.c	Thu Mar 18 02:13:19 2010 -0400
+++ b/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_arp.c	Thu Mar 18 06:33:50 2010 -0700
@@ -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.
  */
 
@@ -41,7 +41,7 @@
 extern char cmlog[];
 
 extern int ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s,
-    ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr);
+    ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr, zoneid_t myzoneid);
 extern void ibcm_arp_delete_prwqn(ibcm_arp_prwqn_t *wqnp);
 
 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibt_ip_addr_s))
@@ -78,15 +78,17 @@
 
 
 ibt_status_t
-ibcm_arp_get_ibaddr(ibt_ip_addr_t srcaddr, ibt_ip_addr_t destaddr,
-    ib_gid_t *sgid, ib_gid_t *dgid)
+ibcm_arp_get_ibaddr(zoneid_t myzoneid, ibt_ip_addr_t srcaddr,
+    ibt_ip_addr_t destaddr, ib_gid_t *sgid, ib_gid_t *dgid,
+    ibt_ip_addr_t *saddrp)
 {
 	ibcm_arp_streams_t	*ib_s;
 	ibcm_arp_prwqn_t	*wqnp;
 	int			ret = 0;
+	int			len;
 
-	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr(%p, %p, %p, %p)",
-	    srcaddr, destaddr, sgid, dgid);
+	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr(%d, %p, %p, %p, %p, %p)",
+	    myzoneid, srcaddr, destaddr, sgid, dgid, saddrp);
 
 	ib_s = (ibcm_arp_streams_t *)kmem_zalloc(sizeof (ibcm_arp_streams_t),
 	    KM_SLEEP);
@@ -98,7 +100,7 @@
 	ib_s->done = B_FALSE;
 	mutex_exit(&ib_s->lock);
 
-	ret = ibcm_resolver_pr_lookup(ib_s, &destaddr, &srcaddr);
+	ret = ibcm_resolver_pr_lookup(ib_s, &destaddr, &srcaddr, myzoneid);
 
 	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: ibcm_resolver_pr_lookup "
 	    "returned: %d", ret);
@@ -113,14 +115,66 @@
 	wqnp = ib_s->wqnp;
 	if (ib_s->status == 0) {
 		if (sgid)
-			*sgid = ib_s->wqnp->sgid;
+			*sgid = wqnp->sgid;
 		if (dgid)
-			*dgid = ib_s->wqnp->dgid;
+			*dgid = wqnp->dgid;
+		/*
+		 * If the user supplied a address, then verify we got
+		 * for the same address.
+		 */
+		if (wqnp->usrc_addr.family && sgid) {
+			len = (wqnp->usrc_addr.family == AF_INET) ?
+			    IP_ADDR_LEN : sizeof (in6_addr_t);
+			if (bcmp(&wqnp->usrc_addr.un,
+			    &wqnp->src_addr.un, len)) {
+				IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: "
+				    "srcaddr mismatch");
+
+				/* Clean-up old data, and reset the done flag */
+				ibcm_arp_delete_prwqn(wqnp);
+				ib_s->done = B_FALSE;
+				mutex_exit(&ib_s->lock);
+
+				ret = ibcm_resolver_pr_lookup(ib_s, &srcaddr,
+				    &srcaddr, myzoneid);
+				if (ret == 0) {
+					mutex_enter(&ib_s->lock);
+					while (ib_s->done != B_TRUE)
+						cv_wait(&ib_s->cv, &ib_s->lock);
+					mutex_exit(&ib_s->lock);
+				}
+				mutex_enter(&ib_s->lock);
+				wqnp = ib_s->wqnp;
+				if (ib_s->status == 0) {
+					if (sgid)
+						*sgid = wqnp->dgid;
+
+					if (saddrp)
+						bcopy(&wqnp->src_addr, saddrp,
+						    sizeof (ibt_ip_addr_t));
+
+					IBTF_DPRINTF_L4(cmlog,
+					    "ibcm_arp_get_ibaddr: "
+					    "SGID: %llX:%llX DGID: %llX:%llX",
+					    sgid->gid_prefix, sgid->gid_guid,
+					    dgid->gid_prefix, dgid->gid_guid);
+
+					ibcm_arp_delete_prwqn(wqnp);
+				} else if (ret == 0) {
+					if (wqnp)
+						kmem_free(wqnp,
+						    sizeof (ibcm_arp_prwqn_t));
+				}
+				goto arp_ibaddr_done;
+			}
+		}
+
+		if (saddrp)
+			bcopy(&wqnp->src_addr, saddrp, sizeof (ibt_ip_addr_t));
 
 		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr: SGID: %llX:%llX"
-		    " DGID: %llX:%llX",
-		    ib_s->wqnp->sgid.gid_prefix, ib_s->wqnp->sgid.gid_guid,
-		    ib_s->wqnp->dgid.gid_prefix, ib_s->wqnp->dgid.gid_guid);
+		    " DGID: %llX:%llX", sgid->gid_prefix, sgid->gid_guid,
+		    dgid->gid_prefix, dgid->gid_guid);
 
 		ibcm_arp_delete_prwqn(wqnp);
 	} else if (ret == 0) {
@@ -132,6 +186,7 @@
 		if (wqnp)
 			kmem_free(wqnp, sizeof (ibcm_arp_prwqn_t));
 	}
+arp_ibaddr_done:
 	ret = ib_s->status;
 	mutex_exit(&ib_s->lock);
 
@@ -148,76 +203,6 @@
 }
 
 
-/*
- * Routine to get list of "local" IP-ADDR to GID/P_KEY mapping information.
- * Optionally, if "gid" and/or "p_key" info are specified, then retrieve the
- * IP-ADDR info for that attribute only.
- */
-
-static ibcm_arp_ip_t *
-ibcm_arp_ibd_gid2mac(ib_gid_t *gid, ib_pkey_t pkey, ibcm_arp_ibd_insts_t *ibdp)
-{
-	ibcm_arp_ip_t		*ipp;
-	int			i;
-
-	for (i = 0, ipp = ibdp->ibcm_arp_ip; i < ibdp->ibcm_arp_ibd_cnt;
-	    i++, ipp++) {
-		if ((ipp->ip_port_gid.gid_prefix == gid->gid_prefix) &&
-		    (ipp->ip_port_gid.gid_guid == gid->gid_guid)) {
-			if (pkey) {
-				if (ipp->ip_pkey == pkey)
-					return (ipp);
-				else
-					continue;
-			}
-			return (ipp);
-		}
-	}
-	return (NULL);
-}
-
-static ibt_status_t
-ibcm_arp_ibd_mac2gid(ibcm_arp_ibd_insts_t *ibdp, ibt_ip_addr_t *srcip,
-    ib_gid_t *sgid)
-{
-	ibcm_arp_ip_t		*ipp;
-	int			i;
-	boolean_t		found = B_FALSE;
-
-	for (i = 0, ipp = ibdp->ibcm_arp_ip; i < ibdp->ibcm_arp_ibd_cnt;
-	    i++, ipp++) {
-
-		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_ibd_mac2gid: GID %llX:%llX",
-		    ipp->ip_port_gid.gid_prefix, ipp->ip_port_gid.gid_guid);
-
-		if (srcip->family == ipp->ip_inet_family) {
-			if ((srcip->family == AF_INET) &&
-			    (bcmp(&srcip->un.ip4addr, &ipp->ip_cm_sin.sin_addr,
-			    sizeof (in_addr_t)) == 0)) {
-				found = B_TRUE;
-			} else if ((srcip->family == AF_INET6) &&
-			    IN6_ARE_ADDR_EQUAL(&srcip->un.ip6addr,
-			    &ipp->ip_cm_sin6.sin6_addr)) {
-				found = B_TRUE;
-			}
-			if (found) {
-				*sgid = ipp->ip_port_gid;
-
-				IBTF_DPRINTF_L4(cmlog, "ibcm_arp_ibd_mac2gid: "
-				    "Found GID %llX:%llX", sgid->gid_prefix,
-				    sgid->gid_guid);
-				return (IBT_SUCCESS);
-			}
-		} else {
-			IBTF_DPRINTF_L3(cmlog, "ibcm_arp_ibd_mac2gid: Different"
-			    " family keep searching...");
-		}
-	}
-	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_ibd_mac2gid: Matching SRC info "
-	    "NOT Found");
-	return (IBT_SRC_IP_NOT_FOUND);
-}
-
 static int
 ibcm_arp_get_ibd_insts_cb(dev_info_t *dip, void *arg)
 {
@@ -444,158 +429,3 @@
 
 	return (IBT_SUCCESS);
 }
-
-_NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibtl_cm_port_list_t))
-
-ibt_status_t
-ibcm_arp_get_srcip_plist(ibt_ip_path_attr_t *ipattr, ibt_path_flags_t flags,
-    ibtl_cm_port_list_t **port_list_p)
-{
-	ibt_path_attr_t		attr;
-	ibt_status_t		ret;
-	ibcm_arp_ibd_insts_t	ibds;
-	ibcm_arp_ip_t		*ipp;
-	ibtl_cm_port_list_t	*plistp;
-	ib_gid_t		sgid;
-	sa_family_t		family_interested = AF_UNSPEC;
-
-	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist(%p, %llX)",
-	    ipattr, flags);
-
-	if (ipattr->ipa_src_ip.family != AF_UNSPEC)
-		family_interested = ipattr->ipa_src_ip.family;
-	else
-		family_interested = ipattr->ipa_dst_ip[0].family;
-
-	sgid.gid_prefix = sgid.gid_guid = 0;
-	bzero(&ibds, sizeof (ibcm_arp_ibd_insts_t));
-	ibds.ibcm_arp_ibd_alloc = IBCM_ARP_IBD_INSTANCES;
-	ibds.ibcm_arp_ibd_cnt = 0;
-	ibds.ibcm_arp_ip = (ibcm_arp_ip_t *)kmem_zalloc(
-	    ibds.ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t), KM_SLEEP);
-
-	ret = ibcm_arp_get_ibds(&ibds, family_interested);
-	if (ret != IBT_SUCCESS) {
-		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_srcip_plist: "
-		    "ibcm_arp_get_ibds failed : 0x%x", ret);
-		goto srcip_plist_end;
-	}
-
-	if (ipattr->ipa_src_ip.family != AF_UNSPEC) {
-		ret = ibcm_arp_ibd_mac2gid(&ibds, &ipattr->ipa_src_ip, &sgid);
-		if (ret != IBT_SUCCESS) {
-			IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_srcip_plist: "
-			    "SGID for the specified SRCIP Not found %X", ret);
-			goto srcip_plist_end;
-		}
-		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist: SGID "
-		    "%llX:%llX", sgid.gid_prefix, sgid.gid_guid);
-	}
-
-	bzero(&attr, sizeof (ibt_path_attr_t));
-	attr.pa_hca_guid = ipattr->ipa_hca_guid;
-	attr.pa_hca_port_num = ipattr->ipa_hca_port_num;
-	attr.pa_sgid = sgid;
-	bcopy(&ipattr->ipa_mtu,  &attr.pa_mtu, sizeof (ibt_mtu_req_t));
-	bcopy(&ipattr->ipa_srate,  &attr.pa_srate, sizeof (ibt_srate_req_t));
-	bcopy(&ipattr->ipa_pkt_lt,  &attr.pa_pkt_lt, sizeof (ibt_pkt_lt_req_t));
-
-	ret = ibtl_cm_get_active_plist(&attr, flags, port_list_p);
-	if (ret == IBT_SUCCESS) {
-		int		i;
-		uint8_t		cnt;
-		boolean_t	no_srcip_configured = B_FALSE;
-		uint8_t		no_srcip_cnt = 0;
-
-		plistp = port_list_p[0];
-		cnt = plistp->p_count;
-		for (i = 0; i < cnt; i++, plistp++) {
-			ipp = ibcm_arp_ibd_gid2mac(&plistp->p_sgid, 0, &ibds);
-			if ((ipp == NULL) ||
-			    (ipp->ip_inet_family == AF_UNSPEC)) {
-				plistp->p_src_ip.family = AF_UNSPEC;
-				no_srcip_configured = B_TRUE;
-				no_srcip_cnt++;
-				IBTF_DPRINTF_L3(cmlog,
-				    "ibcm_arp_get_srcip_plist: SrcIP NOT "
-				    "Configured for GID %llX:%llX",
-				    plistp->p_sgid.gid_prefix,
-				    plistp->p_sgid.gid_guid);
-			} else {
-				IBTF_DPRINTF_L4(cmlog,
-				    "ibcm_arp_get_srcip_plist: GID %llX:%llX",
-				    plistp->p_sgid.gid_prefix,
-				    plistp->p_sgid.gid_guid);
-				if (ipp->ip_inet_family == AF_INET) {
-					plistp->p_src_ip.family = AF_INET;
-					bcopy(&ipp->ip_cm_sin.sin_addr,
-					    &plistp->p_src_ip.un.ip4addr,
-					    sizeof (in_addr_t));
-
-				} else if (ipp->ip_inet_family == AF_INET6) {
-					plistp->p_src_ip.family = AF_INET6;
-					bcopy(&ipp->ip_cm_sin6.sin6_addr,
-					    &plistp->p_src_ip.un.ip6addr,
-					    sizeof (in6_addr_t));
-				}
-				IBCM_PRINT_IP("ibcm_arp_get_srcip_plist: "
-				    "IP Addr is:", &plistp->p_src_ip);
-			}
-		}
-		if (no_srcip_configured) {
-			ibtl_cm_port_list_t	*n_plistp, *tmp_n_plistp;
-			uint8_t			new_cnt;
-
-			new_cnt = cnt - no_srcip_cnt;
-
-			/*
-			 * Looks like some of the SRC GID we found have no
-			 * IP ADDR configured, so remove these entries from
-			 * our list.
-			 */
-			plistp = port_list_p[0];
-			IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist: "
-			    "Only %d SGID (%d/%d) have SrcIP Configured",
-			    new_cnt, no_srcip_cnt, cnt);
-			if (new_cnt) {
-				/* Allocate Memory to hold Src Point info. */
-				n_plistp = kmem_zalloc(new_cnt *
-				    sizeof (ibtl_cm_port_list_t), KM_SLEEP);
-
-				tmp_n_plistp = n_plistp;
-				for (i = 0; i < cnt; i++, plistp++) {
-					if (plistp->p_src_ip.family ==
-					    AF_UNSPEC)
-						continue;
-
-					bcopy(plistp, n_plistp,
-					    sizeof (ibtl_cm_port_list_t));
-					n_plistp->p_count = new_cnt;
-					n_plistp++;
-				}
-				plistp = port_list_p[0];
-				*port_list_p = tmp_n_plistp;
-			} else {
-				/*
-				 * All entries we have, do not have IP-Addr
-				 * configured so return empty hand.
-				 */
-				IBTF_DPRINTF_L2(cmlog,
-				    "ibcm_arp_get_srcip_plist: None of SGID "
-				    "found have SrcIP Configured");
-				*port_list_p = NULL;
-				ret = IBT_SRC_IP_NOT_FOUND;
-			}
-			IBTF_DPRINTF_L4(cmlog, "FREE OLD list %p, NEW list is "
-			    "%p - %p", plistp, port_list_p, *port_list_p);
-			kmem_free(plistp, cnt * sizeof (ibtl_cm_port_list_t));
-		}
-	}
-
-srcip_plist_end:
-	if (ibds.ibcm_arp_ip)
-		kmem_free(ibds.ibcm_arp_ip, ibds.ibcm_arp_ibd_alloc *
-		    sizeof (ibcm_arp_ip_t));
-
-	return (ret);
-}
--- a/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_arp_link.c	Thu Mar 18 02:13:19 2010 -0400
+++ b/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_arp_link.c	Thu Mar 18 06:33:50 2010 -0700
@@ -104,7 +104,7 @@
 
 int
 ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr,
-    ibt_ip_addr_t *src_addr)
+    ibt_ip_addr_t *src_addr, zoneid_t myzoneid)
 {
 	ibcm_arp_prwqn_t *wqnp;
 	ire_t	*ire = NULL;
@@ -112,7 +112,6 @@
 	ill_t	*ill = NULL;
 	ill_t	*hwaddr_ill = NULL;
 	ip_stack_t *ipst;
-	int		len;
 	ipaddr_t	setsrcv4;
 	in6_addr_t	setsrcv6;
 
@@ -126,30 +125,16 @@
 		return (1);
 	}
 
-	ipst = netstack_find_by_zoneid(GLOBAL_ZONEID)->netstack_ip;
+	ipst = netstack_find_by_zoneid(myzoneid)->netstack_ip;
 	if (dst_addr->family == AF_INET) {
 		/*
-		 * A local address is always specified, and it is used
-		 * to find the zoneid.
-		 */
-		ipif = ipif_lookup_addr(src_addr->un.ip4addr, NULL, ALL_ZONES,
-		    ipst);
-		if (ipif == NULL) {
-			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
-			    "ipif_lookup_addr failed");
-			ib_s->status = EFAULT;
-			goto fail;
-		}
-
-		/*
 		 * get an ire for the destination adress.
 		 * Note that we can't use MATCH_IRE_ILL since that would
-		 * require that the first ill we find have ire_ill set. Thus
-		 * we compare ire_ill against ipif_ill after the lookup.
+		 * require that the first ill we find have ire_ill set.
 		 */
 		setsrcv4 = INADDR_ANY;
 		ire = ire_route_recursive_v4(dst_addr->un.ip4addr, 0, NULL,
-		    ipif->ipif_zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst,
+		    myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst,
 		    &setsrcv4, NULL, NULL);
 
 		ASSERT(ire != NULL);
@@ -166,35 +151,22 @@
 			ib_s->status = EFAULT;
 			goto fail;
 		}
-		if (ill != ipif->ipif_ill) {
-			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
-			    "wrong ill");
-			ib_s->status = EFAULT;
+
+		/* Pick a source address */
+		if (ip_select_source_v4(ill, setsrcv4, dst_addr->un.ip4addr,
+		    INADDR_ANY, myzoneid, ipst, &wqnp->src_addr.un.ip4addr,
+		    NULL, NULL) != 0) {
+			ib_s->status = EADDRNOTAVAIL;
 			goto fail;
 		}
 
 		wqnp->gateway.un.ip4addr = ire->ire_gateway_addr;
 		wqnp->netmask.un.ip4addr = ire->ire_mask;
-		wqnp->src_addr.un.ip4addr = src_addr->un.ip4addr;
 		wqnp->src_addr.family = wqnp->gateway.family =
 		    wqnp->netmask.family = AF_INET;
 
 	} else if (dst_addr->family == AF_INET6) {
 		/*
-		 * A local address is always specified, and it is used
-		 * to find the zoneid.
-		 * We should really match on scopeid for link locals here.
-		 */
-		ipif = ipif_lookup_addr_v6(&src_addr->un.ip6addr, NULL,
-		    ALL_ZONES, ipst);
-		if (ipif == NULL) {
-			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
-			    "ipif_lookup_addr_v6 failed");
-			ib_s->status = EFAULT;
-			goto fail;
-		}
-
-		/*
 		 * get an ire for the destination adress.
 		 * Note that we can't use MATCH_IRE_ILL since that would
 		 * require that the first ill we find have ire_ill set. Thus
@@ -202,7 +174,7 @@
 		 */
 		setsrcv6 = ipv6_all_zeros;
 		ire = ire_route_recursive_v6(&dst_addr->un.ip6addr, 0, NULL,
-		    ipif->ipif_zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst,
+		    myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst,
 		    &setsrcv6, NULL, NULL);
 
 		ASSERT(ire != NULL);
@@ -220,16 +192,16 @@
 			goto fail;
 		}
 
-		if (ill != ipif->ipif_ill) {
-			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
-			    "wrong ill");
-			ib_s->status = EFAULT;
+		/* Pick a source address */
+		if (ip_select_source_v6(ill, &setsrcv6, &dst_addr->un.ip6addr,
+		    myzoneid, ipst, B_FALSE, IPV6_PREFER_SRC_DEFAULT,
+		    &wqnp->src_addr.un.ip6addr, NULL, NULL) != 0) {
+			ib_s->status = EADDRNOTAVAIL;
 			goto fail;
 		}
 
 		wqnp->gateway.un.ip6addr = ire->ire_gateway_addr_v6;
 		wqnp->netmask.un.ip6addr = ire->ire_mask_v6;
-		wqnp->src_addr.un.ip6addr = src_addr->un.ip6addr;
 		wqnp->src_addr.family = wqnp->gateway.family =
 		    wqnp->netmask.family = AF_INET6;
 	}
@@ -241,6 +213,18 @@
 	 * interface bound to the given address.
 	 */
 	if (IS_IPMP(ill)) {
+		if (wqnp->src_addr.family == AF_INET) {
+			ipif = ipif_lookup_addr(wqnp->src_addr.un.ip4addr, ill,
+			    myzoneid, ipst);
+		} else {
+			ipif = ipif_lookup_addr_v6(&wqnp->src_addr.un.ip6addr,
+			    ill, myzoneid, ipst);
+		}
+		if (ipif == NULL) {
+			ib_s->status = ENETUNREACH;
+			goto fail;
+		}
+
 		if ((hwaddr_ill = ipmp_ipif_hold_bound_ill(ipif)) == NULL) {
 			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
 			    "no bound ill for IPMP interface %s",
@@ -266,25 +250,11 @@
 	    wqnp->ifname);
 
 	/*
-	 * if the user supplied a address, then verify rts returned
-	 * the same address
-	 */
-	if (wqnp->usrc_addr.family) {
-		len = (wqnp->usrc_addr.family == AF_INET) ?
-		    IP_ADDR_LEN : sizeof (in6_addr_t);
-		if (bcmp(&wqnp->usrc_addr.un, &wqnp->src_addr.un, len)) {
-			IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
-			    "srcaddr mismatch:%d", ENETUNREACH);
-			goto fail;
-		}
-	}
-
-	/*
 	 * at this stage, we have the source address and the IB
 	 * interface, now get the destination mac address from
 	 * arp or ipv6 drivers
 	 */
-	ib_s->status = ibcm_nce_lookup(wqnp, ill, getzoneid());
+	ib_s->status = ibcm_nce_lookup(wqnp, ill, myzoneid);
 	if (ib_s->status != 0) {
 		IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: "
 		    "ibcm_nce_lookup failed: %d", ib_s->status);
@@ -294,7 +264,8 @@
 	ill_refrele(hwaddr_ill);
 	ill_refrele(ill);
 	ire_refrele(ire);
-	ipif_refrele(ipif);
+	if (ipif != NULL)
+		ipif_refrele(ipif);
 	netstack_rele(ipst->ips_netstack);
 
 	IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: Return: 0x%p", wqnp);
--- a/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_path.c	Thu Mar 18 02:13:19 2010 -0400
+++ b/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_path.c	Thu Mar 18 06:33:50 2010 -0700
@@ -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.
  */
 
@@ -63,9 +63,6 @@
 
 
 /* Prototype Declarations. */
-static ibt_status_t ibcm_get_path_rec(ibcm_path_tqargs_t *, ibcm_dinfo_t *,
-    uint8_t *, ibt_path_info_t *);
-
 static ibt_status_t ibcm_saa_path_rec(ibcm_path_tqargs_t *,
     ibtl_cm_port_list_t *, ibcm_dinfo_t *, uint8_t *);
 
@@ -660,8 +657,8 @@
 	ibt_status_t		retval;
 	ib_gid_t		*d_gids_p = NULL;
 	ibtl_cm_port_list_t	*slistp = NULL;
-	uint_t			dnum = 0, num_dest;
-	uint_t			i, j;
+	uint_t			dnum = 0;
+	uint8_t			num_dest, i, j;
 	ibcm_hca_info_t		*hcap;
 	ibmf_saa_handle_t	saa_handle;
 
@@ -899,7 +896,7 @@
 {
 	uint8_t		num_path = *max_count;
 	uint8_t		num_path_plus;
-	uint_t		extra, idx, rec_found = 0;
+	uint8_t		extra, idx, rec_found = 0;
 	ibt_status_t	retval = IBT_SUCCESS;
 	int		unicast_dgid_present = 0;
 	uint8_t		i;
@@ -1126,7 +1123,7 @@
 	size_t			length;
 	ibt_status_t		retval;
 	int			i, j, k;
-	int			found, p_fnd;
+	uint8_t			found, p_fnd;
 	ibt_path_attr_t		*attrp = &p_arg->attr;
 	ibmf_saa_handle_t	saa_handle;
 
@@ -1386,7 +1383,8 @@
 	uint64_t		c_mask = 0;
 	ib_gid_t		*gid_ptr, *gid_s_ptr;
 	size_t			length;
-	int			template_len, found, num_rec;
+	int			template_len;
+	uint8_t			found, num_rec;
 	int			i, k;
 	ibt_status_t		retval;
 	uint8_t			sgid_cnt, dgid_cnt;
@@ -3023,15 +3021,10 @@
 	uint_t			len;
 } ibcm_ip_path_tqargs_t;
 
-typedef struct ibcm_ip_dest_s {
-	ib_gid_t	d_gid;
-	ibt_ip_addr_t	d_ip;
-} ibcm_ip_dest_t;
-
 /* Holds destination information needed to fill in ibt_path_info_t. */
 typedef struct ibcm_ip_dinfo_s {
 	uint8_t		num_dest;
-	ibcm_ip_dest_t	dest[1];
+	ib_gid_t	d_gid[1];
 } ibcm_ip_dinfo_t;
 
 _NOTE(SCHEME_PROTECTS_DATA("Temporary path storage", ibcm_ip_dinfo_s))
@@ -3052,7 +3045,7 @@
     ibcm_ip_dinfo_t *dinfo, uint8_t *max_count)
 {
 	uint8_t		num_path = *max_count;
-	uint_t		rec_found = 0;
+	uint8_t		rec_found = 0;
 	ibt_status_t	retval = IBT_SUCCESS;
 	uint8_t		i, j;
 
@@ -3173,7 +3166,7 @@
 	size_t			length;
 	ibt_status_t		retval;
 	int			i, j, k;
-	int			found, p_fnd;
+	uint8_t			found, p_fnd;
 	ibt_ip_path_attr_t	*attrp = &p_arg->attr;
 	ibmf_saa_handle_t	saa_handle;
 
@@ -3278,15 +3271,15 @@
 
 		for (k = 0; k < dinfo->num_dest; k++) {
 			if (pathrec_req.SGID.gid_prefix !=
-			    dinfo->dest[k].d_gid.gid_prefix) {
+			    dinfo->d_gid[k].gid_prefix) {
 				IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: "
 				    "SGID_pfx=%llX DGID_pfx=%llX doesn't match",
 				    pathrec_req.SGID.gid_prefix,
-				    dinfo->dest[k].d_gid.gid_prefix);
+				    dinfo->d_gid[k].gid_prefix);
 				continue;
 			}
 
-			pathrec_req.DGID = dinfo->dest[k].d_gid;
+			pathrec_req.DGID = dinfo->d_gid[k];
 			c_mask |= SA_PR_COMPMASK_DGID;
 
 			IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: "
@@ -3390,7 +3383,8 @@
 	uint64_t		c_mask = 0;
 	ib_gid_t		*gid_ptr, *gid_s_ptr;
 	size_t			length;
-	int			template_len, found, num_rec;
+	int			template_len;
+	uint8_t			found, num_rec;
 	int			i;
 	ibt_status_t		retval;
 	uint8_t			sgid_cnt, dgid_cnt;
@@ -3446,7 +3440,7 @@
 
 	/* DGIDs */
 	for (i = 0; i < dgid_cnt; i++) {
-		*gid_ptr = dinfo->dest[i].d_gid;
+		*gid_ptr = dinfo->d_gid[i];
 
 		IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: DGID[%d] = "
 		    "%llX:%llX", i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
@@ -3749,9 +3743,11 @@
 	ibt_status_t		retval = IBT_SUCCESS;
 	ibtl_cm_port_list_t	*sl = NULL;
 	uint_t			dnum = 0;
-	uint_t			i, j;
+	uint8_t			i;
 	ibcm_hca_info_t		*hcap;
 	ibmf_saa_handle_t	saa_handle;
+	ibt_path_attr_t		attr;
+	ibt_ip_addr_t		src_ip_p;
 
 	IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths(%p, 0x%X) ",
 	    p_arg, p_arg->flags);
@@ -3770,109 +3766,64 @@
 	 */
 	dgid1.gid_prefix = dgid1.gid_guid = 0;
 	sgid.gid_prefix = sgid.gid_guid = 0;
-	if ((p_arg->attr.ipa_src_ip.family != AF_UNSPEC) &&
-	    (!(p_arg->flags & IBT_PATH_APM))) {
-		ibt_path_attr_t		attr;
-
-		retval = ibcm_arp_get_ibaddr(p_arg->attr.ipa_src_ip,
-		    p_arg->attr.ipa_dst_ip[0], &sgid, &dgid1);
-		if (retval) {
-			IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
-			    "ibcm_arp_get_ibaddr() failed: %d", retval);
-			goto ippath_error;
-		}
-
-		bzero(&attr, sizeof (ibt_path_attr_t));
-		attr.pa_hca_guid = p_arg->attr.ipa_hca_guid;
-		attr.pa_hca_port_num = p_arg->attr.ipa_hca_port_num;
-		attr.pa_sgid = sgid;
-		bcopy(&p_arg->attr.ipa_mtu, &attr.pa_mtu,
-		    sizeof (ibt_mtu_req_t));
-		bcopy(&p_arg->attr.ipa_srate, &attr.pa_srate,
-		    sizeof (ibt_srate_req_t));
-		bcopy(&p_arg->attr.ipa_pkt_lt, &attr.pa_pkt_lt,
-		    sizeof (ibt_pkt_lt_req_t));
-		retval = ibtl_cm_get_active_plist(&attr, p_arg->flags, &sl);
-		if (retval == IBT_SUCCESS) {
-			bcopy(&p_arg->attr.ipa_src_ip, &sl->p_src_ip,
-			    sizeof (ibt_ip_addr_t));
-		} else {
-			IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
-			    "ibtl_cm_get_active_plist: Failed %d", retval);
-			goto ippath_error;
-		}
+
+	retval = ibcm_arp_get_ibaddr(getzoneid(), p_arg->attr.ipa_src_ip,
+	    p_arg->attr.ipa_dst_ip[0], &sgid, &dgid1, &src_ip_p);
+	if (retval) {
+		IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
+		    "ibcm_arp_get_ibaddr() failed: %d", retval);
+		goto ippath_error;
+	}
+
+	bzero(&attr, sizeof (ibt_path_attr_t));
+	attr.pa_hca_guid = p_arg->attr.ipa_hca_guid;
+	attr.pa_hca_port_num = p_arg->attr.ipa_hca_port_num;
+	attr.pa_sgid = sgid;
+	bcopy(&p_arg->attr.ipa_mtu, &attr.pa_mtu, sizeof (ibt_mtu_req_t));
+	bcopy(&p_arg->attr.ipa_srate, &attr.pa_srate, sizeof (ibt_srate_req_t));
+	bcopy(&p_arg->attr.ipa_pkt_lt, &attr.pa_pkt_lt,
+	    sizeof (ibt_pkt_lt_req_t));
+	retval = ibtl_cm_get_active_plist(&attr, p_arg->flags, &sl);
+	if (retval == IBT_SUCCESS) {
+		bcopy(&src_ip_p, &sl->p_src_ip, sizeof (ibt_ip_addr_t));
 	} else {
-		boolean_t	arp_nd_lookup = B_FALSE;
-
-		/*
-		 * Get list of active HCA-Port list, that matches input
-		 * specified attr.
-		 */
-		retval = ibcm_arp_get_srcip_plist(&p_arg->attr, p_arg->flags,
-		    &sl);
-		if (retval != IBT_SUCCESS) {
-			IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
-			    "ibcm_arp_get_srcip_plist: Failed %d", retval);
-			goto ippath_error;
-		}
-
-		/*
-		 * Accumulate all destination information.
-		 * Get GID info for the specified input ip-addr.
-		 */
-		for (j = 0; j < sl->p_count; j++) {
-			retval = ibcm_arp_get_ibaddr(sl[j].p_src_ip,
-			    p_arg->attr.ipa_dst_ip[0], NULL, &dgid1);
-			if (retval == IBT_SUCCESS) {
-				arp_nd_lookup = B_TRUE; /* found */
-				IBCM_PRINT_IP("ibcm_process_get_ip_paths: "
-				    "SrcIP ", &sl[j].p_src_ip);
-				IBCM_PRINT_IP("ibcm_process_get_ip_paths: "
-				    "DstIP ", &p_arg->attr.ipa_dst_ip[0]);
-				break;
-			}
-			IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths: "
-			    "ibcm_arp_get_ibaddr() failed: %d", retval);
-		}
-		if (!arp_nd_lookup)
-			goto ippath_error1;
+		IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
+		    "ibtl_cm_get_active_plist: Failed %d", retval);
+		goto ippath_error;
 	}
 
 	IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_ip_paths: SGID %llX:%llX, "
 	    "DGID0: %llX:%llX", sl->p_sgid.gid_prefix, sl->p_sgid.gid_guid,
 	    dgid1.gid_prefix, dgid1.gid_guid);
 
-	len = p_arg->attr.ipa_ndst + 1;
-	len = (len * sizeof (ibcm_ip_dest_t)) + sizeof (ibcm_ip_dinfo_t);
+	len = p_arg->attr.ipa_ndst - 1;
+	len = (len * sizeof (ib_gid_t)) + sizeof (ibcm_ip_dinfo_t);
 	dinfo = kmem_zalloc(len, KM_SLEEP);
 
-	dinfo->dest[0].d_gid = dgid1;
-	bcopy(&p_arg->attr.ipa_dst_ip[0], &dinfo->dest[0].d_ip,
-	    sizeof (ibt_ip_addr_t));
+	dinfo->d_gid[0] = dgid1;
 
 	i = 1;
 	if (p_arg->attr.ipa_ndst > 1) {
 		/* Get DGID for all specified Dest IP Addr */
 		for (; i < p_arg->attr.ipa_ndst; i++) {
-			retval = ibcm_arp_get_ibaddr(sl->p_src_ip,
-			    p_arg->attr.ipa_dst_ip[i], NULL, &dgid2);
+			retval = ibcm_arp_get_ibaddr(getzoneid(),
+			    p_arg->attr.ipa_src_ip, p_arg->attr.ipa_dst_ip[i],
+			    NULL, &dgid2, NULL);
 			if (retval) {
 				IBTF_DPRINTF_L2(cmlog,
 				    "ibcm_process_get_ip_paths: "
 				    "ibcm_arp_get_ibaddr failed: %d", retval);
 				goto ippath_error2;
 			}
-			dinfo->dest[i].d_gid = dgid2;
+			dinfo->d_gid[i] = dgid2;
 
 			IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_ip_paths: "
 			    "DGID%d: %llX:%llX", i, dgid2.gid_prefix,
 			    dgid2.gid_guid);
-			bcopy(&p_arg->attr.ipa_dst_ip[i], &dinfo->dest[i].d_ip,
-			    sizeof (ibt_ip_addr_t));
 		}
 
 		if (p_arg->flags & IBT_PATH_APM) {
-			dgid2 = dinfo->dest[1].d_gid;
+			dgid2 = dinfo->d_gid[1];
 
 			retval = ibcm_get_comp_pgids(dgid1, dgid2, 0,
 			    &d_gids_p, &dnum);
@@ -3887,8 +3838,7 @@
 			    "Found %d Comp DGID", dnum);
 
 			if (dnum) {
-				dinfo->dest[i].d_gid = d_gids_p[0];
-				dinfo->dest[i].d_ip.family = AF_UNSPEC;
+				dinfo->d_gid[i] = d_gids_p[0];
 				i++;
 			}
 		}
@@ -4334,8 +4284,8 @@
 	/* If optional attributes are specified, validate them. */
 	if (attrp) {
 		/* Get SGID and DGID for the specified input ip-addr */
-		retval = ibcm_arp_get_ibaddr(attrp->apa_src_ip,
-		    attrp->apa_dst_ip, &new_sgid, &new_dgid);
+		retval = ibcm_arp_get_ibaddr(getzoneid(), attrp->apa_src_ip,
+		    attrp->apa_dst_ip, &new_sgid, &new_dgid, NULL);
 		if (retval) {
 			IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: "
 			    "ibcm_arp_get_ibaddr() failed: %d", retval);
--- a/usr/src/uts/common/sys/ib/mgt/ibcm/ibcm_arp.h	Thu Mar 18 02:13:19 2010 -0400
+++ b/usr/src/uts/common/sys/ib/mgt/ibcm/ibcm_arp.h	Thu Mar 18 06:33:50 2010 -0700
@@ -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.
  */
 
@@ -101,10 +101,9 @@
 	ibcm_arp_ip_t	*ibcm_arp_ip;
 } ibcm_arp_ibd_insts_t;
 
-ibt_status_t ibcm_arp_get_ibaddr(ibt_ip_addr_t srcip, ibt_ip_addr_t destip,
-    ib_gid_t *sgid, ib_gid_t *dgid);
-ibt_status_t ibcm_arp_get_srcip_plist(ibt_ip_path_attr_t *attr,
-    ibt_path_flags_t flags, ibtl_cm_port_list_t **list_p);
+ibt_status_t ibcm_arp_get_ibaddr(zoneid_t zoneid, ibt_ip_addr_t srcip,
+    ibt_ip_addr_t destip, ib_gid_t *sgid, ib_gid_t *dgid,
+    ibt_ip_addr_t *saddr_p);
 ibt_status_t ibcm_arp_get_ibds(ibcm_arp_ibd_insts_t *ibdp, sa_family_t fam);
 
 #ifdef	__cplusplus