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