Home | History | Annotate | Download | only in ibcm
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <sys/types.h>
     27 #include <sys/ddi.h>
     28 #include <sys/sunddi.h>
     29 #include <sys/strsubr.h>
     30 #include <sys/socket.h>
     31 #include <net/if_arp.h>
     32 #include <net/if_types.h>
     33 #include <sys/sockio.h>
     34 #include <sys/pathname.h>
     35 
     36 #include <sys/ib/mgt/ibcm/ibcm_arp.h>
     37 
     38 #include <sys/kstr.h>
     39 #include <sys/t_kuser.h>
     40 
     41 extern char cmlog[];
     42 
     43 extern int ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s,
     44     ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr);
     45 extern void ibcm_arp_delete_prwqn(ibcm_arp_prwqn_t *wqnp);
     46 
     47 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibt_ip_addr_s))
     48 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_ip_t))
     49 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_ibd_insts_t))
     50 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_prwqn_t))
     51 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", sockaddr_in))
     52 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", sockaddr_in6))
     53 
     54 int ibcm_printip = 0;
     55 
     56 /*
     57  * Function:
     58  *	ibcm_ip_print
     59  * Input:
     60  *	label		Arbitrary qualifying string
     61  *	ipa		Pointer to IP Address to print
     62  */
     63 void
     64 ibcm_ip_print(char *label, ibt_ip_addr_t *ipaddr)
     65 {
     66 	char    buf[INET6_ADDRSTRLEN];
     67 
     68 	if (ipaddr->family == AF_INET) {
     69 		IBTF_DPRINTF_L2(cmlog, "%s: %s", label,
     70 		    inet_ntop(AF_INET, &ipaddr->un.ip4addr, buf, sizeof (buf)));
     71 	} else if (ipaddr->family == AF_INET6) {
     72 		IBTF_DPRINTF_L2(cmlog, "%s: %s", label, inet_ntop(AF_INET6,
     73 		    &ipaddr->un.ip6addr, buf, sizeof (buf)));
     74 	} else {
     75 		IBTF_DPRINTF_L2(cmlog, "%s: IP ADDR NOT SPECIFIED ", label);
     76 	}
     77 }
     78 
     79 
     80 ibt_status_t
     81 ibcm_arp_get_ibaddr(ibt_ip_addr_t srcaddr, ibt_ip_addr_t destaddr,
     82     ib_gid_t *sgid, ib_gid_t *dgid)
     83 {
     84 	ibcm_arp_streams_t	*ib_s;
     85 	ibcm_arp_prwqn_t	*wqnp;
     86 	int			ret = 0;
     87 
     88 	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr(%p, %p, %p, %p)",
     89 	    srcaddr, destaddr, sgid, dgid);
     90 
     91 	ib_s = (ibcm_arp_streams_t *)kmem_zalloc(sizeof (ibcm_arp_streams_t),
     92 	    KM_SLEEP);
     93 
     94 	mutex_init(&ib_s->lock, NULL, MUTEX_DEFAULT, NULL);
     95 	cv_init(&ib_s->cv, NULL, CV_DRIVER, NULL);
     96 
     97 	mutex_enter(&ib_s->lock);
     98 	ib_s->done = B_FALSE;
     99 	mutex_exit(&ib_s->lock);
    100 
    101 	ret = ibcm_resolver_pr_lookup(ib_s, &destaddr, &srcaddr);
    102 
    103 	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: ibcm_resolver_pr_lookup "
    104 	    "returned: %d", ret);
    105 	if (ret == 0) {
    106 		mutex_enter(&ib_s->lock);
    107 		while (ib_s->done != B_TRUE)
    108 			cv_wait(&ib_s->cv, &ib_s->lock);
    109 		mutex_exit(&ib_s->lock);
    110 	}
    111 
    112 	mutex_enter(&ib_s->lock);
    113 	wqnp = ib_s->wqnp;
    114 	if (ib_s->status == 0) {
    115 		if (sgid)
    116 			*sgid = ib_s->wqnp->sgid;
    117 		if (dgid)
    118 			*dgid = ib_s->wqnp->dgid;
    119 
    120 		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr: SGID: %llX:%llX"
    121 		    " DGID: %llX:%llX",
    122 		    ib_s->wqnp->sgid.gid_prefix, ib_s->wqnp->sgid.gid_guid,
    123 		    ib_s->wqnp->dgid.gid_prefix, ib_s->wqnp->dgid.gid_guid);
    124 
    125 		ibcm_arp_delete_prwqn(wqnp);
    126 	} else if (ret == 0) {
    127 		/*
    128 		 * We come here only when lookup has returned empty (failed)
    129 		 * via callback routine.
    130 		 * i.e. ib_s->status is non-zero, while ret is zero.
    131 		 */
    132 		if (wqnp)
    133 			kmem_free(wqnp, sizeof (ibcm_arp_prwqn_t));
    134 	}
    135 	ret = ib_s->status;
    136 	mutex_exit(&ib_s->lock);
    137 
    138 arp_ibaddr_error:
    139 
    140 	mutex_destroy(&ib_s->lock);
    141 	cv_destroy(&ib_s->cv);
    142 	kmem_free(ib_s, sizeof (ibcm_arp_streams_t));
    143 
    144 	if (ret)
    145 		return (IBT_FAILURE);
    146 	else
    147 		return (IBT_SUCCESS);
    148 }
    149 
    150 
    151 /*
    152  * Routine to get list of "local" IP-ADDR to GID/P_KEY mapping information.
    153  * Optionally, if "gid" and/or "p_key" info are specified, then retrieve the
    154  * IP-ADDR info for that attribute only.
    155  */
    156 
    157 static ibcm_arp_ip_t *
    158 ibcm_arp_ibd_gid2mac(ib_gid_t *gid, ib_pkey_t pkey, ibcm_arp_ibd_insts_t *ibdp)
    159 {
    160 	ibcm_arp_ip_t		*ipp;
    161 	int			i;
    162 
    163 	for (i = 0, ipp = ibdp->ibcm_arp_ip; i < ibdp->ibcm_arp_ibd_cnt;
    164 	    i++, ipp++) {
    165 		if ((ipp->ip_port_gid.gid_prefix == gid->gid_prefix) &&
    166 		    (ipp->ip_port_gid.gid_guid == gid->gid_guid)) {
    167 			if (pkey) {
    168 				if (ipp->ip_pkey == pkey)
    169 					return (ipp);
    170 				else
    171 					continue;
    172 			}
    173 			return (ipp);
    174 		}
    175 	}
    176 	return (NULL);
    177 }
    178 
    179 static ibt_status_t
    180 ibcm_arp_ibd_mac2gid(ibcm_arp_ibd_insts_t *ibdp, ibt_ip_addr_t *srcip,
    181     ib_gid_t *sgid)
    182 {
    183 	ibcm_arp_ip_t		*ipp;
    184 	int			i;
    185 	boolean_t		found = B_FALSE;
    186 
    187 	for (i = 0, ipp = ibdp->ibcm_arp_ip; i < ibdp->ibcm_arp_ibd_cnt;
    188 	    i++, ipp++) {
    189 
    190 		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_ibd_mac2gid: GID %llX:%llX",
    191 		    ipp->ip_port_gid.gid_prefix, ipp->ip_port_gid.gid_guid);
    192 
    193 		if (srcip->family == ipp->ip_inet_family) {
    194 			if ((srcip->family == AF_INET) &&
    195 			    (bcmp(&srcip->un.ip4addr, &ipp->ip_cm_sin.sin_addr,
    196 			    sizeof (in_addr_t)) == 0)) {
    197 				found = B_TRUE;
    198 			} else if ((srcip->family == AF_INET6) &&
    199 			    IN6_ARE_ADDR_EQUAL(&srcip->un.ip6addr,
    200 			    &ipp->ip_cm_sin6.sin6_addr)) {
    201 				found = B_TRUE;
    202 			}
    203 			if (found) {
    204 				*sgid = ipp->ip_port_gid;
    205 
    206 				IBTF_DPRINTF_L4(cmlog, "ibcm_arp_ibd_mac2gid: "
    207 				    "Found GID %llX:%llX", sgid->gid_prefix,
    208 				    sgid->gid_guid);
    209 				return (IBT_SUCCESS);
    210 			}
    211 		} else {
    212 			IBTF_DPRINTF_L3(cmlog, "ibcm_arp_ibd_mac2gid: Different"
    213 			    " family keep searching...");
    214 		}
    215 	}
    216 	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_ibd_mac2gid: Matching SRC info "
    217 	    "NOT Found");
    218 	return (IBT_SRC_IP_NOT_FOUND);
    219 }
    220 
    221 static int
    222 ibcm_arp_get_ibd_insts_cb(dev_info_t *dip, void *arg)
    223 {
    224 	ibcm_arp_ibd_insts_t *ibds = (ibcm_arp_ibd_insts_t *)arg;
    225 	ibcm_arp_ip_t	*ipp;
    226 	ib_pkey_t	pkey;
    227 	uint8_t		port;
    228 	ib_guid_t	hca_guid;
    229 	ib_gid_t	port_gid;
    230 
    231 	if (i_ddi_devi_attached(dip) &&
    232 	    (strcmp(ddi_node_name(dip), "ibport") == 0) &&
    233 	    (strstr(ddi_get_name_addr(dip), "ipib") != NULL)) {
    234 
    235 		if (ibds->ibcm_arp_ibd_cnt >= ibds->ibcm_arp_ibd_alloc) {
    236 			ibcm_arp_ip_t	*tmp = NULL;
    237 			uint8_t		new_count;
    238 
    239 			new_count = ibds->ibcm_arp_ibd_alloc +
    240 			    IBCM_ARP_IBD_INSTANCES;
    241 
    242 			tmp = (ibcm_arp_ip_t *)kmem_zalloc(
    243 			    new_count * sizeof (ibcm_arp_ip_t), KM_SLEEP);
    244 			bcopy(ibds->ibcm_arp_ip, tmp,
    245 			    ibds->ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t));
    246 			kmem_free(ibds->ibcm_arp_ip,
    247 			    ibds->ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t));
    248 			ibds->ibcm_arp_ibd_alloc = new_count;
    249 			ibds->ibcm_arp_ip = tmp;
    250 		}
    251 
    252 		if (((hca_guid = ddi_prop_get_int64(DDI_DEV_T_ANY, dip, 0,
    253 		    "hca-guid", 0)) == 0) ||
    254 		    ((port = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
    255 		    "port-number", 0)) == 0) ||
    256 		    (ibt_get_port_state_byguid(hca_guid, port, &port_gid,
    257 		    NULL) != IBT_SUCCESS) ||
    258 		    ((pkey = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
    259 		    "port-pkey", IB_PKEY_INVALID_LIMITED)) <=
    260 		    IB_PKEY_INVALID_FULL)) {
    261 			return (DDI_WALK_CONTINUE);
    262 		}
    263 
    264 		ipp = &ibds->ibcm_arp_ip[ibds->ibcm_arp_ibd_cnt];
    265 		ipp->ip_inst = ddi_get_instance(dip);
    266 		ipp->ip_pkey = pkey;
    267 		ipp->ip_hca_guid = hca_guid;
    268 		ipp->ip_port_gid = port_gid;
    269 		ibds->ibcm_arp_ibd_cnt++;
    270 	}
    271 	return (DDI_WALK_CONTINUE);
    272 }
    273 
    274 static void
    275 ibcm_arp_get_ibd_insts(ibcm_arp_ibd_insts_t *ibds)
    276 {
    277 	ddi_walk_devs(ddi_root_node(), ibcm_arp_get_ibd_insts_cb, ibds);
    278 }
    279 
    280 /*
    281  * Issue an ioctl down to IP.  There are several similar versions of this
    282  * function (e.g., rpcib_do_ip_ioctl()); clearly a utility routine is needed.
    283  */
    284 static int
    285 ibcm_do_ip_ioctl(int cmd, int len, void *arg)
    286 {
    287 	vnode_t *kkvp;
    288 	TIUSER  *tiptr;
    289 	struct  strioctl iocb;
    290 	int	err = 0;
    291 
    292 	if (lookupname("/dev/udp", UIO_SYSSPACE, FOLLOW, NULLVPP, &kkvp) != 0)
    293 		return (EPROTO);
    294 
    295 	if (t_kopen(NULL, kkvp->v_rdev, FREAD|FWRITE, &tiptr, CRED()) != 0) {
    296 		VN_RELE(kkvp);
    297 		return (EPROTO);
    298 	}
    299 
    300 	iocb.ic_cmd = cmd;
    301 	iocb.ic_timout = 0;
    302 	iocb.ic_len = len;
    303 	iocb.ic_dp = (caddr_t)arg;
    304 	err = kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb);
    305 	(void) t_kclose(tiptr, 0);
    306 	VN_RELE(kkvp);
    307 	return (err);
    308 }
    309 
    310 /*
    311  * Issue an SIOCGLIFCONF down to IP and return the result in `lifcp'.
    312  * lifcp->lifc_buf is dynamically allocated to be *bufsizep bytes.
    313  */
    314 static int
    315 ibcm_do_lifconf(struct lifconf *lifcp, uint_t *bufsizep, sa_family_t family_loc)
    316 {
    317 	int err;
    318 	struct lifnum lifn;
    319 
    320 	bzero(&lifn, sizeof (struct lifnum));
    321 	lifn.lifn_family = family_loc;
    322 
    323 	err = ibcm_do_ip_ioctl(SIOCGLIFNUM, sizeof (struct lifnum), &lifn);
    324 	if (err != 0)
    325 		return (err);
    326 
    327 	IBTF_DPRINTF_L4(cmlog, "ibcm_do_lifconf: Family %d, lifn_count %d",
    328 	    family_loc, lifn.lifn_count);
    329 	/*
    330 	 * Pad the interface count to account for additional interfaces that
    331 	 * may have been configured between the SIOCGLIFNUM and SIOCGLIFCONF.
    332 	 */
    333 	lifn.lifn_count += 4;
    334 
    335 	bzero(lifcp, sizeof (struct lifconf));
    336 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lifcp))
    337 	lifcp->lifc_family = family_loc;
    338 	lifcp->lifc_len = *bufsizep = lifn.lifn_count * sizeof (struct lifreq);
    339 	lifcp->lifc_buf = kmem_zalloc(*bufsizep, KM_SLEEP);
    340 
    341 	err = ibcm_do_ip_ioctl(SIOCGLIFCONF, sizeof (struct lifconf), lifcp);
    342 	if (err != 0) {
    343 		kmem_free(lifcp->lifc_buf, *bufsizep);
    344 		return (err);
    345 	}
    346 	return (0);
    347 }
    348 
    349 /*
    350  * Fill in `ibds' with IP addresses tied to IFT_IB IP interfaces.  Returns
    351  * B_TRUE if at least one address was filled in.
    352  */
    353 static boolean_t
    354 ibcm_arp_get_ibd_ipaddr(ibcm_arp_ibd_insts_t *ibds, sa_family_t family_loc)
    355 {
    356 	int i, nifs, naddr = 0;
    357 	uint_t bufsize;
    358 	struct lifconf lifc;
    359 	struct lifreq *lifrp;
    360 	ibcm_arp_ip_t *ipp;
    361 
    362 	if (ibcm_do_lifconf(&lifc, &bufsize, family_loc) != 0)
    363 		return (B_FALSE);
    364 
    365 	nifs = lifc.lifc_len / sizeof (struct lifreq);
    366 
    367 	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibd_ipaddr: Family %d, nifs %d",
    368 	    family_loc, nifs);
    369 
    370 	for (lifrp = lifc.lifc_req, i = 0;
    371 	    i < nifs && naddr < ibds->ibcm_arp_ibd_cnt; i++, lifrp++) {
    372 		if (lifrp->lifr_type != IFT_IB)
    373 			continue;
    374 
    375 		ipp = &ibds->ibcm_arp_ip[naddr];
    376 		switch (lifrp->lifr_addr.ss_family) {
    377 		case AF_INET:
    378 			ipp->ip_inet_family = AF_INET;
    379 			bcopy(&lifrp->lifr_addr, &ipp->ip_cm_sin,
    380 			    sizeof (struct sockaddr_in));
    381 			naddr++;
    382 			break;
    383 		case AF_INET6:
    384 			ipp->ip_inet_family = AF_INET6;
    385 			bcopy(&lifrp->lifr_addr, &ipp->ip_cm_sin6,
    386 			    sizeof (struct sockaddr_in6));
    387 			naddr++;
    388 			break;
    389 		}
    390 	}
    391 
    392 	kmem_free(lifc.lifc_buf, bufsize);
    393 	return (naddr > 0);
    394 }
    395 
    396 ibt_status_t
    397 ibcm_arp_get_ibds(ibcm_arp_ibd_insts_t *ibdp, sa_family_t family_loc)
    398 {
    399 #ifdef DEBUG
    400 	int i;
    401 #endif
    402 
    403 	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds(%p)", ibdp);
    404 
    405 	ibcm_arp_get_ibd_insts(ibdp);
    406 
    407 	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibds: Found %d ibd instances",
    408 	    ibdp->ibcm_arp_ibd_cnt);
    409 
    410 	if (ibdp->ibcm_arp_ibd_cnt == 0)
    411 		return (IBT_SRC_IP_NOT_FOUND);
    412 
    413 	/* Get the IP addresses of active ports. */
    414 	if (!ibcm_arp_get_ibd_ipaddr(ibdp, family_loc)) {
    415 		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibds: failed to get "
    416 		    "ibd instance: IBT_SRC_IP_NOT_FOUND");
    417 		return (IBT_SRC_IP_NOT_FOUND);
    418 	}
    419 
    420 #ifdef DEBUG
    421 	for (i = 0; i < ibdp->ibcm_arp_ibd_cnt; i++) {
    422 		char    my_buf[INET6_ADDRSTRLEN];
    423 		ibcm_arp_ip_t	*aip = &ibdp->ibcm_arp_ip[i];
    424 
    425 		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds: ibd[%d]: Family %d "
    426 		    "Instance %d PKey 0x%lX \n HCAGUID 0x%llX SGID %llX:%llX",
    427 		    i, aip->ip_inet_family, aip->ip_inst, aip->ip_pkey,
    428 		    aip->ip_hca_guid, aip->ip_port_gid.gid_prefix,
    429 		    aip->ip_port_gid.gid_guid);
    430 		if (aip->ip_inet_family == AF_INET) {
    431 			IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds: IPV4: %s",
    432 			    inet_ntop(AF_INET, &aip->ip_cm_sin.sin_addr, my_buf,
    433 			    sizeof (my_buf)));
    434 		} else if (aip->ip_inet_family == AF_INET6) {
    435 			IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds: IPV6: %s",
    436 			    inet_ntop(AF_INET6, &aip->ip_cm_sin6.sin6_addr,
    437 			    my_buf, sizeof (my_buf)));
    438 		} else {
    439 			IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibds: Unknown "
    440 			    "Family %d", aip->ip_inet_family);
    441 		}
    442 	}
    443 #endif
    444 
    445 	return (IBT_SUCCESS);
    446 }
    447 
    448 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibtl_cm_port_list_t))
    449 
    450 ibt_status_t
    451 ibcm_arp_get_srcip_plist(ibt_ip_path_attr_t *ipattr, ibt_path_flags_t flags,
    452     ibtl_cm_port_list_t **port_list_p)
    453 {
    454 	ibt_path_attr_t		attr;
    455 	ibt_status_t		ret;
    456 	ibcm_arp_ibd_insts_t	ibds;
    457 	ibcm_arp_ip_t		*ipp;
    458 	ibtl_cm_port_list_t	*plistp;
    459 	ib_gid_t		sgid;
    460 	sa_family_t		family_interested = AF_UNSPEC;
    461 
    462 	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist(%p, %llX)",
    463 	    ipattr, flags);
    464 
    465 	if (ipattr->ipa_src_ip.family != AF_UNSPEC)
    466 		family_interested = ipattr->ipa_src_ip.family;
    467 	else
    468 		family_interested = ipattr->ipa_dst_ip[0].family;
    469 
    470 	sgid.gid_prefix = sgid.gid_guid = 0;
    471 	bzero(&ibds, sizeof (ibcm_arp_ibd_insts_t));
    472 	ibds.ibcm_arp_ibd_alloc = IBCM_ARP_IBD_INSTANCES;
    473 	ibds.ibcm_arp_ibd_cnt = 0;
    474 	ibds.ibcm_arp_ip = (ibcm_arp_ip_t *)kmem_zalloc(
    475 	    ibds.ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t), KM_SLEEP);
    476 
    477 	ret = ibcm_arp_get_ibds(&ibds, family_interested);
    478 	if (ret != IBT_SUCCESS) {
    479 		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_srcip_plist: "
    480 		    "ibcm_arp_get_ibds failed : 0x%x", ret);
    481 		goto srcip_plist_end;
    482 	}
    483 
    484 	if (ipattr->ipa_src_ip.family != AF_UNSPEC) {
    485 		ret = ibcm_arp_ibd_mac2gid(&ibds, &ipattr->ipa_src_ip, &sgid);
    486 		if (ret != IBT_SUCCESS) {
    487 			IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_srcip_plist: "
    488 			    "SGID for the specified SRCIP Not found %X", ret);
    489 			goto srcip_plist_end;
    490 		}
    491 		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist: SGID "
    492 		    "%llX:%llX", sgid.gid_prefix, sgid.gid_guid);
    493 	}
    494 
    495 	bzero(&attr, sizeof (ibt_path_attr_t));
    496 	attr.pa_hca_guid = ipattr->ipa_hca_guid;
    497 	attr.pa_hca_port_num = ipattr->ipa_hca_port_num;
    498 	attr.pa_sgid = sgid;
    499 	bcopy(&ipattr->ipa_mtu,  &attr.pa_mtu, sizeof (ibt_mtu_req_t));
    500 	bcopy(&ipattr->ipa_srate,  &attr.pa_srate, sizeof (ibt_srate_req_t));
    501 	bcopy(&ipattr->ipa_pkt_lt,  &attr.pa_pkt_lt, sizeof (ibt_pkt_lt_req_t));
    502 
    503 	ret = ibtl_cm_get_active_plist(&attr, flags, port_list_p);
    504 	if (ret == IBT_SUCCESS) {
    505 		int		i;
    506 		uint8_t		cnt;
    507 		boolean_t	no_srcip_configured = B_FALSE;
    508 		uint8_t		no_srcip_cnt = 0;
    509 
    510 		plistp = port_list_p[0];
    511 		cnt = plistp->p_count;
    512 		for (i = 0; i < cnt; i++, plistp++) {
    513 			ipp = ibcm_arp_ibd_gid2mac(&plistp->p_sgid, 0, &ibds);
    514 			if ((ipp == NULL) ||
    515 			    (ipp->ip_inet_family == AF_UNSPEC)) {
    516 				plistp->p_src_ip.family = AF_UNSPEC;
    517 				no_srcip_configured = B_TRUE;
    518 				no_srcip_cnt++;
    519 				IBTF_DPRINTF_L3(cmlog,
    520 				    "ibcm_arp_get_srcip_plist: SrcIP NOT "
    521 				    "Configured for GID %llX:%llX",
    522 				    plistp->p_sgid.gid_prefix,
    523 				    plistp->p_sgid.gid_guid);
    524 			} else {
    525 				IBTF_DPRINTF_L4(cmlog,
    526 				    "ibcm_arp_get_srcip_plist: GID %llX:%llX",
    527 				    plistp->p_sgid.gid_prefix,
    528 				    plistp->p_sgid.gid_guid);
    529 				if (ipp->ip_inet_family == AF_INET) {
    530 					plistp->p_src_ip.family = AF_INET;
    531 					bcopy(&ipp->ip_cm_sin.sin_addr,
    532 					    &plistp->p_src_ip.un.ip4addr,
    533 					    sizeof (in_addr_t));
    534 
    535 				} else if (ipp->ip_inet_family == AF_INET6) {
    536 					plistp->p_src_ip.family = AF_INET6;
    537 					bcopy(&ipp->ip_cm_sin6.sin6_addr,
    538 					    &plistp->p_src_ip.un.ip6addr,
    539 					    sizeof (in6_addr_t));
    540 				}
    541 				IBCM_PRINT_IP("ibcm_arp_get_srcip_plist: "
    542 				    "IP Addr is:", &plistp->p_src_ip);
    543 			}
    544 		}
    545 		if (no_srcip_configured) {
    546 			ibtl_cm_port_list_t	*n_plistp, *tmp_n_plistp;
    547 			uint8_t			new_cnt;
    548 
    549 			new_cnt = cnt - no_srcip_cnt;
    550 
    551 			/*
    552 			 * Looks like some of the SRC GID we found have no
    553 			 * IP ADDR configured, so remove these entries from
    554 			 * our list.
    555 			 */
    556 			plistp = port_list_p[0];
    557 			IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist: "
    558 			    "Only %d SGID (%d/%d) have SrcIP Configured",
    559 			    new_cnt, no_srcip_cnt, cnt);
    560 			if (new_cnt) {
    561 				/* Allocate Memory to hold Src Point info. */
    562 				n_plistp = kmem_zalloc(new_cnt *
    563 				    sizeof (ibtl_cm_port_list_t), KM_SLEEP);
    564 
    565 				tmp_n_plistp = n_plistp;
    566 				for (i = 0; i < cnt; i++, plistp++) {
    567 					if (plistp->p_src_ip.family ==
    568 					    AF_UNSPEC)
    569 						continue;
    570 
    571 					bcopy(plistp, n_plistp,
    572 					    sizeof (ibtl_cm_port_list_t));
    573 					n_plistp->p_count = new_cnt;
    574 					n_plistp++;
    575 				}
    576 				plistp = port_list_p[0];
    577 				*port_list_p = tmp_n_plistp;
    578 			} else {
    579 				/*
    580 				 * All entries we have, do not have IP-Addr
    581 				 * configured so return empty hand.
    582 				 */
    583 				IBTF_DPRINTF_L2(cmlog,
    584 				    "ibcm_arp_get_srcip_plist: None of SGID "
    585 				    "found have SrcIP Configured");
    586 				*port_list_p = NULL;
    587 				ret = IBT_SRC_IP_NOT_FOUND;
    588 			}
    589 			IBTF_DPRINTF_L4(cmlog, "FREE OLD list %p, NEW list is "
    590 			    "%p - %p", plistp, port_list_p, *port_list_p);
    591 			kmem_free(plistp, cnt * sizeof (ibtl_cm_port_list_t));
    592 		}
    593 	}
    594 
    595 srcip_plist_end:
    596 	if (ibds.ibcm_arp_ip)
    597 		kmem_free(ibds.ibcm_arp_ip, ibds.ibcm_arp_ibd_alloc *
    598 		    sizeof (ibcm_arp_ip_t));
    599 
    600 	return (ret);
    601 }
    602