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