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