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 /* 27 * This RCM module adds support to the RCM framework for VLAN links 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <errno.h> 34 #include <sys/types.h> 35 #include <synch.h> 36 #include <assert.h> 37 #include <strings.h> 38 #include "rcm_module.h" 39 #include <libintl.h> 40 #include <libdllink.h> 41 #include <libdlvlan.h> 42 #include <libdlpi.h> 43 44 /* 45 * Definitions 46 */ 47 #ifndef lint 48 #define _(x) gettext(x) 49 #else 50 #define _(x) x 51 #endif 52 53 /* Some generic well-knowns and defaults used in this module */ 54 #define RCM_LINK_PREFIX "SUNW_datalink" /* RCM datalink name prefix */ 55 #define RCM_LINK_RESOURCE_MAX (13 + LINKID_STR_WIDTH) 56 57 /* VLAN link flags */ 58 typedef enum { 59 VLAN_OFFLINED = 0x1, 60 VLAN_CONSUMER_OFFLINED = 0x2, 61 VLAN_STALE = 0x4 62 } vlan_flag_t; 63 64 /* link representation */ 65 typedef struct dl_vlan { 66 struct dl_vlan *dv_next; /* next VLAN on the same link */ 67 struct dl_vlan *dv_prev; /* prev VLAN on the same link */ 68 datalink_id_t dv_vlanid; 69 vlan_flag_t dv_flags; /* VLAN link flags */ 70 } dl_vlan_t; 71 72 /* VLAN Cache state flags */ 73 typedef enum { 74 CACHE_NODE_STALE = 0x1, /* stale cached data */ 75 CACHE_NODE_NEW = 0x2, /* new cached nodes */ 76 CACHE_NODE_OFFLINED = 0x4 /* nodes offlined */ 77 } cache_node_state_t; 78 79 /* Network Cache lookup options */ 80 #define CACHE_NO_REFRESH 0x1 /* cache refresh not needed */ 81 #define CACHE_REFRESH 0x2 /* refresh cache */ 82 83 /* Cache element */ 84 typedef struct link_cache { 85 struct link_cache *vc_next; /* next cached resource */ 86 struct link_cache *vc_prev; /* prev cached resource */ 87 char *vc_resource; /* resource name */ 88 datalink_id_t vc_linkid; /* linkid */ 89 dl_vlan_t *vc_vlan; /* VLAN list on this link */ 90 cache_node_state_t vc_state; /* cache state flags */ 91 } link_cache_t; 92 93 /* 94 * Global cache for network VLANs 95 */ 96 static link_cache_t cache_head; 97 static link_cache_t cache_tail; 98 static mutex_t cache_lock; 99 static int events_registered = 0; 100 101 static dladm_handle_t dld_handle = NULL; 102 103 /* 104 * RCM module interface prototypes 105 */ 106 static int vlan_register(rcm_handle_t *); 107 static int vlan_unregister(rcm_handle_t *); 108 static int vlan_get_info(rcm_handle_t *, char *, id_t, uint_t, 109 char **, char **, nvlist_t *, rcm_info_t **); 110 static int vlan_suspend(rcm_handle_t *, char *, id_t, 111 timespec_t *, uint_t, char **, rcm_info_t **); 112 static int vlan_resume(rcm_handle_t *, char *, id_t, uint_t, 113 char **, rcm_info_t **); 114 static int vlan_offline(rcm_handle_t *, char *, id_t, uint_t, 115 char **, rcm_info_t **); 116 static int vlan_undo_offline(rcm_handle_t *, char *, id_t, uint_t, 117 char **, rcm_info_t **); 118 static int vlan_remove(rcm_handle_t *, char *, id_t, uint_t, 119 char **, rcm_info_t **); 120 static int vlan_notify_event(rcm_handle_t *, char *, id_t, uint_t, 121 char **, nvlist_t *, rcm_info_t **); 122 static int vlan_configure(rcm_handle_t *, datalink_id_t); 123 124 /* Module private routines */ 125 static void cache_free(); 126 static int cache_update(rcm_handle_t *); 127 static void cache_remove(link_cache_t *); 128 static void node_free(link_cache_t *); 129 static void cache_insert(link_cache_t *); 130 static link_cache_t *cache_lookup(rcm_handle_t *, char *, char); 131 static int vlan_consumer_offline(rcm_handle_t *, link_cache_t *, 132 char **, uint_t, rcm_info_t **); 133 static void vlan_consumer_online(rcm_handle_t *, link_cache_t *, 134 char **, uint_t, rcm_info_t **); 135 static int vlan_offline_vlan(link_cache_t *, uint32_t, 136 cache_node_state_t); 137 static void vlan_online_vlan(link_cache_t *); 138 static char *vlan_usage(link_cache_t *); 139 static void vlan_log_err(datalink_id_t, char **, char *); 140 static int vlan_consumer_notify(rcm_handle_t *, datalink_id_t, 141 char **, uint_t, rcm_info_t **); 142 143 /* Module-Private data */ 144 static struct rcm_mod_ops vlan_ops = 145 { 146 RCM_MOD_OPS_VERSION, 147 vlan_register, 148 vlan_unregister, 149 vlan_get_info, 150 vlan_suspend, 151 vlan_resume, 152 vlan_offline, 153 vlan_undo_offline, 154 vlan_remove, 155 NULL, 156 NULL, 157 vlan_notify_event 158 }; 159 160 /* 161 * rcm_mod_init() - Update registrations, and return the ops structure. 162 */ 163 struct rcm_mod_ops * 164 rcm_mod_init(void) 165 { 166 dladm_status_t status; 167 char errmsg[DLADM_STRSIZE]; 168 169 rcm_log_message(RCM_TRACE1, "VLAN: mod_init\n"); 170 171 cache_head.vc_next = &cache_tail; 172 cache_head.vc_prev = NULL; 173 cache_tail.vc_prev = &cache_head; 174 cache_tail.vc_next = NULL; 175 (void) mutex_init(&cache_lock, 0, NULL); 176 177 if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) { 178 rcm_log_message(RCM_WARNING, 179 "VLAN: mod_init failed: cannot open datalink handle: %s\n", 180 dladm_status2str(status, errmsg)); 181 return (NULL); 182 } 183 184 /* Return the ops vectors */ 185 return (&vlan_ops); 186 } 187 188 /* 189 * rcm_mod_info() - Return a string describing this module. 190 */ 191 const char * 192 rcm_mod_info(void) 193 { 194 rcm_log_message(RCM_TRACE1, "VLAN: mod_info\n"); 195 196 return ("VLAN module version 1.2"); 197 } 198 199 /* 200 * rcm_mod_fini() - Destroy the network VLAN cache. 201 */ 202 int 203 rcm_mod_fini(void) 204 { 205 rcm_log_message(RCM_TRACE1, "VLAN: mod_fini\n"); 206 207 /* 208 * Note that vlan_unregister() does not seem to be called anywhere, 209 * therefore we free the cache nodes here. In theory we should call 210 * rcm_register_interest() for each node before we free it, the 211 * framework does not provide the rcm_handle to allow us to do so. 212 */ 213 cache_free(); 214 (void) mutex_destroy(&cache_lock); 215 216 dladm_close(dld_handle); 217 return (RCM_SUCCESS); 218 } 219 220 /* 221 * vlan_register() - Make sure the cache is properly sync'ed, and its 222 * registrations are in order. 223 */ 224 static int 225 vlan_register(rcm_handle_t *hd) 226 { 227 rcm_log_message(RCM_TRACE1, "VLAN: register\n"); 228 229 if (cache_update(hd) < 0) 230 return (RCM_FAILURE); 231 232 /* 233 * Need to register interest in all new resources 234 * getting attached, so we get attach event notifications 235 */ 236 if (!events_registered) { 237 if (rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL) 238 != RCM_SUCCESS) { 239 rcm_log_message(RCM_ERROR, 240 _("VLAN: failed to register %s\n"), 241 RCM_RESOURCE_LINK_NEW); 242 return (RCM_FAILURE); 243 } else { 244 rcm_log_message(RCM_DEBUG, "VLAN: registered %s\n", 245 RCM_RESOURCE_LINK_NEW); 246 events_registered++; 247 } 248 } 249 250 return (RCM_SUCCESS); 251 } 252 253 /* 254 * vlan_unregister() - Walk the cache, unregistering all the networks. 255 */ 256 static int 257 vlan_unregister(rcm_handle_t *hd) 258 { 259 link_cache_t *node; 260 261 rcm_log_message(RCM_TRACE1, "VLAN: unregister\n"); 262 263 /* Walk the cache, unregistering everything */ 264 (void) mutex_lock(&cache_lock); 265 node = cache_head.vc_next; 266 while (node != &cache_tail) { 267 if (rcm_unregister_interest(hd, node->vc_resource, 0) 268 != RCM_SUCCESS) { 269 rcm_log_message(RCM_ERROR, 270 _("VLAN: failed to unregister %s\n"), 271 node->vc_resource); 272 (void) mutex_unlock(&cache_lock); 273 return (RCM_FAILURE); 274 } 275 cache_remove(node); 276 node_free(node); 277 node = cache_head.vc_next; 278 } 279 (void) mutex_unlock(&cache_lock); 280 281 /* 282 * Unregister interest in all new resources 283 */ 284 if (events_registered) { 285 if (rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0) 286 != RCM_SUCCESS) { 287 rcm_log_message(RCM_ERROR, 288 _("VLAN: failed to unregister %s\n"), 289 RCM_RESOURCE_LINK_NEW); 290 return (RCM_FAILURE); 291 } else { 292 rcm_log_message(RCM_DEBUG, "VLAN: unregistered %s\n", 293 RCM_RESOURCE_LINK_NEW); 294 events_registered--; 295 } 296 } 297 298 return (RCM_SUCCESS); 299 } 300 301 /* 302 * vlan_offline() - Offline VLANs on a specific node. 303 */ 304 static int 305 vlan_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 306 char **errorp, rcm_info_t **info) 307 { 308 link_cache_t *node; 309 310 rcm_log_message(RCM_TRACE1, "VLAN: offline(%s)\n", rsrc); 311 312 /* Lock the cache and lookup the resource */ 313 (void) mutex_lock(&cache_lock); 314 node = cache_lookup(hd, rsrc, CACHE_REFRESH); 315 if (node == NULL) { 316 /* should not happen because the resource is registered. */ 317 vlan_log_err(node->vc_linkid, errorp, "unrecognized resource"); 318 (void) mutex_unlock(&cache_lock); 319 return (RCM_SUCCESS); 320 } 321 322 /* 323 * Inform consumers (IP interfaces) of associated VLANs to be offlined 324 */ 325 if (vlan_consumer_offline(hd, node, errorp, flags, info) == 326 RCM_SUCCESS) { 327 rcm_log_message(RCM_DEBUG, 328 "VLAN: consumers agreed on offline\n"); 329 } else { 330 vlan_log_err(node->vc_linkid, errorp, 331 "consumers failed to offline"); 332 (void) mutex_unlock(&cache_lock); 333 return (RCM_FAILURE); 334 } 335 336 /* Check if it's a query */ 337 if (flags & RCM_QUERY) { 338 rcm_log_message(RCM_TRACE1, 339 "VLAN: offline query succeeded(%s)\n", rsrc); 340 (void) mutex_unlock(&cache_lock); 341 return (RCM_SUCCESS); 342 } 343 344 if (vlan_offline_vlan(node, VLAN_OFFLINED, CACHE_NODE_OFFLINED) != 345 RCM_SUCCESS) { 346 vlan_online_vlan(node); 347 vlan_log_err(node->vc_linkid, errorp, "offline failed"); 348 (void) mutex_unlock(&cache_lock); 349 return (RCM_FAILURE); 350 } 351 352 rcm_log_message(RCM_TRACE1, "VLAN: Offline succeeded(%s)\n", rsrc); 353 (void) mutex_unlock(&cache_lock); 354 return (RCM_SUCCESS); 355 } 356 357 /* 358 * vlan_undo_offline() - Undo offline of a previously offlined node. 359 */ 360 /*ARGSUSED*/ 361 static int 362 vlan_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 363 char **errorp, rcm_info_t **info) 364 { 365 link_cache_t *node; 366 367 rcm_log_message(RCM_TRACE1, "VLAN: online(%s)\n", rsrc); 368 369 (void) mutex_lock(&cache_lock); 370 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH); 371 if (node == NULL) { 372 vlan_log_err(DATALINK_INVALID_LINKID, errorp, "no such link"); 373 (void) mutex_unlock(&cache_lock); 374 errno = ENOENT; 375 return (RCM_FAILURE); 376 } 377 378 /* Check if no attempt should be made to online the link here */ 379 if (!(node->vc_state & CACHE_NODE_OFFLINED)) { 380 vlan_log_err(node->vc_linkid, errorp, "link not offlined"); 381 (void) mutex_unlock(&cache_lock); 382 errno = ENOTSUP; 383 return (RCM_SUCCESS); 384 } 385 386 vlan_online_vlan(node); 387 388 /* 389 * Inform IP interfaces on associated VLANs to be onlined 390 */ 391 vlan_consumer_online(hd, node, errorp, flags, info); 392 393 node->vc_state &= ~CACHE_NODE_OFFLINED; 394 rcm_log_message(RCM_TRACE1, "VLAN: online succeeded(%s)\n", rsrc); 395 (void) mutex_unlock(&cache_lock); 396 return (RCM_SUCCESS); 397 } 398 399 static void 400 vlan_online_vlan(link_cache_t *node) 401 { 402 dl_vlan_t *vlan; 403 dladm_status_t status; 404 char errmsg[DLADM_STRSIZE]; 405 406 /* 407 * Try to bring on all offlined VLANs 408 */ 409 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) { 410 if (!(vlan->dv_flags & VLAN_OFFLINED)) 411 continue; 412 413 if ((status = dladm_vlan_up(dld_handle, vlan->dv_vlanid)) != 414 DLADM_STATUS_OK) { 415 /* 416 * Print a warning message and continue to online 417 * other VLANs. 418 */ 419 rcm_log_message(RCM_WARNING, 420 _("VLAN: VLAN online failed (%u): %s\n"), 421 vlan->dv_vlanid, dladm_status2str(status, errmsg)); 422 } else { 423 vlan->dv_flags &= ~VLAN_OFFLINED; 424 } 425 } 426 } 427 428 static int 429 vlan_offline_vlan(link_cache_t *node, uint32_t flags, cache_node_state_t state) 430 { 431 dl_vlan_t *vlan; 432 dladm_status_t status; 433 char errmsg[DLADM_STRSIZE]; 434 435 rcm_log_message(RCM_TRACE2, "VLAN: vlan_offline_vlan (%s %u %u)\n", 436 node->vc_resource, flags, state); 437 438 /* 439 * Try to delete all explicit created VLAN 440 */ 441 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) { 442 if ((status = dladm_vlan_delete(dld_handle, vlan->dv_vlanid, 443 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 444 rcm_log_message(RCM_WARNING, 445 _("VLAN: VLAN offline failed (%u): %s\n"), 446 vlan->dv_vlanid, dladm_status2str(status, errmsg)); 447 return (RCM_FAILURE); 448 } else { 449 rcm_log_message(RCM_TRACE1, 450 "VLAN: VLAN offline succeeded(%u)\n", 451 vlan->dv_vlanid); 452 vlan->dv_flags |= flags; 453 } 454 } 455 456 node->vc_state |= state; 457 return (RCM_SUCCESS); 458 } 459 460 /* 461 * vlan_get_info() - Gather usage information for this resource. 462 */ 463 /*ARGSUSED*/ 464 int 465 vlan_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 466 char **usagep, char **errorp, nvlist_t *props, rcm_info_t **info) 467 { 468 link_cache_t *node; 469 470 rcm_log_message(RCM_TRACE1, "VLAN: get_info(%s)\n", rsrc); 471 472 (void) mutex_lock(&cache_lock); 473 node = cache_lookup(hd, rsrc, CACHE_REFRESH); 474 if (node == NULL) { 475 rcm_log_message(RCM_INFO, 476 _("VLAN: get_info(%s) unrecognized resource\n"), rsrc); 477 (void) mutex_unlock(&cache_lock); 478 errno = ENOENT; 479 return (RCM_FAILURE); 480 } 481 482 *usagep = vlan_usage(node); 483 (void) mutex_unlock(&cache_lock); 484 if (*usagep == NULL) { 485 /* most likely malloc failure */ 486 rcm_log_message(RCM_ERROR, 487 _("VLAN: get_info(%s) malloc failure\n"), rsrc); 488 (void) mutex_unlock(&cache_lock); 489 errno = ENOMEM; 490 return (RCM_FAILURE); 491 } 492 493 /* Set client/role properties */ 494 (void) nvlist_add_string(props, RCM_CLIENT_NAME, "VLAN"); 495 496 rcm_log_message(RCM_TRACE1, "VLAN: get_info(%s) info = %s\n", 497 rsrc, *usagep); 498 return (RCM_SUCCESS); 499 } 500 501 /* 502 * vlan_suspend() - Nothing to do, always okay 503 */ 504 /*ARGSUSED*/ 505 static int 506 vlan_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval, 507 uint_t flags, char **errorp, rcm_info_t **info) 508 { 509 rcm_log_message(RCM_TRACE1, "VLAN: suspend(%s)\n", rsrc); 510 return (RCM_SUCCESS); 511 } 512 513 /* 514 * vlan_resume() - Nothing to do, always okay 515 */ 516 /*ARGSUSED*/ 517 static int 518 vlan_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 519 char **errorp, rcm_info_t **info) 520 { 521 rcm_log_message(RCM_TRACE1, "VLAN: resume(%s)\n", rsrc); 522 return (RCM_SUCCESS); 523 } 524 525 /* 526 * vlan_consumer_remove() 527 * 528 * Notify VLAN consumers to remove cache. 529 */ 530 static int 531 vlan_consumer_remove(rcm_handle_t *hd, link_cache_t *node, uint_t flags, 532 rcm_info_t **info) 533 { 534 dl_vlan_t *vlan = NULL; 535 char rsrc[RCM_LINK_RESOURCE_MAX]; 536 int ret = RCM_SUCCESS; 537 538 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_remove (%s)\n", 539 node->vc_resource); 540 541 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) { 542 543 /* 544 * This will only be called when the offline operation 545 * succeeds, so the VLAN consumers must have been offlined 546 * at this point. 547 */ 548 assert(vlan->dv_flags & VLAN_CONSUMER_OFFLINED); 549 550 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", 551 RCM_LINK_PREFIX, vlan->dv_vlanid); 552 553 ret = rcm_notify_remove(hd, rsrc, flags, info); 554 if (ret != RCM_SUCCESS) { 555 rcm_log_message(RCM_WARNING, 556 _("VLAN: notify remove failed (%s)\n"), rsrc); 557 break; 558 } 559 } 560 561 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_remove done\n"); 562 return (ret); 563 } 564 565 /* 566 * vlan_remove() - remove a resource from cache 567 */ 568 /*ARGSUSED*/ 569 static int 570 vlan_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 571 char **errorp, rcm_info_t **info) 572 { 573 link_cache_t *node; 574 int rv; 575 576 rcm_log_message(RCM_TRACE1, "VLAN: remove(%s)\n", rsrc); 577 578 (void) mutex_lock(&cache_lock); 579 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH); 580 if (node == NULL) { 581 rcm_log_message(RCM_INFO, 582 _("VLAN: remove(%s) unrecognized resource\n"), rsrc); 583 (void) mutex_unlock(&cache_lock); 584 errno = ENOENT; 585 return (RCM_FAILURE); 586 } 587 588 /* remove the cached entry for the resource */ 589 cache_remove(node); 590 (void) mutex_unlock(&cache_lock); 591 592 rv = vlan_consumer_remove(hd, node, flags, info); 593 node_free(node); 594 return (rv); 595 } 596 597 /* 598 * vlan_notify_event - Project private implementation to receive new resource 599 * events. It intercepts all new resource events. If the 600 * new resource is a network resource, pass up a notify 601 * for it too. The new resource need not be cached, since 602 * it is done at register again. 603 */ 604 /*ARGSUSED*/ 605 static int 606 vlan_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 607 char **errorp, nvlist_t *nvl, rcm_info_t **info) 608 { 609 nvpair_t *nvp = NULL; 610 datalink_id_t linkid; 611 uint64_t id64; 612 int rv = RCM_SUCCESS; 613 614 rcm_log_message(RCM_TRACE1, "VLAN: notify_event(%s)\n", rsrc); 615 616 if (strcmp(rsrc, RCM_RESOURCE_LINK_NEW) != 0) { 617 vlan_log_err(DATALINK_INVALID_LINKID, errorp, 618 "unrecognized event"); 619 errno = EINVAL; 620 return (RCM_FAILURE); 621 } 622 623 /* Update cache to reflect latest VLANs */ 624 if (cache_update(hd) < 0) { 625 vlan_log_err(DATALINK_INVALID_LINKID, errorp, 626 "private Cache update failed"); 627 return (RCM_FAILURE); 628 } 629 630 /* 631 * Try best to recover all configuration. 632 */ 633 rcm_log_message(RCM_DEBUG, "VLAN: process_nvlist\n"); 634 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { 635 if (strcmp(nvpair_name(nvp), RCM_NV_LINKID) != 0) 636 continue; 637 638 if (nvpair_value_uint64(nvp, &id64) != 0) { 639 vlan_log_err(DATALINK_INVALID_LINKID, errorp, 640 "cannot get linkid"); 641 rv = RCM_FAILURE; 642 continue; 643 } 644 645 linkid = (datalink_id_t)id64; 646 if (vlan_configure(hd, linkid) != 0) { 647 vlan_log_err(linkid, errorp, "configuring failed"); 648 rv = RCM_FAILURE; 649 continue; 650 } 651 652 /* Notify all VLAN consumers */ 653 if (vlan_consumer_notify(hd, linkid, errorp, flags, 654 info) != 0) { 655 vlan_log_err(linkid, errorp, "consumer notify failed"); 656 rv = RCM_FAILURE; 657 } 658 } 659 660 rcm_log_message(RCM_TRACE1, 661 "VLAN: notify_event: link configuration complete\n"); 662 return (rv); 663 } 664 665 /* 666 * vlan_usage - Determine the usage of a link. 667 * The returned buffer is owned by caller, and the caller 668 * must free it up when done. 669 */ 670 static char * 671 vlan_usage(link_cache_t *node) 672 { 673 dl_vlan_t *vlan; 674 int nvlan; 675 char *buf; 676 const char *fmt; 677 char *sep; 678 char errmsg[DLADM_STRSIZE]; 679 char name[MAXLINKNAMELEN]; 680 dladm_status_t status; 681 size_t bufsz; 682 683 rcm_log_message(RCM_TRACE2, "VLAN: usage(%s)\n", node->vc_resource); 684 685 assert(MUTEX_HELD(&cache_lock)); 686 if ((status = dladm_datalink_id2info(dld_handle, node->vc_linkid, NULL, 687 NULL, NULL, name, sizeof (name))) != DLADM_STATUS_OK) { 688 rcm_log_message(RCM_ERROR, 689 _("VLAN: usage(%s) get link name failure(%s)\n"), 690 node->vc_resource, dladm_status2str(status, errmsg)); 691 return (NULL); 692 } 693 694 if (node->vc_state & CACHE_NODE_OFFLINED) 695 fmt = _("%1$s offlined"); 696 else 697 fmt = _("%1$s VLANs: "); 698 699 /* TRANSLATION_NOTE: separator used between VLAN linkids */ 700 sep = _(", "); 701 702 nvlan = 0; 703 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) 704 nvlan++; 705 706 /* space for VLANs and separators, plus message */ 707 bufsz = nvlan * (MAXLINKNAMELEN + strlen(sep)) + 708 strlen(fmt) + MAXLINKNAMELEN + 1; 709 if ((buf = malloc(bufsz)) == NULL) { 710 rcm_log_message(RCM_ERROR, 711 _("VLAN: usage(%s) malloc failure(%s)\n"), 712 node->vc_resource, strerror(errno)); 713 return (NULL); 714 } 715 (void) snprintf(buf, bufsz, fmt, name); 716 717 if (node->vc_state & CACHE_NODE_OFFLINED) { 718 /* Nothing else to do */ 719 rcm_log_message(RCM_TRACE2, "VLAN: usage (%s) info = %s\n", 720 node->vc_resource, buf); 721 return (buf); 722 } 723 724 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) { 725 rcm_log_message(RCM_DEBUG, "VLAN:= %u\n", vlan->dv_vlanid); 726 727 if ((status = dladm_datalink_id2info(dld_handle, 728 vlan->dv_vlanid, NULL, NULL, NULL, name, 729 sizeof (name))) != DLADM_STATUS_OK) { 730 rcm_log_message(RCM_ERROR, 731 _("VLAN: usage(%s) get vlan %u name failure(%s)\n"), 732 node->vc_resource, vlan->dv_vlanid, 733 dladm_status2str(status, errmsg)); 734 free(buf); 735 return (NULL); 736 } 737 738 (void) strlcat(buf, name, bufsz); 739 if (vlan->dv_next != NULL) 740 (void) strlcat(buf, sep, bufsz); 741 } 742 743 rcm_log_message(RCM_TRACE2, "VLAN: usage (%s) info = %s\n", 744 node->vc_resource, buf); 745 746 return (buf); 747 } 748 749 /* 750 * Cache management routines, all cache management functions should be 751 * be called with cache_lock held. 752 */ 753 754 /* 755 * cache_lookup() - Get a cache node for a resource. 756 * Call with cache lock held. 757 * 758 * This ensures that the cache is consistent with the system state and 759 * returns a pointer to the cache element corresponding to the resource. 760 */ 761 static link_cache_t * 762 cache_lookup(rcm_handle_t *hd, char *rsrc, char options) 763 { 764 link_cache_t *node; 765 766 rcm_log_message(RCM_TRACE2, "VLAN: cache lookup(%s)\n", rsrc); 767 768 assert(MUTEX_HELD(&cache_lock)); 769 if (options & CACHE_REFRESH) { 770 /* drop lock since update locks cache again */ 771 (void) mutex_unlock(&cache_lock); 772 (void) cache_update(hd); 773 (void) mutex_lock(&cache_lock); 774 } 775 776 node = cache_head.vc_next; 777 for (; node != &cache_tail; node = node->vc_next) { 778 if (strcmp(rsrc, node->vc_resource) == 0) { 779 rcm_log_message(RCM_TRACE2, 780 "VLAN: cache lookup succeeded(%s)\n", rsrc); 781 return (node); 782 } 783 } 784 return (NULL); 785 } 786 787 /* 788 * node_free - Free a node from the cache 789 */ 790 static void 791 node_free(link_cache_t *node) 792 { 793 dl_vlan_t *vlan, *next; 794 795 if (node != NULL) { 796 free(node->vc_resource); 797 798 /* free the VLAN list */ 799 for (vlan = node->vc_vlan; vlan != NULL; vlan = next) { 800 next = vlan->dv_next; 801 free(vlan); 802 } 803 free(node); 804 } 805 } 806 807 /* 808 * cache_insert - Insert a resource node in cache 809 */ 810 static void 811 cache_insert(link_cache_t *node) 812 { 813 assert(MUTEX_HELD(&cache_lock)); 814 815 /* insert at the head for best performance */ 816 node->vc_next = cache_head.vc_next; 817 node->vc_prev = &cache_head; 818 819 node->vc_next->vc_prev = node; 820 node->vc_prev->vc_next = node; 821 } 822 823 /* 824 * cache_remove() - Remove a resource node from cache. 825 */ 826 static void 827 cache_remove(link_cache_t *node) 828 { 829 assert(MUTEX_HELD(&cache_lock)); 830 node->vc_next->vc_prev = node->vc_prev; 831 node->vc_prev->vc_next = node->vc_next; 832 node->vc_next = NULL; 833 node->vc_prev = NULL; 834 } 835 836 typedef struct vlan_update_arg_s { 837 rcm_handle_t *hd; 838 int retval; 839 } vlan_update_arg_t; 840 841 /* 842 * vlan_update() - Update physical interface properties 843 */ 844 static int 845 vlan_update(dladm_handle_t handle, datalink_id_t vlanid, void *arg) 846 { 847 vlan_update_arg_t *vlan_update_argp = arg; 848 rcm_handle_t *hd = vlan_update_argp->hd; 849 link_cache_t *node; 850 dl_vlan_t *vlan; 851 char *rsrc; 852 dladm_vlan_attr_t vlan_attr; 853 dladm_status_t status; 854 char errmsg[DLADM_STRSIZE]; 855 boolean_t newnode = B_FALSE; 856 int ret = -1; 857 858 rcm_log_message(RCM_TRACE2, "VLAN: vlan_update(%u)\n", vlanid); 859 860 assert(MUTEX_HELD(&cache_lock)); 861 status = dladm_vlan_info(handle, vlanid, &vlan_attr, DLADM_OPT_ACTIVE); 862 if (status != DLADM_STATUS_OK) { 863 rcm_log_message(RCM_TRACE1, 864 "VLAN: vlan_update() cannot get vlan information for " 865 "%u(%s)\n", vlanid, dladm_status2str(status, errmsg)); 866 return (DLADM_WALK_CONTINUE); 867 } 868 869 rsrc = malloc(RCM_LINK_RESOURCE_MAX); 870 if (rsrc == NULL) { 871 rcm_log_message(RCM_ERROR, _("VLAN: malloc error(%s): %u\n"), 872 strerror(errno), vlanid); 873 goto done; 874 } 875 876 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", 877 RCM_LINK_PREFIX, vlan_attr.dv_linkid); 878 879 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH); 880 if (node != NULL) { 881 rcm_log_message(RCM_DEBUG, 882 "VLAN: %s already registered (vlanid:%d)\n", 883 rsrc, vlan_attr.dv_vid); 884 free(rsrc); 885 } else { 886 rcm_log_message(RCM_DEBUG, 887 "VLAN: %s is a new resource (vlanid:%d)\n", 888 rsrc, vlan_attr.dv_vid); 889 if ((node = calloc(1, sizeof (link_cache_t))) == NULL) { 890 free(rsrc); 891 rcm_log_message(RCM_ERROR, _("VLAN: calloc: %s\n"), 892 strerror(errno)); 893 goto done; 894 } 895 896 node->vc_resource = rsrc; 897 node->vc_vlan = NULL; 898 node->vc_linkid = vlan_attr.dv_linkid; 899 node->vc_state |= CACHE_NODE_NEW; 900 newnode = B_TRUE; 901 } 902 903 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) { 904 if (vlan->dv_vlanid == vlanid) { 905 vlan->dv_flags &= ~VLAN_STALE; 906 break; 907 } 908 } 909 910 if (vlan == NULL) { 911 if ((vlan = calloc(1, sizeof (dl_vlan_t))) == NULL) { 912 rcm_log_message(RCM_ERROR, _("VLAN: malloc: %s\n"), 913 strerror(errno)); 914 if (newnode) { 915 free(rsrc); 916 free(node); 917 } 918 goto done; 919 } 920 vlan->dv_vlanid = vlanid; 921 vlan->dv_next = node->vc_vlan; 922 vlan->dv_prev = NULL; 923 if (node->vc_vlan != NULL) 924 node->vc_vlan->dv_prev = vlan; 925 node->vc_vlan = vlan; 926 } 927 928 node->vc_state &= ~CACHE_NODE_STALE; 929 930 if (newnode) 931 cache_insert(node); 932 933 rcm_log_message(RCM_TRACE3, "VLAN: vlan_update: succeeded(%u)\n", 934 vlanid); 935 ret = 0; 936 done: 937 vlan_update_argp->retval = ret; 938 return (ret == 0 ? DLADM_WALK_CONTINUE : DLADM_WALK_TERMINATE); 939 } 940 941 /* 942 * vlan_update_all() - Determine all VLAN links in the system 943 */ 944 static int 945 vlan_update_all(rcm_handle_t *hd) 946 { 947 vlan_update_arg_t arg = {NULL, 0}; 948 949 rcm_log_message(RCM_TRACE2, "VLAN: vlan_update_all\n"); 950 951 assert(MUTEX_HELD(&cache_lock)); 952 arg.hd = hd; 953 (void) dladm_walk_datalink_id(vlan_update, dld_handle, &arg, 954 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 955 return (arg.retval); 956 } 957 958 /* 959 * cache_update() - Update cache with latest interface info 960 */ 961 static int 962 cache_update(rcm_handle_t *hd) 963 { 964 link_cache_t *node, *nnode; 965 dl_vlan_t *vlan; 966 int rv; 967 968 rcm_log_message(RCM_TRACE2, "VLAN: cache_update\n"); 969 970 (void) mutex_lock(&cache_lock); 971 972 /* first we walk the entire cache, marking each entry stale */ 973 node = cache_head.vc_next; 974 for (; node != &cache_tail; node = node->vc_next) { 975 node->vc_state |= CACHE_NODE_STALE; 976 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) 977 vlan->dv_flags |= VLAN_STALE; 978 } 979 980 rv = vlan_update_all(hd); 981 982 /* 983 * Continue to delete all stale nodes from the cache even 984 * vlan_update_all() failed. Unregister link that are not offlined 985 * and still in cache 986 */ 987 for (node = cache_head.vc_next; node != &cache_tail; node = nnode) { 988 dl_vlan_t *vlan, *next; 989 990 for (vlan = node->vc_vlan; vlan != NULL; vlan = next) { 991 next = vlan->dv_next; 992 993 /* clear stale VLANs */ 994 if (vlan->dv_flags & VLAN_STALE) { 995 if (vlan->dv_prev != NULL) 996 vlan->dv_prev->dv_next = next; 997 else 998 node->vc_vlan = next; 999 1000 if (next != NULL) 1001 next->dv_prev = vlan->dv_prev; 1002 free(vlan); 1003 } 1004 } 1005 1006 nnode = node->vc_next; 1007 if (node->vc_state & CACHE_NODE_STALE) { 1008 (void) rcm_unregister_interest(hd, node->vc_resource, 1009 0); 1010 rcm_log_message(RCM_DEBUG, "VLAN: unregistered %s\n", 1011 node->vc_resource); 1012 assert(node->vc_vlan == NULL); 1013 cache_remove(node); 1014 node_free(node); 1015 continue; 1016 } 1017 1018 if (!(node->vc_state & CACHE_NODE_NEW)) 1019 continue; 1020 1021 if (rcm_register_interest(hd, node->vc_resource, 0, NULL) != 1022 RCM_SUCCESS) { 1023 rcm_log_message(RCM_ERROR, 1024 _("VLAN: failed to register %s\n"), 1025 node->vc_resource); 1026 rv = -1; 1027 } else { 1028 rcm_log_message(RCM_DEBUG, "VLAN: registered %s\n", 1029 node->vc_resource); 1030 node->vc_state &= ~CACHE_NODE_NEW; 1031 } 1032 } 1033 1034 (void) mutex_unlock(&cache_lock); 1035 return (rv); 1036 } 1037 1038 /* 1039 * cache_free() - Empty the cache 1040 */ 1041 static void 1042 cache_free() 1043 { 1044 link_cache_t *node; 1045 1046 rcm_log_message(RCM_TRACE2, "VLAN: cache_free\n"); 1047 1048 (void) mutex_lock(&cache_lock); 1049 node = cache_head.vc_next; 1050 while (node != &cache_tail) { 1051 cache_remove(node); 1052 node_free(node); 1053 node = cache_head.vc_next; 1054 } 1055 (void) mutex_unlock(&cache_lock); 1056 } 1057 1058 /* 1059 * vlan_log_err() - RCM error log wrapper 1060 */ 1061 static void 1062 vlan_log_err(datalink_id_t linkid, char **errorp, char *errmsg) 1063 { 1064 char link[MAXLINKNAMELEN]; 1065 char errstr[DLADM_STRSIZE]; 1066 dladm_status_t status; 1067 int len; 1068 const char *errfmt; 1069 char *error; 1070 1071 link[0] = '\0'; 1072 if (linkid != DATALINK_INVALID_LINKID) { 1073 char rsrc[RCM_LINK_RESOURCE_MAX]; 1074 1075 (void) snprintf(rsrc, sizeof (rsrc), "%s/%u", 1076 RCM_LINK_PREFIX, linkid); 1077 1078 rcm_log_message(RCM_ERROR, _("VLAN: %s(%s)\n"), errmsg, rsrc); 1079 if ((status = dladm_datalink_id2info(dld_handle, linkid, NULL, 1080 NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) { 1081 rcm_log_message(RCM_WARNING, 1082 _("VLAN: cannot get link name for (%s) %s\n"), 1083 rsrc, dladm_status2str(status, errstr)); 1084 } 1085 } else { 1086 rcm_log_message(RCM_ERROR, _("VLAN: %s\n"), errmsg); 1087 } 1088 1089 errfmt = strlen(link) > 0 ? _("VLAN: %s(%s)") : _("VLAN: %s"); 1090 len = strlen(errfmt) + strlen(errmsg) + MAXLINKNAMELEN + 1; 1091 if ((error = malloc(len)) != NULL) { 1092 if (strlen(link) > 0) 1093 (void) snprintf(error, len, errfmt, errmsg, link); 1094 else 1095 (void) snprintf(error, len, errfmt, errmsg); 1096 } 1097 1098 if (errorp != NULL) 1099 *errorp = error; 1100 } 1101 1102 /* 1103 * vlan_consumer_online() 1104 * 1105 * Notify online to VLAN consumers. 1106 */ 1107 /* ARGSUSED */ 1108 static void 1109 vlan_consumer_online(rcm_handle_t *hd, link_cache_t *node, char **errorp, 1110 uint_t flags, rcm_info_t **info) 1111 { 1112 dl_vlan_t *vlan; 1113 char rsrc[RCM_LINK_RESOURCE_MAX]; 1114 1115 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_online (%s)\n", 1116 node->vc_resource); 1117 1118 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) { 1119 if (!(vlan->dv_flags & VLAN_CONSUMER_OFFLINED)) 1120 continue; 1121 1122 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", 1123 RCM_LINK_PREFIX, vlan->dv_vlanid); 1124 1125 if (rcm_notify_online(hd, rsrc, flags, info) == RCM_SUCCESS) 1126 vlan->dv_flags &= ~VLAN_CONSUMER_OFFLINED; 1127 } 1128 1129 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_online done\n"); 1130 } 1131 1132 /* 1133 * vlan_consumer_offline() 1134 * 1135 * Offline VLAN consumers. 1136 */ 1137 static int 1138 vlan_consumer_offline(rcm_handle_t *hd, link_cache_t *node, char **errorp, 1139 uint_t flags, rcm_info_t **info) 1140 { 1141 dl_vlan_t *vlan; 1142 char rsrc[RCM_LINK_RESOURCE_MAX]; 1143 int ret = RCM_SUCCESS; 1144 1145 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_offline (%s)\n", 1146 node->vc_resource); 1147 1148 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) { 1149 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", 1150 RCM_LINK_PREFIX, vlan->dv_vlanid); 1151 1152 ret = rcm_request_offline(hd, rsrc, flags, info); 1153 if (ret != RCM_SUCCESS) 1154 break; 1155 1156 vlan->dv_flags |= VLAN_CONSUMER_OFFLINED; 1157 } 1158 1159 if (vlan != NULL) 1160 vlan_consumer_online(hd, node, errorp, flags, info); 1161 1162 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_offline done\n"); 1163 return (ret); 1164 } 1165 1166 /* 1167 * Send RCM_RESOURCE_LINK_NEW events to other modules about new VLANs. 1168 * Return 0 on success, -1 on failure. 1169 */ 1170 static int 1171 vlan_notify_new_vlan(rcm_handle_t *hd, char *rsrc) 1172 { 1173 link_cache_t *node; 1174 dl_vlan_t *vlan; 1175 nvlist_t *nvl = NULL; 1176 uint64_t id; 1177 int ret = -1; 1178 1179 rcm_log_message(RCM_TRACE2, "VLAN: vlan_notify_new_vlan (%s)\n", rsrc); 1180 1181 (void) mutex_lock(&cache_lock); 1182 if ((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) == NULL) { 1183 (void) mutex_unlock(&cache_lock); 1184 return (0); 1185 } 1186 1187 if (nvlist_alloc(&nvl, 0, 0) != 0) { 1188 (void) mutex_unlock(&cache_lock); 1189 rcm_log_message(RCM_WARNING, 1190 _("VLAN: failed to allocate nvlist\n")); 1191 goto done; 1192 } 1193 1194 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) { 1195 rcm_log_message(RCM_TRACE2, 1196 "VLAN: vlan_notify_new_vlan add (%u)\n", 1197 vlan->dv_vlanid); 1198 1199 id = vlan->dv_vlanid; 1200 if (nvlist_add_uint64(nvl, RCM_NV_LINKID, id) != 0) { 1201 rcm_log_message(RCM_ERROR, 1202 _("VLAN: failed to construct nvlist\n")); 1203 (void) mutex_unlock(&cache_lock); 1204 goto done; 1205 } 1206 } 1207 (void) mutex_unlock(&cache_lock); 1208 1209 if (rcm_notify_event(hd, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) != 1210 RCM_SUCCESS) { 1211 rcm_log_message(RCM_ERROR, 1212 _("VLAN: failed to notify %s event for %s\n"), 1213 RCM_RESOURCE_LINK_NEW, node->vc_resource); 1214 goto done; 1215 } 1216 1217 ret = 0; 1218 done: 1219 if (nvl != NULL) 1220 nvlist_free(nvl); 1221 return (ret); 1222 } 1223 1224 /* 1225 * vlan_consumer_notify() - Notify consumers of VLANs coming back online. 1226 */ 1227 static int 1228 vlan_consumer_notify(rcm_handle_t *hd, datalink_id_t linkid, char **errorp, 1229 uint_t flags, rcm_info_t **info) 1230 { 1231 char rsrc[RCM_LINK_RESOURCE_MAX]; 1232 link_cache_t *node; 1233 1234 /* Check for the interface in the cache */ 1235 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", RCM_LINK_PREFIX, 1236 linkid); 1237 1238 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_notify(%s)\n", rsrc); 1239 1240 /* 1241 * Inform IP consumers of the new link. 1242 */ 1243 if (vlan_notify_new_vlan(hd, rsrc) != 0) { 1244 (void) mutex_lock(&cache_lock); 1245 if ((node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH)) != NULL) { 1246 (void) vlan_offline_vlan(node, VLAN_STALE, 1247 CACHE_NODE_STALE); 1248 } 1249 (void) mutex_unlock(&cache_lock); 1250 rcm_log_message(RCM_TRACE2, 1251 "VLAN: vlan_notify_new_vlan failed(%s)\n", rsrc); 1252 return (-1); 1253 } 1254 1255 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_notify succeeded\n"); 1256 return (0); 1257 } 1258 1259 typedef struct vlan_up_arg_s { 1260 datalink_id_t linkid; 1261 int retval; 1262 } vlan_up_arg_t; 1263 1264 static int 1265 vlan_up(dladm_handle_t handle, datalink_id_t vlanid, void *arg) 1266 { 1267 vlan_up_arg_t *vlan_up_argp = arg; 1268 dladm_status_t status; 1269 dladm_vlan_attr_t vlan_attr; 1270 char errmsg[DLADM_STRSIZE]; 1271 1272 status = dladm_vlan_info(handle, vlanid, &vlan_attr, DLADM_OPT_PERSIST); 1273 if (status != DLADM_STATUS_OK) { 1274 rcm_log_message(RCM_TRACE1, 1275 "VLAN: vlan_up(): cannot get information for VLAN %u " 1276 "(%s)\n", vlanid, dladm_status2str(status, errmsg)); 1277 return (DLADM_WALK_CONTINUE); 1278 } 1279 1280 if (vlan_attr.dv_linkid != vlan_up_argp->linkid) 1281 return (DLADM_WALK_CONTINUE); 1282 1283 rcm_log_message(RCM_TRACE3, "VLAN: vlan_up(%u)\n", vlanid); 1284 if ((status = dladm_vlan_up(handle, vlanid)) == DLADM_STATUS_OK) 1285 return (DLADM_WALK_CONTINUE); 1286 1287 /* 1288 * Prompt the warning message and continue to UP other VLANs. 1289 */ 1290 rcm_log_message(RCM_WARNING, 1291 _("VLAN: VLAN up failed (%u): %s\n"), 1292 vlanid, dladm_status2str(status, errmsg)); 1293 1294 vlan_up_argp->retval = -1; 1295 return (DLADM_WALK_CONTINUE); 1296 } 1297 1298 /* 1299 * vlan_configure() - Configure VLANs over a physical link after it attaches 1300 */ 1301 static int 1302 vlan_configure(rcm_handle_t *hd, datalink_id_t linkid) 1303 { 1304 char rsrc[RCM_LINK_RESOURCE_MAX]; 1305 link_cache_t *node; 1306 vlan_up_arg_t arg = {DATALINK_INVALID_LINKID, 0}; 1307 1308 /* Check for the VLANs in the cache */ 1309 (void) snprintf(rsrc, sizeof (rsrc), "%s/%u", RCM_LINK_PREFIX, linkid); 1310 1311 rcm_log_message(RCM_TRACE2, "VLAN: vlan_configure(%s)\n", rsrc); 1312 1313 /* Check if the link is new or was previously offlined */ 1314 (void) mutex_lock(&cache_lock); 1315 if (((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) != NULL) && 1316 (!(node->vc_state & CACHE_NODE_OFFLINED))) { 1317 rcm_log_message(RCM_TRACE2, 1318 "VLAN: Skipping configured interface(%s)\n", rsrc); 1319 (void) mutex_unlock(&cache_lock); 1320 return (0); 1321 } 1322 (void) mutex_unlock(&cache_lock); 1323 1324 arg.linkid = linkid; 1325 (void) dladm_walk_datalink_id(vlan_up, dld_handle, &arg, 1326 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); 1327 1328 if (arg.retval == 0) { 1329 rcm_log_message(RCM_TRACE2, 1330 "VLAN: vlan_configure succeeded(%s)\n", rsrc); 1331 } 1332 return (arg.retval); 1333 } 1334