1d62bc4baSyz147064 /* 2d62bc4baSyz147064 * CDDL HEADER START 3d62bc4baSyz147064 * 4d62bc4baSyz147064 * The contents of this file are subject to the terms of the 5d62bc4baSyz147064 * Common Development and Distribution License (the "License"). 6d62bc4baSyz147064 * You may not use this file except in compliance with the License. 7d62bc4baSyz147064 * 8d62bc4baSyz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9d62bc4baSyz147064 * or http://www.opensolaris.org/os/licensing. 10d62bc4baSyz147064 * See the License for the specific language governing permissions 11d62bc4baSyz147064 * and limitations under the License. 12d62bc4baSyz147064 * 13d62bc4baSyz147064 * When distributing Covered Code, include this CDDL HEADER in each 14d62bc4baSyz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15d62bc4baSyz147064 * If applicable, add the following below this CDDL HEADER, with the 16d62bc4baSyz147064 * fields enclosed by brackets "[]" replaced with your own identifying 17d62bc4baSyz147064 * information: Portions Copyright [yyyy] [name of copyright owner] 18d62bc4baSyz147064 * 19d62bc4baSyz147064 * CDDL HEADER END 20d62bc4baSyz147064 */ 21d62bc4baSyz147064 22d62bc4baSyz147064 /* 23a73e6fc1SCathy Zhou * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24d62bc4baSyz147064 * Use is subject to license terms. 25d62bc4baSyz147064 */ 26d62bc4baSyz147064 27d62bc4baSyz147064 /* 28d62bc4baSyz147064 * Utility functions used by the dlmgmtd daemon. 29d62bc4baSyz147064 */ 30d62bc4baSyz147064 31d62bc4baSyz147064 #include <assert.h> 32d62bc4baSyz147064 #include <pthread.h> 33d62bc4baSyz147064 #include <stddef.h> 34d62bc4baSyz147064 #include <stdlib.h> 35d62bc4baSyz147064 #include <stdio.h> 36*2b24ab6bSSebastien Roy #include <errno.h> 37d62bc4baSyz147064 #include <strings.h> 38*2b24ab6bSSebastien Roy #include <string.h> 39d62bc4baSyz147064 #include <syslog.h> 40d62bc4baSyz147064 #include <stdarg.h> 41*2b24ab6bSSebastien Roy #include <zone.h> 4282a2fc47SJames Carlson #include <errno.h> 43d62bc4baSyz147064 #include <libdlpi.h> 44d62bc4baSyz147064 #include "dlmgmt_impl.h" 45d62bc4baSyz147064 46d62bc4baSyz147064 /* 47*2b24ab6bSSebastien Roy * There are three datalink AVL tables. The dlmgmt_name_avl tree contains all 48*2b24ab6bSSebastien Roy * datalinks and is keyed by zoneid and link name. The dlmgmt_id_avl also 49*2b24ab6bSSebastien Roy * contains all datalinks, and it is keyed by link ID. The dlmgmt_loan_avl is 50*2b24ab6bSSebastien Roy * keyed by link name, and contains the set of global-zone links that are 51*2b24ab6bSSebastien Roy * currently on loan to non-global zones. 52d62bc4baSyz147064 */ 53d62bc4baSyz147064 avl_tree_t dlmgmt_name_avl; 54d62bc4baSyz147064 avl_tree_t dlmgmt_id_avl; 55*2b24ab6bSSebastien Roy avl_tree_t dlmgmt_loan_avl; 56d62bc4baSyz147064 57d62bc4baSyz147064 avl_tree_t dlmgmt_dlconf_avl; 58d62bc4baSyz147064 59d62bc4baSyz147064 static pthread_rwlock_t dlmgmt_avl_lock = PTHREAD_RWLOCK_INITIALIZER; 60d62bc4baSyz147064 static pthread_mutex_t dlmgmt_avl_mutex = PTHREAD_MUTEX_INITIALIZER; 61d62bc4baSyz147064 static pthread_cond_t dlmgmt_avl_cv = PTHREAD_COND_INITIALIZER; 62d62bc4baSyz147064 static pthread_rwlock_t dlmgmt_dlconf_lock = PTHREAD_RWLOCK_INITIALIZER; 63d62bc4baSyz147064 64d62bc4baSyz147064 typedef struct dlmgmt_prefix { 65d62bc4baSyz147064 struct dlmgmt_prefix *lp_next; 66d62bc4baSyz147064 char lp_prefix[MAXLINKNAMELEN]; 67*2b24ab6bSSebastien Roy zoneid_t lp_zoneid; 68d62bc4baSyz147064 uint_t lp_nextppa; 69d62bc4baSyz147064 } dlmgmt_prefix_t; 70*2b24ab6bSSebastien Roy static dlmgmt_prefix_t dlmgmt_prefixlist; 71d62bc4baSyz147064 72*2b24ab6bSSebastien Roy datalink_id_t dlmgmt_nextlinkid; 73d62bc4baSyz147064 static datalink_id_t dlmgmt_nextconfid = 1; 74d62bc4baSyz147064 75d62bc4baSyz147064 static void dlmgmt_advance_linkid(dlmgmt_link_t *); 76d62bc4baSyz147064 static void dlmgmt_advance_ppa(dlmgmt_link_t *); 77d62bc4baSyz147064 78d62bc4baSyz147064 void 79d62bc4baSyz147064 dlmgmt_log(int pri, const char *fmt, ...) 80d62bc4baSyz147064 { 81d62bc4baSyz147064 va_list alist; 82d62bc4baSyz147064 83d62bc4baSyz147064 va_start(alist, fmt); 84d62bc4baSyz147064 if (debug) { 85d62bc4baSyz147064 (void) vfprintf(stderr, fmt, alist); 86d62bc4baSyz147064 (void) fputc('\n', stderr); 87d62bc4baSyz147064 } else { 88d62bc4baSyz147064 vsyslog(pri, fmt, alist); 89d62bc4baSyz147064 } 90d62bc4baSyz147064 va_end(alist); 91d62bc4baSyz147064 } 92d62bc4baSyz147064 93d62bc4baSyz147064 static int 94d62bc4baSyz147064 cmp_link_by_name(const void *v1, const void *v2) 95d62bc4baSyz147064 { 96d62bc4baSyz147064 const dlmgmt_link_t *link1 = v1; 97d62bc4baSyz147064 const dlmgmt_link_t *link2 = v2; 98d62bc4baSyz147064 int cmp; 99d62bc4baSyz147064 100d62bc4baSyz147064 cmp = strcmp(link1->ll_link, link2->ll_link); 101d62bc4baSyz147064 return ((cmp == 0) ? 0 : ((cmp < 0) ? -1 : 1)); 102d62bc4baSyz147064 } 103d62bc4baSyz147064 104*2b24ab6bSSebastien Roy /* 105*2b24ab6bSSebastien Roy * Note that the zoneid associated with a link is effectively part of its 106*2b24ab6bSSebastien Roy * name. This is essentially what results in having each zone have disjoint 107*2b24ab6bSSebastien Roy * datalink namespaces. 108*2b24ab6bSSebastien Roy */ 109*2b24ab6bSSebastien Roy static int 110*2b24ab6bSSebastien Roy cmp_link_by_zname(const void *v1, const void *v2) 111*2b24ab6bSSebastien Roy { 112*2b24ab6bSSebastien Roy const dlmgmt_link_t *link1 = v1; 113*2b24ab6bSSebastien Roy const dlmgmt_link_t *link2 = v2; 114*2b24ab6bSSebastien Roy 115*2b24ab6bSSebastien Roy if (link1->ll_zoneid < link2->ll_zoneid) 116*2b24ab6bSSebastien Roy return (-1); 117*2b24ab6bSSebastien Roy if (link1->ll_zoneid > link2->ll_zoneid) 118*2b24ab6bSSebastien Roy return (1); 119*2b24ab6bSSebastien Roy return (cmp_link_by_name(link1, link2)); 120*2b24ab6bSSebastien Roy } 121*2b24ab6bSSebastien Roy 122d62bc4baSyz147064 static int 123d62bc4baSyz147064 cmp_link_by_id(const void *v1, const void *v2) 124d62bc4baSyz147064 { 125d62bc4baSyz147064 const dlmgmt_link_t *link1 = v1; 126d62bc4baSyz147064 const dlmgmt_link_t *link2 = v2; 127d62bc4baSyz147064 128d62bc4baSyz147064 if ((uint64_t)(link1->ll_linkid) == (uint64_t)(link2->ll_linkid)) 129d62bc4baSyz147064 return (0); 130d62bc4baSyz147064 else if ((uint64_t)(link1->ll_linkid) < (uint64_t)(link2->ll_linkid)) 131d62bc4baSyz147064 return (-1); 132d62bc4baSyz147064 else 133d62bc4baSyz147064 return (1); 134d62bc4baSyz147064 } 135d62bc4baSyz147064 136d62bc4baSyz147064 static int 137d62bc4baSyz147064 cmp_dlconf_by_id(const void *v1, const void *v2) 138d62bc4baSyz147064 { 139d62bc4baSyz147064 const dlmgmt_dlconf_t *dlconfp1 = v1; 140d62bc4baSyz147064 const dlmgmt_dlconf_t *dlconfp2 = v2; 141d62bc4baSyz147064 142d62bc4baSyz147064 if (dlconfp1->ld_id == dlconfp2->ld_id) 143d62bc4baSyz147064 return (0); 144d62bc4baSyz147064 else if (dlconfp1->ld_id < dlconfp2->ld_id) 145d62bc4baSyz147064 return (-1); 146d62bc4baSyz147064 else 147d62bc4baSyz147064 return (1); 148d62bc4baSyz147064 } 149d62bc4baSyz147064 150*2b24ab6bSSebastien Roy void 151*2b24ab6bSSebastien Roy dlmgmt_linktable_init(void) 152d62bc4baSyz147064 { 153d62bc4baSyz147064 /* 154*2b24ab6bSSebastien Roy * Initialize the prefix list. First add the "net" prefix for the 155*2b24ab6bSSebastien Roy * global zone to the list. 156d62bc4baSyz147064 */ 157*2b24ab6bSSebastien Roy dlmgmt_prefixlist.lp_next = NULL; 158*2b24ab6bSSebastien Roy dlmgmt_prefixlist.lp_zoneid = GLOBAL_ZONEID; 159*2b24ab6bSSebastien Roy dlmgmt_prefixlist.lp_nextppa = 0; 160*2b24ab6bSSebastien Roy (void) strlcpy(dlmgmt_prefixlist.lp_prefix, "net", MAXLINKNAMELEN); 161d62bc4baSyz147064 162*2b24ab6bSSebastien Roy avl_create(&dlmgmt_name_avl, cmp_link_by_zname, sizeof (dlmgmt_link_t), 163*2b24ab6bSSebastien Roy offsetof(dlmgmt_link_t, ll_name_node)); 164d62bc4baSyz147064 avl_create(&dlmgmt_id_avl, cmp_link_by_id, sizeof (dlmgmt_link_t), 165*2b24ab6bSSebastien Roy offsetof(dlmgmt_link_t, ll_id_node)); 166*2b24ab6bSSebastien Roy avl_create(&dlmgmt_loan_avl, cmp_link_by_name, sizeof (dlmgmt_link_t), 167*2b24ab6bSSebastien Roy offsetof(dlmgmt_link_t, ll_loan_node)); 168d62bc4baSyz147064 avl_create(&dlmgmt_dlconf_avl, cmp_dlconf_by_id, 169d62bc4baSyz147064 sizeof (dlmgmt_dlconf_t), offsetof(dlmgmt_dlconf_t, ld_node)); 170d62bc4baSyz147064 dlmgmt_nextlinkid = 1; 171d62bc4baSyz147064 } 172d62bc4baSyz147064 173d62bc4baSyz147064 void 174*2b24ab6bSSebastien Roy dlmgmt_linktable_fini(void) 175d62bc4baSyz147064 { 176d62bc4baSyz147064 dlmgmt_prefix_t *lpp, *next; 177d62bc4baSyz147064 178*2b24ab6bSSebastien Roy for (lpp = dlmgmt_prefixlist.lp_next; lpp != NULL; lpp = next) { 179d62bc4baSyz147064 next = lpp->lp_next; 180d62bc4baSyz147064 free(lpp); 181d62bc4baSyz147064 } 182d62bc4baSyz147064 183d62bc4baSyz147064 avl_destroy(&dlmgmt_dlconf_avl); 184d62bc4baSyz147064 avl_destroy(&dlmgmt_name_avl); 185*2b24ab6bSSebastien Roy avl_destroy(&dlmgmt_loan_avl); 186d62bc4baSyz147064 avl_destroy(&dlmgmt_id_avl); 187d62bc4baSyz147064 } 188d62bc4baSyz147064 189*2b24ab6bSSebastien Roy static void 190d62bc4baSyz147064 linkattr_add(dlmgmt_linkattr_t **headp, dlmgmt_linkattr_t *attrp) 191d62bc4baSyz147064 { 192d62bc4baSyz147064 if (*headp == NULL) { 193d62bc4baSyz147064 *headp = attrp; 194d62bc4baSyz147064 } else { 195d62bc4baSyz147064 (*headp)->lp_prev = attrp; 196d62bc4baSyz147064 attrp->lp_next = *headp; 197d62bc4baSyz147064 *headp = attrp; 198d62bc4baSyz147064 } 199d62bc4baSyz147064 } 200d62bc4baSyz147064 201*2b24ab6bSSebastien Roy static void 202d62bc4baSyz147064 linkattr_rm(dlmgmt_linkattr_t **headp, dlmgmt_linkattr_t *attrp) 203d62bc4baSyz147064 { 204d62bc4baSyz147064 dlmgmt_linkattr_t *next, *prev; 205d62bc4baSyz147064 206d62bc4baSyz147064 next = attrp->lp_next; 207d62bc4baSyz147064 prev = attrp->lp_prev; 208d62bc4baSyz147064 if (next != NULL) 209d62bc4baSyz147064 next->lp_prev = prev; 210d62bc4baSyz147064 if (prev != NULL) 211d62bc4baSyz147064 prev->lp_next = next; 212d62bc4baSyz147064 else 213d62bc4baSyz147064 *headp = next; 214*2b24ab6bSSebastien Roy } 215d62bc4baSyz147064 216*2b24ab6bSSebastien Roy dlmgmt_linkattr_t * 217*2b24ab6bSSebastien Roy linkattr_find(dlmgmt_linkattr_t *headp, const char *attr) 218*2b24ab6bSSebastien Roy { 219*2b24ab6bSSebastien Roy dlmgmt_linkattr_t *attrp; 220*2b24ab6bSSebastien Roy 221*2b24ab6bSSebastien Roy for (attrp = headp; attrp != NULL; attrp = attrp->lp_next) { 222*2b24ab6bSSebastien Roy if (strcmp(attrp->lp_name, attr) == 0) 223*2b24ab6bSSebastien Roy break; 224*2b24ab6bSSebastien Roy } 225*2b24ab6bSSebastien Roy return (attrp); 226d62bc4baSyz147064 } 227d62bc4baSyz147064 228d62bc4baSyz147064 int 229d62bc4baSyz147064 linkattr_set(dlmgmt_linkattr_t **headp, const char *attr, void *attrval, 230d62bc4baSyz147064 size_t attrsz, dladm_datatype_t type) 231d62bc4baSyz147064 { 232d62bc4baSyz147064 dlmgmt_linkattr_t *attrp; 233*2b24ab6bSSebastien Roy void *newval; 234*2b24ab6bSSebastien Roy boolean_t new; 235d62bc4baSyz147064 236*2b24ab6bSSebastien Roy attrp = linkattr_find(*headp, attr); 237d62bc4baSyz147064 if (attrp != NULL) { 238d62bc4baSyz147064 /* 239d62bc4baSyz147064 * It is already set. If the value changed, update it. 240d62bc4baSyz147064 */ 241d62bc4baSyz147064 if (linkattr_equal(headp, attr, attrval, attrsz)) 242d62bc4baSyz147064 return (0); 243*2b24ab6bSSebastien Roy new = B_FALSE; 244d62bc4baSyz147064 } else { 245d62bc4baSyz147064 /* 246d62bc4baSyz147064 * It is not set yet, allocate the linkattr and prepend to the 247d62bc4baSyz147064 * list. 248d62bc4baSyz147064 */ 249d62bc4baSyz147064 if ((attrp = calloc(1, sizeof (dlmgmt_linkattr_t))) == NULL) 250d62bc4baSyz147064 return (ENOMEM); 251d62bc4baSyz147064 252d62bc4baSyz147064 (void) strlcpy(attrp->lp_name, attr, MAXLINKATTRLEN); 253*2b24ab6bSSebastien Roy new = B_TRUE; 254d62bc4baSyz147064 } 255*2b24ab6bSSebastien Roy if ((newval = calloc(1, attrsz)) == NULL) { 256*2b24ab6bSSebastien Roy if (new) 257d62bc4baSyz147064 free(attrp); 258d62bc4baSyz147064 return (ENOMEM); 259d62bc4baSyz147064 } 260d62bc4baSyz147064 261*2b24ab6bSSebastien Roy if (!new) 262*2b24ab6bSSebastien Roy free(attrp->lp_val); 263*2b24ab6bSSebastien Roy attrp->lp_val = newval; 264d62bc4baSyz147064 bcopy(attrval, attrp->lp_val, attrsz); 265d62bc4baSyz147064 attrp->lp_sz = attrsz; 266d62bc4baSyz147064 attrp->lp_type = type; 26762ee1d25SArtem Kachitchkine attrp->lp_linkprop = dladm_attr_is_linkprop(attr); 268*2b24ab6bSSebastien Roy if (new) 269*2b24ab6bSSebastien Roy linkattr_add(headp, attrp); 270d62bc4baSyz147064 return (0); 271d62bc4baSyz147064 } 272d62bc4baSyz147064 273*2b24ab6bSSebastien Roy void 274d62bc4baSyz147064 linkattr_unset(dlmgmt_linkattr_t **headp, const char *attr) 275d62bc4baSyz147064 { 276*2b24ab6bSSebastien Roy dlmgmt_linkattr_t *attrp; 277d62bc4baSyz147064 278*2b24ab6bSSebastien Roy if ((attrp = linkattr_find(*headp, attr)) != NULL) 279*2b24ab6bSSebastien Roy linkattr_rm(headp, attrp); 280d62bc4baSyz147064 } 281d62bc4baSyz147064 282d62bc4baSyz147064 int 283d62bc4baSyz147064 linkattr_get(dlmgmt_linkattr_t **headp, const char *attr, void **attrvalp, 284d62bc4baSyz147064 size_t *attrszp, dladm_datatype_t *typep) 285d62bc4baSyz147064 { 286*2b24ab6bSSebastien Roy dlmgmt_linkattr_t *attrp; 287d62bc4baSyz147064 288*2b24ab6bSSebastien Roy if ((attrp = linkattr_find(*headp, attr)) == NULL) 289d62bc4baSyz147064 return (ENOENT); 290d62bc4baSyz147064 291d62bc4baSyz147064 *attrvalp = attrp->lp_val; 292d62bc4baSyz147064 *attrszp = attrp->lp_sz; 293d62bc4baSyz147064 if (typep != NULL) 294d62bc4baSyz147064 *typep = attrp->lp_type; 295d62bc4baSyz147064 return (0); 296d62bc4baSyz147064 } 297d62bc4baSyz147064 29862ee1d25SArtem Kachitchkine int 29962ee1d25SArtem Kachitchkine linkprop_getnext(dlmgmt_linkattr_t **headp, const char *lastattr, 30062ee1d25SArtem Kachitchkine char **attrnamep, void **attrvalp, size_t *attrszp, dladm_datatype_t *typep) 30162ee1d25SArtem Kachitchkine { 30262ee1d25SArtem Kachitchkine dlmgmt_linkattr_t *attrp; 30362ee1d25SArtem Kachitchkine 30462ee1d25SArtem Kachitchkine /* skip to entry following lastattr or pick first if none specified */ 30562ee1d25SArtem Kachitchkine for (attrp = *headp; attrp != NULL; attrp = attrp->lp_next) { 30662ee1d25SArtem Kachitchkine if (!attrp->lp_linkprop) 30762ee1d25SArtem Kachitchkine continue; 30862ee1d25SArtem Kachitchkine if (lastattr[0] == '\0') 30962ee1d25SArtem Kachitchkine break; 31062ee1d25SArtem Kachitchkine if (strcmp(attrp->lp_name, lastattr) == 0) { 31162ee1d25SArtem Kachitchkine attrp = attrp->lp_next; 31262ee1d25SArtem Kachitchkine break; 31362ee1d25SArtem Kachitchkine } 31462ee1d25SArtem Kachitchkine } 31562ee1d25SArtem Kachitchkine if (attrp == NULL) 31662ee1d25SArtem Kachitchkine return (ENOENT); 31762ee1d25SArtem Kachitchkine 31862ee1d25SArtem Kachitchkine *attrnamep = attrp->lp_name; 31962ee1d25SArtem Kachitchkine *attrvalp = attrp->lp_val; 32062ee1d25SArtem Kachitchkine *attrszp = attrp->lp_sz; 32162ee1d25SArtem Kachitchkine *typep = attrp->lp_type; 32262ee1d25SArtem Kachitchkine return (0); 32362ee1d25SArtem Kachitchkine } 32462ee1d25SArtem Kachitchkine 325d62bc4baSyz147064 boolean_t 326d62bc4baSyz147064 linkattr_equal(dlmgmt_linkattr_t **headp, const char *attr, void *attrval, 327d62bc4baSyz147064 size_t attrsz) 328d62bc4baSyz147064 { 329d62bc4baSyz147064 void *saved_attrval; 330d62bc4baSyz147064 size_t saved_attrsz; 331d62bc4baSyz147064 332d62bc4baSyz147064 if (linkattr_get(headp, attr, &saved_attrval, &saved_attrsz, NULL) != 0) 333d62bc4baSyz147064 return (B_FALSE); 334d62bc4baSyz147064 335d62bc4baSyz147064 return ((saved_attrsz == attrsz) && 336d62bc4baSyz147064 (memcmp(saved_attrval, attrval, attrsz) == 0)); 337d62bc4baSyz147064 } 338d62bc4baSyz147064 339d62bc4baSyz147064 static int 340d62bc4baSyz147064 dlmgmt_table_readwritelock(boolean_t write) 341d62bc4baSyz147064 { 342d62bc4baSyz147064 if (write) 343d62bc4baSyz147064 return (pthread_rwlock_trywrlock(&dlmgmt_avl_lock)); 344d62bc4baSyz147064 else 345d62bc4baSyz147064 return (pthread_rwlock_tryrdlock(&dlmgmt_avl_lock)); 346d62bc4baSyz147064 } 347d62bc4baSyz147064 348d62bc4baSyz147064 void 349d62bc4baSyz147064 dlmgmt_table_lock(boolean_t write) 350d62bc4baSyz147064 { 351d62bc4baSyz147064 (void) pthread_mutex_lock(&dlmgmt_avl_mutex); 352d62bc4baSyz147064 while (dlmgmt_table_readwritelock(write) == EBUSY) 353d62bc4baSyz147064 (void) pthread_cond_wait(&dlmgmt_avl_cv, &dlmgmt_avl_mutex); 354d62bc4baSyz147064 355d62bc4baSyz147064 (void) pthread_mutex_unlock(&dlmgmt_avl_mutex); 356d62bc4baSyz147064 } 357d62bc4baSyz147064 358d62bc4baSyz147064 void 359*2b24ab6bSSebastien Roy dlmgmt_table_unlock(void) 360d62bc4baSyz147064 { 361d62bc4baSyz147064 (void) pthread_rwlock_unlock(&dlmgmt_avl_lock); 362d62bc4baSyz147064 (void) pthread_mutex_lock(&dlmgmt_avl_mutex); 363d62bc4baSyz147064 (void) pthread_cond_broadcast(&dlmgmt_avl_cv); 364d62bc4baSyz147064 (void) pthread_mutex_unlock(&dlmgmt_avl_mutex); 365d62bc4baSyz147064 } 366d62bc4baSyz147064 367d62bc4baSyz147064 void 368d62bc4baSyz147064 link_destroy(dlmgmt_link_t *linkp) 369d62bc4baSyz147064 { 370d62bc4baSyz147064 dlmgmt_linkattr_t *next, *attrp; 371d62bc4baSyz147064 372d62bc4baSyz147064 for (attrp = linkp->ll_head; attrp != NULL; attrp = next) { 373d62bc4baSyz147064 next = attrp->lp_next; 374d62bc4baSyz147064 free(attrp->lp_val); 375d62bc4baSyz147064 free(attrp); 376d62bc4baSyz147064 } 377d62bc4baSyz147064 free(linkp); 378d62bc4baSyz147064 } 379d62bc4baSyz147064 380*2b24ab6bSSebastien Roy /* 381*2b24ab6bSSebastien Roy * Set the DLMGMT_ACTIVE flag on the link to note that it is active. When a 382*2b24ab6bSSebastien Roy * link becomes active and it belongs to a non-global zone, it is also added 383*2b24ab6bSSebastien Roy * to that zone. 384*2b24ab6bSSebastien Roy */ 385*2b24ab6bSSebastien Roy int 386*2b24ab6bSSebastien Roy link_activate(dlmgmt_link_t *linkp) 387d62bc4baSyz147064 { 388*2b24ab6bSSebastien Roy int err = 0; 389*2b24ab6bSSebastien Roy zoneid_t zoneid; 390d62bc4baSyz147064 391*2b24ab6bSSebastien Roy if (zone_check_datalink(&zoneid, linkp->ll_linkid) == 0) { 392*2b24ab6bSSebastien Roy /* 393*2b24ab6bSSebastien Roy * This link was already added to a non-global zone. This can 394*2b24ab6bSSebastien Roy * happen if dlmgmtd is restarted. 395*2b24ab6bSSebastien Roy */ 396*2b24ab6bSSebastien Roy if (zoneid != linkp->ll_zoneid) { 397*2b24ab6bSSebastien Roy if (link_by_name(linkp->ll_link, zoneid) != NULL) { 398*2b24ab6bSSebastien Roy err = EEXIST; 399*2b24ab6bSSebastien Roy goto done; 400*2b24ab6bSSebastien Roy } 401*2b24ab6bSSebastien Roy avl_remove(&dlmgmt_name_avl, linkp); 402*2b24ab6bSSebastien Roy linkp->ll_zoneid = zoneid; 403*2b24ab6bSSebastien Roy avl_add(&dlmgmt_name_avl, linkp); 404*2b24ab6bSSebastien Roy avl_add(&dlmgmt_loan_avl, linkp); 405*2b24ab6bSSebastien Roy linkp->ll_onloan = B_TRUE; 406*2b24ab6bSSebastien Roy } 407*2b24ab6bSSebastien Roy } else if (linkp->ll_zoneid != GLOBAL_ZONEID) { 408*2b24ab6bSSebastien Roy err = zone_add_datalink(linkp->ll_zoneid, linkp->ll_linkid); 409*2b24ab6bSSebastien Roy } 410*2b24ab6bSSebastien Roy done: 411*2b24ab6bSSebastien Roy if (err == 0) 412*2b24ab6bSSebastien Roy linkp->ll_flags |= DLMGMT_ACTIVE; 413*2b24ab6bSSebastien Roy return (err); 414*2b24ab6bSSebastien Roy } 415*2b24ab6bSSebastien Roy 416*2b24ab6bSSebastien Roy /* 417*2b24ab6bSSebastien Roy * Is linkp visible from the caller's zoneid? It is if the link is in the 418*2b24ab6bSSebastien Roy * same zone as the caller, or if the caller is in the global zone and the 419*2b24ab6bSSebastien Roy * link is on loan to a non-global zone. 420*2b24ab6bSSebastien Roy */ 421*2b24ab6bSSebastien Roy boolean_t 422*2b24ab6bSSebastien Roy link_is_visible(dlmgmt_link_t *linkp, zoneid_t zoneid) 423*2b24ab6bSSebastien Roy { 424*2b24ab6bSSebastien Roy return (linkp->ll_zoneid == zoneid || 425*2b24ab6bSSebastien Roy (zoneid == GLOBAL_ZONEID && linkp->ll_onloan)); 426d62bc4baSyz147064 } 427d62bc4baSyz147064 428d62bc4baSyz147064 dlmgmt_link_t * 429*2b24ab6bSSebastien Roy link_by_id(datalink_id_t linkid, zoneid_t zoneid) 430d62bc4baSyz147064 { 431*2b24ab6bSSebastien Roy dlmgmt_link_t link, *linkp; 432*2b24ab6bSSebastien Roy 433*2b24ab6bSSebastien Roy link.ll_linkid = linkid; 434*2b24ab6bSSebastien Roy linkp = avl_find(&dlmgmt_id_avl, &link, NULL); 435*2b24ab6bSSebastien Roy if (zoneid != GLOBAL_ZONEID && linkp->ll_zoneid != zoneid) 436*2b24ab6bSSebastien Roy linkp = NULL; 437*2b24ab6bSSebastien Roy return (linkp); 438*2b24ab6bSSebastien Roy } 439*2b24ab6bSSebastien Roy 440*2b24ab6bSSebastien Roy dlmgmt_link_t * 441*2b24ab6bSSebastien Roy link_by_name(const char *name, zoneid_t zoneid) 442*2b24ab6bSSebastien Roy { 443*2b24ab6bSSebastien Roy dlmgmt_link_t link, *linkp; 444d62bc4baSyz147064 445d62bc4baSyz147064 (void) strlcpy(link.ll_link, name, MAXLINKNAMELEN); 446*2b24ab6bSSebastien Roy link.ll_zoneid = zoneid; 447*2b24ab6bSSebastien Roy linkp = avl_find(&dlmgmt_name_avl, &link, NULL); 448*2b24ab6bSSebastien Roy if (linkp == NULL && zoneid == GLOBAL_ZONEID) { 449*2b24ab6bSSebastien Roy /* The link could be on loan to a non-global zone? */ 450*2b24ab6bSSebastien Roy linkp = avl_find(&dlmgmt_loan_avl, &link, NULL); 451*2b24ab6bSSebastien Roy } 452*2b24ab6bSSebastien Roy return (linkp); 453d62bc4baSyz147064 } 454d62bc4baSyz147064 455d62bc4baSyz147064 int 456d62bc4baSyz147064 dlmgmt_create_common(const char *name, datalink_class_t class, uint32_t media, 457*2b24ab6bSSebastien Roy zoneid_t zoneid, uint32_t flags, dlmgmt_link_t **linkpp) 458d62bc4baSyz147064 { 459*2b24ab6bSSebastien Roy dlmgmt_link_t *linkp = NULL; 460d62bc4baSyz147064 avl_index_t name_where, id_where; 461*2b24ab6bSSebastien Roy int err = 0; 462d62bc4baSyz147064 463d62bc4baSyz147064 if (!dladm_valid_linkname(name)) 464d62bc4baSyz147064 return (EINVAL); 465*2b24ab6bSSebastien Roy if (dlmgmt_nextlinkid == DATALINK_INVALID_LINKID) 466*2b24ab6bSSebastien Roy return (ENOSPC); 467d62bc4baSyz147064 468*2b24ab6bSSebastien Roy if ((linkp = calloc(1, sizeof (dlmgmt_link_t))) == NULL) { 469*2b24ab6bSSebastien Roy err = ENOMEM; 470*2b24ab6bSSebastien Roy goto done; 471*2b24ab6bSSebastien Roy } 472d62bc4baSyz147064 473*2b24ab6bSSebastien Roy (void) strlcpy(linkp->ll_link, name, MAXLINKNAMELEN); 474*2b24ab6bSSebastien Roy linkp->ll_class = class; 475*2b24ab6bSSebastien Roy linkp->ll_media = media; 476*2b24ab6bSSebastien Roy linkp->ll_linkid = dlmgmt_nextlinkid; 477*2b24ab6bSSebastien Roy linkp->ll_zoneid = zoneid; 478*2b24ab6bSSebastien Roy linkp->ll_gen = 0; 479d62bc4baSyz147064 480*2b24ab6bSSebastien Roy if (avl_find(&dlmgmt_name_avl, linkp, &name_where) != NULL || 481*2b24ab6bSSebastien Roy avl_find(&dlmgmt_id_avl, linkp, &id_where) != NULL) { 482*2b24ab6bSSebastien Roy err = EEXIST; 483*2b24ab6bSSebastien Roy goto done; 484*2b24ab6bSSebastien Roy } 485*2b24ab6bSSebastien Roy 486d62bc4baSyz147064 avl_insert(&dlmgmt_name_avl, linkp, name_where); 487d62bc4baSyz147064 avl_insert(&dlmgmt_id_avl, linkp, id_where); 488*2b24ab6bSSebastien Roy 489*2b24ab6bSSebastien Roy if ((flags & DLMGMT_ACTIVE) && (err = link_activate(linkp)) != 0) { 490*2b24ab6bSSebastien Roy avl_remove(&dlmgmt_name_avl, linkp); 491*2b24ab6bSSebastien Roy avl_remove(&dlmgmt_id_avl, linkp); 492*2b24ab6bSSebastien Roy goto done; 493*2b24ab6bSSebastien Roy } 494*2b24ab6bSSebastien Roy 495*2b24ab6bSSebastien Roy linkp->ll_flags = flags; 496d62bc4baSyz147064 dlmgmt_advance(linkp); 497d62bc4baSyz147064 *linkpp = linkp; 498*2b24ab6bSSebastien Roy 499*2b24ab6bSSebastien Roy done: 500*2b24ab6bSSebastien Roy if (err != 0) 501*2b24ab6bSSebastien Roy free(linkp); 502*2b24ab6bSSebastien Roy return (err); 503d62bc4baSyz147064 } 504d62bc4baSyz147064 505d62bc4baSyz147064 int 506d62bc4baSyz147064 dlmgmt_destroy_common(dlmgmt_link_t *linkp, uint32_t flags) 507d62bc4baSyz147064 { 508d62bc4baSyz147064 if ((linkp->ll_flags & flags) == 0) { 509d62bc4baSyz147064 /* 510d62bc4baSyz147064 * The link does not exist in the specified space. 511d62bc4baSyz147064 */ 512d62bc4baSyz147064 return (ENOENT); 513d62bc4baSyz147064 } 514*2b24ab6bSSebastien Roy 515d62bc4baSyz147064 linkp->ll_flags &= ~flags; 516*2b24ab6bSSebastien Roy if (flags & DLMGMT_PERSIST) { 517d62bc4baSyz147064 dlmgmt_linkattr_t *next, *attrp; 518d62bc4baSyz147064 519d62bc4baSyz147064 for (attrp = linkp->ll_head; attrp != NULL; attrp = next) { 520d62bc4baSyz147064 next = attrp->lp_next; 521d62bc4baSyz147064 free(attrp->lp_val); 522d62bc4baSyz147064 free(attrp); 523d62bc4baSyz147064 } 524d62bc4baSyz147064 linkp->ll_head = NULL; 525d62bc4baSyz147064 } 526d62bc4baSyz147064 527*2b24ab6bSSebastien Roy if ((flags & DLMGMT_ACTIVE) && linkp->ll_zoneid != GLOBAL_ZONEID) { 528*2b24ab6bSSebastien Roy (void) zone_remove_datalink(linkp->ll_zoneid, linkp->ll_linkid); 529*2b24ab6bSSebastien Roy if (linkp->ll_onloan) 530*2b24ab6bSSebastien Roy avl_remove(&dlmgmt_loan_avl, linkp); 531*2b24ab6bSSebastien Roy } 532*2b24ab6bSSebastien Roy 533d62bc4baSyz147064 if (linkp->ll_flags == 0) { 534d62bc4baSyz147064 avl_remove(&dlmgmt_id_avl, linkp); 535d62bc4baSyz147064 avl_remove(&dlmgmt_name_avl, linkp); 536d62bc4baSyz147064 link_destroy(linkp); 537d62bc4baSyz147064 } 538d62bc4baSyz147064 539d62bc4baSyz147064 return (0); 540d62bc4baSyz147064 } 541d62bc4baSyz147064 542*2b24ab6bSSebastien Roy int 543d62bc4baSyz147064 dlmgmt_getattr_common(dlmgmt_linkattr_t **headp, const char *attr, 544024b0a25Sseb dlmgmt_getattr_retval_t *retvalp) 545d62bc4baSyz147064 { 546d62bc4baSyz147064 int err; 547d62bc4baSyz147064 void *attrval; 548d62bc4baSyz147064 size_t attrsz; 549d62bc4baSyz147064 dladm_datatype_t attrtype; 550d62bc4baSyz147064 551d62bc4baSyz147064 err = linkattr_get(headp, attr, &attrval, &attrsz, &attrtype); 552d62bc4baSyz147064 if (err != 0) 553*2b24ab6bSSebastien Roy return (err); 554d62bc4baSyz147064 555d62bc4baSyz147064 assert(attrsz > 0); 556*2b24ab6bSSebastien Roy if (attrsz > MAXLINKATTRVALLEN) 557*2b24ab6bSSebastien Roy return (EINVAL); 558d62bc4baSyz147064 559d62bc4baSyz147064 retvalp->lr_type = attrtype; 560024b0a25Sseb retvalp->lr_attrsz = attrsz; 561024b0a25Sseb bcopy(attrval, retvalp->lr_attrval, attrsz); 562*2b24ab6bSSebastien Roy return (0); 563d62bc4baSyz147064 } 564d62bc4baSyz147064 565d62bc4baSyz147064 void 566d62bc4baSyz147064 dlmgmt_dlconf_table_lock(boolean_t write) 567d62bc4baSyz147064 { 568d62bc4baSyz147064 if (write) 569d62bc4baSyz147064 (void) pthread_rwlock_wrlock(&dlmgmt_dlconf_lock); 570d62bc4baSyz147064 else 571d62bc4baSyz147064 (void) pthread_rwlock_rdlock(&dlmgmt_dlconf_lock); 572d62bc4baSyz147064 } 573d62bc4baSyz147064 574d62bc4baSyz147064 void 575*2b24ab6bSSebastien Roy dlmgmt_dlconf_table_unlock(void) 576d62bc4baSyz147064 { 577d62bc4baSyz147064 (void) pthread_rwlock_unlock(&dlmgmt_dlconf_lock); 578d62bc4baSyz147064 } 579d62bc4baSyz147064 580d62bc4baSyz147064 int 581d62bc4baSyz147064 dlconf_create(const char *name, datalink_id_t linkid, datalink_class_t class, 582*2b24ab6bSSebastien Roy uint32_t media, zoneid_t zoneid, dlmgmt_dlconf_t **dlconfpp) 583d62bc4baSyz147064 { 584d62bc4baSyz147064 dlmgmt_dlconf_t *dlconfp = NULL; 585d62bc4baSyz147064 int err = 0; 586d62bc4baSyz147064 587d62bc4baSyz147064 if (dlmgmt_nextconfid == 0) { 588d62bc4baSyz147064 err = ENOSPC; 589d62bc4baSyz147064 goto done; 590d62bc4baSyz147064 } 591d62bc4baSyz147064 592d62bc4baSyz147064 if ((dlconfp = calloc(1, sizeof (dlmgmt_dlconf_t))) == NULL) { 593d62bc4baSyz147064 err = ENOMEM; 594d62bc4baSyz147064 goto done; 595d62bc4baSyz147064 } 596d62bc4baSyz147064 597d62bc4baSyz147064 (void) strlcpy(dlconfp->ld_link, name, MAXLINKNAMELEN); 598d62bc4baSyz147064 dlconfp->ld_linkid = linkid; 599d62bc4baSyz147064 dlconfp->ld_class = class; 600d62bc4baSyz147064 dlconfp->ld_media = media; 601d62bc4baSyz147064 dlconfp->ld_id = dlmgmt_nextconfid; 602*2b24ab6bSSebastien Roy dlconfp->ld_zoneid = zoneid; 603d62bc4baSyz147064 604d62bc4baSyz147064 done: 605d62bc4baSyz147064 *dlconfpp = dlconfp; 606d62bc4baSyz147064 return (err); 607d62bc4baSyz147064 } 608d62bc4baSyz147064 609d62bc4baSyz147064 void 610d62bc4baSyz147064 dlconf_destroy(dlmgmt_dlconf_t *dlconfp) 611d62bc4baSyz147064 { 612d62bc4baSyz147064 dlmgmt_linkattr_t *next, *attrp; 613d62bc4baSyz147064 614d62bc4baSyz147064 for (attrp = dlconfp->ld_head; attrp != NULL; attrp = next) { 615d62bc4baSyz147064 next = attrp->lp_next; 616d62bc4baSyz147064 free(attrp->lp_val); 617d62bc4baSyz147064 free(attrp); 618d62bc4baSyz147064 } 619d62bc4baSyz147064 free(dlconfp); 620d62bc4baSyz147064 } 621d62bc4baSyz147064 622d62bc4baSyz147064 int 623*2b24ab6bSSebastien Roy dlmgmt_generate_name(const char *prefix, char *name, size_t size, 624*2b24ab6bSSebastien Roy zoneid_t zoneid) 625d62bc4baSyz147064 { 626d62bc4baSyz147064 dlmgmt_prefix_t *lpp, *prev = NULL; 627*2b24ab6bSSebastien Roy dlmgmt_link_t link, *linkp; 628d62bc4baSyz147064 629d62bc4baSyz147064 /* 630d62bc4baSyz147064 * See whether the requested prefix is already in the list. 631d62bc4baSyz147064 */ 632*2b24ab6bSSebastien Roy for (lpp = &dlmgmt_prefixlist; lpp != NULL; 633*2b24ab6bSSebastien Roy prev = lpp, lpp = lpp->lp_next) { 634*2b24ab6bSSebastien Roy if (lpp->lp_zoneid == zoneid && 635*2b24ab6bSSebastien Roy strcmp(prefix, lpp->lp_prefix) == 0) 636d62bc4baSyz147064 break; 637d62bc4baSyz147064 } 638d62bc4baSyz147064 639d62bc4baSyz147064 /* 640d62bc4baSyz147064 * Not found. 641d62bc4baSyz147064 */ 642d62bc4baSyz147064 if (lpp == NULL) { 643d62bc4baSyz147064 assert(prev != NULL); 644d62bc4baSyz147064 645d62bc4baSyz147064 /* 646d62bc4baSyz147064 * First add this new prefix into the prefix list. 647d62bc4baSyz147064 */ 648d62bc4baSyz147064 if ((lpp = malloc(sizeof (dlmgmt_prefix_t))) == NULL) 649d62bc4baSyz147064 return (ENOMEM); 650d62bc4baSyz147064 651d62bc4baSyz147064 prev->lp_next = lpp; 652d62bc4baSyz147064 lpp->lp_next = NULL; 653*2b24ab6bSSebastien Roy lpp->lp_zoneid = zoneid; 654d62bc4baSyz147064 lpp->lp_nextppa = 0; 655d62bc4baSyz147064 (void) strlcpy(lpp->lp_prefix, prefix, MAXLINKNAMELEN); 656d62bc4baSyz147064 657d62bc4baSyz147064 /* 658d62bc4baSyz147064 * Now determine this prefix's nextppa. 659d62bc4baSyz147064 */ 660d62bc4baSyz147064 (void) snprintf(link.ll_link, MAXLINKNAMELEN, "%s%d", 661*2b24ab6bSSebastien Roy prefix, 0); 662*2b24ab6bSSebastien Roy link.ll_zoneid = zoneid; 663*2b24ab6bSSebastien Roy if ((linkp = avl_find(&dlmgmt_name_avl, &link, NULL)) != NULL) 664d62bc4baSyz147064 dlmgmt_advance_ppa(linkp); 665d62bc4baSyz147064 } 666d62bc4baSyz147064 667d62bc4baSyz147064 if (lpp->lp_nextppa == (uint_t)-1) 668d62bc4baSyz147064 return (ENOSPC); 669d62bc4baSyz147064 670d62bc4baSyz147064 (void) snprintf(name, size, "%s%d", prefix, lpp->lp_nextppa); 671d62bc4baSyz147064 return (0); 672d62bc4baSyz147064 } 673d62bc4baSyz147064 674d62bc4baSyz147064 /* 675d62bc4baSyz147064 * Advance the next available ppa value if the name prefix of the current 676d62bc4baSyz147064 * link is in the prefix list. 677d62bc4baSyz147064 */ 678d62bc4baSyz147064 static void 679d62bc4baSyz147064 dlmgmt_advance_ppa(dlmgmt_link_t *linkp) 680d62bc4baSyz147064 { 681d62bc4baSyz147064 dlmgmt_prefix_t *lpp; 682d62bc4baSyz147064 char prefix[MAXLINKNAMELEN]; 683*2b24ab6bSSebastien Roy char linkname[MAXLINKNAMELEN]; 684d62bc4baSyz147064 uint_t start, ppa; 685d62bc4baSyz147064 686d62bc4baSyz147064 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa); 687d62bc4baSyz147064 688d62bc4baSyz147064 /* 689d62bc4baSyz147064 * See whether the requested prefix is already in the list. 690d62bc4baSyz147064 */ 691*2b24ab6bSSebastien Roy for (lpp = &dlmgmt_prefixlist; lpp != NULL; lpp = lpp->lp_next) { 692*2b24ab6bSSebastien Roy if (lpp->lp_zoneid == linkp->ll_zoneid && 693*2b24ab6bSSebastien Roy strcmp(prefix, lpp->lp_prefix) == 0) 694d62bc4baSyz147064 break; 695d62bc4baSyz147064 } 696d62bc4baSyz147064 697d62bc4baSyz147064 /* 698d62bc4baSyz147064 * If the link name prefix is in the list, advance the 699d62bc4baSyz147064 * next available ppa for the <prefix>N name. 700d62bc4baSyz147064 */ 701d62bc4baSyz147064 if (lpp == NULL || lpp->lp_nextppa != ppa) 702d62bc4baSyz147064 return; 703d62bc4baSyz147064 704d62bc4baSyz147064 start = lpp->lp_nextppa++; 705d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); 706d62bc4baSyz147064 while (lpp->lp_nextppa != start) { 707d62bc4baSyz147064 if (lpp->lp_nextppa == (uint_t)-1) { 708d62bc4baSyz147064 /* 709d62bc4baSyz147064 * wrapped around. search from <prefix>1. 710d62bc4baSyz147064 */ 711d62bc4baSyz147064 lpp->lp_nextppa = 0; 712*2b24ab6bSSebastien Roy (void) snprintf(linkname, MAXLINKNAMELEN, 713d62bc4baSyz147064 "%s%d", lpp->lp_prefix, lpp->lp_nextppa); 714*2b24ab6bSSebastien Roy linkp = link_by_name(linkname, lpp->lp_zoneid); 715d62bc4baSyz147064 if (linkp == NULL) 716d62bc4baSyz147064 return; 717d62bc4baSyz147064 } else { 718d62bc4baSyz147064 if (linkp == NULL) 719d62bc4baSyz147064 return; 720d62bc4baSyz147064 (void) dlpi_parselink(linkp->ll_link, prefix, &ppa); 721d62bc4baSyz147064 if ((strcmp(prefix, lpp->lp_prefix) != 0) || 722d62bc4baSyz147064 (ppa != lpp->lp_nextppa)) { 723d62bc4baSyz147064 return; 724d62bc4baSyz147064 } 725d62bc4baSyz147064 } 726d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_name_avl, linkp); 727d62bc4baSyz147064 lpp->lp_nextppa++; 728d62bc4baSyz147064 } 729d62bc4baSyz147064 lpp->lp_nextppa = (uint_t)-1; 730d62bc4baSyz147064 } 731d62bc4baSyz147064 732d62bc4baSyz147064 /* 733d62bc4baSyz147064 * Advance to the next available linkid value. 734d62bc4baSyz147064 */ 735d62bc4baSyz147064 static void 736d62bc4baSyz147064 dlmgmt_advance_linkid(dlmgmt_link_t *linkp) 737d62bc4baSyz147064 { 738d62bc4baSyz147064 datalink_id_t start; 739d62bc4baSyz147064 740d62bc4baSyz147064 if (linkp->ll_linkid != dlmgmt_nextlinkid) 741d62bc4baSyz147064 return; 742d62bc4baSyz147064 743d62bc4baSyz147064 start = dlmgmt_nextlinkid; 744d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp); 745d62bc4baSyz147064 746d62bc4baSyz147064 do { 747d62bc4baSyz147064 if (dlmgmt_nextlinkid == DATALINK_MAX_LINKID) { 748d62bc4baSyz147064 /* 749d62bc4baSyz147064 * wrapped around. search from 1. 750d62bc4baSyz147064 */ 751d62bc4baSyz147064 dlmgmt_nextlinkid = 1; 752*2b24ab6bSSebastien Roy if ((linkp = link_by_id(1, GLOBAL_ZONEID)) == NULL) 753d62bc4baSyz147064 return; 754d62bc4baSyz147064 } else { 755d62bc4baSyz147064 dlmgmt_nextlinkid++; 756d62bc4baSyz147064 if (linkp == NULL) 757d62bc4baSyz147064 return; 758d62bc4baSyz147064 if (linkp->ll_linkid != dlmgmt_nextlinkid) 759d62bc4baSyz147064 return; 760d62bc4baSyz147064 } 761d62bc4baSyz147064 762d62bc4baSyz147064 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp); 763d62bc4baSyz147064 } while (dlmgmt_nextlinkid != start); 764d62bc4baSyz147064 765d62bc4baSyz147064 dlmgmt_nextlinkid = DATALINK_INVALID_LINKID; 766d62bc4baSyz147064 } 767d62bc4baSyz147064 768d62bc4baSyz147064 /* 769d62bc4baSyz147064 * Advance various global values, for example, next linkid value, next ppa for 770d62bc4baSyz147064 * various prefix etc. 771d62bc4baSyz147064 */ 772d62bc4baSyz147064 void 773d62bc4baSyz147064 dlmgmt_advance(dlmgmt_link_t *linkp) 774d62bc4baSyz147064 { 775d62bc4baSyz147064 dlmgmt_advance_linkid(linkp); 776d62bc4baSyz147064 dlmgmt_advance_ppa(linkp); 777d62bc4baSyz147064 } 778d62bc4baSyz147064 779d62bc4baSyz147064 /* 780d62bc4baSyz147064 * Advance to the next available dlconf id. 781d62bc4baSyz147064 */ 782d62bc4baSyz147064 void 783d62bc4baSyz147064 dlmgmt_advance_dlconfid(dlmgmt_dlconf_t *dlconfp) 784d62bc4baSyz147064 { 785d62bc4baSyz147064 uint_t start; 786d62bc4baSyz147064 787d62bc4baSyz147064 start = dlmgmt_nextconfid++; 788d62bc4baSyz147064 dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp); 789d62bc4baSyz147064 while (dlmgmt_nextconfid != start) { 790d62bc4baSyz147064 if (dlmgmt_nextconfid == 0) { 791d62bc4baSyz147064 dlmgmt_dlconf_t dlconf; 792d62bc4baSyz147064 793d62bc4baSyz147064 /* 794d62bc4baSyz147064 * wrapped around. search from 1. 795d62bc4baSyz147064 */ 796d62bc4baSyz147064 dlconf.ld_id = dlmgmt_nextconfid = 1; 797a73e6fc1SCathy Zhou dlconfp = avl_find(&dlmgmt_dlconf_avl, &dlconf, NULL); 798d62bc4baSyz147064 if (dlconfp == NULL) 799d62bc4baSyz147064 return; 800d62bc4baSyz147064 } else { 801d62bc4baSyz147064 if ((dlconfp == NULL) || 802d62bc4baSyz147064 (dlconfp->ld_id != dlmgmt_nextconfid)) { 803d62bc4baSyz147064 return; 804d62bc4baSyz147064 } 805d62bc4baSyz147064 } 806a73e6fc1SCathy Zhou dlconfp = AVL_NEXT(&dlmgmt_dlconf_avl, dlconfp); 807d62bc4baSyz147064 dlmgmt_nextconfid++; 808d62bc4baSyz147064 } 809d62bc4baSyz147064 dlmgmt_nextconfid = 0; 810d62bc4baSyz147064 } 811