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