1*c0dd49bdSEiji Ota /*
2*c0dd49bdSEiji Ota  * CDDL HEADER START
3*c0dd49bdSEiji Ota  *
4*c0dd49bdSEiji Ota  * The contents of this file are subject to the terms of the
5*c0dd49bdSEiji Ota  * Common Development and Distribution License (the "License").
6*c0dd49bdSEiji Ota  * You may not use this file except in compliance with the License.
7*c0dd49bdSEiji Ota  *
8*c0dd49bdSEiji Ota  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*c0dd49bdSEiji Ota  * or http://www.opensolaris.org/os/licensing.
10*c0dd49bdSEiji Ota  * See the License for the specific language governing permissions
11*c0dd49bdSEiji Ota  * and limitations under the License.
12*c0dd49bdSEiji Ota  *
13*c0dd49bdSEiji Ota  * When distributing Covered Code, include this CDDL HEADER in each
14*c0dd49bdSEiji Ota  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*c0dd49bdSEiji Ota  * If applicable, add the following below this CDDL HEADER, with the
16*c0dd49bdSEiji Ota  * fields enclosed by brackets "[]" replaced with your own identifying
17*c0dd49bdSEiji Ota  * information: Portions Copyright [yyyy] [name of copyright owner]
18*c0dd49bdSEiji Ota  *
19*c0dd49bdSEiji Ota  * CDDL HEADER END
20*c0dd49bdSEiji Ota  */
21*c0dd49bdSEiji Ota /*
22*c0dd49bdSEiji Ota  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*c0dd49bdSEiji Ota  */
24*c0dd49bdSEiji Ota #include <sys/types.h>
25*c0dd49bdSEiji Ota #include <sys/sunddi.h>
26*c0dd49bdSEiji Ota #include <sys/dlpi.h>
27*c0dd49bdSEiji Ota #include <sys/ib/clients/rdsv3/rdsv3_sc.h>
28*c0dd49bdSEiji Ota #include <sys/ib/clients/rdsv3/rdsv3_debug.h>
29*c0dd49bdSEiji Ota 
30*c0dd49bdSEiji Ota /*
31*c0dd49bdSEiji Ota  * RDS Path MAP
32*c0dd49bdSEiji Ota  *
33*c0dd49bdSEiji Ota  * N - Node record, P - Path record
34*c0dd49bdSEiji Ota  *
35*c0dd49bdSEiji Ota  * rds_path_map -
36*c0dd49bdSEiji Ota  *              |
37*c0dd49bdSEiji Ota  *              v
38*c0dd49bdSEiji Ota  *      	---------	---------	---------
39*c0dd49bdSEiji Ota  *     		|   N   |------>|  N    |------>|   N   |------> NULL
40*c0dd49bdSEiji Ota  * NULL <-------|       |<------|       |<------|       |
41*c0dd49bdSEiji Ota  *     		---------       ---------       ---------
42*c0dd49bdSEiji Ota  *               |               |               |
43*c0dd49bdSEiji Ota  *               |               |               |
44*c0dd49bdSEiji Ota  *               v               v               v
45*c0dd49bdSEiji Ota  *		--------        ---------       ---------
46*c0dd49bdSEiji Ota  *		|  P   |        |  P    |       |  P    |
47*c0dd49bdSEiji Ota  *		--------        ---------       ---------
48*c0dd49bdSEiji Ota  *		|  ^            |   ^           |   ^
49*c0dd49bdSEiji Ota  *		|  |            |   |           |   |
50*c0dd49bdSEiji Ota  *		v  |            v   |           v   |
51*c0dd49bdSEiji Ota  *		--------	--------	---------
52*c0dd49bdSEiji Ota  *		|   P  |	|  P   |	|  P    |
53*c0dd49bdSEiji Ota  *		--------	--------	---------
54*c0dd49bdSEiji Ota  *		  o		   o		   o
55*c0dd49bdSEiji Ota  *		  o		   o		   o
56*c0dd49bdSEiji Ota  *		  o		   o		   o
57*c0dd49bdSEiji Ota  */
58*c0dd49bdSEiji Ota 
59*c0dd49bdSEiji Ota typedef struct rds_path_record_s {
60*c0dd49bdSEiji Ota 	ipaddr_t			libd_ip;
61*c0dd49bdSEiji Ota 	ipaddr_t			ribd_ip;
62*c0dd49bdSEiji Ota 	struct rds_path_record_s	*up;
63*c0dd49bdSEiji Ota 	struct rds_path_record_s	*downp;
64*c0dd49bdSEiji Ota 	char				lifname[MAXNAMELEN];
65*c0dd49bdSEiji Ota 	char				rifname[MAXNAMELEN];
66*c0dd49bdSEiji Ota } rds_path_record_t;
67*c0dd49bdSEiji Ota 
68*c0dd49bdSEiji Ota typedef struct rds_node_record_s {
69*c0dd49bdSEiji Ota 	struct rds_node_record_s	*nextp;
70*c0dd49bdSEiji Ota 	ipaddr_t			lnode_ip;	/* local ip */
71*c0dd49bdSEiji Ota 	ipaddr_t			rnode_ip;	/* remote ip */
72*c0dd49bdSEiji Ota 	struct rds_path_record_s	*downp;
73*c0dd49bdSEiji Ota 	struct rds_node_record_s	*prevp;
74*c0dd49bdSEiji Ota } rds_node_record_t;
75*c0dd49bdSEiji Ota 
76*c0dd49bdSEiji Ota static char			sc_device_name[MAXNAMELEN] = "NotInitialized";
77*c0dd49bdSEiji Ota static kmutex_t			rdsv3_pathmap_lock;
78*c0dd49bdSEiji Ota static rds_node_record_t	*rdsv3_pathmap = NULL;
79*c0dd49bdSEiji Ota 
80*c0dd49bdSEiji Ota #define	RDS_VALIDATE_PATH(p)						\
81*c0dd49bdSEiji Ota 	if ((p->local.iftype != DL_IB) || (p->remote.iftype != DL_IB))	\
82*c0dd49bdSEiji Ota 		return
83*c0dd49bdSEiji Ota 
84*c0dd49bdSEiji Ota #define	isalpha(ch)	(((ch) >= 'a' && (ch) <= 'z') || \
85*c0dd49bdSEiji Ota 			((ch) >= 'A' && (ch) <= 'Z'))
86*c0dd49bdSEiji Ota 
87*c0dd49bdSEiji Ota /*
88*c0dd49bdSEiji Ota  * Called by SC to register the Sun Cluster device name
89*c0dd49bdSEiji Ota  */
90*c0dd49bdSEiji Ota void
rdsv3_clif_name(char * name)91*c0dd49bdSEiji Ota rdsv3_clif_name(char *name)
92*c0dd49bdSEiji Ota {
93*c0dd49bdSEiji Ota 	int	i;
94*c0dd49bdSEiji Ota 
95*c0dd49bdSEiji Ota 	ASSERT(name != NULL);
96*c0dd49bdSEiji Ota 
97*c0dd49bdSEiji Ota 	mutex_enter(&rdsv3_pathmap_lock);
98*c0dd49bdSEiji Ota 
99*c0dd49bdSEiji Ota 	/* extract the device name from the interface name */
100*c0dd49bdSEiji Ota 	i = strlen(name) - 1;
101*c0dd49bdSEiji Ota 	while ((i >= 0) && (!isalpha(name[i]))) i--;
102*c0dd49bdSEiji Ota 	if (i >= 0) {
103*c0dd49bdSEiji Ota 		(void) strncpy(sc_device_name, name, i + 1);
104*c0dd49bdSEiji Ota 		sc_device_name[i + 1] = '\0';
105*c0dd49bdSEiji Ota 	}
106*c0dd49bdSEiji Ota 
107*c0dd49bdSEiji Ota 	mutex_exit(&rdsv3_pathmap_lock);
108*c0dd49bdSEiji Ota }
109*c0dd49bdSEiji Ota 
110*c0dd49bdSEiji Ota /*
111*c0dd49bdSEiji Ota  * Called by SC on discovering a new path
112*c0dd49bdSEiji Ota  */
113*c0dd49bdSEiji Ota void
rdsv3_path_up(rds_path_t * path)114*c0dd49bdSEiji Ota rdsv3_path_up(rds_path_t *path)
115*c0dd49bdSEiji Ota {
116*c0dd49bdSEiji Ota 	rds_node_record_t	*p;
117*c0dd49bdSEiji Ota 	rds_path_record_t	*p1;
118*c0dd49bdSEiji Ota 
119*c0dd49bdSEiji Ota 	ASSERT(path != NULL);
120*c0dd49bdSEiji Ota 
121*c0dd49bdSEiji Ota 	/* ignore if the end points are not of type DL_IB */
122*c0dd49bdSEiji Ota 	RDS_VALIDATE_PATH(path);
123*c0dd49bdSEiji Ota 
124*c0dd49bdSEiji Ota 	mutex_enter(&rdsv3_pathmap_lock);
125*c0dd49bdSEiji Ota 
126*c0dd49bdSEiji Ota 	p = rdsv3_pathmap;
127*c0dd49bdSEiji Ota 	while ((p) && ((p->lnode_ip != path->local.node_ipaddr) ||
128*c0dd49bdSEiji Ota 	    (p->rnode_ip != path->remote.node_ipaddr))) {
129*c0dd49bdSEiji Ota 		p = p->nextp;
130*c0dd49bdSEiji Ota 	}
131*c0dd49bdSEiji Ota 
132*c0dd49bdSEiji Ota 	if (p == NULL) {
133*c0dd49bdSEiji Ota 		p = (rds_node_record_t *)kmem_alloc(sizeof (rds_node_record_t),
134*c0dd49bdSEiji Ota 		    KM_SLEEP);
135*c0dd49bdSEiji Ota 		p1 = (rds_path_record_t *)kmem_alloc(
136*c0dd49bdSEiji Ota 		    sizeof (rds_path_record_t), KM_SLEEP);
137*c0dd49bdSEiji Ota 
138*c0dd49bdSEiji Ota 		p->nextp = NULL;
139*c0dd49bdSEiji Ota 		p->lnode_ip = path->local.node_ipaddr;
140*c0dd49bdSEiji Ota 		p->rnode_ip = path->remote.node_ipaddr;
141*c0dd49bdSEiji Ota 		p->downp = p1;
142*c0dd49bdSEiji Ota 		p->prevp = NULL;
143*c0dd49bdSEiji Ota 
144*c0dd49bdSEiji Ota 		p1->libd_ip = path->local.ipaddr;
145*c0dd49bdSEiji Ota 		p1->ribd_ip = path->remote.ipaddr;
146*c0dd49bdSEiji Ota 		p1->up = NULL;
147*c0dd49bdSEiji Ota 		p1->downp = NULL;
148*c0dd49bdSEiji Ota 		(void) strcpy(p1->lifname, path->local.ifname);
149*c0dd49bdSEiji Ota 		(void) strcpy(p1->rifname, path->remote.ifname);
150*c0dd49bdSEiji Ota 
151*c0dd49bdSEiji Ota 		if (rdsv3_pathmap == NULL) {
152*c0dd49bdSEiji Ota 			rdsv3_pathmap = p;
153*c0dd49bdSEiji Ota 		} else {
154*c0dd49bdSEiji Ota 			/* insert this node at the head */
155*c0dd49bdSEiji Ota 			rdsv3_pathmap->prevp = p;
156*c0dd49bdSEiji Ota 			p->nextp = rdsv3_pathmap;
157*c0dd49bdSEiji Ota 			rdsv3_pathmap = p;
158*c0dd49bdSEiji Ota 		}
159*c0dd49bdSEiji Ota 	} else {
160*c0dd49bdSEiji Ota 		/* we found a match */
161*c0dd49bdSEiji Ota 		p1 = (rds_path_record_t *)kmem_alloc(
162*c0dd49bdSEiji Ota 		    sizeof (rds_path_record_t), KM_SLEEP);
163*c0dd49bdSEiji Ota 
164*c0dd49bdSEiji Ota 		p1->libd_ip = path->local.ipaddr;
165*c0dd49bdSEiji Ota 		p1->ribd_ip = path->remote.ipaddr;
166*c0dd49bdSEiji Ota 		p1->downp = p->downp;
167*c0dd49bdSEiji Ota 		p->downp->up = p1;
168*c0dd49bdSEiji Ota 		p1->up = NULL;
169*c0dd49bdSEiji Ota 		p->downp = p1;
170*c0dd49bdSEiji Ota 		(void) strcpy(p1->lifname, path->local.ifname);
171*c0dd49bdSEiji Ota 		(void) strcpy(p1->rifname, path->remote.ifname);
172*c0dd49bdSEiji Ota 	}
173*c0dd49bdSEiji Ota 
174*c0dd49bdSEiji Ota 	mutex_exit(&rdsv3_pathmap_lock);
175*c0dd49bdSEiji Ota }
176*c0dd49bdSEiji Ota 
177*c0dd49bdSEiji Ota /*
178*c0dd49bdSEiji Ota  * Called by SC to delete a path
179*c0dd49bdSEiji Ota  */
180*c0dd49bdSEiji Ota void
rdsv3_path_down(rds_path_t * path)181*c0dd49bdSEiji Ota rdsv3_path_down(rds_path_t *path)
182*c0dd49bdSEiji Ota {
183*c0dd49bdSEiji Ota 	rds_node_record_t	*p;
184*c0dd49bdSEiji Ota 	rds_path_record_t	*p1, *p1up, *p1downp;
185*c0dd49bdSEiji Ota 
186*c0dd49bdSEiji Ota 	ASSERT(path != NULL);
187*c0dd49bdSEiji Ota 
188*c0dd49bdSEiji Ota 	/* ignore if the end points are not of type DL_IB */
189*c0dd49bdSEiji Ota 	RDS_VALIDATE_PATH(path);
190*c0dd49bdSEiji Ota 
191*c0dd49bdSEiji Ota 	mutex_enter(&rdsv3_pathmap_lock);
192*c0dd49bdSEiji Ota 
193*c0dd49bdSEiji Ota 	p = rdsv3_pathmap;
194*c0dd49bdSEiji Ota 	while ((p) && ((p->lnode_ip != path->local.node_ipaddr) ||
195*c0dd49bdSEiji Ota 	    (p->rnode_ip != path->remote.node_ipaddr))) {
196*c0dd49bdSEiji Ota 		p = p->nextp;
197*c0dd49bdSEiji Ota 	}
198*c0dd49bdSEiji Ota 
199*c0dd49bdSEiji Ota 	if (p == NULL) {
200*c0dd49bdSEiji Ota 		/* no match */
201*c0dd49bdSEiji Ota 		RDSV3_DPRINTF2("rdsv3_path_down", "Node record not found "
202*c0dd49bdSEiji Ota 		    "(0x%x <-> 0x%x)", path->local.node_ipaddr,
203*c0dd49bdSEiji Ota 		    path->remote.node_ipaddr);
204*c0dd49bdSEiji Ota 		mutex_exit(&rdsv3_pathmap_lock);
205*c0dd49bdSEiji Ota 		return;
206*c0dd49bdSEiji Ota 	}
207*c0dd49bdSEiji Ota 
208*c0dd49bdSEiji Ota 	p1 = p->downp;
209*c0dd49bdSEiji Ota 	while ((p1) && ((p1->libd_ip != path->local.ipaddr) ||
210*c0dd49bdSEiji Ota 	    (p1->ribd_ip != path->remote.ipaddr))) {
211*c0dd49bdSEiji Ota 		p1 = p1->downp;
212*c0dd49bdSEiji Ota 	}
213*c0dd49bdSEiji Ota 
214*c0dd49bdSEiji Ota 	if (p1 == NULL) {
215*c0dd49bdSEiji Ota 		/* no match */
216*c0dd49bdSEiji Ota 		RDSV3_DPRINTF2("rdsv3_path_down", "Path record not found "
217*c0dd49bdSEiji Ota 		    "(0x%x <-> 0x%x)", path->local.ipaddr, path->remote.ipaddr);
218*c0dd49bdSEiji Ota 		mutex_exit(&rdsv3_pathmap_lock);
219*c0dd49bdSEiji Ota 		return;
220*c0dd49bdSEiji Ota 	}
221*c0dd49bdSEiji Ota 
222*c0dd49bdSEiji Ota 	/* we found the record, remove it */
223*c0dd49bdSEiji Ota 	p1up = p1->up;
224*c0dd49bdSEiji Ota 	p1downp = p1->downp;
225*c0dd49bdSEiji Ota 
226*c0dd49bdSEiji Ota 	if (p1up) {
227*c0dd49bdSEiji Ota 		p1up->downp = p1downp;
228*c0dd49bdSEiji Ota 	} else {
229*c0dd49bdSEiji Ota 		/* this is the first path record */
230*c0dd49bdSEiji Ota 		p->downp = p1downp;
231*c0dd49bdSEiji Ota 	}
232*c0dd49bdSEiji Ota 
233*c0dd49bdSEiji Ota 	if (p1downp) {
234*c0dd49bdSEiji Ota 		p1downp->up = p1up;
235*c0dd49bdSEiji Ota 	}
236*c0dd49bdSEiji Ota 
237*c0dd49bdSEiji Ota 	kmem_free(p1, sizeof (rds_path_record_t));
238*c0dd49bdSEiji Ota 
239*c0dd49bdSEiji Ota 	/* remove the node record if there are no path records */
240*c0dd49bdSEiji Ota 	if (p->downp == NULL) {
241*c0dd49bdSEiji Ota 		if (p->prevp) {
242*c0dd49bdSEiji Ota 			p->prevp->nextp = p->nextp;
243*c0dd49bdSEiji Ota 		} else {
244*c0dd49bdSEiji Ota 			/* this is the first node record */
245*c0dd49bdSEiji Ota 			ASSERT(p == rdsv3_pathmap);
246*c0dd49bdSEiji Ota 			rdsv3_pathmap = p->nextp;
247*c0dd49bdSEiji Ota 		}
248*c0dd49bdSEiji Ota 
249*c0dd49bdSEiji Ota 		if (p->nextp) {
250*c0dd49bdSEiji Ota 			p->nextp->prevp = p->prevp;
251*c0dd49bdSEiji Ota 		}
252*c0dd49bdSEiji Ota 
253*c0dd49bdSEiji Ota 		kmem_free(p, sizeof (rds_node_record_t));
254*c0dd49bdSEiji Ota 	}
255*c0dd49bdSEiji Ota 
256*c0dd49bdSEiji Ota 	mutex_exit(&rdsv3_pathmap_lock);
257*c0dd49bdSEiji Ota }
258*c0dd49bdSEiji Ota 
259*c0dd49bdSEiji Ota int
rdsv3_sc_path_lookup(ipaddr_t * localip,ipaddr_t * remip)260*c0dd49bdSEiji Ota rdsv3_sc_path_lookup(ipaddr_t *localip, ipaddr_t *remip)
261*c0dd49bdSEiji Ota {
262*c0dd49bdSEiji Ota 	rds_node_record_t	*p;
263*c0dd49bdSEiji Ota 	rds_path_record_t	*p1, *p1downp;
264*c0dd49bdSEiji Ota 
265*c0dd49bdSEiji Ota 	mutex_enter(&rdsv3_pathmap_lock);
266*c0dd49bdSEiji Ota 
267*c0dd49bdSEiji Ota 	p = rdsv3_pathmap;
268*c0dd49bdSEiji Ota 	while ((p) && ((p->lnode_ip != *localip) || (p->rnode_ip != *remip))) {
269*c0dd49bdSEiji Ota 		p = p->nextp;
270*c0dd49bdSEiji Ota 	}
271*c0dd49bdSEiji Ota 
272*c0dd49bdSEiji Ota 	if (p == NULL) {
273*c0dd49bdSEiji Ota 		/* no match */
274*c0dd49bdSEiji Ota 		RDSV3_DPRINTF2("rdsv3_sc_path_lookup", "Node record not found "
275*c0dd49bdSEiji Ota 		    "(0x%x <-> 0x%x)", *localip, *remip);
276*c0dd49bdSEiji Ota 		mutex_exit(&rdsv3_pathmap_lock);
277*c0dd49bdSEiji Ota 		return (0);
278*c0dd49bdSEiji Ota 	}
279*c0dd49bdSEiji Ota 
280*c0dd49bdSEiji Ota 	/* found a path */
281*c0dd49bdSEiji Ota 	p1 = p->downp;
282*c0dd49bdSEiji Ota 	*localip = p1->libd_ip;
283*c0dd49bdSEiji Ota 	*remip = p1->ribd_ip;
284*c0dd49bdSEiji Ota 
285*c0dd49bdSEiji Ota 	/*
286*c0dd49bdSEiji Ota 	 * But next time, we want to use a different path record so move this
287*c0dd49bdSEiji Ota 	 * path record to the end.
288*c0dd49bdSEiji Ota 	 */
289*c0dd49bdSEiji Ota 	p1downp = p1->downp;
290*c0dd49bdSEiji Ota 	if (p1downp != NULL) {
291*c0dd49bdSEiji Ota 		p->downp = p1downp;
292*c0dd49bdSEiji Ota 		p1downp->up = NULL;
293*c0dd49bdSEiji Ota 
294*c0dd49bdSEiji Ota 		/* walk down to the last path record */
295*c0dd49bdSEiji Ota 		while (p1downp->downp != NULL) {
296*c0dd49bdSEiji Ota 			p1downp = p1downp->downp;
297*c0dd49bdSEiji Ota 		}
298*c0dd49bdSEiji Ota 
299*c0dd49bdSEiji Ota 		/* Attach the first path record to the end */
300*c0dd49bdSEiji Ota 		p1downp->downp = p1;
301*c0dd49bdSEiji Ota 		p1->up = p1downp;
302*c0dd49bdSEiji Ota 		p1->downp = NULL;
303*c0dd49bdSEiji Ota 	}
304*c0dd49bdSEiji Ota 
305*c0dd49bdSEiji Ota 	mutex_exit(&rdsv3_pathmap_lock);
306*c0dd49bdSEiji Ota 
307*c0dd49bdSEiji Ota 	return (1);
308*c0dd49bdSEiji Ota }
309*c0dd49bdSEiji Ota 
310*c0dd49bdSEiji Ota boolean_t
rdsv3_if_lookup_by_name(char * devname)311*c0dd49bdSEiji Ota rdsv3_if_lookup_by_name(char *devname)
312*c0dd49bdSEiji Ota {
313*c0dd49bdSEiji Ota 	mutex_enter(&rdsv3_pathmap_lock);
314*c0dd49bdSEiji Ota 
315*c0dd49bdSEiji Ota 	/*
316*c0dd49bdSEiji Ota 	 * Sun Cluster always names its interconnect virtual network interface
317*c0dd49bdSEiji Ota 	 * as clprivnetx, so  return TRUE if there is atleast one node record
318*c0dd49bdSEiji Ota 	 * and the interface name is clprivnet something.
319*c0dd49bdSEiji Ota 	 */
320*c0dd49bdSEiji Ota 	if (strcmp(devname, sc_device_name) == 0) {
321*c0dd49bdSEiji Ota 		/* clprivnet address */
322*c0dd49bdSEiji Ota 		mutex_exit(&rdsv3_pathmap_lock);
323*c0dd49bdSEiji Ota 		return (B_TRUE);
324*c0dd49bdSEiji Ota 	}
325*c0dd49bdSEiji Ota 
326*c0dd49bdSEiji Ota 	mutex_exit(&rdsv3_pathmap_lock);
327*c0dd49bdSEiji Ota 	return (B_FALSE);
328*c0dd49bdSEiji Ota }
329*c0dd49bdSEiji Ota 
330*c0dd49bdSEiji Ota boolean_t
rdsv3_if_lookup_by_addr(ipaddr_t addr)331*c0dd49bdSEiji Ota rdsv3_if_lookup_by_addr(ipaddr_t addr)
332*c0dd49bdSEiji Ota {
333*c0dd49bdSEiji Ota 	rds_node_record_t	*p;
334*c0dd49bdSEiji Ota 	rds_path_record_t	*p1;
335*c0dd49bdSEiji Ota 
336*c0dd49bdSEiji Ota 	mutex_enter(&rdsv3_pathmap_lock);
337*c0dd49bdSEiji Ota 
338*c0dd49bdSEiji Ota 	p = rdsv3_pathmap;
339*c0dd49bdSEiji Ota 	while ((p) && (p->lnode_ip != addr)) {
340*c0dd49bdSEiji Ota 		p1 = p->downp;
341*c0dd49bdSEiji Ota 		while ((p1) && (p1->libd_ip != addr)) {
342*c0dd49bdSEiji Ota 			p1 = p1->downp;
343*c0dd49bdSEiji Ota 		}
344*c0dd49bdSEiji Ota 
345*c0dd49bdSEiji Ota 		/* we found a match */
346*c0dd49bdSEiji Ota 		if (p1 != NULL)
347*c0dd49bdSEiji Ota 			break;
348*c0dd49bdSEiji Ota 
349*c0dd49bdSEiji Ota 		/* go to the next node record */
350*c0dd49bdSEiji Ota 		p = p->nextp;
351*c0dd49bdSEiji Ota 	}
352*c0dd49bdSEiji Ota 
353*c0dd49bdSEiji Ota 	mutex_exit(&rdsv3_pathmap_lock);
354*c0dd49bdSEiji Ota 	if (p == NULL) {
355*c0dd49bdSEiji Ota 		/* no match */
356*c0dd49bdSEiji Ota 		RDSV3_DPRINTF2("rds_if_lookup_by_addr",
357*c0dd49bdSEiji Ota 		    "Addr: 0x%x not found", addr);
358*c0dd49bdSEiji Ota 		return (B_FALSE);
359*c0dd49bdSEiji Ota 	}
360*c0dd49bdSEiji Ota 
361*c0dd49bdSEiji Ota 	/* Found a matching node record */
362*c0dd49bdSEiji Ota 	return (B_TRUE);
363*c0dd49bdSEiji Ota }
364*c0dd49bdSEiji Ota 
365*c0dd49bdSEiji Ota /*
366*c0dd49bdSEiji Ota  * If SC is configured then addr would be a clprivnet address. Find the
367*c0dd49bdSEiji Ota  * node record and return the first IB address. If the node record is not
368*c0dd49bdSEiji Ota  * found, then return addr as-is.
369*c0dd49bdSEiji Ota  */
370*c0dd49bdSEiji Ota ipaddr_t
rdsv3_scaddr_to_ibaddr(ipaddr_t addr)371*c0dd49bdSEiji Ota rdsv3_scaddr_to_ibaddr(ipaddr_t addr)
372*c0dd49bdSEiji Ota {
373*c0dd49bdSEiji Ota 	rds_node_record_t	*p;
374*c0dd49bdSEiji Ota 	rds_path_record_t	*p1;
375*c0dd49bdSEiji Ota 	ipaddr_t		ret = addr;
376*c0dd49bdSEiji Ota 
377*c0dd49bdSEiji Ota 	mutex_enter(&rdsv3_pathmap_lock);
378*c0dd49bdSEiji Ota 
379*c0dd49bdSEiji Ota 	p = rdsv3_pathmap;
380*c0dd49bdSEiji Ota 	while ((p) && (p->lnode_ip != addr)) {
381*c0dd49bdSEiji Ota 		/* go to the next node record */
382*c0dd49bdSEiji Ota 		p = p->nextp;
383*c0dd49bdSEiji Ota 	}
384*c0dd49bdSEiji Ota 
385*c0dd49bdSEiji Ota 	if (p != NULL) {
386*c0dd49bdSEiji Ota 		p1 = p->downp;
387*c0dd49bdSEiji Ota 		ret = p1->libd_ip;
388*c0dd49bdSEiji Ota 		RDSV3_DPRINTF3("rds_scaddr_to_ibaddr",
389*c0dd49bdSEiji Ota 		    "Addr: 0x%x found: 0x%x", addr, p1->libd_ip);
390*c0dd49bdSEiji Ota 	}
391*c0dd49bdSEiji Ota 	mutex_exit(&rdsv3_pathmap_lock);
392*c0dd49bdSEiji Ota 
393*c0dd49bdSEiji Ota 	/* Found a matching node record */
394*c0dd49bdSEiji Ota 	return (ret);
395*c0dd49bdSEiji Ota }
396