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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/ddi.h> 28 #include <sys/sunddi.h> 29 #include <sys/stropts.h> 30 #include <sys/stream.h> 31 #include <sys/strsun.h> 32 #include <sys/strsubr.h> 33 #include <sys/socket.h> 34 #include <sys/stat.h> 35 #include <net/if_arp.h> 36 #include <sys/file.h> 37 #include <sys/sockio.h> 38 #include <sys/pathname.h> 39 #include <inet/arp.h> 40 #include <sys/modctl.h> 41 42 #include <sys/ib/mgt/ibcm/ibcm_arp.h> 43 44 #include <sys/kstr.h> 45 #include <sys/tiuser.h> 46 #include <sys/t_kuser.h> 47 48 extern char cmlog[]; 49 50 extern int ibcm_arp_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr, 51 ibt_ip_addr_t *src_addr, uint8_t localroute, uint32_t bound_dev_if, 52 ibcm_arp_pr_comp_func_t func); 53 extern void ibcm_arp_pr_arp_ack(mblk_t *mp); 54 extern void ibcm_arp_prwqn_delete(ibcm_arp_prwqn_t *wqnp); 55 56 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", datab)) 57 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibt_ip_addr_s)) 58 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_ip_t)) 59 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_ibd_insts_t)) 60 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibcm_arp_prwqn_t)) 61 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", iocblk)) 62 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", msgb)) 63 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", queue)) 64 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", sockaddr_in)) 65 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", sockaddr_in6)) 66 67 /* 68 * ibcm_arp_get_ibaddr_cb 69 */ 70 static int 71 ibcm_arp_get_ibaddr_cb(void *arg, int status) 72 { 73 ibcm_arp_prwqn_t *wqnp = (ibcm_arp_prwqn_t *)arg; 74 ibcm_arp_streams_t *ib_s = (ibcm_arp_streams_t *)wqnp->arg; 75 76 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr_cb(ib_s: %p wqnp: %p)", 77 ib_s, wqnp); 78 79 mutex_enter(&ib_s->lock); 80 ib_s->status = status; 81 ib_s->done = B_TRUE; 82 83 IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr_cb: SGID %llX:%llX " 84 "DGID: %llX:%llX", wqnp->sgid.gid_prefix, wqnp->sgid.gid_guid, 85 wqnp->dgid.gid_prefix, wqnp->dgid.gid_guid); 86 87 /* lock is held by the caller. */ 88 cv_signal(&ib_s->cv); 89 mutex_exit(&ib_s->lock); 90 return (0); 91 } 92 93 /* 94 * Lower read service procedure (messages coming back from arp/ip). 95 * Process messages based on queue type. 96 */ 97 static int 98 ibcm_arp_lrsrv(queue_t *q) 99 { 100 mblk_t *mp; 101 ibcm_arp_streams_t *ib_s = q->q_ptr; 102 103 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_lrsrv(%p, ibd_s: 0x%p)", q, ib_s); 104 105 if (WR(q) == ib_s->arpqueue) { 106 while (mp = getq(q)) { 107 ibcm_arp_pr_arp_ack(mp); 108 } 109 } 110 111 return (0); 112 } 113 114 /* 115 * Lower write service procedure. 116 * Used when lower streams are flow controlled. 117 */ 118 static int 119 ibcm_arp_lwsrv(queue_t *q) 120 { 121 mblk_t *mp; 122 123 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_lwsrv(%p)", q); 124 125 while (mp = getq(q)) { 126 if (canputnext(q)) { 127 putnext(q, mp); 128 } else { 129 (void) putbq(q, mp); 130 qenable(q); 131 break; 132 } 133 } 134 135 return (0); 136 } 137 138 /* 139 * Lower read put procedure. Arp/ip messages come here. 140 */ 141 static int 142 ibcm_arp_lrput(queue_t *q, mblk_t *mp) 143 { 144 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_lrput(0x%p, db_type: %d)", 145 q, DB_TYPE(mp)); 146 147 switch (DB_TYPE(mp)) { 148 case M_FLUSH: 149 /* 150 * Turn around 151 */ 152 if (*mp->b_rptr & FLUSHW) { 153 *mp->b_rptr &= ~FLUSHR; 154 qreply(q, mp); 155 return (0); 156 } 157 freemsg(mp); 158 break; 159 case M_IOCACK: 160 case M_IOCNAK: 161 case M_DATA: 162 /* 163 * This could be in interrupt context. 164 * Some of the ibt calls cannot be called in 165 * interrupt context, so 166 * put it in the queue and the message will be 167 * processed by service proccedure 168 */ 169 (void) putq(q, mp); 170 qenable(q); 171 break; 172 default: 173 IBTF_DPRINTF_L2(cmlog, "ibcm_arp_lrput: " 174 "got unknown msg <0x%x>\n", mp->b_datap->db_type); 175 ASSERT(0); 176 break; 177 } 178 179 return (0); 180 } 181 182 /* 183 * Streams write queue module info 184 */ 185 static struct module_info ibcm_arp_winfo = { 186 0, /* module ID number */ 187 "ibcm", /* module name */ 188 0, /* min packet size */ 189 INFPSZ, 190 49152, /* STREAM queue high water mark -- 49152 */ 191 12 /* STREAM queue low water mark -- 12 */ 192 }; 193 194 /* 195 * Streams lower write queue, for ibcm/ip requests. 196 */ 197 static struct qinit ibcm_arp_lwinit = { 198 NULL, /* qi_putp */ 199 ibcm_arp_lwsrv, /* qi_srvp */ 200 NULL, /* qi_qopen */ 201 NULL, /* qi_qclose */ 202 NULL, /* qi_qadmin */ 203 &ibcm_arp_winfo, /* module info */ 204 NULL, /* module statistics struct */ 205 NULL, 206 NULL, 207 STRUIOT_NONE /* stream uio type is standard uiomove() */ 208 }; 209 210 /* 211 * Streams lower read queue: read reply messages from ibcm/ip. 212 */ 213 static struct qinit ibcm_arp_lrinit = { 214 ibcm_arp_lrput, /* qi_putp */ 215 ibcm_arp_lrsrv, /* qi_srvp */ 216 NULL, /* qi_qopen */ 217 NULL, /* qi_qclose */ 218 NULL, /* qi_qadmin */ 219 &ibcm_arp_winfo, /* module info */ 220 NULL, /* module statistics struct */ 221 NULL, 222 NULL, 223 STRUIOT_NONE /* stream uio type is standard uiomove() */ 224 }; 225 226 227 static int 228 ibcm_arp_link_driver(ibcm_arp_streams_t *ib_s, char *path, queue_t **q, 229 vnode_t **dev_vp) 230 { 231 struct stdata *dev_stp; 232 vnode_t *vp; 233 int error; 234 queue_t *rq; 235 236 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_link_driver: Enter: %s", path); 237 238 /* open the driver from inside the kernel */ 239 error = vn_open(path, UIO_SYSSPACE, FREAD|FWRITE, 0, &vp, 240 0, NULL); 241 if (error) { 242 IBTF_DPRINTF_L2(cmlog, "ibcm_arp_link_driver: " 243 "vn_open('%s') failed\n", path); 244 return (error); 245 } 246 *dev_vp = vp; 247 248 dev_stp = vp->v_stream; 249 *q = dev_stp->sd_wrq; 250 251 VN_HOLD(vp); 252 253 rq = RD(dev_stp->sd_wrq); 254 RD(rq)->q_ptr = WR(rq)->q_ptr = ib_s; 255 setq(rq, &ibcm_arp_lrinit, &ibcm_arp_lwinit, NULL, QMTSAFE, 256 SQ_CI|SQ_CO, B_FALSE); 257 258 return (0); 259 } 260 261 extern struct qinit strdata; 262 extern struct qinit stwdata; 263 264 /* 265 * Unlink ip, ibcm, icmp6 drivers 266 */ 267 /* ARGSUSED */ 268 static int 269 ibcm_arp_unlink_driver(queue_t **q, vnode_t **dev_vp) 270 { 271 vnode_t *vp = *dev_vp; 272 struct stdata *dev_stp = vp->v_stream; 273 queue_t *wrq, *rq; 274 int rc; 275 276 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_unlink_driver: Enter: 0x%p", q); 277 278 wrq = dev_stp->sd_wrq; 279 rq = RD(wrq); 280 281 disable_svc(rq); 282 wait_svc(rq); 283 flushq(rq, FLUSHALL); 284 flushq(WR(rq), FLUSHALL); 285 286 rq->q_ptr = wrq->q_ptr = dev_stp; 287 288 setq(rq, &strdata, &stwdata, NULL, QMTSAFE, SQ_CI|SQ_CO, B_TRUE); 289 290 if ((rc = VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL)) != 0) { 291 IBTF_DPRINTF_L2(cmlog, "ibcm_arp_unlink_driver: VOP_CLOSE " 292 "failed %d\n", rc); 293 } 294 VN_RELE(vp); 295 296 return (0); 297 } 298 299 static int 300 ibcm_arp_unlink_drivers(ibcm_arp_streams_t *ib_s) 301 { 302 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_unlink_drivers(%p)", ib_s); 303 304 if (ib_s->arpqueue) { 305 (void) ibcm_arp_unlink_driver(&ib_s->arpqueue, &ib_s->arp_vp); 306 } 307 308 return (0); 309 } 310 311 /* 312 * Link ip, ibtl drivers below ibtl 313 */ 314 static int 315 ibcm_arp_link_drivers(ibcm_arp_streams_t *ib_s) 316 { 317 int rc; 318 319 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_link_drivers(%p)", ib_s); 320 321 if ((rc = ibcm_arp_link_driver(ib_s, "/dev/arp", &ib_s->arpqueue, 322 &ib_s->arp_vp)) != 0) { 323 IBTF_DPRINTF_L2(cmlog, "ibcm_arp_link_drivers: " 324 "ibcm_arp_link_driver failed: %d\n", rc); 325 return (rc); 326 } 327 328 return (0); 329 } 330 331 ibt_status_t 332 ibcm_arp_get_ibaddr(ipaddr_t srcip, ipaddr_t destip, ib_gid_t *sgid, 333 ib_gid_t *dgid) 334 { 335 ibcm_arp_streams_t *ib_s; 336 ibt_ip_addr_t srcaddr, destaddr; 337 int ret = 0; 338 339 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr(%lX, %lX, %p, %p)", 340 htonl(srcip), htonl(destip), sgid, dgid); 341 342 ib_s = (ibcm_arp_streams_t *)kmem_zalloc(sizeof (ibcm_arp_streams_t), 343 KM_SLEEP); 344 345 mutex_init(&ib_s->lock, NULL, MUTEX_DEFAULT, NULL); 346 cv_init(&ib_s->cv, NULL, CV_DRIVER, NULL); 347 348 ret = ibcm_arp_link_drivers(ib_s); 349 if (ret != 0) { 350 IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: " 351 "ibcm_arp_link_drivers failed %d", ret); 352 goto arp_ibaddr_error; 353 } 354 355 bzero(&destaddr, sizeof (ibt_ip_addr_t)); 356 bzero(&srcaddr, sizeof (ibt_ip_addr_t)); 357 358 mutex_enter(&ib_s->lock); 359 ib_s->done = B_FALSE; 360 mutex_exit(&ib_s->lock); 361 362 destaddr.family = AF_INET_OFFLOAD; 363 destaddr.un.ip4addr = destip; 364 srcaddr.family = AF_INET_OFFLOAD; 365 srcaddr.un.ip4addr = srcip; 366 367 IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: SrcIP %lX, DstIP %lX", 368 srcaddr.un.ip4addr, destaddr.un.ip4addr); 369 ret = ibcm_arp_pr_lookup(ib_s, &destaddr, &srcaddr, 0, NULL, 370 ibcm_arp_get_ibaddr_cb); 371 372 IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibaddr: ibcm_arp_pr_lookup " 373 "returned: %d", ret); 374 if (ret == 0) { 375 mutex_enter(&ib_s->lock); 376 while (ib_s->done != B_TRUE) 377 cv_wait(&ib_s->cv, &ib_s->lock); 378 mutex_exit(&ib_s->lock); 379 } 380 381 (void) ibcm_arp_unlink_drivers(ib_s); 382 mutex_enter(&ib_s->lock); 383 ret = ib_s->status; 384 if (ret == 0) { 385 ibcm_arp_prwqn_t *wqnp = ib_s->wqnp; 386 if (sgid) 387 *sgid = ib_s->wqnp->sgid; 388 if (dgid) 389 *dgid = ib_s->wqnp->dgid; 390 391 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibaddr: SGID: %llX:%llX" 392 " DGID: %llX:%llX", 393 ib_s->wqnp->sgid.gid_prefix, ib_s->wqnp->sgid.gid_guid, 394 ib_s->wqnp->dgid.gid_prefix, ib_s->wqnp->dgid.gid_guid); 395 396 mutex_exit(&ib_s->lock); 397 ibcm_arp_prwqn_delete(wqnp); 398 mutex_enter(&ib_s->lock); 399 } 400 mutex_exit(&ib_s->lock); 401 402 arp_ibaddr_error: 403 404 mutex_destroy(&ib_s->lock); 405 cv_destroy(&ib_s->cv); 406 kmem_free(ib_s, sizeof (ibcm_arp_streams_t)); 407 408 if (ret) 409 return (IBT_FAILURE); 410 else 411 return (IBT_SUCCESS); 412 } 413 414 415 /* 416 * Routine to get list of "local" IP-ADDR to GID/P_KEY mapping information. 417 * Optionally, if "gid" and/or "p_key" info are specified, then retrieve the 418 * IP-ADDR info for that attribute only. 419 */ 420 421 static ibcm_arp_ip_t * 422 ibcm_arp_ibd_gid2mac(ib_gid_t *gid, ib_pkey_t pkey, ibcm_arp_ibd_insts_t *ibdp) 423 { 424 ibcm_arp_ip_t *ipp; 425 int i; 426 427 for (i = 0, ipp = ibdp->ibcm_arp_ip; i < ibdp->ibcm_arp_ibd_cnt; 428 i++, ipp++) { 429 if ((ipp->ip_port_gid.gid_prefix == gid->gid_prefix) && 430 (ipp->ip_port_gid.gid_guid == gid->gid_guid)) { 431 if (pkey) { 432 if (ipp->ip_pkey == pkey) 433 return (ipp); 434 else 435 continue; 436 } 437 return (ipp); 438 } 439 } 440 return (NULL); 441 } 442 443 static ibt_status_t 444 ibcm_arp_ibd_mac2gid(ibcm_arp_ibd_insts_t *ibdp, ipaddr_t srcip, 445 ib_gid_t *sgid) 446 { 447 ibcm_arp_ip_t *ipp; 448 int i; 449 450 for (i = 0, ipp = ibdp->ibcm_arp_ip; i < ibdp->ibcm_arp_ibd_cnt; 451 i++, ipp++) { 452 453 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_ibd_mac2gid: Is %lX == %lX " 454 "GID %llX:%llX", srcip, ipp->ip_cm_sin.sin_addr, 455 ipp->ip_port_gid.gid_prefix, ipp->ip_port_gid.gid_guid); 456 457 if (bcmp(&srcip, &ipp->ip_cm_sin.sin_addr, sizeof (in_addr_t)) 458 == 0) { 459 *sgid = ipp->ip_port_gid; 460 461 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_ibd_mac2gid: Found " 462 "GID %llX:%llX", sgid->gid_prefix, sgid->gid_guid); 463 return (IBT_SUCCESS); 464 } 465 } 466 IBTF_DPRINTF_L3(cmlog, "ibcm_arp_ibd_mac2gid: Matching SRC info " 467 "NOT Found"); 468 return (IBT_SRC_IP_NOT_FOUND); 469 } 470 471 static int 472 ibcm_arp_get_ibd_insts_cb(dev_info_t *dip, void *arg) 473 { 474 ibcm_arp_ibd_insts_t *ibds = (ibcm_arp_ibd_insts_t *)arg; 475 ibcm_arp_ip_t *ipp; 476 ib_pkey_t pkey; 477 uint8_t port; 478 ib_guid_t hca_guid; 479 ib_gid_t port_gid; 480 481 if (i_ddi_devi_attached(dip) && 482 (strcmp(ddi_node_name(dip), "ibport") == 0) && 483 (strstr(ddi_get_name_addr(dip), "ipib") != NULL)) { 484 485 if (ibds->ibcm_arp_ibd_cnt >= ibds->ibcm_arp_ibd_alloc) { 486 ibcm_arp_ip_t *tmp = NULL; 487 uint8_t new_count; 488 489 new_count = ibds->ibcm_arp_ibd_alloc + 490 IBCM_ARP_IBD_INSTANCES; 491 492 tmp = (ibcm_arp_ip_t *)kmem_zalloc( 493 new_count * sizeof (ibcm_arp_ip_t), KM_SLEEP); 494 bcopy(ibds->ibcm_arp_ip, tmp, 495 ibds->ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t)); 496 kmem_free(ibds->ibcm_arp_ip, 497 ibds->ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t)); 498 ibds->ibcm_arp_ibd_alloc = new_count; 499 ibds->ibcm_arp_ip = tmp; 500 } 501 502 if (((hca_guid = ddi_prop_get_int64(DDI_DEV_T_ANY, dip, 0, 503 "hca-guid", 0)) == 0) || 504 ((port = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 505 "port-number", 0)) == 0) || 506 (ibt_get_port_state_byguid(hca_guid, port, &port_gid, 507 NULL) != IBT_SUCCESS) || 508 ((pkey = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 509 "port-pkey", IB_PKEY_INVALID_LIMITED)) <= 510 IB_PKEY_INVALID_FULL)) { 511 return (DDI_WALK_CONTINUE); 512 } 513 514 ipp = &ibds->ibcm_arp_ip[ibds->ibcm_arp_ibd_cnt]; 515 ipp->ip_inst = ddi_get_instance(dip); 516 ipp->ip_pkey = pkey; 517 ipp->ip_hca_guid = hca_guid; 518 ipp->ip_port_gid = port_gid; 519 ibds->ibcm_arp_ibd_cnt++; 520 } 521 return (DDI_WALK_CONTINUE); 522 } 523 524 static void 525 ibcm_arp_get_ibd_insts(ibcm_arp_ibd_insts_t *ibds) 526 { 527 ddi_walk_devs(ddi_root_node(), ibcm_arp_get_ibd_insts_cb, ibds); 528 } 529 530 /* 531 * Return ibd interfaces and ibd instances. 532 */ 533 static int 534 ibcm_arp_get_ibd_ipaddr(ibcm_arp_ibd_insts_t *ibds) 535 { 536 TIUSER *tiptr; 537 vnode_t *kvp; 538 vnode_t *vp = NULL; 539 struct strioctl iocb; 540 struct lifreq lif_req; 541 int k, ip_cnt; 542 ibcm_arp_ip_t *ipp; 543 544 if (lookupname("/dev/udp", UIO_SYSSPACE, FOLLOW, NULLVPP, &kvp) == 0) { 545 if (t_kopen((file_t *)NULL, kvp->v_rdev, FREAD|FWRITE, 546 &tiptr, CRED()) == 0) { 547 vp = tiptr->fp->f_vnode; 548 } else { 549 VN_RELE(kvp); 550 } 551 } 552 553 if (vp == NULL) 554 return (-1); 555 556 /* Get ibd ip's */ 557 ip_cnt = 0; 558 for (k = 0, ipp = ibds->ibcm_arp_ip; k < ibds->ibcm_arp_ibd_cnt; 559 k++, ipp++) { 560 561 (void) bzero((void *)&lif_req, sizeof (struct lifreq)); 562 (void) snprintf(lif_req.lifr_name, sizeof (lif_req.lifr_name), 563 "%s%d", IBCM_ARP_IBD_NAME, ipp->ip_inst); 564 565 (void) bzero((void *)&iocb, sizeof (struct strioctl)); 566 iocb.ic_cmd = SIOCGLIFADDR; 567 iocb.ic_timout = 0; 568 iocb.ic_len = sizeof (struct lifreq); 569 iocb.ic_dp = (caddr_t)&lif_req; 570 571 if (kstr_ioctl(vp, I_STR, (intptr_t)&iocb) == 0) { 572 ipp->ip_inet_family = AF_INET; 573 bcopy(&lif_req.lifr_addr, &ipp->ip_cm_sin, 574 sizeof (struct sockaddr_in)); 575 ip_cnt++; 576 continue; 577 } 578 } 579 580 (void) t_kclose(tiptr, 0); 581 VN_RELE(kvp); 582 583 if (ip_cnt == 0) 584 return (-1); 585 else 586 return (0); 587 } 588 589 ibt_status_t 590 ibcm_arp_get_ibds(ibcm_arp_ibd_insts_t *ibdp) 591 { 592 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_ibds(%p)", ibdp); 593 594 ibcm_arp_get_ibd_insts(ibdp); 595 596 IBTF_DPRINTF_L3(cmlog, "ibcm_arp_get_ibds: Found %d ibd instances", 597 ibdp->ibcm_arp_ibd_cnt); 598 599 if (ibdp->ibcm_arp_ibd_cnt == 0) 600 return (IBT_SRC_IP_NOT_FOUND); 601 602 /* Get the IP addresses of active ports. */ 603 if (ibcm_arp_get_ibd_ipaddr(ibdp) != 0) { 604 IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_ibds: failed to get " 605 "ibd instance: IBT_SRC_IP_NOT_FOUND"); 606 return (IBT_SRC_IP_NOT_FOUND); 607 } 608 609 return (IBT_SUCCESS); 610 } 611 612 _NOTE(SCHEME_PROTECTS_DATA("Unshared data", ibtl_cm_port_list_t)) 613 614 ibt_status_t 615 ibcm_arp_get_srcip_plist(ibt_ip_path_attr_t *ipattr, ibt_path_flags_t flags, 616 ibtl_cm_port_list_t **port_list_p) 617 { 618 ibt_path_attr_t attr; 619 ibt_status_t ret; 620 ibcm_arp_ibd_insts_t ibds; 621 ibcm_arp_ip_t *ipp; 622 ibtl_cm_port_list_t *plistp; 623 ib_gid_t sgid; 624 625 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist(%p, %llX)", 626 ipattr, flags); 627 628 sgid.gid_prefix = sgid.gid_guid = 0; 629 bzero(&ibds, sizeof (ibcm_arp_ibd_insts_t)); 630 ibds.ibcm_arp_ibd_alloc = IBCM_ARP_IBD_INSTANCES; 631 ibds.ibcm_arp_ibd_cnt = 0; 632 ibds.ibcm_arp_ip = (ibcm_arp_ip_t *)kmem_zalloc( 633 ibds.ibcm_arp_ibd_alloc * sizeof (ibcm_arp_ip_t), KM_SLEEP); 634 635 ret = ibcm_arp_get_ibds(&ibds); 636 if (ret != IBT_SUCCESS) { 637 IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_srcip_plist: " 638 "ibcm_arp_get_ibds failed : 0x%x", ret); 639 goto srcip_plist_end; 640 } 641 642 if (ipattr->ipa_src_ip.family != AF_UNSPEC) { 643 ret = ibcm_arp_ibd_mac2gid(&ibds, 644 htonl(ipattr->ipa_src_ip.un.ip4addr), &sgid); 645 if (ret != IBT_SUCCESS) { 646 IBTF_DPRINTF_L2(cmlog, "ibcm_arp_get_srcip_plist: " 647 "SGID for the specified SRCIP Not found %X", ret); 648 goto srcip_plist_end; 649 } 650 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist: SGID " 651 "%llX:%llX", sgid.gid_prefix, sgid.gid_guid); 652 } 653 654 bzero(&attr, sizeof (ibt_path_attr_t)); 655 attr.pa_hca_guid = ipattr->ipa_hca_guid; 656 attr.pa_hca_port_num = ipattr->ipa_hca_port_num; 657 attr.pa_sgid = sgid; 658 bcopy(&ipattr->ipa_mtu, &attr.pa_mtu, sizeof (ibt_mtu_req_t)); 659 bcopy(&ipattr->ipa_srate, &attr.pa_srate, sizeof (ibt_srate_req_t)); 660 bcopy(&ipattr->ipa_pkt_lt, &attr.pa_pkt_lt, sizeof (ibt_pkt_lt_req_t)); 661 662 ret = ibtl_cm_get_active_plist(&attr, flags, port_list_p); 663 if (ret == IBT_SUCCESS) { 664 int i; 665 uint8_t cnt; 666 boolean_t no_srcip_configured = B_FALSE; 667 uint8_t no_srcip_cnt = 0; 668 669 plistp = port_list_p[0]; 670 cnt = plistp->p_count; 671 for (i = 0; i < cnt; i++, plistp++) { 672 ipp = ibcm_arp_ibd_gid2mac(&plistp->p_sgid, 0, &ibds); 673 if ((ipp == NULL) || 674 (ipp->ip_inet_family == AF_UNSPEC)) { 675 plistp->p_src_ip.family = AF_UNSPEC; 676 no_srcip_configured = B_TRUE; 677 no_srcip_cnt++; 678 IBTF_DPRINTF_L3(cmlog, 679 "ibcm_arp_get_srcip_plist: SrcIP NOT " 680 "Configured for GID %llX:%llX", 681 plistp->p_sgid.gid_prefix, 682 plistp->p_sgid.gid_guid); 683 } else { 684 IBTF_DPRINTF_L4(cmlog, 685 "ibcm_arp_get_srcip_plist: GID %llX:%llX", 686 plistp->p_sgid.gid_prefix, 687 plistp->p_sgid.gid_guid); 688 if (ipp->ip_inet_family == AF_INET) { 689 plistp->p_src_ip.family = AF_INET; 690 bcopy(&ipp->ip_cm_sin.sin_addr, 691 &plistp->p_src_ip.un.ip4addr, 692 sizeof (in_addr_t)); 693 694 IBTF_DPRINTF_L4(cmlog, 695 "ibcm_arp_get_srcip_plist: SrcIP: " 696 "%lX", plistp->p_src_ip.un.ip4addr); 697 } else if (ipp->ip_inet_family == AF_INET6) { 698 plistp->p_src_ip.family = AF_INET6; 699 bcopy(&ipp->ip_cm_sin6.sin6_addr, 700 &plistp->p_src_ip.un.ip6addr, 701 sizeof (in6_addr_t)); 702 } 703 } 704 } 705 if (no_srcip_configured == B_TRUE) { 706 ibtl_cm_port_list_t *n_plistp, *tmp_n_plistp; 707 uint8_t new_cnt; 708 709 new_cnt = cnt - no_srcip_cnt; 710 711 /* 712 * Looks like some of the SRC GID we found have no 713 * IP ADDR configured, so remove these entries from 714 * our list. 715 */ 716 plistp = port_list_p[0]; 717 IBTF_DPRINTF_L4(cmlog, "ibcm_arp_get_srcip_plist: " 718 "Only %d SGID (%d/%d) have SrcIP Configured", 719 new_cnt, no_srcip_cnt, cnt); 720 if (new_cnt) { 721 /* Allocate Memory to hold Src Point info. */ 722 n_plistp = kmem_zalloc(new_cnt * 723 sizeof (ibtl_cm_port_list_t), KM_SLEEP); 724 725 tmp_n_plistp = n_plistp; 726 for (i = 0; i < cnt; i++, plistp++) { 727 if (plistp->p_src_ip.family == 728 AF_UNSPEC) 729 continue; 730 731 bcopy(plistp, n_plistp, 732 sizeof (ibtl_cm_port_list_t)); 733 n_plistp->p_count = new_cnt; 734 n_plistp++; 735 } 736 plistp = port_list_p[0]; 737 *port_list_p = tmp_n_plistp; 738 } else { 739 /* 740 * All entries we have, do not have IP-Addr 741 * configured so return empty hand. 742 */ 743 IBTF_DPRINTF_L2(cmlog, 744 "ibcm_arp_get_srcip_plist: None of SGID " 745 "found have SrcIP Configured"); 746 *port_list_p = NULL; 747 ret = IBT_SRC_IP_NOT_FOUND; 748 } 749 IBTF_DPRINTF_L4(cmlog, "FREE OLD list %p, NEW list is " 750 "%p - %p", plistp, port_list_p, *port_list_p); 751 kmem_free(plistp, cnt * sizeof (ibtl_cm_port_list_t)); 752 } 753 } 754 755 srcip_plist_end: 756 if (ibds.ibcm_arp_ip) 757 kmem_free(ibds.ibcm_arp_ip, ibds.ibcm_arp_ibd_alloc * 758 sizeof (ibcm_arp_ip_t)); 759 760 return (ret); 761 } 762 /* Routines for warlock */ 763 764 /* ARGSUSED */ 765 static int 766 ibcm_arp_dummy_ibaddr_hdl(void *arg, int status) 767 { 768 ibcm_arp_prwqn_t dummy_wqn1; 769 ibcm_arp_prwqn_t dummy_wqn2; 770 771 dummy_wqn1.func = ibcm_arp_get_ibaddr_cb; 772 dummy_wqn2.func = ibcm_arp_dummy_ibaddr_hdl; 773 774 IBTF_DPRINTF_L5(cmlog, "ibcm_arp_dummy_ibaddr_hdl: " 775 "dummy_wqn1.func %p %p", dummy_wqn1.func, dummy_wqn2.func); 776 777 return (0); 778 } 779