d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * CDDL HEADER START
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * The contents of this file are subject to the terms of the
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Common Development and Distribution License (the "License").
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * You may not use this file except in compliance with the License.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * or http://www.opensolaris.org/os/licensing.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * See the License for the specific language governing permissions
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * and limitations under the License.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * When distributing Covered Code, include this CDDL HEADER in each
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * If applicable, add the following below this CDDL HEADER, with the
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * fields enclosed by brackets "[]" replaced with your own identifying
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * information: Portions Copyright [yyyy] [name of copyright owner]
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * CDDL HEADER END
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
327151705b7439cb7ab35c370f682cac7ef9523aCathy Zhou * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * This RCM module adds support to the RCM framework for VLAN links
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <stdio.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <stdlib.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <string.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <errno.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/types.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <synch.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <assert.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <strings.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include "rcm_module.h"
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <libintl.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <libdllink.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <libdlvlan.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <libdlpi.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Definitions
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#ifndef lint
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#define _(x) gettext(x)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#else
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#define _(x) x
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#endif
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* Some generic well-knowns and defaults used in this module */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#define RCM_LINK_PREFIX "SUNW_datalink" /* RCM datalink name prefix */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#define RCM_LINK_RESOURCE_MAX (13 + LINKID_STR_WIDTH)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* VLAN link flags */
d62bc4badc1c1f1549c961cfb8b420e650e1272byztypedef enum {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VLAN_OFFLINED = 0x1,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VLAN_CONSUMER_OFFLINED = 0x2,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VLAN_STALE = 0x4
d62bc4badc1c1f1549c961cfb8b420e650e1272byz} vlan_flag_t;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* link representation */
d62bc4badc1c1f1549c961cfb8b420e650e1272byztypedef struct dl_vlan {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct dl_vlan *dv_next; /* next VLAN on the same link */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct dl_vlan *dv_prev; /* prev VLAN on the same link */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz datalink_id_t dv_vlanid;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_flag_t dv_flags; /* VLAN link flags */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz} dl_vlan_t;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* VLAN Cache state flags */
d62bc4badc1c1f1549c961cfb8b420e650e1272byztypedef enum {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz CACHE_NODE_STALE = 0x1, /* stale cached data */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz CACHE_NODE_NEW = 0x2, /* new cached nodes */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz CACHE_NODE_OFFLINED = 0x4 /* nodes offlined */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz} cache_node_state_t;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* Network Cache lookup options */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#define CACHE_NO_REFRESH 0x1 /* cache refresh not needed */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#define CACHE_REFRESH 0x2 /* refresh cache */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* Cache element */
d62bc4badc1c1f1549c961cfb8b420e650e1272byztypedef struct link_cache {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct link_cache *vc_next; /* next cached resource */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct link_cache *vc_prev; /* prev cached resource */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char *vc_resource; /* resource name */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz datalink_id_t vc_linkid; /* linkid */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vc_vlan; /* VLAN list on this link */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_node_state_t vc_state; /* cache state flags */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz} link_cache_t;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Global cache for network VLANs
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic link_cache_t cache_head;
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic link_cache_t cache_tail;
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic mutex_t cache_lock;
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int events_registered = 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskeystatic dladm_handle_t dld_handle = NULL;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * RCM module interface prototypes
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_register(rcm_handle_t *);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_unregister(rcm_handle_t *);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_get_info(rcm_handle_t *, char *, id_t, uint_t,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **, char **, nvlist_t *, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_suspend(rcm_handle_t *, char *, id_t,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz timespec_t *, uint_t, char **, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_resume(rcm_handle_t *, char *, id_t, uint_t,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_offline(rcm_handle_t *, char *, id_t, uint_t,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_undo_offline(rcm_handle_t *, char *, id_t, uint_t,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_remove(rcm_handle_t *, char *, id_t, uint_t,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_notify_event(rcm_handle_t *, char *, id_t, uint_t,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **, nvlist_t *, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_configure(rcm_handle_t *, datalink_id_t);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* Module private routines */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void cache_free();
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int cache_update(rcm_handle_t *);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void cache_remove(link_cache_t *);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void node_free(link_cache_t *);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void cache_insert(link_cache_t *);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic link_cache_t *cache_lookup(rcm_handle_t *, char *, char);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_consumer_offline(rcm_handle_t *, link_cache_t *,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **, uint_t, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void vlan_consumer_online(rcm_handle_t *, link_cache_t *,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **, uint_t, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_offline_vlan(link_cache_t *, uint32_t,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_node_state_t);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void vlan_online_vlan(link_cache_t *);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic char *vlan_usage(link_cache_t *);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void vlan_log_err(datalink_id_t, char **, char *);
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int vlan_consumer_notify(rcm_handle_t *, datalink_id_t,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **, uint_t, rcm_info_t **);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* Module-Private data */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic struct rcm_mod_ops vlan_ops =
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_MOD_OPS_VERSION,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_register,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_unregister,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_get_info,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_suspend,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_resume,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_offline,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_undo_offline,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_remove,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz NULL,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz NULL,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_notify_event
d62bc4badc1c1f1549c961cfb8b420e650e1272byz};
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * rcm_mod_init() - Update registrations, and return the ops structure.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstruct rcm_mod_ops *
d62bc4badc1c1f1549c961cfb8b420e650e1272byzrcm_mod_init(void)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d4d1f7bf736e9deaf99b53c54fc31cecd3a9e435Vasumathi Sundaram - Sun Microsystems dladm_status_t status;
d4d1f7bf736e9deaf99b53c54fc31cecd3a9e435Vasumathi Sundaram - Sun Microsystems char errmsg[DLADM_STRSIZE];
d4d1f7bf736e9deaf99b53c54fc31cecd3a9e435Vasumathi Sundaram - Sun Microsystems
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: mod_init\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_head.vc_next = &cache_tail;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_head.vc_prev = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_tail.vc_prev = &cache_head;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_tail.vc_next = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_init(&cache_lock, 0, NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d4d1f7bf736e9deaf99b53c54fc31cecd3a9e435Vasumathi Sundaram - Sun Microsystems if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) {
d4d1f7bf736e9deaf99b53c54fc31cecd3a9e435Vasumathi Sundaram - Sun Microsystems rcm_log_message(RCM_WARNING,
d4d1f7bf736e9deaf99b53c54fc31cecd3a9e435Vasumathi Sundaram - Sun Microsystems "VLAN: mod_init failed: cannot open datalink handle: %s\n",
d4d1f7bf736e9deaf99b53c54fc31cecd3a9e435Vasumathi Sundaram - Sun Microsystems dladm_status2str(status, errmsg));
d4d1f7bf736e9deaf99b53c54fc31cecd3a9e435Vasumathi Sundaram - Sun Microsystems return (NULL);
d4d1f7bf736e9deaf99b53c54fc31cecd3a9e435Vasumathi Sundaram - Sun Microsystems }
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Return the ops vectors */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (&vlan_ops);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * rcm_mod_info() - Return a string describing this module.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzconst char *
d62bc4badc1c1f1549c961cfb8b420e650e1272byzrcm_mod_info(void)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: mod_info\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
648495d6a097a39eaebc7e56d25f2463ff3bba65vikram return ("VLAN module version 1.2");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * rcm_mod_fini() - Destroy the network VLAN cache.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint
d62bc4badc1c1f1549c961cfb8b420e650e1272byzrcm_mod_fini(void)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: mod_fini\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Note that vlan_unregister() does not seem to be called anywhere,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * therefore we free the cache nodes here. In theory we should call
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * rcm_register_interest() for each node before we free it, the
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * framework does not provide the rcm_handle to allow us to do so.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_free();
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_destroy(&cache_lock);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey dladm_close(dld_handle);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_register() - Make sure the cache is properly sync'ed, and its
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * registrations are in order.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_register(rcm_handle_t *hd)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: register\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (cache_update(hd) < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Need to register interest in all new resources
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * getting attached, so we get attach event notifications
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!events_registered) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz != RCM_SUCCESS) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: failed to register %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_RESOURCE_LINK_NEW);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_DEBUG, "VLAN: registered %s\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_RESOURCE_LINK_NEW);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz events_registered++;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_unregister() - Walk the cache, unregistering all the networks.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_unregister(rcm_handle_t *hd)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: unregister\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Walk the cache, unregistering everything */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_head.vc_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz while (node != &cache_tail) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rcm_unregister_interest(hd, node->vc_resource, 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz != RCM_SUCCESS) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: failed to unregister %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_remove(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node_free(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_head.vc_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Unregister interest in all new resources
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (events_registered) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz != RCM_SUCCESS) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: failed to unregister %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_RESOURCE_LINK_NEW);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_DEBUG, "VLAN: unregistered %s\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_RESOURCE_LINK_NEW);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz events_registered--;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_offline() - Offline VLANs on a specific node.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **errorp, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: offline(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Lock the cache and lookup the resource */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_lookup(hd, rsrc, CACHE_REFRESH);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* should not happen because the resource is registered. */
327151705b7439cb7ab35c370f682cac7ef9523aCathy Zhou vlan_log_err(DATALINK_INVALID_LINKID, errorp,
327151705b7439cb7ab35c370f682cac7ef9523aCathy Zhou "unrecognized resource");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Inform consumers (IP interfaces) of associated VLANs to be offlined
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan_consumer_offline(hd, node, errorp, flags, info) ==
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_SUCCESS) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_DEBUG,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: consumers agreed on offline\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_log_err(node->vc_linkid, errorp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "consumers failed to offline");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Check if it's a query */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (flags & RCM_QUERY) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: offline query succeeded(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan_offline_vlan(node, VLAN_OFFLINED, CACHE_NODE_OFFLINED) !=
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_SUCCESS) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_online_vlan(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_log_err(node->vc_linkid, errorp, "offline failed");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: Offline succeeded(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_undo_offline() - Undo offline of a previously offlined node.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*ARGSUSED*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **errorp, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: online(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_log_err(DATALINK_INVALID_LINKID, errorp, "no such link");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz errno = ENOENT;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Check if no attempt should be made to online the link here */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!(node->vc_state & CACHE_NODE_OFFLINED)) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_log_err(node->vc_linkid, errorp, "link not offlined");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz errno = ENOTSUP;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_online_vlan(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Inform IP interfaces on associated VLANs to be onlined
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_consumer_online(hd, node, errorp, flags, info);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_state &= ~CACHE_NODE_OFFLINED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: online succeeded(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_online_vlan(link_cache_t *node)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dladm_status_t status;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char errmsg[DLADM_STRSIZE];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Try to bring on all offlined VLANs
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!(vlan->dv_flags & VLAN_OFFLINED))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if ((status = dladm_vlan_up(dld_handle, vlan->dv_vlanid)) !=
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DLADM_STATUS_OK) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Print a warning message and continue to online
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * other VLANs.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_WARNING,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: VLAN online failed (%u): %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_vlanid, dladm_status2str(status, errmsg));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_flags &= ~VLAN_OFFLINED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_offline_vlan(link_cache_t *node, uint32_t flags, cache_node_state_t state)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dladm_status_t status;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char errmsg[DLADM_STRSIZE];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_offline_vlan (%s %u %u)\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource, flags, state);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Try to delete all explicit created VLAN
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if ((status = dladm_vlan_delete(dld_handle, vlan->dv_vlanid,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_WARNING,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: VLAN offline failed (%u): %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_vlanid, dladm_status2str(status, errmsg));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: VLAN offline succeeded(%u)\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_vlanid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_flags |= flags;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_state |= state;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_get_info() - Gather usage information for this resource.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*ARGSUSED*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **usagep, char **errorp, nvlist_t *props, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: get_info(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_lookup(hd, rsrc, CACHE_REFRESH);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_INFO,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: get_info(%s) unrecognized resource\n"), rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz errno = ENOENT;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *usagep = vlan_usage(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (*usagep == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* most likely malloc failure */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: get_info(%s) malloc failure\n"), rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz errno = ENOMEM;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Set client/role properties */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) nvlist_add_string(props, RCM_CLIENT_NAME, "VLAN");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: get_info(%s) info = %s\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rsrc, *usagep);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_suspend() - Nothing to do, always okay
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*ARGSUSED*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz uint_t flags, char **errorp, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: suspend(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_resume() - Nothing to do, always okay
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*ARGSUSED*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **errorp, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: resume(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_SUCCESS);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_consumer_remove()
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Notify VLAN consumers to remove cache.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_consumer_remove(rcm_handle_t *hd, link_cache_t *node, uint_t flags,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char rsrc[RCM_LINK_RESOURCE_MAX];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int ret = RCM_SUCCESS;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_remove (%s)\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * This will only be called when the offline operation
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * succeeds, so the VLAN consumers must have been offlined
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * at this point.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(vlan->dv_flags & VLAN_CONSUMER_OFFLINED);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_LINK_PREFIX, vlan->dv_vlanid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ret = rcm_notify_remove(hd, rsrc, flags, info);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ret != RCM_SUCCESS) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_WARNING,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: notify remove failed (%s)\n"), rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_remove done\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (ret);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_remove() - remove a resource from cache
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*ARGSUSED*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **errorp, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int rv;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: remove(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_INFO,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: remove(%s) unrecognized resource\n"), rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz errno = ENOENT;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* remove the cached entry for the resource */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_remove(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rv = vlan_consumer_remove(hd, node, flags, info);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node_free(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (rv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_notify_event - Project private implementation to receive new resource
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * events. It intercepts all new resource events. If the
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * new resource is a network resource, pass up a notify
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * for it too. The new resource need not be cached, since
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * it is done at register again.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*ARGSUSED*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char **errorp, nvlist_t *nvl, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz nvpair_t *nvp = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz datalink_id_t linkid;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz uint64_t id64;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int rv = RCM_SUCCESS;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1, "VLAN: notify_event(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (strcmp(rsrc, RCM_RESOURCE_LINK_NEW) != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_log_err(DATALINK_INVALID_LINKID, errorp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "unrecognized event");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz errno = EINVAL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Update cache to reflect latest VLANs */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (cache_update(hd) < 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_log_err(DATALINK_INVALID_LINKID, errorp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "private Cache update failed");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (RCM_FAILURE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Try best to recover all configuration.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_DEBUG, "VLAN: process_nvlist\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (strcmp(nvpair_name(nvp), RCM_NV_LINKID) != 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (nvpair_value_uint64(nvp, &id64) != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_log_err(DATALINK_INVALID_LINKID, errorp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "cannot get linkid");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rv = RCM_FAILURE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz linkid = (datalink_id_t)id64;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan_configure(hd, linkid) != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_log_err(linkid, errorp, "configuring failed");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rv = RCM_FAILURE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Notify all VLAN consumers */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan_consumer_notify(hd, linkid, errorp, flags,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz info) != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_log_err(linkid, errorp, "consumer notify failed");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rv = RCM_FAILURE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: notify_event: link configuration complete\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (rv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_usage - Determine the usage of a link.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * The returned buffer is owned by caller, and the caller
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * must free it up when done.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic char *
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_usage(link_cache_t *node)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int nvlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char *buf;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz const char *fmt;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char *sep;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char errmsg[DLADM_STRSIZE];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char name[MAXLINKNAMELEN];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dladm_status_t status;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz size_t bufsz;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: usage(%s)\n", node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(MUTEX_HELD(&cache_lock));
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if ((status = dladm_datalink_id2info(dld_handle, node->vc_linkid, NULL,
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey NULL, NULL, name, sizeof (name))) != DLADM_STATUS_OK) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: usage(%s) get link name failure(%s)\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource, dladm_status2str(status, errmsg));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node->vc_state & CACHE_NODE_OFFLINED)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz fmt = _("%1$s offlined");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz else
d62bc4badc1c1f1549c961cfb8b420e650e1272byz fmt = _("%1$s VLANs: ");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* TRANSLATION_NOTE: separator used between VLAN linkids */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz sep = _(", ");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz nvlan = 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz nvlan++;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* space for VLANs and separators, plus message */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz bufsz = nvlan * (MAXLINKNAMELEN + strlen(sep)) +
d62bc4badc1c1f1549c961cfb8b420e650e1272byz strlen(fmt) + MAXLINKNAMELEN + 1;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((buf = malloc(bufsz)) == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: usage(%s) malloc failure(%s)\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource, strerror(errno));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(buf, bufsz, fmt, name);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node->vc_state & CACHE_NODE_OFFLINED) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Nothing else to do */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: usage (%s) info = %s\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource, buf);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (buf);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_DEBUG, "VLAN:= %u\n", vlan->dv_vlanid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if ((status = dladm_datalink_id2info(dld_handle,
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey vlan->dv_vlanid, NULL, NULL, NULL, name,
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey sizeof (name))) != DLADM_STATUS_OK) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: usage(%s) get vlan %u name failure(%s)\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource, vlan->dv_vlanid,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dladm_status2str(status, errmsg));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz free(buf);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) strlcat(buf, name, bufsz);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan->dv_next != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) strlcat(buf, sep, bufsz);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: usage (%s) info = %s\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource, buf);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (buf);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Cache management routines, all cache management functions should be
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * be called with cache_lock held.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * cache_lookup() - Get a cache node for a resource.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Call with cache lock held.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * This ensures that the cache is consistent with the system state and
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * returns a pointer to the cache element corresponding to the resource.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic link_cache_t *
d62bc4badc1c1f1549c961cfb8b420e650e1272byzcache_lookup(rcm_handle_t *hd, char *rsrc, char options)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: cache lookup(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(MUTEX_HELD(&cache_lock));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (options & CACHE_REFRESH) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* drop lock since update locks cache again */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) cache_update(hd);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_head.vc_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (; node != &cache_tail; node = node->vc_next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (strcmp(rsrc, node->vc_resource) == 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: cache lookup succeeded(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * node_free - Free a node from the cache
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byznode_free(link_cache_t *node)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan, *next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node != NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz free(node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* free the VLAN list */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz next = vlan->dv_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz free(vlan);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz free(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * cache_insert - Insert a resource node in cache
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byzcache_insert(link_cache_t *node)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(MUTEX_HELD(&cache_lock));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* insert at the head for best performance */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_next = cache_head.vc_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_prev = &cache_head;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_next->vc_prev = node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_prev->vc_next = node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * cache_remove() - Remove a resource node from cache.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byzcache_remove(link_cache_t *node)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(MUTEX_HELD(&cache_lock));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_next->vc_prev = node->vc_prev;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_prev->vc_next = node->vc_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_next = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_prev = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byztypedef struct vlan_update_arg_s {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_handle_t *hd;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int retval;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz} vlan_update_arg_t;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_update() - Update physical interface properties
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskeyvlan_update(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_update_arg_t *vlan_update_argp = arg;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_handle_t *hd = vlan_update_argp->hd;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char *rsrc;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dladm_vlan_attr_t vlan_attr;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dladm_status_t status;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char errmsg[DLADM_STRSIZE];
44e79163a6f229e84295b0d2aff268af3df641b9yz boolean_t newnode = B_FALSE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int ret = -1;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_update(%u)\n", vlanid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(MUTEX_HELD(&cache_lock));
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey status = dladm_vlan_info(handle, vlanid, &vlan_attr, DLADM_OPT_ACTIVE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (status != DLADM_STATUS_OK) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: vlan_update() cannot get vlan information for "
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "%u(%s)\n", vlanid, dladm_status2str(status, errmsg));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (DLADM_WALK_CONTINUE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rsrc = malloc(RCM_LINK_RESOURCE_MAX);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rsrc == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR, _("VLAN: malloc error(%s): %u\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz strerror(errno), vlanid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto done;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_LINK_PREFIX, vlan_attr.dv_linkid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node != NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_DEBUG,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: %s already registered (vlanid:%d)\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rsrc, vlan_attr.dv_vid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz free(rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_DEBUG,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: %s is a new resource (vlanid:%d)\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rsrc, vlan_attr.dv_vid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((node = calloc(1, sizeof (link_cache_t))) == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz free(rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR, _("VLAN: calloc: %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz strerror(errno));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto done;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource = rsrc;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_vlan = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_linkid = vlan_attr.dv_linkid;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_state |= CACHE_NODE_NEW;
44e79163a6f229e84295b0d2aff268af3df641b9yz newnode = B_TRUE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan->dv_vlanid == vlanid) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_flags &= ~VLAN_STALE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((vlan = calloc(1, sizeof (dl_vlan_t))) == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR, _("VLAN: malloc: %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz strerror(errno));
44e79163a6f229e84295b0d2aff268af3df641b9yz if (newnode) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz free(rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz free(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto done;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_vlanid = vlanid;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_next = node->vc_vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_prev = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node->vc_vlan != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_vlan->dv_prev = vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_vlan = vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_state &= ~CACHE_NODE_STALE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
44e79163a6f229e84295b0d2aff268af3df641b9yz if (newnode)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_insert(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE3, "VLAN: vlan_update: succeeded(%u)\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlanid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ret = 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdone:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_update_argp->retval = ret;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (ret == 0 ? DLADM_WALK_CONTINUE : DLADM_WALK_TERMINATE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_update_all() - Determine all VLAN links in the system
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_update_all(rcm_handle_t *hd)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_update_arg_t arg = {NULL, 0};
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_update_all\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(MUTEX_HELD(&cache_lock));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz arg.hd = hd;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey (void) dladm_walk_datalink_id(vlan_update, dld_handle, &arg,
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (arg.retval);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * cache_update() - Update cache with latest interface info
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzcache_update(rcm_handle_t *hd)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node, *nnode;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int rv;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: cache_update\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* first we walk the entire cache, marking each entry stale */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_head.vc_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (; node != &cache_tail; node = node->vc_next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_state |= CACHE_NODE_STALE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_flags |= VLAN_STALE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rv = vlan_update_all(hd);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Continue to delete all stale nodes from the cache even
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_update_all() failed. Unregister link that are not offlined
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * and still in cache
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (node = cache_head.vc_next; node != &cache_tail; node = nnode) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan, *next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz next = vlan->dv_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* clear stale VLANs */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan->dv_flags & VLAN_STALE) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan->dv_prev != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_prev->dv_next = next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz else
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_vlan = next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (next != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz next->dv_prev = vlan->dv_prev;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz free(vlan);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz nnode = node->vc_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (node->vc_state & CACHE_NODE_STALE) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) rcm_unregister_interest(hd, node->vc_resource,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz 0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_DEBUG, "VLAN: unregistered %s\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(node->vc_vlan == NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_remove(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node_free(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!(node->vc_state & CACHE_NODE_NEW))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rcm_register_interest(hd, node->vc_resource, 0, NULL) !=
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_SUCCESS) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: failed to register %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rv = -1;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_DEBUG, "VLAN: registered %s\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_state &= ~CACHE_NODE_NEW;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (rv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * cache_free() - Empty the cache
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byzcache_free()
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: cache_free\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_head.vc_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz while (node != &cache_tail) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cache_remove(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node_free(node);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node = cache_head.vc_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_log_err() - RCM error log wrapper
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_log_err(datalink_id_t linkid, char **errorp, char *errmsg)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char link[MAXLINKNAMELEN];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char errstr[DLADM_STRSIZE];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dladm_status_t status;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int len;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz const char *errfmt;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char *error;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link[0] = '\0';
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (linkid != DATALINK_INVALID_LINKID) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char rsrc[RCM_LINK_RESOURCE_MAX];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(rsrc, sizeof (rsrc), "%s/%u",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_LINK_PREFIX, linkid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR, _("VLAN: %s(%s)\n"), errmsg, rsrc);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if ((status = dladm_datalink_id2info(dld_handle, linkid, NULL,
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_WARNING,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: cannot get link name for (%s) %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rsrc, dladm_status2str(status, errstr));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR, _("VLAN: %s\n"), errmsg);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz errfmt = strlen(link) > 0 ? _("VLAN: %s(%s)") : _("VLAN: %s");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz len = strlen(errfmt) + strlen(errmsg) + MAXLINKNAMELEN + 1;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((error = malloc(len)) != NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (strlen(link) > 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(error, len, errfmt, errmsg, link);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz else
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(error, len, errfmt, errmsg);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (errorp != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *errorp = error;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_consumer_online()
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Notify online to VLAN consumers.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* ARGSUSED */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_consumer_online(rcm_handle_t *hd, link_cache_t *node, char **errorp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz uint_t flags, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char rsrc[RCM_LINK_RESOURCE_MAX];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_online (%s)\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!(vlan->dv_flags & VLAN_CONSUMER_OFFLINED))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_LINK_PREFIX, vlan->dv_vlanid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rcm_notify_online(hd, rsrc, flags, info) == RCM_SUCCESS)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_flags &= ~VLAN_CONSUMER_OFFLINED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_online done\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_consumer_offline()
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Offline VLAN consumers.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_consumer_offline(rcm_handle_t *hd, link_cache_t *node, char **errorp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz uint_t flags, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char rsrc[RCM_LINK_RESOURCE_MAX];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int ret = RCM_SUCCESS;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_offline (%s)\n",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_LINK_PREFIX, vlan->dv_vlanid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ret = rcm_request_offline(hd, rsrc, flags, info);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ret != RCM_SUCCESS)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan->dv_flags |= VLAN_CONSUMER_OFFLINED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_consumer_online(hd, node, errorp, flags, info);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_offline done\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (ret);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Send RCM_RESOURCE_LINK_NEW events to other modules about new VLANs.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Return 0 on success, -1 on failure.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_notify_new_vlan(rcm_handle_t *hd, char *rsrc)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_vlan_t *vlan;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz nvlist_t *nvl = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz uint64_t id;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int ret = -1;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_notify_new_vlan (%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (nvlist_alloc(&nvl, 0, 0) != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_WARNING,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: failed to allocate nvlist\n"));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto done;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rcm_log_message(RCM_TRACE2,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "VLAN: vlan_notify_new_vlan add (%u)\n",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng vlan->dv_vlanid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng id = vlan->dv_vlanid;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (nvlist_add_uint64(nvl, RCM_NV_LINKID, id) != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rcm_log_message(RCM_ERROR,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng _("VLAN: failed to construct nvlist\n"));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) mutex_unlock(&cache_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng goto done;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rcm_notify_event(hd, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) !=
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_SUCCESS) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_ERROR,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: failed to notify %s event for %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz RCM_RESOURCE_LINK_NEW, node->vc_resource);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto done;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ret = 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdone:
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(nvl);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (ret);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_consumer_notify() - Notify consumers of VLANs coming back online.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_consumer_notify(rcm_handle_t *hd, datalink_id_t linkid, char **errorp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz uint_t flags, rcm_info_t **info)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char rsrc[RCM_LINK_RESOURCE_MAX];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Check for the interface in the cache */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", RCM_LINK_PREFIX,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz linkid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_notify(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Inform IP consumers of the new link.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan_notify_new_vlan(hd, rsrc) != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH)) != NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) vlan_offline_vlan(node, VLAN_STALE,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz CACHE_NODE_STALE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: vlan_notify_new_vlan failed(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (-1);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_notify succeeded\n");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byztypedef struct vlan_up_arg_s {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz datalink_id_t linkid;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int retval;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz} vlan_up_arg_t;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskeyvlan_up(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_up_arg_t *vlan_up_argp = arg;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dladm_status_t status;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dladm_vlan_attr_t vlan_attr;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char errmsg[DLADM_STRSIZE];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey status = dladm_vlan_info(handle, vlanid, &vlan_attr, DLADM_OPT_PERSIST);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (status != DLADM_STATUS_OK) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE1,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: vlan_up(): cannot get information for VLAN %u "
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "(%s)\n", vlanid, dladm_status2str(status, errmsg));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (DLADM_WALK_CONTINUE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vlan_attr.dv_linkid != vlan_up_argp->linkid)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (DLADM_WALK_CONTINUE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE3, "VLAN: vlan_up(%u)\n", vlanid);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if ((status = dladm_vlan_up(handle, vlanid)) == DLADM_STATUS_OK)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (DLADM_WALK_CONTINUE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Prompt the warning message and continue to UP other VLANs.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_WARNING,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _("VLAN: VLAN up failed (%u): %s\n"),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlanid, dladm_status2str(status, errmsg));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_up_argp->retval = -1;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (DLADM_WALK_CONTINUE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vlan_configure() - Configure VLANs over a physical link after it attaches
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvlan_configure(rcm_handle_t *hd, datalink_id_t linkid)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char rsrc[RCM_LINK_RESOURCE_MAX];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz link_cache_t *node;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vlan_up_arg_t arg = {DATALINK_INVALID_LINKID, 0};
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Check for the VLANs in the cache */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) snprintf(rsrc, sizeof (rsrc), "%s/%u", RCM_LINK_PREFIX, linkid);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2, "VLAN: vlan_configure(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Check if the link is new or was previously offlined */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_lock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) != NULL) &&
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (!(node->vc_state & CACHE_NODE_OFFLINED))) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: Skipping configured interface(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) mutex_unlock(&cache_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz arg.linkid = linkid;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey (void) dladm_walk_datalink_id(vlan_up, dld_handle, &arg,
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (arg.retval == 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rcm_log_message(RCM_TRACE2,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "VLAN: vlan_configure succeeded(%s)\n", rsrc);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (arg.retval);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}