xref: /onnv-gate/usr/src/uts/common/io/ib/clients/rds/rdsib_sc.c (revision 4467:e004b2587f27)
13302Sagiri /*
23302Sagiri  * CDDL HEADER START
33302Sagiri  *
43302Sagiri  * The contents of this file are subject to the terms of the
53302Sagiri  * Common Development and Distribution License (the "License").
63302Sagiri  * You may not use this file except in compliance with the License.
73302Sagiri  *
83302Sagiri  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93302Sagiri  * or http://www.opensolaris.org/os/licensing.
103302Sagiri  * See the License for the specific language governing permissions
113302Sagiri  * and limitations under the License.
123302Sagiri  *
133302Sagiri  * When distributing Covered Code, include this CDDL HEADER in each
143302Sagiri  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153302Sagiri  * If applicable, add the following below this CDDL HEADER, with the
163302Sagiri  * fields enclosed by brackets "[]" replaced with your own identifying
173302Sagiri  * information: Portions Copyright [yyyy] [name of copyright owner]
183302Sagiri  *
193302Sagiri  * CDDL HEADER END
203302Sagiri  */
213302Sagiri /*
224154Sagiri  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
233302Sagiri  * Use is subject to license terms.
243302Sagiri  */
253302Sagiri 
263302Sagiri #pragma ident	"%Z%%M%	%I%	%E% SMI"
273302Sagiri 
283302Sagiri #include <sys/ib/clients/rds/rdsib_sc.h>
293302Sagiri #include <sys/ib/clients/rds/rdsib_debug.h>
303302Sagiri #include <sys/types.h>
313302Sagiri #include <sys/sunddi.h>
32*4467Sagiri #include <sys/dlpi.h>
333302Sagiri 
343302Sagiri /*
353302Sagiri  * RDS Path MAP
363302Sagiri  *
373302Sagiri  * N - Node record, P - Path record
383302Sagiri  *
393302Sagiri  * rds_path_map -
403302Sagiri  *              |
413302Sagiri  *              v
423302Sagiri  *      	---------	---------	---------
433302Sagiri  *     		|   N   |------>|  N    |------>|   N   |------> NULL
443302Sagiri  * NULL <-------|       |<------|       |<------|       |
453302Sagiri  *     		---------       ---------       ---------
463302Sagiri  *               |               |               |
473302Sagiri  *               |               |               |
483302Sagiri  *               v               v               v
493302Sagiri  *		--------        ---------       ---------
503302Sagiri  *		|  P   |        |  P    |       |  P    |
513302Sagiri  *		--------        ---------       ---------
523302Sagiri  *		|  ^            |   ^           |   ^
533302Sagiri  *		|  |            |   |           |   |
543302Sagiri  *		v  |            v   |           v   |
553302Sagiri  *		--------	--------	---------
563302Sagiri  *		|   P  |	|  P   |	|  P    |
573302Sagiri  *		--------	--------	---------
583302Sagiri  *		  o		   o		   o
593302Sagiri  *		  o		   o		   o
603302Sagiri  *		  o		   o		   o
613302Sagiri  */
623302Sagiri 
633302Sagiri typedef struct rds_path_record_s {
643302Sagiri 	ipaddr_t			libd_ip;
653302Sagiri 	ipaddr_t			ribd_ip;
663302Sagiri 	struct rds_path_record_s	*up;
673302Sagiri 	struct rds_path_record_s	*downp;
684154Sagiri 	char				lifname[MAXNAMELEN];
694154Sagiri 	char				rifname[MAXNAMELEN];
703302Sagiri } rds_path_record_t;
713302Sagiri 
723302Sagiri typedef struct rds_node_record_s {
733302Sagiri 	struct rds_node_record_s	*nextp;
743302Sagiri 	ipaddr_t			lnode_ip;	/* local ip */
753302Sagiri 	ipaddr_t			rnode_ip;	/* remote ip */
763302Sagiri 	struct rds_path_record_s	*downp;
773302Sagiri 	struct rds_node_record_s	*prevp;
783302Sagiri } rds_node_record_t;
793302Sagiri 
80*4467Sagiri char			sc_device_name[MAXNAMELEN] = "NotInitialized";
813302Sagiri kmutex_t		rds_pathmap_lock;
823302Sagiri rds_node_record_t	*rds_pathmap = NULL;
833302Sagiri 
84*4467Sagiri #define	RDS_VALIDATE_PATH(p)						\
85*4467Sagiri 	if ((p->local.iftype != DL_IB) || (p->remote.iftype != DL_IB))	\
86*4467Sagiri 		return
87*4467Sagiri 
88*4467Sagiri #define	isalpha(ch)	(((ch) >= 'a' && (ch) <= 'z') || \
89*4467Sagiri 			((ch) >= 'A' && (ch) <= 'Z'))
904154Sagiri 
91*4467Sagiri /*
92*4467Sagiri  * Called by SC to register the Sun Cluster device name
93*4467Sagiri  */
94*4467Sagiri void
rds_clif_name(char * name)95*4467Sagiri rds_clif_name(char *name)
96*4467Sagiri {
97*4467Sagiri 	int	i;
98*4467Sagiri 
99*4467Sagiri 	ASSERT(name != NULL);
100*4467Sagiri 
101*4467Sagiri 	mutex_enter(&rds_pathmap_lock);
102*4467Sagiri 
103*4467Sagiri 	/* extract the device name from the interface name */
104*4467Sagiri 	i = strlen(name) - 1;
105*4467Sagiri 	while ((i >= 0) && (!isalpha(name[i]))) i--;
106*4467Sagiri 	if (i >= 0) {
107*4467Sagiri 		(void) strncpy(sc_device_name, name, i + 1);
108*4467Sagiri 		sc_device_name[i + 1] = '\0';
1094154Sagiri 	}
1104154Sagiri 
111*4467Sagiri 	mutex_exit(&rds_pathmap_lock);
1124154Sagiri }
1134154Sagiri 
1143302Sagiri /*
1153302Sagiri  * Called by SC on discovering a new path
1163302Sagiri  */
1173302Sagiri void
rds_path_up(rds_path_t * path)1183302Sagiri rds_path_up(rds_path_t *path)
1193302Sagiri {
1203302Sagiri 	rds_node_record_t	*p;
1213302Sagiri 	rds_path_record_t	*p1;
1223302Sagiri 
1233302Sagiri 	ASSERT(path != NULL);
1243302Sagiri 
125*4467Sagiri 	/* ignore if the end points are not of type DL_IB */
126*4467Sagiri 	RDS_VALIDATE_PATH(path);
1273302Sagiri 
1283302Sagiri 	mutex_enter(&rds_pathmap_lock);
1293302Sagiri 
1303302Sagiri 	p = rds_pathmap;
1313302Sagiri 	while ((p) && ((p->lnode_ip != path->local.node_ipaddr) ||
1323302Sagiri 	    (p->rnode_ip != path->remote.node_ipaddr))) {
1333302Sagiri 		p = p->nextp;
1343302Sagiri 	}
1353302Sagiri 
1363302Sagiri 	if (p == NULL) {
1373302Sagiri 		p = (rds_node_record_t *)kmem_alloc(sizeof (rds_node_record_t),
1383302Sagiri 		    KM_SLEEP);
1393302Sagiri 		p1 = (rds_path_record_t *)kmem_alloc(
1403302Sagiri 		    sizeof (rds_path_record_t), KM_SLEEP);
1413302Sagiri 
1423302Sagiri 		p->nextp = NULL;
1433302Sagiri 		p->lnode_ip = path->local.node_ipaddr;
1443302Sagiri 		p->rnode_ip = path->remote.node_ipaddr;
1453302Sagiri 		p->downp = p1;
1463302Sagiri 		p->prevp = NULL;
1473302Sagiri 
1483302Sagiri 		p1->libd_ip = path->local.ipaddr;
1493302Sagiri 		p1->ribd_ip = path->remote.ipaddr;
1503302Sagiri 		p1->up = NULL;
1513302Sagiri 		p1->downp = NULL;
1523302Sagiri 		(void) strcpy(p1->lifname, path->local.ifname);
1533302Sagiri 		(void) strcpy(p1->rifname, path->remote.ifname);
1543302Sagiri 
1553302Sagiri 		if (rds_pathmap == NULL) {
1563302Sagiri 			rds_pathmap = p;
1573302Sagiri 		} else {
1583302Sagiri 			/* insert this node at the head */
1593302Sagiri 			rds_pathmap->prevp = p;
1603302Sagiri 			p->nextp = rds_pathmap;
1613302Sagiri 			rds_pathmap = p;
1623302Sagiri 		}
1633302Sagiri 	} else {
1643302Sagiri 		/* we found a match */
1653302Sagiri 		p1 = (rds_path_record_t *)kmem_alloc(
1663302Sagiri 		    sizeof (rds_path_record_t), KM_SLEEP);
1673302Sagiri 
1683302Sagiri 		p1->libd_ip = path->local.ipaddr;
1693302Sagiri 		p1->ribd_ip = path->remote.ipaddr;
1703302Sagiri 		p1->downp = p->downp;
1713302Sagiri 		p->downp->up = p1;
1723302Sagiri 		p1->up = NULL;
1733302Sagiri 		p->downp = p1;
1743302Sagiri 		(void) strcpy(p1->lifname, path->local.ifname);
1753302Sagiri 		(void) strcpy(p1->rifname, path->remote.ifname);
1763302Sagiri 	}
1773302Sagiri 
1783302Sagiri 	mutex_exit(&rds_pathmap_lock);
1793302Sagiri }
1803302Sagiri 
1813302Sagiri /*
1823302Sagiri  * Called by SC to delete a path
1833302Sagiri  */
1843302Sagiri void
rds_path_down(rds_path_t * path)1853302Sagiri rds_path_down(rds_path_t *path)
1863302Sagiri {
1873302Sagiri 	rds_node_record_t	*p;
1883302Sagiri 	rds_path_record_t	*p1, *p1up, *p1downp;
1893302Sagiri 
1903302Sagiri 	ASSERT(path != NULL);
1913302Sagiri 
192*4467Sagiri 	/* ignore if the end points are not of type DL_IB */
193*4467Sagiri 	RDS_VALIDATE_PATH(path);
1943302Sagiri 
1953302Sagiri 	mutex_enter(&rds_pathmap_lock);
1963302Sagiri 
1973302Sagiri 	p = rds_pathmap;
1983302Sagiri 	while ((p) && ((p->lnode_ip != path->local.node_ipaddr) ||
1993302Sagiri 	    (p->rnode_ip != path->remote.node_ipaddr))) {
2003302Sagiri 		p = p->nextp;
2013302Sagiri 	}
2023302Sagiri 
2033302Sagiri 	if (p == NULL) {
2043302Sagiri 		/* no match */
2053302Sagiri 		RDS_DPRINTF2("rds_path_down", "Node record not found "
2063302Sagiri 		    "(0x%x <-> 0x%x)", path->local.node_ipaddr,
2073302Sagiri 		    path->remote.node_ipaddr);
2083302Sagiri 		mutex_exit(&rds_pathmap_lock);
2093302Sagiri 		return;
2103302Sagiri 	}
2113302Sagiri 
2123302Sagiri 	p1 = p->downp;
2133302Sagiri 	while ((p1) && ((p1->libd_ip != path->local.ipaddr) ||
2143302Sagiri 	    (p1->ribd_ip != path->remote.ipaddr))) {
2153302Sagiri 		p1 = p1->downp;
2163302Sagiri 	}
2173302Sagiri 
2183302Sagiri 	if (p1 == NULL) {
2193302Sagiri 		/* no match */
2203302Sagiri 		RDS_DPRINTF2("rds_path_down", "Path record not found "
2213302Sagiri 		    "(0x%x <-> 0x%x)", path->local.ipaddr, path->remote.ipaddr);
2223302Sagiri 		mutex_exit(&rds_pathmap_lock);
2233302Sagiri 		return;
2243302Sagiri 	}
2253302Sagiri 
2263302Sagiri 	/* we found the record, remove it */
2273302Sagiri 	p1up = p1->up;
2283302Sagiri 	p1downp = p1->downp;
2293302Sagiri 
2303302Sagiri 	if (p1up) {
2313302Sagiri 		p1up->downp = p1downp;
2323302Sagiri 	} else {
2333302Sagiri 		/* this is the first path record */
2343302Sagiri 		p->downp = p1downp;
2353302Sagiri 	}
2363302Sagiri 
2373302Sagiri 	if (p1downp) {
2383302Sagiri 		p1downp->up = p1up;
2393302Sagiri 	}
2403302Sagiri 
2413302Sagiri 	kmem_free(p1, sizeof (rds_path_record_t));
2423302Sagiri 
2433302Sagiri 	/* remove the node record if there are no path records */
2443302Sagiri 	if (p->downp == NULL) {
2453302Sagiri 		if (p->prevp) {
2463302Sagiri 			p->prevp->nextp = p->nextp;
2473302Sagiri 		} else {
2483302Sagiri 			/* this is the first node record */
2493302Sagiri 			ASSERT(p == rds_pathmap);
2504154Sagiri 			rds_pathmap = p->nextp;
2513302Sagiri 		}
2523302Sagiri 
2533302Sagiri 		if (p->nextp) {
2543302Sagiri 			p->nextp->prevp = p->prevp;
2553302Sagiri 		}
2563302Sagiri 
2573302Sagiri 		kmem_free(p, sizeof (rds_node_record_t));
2583302Sagiri 	}
2593302Sagiri 
2603302Sagiri 	mutex_exit(&rds_pathmap_lock);
2613302Sagiri }
2623302Sagiri 
2633302Sagiri int
rds_sc_path_lookup(ipaddr_t * localip,ipaddr_t * remip)2643302Sagiri rds_sc_path_lookup(ipaddr_t *localip, ipaddr_t *remip)
2653302Sagiri {
2663302Sagiri 	rds_node_record_t	*p;
267*4467Sagiri 	rds_path_record_t	*p1, *p1downp;
2683302Sagiri 
2693302Sagiri 	mutex_enter(&rds_pathmap_lock);
2703302Sagiri 
2713302Sagiri 	p = rds_pathmap;
2723302Sagiri 	while ((p) && ((p->lnode_ip != *localip) || (p->rnode_ip != *remip))) {
2733302Sagiri 		p = p->nextp;
2743302Sagiri 	}
2753302Sagiri 
2763302Sagiri 	if (p == NULL) {
2773302Sagiri 		/* no match */
2783302Sagiri 		RDS_DPRINTF2("rds_sc_path_lookup", "Node record not found "
2793302Sagiri 		    "(0x%x <-> 0x%x)", *localip, *remip);
2803302Sagiri 		mutex_exit(&rds_pathmap_lock);
2813302Sagiri 		return (0);
2823302Sagiri 	}
2833302Sagiri 
2843302Sagiri 	/* found a path */
2853302Sagiri 	p1 = p->downp;
2863302Sagiri 	*localip = p1->libd_ip;
2873302Sagiri 	*remip = p1->ribd_ip;
2883302Sagiri 
289*4467Sagiri 	/*
290*4467Sagiri 	 * But next time, we want to use a different path record so move this
291*4467Sagiri 	 * path record to the end.
292*4467Sagiri 	 */
293*4467Sagiri 	p1downp = p1->downp;
294*4467Sagiri 	if (p1downp != NULL) {
295*4467Sagiri 		p->downp = p1downp;
296*4467Sagiri 		p1downp->up = NULL;
297*4467Sagiri 
298*4467Sagiri 		/* walk down to the last path record */
299*4467Sagiri 		while (p1downp->downp != NULL) {
300*4467Sagiri 			p1downp = p1downp->downp;
301*4467Sagiri 		}
302*4467Sagiri 
303*4467Sagiri 		/* Attach the first path record to the end */
304*4467Sagiri 		p1downp->downp = p1;
305*4467Sagiri 		p1->up = p1downp;
306*4467Sagiri 		p1->downp = NULL;
307*4467Sagiri 	}
308*4467Sagiri 
3093302Sagiri 	mutex_exit(&rds_pathmap_lock);
3103302Sagiri 
3113302Sagiri 	return (1);
3123302Sagiri }
3133302Sagiri 
3143302Sagiri boolean_t
rds_if_lookup_by_name(char * devname)315*4467Sagiri rds_if_lookup_by_name(char *devname)
3163302Sagiri {
3173302Sagiri 	mutex_enter(&rds_pathmap_lock);
3183302Sagiri 
3194154Sagiri 	/*
3204154Sagiri 	 * Sun Cluster always names its interconnect virtual network interface
3214154Sagiri 	 * as clprivnetx, so  return TRUE if there is atleast one node record
3224154Sagiri 	 * and the interface name is clprivnet something.
3234154Sagiri 	 */
324*4467Sagiri 	if (strcmp(devname, sc_device_name) == 0) {
3254154Sagiri 		/* clprivnet address */
3264154Sagiri 		mutex_exit(&rds_pathmap_lock);
3274154Sagiri 		return (B_TRUE);
3284154Sagiri 	}
3294154Sagiri 
3303302Sagiri 	mutex_exit(&rds_pathmap_lock);
331*4467Sagiri 	return (B_FALSE);
3323302Sagiri }
3333302Sagiri 
3343302Sagiri boolean_t
rds_if_lookup_by_addr(ipaddr_t addr)3353302Sagiri rds_if_lookup_by_addr(ipaddr_t addr)
3363302Sagiri {
3373302Sagiri 	rds_node_record_t	*p;
3383302Sagiri 	rds_path_record_t	*p1;
3393302Sagiri 
3403302Sagiri 	mutex_enter(&rds_pathmap_lock);
3413302Sagiri 
3423302Sagiri 	p = rds_pathmap;
3433302Sagiri 	while ((p) && (p->lnode_ip != addr)) {
3443302Sagiri 		p1 = p->downp;
3453302Sagiri 		while ((p1) && (p1->libd_ip != addr)) {
3463302Sagiri 			p1 = p1->downp;
3473302Sagiri 		}
3483302Sagiri 
3493302Sagiri 		/* we found a match */
3503302Sagiri 		if (p1 != NULL)
3513302Sagiri 			break;
3523302Sagiri 
3533302Sagiri 		/* go to the next node record */
3543302Sagiri 		p = p->nextp;
3553302Sagiri 	}
3563302Sagiri 
3573302Sagiri 	mutex_exit(&rds_pathmap_lock);
3583302Sagiri 	if (p == NULL) {
3593302Sagiri 		/* no match */
3603302Sagiri 		RDS_DPRINTF2("rds_if_lookup_by_addr",
3613302Sagiri 		    "Addr: 0x%x not found", addr);
3623302Sagiri 		return (B_FALSE);
3633302Sagiri 	}
3643302Sagiri 
3653302Sagiri 	/* Found a matching node record */
3663302Sagiri 	return (B_TRUE);
3673302Sagiri }
368