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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Utility functions used by the dlmgmtd daemon. 29 */ 30 31 #include <assert.h> 32 #include <pthread.h> 33 #include <stddef.h> 34 #include <stdlib.h> 35 #include <stdio.h> 36 #include <strings.h> 37 #include <syslog.h> 38 #include <stdarg.h> 39 #include <errno.h> 40 #include <libdlpi.h> 41 #include "dlmgmt_impl.h" 42 43 /* 44 * There are two datalink AVL tables. One table (dlmgmt_name_avl) is keyed by 45 * the link name, and the other (dlmgmt_id_avl) is keyed by the link id. 46 * Each link will be present in both tables. 47 */ 48 avl_tree_t dlmgmt_name_avl; 49 avl_tree_t dlmgmt_id_avl; 50 51 avl_tree_t dlmgmt_dlconf_avl; 52 53 static pthread_rwlock_t dlmgmt_avl_lock = PTHREAD_RWLOCK_INITIALIZER; 54 static pthread_mutex_t dlmgmt_avl_mutex = PTHREAD_MUTEX_INITIALIZER; 55 static pthread_cond_t dlmgmt_avl_cv = PTHREAD_COND_INITIALIZER; 56 static pthread_rwlock_t dlmgmt_dlconf_lock = PTHREAD_RWLOCK_INITIALIZER; 57 58 typedef struct dlmgmt_prefix { 59 struct dlmgmt_prefix *lp_next; 60 char lp_prefix[MAXLINKNAMELEN]; 61 uint_t lp_nextppa; 62 } dlmgmt_prefix_t; 63 static dlmgmt_prefix_t *dlmgmt_prefixlist; 64 65 static datalink_id_t dlmgmt_nextlinkid; 66 static datalink_id_t dlmgmt_nextconfid = 1; 67 68 static int linkattr_add(dlmgmt_linkattr_t **, 69 dlmgmt_linkattr_t *); 70 static int linkattr_rm(dlmgmt_linkattr_t **, 71 dlmgmt_linkattr_t *); 72 static int link_create(const char *, datalink_class_t, uint32_t, 73 uint32_t, dlmgmt_link_t **); 74 75 static void dlmgmt_advance_linkid(dlmgmt_link_t *); 76 static void dlmgmt_advance_ppa(dlmgmt_link_t *); 77 78 void 79 dlmgmt_log(int pri, const char *fmt, ...) 80 { 81 va_list alist; 82 83 va_start(alist, fmt); 84 if (debug) { 85 (void) vfprintf(stderr, fmt, alist); 86 (void) fputc('\n', stderr); 87 } else { 88 vsyslog(pri, fmt, alist); 89 } 90 va_end(alist); 91 } 92 93 static int 94 cmp_link_by_name(const void *v1, const void *v2) 95 { 96 const dlmgmt_link_t *link1 = v1; 97 const dlmgmt_link_t *link2 = v2; 98 int cmp; 99 100 cmp = strcmp(link1->ll_link, link2->ll_link); 101 return ((cmp == 0) ? 0 : ((cmp < 0) ? -1 : 1)); 102 } 103 104 static int 105 cmp_link_by_id(const void *v1, const void *v2) 106 { 107 const dlmgmt_link_t *link1 = v1; 108 const dlmgmt_link_t *link2 = v2; 109 110 if ((uint64_t)(link1->ll_linkid) == (uint64_t)(link2->ll_linkid)) 111 return (0); 112 else if ((uint64_t)(link1->ll_linkid) < (uint64_t)(link2->ll_linkid)) 113 return (-1); 114 else 115 return (1); 116 } 117 118 static int 119 cmp_dlconf_by_id(const void *v1, const void *v2) 120 { 121 const dlmgmt_dlconf_t *dlconfp1 = v1; 122 const dlmgmt_dlconf_t *dlconfp2 = v2; 123 124 if (dlconfp1->ld_id == dlconfp2->ld_id) 125 return (0); 126 else if (dlconfp1->ld_id < dlconfp2->ld_id) 127 return (-1); 128 else 129 return (1); 130 } 131 132 int 133 dlmgmt_linktable_init() 134 { 135 /* 136 * Initialize the prefix list. First add the "net" prefix to the list. 137 */ 138 dlmgmt_prefixlist = malloc(sizeof (dlmgmt_prefix_t)); 139 if (dlmgmt_prefixlist == NULL) { 140 dlmgmt_log(LOG_WARNING, "dlmgmt_linktable_init() failed: %s", 141 strerror(ENOMEM)); 142 return (ENOMEM); 143 } 144 145 dlmgmt_prefixlist->lp_next = NULL; 146 dlmgmt_prefixlist->lp_nextppa = 0; 147 (void) strlcpy(dlmgmt_prefixlist->lp_prefix, "net", MAXLINKNAMELEN); 148 149 avl_create(&dlmgmt_name_avl, cmp_link_by_name, sizeof (dlmgmt_link_t), 150 offsetof(dlmgmt_link_t, ll_node_by_name)); 151 avl_create(&dlmgmt_id_avl, cmp_link_by_id, sizeof (dlmgmt_link_t), 152 offsetof(dlmgmt_link_t, ll_node_by_id)); 153 avl_create(&dlmgmt_dlconf_avl, cmp_dlconf_by_id, 154 sizeof (dlmgmt_dlconf_t), offsetof(dlmgmt_dlconf_t, ld_node)); 155 dlmgmt_nextlinkid = 1; 156 return (0); 157 } 158 159 void 160 dlmgmt_linktable_fini() 161 { 162 dlmgmt_prefix_t *lpp, *next; 163 164 for (lpp = dlmgmt_prefixlist; lpp != NULL; lpp = next) { 165 next = lpp->lp_next; 166 free(lpp); 167 } 168 169 avl_destroy(&dlmgmt_dlconf_avl); 170 avl_destroy(&dlmgmt_name_avl); 171 avl_destroy(&dlmgmt_id_avl); 172 } 173 174 static int 175 linkattr_add(dlmgmt_linkattr_t **headp, dlmgmt_linkattr_t *attrp) 176 { 177 if (*headp == NULL) { 178 *headp = attrp; 179 } else { 180 (*headp)->lp_prev = attrp; 181 attrp->lp_next = *headp; 182 *headp = attrp; 183 } 184 return (0); 185 } 186 187 static int 188 linkattr_rm(dlmgmt_linkattr_t **headp, dlmgmt_linkattr_t *attrp) 189 { 190 dlmgmt_linkattr_t *next, *prev; 191 192 next = attrp->lp_next; 193 prev = attrp->lp_prev; 194 if (next != NULL) 195 next->lp_prev = prev; 196 if (prev != NULL) 197 prev->lp_next = next; 198 else 199 *headp = next; 200 201 return (0); 202 } 203 204 int 205 linkattr_set(dlmgmt_linkattr_t **headp, const char *attr, void *attrval, 206 size_t attrsz, dladm_datatype_t type) 207 { 208 dlmgmt_linkattr_t *attrp; 209 int err; 210 211 /* 212 * See whether the attr is already set. 213 */ 214 for (attrp = *headp; attrp != NULL; attrp = attrp->lp_next) { 215 if (strcmp(attrp->lp_name, attr) == 0) 216 break; 217 } 218 219 if (attrp != NULL) { 220 /* 221 * It is already set. If the value changed, update it. 222 */ 223 if (linkattr_equal(headp, attr, attrval, attrsz)) 224 return (0); 225 226 free(attrp->lp_val); 227 } else { 228 /* 229 * It is not set yet, allocate the linkattr and prepend to the 230 * list. 231 */ 232 if ((attrp = calloc(1, sizeof (dlmgmt_linkattr_t))) == NULL) 233 return (ENOMEM); 234 235 if ((err = linkattr_add(headp, attrp)) != 0) { 236 free(attrp); 237 return (err); 238 } 239 (void) strlcpy(attrp->lp_name, attr, MAXLINKATTRLEN); 240 } 241 if ((attrp->lp_val = calloc(1, attrsz)) == NULL) { 242 (void) linkattr_rm(headp, attrp); 243 free(attrp); 244 return (ENOMEM); 245 } 246 247 bcopy(attrval, attrp->lp_val, attrsz); 248 attrp->lp_sz = attrsz; 249 attrp->lp_type = type; 250 attrp->lp_linkprop = dladm_attr_is_linkprop(attr); 251 return (0); 252 } 253 254 int 255 linkattr_unset(dlmgmt_linkattr_t **headp, const char *attr) 256 { 257 dlmgmt_linkattr_t *attrp, *prev; 258 259 /* 260 * See whether the attr exists. 261 */ 262 for (prev = NULL, attrp = *headp; attrp != NULL; 263 prev = attrp, attrp = attrp->lp_next) { 264 if (strcmp(attrp->lp_name, attr) == 0) 265 break; 266 } 267 268 /* 269 * This attribute is not set in the first place. Return success. 270 */ 271 if (attrp == NULL) 272 return (0); 273 274 /* 275 * Remove this attr from the list. 276 */ 277 if (prev == NULL) 278 *headp = attrp->lp_next; 279 else 280 prev->lp_next = attrp->lp_next; 281 282 free(attrp->lp_val); 283 free(attrp); 284 return (0); 285 } 286 287 int 288 linkattr_get(dlmgmt_linkattr_t **headp, const char *attr, void **attrvalp, 289 size_t *attrszp, dladm_datatype_t *typep) 290 { 291 dlmgmt_linkattr_t *attrp = *headp; 292 293 /* 294 * find the specific attr. 295 */ 296 for (attrp = *headp; attrp != NULL; attrp = attrp->lp_next) { 297 if (strcmp(attrp->lp_name, attr) == 0) 298 break; 299 } 300 301 if (attrp == NULL) 302 return (ENOENT); 303 304 *attrvalp = attrp->lp_val; 305 *attrszp = attrp->lp_sz; 306 if (typep != NULL) 307 *typep = attrp->lp_type; 308 return (0); 309 } 310 311 int 312 linkprop_getnext(dlmgmt_linkattr_t **headp, const char *lastattr, 313 char **attrnamep, void **attrvalp, size_t *attrszp, dladm_datatype_t *typep) 314 { 315 dlmgmt_linkattr_t *attrp; 316 317 /* skip to entry following lastattr or pick first if none specified */ 318 for (attrp = *headp; attrp != NULL; attrp = attrp->lp_next) { 319 if (!attrp->lp_linkprop) 320 continue; 321 if (lastattr[0] == '\0') 322 break; 323 if (strcmp(attrp->lp_name, lastattr) == 0) { 324 attrp = attrp->lp_next; 325 break; 326 } 327 } 328 if (attrp == NULL) 329 return (ENOENT); 330 331 *attrnamep = attrp->lp_name; 332 *attrvalp = attrp->lp_val; 333 *attrszp = attrp->lp_sz; 334 *typep = attrp->lp_type; 335 return (0); 336 } 337 338 boolean_t 339 linkattr_equal(dlmgmt_linkattr_t **headp, const char *attr, void *attrval, 340 size_t attrsz) 341 { 342 void *saved_attrval; 343 size_t saved_attrsz; 344 345 if (linkattr_get(headp, attr, &saved_attrval, &saved_attrsz, NULL) != 0) 346 return (B_FALSE); 347 348 return ((saved_attrsz == attrsz) && 349 (memcmp(saved_attrval, attrval, attrsz) == 0)); 350 } 351 352 static int 353 dlmgmt_table_readwritelock(boolean_t write) 354 { 355 if (write) 356 return (pthread_rwlock_trywrlock(&dlmgmt_avl_lock)); 357 else 358 return (pthread_rwlock_tryrdlock(&dlmgmt_avl_lock)); 359 } 360 361 void 362 dlmgmt_table_lock(boolean_t write) 363 { 364 (void) pthread_mutex_lock(&dlmgmt_avl_mutex); 365 while (dlmgmt_table_readwritelock(write) == EBUSY) 366 (void) pthread_cond_wait(&dlmgmt_avl_cv, &dlmgmt_avl_mutex); 367 368 (void) pthread_mutex_unlock(&dlmgmt_avl_mutex); 369 } 370 371 void 372 dlmgmt_table_unlock() 373 { 374 (void) pthread_rwlock_unlock(&dlmgmt_avl_lock); 375 (void) pthread_mutex_lock(&dlmgmt_avl_mutex); 376 (void) pthread_cond_broadcast(&dlmgmt_avl_cv); 377 (void) pthread_mutex_unlock(&dlmgmt_avl_mutex); 378 } 379 380 static int 381 link_create(const char *name, datalink_class_t class, uint32_t media, 382 uint32_t flags, dlmgmt_link_t **linkpp) 383 { 384 dlmgmt_link_t *linkp = NULL; 385 int err = 0; 386 387 if (dlmgmt_nextlinkid == DATALINK_INVALID_LINKID) { 388 err = ENOSPC; 389 goto done; 390 } 391 392 if ((linkp = calloc(1, sizeof (dlmgmt_link_t))) == NULL) { 393 err = ENOMEM; 394 goto done; 395 } 396 397 (void) strlcpy(linkp->ll_link, name, MAXLINKNAMELEN); 398 linkp->ll_class = class; 399 linkp->ll_media = media; 400 linkp->ll_linkid = dlmgmt_nextlinkid; 401 linkp->ll_flags = flags; 402 linkp->ll_gen = 0; 403 done: 404 *linkpp = linkp; 405 return (err); 406 } 407 408 void 409 link_destroy(dlmgmt_link_t *linkp) 410 { 411 dlmgmt_linkattr_t *next, *attrp; 412 413 for (attrp = linkp->ll_head; attrp != NULL; attrp = next) { 414 next = attrp->lp_next; 415 free(attrp->lp_val); 416 free(attrp); 417 } 418 free(linkp); 419 } 420 421 dlmgmt_link_t * 422 link_by_id(datalink_id_t linkid) 423 { 424 dlmgmt_link_t link; 425 426 link.ll_linkid = linkid; 427 return (avl_find(&dlmgmt_id_avl, &link, NULL)); 428 } 429 430 dlmgmt_link_t * 431 link_by_name(const char *name) 432 { 433 dlmgmt_link_t link; 434 435 (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN); 436 return (avl_find(&dlmgmt_name_avl, &link, NULL)); 437 } 438 439 int 440 dlmgmt_create_common(const char *name, datalink_class_t class, uint32_t media, 441 uint32_t flags, dlmgmt_link_t **linkpp) 442 { 443 dlmgmt_link_t link, *linkp, *tmp; 444 avl_index_t name_where, id_where; 445 int err; 446 447 /* 448 * Validate the link. 449 */ 450 if (!dladm_valid_linkname(name)) 451 return (EINVAL); 452 453 /* 454 * Check to see whether this is an existing link name. 455 */ 456 (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN); 457 if ((linkp = avl_find(&dlmgmt_name_avl, &link, &name_where)) != NULL) 458 return (EEXIST); 459 460 if ((err = link_create(name, class, media, flags, &linkp)) != 0) 461 return (err); 462 463 link.ll_linkid = linkp->ll_linkid; 464 tmp = avl_find(&dlmgmt_id_avl, &link, &id_where); 465 assert(tmp == NULL); 466 avl_insert(&dlmgmt_name_avl, linkp, name_where); 467 avl_insert(&dlmgmt_id_avl, linkp, id_where); 468 dlmgmt_advance(linkp); 469 *linkpp = linkp; 470 return (0); 471 } 472 473 int 474 dlmgmt_destroy_common(dlmgmt_link_t *linkp, uint32_t flags) 475 { 476 if ((linkp->ll_flags & flags) == 0) { 477 /* 478 * The link does not exist in the specified space. 479 */ 480 return (ENOENT); 481 } 482 linkp->ll_flags &= ~flags; 483 if (!(linkp->ll_flags & DLMGMT_PERSIST)) { 484 dlmgmt_linkattr_t *next, *attrp; 485 486 for (attrp = linkp->ll_head; attrp != NULL; attrp = next) { 487 next = attrp->lp_next; 488 free(attrp->lp_val); 489 free(attrp); 490 } 491 linkp->ll_head = NULL; 492 } 493 494 if (linkp->ll_flags == 0) { 495 avl_remove(&dlmgmt_id_avl, linkp); 496 avl_remove(&dlmgmt_name_avl, linkp); 497 link_destroy(linkp); 498 } 499 500 return (0); 501 } 502 503 void 504 dlmgmt_getattr_common(dlmgmt_linkattr_t **headp, const char *attr, 505 dlmgmt_getattr_retval_t *retvalp) 506 { 507 int err; 508 void *attrval; 509 size_t attrsz; 510 dladm_datatype_t attrtype; 511 512 err = linkattr_get(headp, attr, &attrval, &attrsz, &attrtype); 513 if (err != 0) 514 goto done; 515 516 assert(attrsz > 0); 517 if (attrsz > MAXLINKATTRVALLEN) { 518 err = EINVAL; 519 goto done; 520 } 521 522 retvalp->lr_type = attrtype; 523 retvalp->lr_attrsz = attrsz; 524 bcopy(attrval, retvalp->lr_attrval, attrsz); 525 done: 526 retvalp->lr_err = err; 527 } 528 529 void 530 dlmgmt_dlconf_table_lock(boolean_t write) 531 { 532 if (write) 533 (void) pthread_rwlock_wrlock(&dlmgmt_dlconf_lock); 534 else 535 (void) pthread_rwlock_rdlock(&dlmgmt_dlconf_lock); 536 } 537 538 void 539 dlmgmt_dlconf_table_unlock() 540 { 541 (void) pthread_rwlock_unlock(&dlmgmt_dlconf_lock); 542 } 543 544 int 545 dlconf_create(const char *name, datalink_id_t linkid, datalink_class_t class, 546 uint32_t media, dlmgmt_dlconf_t **dlconfpp) 547 { 548 dlmgmt_dlconf_t *dlconfp = NULL; 549 int err = 0; 550 551 if (dlmgmt_nextconfid == 0) { 552 err = ENOSPC; 553 goto done; 554 } 555 556 if ((dlconfp = calloc(1, sizeof (dlmgmt_dlconf_t))) == NULL) { 557 err = ENOMEM; 558 goto done; 559 } 560 561 (void) strlcpy(dlconfp->ld_link, name, MAXLINKNAMELEN); 562 dlconfp->ld_linkid = linkid; 563 dlconfp->ld_class = class; 564 dlconfp->ld_media = media; 565 dlconfp->ld_id = dlmgmt_nextconfid; 566 567 done: 568 *dlconfpp = dlconfp; 569 return (err); 570 } 571 572 void 573 dlconf_destroy(dlmgmt_dlconf_t *dlconfp) 574 { 575 dlmgmt_linkattr_t *next, *attrp; 576 577 for (attrp = dlconfp->ld_head; attrp != NULL; attrp = next) { 578 next = attrp->lp_next; 579 free(attrp->lp_val); 580 free(attrp); 581 } 582 free(dlconfp); 583 } 584 585 int 586 dlmgmt_generate_name(const char *prefix, char *name, size_t size) 587 { 588 dlmgmt_prefix_t *lpp, *prev = NULL; 589 590 /* 591 * See whether the requested prefix is already in the list. 592 */ 593 for (lpp = dlmgmt_prefixlist; lpp != NULL; prev = lpp, 594 lpp = lpp->lp_next) { 595 if (strcmp(prefix, lpp->lp_prefix) == 0) 596 break; 597 } 598 599 /* 600 * Not found. 601 */ 602 if (lpp == NULL) { 603 dlmgmt_link_t *linkp, link; 604 605 assert(prev != NULL); 606 607 /* 608 * First add this new prefix into the prefix list. 609 */ 610 if ((lpp = malloc(sizeof (dlmgmt_prefix_t))) == NULL) 611 return (ENOMEM); 612 613 prev->lp_next = lpp; 614 lpp->lp_next = NULL; 615 lpp->lp_nextppa = 0; 616 (void) strlcpy(lpp->lp_prefix, prefix, MAXLINKNAMELEN); 617 618 /* 619 * Now determine this prefix's nextppa. 620 */ 621 (void) snprintf(link.ll_link, MAXLINKNAMELEN, "%s%d", 622 prefix, lpp->lp_nextppa); 623 linkp = avl_find(&dlmgmt_name_avl, &link, NULL); 624 if (linkp != NULL) 625 dlmgmt_advance_ppa(linkp); 626 } 627 628 if (lpp->lp_nextppa == (uint_t)-1) 629 return (ENOSPC); 630 631 (void) snprintf(name, size, "%s%d", prefix, lpp->lp_nextppa); 632 return (0); 633 } 634 635 /* 636 * Advance the next available ppa value if the name prefix of the current 637 * link is in the prefix list. 638 */ 639 static void 640 dlmgmt_advance_ppa(dlmgmt_link_t *linkp) 641 { 642 dlmgmt_prefix_t *lpp; 643 char prefix[MAXLINKNAMELEN]; 644 uint_t start, ppa; 645 646 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa); 647 648 /* 649 * See whether the requested prefix is already in the list. 650 */ 651 for (lpp = dlmgmt_prefixlist; lpp != NULL; lpp = lpp->lp_next) { 652 if (strcmp(prefix, lpp->lp_prefix) == 0) 653 break; 654 } 655 656 /* 657 * If the link name prefix is in the list, advance the 658 * next available ppa for the <prefix>N name. 659 */ 660 if (lpp == NULL || lpp->lp_nextppa != ppa) 661 return; 662 663 start = lpp->lp_nextppa++; 664 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); 665 while (lpp->lp_nextppa != start) { 666 if (lpp->lp_nextppa == (uint_t)-1) { 667 dlmgmt_link_t link; 668 669 /* 670 * wrapped around. search from <prefix>1. 671 */ 672 lpp->lp_nextppa = 0; 673 (void) snprintf(link.ll_link, MAXLINKNAMELEN, 674 "%s%d", lpp->lp_prefix, lpp->lp_nextppa); 675 linkp = avl_find(&dlmgmt_name_avl, &link, NULL); 676 if (linkp == NULL) 677 return; 678 } else { 679 if (linkp == NULL) 680 return; 681 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa); 682 if ((strcmp(prefix, lpp->lp_prefix) != 0) || 683 (ppa != lpp->lp_nextppa)) { 684 return; 685 } 686 } 687 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); 688 lpp->lp_nextppa++; 689 } 690 lpp->lp_nextppa = (uint_t)-1; 691 } 692 693 /* 694 * Advance to the next available linkid value. 695 */ 696 static void 697 dlmgmt_advance_linkid(dlmgmt_link_t *linkp) 698 { 699 datalink_id_t start; 700 701 if (linkp->ll_linkid != dlmgmt_nextlinkid) 702 return; 703 704 start = dlmgmt_nextlinkid; 705 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp); 706 707 do { 708 if (dlmgmt_nextlinkid == DATALINK_MAX_LINKID) { 709 dlmgmt_link_t link; 710 711 /* 712 * wrapped around. search from 1. 713 */ 714 dlmgmt_nextlinkid = 1; 715 link.ll_linkid = 1; 716 linkp = avl_find(&dlmgmt_id_avl, &link, NULL); 717 if (linkp == NULL) 718 return; 719 } else { 720 dlmgmt_nextlinkid++; 721 if (linkp == NULL) 722 return; 723 if (linkp->ll_linkid != dlmgmt_nextlinkid) 724 return; 725 } 726 727 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp); 728 } while (dlmgmt_nextlinkid != start); 729 730 dlmgmt_nextlinkid = DATALINK_INVALID_LINKID; 731 } 732 733 /* 734 * Advance various global values, for example, next linkid value, next ppa for 735 * various prefix etc. 736 */ 737 void 738 dlmgmt_advance(dlmgmt_link_t *linkp) 739 { 740 dlmgmt_advance_linkid(linkp); 741 dlmgmt_advance_ppa(linkp); 742 } 743 744 /* 745 * Advance to the next available dlconf id. 746 */ 747 void 748 dlmgmt_advance_dlconfid(dlmgmt_dlconf_t *dlconfp) 749 { 750 uint_t start; 751 752 start = dlmgmt_nextconfid++; 753 dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp); 754 while (dlmgmt_nextconfid != start) { 755 if (dlmgmt_nextconfid == 0) { 756 dlmgmt_dlconf_t dlconf; 757 758 /* 759 * wrapped around. search from 1. 760 */ 761 dlconf.ld_id = dlmgmt_nextconfid = 1; 762 dlconfp = avl_find(&dlmgmt_dlconf_avl, &dlconf, NULL); 763 if (dlconfp == NULL) 764 return; 765 } else { 766 if ((dlconfp == NULL) || 767 (dlconfp->ld_id != dlmgmt_nextconfid)) { 768 return; 769 } 770 } 771 dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp); 772 dlmgmt_nextconfid++; 773 } 774 dlmgmt_nextconfid = 0; 775 } 776