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