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