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