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 (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <stdio.h> 26 #include <libdevinfo.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <string.h> 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <stropts.h> 33 #include <stdlib.h> 34 #include <errno.h> 35 #include <strings.h> 36 #include <libintl.h> 37 #include <net/if_types.h> 38 #include <net/if_dl.h> 39 #include <sys/dld.h> 40 #include <sys/ib/ib_types.h> 41 #include <sys/ibpart.h> 42 #include <libdllink.h> 43 #include <libdladm.h> 44 #include <libdlib.h> 45 #include <libdladm_impl.h> 46 47 /* 48 * IP over IB administration API; see PSARC/2010/085 49 */ 50 51 /* 52 * Function prototypes 53 */ 54 dladm_status_t dladm_part_create(dladm_handle_t, datalink_id_t, ib_pkey_t, 55 uint32_t, char *, datalink_id_t *, dladm_arg_list_t *); 56 static int dladm_ibd_get_instance(char *); 57 static dladm_status_t i_dladm_part_create(dladm_handle_t, 58 dladm_part_attr_t *); 59 dladm_status_t dladm_part_persist_conf(dladm_handle_t, dladm_part_attr_t *); 60 static dladm_status_t i_dladm_part_delete(dladm_handle_t, datalink_id_t); 61 dladm_status_t dladm_part_delete(dladm_handle_t, datalink_id_t, int); 62 static int i_dladm_part_up(dladm_handle_t, datalink_id_t, void *); 63 dladm_status_t dladm_part_up(dladm_handle_t, datalink_id_t, uint32_t); 64 65 /* 66 * Convert a error status returned by the IP over IB kernel driver to a 67 * valid dladm status. 68 */ 69 static dladm_status_t 70 dladm_ib_ioctl_err2status(int err) 71 { 72 switch (err) { 73 case 0: 74 return (DLADM_STATUS_OK); 75 case IBD_INVALID_PORT_INST: 76 return (DLADM_STATUS_INVALID_PORT_INSTANCE); 77 case IBD_PORT_IS_DOWN: 78 return (DLADM_STATUS_PORT_IS_DOWN); 79 case IBD_PKEY_NOT_PRESENT: 80 return (DLADM_STATUS_PKEY_NOT_PRESENT); 81 case IBD_PARTITION_EXISTS: 82 return (DLADM_STATUS_PARTITION_EXISTS); 83 case IBD_INVALID_PKEY: 84 return (DLADM_STATUS_INVALID_PKEY); 85 case IBD_NO_HW_RESOURCE: 86 return (DLADM_STATUS_NO_IB_HW_RESOURCE); 87 case IBD_INVALID_PKEY_TBL_SIZE: 88 return (DLADM_STATUS_INVALID_PKEY_TBL_SIZE); 89 default: 90 return (DLADM_STATUS_FAILED); 91 } 92 } 93 94 static dladm_status_t 95 i_dladm_ib_ioctl(dladm_handle_t handle, int ioccmd, ibd_ioctl_t *iocp) 96 { 97 if (ioctl(dladm_dld_fd(handle), ioccmd, iocp) == 0) 98 return (DLADM_STATUS_OK); 99 100 if (iocp->ioc_status == 0) 101 return (dladm_errno2status(errno)); 102 103 return (dladm_ib_ioctl_err2status(iocp->ioc_status)); 104 } 105 106 /* 107 * Get the active configuration information for the partition given by 108 * the 'linkid'. 109 */ 110 static dladm_status_t 111 i_dladm_part_info_active(dladm_handle_t handle, datalink_id_t linkid, 112 dladm_part_attr_t *attrp) 113 { 114 ibpart_ioctl_t ioc; 115 dladm_status_t status = DLADM_STATUS_OK; 116 117 bzero(&ioc, sizeof (ioc)); 118 bzero(attrp, sizeof (*attrp)); 119 /* 120 * The ioc_linkid here will contain the data link id of the IB partition 121 * object. 122 */ 123 ioc.ibdioc.ioc_linkid = linkid; 124 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPART; 125 126 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); 127 if (status != DLADM_STATUS_OK) 128 goto bail; 129 130 /* 131 * On return from the ioctl ioc_linkid field contains the IB port's 132 * linkid. 133 */ 134 attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid; 135 attrp->dia_partlinkid = ioc.ioc_partid; 136 attrp->dia_pkey = ioc.ioc_pkey; 137 attrp->dia_portnum = ioc.ibdioc.ioc_portnum; 138 attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid; 139 attrp->dia_port_guid = ioc.ibdioc.ioc_portguid; 140 attrp->dia_instance = ioc.ibdioc.ioc_port_inst; 141 142 /* 143 * If the IP over IB driver reports that this partition was created 144 * forcibly, then set the force create flag. 145 */ 146 if (ioc.ioc_force_create) 147 attrp->dia_flags |= DLADM_IBPART_FORCE_CREATE; 148 149 bail: 150 return (status); 151 } 152 153 /* 154 * Get the configuration information about the IB partition 'linkid' from the 155 * persistent configuration. 156 */ 157 static dladm_status_t 158 i_dladm_part_info_persist(dladm_handle_t handle, datalink_id_t linkid, 159 dladm_part_attr_t *attrp) 160 { 161 dladm_conf_t conf; 162 dladm_status_t status; 163 char linkover[MAXLINKNAMELEN]; 164 datalink_class_t class; 165 boolean_t force = B_FALSE; 166 167 /* Get the IB partition's datalink ID */ 168 if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class, 169 NULL, NULL, 0)) != DLADM_STATUS_OK) 170 goto done; 171 172 bzero(attrp, sizeof (*attrp)); 173 attrp->dia_partlinkid = linkid; 174 if ((status = dladm_read_conf(handle, linkid, &conf)) != 175 DLADM_STATUS_OK) 176 return (status); 177 178 /* 179 * Get the name of the IB Phys link over which IB partition was 180 * created. 181 */ 182 status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, 183 sizeof (linkover)); 184 if (status != DLADM_STATUS_OK) { 185 attrp->dia_physlinkid = DATALINK_INVALID_LINKID; 186 goto done; 187 } else { 188 /* Get the IB Phys link's datalink ID */ 189 if ((status = dladm_name2info(handle, linkover, 190 &attrp->dia_physlinkid, NULL, NULL, NULL)) != 191 DLADM_STATUS_OK) 192 goto done; 193 } 194 195 /* Get the IB partition's P_Key */ 196 status = dladm_get_conf_field(handle, conf, FPORTPKEY, 197 &attrp->dia_pkey, sizeof (uint64_t)); 198 if (status != DLADM_STATUS_OK) 199 goto done; 200 201 if (class != DATALINK_CLASS_PART) { 202 status = DLADM_STATUS_BADARG; 203 goto done; 204 } 205 206 /* 207 * If the FFORCE field is set in the persistent configuration database 208 * set the force create flag in the partition attributes. 209 */ 210 status = dladm_get_conf_field(handle, conf, FFORCE, &force, 211 sizeof (boolean_t)); 212 if (status != DLADM_STATUS_OK) { 213 if (status != DLADM_STATUS_NOTFOUND) 214 goto done; 215 } else if (force == B_TRUE) { 216 attrp->dia_flags |= DLADM_IBPART_FORCE_CREATE; 217 } 218 219 status = DLADM_STATUS_OK; 220 done: 221 dladm_destroy_conf(handle, conf); 222 return (status); 223 } 224 225 /* 226 * Get the configuration information for the IB partition given by the datalink 227 * ID 'linkid'. Based on the 'flags' field the information is either from the 228 * active system (DLADM_OPT_ACTIVE) or from the persistent configuration 229 * database. 230 */ 231 dladm_status_t 232 dladm_part_info(dladm_handle_t handle, datalink_id_t linkid, 233 dladm_part_attr_t *attrp, uint32_t flags) 234 { 235 if (flags == DLADM_OPT_ACTIVE) 236 return (i_dladm_part_info_active(handle, linkid, attrp)); 237 else if (flags == DLADM_OPT_PERSIST) 238 return (i_dladm_part_info_persist(handle, linkid, attrp)); 239 else 240 return (DLADM_STATUS_BADARG); 241 } 242 243 /* 244 * Get the configuration information for the IB Phys link given by the datalink 245 * ID 'linkid'. 246 */ 247 /* ARGSUSED */ 248 dladm_status_t 249 dladm_ib_info(dladm_handle_t handle, datalink_id_t linkid, 250 dladm_ib_attr_t *attrp, uint32_t flags) 251 { 252 int instance; 253 ibport_ioctl_t ioc; 254 dladm_phys_attr_t dpa; 255 dladm_status_t status = DLADM_STATUS_OK; 256 257 /* 258 * We need to get the device name of the IB Phys link to get the 259 * correct instance number of the IP over IB driver instance. 260 */ 261 if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE) 262 != DLADM_STATUS_OK) 263 return (DLADM_STATUS_BADARG); 264 265 /* 266 * Get the instance number of the IP over IB driver instance which 267 * represents this IB Phys link. 268 */ 269 instance = dladm_ibd_get_instance(dpa.dp_dev); 270 if (instance == -1) 271 return (DLADM_STATUS_FAILED); 272 273 bzero(&ioc, sizeof (ioc)); 274 /* 275 * The ioc_linkid here will contain IB port linkid here. We make the 276 * first ioctl call to get the P_Key table size for this HCA port. 277 */ 278 ioc.ibdioc.ioc_linkid = linkid; 279 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_PKEYTBLSZ; 280 ioc.ioc_pkey_tbl_sz = 0; 281 ioc.ibdioc.ioc_port_inst = instance; 282 283 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); 284 if (status != DLADM_STATUS_OK) 285 return (status); 286 287 /* 288 * Now allocate the memory for the P_Key table based on the table size 289 * return by the ioctl. 290 */ 291 ioc.ioc_pkeys = calloc(sizeof (ib_pkey_t), ioc.ioc_pkey_tbl_sz); 292 if (ioc.ioc_pkeys == NULL) { 293 status = dladm_errno2status(errno); 294 goto bail; 295 } 296 297 /* 298 * Call the ioctl again to get the P_Key table and other IB Phys link 299 * attributes. 300 */ 301 ioc.ibdioc.ioc_linkid = linkid; 302 ioc.ibdioc.ioc_port_inst = instance; 303 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPORT; 304 305 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); 306 if (status != DLADM_STATUS_OK) 307 goto bail; 308 309 attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid; 310 attrp->dia_portnum = ioc.ibdioc.ioc_portnum; 311 attrp->dia_port_pkey_tbl_sz = ioc.ioc_pkey_tbl_sz; 312 attrp->dia_port_pkeys = ioc.ioc_pkeys; 313 attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid; 314 attrp->dia_port_guid = ioc.ibdioc.ioc_portguid; 315 attrp->dia_instance = ioc.ibdioc.ioc_port_inst; 316 return (status); 317 bail: 318 free(ioc.ioc_pkeys); 319 return (status); 320 } 321 322 /* 323 * Free the memory allocated for the IB HCA port's P_Key table by 324 * dladm_ib_info library call. 325 */ 326 void 327 dladm_free_ib_info(dladm_ib_attr_t *attr) 328 { 329 if (attr && attr->dia_port_pkeys) 330 free(attr->dia_port_pkeys); 331 } 332 333 /* 334 * Call into the IP over IB driver to create a partition object. 335 */ 336 static dladm_status_t 337 i_dladm_part_create(dladm_handle_t handle, dladm_part_attr_t *pattr) 338 { 339 ibpart_ioctl_t ioc; 340 dladm_status_t status = DLADM_STATUS_OK; 341 342 bzero(&ioc, sizeof (ioc)); 343 344 /* IB Physical datalink ID */ 345 ioc.ibdioc.ioc_linkid = pattr->dia_physlinkid; 346 /* IB Partition datalink ID */ 347 ioc.ioc_partid = pattr->dia_partlinkid; 348 ioc.ioc_pkey = pattr->dia_pkey; 349 ioc.ibdioc.ioc_port_inst = pattr->dia_instance; 350 ioc.ioc_force_create = ((pattr->dia_flags & DLADM_OPT_FORCE) 351 != 0); 352 353 status = i_dladm_ib_ioctl(handle, IBD_CREATE_IBPART, 354 (ibd_ioctl_t *)&ioc); 355 return (status); 356 } 357 358 /* 359 * Create an entry in the dladm persistent configuration database for the 360 * partition specified by pattr. 361 */ 362 dladm_status_t 363 dladm_part_persist_conf(dladm_handle_t handle, dladm_part_attr_t *pattr) 364 { 365 366 dladm_conf_t conf; 367 dladm_status_t status; 368 char linkover[MAXLINKNAMELEN]; 369 uint64_t u64; 370 371 status = dladm_create_conf(handle, pattr->dia_pname, 372 pattr->dia_partlinkid, DATALINK_CLASS_PART, DL_IB, &conf); 373 374 if (status != DLADM_STATUS_OK) 375 return (status); 376 377 /* 378 * Get the name of the IB Phys link over which this partition was 379 * created. 380 */ 381 status = dladm_datalink_id2info(handle, pattr->dia_physlinkid, 382 NULL, NULL, NULL, linkover, sizeof (linkover)); 383 if (status != DLADM_STATUS_OK) 384 return (status); 385 386 /* Store IB Phys link name (linkover) */ 387 status = dladm_set_conf_field(handle, conf, FLINKOVER, DLADM_TYPE_STR, 388 linkover); 389 if (status != DLADM_STATUS_OK) 390 return (status); 391 392 u64 = pattr->dia_pkey; 393 394 /* Store the IB Partitions P_Key */ 395 status = dladm_set_conf_field(handle, conf, FPORTPKEY, 396 DLADM_TYPE_UINT64, &u64); 397 if (status != DLADM_STATUS_OK) 398 return (status); 399 400 if (pattr->dia_flags & DLADM_OPT_FORCE) { 401 boolean_t force = B_TRUE; 402 /* Store the force create flag. */ 403 status = dladm_set_conf_field(handle, conf, FFORCE, 404 DLADM_TYPE_BOOLEAN, &force); 405 if (status != DLADM_STATUS_OK) 406 goto done; 407 } 408 409 status = dladm_write_conf(handle, conf); 410 if (status != DLADM_STATUS_OK) 411 return (status); 412 413 dladm_destroy_conf(handle, conf); 414 done: 415 return (status); 416 } 417 418 /* 419 * Create a new IB Partition datalink of name 'pname' over the IB Physical link 420 * given in 'physlinkid' with the P_key 'pkey' and return the datalink ID in 421 * 'partlinkid'. If the 'force' option is set in the 'flags' argument, the 422 * partition will be created even if the P_Key 'pkey' does not exist or if the 423 * HCA port represented by the IB Phys link is down. If the 'temporary' flag is 424 * set, then the configuration information is not added to the persistent 425 * database. 426 */ 427 dladm_status_t 428 dladm_part_create(dladm_handle_t handle, datalink_id_t physlinkid, 429 ib_pkey_t pkey, uint32_t flags, char *pname, datalink_id_t *partlinkid, 430 dladm_arg_list_t *proplist) 431 { 432 int i; 433 dladm_status_t status; 434 uint_t media; 435 boolean_t part_created = B_FALSE; 436 boolean_t conf_set = B_FALSE; 437 dladm_phys_attr_t dpa; 438 dladm_part_attr_t pattr; 439 440 pattr.dia_pkey = pkey; 441 pattr.dia_physlinkid = physlinkid; /* IB Phys link's datalink id */ 442 pattr.dia_flags = flags; 443 pattr.dia_pname = pname; 444 445 flags &= ~DLADM_OPT_FORCE; 446 447 /* 448 * Check whether the PKEY is valid. If not, return immediately 449 * Only full members are allowed as per the IPoIB specification 450 */ 451 if (pattr.dia_pkey <= IB_PKEY_INVALID_FULL) 452 return (DLADM_STATUS_INVALID_PKEY); 453 454 /* 455 * Get the media type of the Phys link datalink ID provided and 456 * make sure that it is Infiniband media DL_IB) 457 */ 458 if ((status = dladm_datalink_id2info(handle, pattr.dia_physlinkid, NULL, 459 NULL, &media, NULL, 0)) != DLADM_STATUS_OK) 460 return (status); 461 462 if (media != DL_IB) 463 return (dladm_errno2status(ENOTSUP)); 464 465 /* 466 * Get the instance number of the IP over IB driver instance which the 467 * IB Phys link 'physlinkid' over which we will be creating our IB 468 * partition. 469 */ 470 if ((status = dladm_phys_info(handle, pattr.dia_physlinkid, &dpa, 471 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) 472 return (status); 473 474 pattr.dia_instance = dladm_ibd_get_instance(dpa.dp_dev); 475 if (pattr.dia_instance == -1) 476 return (DLADM_STATUS_FAILED); 477 478 479 if ((status = dladm_create_datalink_id(handle, pattr.dia_pname, 480 DATALINK_CLASS_PART, DL_IB, flags, &pattr.dia_partlinkid)) != 481 DLADM_STATUS_OK) 482 return (status); 483 484 /* 485 * Create the IB partition object. 486 */ 487 status = i_dladm_part_create(handle, &pattr); 488 if (status != DLADM_STATUS_OK) 489 goto done; 490 491 part_created = B_TRUE; 492 493 /* 494 * If the persist flag is set then write this partition information 495 * to the persistent configuration. 496 */ 497 if (pattr.dia_flags & DLADM_OPT_PERSIST) { 498 status = dladm_part_persist_conf(handle, &pattr); 499 if (status != DLADM_STATUS_OK) 500 goto done; 501 conf_set = B_TRUE; 502 } 503 504 /* 505 * If the name-value pair list of properties were provided set those 506 * properties over the datalink. 507 */ 508 if (proplist != NULL) { 509 for (i = 0; i < proplist->al_count; i++) { 510 dladm_arg_info_t *aip = &proplist->al_info[i]; 511 512 status = dladm_set_linkprop(handle, 513 pattr.dia_partlinkid, aip->ai_name, aip->ai_val, 514 aip->ai_count, pattr.dia_flags); 515 if (status != DLADM_STATUS_OK) 516 break; 517 } 518 } 519 done: 520 if (status != DLADM_STATUS_OK) { 521 if (conf_set) 522 (void) dladm_remove_conf(handle, pattr.dia_partlinkid); 523 if (part_created) 524 (void) i_dladm_part_delete(handle, 525 pattr.dia_partlinkid); 526 (void) dladm_destroy_datalink_id(handle, pattr.dia_partlinkid, 527 flags); 528 } 529 530 if (partlinkid != NULL) 531 *partlinkid = pattr.dia_partlinkid; 532 533 return (status); 534 } 535 536 /* 537 * Call into the IP over IB driver to delete the IB partition and free up all 538 * the resources allocated for it. 539 */ 540 static dladm_status_t 541 i_dladm_part_delete(dladm_handle_t handle, datalink_id_t partid) 542 { 543 ibpart_ioctl_t ioc; 544 dladm_status_t status = DLADM_STATUS_OK; 545 546 bzero(&ioc, sizeof (ioc)); 547 ioc.ioc_partid = partid; 548 status = i_dladm_ib_ioctl(handle, IBD_DELETE_IBPART, 549 (ibd_ioctl_t *)&ioc); 550 return (status); 551 } 552 553 /* 554 * Delete an IB partition if 'flags' contains the active flag. Update the 555 * persistent configuration if 'flags' contains the persist flag. 556 */ 557 dladm_status_t 558 dladm_part_delete(dladm_handle_t handle, datalink_id_t partid, int flags) 559 { 560 dladm_status_t status = DLADM_STATUS_OK; 561 datalink_class_t class; 562 563 if (flags == 0) 564 return (DLADM_STATUS_BADARG); 565 566 /* 567 * Make sure that the datalinkid provided is an IB partition class 568 * datalink ID. 569 */ 570 if ((dladm_datalink_id2info(handle, partid, NULL, &class, NULL, NULL, 0) 571 != DLADM_STATUS_OK)) 572 return (DLADM_STATUS_BADARG); 573 574 if (class != DATALINK_CLASS_PART) 575 return (DLADM_STATUS_BADARG); 576 577 if ((flags & DLADM_OPT_ACTIVE) != 0) { 578 status = i_dladm_part_delete(handle, partid); 579 if (status == DLADM_STATUS_OK) { 580 (void) dladm_set_linkprop(handle, partid, NULL, NULL, 0, 581 DLADM_OPT_ACTIVE); 582 (void) dladm_destroy_datalink_id(handle, partid, 583 DLADM_OPT_ACTIVE); 584 } else if (status != DLADM_STATUS_NOTFOUND || 585 !(flags & DLADM_OPT_PERSIST)) { 586 return (status); 587 } 588 } 589 590 if ((flags & DLADM_OPT_PERSIST) != 0) { 591 dladm_status_t db_status; 592 db_status = dladm_remove_conf(handle, partid); 593 594 /* 595 * A partition could have been temporarily deleted in which 596 * case the delete of the active partition above would have 597 * failed. In that case, we update the status to be returned 598 * to that of the status returned for deleting the persistent 599 * database entry. 600 */ 601 if (status == DLADM_STATUS_NOTFOUND) 602 status = db_status; 603 604 (void) dladm_destroy_datalink_id(handle, partid, 605 DLADM_OPT_PERSIST); 606 } 607 608 return (status); 609 } 610 611 /* 612 * Call into the IP over IB driver to create the active instances of one or all 613 * IB partitions present in the persistent configuration. 614 */ 615 /* ARGSUSED */ 616 static int 617 i_dladm_part_up(dladm_handle_t handle, datalink_id_t plinkid, void *arg) 618 { 619 dladm_conf_t conf; 620 datalink_id_t linkid; 621 ib_pkey_t pkey; 622 uint64_t u64; 623 char linkover[MAXLINKNAMELEN]; 624 dladm_status_t status; 625 dladm_phys_attr_t dpa; 626 dladm_part_attr_t pattr; 627 628 /* 629 * plinkid is the IB partition datalink's ID. Get an handle to the 630 * persistent configuration entry for this datalink ID. If this datalink 631 * ID is not present in the persistent configuration return. 632 */ 633 if ((status = dladm_read_conf(handle, plinkid, &conf)) != 634 DLADM_STATUS_OK) 635 return (status); 636 637 /* 638 * Get the name of the IB Phys link over which this partition was 639 * created. 640 */ 641 status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, 642 sizeof (linkover)); 643 if (status != DLADM_STATUS_OK) 644 goto done; 645 646 if ((status = dladm_name2info(handle, linkover, &linkid, NULL, NULL, 647 NULL)) != DLADM_STATUS_OK) 648 goto done; 649 650 /* 651 * Get the phys attribute of the IB Phys link to get the device name 652 * associated with the phys link. We need this to get the IP over IB 653 * driver instance number. 654 */ 655 if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE) 656 != DLADM_STATUS_OK) 657 goto done; 658 659 /* Get the IB partition's P_key */ 660 status = dladm_get_conf_field(handle, conf, FPORTPKEY, &u64, 661 sizeof (u64)); 662 if (status != DLADM_STATUS_OK) 663 goto done; 664 665 pkey = (ib_pkey_t)u64; 666 667 /* 668 * We always set the force flag during dladm_part_up because we want 669 * the partition creation to succeed even if the IB HCA port over which 670 * the partition is being created is still down. Since dladm_part_up 671 * is usually invoked during early boot sequence, it is possible under 672 * some IB subnet configurations for dladm_up_part to be called before 673 * the IB link negotiation is completed and port state is set to active 674 * and P_Key table is updated. 675 */ 676 pattr.dia_flags = DLADM_OPT_FORCE | DLADM_OPT_ACTIVE | 677 DLADM_OPT_PERSIST; 678 /* IB Phys link's datalink ID. */ 679 pattr.dia_physlinkid = linkid; 680 /* IB Partition's datalink ID. */ 681 pattr.dia_partlinkid = plinkid; 682 pattr.dia_pkey = pkey; 683 pattr.dia_instance = dladm_ibd_get_instance(dpa.dp_dev); 684 if (pattr.dia_instance == -1) 685 return (DLADM_WALK_CONTINUE); 686 687 /* Create the active IB Partition object. */ 688 if (i_dladm_part_create(handle, &pattr) == DLADM_STATUS_OK && 689 dladm_up_datalink_id(handle, plinkid) != DLADM_STATUS_OK) 690 (void) i_dladm_part_delete(handle, linkid); 691 692 done: 693 dladm_destroy_conf(handle, conf); 694 return (DLADM_WALK_CONTINUE); 695 } 696 697 /* 698 * Bring up one or all IB partition(s) present in the persistent configuration 699 * database. If we need to bring up one IB Partition, its datalink ID is 700 * provided in 'linkid'. 701 */ 702 /* ARGSUSED */ 703 dladm_status_t 704 dladm_part_up(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) 705 { 706 dladm_status_t status = DLADM_STATUS_OK; 707 708 if (linkid == DATALINK_ALL_LINKID) { 709 (void) dladm_walk_datalink_id(i_dladm_part_up, handle, 710 &status, DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, 711 DLADM_OPT_PERSIST); 712 return (DLADM_STATUS_OK); 713 } else { 714 (void) i_dladm_part_up(handle, linkid, &status); 715 return (status); 716 } 717 } 718 719 static int 720 dladm_ibd_get_instance(char *devname) 721 { 722 int instance; 723 724 /* 725 * The devname contains the driver name followed by the instance 726 * number. Lets just skip the driver name and get the instance. We use 727 * strlen of ibp here to get the driver name length. 728 */ 729 instance = atoi(devname + strlen("ibp")); 730 731 return (instance); 732 } 733