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