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