ibcm_arp.c revision 4703:bb31c50bb3ab
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 2007 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include <sys/types.h>
29#include <sys/ddi.h>
30#include <sys/sunddi.h>
31#include <sys/stropts.h>
32#include <sys/stream.h>
33#include <sys/strsun.h>
34#include <sys/strsubr.h>
35#include <sys/socket.h>
36#include <sys/stat.h>
37#include <net/if_arp.h>
38#include <sys/file.h>
39#include <sys/sockio.h>
40#include <sys/pathname.h>
41#include <inet/arp.h>
42#include <sys/modctl.h>
43
44#include <sys/ib/mgt/ibcm/ibcm_arp.h>
45
46#include <sys/kstr.h>
47#include <sys/tiuser.h>
48#include <sys/t_kuser.h>
49
50extern char cmlog[];
51
52extern int ibcm_arp_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr,
53    ibt_ip_addr_t *src_addr, uint8_t localroute, uint32_t bound_dev_if,
54    ibcm_arp_pr_comp_func_t func);
55extern void ibcm_arp_pr_arp_ack(mblk_t *mp);
56extern void ibcm_arp_prwqn_delete(ibcm_arp_prwqn_t *wqnp);
57
58_NOTE(SCHEME_PROTECTS_DATA("Unshared data", datab))
59_NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibt_ip_addr_s))
60_NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_ip_t))
61_NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_ibd_insts_t))
62_NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_prwqn_t))
63_NOTE(SCHEME_PROTECTS_DATA("Unshared data", iocblk))
64_NOTE(SCHEME_PROTECTS_DATA("Unshared data", msgb))
65_NOTE(SCHEME_PROTECTS_DATA("Unshared data", queue))
66_NOTE(SCHEME_PROTECTS_DATA("Unshared data", sockaddr_in))
67_NOTE(SCHEME_PROTECTS_DATA("Unshared data", sockaddr_in6))
68
69/*
70 * ibcm_arp_get_ibaddr_cb
71 */
72static int
73ibcm_arp_get_ibaddr_cb(void *arg, int status)
74{
75	ibcm_arp_prwqn_t	*wqnp = (ibcm_arp_prwqn_t *)arg;
76	ibcm_arp_streams_t	*ib_s = (ibcm_arp_streams_t *)wqnp->arg;
77
78	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr_cb(ib_s: %p wqnp: %p)",
79	    ib_s, wqnp);
80
81	mutex_enter(&ib_s->lock);
82	ib_s->status = status;
83
84	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr_cb: SGID %llX:%llX "
85	    "DGID: %llX:%llX", wqnp->sgid.gid_prefix, wqnp->sgid.gid_guid,
86	    wqnp->dgid.gid_prefix, wqnp->dgid.gid_guid);
87
88	/* lock is held by the caller. */
89	cv_signal(&ib_s->cv);
90	mutex_exit(&ib_s->lock);
91	return (0);
92}
93
94/*
95 * Lower read service procedure (messages coming back from arp/ip).
96 * Process messages based on queue type.
97 */
98static int
99ibcm_arp_lrsrv(queue_t *q)
100{
101	mblk_t *mp;
102	ibcm_arp_streams_t *ib_s = q->q_ptr;
103
104	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_lrsrv(%p, ibd_s: 0x%p)", q, ib_s);
105
106	if (WR(q) == ib_s->arpqueue) {
107		while (mp = getq(q)) {
108			ibcm_arp_pr_arp_ack(mp);
109		}
110	} else {
111		freemsg(mp);
112	}
113
114	return (0);
115}
116
117/*
118 * Lower write service procedure.
119 * Used when lower streams are flow controlled.
120 */
121static int
122ibcm_arp_lwsrv(queue_t *q)
123{
124	mblk_t *mp;
125
126	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_lwsrv(%p)", q);
127
128	while (mp = getq(q)) {
129		if (canputnext(q)) {
130			putnext(q, mp);
131		} else {
132			(void) putbq(q, mp);
133			qenable(q);
134			break;
135		}
136	}
137
138	return (0);
139}
140
141/*
142 * Lower read put procedure. Arp/ip messages come here.
143 */
144static int
145ibcm_arp_lrput(queue_t *q, mblk_t *mp)
146{
147	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_lrput(0x%p, db_type: %d)",
148	    q, DB_TYPE(mp));
149
150	switch (DB_TYPE(mp)) {
151		case M_FLUSH:
152			/*
153			 * Turn around
154			 */
155			if (*mp->b_rptr & FLUSHW) {
156				*mp->b_rptr &= ~FLUSHR;
157				qreply(q, mp);
158				return (0);
159			}
160			freemsg(mp);
161			break;
162		case M_IOCACK:
163		case M_IOCNAK:
164		case M_DATA:
165			/*
166			 * This could be in interrupt context.
167			 * Some of the ibt calls cannot be called in
168			 * interrupt context, so
169			 * put it in the queue and the message will be
170			 * processed by service proccedure
171			 */
172			(void) putq(q, mp);
173			qenable(q);
174			break;
175		default:
176			IBTF_DPRINTF_L2(cmlog, "ibcm_arp_lrput: "
177			    "got unknown msg <0x%x>\n", mp->b_datap->db_type);
178			ASSERT(0);
179			break;
180	}
181
182	return (0);
183}
184
185/*
186 * Streams write queue module info
187 */
188static struct module_info ibcm_arp_winfo = {
189	0,		/* module ID number */
190	"ibcm",		/* module name */
191	0,		/* min packet size */
192	INFPSZ,
193	49152,		/* STREAM queue high water mark -- 49152 */
194	12		/* STREAM queue low water mark -- 12 */
195};
196
197/*
198 * Streams lower write queue, for ibcm/ip requests.
199 */
200static struct qinit ibcm_arp_lwinit = {
201	NULL,		/* qi_putp */
202	ibcm_arp_lwsrv,	/* qi_srvp */
203	NULL,		/* qi_qopen */
204	NULL,		/* qi_qclose */
205	NULL,		/* qi_qadmin */
206	&ibcm_arp_winfo,	/* module info */
207	NULL,		/* module statistics struct */
208	NULL,
209	NULL,
210	STRUIOT_NONE	/* stream uio type is standard uiomove() */
211};
212
213/*
214 * Streams lower read queue: read reply messages from ibcm/ip.
215 */
216static struct qinit ibcm_arp_lrinit = {
217	ibcm_arp_lrput,	/* qi_putp */
218	ibcm_arp_lrsrv,	/* qi_srvp */
219	NULL,		/* qi_qopen */
220	NULL,		/* qi_qclose */
221	NULL,		/* qi_qadmin */
222	&ibcm_arp_winfo,	/* module info */
223	NULL,		/* module statistics struct */
224	NULL,
225	NULL,
226	STRUIOT_NONE /* stream uio type is standard uiomove() */
227};
228
229
230static int
231ibcm_arp_link_driver(ibcm_arp_streams_t *ib_s, char *path, queue_t **q,
232    vnode_t **dev_vp)
233{
234	struct stdata *dev_stp;
235	vnode_t *vp;
236	int error;
237	queue_t *rq;
238
239	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_link_driver: Enter: %s", path);
240
241	/* open the driver from inside the kernel */
242	error = vn_open(path, UIO_SYSSPACE, FREAD|FWRITE, 0, &vp,
243	    0, NULL);
244	if (error) {
245		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_link_driver: "
246		    "vn_open('%s') failed\n", path);
247		return (error);
248	}
249	*dev_vp = vp;
250
251	dev_stp = vp->v_stream;
252	*q = dev_stp->sd_wrq;
253
254	VN_HOLD(vp);
255
256	rq = RD(dev_stp->sd_wrq);
257	RD(rq)->q_ptr = WR(rq)->q_ptr = ib_s;
258	setq(rq, &ibcm_arp_lrinit, &ibcm_arp_lwinit, NULL, QMTSAFE,
259	    SQ_CI|SQ_CO, B_FALSE);
260
261	return (0);
262}
263
264extern struct qinit strdata;
265extern struct qinit stwdata;
266
267/*
268 * Unlink ip, ibcm, icmp6 drivers
269 */
270/* ARGSUSED */
271static int
272ibcm_arp_unlink_driver(queue_t **q, vnode_t **dev_vp)
273{
274	vnode_t *vp = *dev_vp;
275	struct stdata *dev_stp = vp->v_stream;
276	queue_t *wrq, *rq;
277	int	rc;
278
279	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_unlink_driver: Enter: 0x%p", q);
280
281	wrq = dev_stp->sd_wrq;
282	rq = RD(wrq);
283
284	disable_svc(rq);
285	wait_svc(rq);
286	flushq(rq, FLUSHALL);
287	flushq(WR(rq), FLUSHALL);
288
289	rq->q_ptr = wrq->q_ptr = dev_stp;
290
291	setq(rq, &strdata, &stwdata, NULL, QMTSAFE, SQ_CI|SQ_CO, B_TRUE);
292
293	if ((rc = VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED())) != 0) {
294		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_unlink_driver: VOP_CLOSE "
295		    "failed %d\n", rc);
296	}
297	vn_rele(vp);
298
299	return (0);
300}
301
302static int
303ibcm_arp_unlink_drivers(ibcm_arp_streams_t *ib_s)
304{
305	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_unlink_drivers(%p)", ib_s);
306
307	if (ib_s->arpqueue) {
308		(void) ibcm_arp_unlink_driver(&ib_s->arpqueue, &ib_s->arp_vp);
309	}
310
311	return (0);
312}
313
314/*
315 * Link ip, ibtl drivers below ibtl
316 */
317static int
318ibcm_arp_link_drivers(ibcm_arp_streams_t *ib_s)
319{
320	int	rc;
321
322	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_link_drivers(%p)", ib_s);
323
324	if ((rc = ibcm_arp_link_driver(ib_s, "/dev/arp", &ib_s->arpqueue,
325	    &ib_s->arp_vp)) != 0) {
326		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_link_drivers: "
327		    "ibcm_arp_link_driver failed: %d\n", rc);
328		return (rc);
329	}
330
331	return (0);
332}
333
334ibt_status_t
335ibcm_arp_get_ibaddr(ipaddr_t srcip, ipaddr_t destip, ib_gid_t *sgid,
336    ib_gid_t *dgid)
337{
338	ibcm_arp_streams_t	*ib_s;
339	ibt_ip_addr_t		srcaddr, destaddr;
340	int			ret;
341
342	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr(%lX, %lX, %p, %p)",
343	    htonl(srcip), htonl(destip), sgid, dgid);
344
345	ib_s = (ibcm_arp_streams_t *)kmem_zalloc(sizeof (ibcm_arp_streams_t),
346	    KM_SLEEP);
347
348	mutex_init(&ib_s->lock, NULL, MUTEX_DEFAULT, NULL);
349	cv_init(&ib_s->cv, NULL, CV_DRIVER, NULL);
350
351	ret = ibcm_arp_link_drivers(ib_s);
352	if (ret != 0) {
353		IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: "
354		    "ibcm_arp_link_drivers failed %d", ret);
355		return (IBT_FAILURE);
356	}
357
358	bzero(&destaddr, sizeof (ibt_ip_addr_t));
359	bzero(&srcaddr, sizeof (ibt_ip_addr_t));
360
361	destaddr.family = AF_INET_OFFLOAD;
362	destaddr.un.ip4addr = htonl(destip);
363	srcaddr.family = AF_INET_OFFLOAD;
364	srcaddr.un.ip4addr = htonl(srcip);
365
366	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: SrcIP %lX, DstIP %lX",
367	    srcaddr.un.ip4addr, destaddr.un.ip4addr);
368	ret = ibcm_arp_pr_lookup(ib_s, &destaddr, &srcaddr, 0, NULL,
369	    ibcm_arp_get_ibaddr_cb);
370
371	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: ibcm_arp_pr_lookup "
372	    "returned: %d", ret);
373	if (ret == 0) {
374		mutex_enter(&ib_s->lock);
375		cv_wait(&ib_s->cv, &ib_s->lock);
376		mutex_exit(&ib_s->lock);
377	}
378
379	(void) ibcm_arp_unlink_drivers(ib_s);
380	ret = ib_s->status;
381	if (ret == 0) {
382		if (sgid)
383			*sgid = ib_s->wqnp->sgid;
384		if (dgid)
385			*dgid = ib_s->wqnp->dgid;
386
387		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr: SGID: %llX:%llX"
388		    " DGID: %llX:%llX",
389		    ib_s->wqnp->sgid.gid_prefix, ib_s->wqnp->sgid.gid_guid,
390		    ib_s->wqnp->dgid.gid_prefix, ib_s->wqnp->dgid.gid_guid);
391
392		ibcm_arp_prwqn_delete(ib_s->wqnp);
393	}
394
395	mutex_destroy(&ib_s->lock);
396	cv_destroy(&ib_s->cv);
397	kmem_free(ib_s, sizeof (ibcm_arp_streams_t));
398
399	if (ret)
400		return (IBT_FAILURE);
401	else
402		return (IBT_SUCCESS);
403}
404
405
406/*
407 * Routine to get list of "local" IP-ADDR to GID/P_KEY mapping information.
408 * Optionally, if "gid" and/or "p_key" info are specified, then retrieve the
409 * IP-ADDR info for that attribute only.
410 */
411
412static ibcm_arp_ip_t *
413ibcm_arp_ibd_gid2mac(ib_gid_t *gid, ib_pkey_t pkey, ibcm_arp_ibd_insts_t *ibdp)
414{
415	ibcm_arp_ip_t		*ipp;
416	int			i;
417
418	for (i = 0, ipp = ibdp->ibcm_arp_ip; i < ibdp->ibcm_arp_ibd_cnt;
419	    i++, ipp++) {
420		if ((ipp->ip_port_gid.gid_prefix == gid->gid_prefix) &&
421		    (ipp->ip_port_gid.gid_guid == gid->gid_guid)) {
422			if (pkey) {
423				if (ipp->ip_pkey == pkey)
424					return (ipp);
425				else
426					continue;
427			}
428			return (ipp);
429		}
430	}
431	return (NULL);
432}
433
434static ibt_status_t
435ibcm_arp_ibd_mac2gid(ibcm_arp_ibd_insts_t *ibdp, ipaddr_t srcip,
436    ib_gid_t *sgid)
437{
438	ibcm_arp_ip_t		*ipp;
439	int			i;
440
441	for (i = 0, ipp = ibdp->ibcm_arp_ip; i < ibdp->ibcm_arp_ibd_cnt;
442	    i++, ipp++) {
443
444		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_ibd_mac2gid: Is %lX == %lX "
445		    "GID %llX:%llX", srcip, ipp->ip_cm_sin.sin_addr,
446		    ipp->ip_port_gid.gid_prefix, ipp->ip_port_gid.gid_guid);
447
448		if (bcmp(&srcip, &ipp->ip_cm_sin.sin_addr, sizeof (in_addr_t))
449		    == 0) {
450			*sgid = ipp->ip_port_gid;
451
452			IBTF_DPRINTF_L4(cmlog, "ibcm_arp_ibd_mac2gid: Found "
453			    "GID %llX:%llX", sgid->gid_prefix, sgid->gid_guid);
454			return (IBT_SUCCESS);
455		}
456	}
457	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_ibd_mac2gid: Matching SRC info "
458	    "NOT Found");
459	return (IBT_SRC_IP_NOT_FOUND);
460}
461
462static int
463ibcm_arp_get_ibd_insts_cb(dev_info_t *dip, void *arg)
464{
465	ibcm_arp_ibd_insts_t *ibds = (ibcm_arp_ibd_insts_t *)arg;
466	ibcm_arp_ip_t	*ipp;
467	ib_pkey_t	pkey;
468	uint8_t		port;
469	ib_guid_t	hca_guid;
470	ib_gid_t	port_gid;
471
472	if (i_ddi_devi_attached(dip) &&
473	    (strcmp(ddi_node_name(dip), "ibport") == 0) &&
474	    (strstr(ddi_get_name_addr(dip), "ipib") != NULL)) {
475
476		if (ibds->ibcm_arp_ibd_cnt >= ibds->ibcm_arp_ibd_alloc) {
477			ibcm_arp_ip_t	*tmp = NULL;
478			int		new_count = 0;
479
480			new_count = ibds->ibcm_arp_ibd_alloc +
481			    IBCM_ARP_IBD_INSTANCES;
482
483			tmp = (ibcm_arp_ip_t *)kmem_zalloc(
484			    new_count * sizeof (ibcm_arp_ip_t), KM_SLEEP);
485			bcopy(ibds->ibcm_arp_ip, tmp,
486			    ibds->ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t));
487			kmem_free(ibds->ibcm_arp_ip,
488			    ibds->ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t));
489			ibds->ibcm_arp_ibd_alloc = new_count;
490			ibds->ibcm_arp_ip = tmp;
491		}
492
493		if (((hca_guid = ddi_prop_get_int64(DDI_DEV_T_ANY, dip, 0,
494		    "hca-guid", 0)) == 0) ||
495		    ((port = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
496		    "port-number", 0)) == 0) ||
497		    (ibt_get_port_state_byguid(hca_guid, port, &port_gid,
498		    NULL) != IBT_SUCCESS) ||
499		    ((pkey = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
500		    "port-pkey", IB_PKEY_INVALID_LIMITED)) <=
501		    IB_PKEY_INVALID_FULL)) {
502			return (DDI_WALK_CONTINUE);
503		}
504
505		ipp = &ibds->ibcm_arp_ip[ibds->ibcm_arp_ibd_cnt];
506		ipp->ip_inst = ddi_get_instance(dip);
507		ipp->ip_pkey = pkey;
508		ipp->ip_hca_guid = hca_guid;
509		ipp->ip_port_gid = port_gid;
510		ibds->ibcm_arp_ibd_cnt++;
511	}
512	return (DDI_WALK_CONTINUE);
513}
514
515static void
516ibcm_arp_get_ibd_insts(ibcm_arp_ibd_insts_t *ibds)
517{
518	ddi_walk_devs(ddi_root_node(), ibcm_arp_get_ibd_insts_cb, ibds);
519}
520
521/*
522 * Return ibd interfaces and ibd instances.
523 */
524static int
525ibcm_arp_get_ibd_ipaddr(ibcm_arp_ibd_insts_t *ibds)
526{
527	TIUSER			*tiptr;
528	vnode_t			*kvp;
529	vnode_t			*vp = NULL;
530	struct strioctl		iocb;
531	struct lifreq		lif_req;
532	int			k, ip_cnt;
533	ibcm_arp_ip_t		*ipp;
534
535	if (lookupname("/dev/udp", UIO_SYSSPACE, FOLLOW, NULLVPP, &kvp) == 0) {
536		if (t_kopen((file_t *)NULL, kvp->v_rdev, FREAD|FWRITE,
537		    &tiptr, CRED()) == 0) {
538			vp = tiptr->fp->f_vnode;
539		} else {
540			VN_RELE(kvp);
541		}
542	}
543
544	if (vp == NULL)
545		return (-1);
546
547	/* Get ibd ip's */
548	ip_cnt = 0;
549	for (k = 0, ipp = ibds->ibcm_arp_ip; k < ibds->ibcm_arp_ibd_cnt;
550	    k++, ipp++) {
551
552		(void) bzero((void *)&lif_req, sizeof (struct lifreq));
553		(void) snprintf(lif_req.lifr_name, sizeof (lif_req.lifr_name),
554		    "%s%d", IBCM_ARP_IBD_NAME, ipp->ip_inst);
555
556		(void) bzero((void *)&iocb, sizeof (struct strioctl));
557		iocb.ic_cmd = SIOCGLIFADDR;
558		iocb.ic_timout = 0;
559		iocb.ic_len = sizeof (struct lifreq);
560		iocb.ic_dp = (caddr_t)&lif_req;
561
562		if (kstr_ioctl(vp, I_STR, (intptr_t)&iocb) == 0) {
563			ipp->ip_inet_family = AF_INET;
564			bcopy(&lif_req.lifr_addr, &ipp->ip_cm_sin,
565			    sizeof (struct sockaddr_in));
566			ip_cnt++;
567			continue;
568		}
569	}
570
571	(void) t_kclose(tiptr, 0);
572	VN_RELE(kvp);
573
574	if (ip_cnt == 0)
575		return (-1);
576	else
577		return (0);
578}
579
580ibt_status_t
581ibcm_arp_get_ibds(ibcm_arp_ibd_insts_t *ibdp)
582{
583	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds(%p)", ibdp);
584
585	ibcm_arp_get_ibd_insts(ibdp);
586
587	IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibds: Found %d ibd instances",
588	    ibdp->ibcm_arp_ibd_cnt);
589
590	if (ibdp->ibcm_arp_ibd_cnt == 0)
591		return (IBT_SRC_IP_NOT_FOUND);
592
593	/* Get the IP addresses of active ports. */
594	if (ibcm_arp_get_ibd_ipaddr(ibdp) != 0) {
595		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibds: failed to get "
596		    "ibd instance: IBT_SRC_IP_NOT_FOUND");
597		return (IBT_SRC_IP_NOT_FOUND);
598	}
599
600	return (IBT_SUCCESS);
601}
602
603_NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibtl_cm_port_list_t))
604
605ibt_status_t
606ibcm_arp_get_srcip_plist(ibt_ip_path_attr_t *ipattr, ibt_path_flags_t flags,
607    ibtl_cm_port_list_t **port_list_p)
608{
609	ibt_path_attr_t		attr;
610	ibt_status_t		ret;
611	ibcm_arp_ibd_insts_t	ibds;
612	ibcm_arp_ip_t		*ipp;
613	ibtl_cm_port_list_t	*plistp;
614	ib_gid_t		sgid;
615
616	IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist(%p, %llX)",
617	    ipattr, flags);
618
619	sgid.gid_prefix = sgid.gid_guid = 0;
620	bzero(&ibds, sizeof (ibcm_arp_ibd_insts_t));
621	ibds.ibcm_arp_ibd_alloc = IBCM_ARP_IBD_INSTANCES;
622	ibds.ibcm_arp_ibd_cnt = 0;
623	ibds.ibcm_arp_ip = (ibcm_arp_ip_t *)kmem_zalloc(
624	    ibds.ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t), KM_SLEEP);
625
626	ret = ibcm_arp_get_ibds(&ibds);
627	if (ret != IBT_SUCCESS) {
628		IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_srcip_plist: "
629		    "ibcm_arp_get_ibds failed : 0x%x", ret);
630		goto srcip_plist_end;
631	}
632
633	if (ipattr->ipa_src_ip.family != AF_UNSPEC) {
634		ret = ibcm_arp_ibd_mac2gid(&ibds,
635		    htonl(ipattr->ipa_src_ip.un.ip4addr), &sgid);
636		if (ret != IBT_SUCCESS) {
637			IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_srcip_plist: "
638			    "SGID for the specified SRCIP Not found %X", ret);
639			goto srcip_plist_end;
640		}
641		IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist: SGID "
642		    "%llX:%llX", sgid.gid_prefix, sgid.gid_guid);
643	}
644
645	bzero(&attr, sizeof (ibt_path_attr_t));
646	attr.pa_hca_guid = ipattr->ipa_hca_guid;
647	attr.pa_hca_port_num = ipattr->ipa_hca_port_num;
648	attr.pa_sgid = sgid;
649	bcopy(&ipattr->ipa_mtu,  &attr.pa_mtu, sizeof (ibt_mtu_req_t));
650	bcopy(&ipattr->ipa_srate,  &attr.pa_srate, sizeof (ibt_srate_req_t));
651	bcopy(&ipattr->ipa_pkt_lt,  &attr.pa_pkt_lt, sizeof (ibt_pkt_lt_req_t));
652
653	ret = ibtl_cm_get_active_plist(&attr, flags, port_list_p);
654	if (ret == IBT_SUCCESS) {
655		int		i;
656
657		plistp = port_list_p[0];
658		for (i = 0; i < plistp->p_count; i++, plistp++) {
659			ipp = ibcm_arp_ibd_gid2mac(&plistp->p_sgid, 0, &ibds);
660			if (ipp == NULL)
661				plistp->p_src_ip.family = AF_UNSPEC;
662			else {
663				IBTF_DPRINTF_L4(cmlog,
664				    "ibcm_arp_get_srcip_plist: GID %llX:%llX",
665				    plistp->p_sgid.gid_prefix,
666				    plistp->p_sgid.gid_guid);
667				if (ipp->ip_inet_family == AF_INET) {
668					plistp->p_src_ip.family = AF_INET;
669					bcopy(&ipp->ip_cm_sin.sin_addr,
670					    &plistp->p_src_ip.un.ip4addr,
671					    sizeof (in_addr_t));
672
673					IBTF_DPRINTF_L4(cmlog,
674					    "ibcm_arp_get_srcip_plist: SrcIP: "
675					    "%lX", plistp->p_src_ip.un.ip4addr);
676				} else if (ipp->ip_inet_family == AF_INET6) {
677					plistp->p_src_ip.family = AF_INET6;
678					bcopy(&ipp->ip_cm_sin6.sin6_addr,
679					    &plistp->p_src_ip.un.ip6addr,
680					    sizeof (in6_addr_t));
681				}
682			}
683		}
684	}
685
686srcip_plist_end:
687	if (ibds.ibcm_arp_ip)
688		kmem_free(ibds.ibcm_arp_ip, ibds.ibcm_arp_ibd_alloc *
689		    sizeof (ibcm_arp_ip_t));
690
691	return (ret);
692}
693/* Routines for warlock */
694
695/* ARGSUSED */
696static int
697ibcm_arp_dummy_ibaddr_hdl(void *arg, int status)
698{
699	ibcm_arp_prwqn_t		dummy_wqn1;
700	ibcm_arp_prwqn_t		dummy_wqn2;
701
702	dummy_wqn1.func = ibcm_arp_get_ibaddr_cb;
703	dummy_wqn2.func = ibcm_arp_dummy_ibaddr_hdl;
704
705	IBTF_DPRINTF_L5(cmlog, "ibcm_arp_dummy_ibaddr_hdl: "
706	    "dummy_wqn1.func %p %p", dummy_wqn1.func, dummy_wqn2.func);
707
708	return (0);
709}
710