15895Syz147064 /*
25895Syz147064 * CDDL HEADER START
35895Syz147064 *
45895Syz147064 * The contents of this file are subject to the terms of the
55895Syz147064 * Common Development and Distribution License (the "License").
65895Syz147064 * You may not use this file except in compliance with the License.
75895Syz147064 *
85895Syz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95895Syz147064 * or http://www.opensolaris.org/os/licensing.
105895Syz147064 * See the License for the specific language governing permissions
115895Syz147064 * and limitations under the License.
125895Syz147064 *
135895Syz147064 * When distributing Covered Code, include this CDDL HEADER in each
145895Syz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155895Syz147064 * If applicable, add the following below this CDDL HEADER, with the
165895Syz147064 * fields enclosed by brackets "[]" replaced with your own identifying
175895Syz147064 * information: Portions Copyright [yyyy] [name of copyright owner]
185895Syz147064 *
195895Syz147064 * CDDL HEADER END
205895Syz147064 */
215895Syz147064 /*
22*12824SCathy.Zhou@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
235895Syz147064 */
245895Syz147064
255895Syz147064 /*
265895Syz147064 * This RCM module adds support to the RCM framework for VLAN links
275895Syz147064 */
285895Syz147064
295895Syz147064 #include <stdio.h>
305895Syz147064 #include <stdlib.h>
315895Syz147064 #include <string.h>
325895Syz147064 #include <errno.h>
335895Syz147064 #include <sys/types.h>
345895Syz147064 #include <synch.h>
355895Syz147064 #include <assert.h>
365895Syz147064 #include <strings.h>
375895Syz147064 #include "rcm_module.h"
385895Syz147064 #include <libintl.h>
395895Syz147064 #include <libdllink.h>
405895Syz147064 #include <libdlvlan.h>
415895Syz147064 #include <libdlpi.h>
425895Syz147064
435895Syz147064 /*
445895Syz147064 * Definitions
455895Syz147064 */
465895Syz147064 #ifndef lint
475895Syz147064 #define _(x) gettext(x)
485895Syz147064 #else
495895Syz147064 #define _(x) x
505895Syz147064 #endif
515895Syz147064
525895Syz147064 /* Some generic well-knowns and defaults used in this module */
535895Syz147064 #define RCM_LINK_PREFIX "SUNW_datalink" /* RCM datalink name prefix */
545895Syz147064 #define RCM_LINK_RESOURCE_MAX (13 + LINKID_STR_WIDTH)
555895Syz147064
565895Syz147064 /* VLAN link flags */
575895Syz147064 typedef enum {
585895Syz147064 VLAN_OFFLINED = 0x1,
595895Syz147064 VLAN_CONSUMER_OFFLINED = 0x2,
605895Syz147064 VLAN_STALE = 0x4
615895Syz147064 } vlan_flag_t;
625895Syz147064
635895Syz147064 /* link representation */
645895Syz147064 typedef struct dl_vlan {
655895Syz147064 struct dl_vlan *dv_next; /* next VLAN on the same link */
665895Syz147064 struct dl_vlan *dv_prev; /* prev VLAN on the same link */
675895Syz147064 datalink_id_t dv_vlanid;
685895Syz147064 vlan_flag_t dv_flags; /* VLAN link flags */
695895Syz147064 } dl_vlan_t;
705895Syz147064
715895Syz147064 /* VLAN Cache state flags */
725895Syz147064 typedef enum {
735895Syz147064 CACHE_NODE_STALE = 0x1, /* stale cached data */
745895Syz147064 CACHE_NODE_NEW = 0x2, /* new cached nodes */
755895Syz147064 CACHE_NODE_OFFLINED = 0x4 /* nodes offlined */
765895Syz147064 } cache_node_state_t;
775895Syz147064
785895Syz147064 /* Network Cache lookup options */
795895Syz147064 #define CACHE_NO_REFRESH 0x1 /* cache refresh not needed */
805895Syz147064 #define CACHE_REFRESH 0x2 /* refresh cache */
815895Syz147064
825895Syz147064 /* Cache element */
835895Syz147064 typedef struct link_cache {
845895Syz147064 struct link_cache *vc_next; /* next cached resource */
855895Syz147064 struct link_cache *vc_prev; /* prev cached resource */
865895Syz147064 char *vc_resource; /* resource name */
875895Syz147064 datalink_id_t vc_linkid; /* linkid */
885895Syz147064 dl_vlan_t *vc_vlan; /* VLAN list on this link */
895895Syz147064 cache_node_state_t vc_state; /* cache state flags */
905895Syz147064 } link_cache_t;
915895Syz147064
925895Syz147064 /*
935895Syz147064 * Global cache for network VLANs
945895Syz147064 */
955895Syz147064 static link_cache_t cache_head;
965895Syz147064 static link_cache_t cache_tail;
975895Syz147064 static mutex_t cache_lock;
985895Syz147064 static int events_registered = 0;
995895Syz147064
1008453SAnurag.Maskey@Sun.COM static dladm_handle_t dld_handle = NULL;
1018453SAnurag.Maskey@Sun.COM
1025895Syz147064 /*
1035895Syz147064 * RCM module interface prototypes
1045895Syz147064 */
1055895Syz147064 static int vlan_register(rcm_handle_t *);
1065895Syz147064 static int vlan_unregister(rcm_handle_t *);
1075895Syz147064 static int vlan_get_info(rcm_handle_t *, char *, id_t, uint_t,
1085895Syz147064 char **, char **, nvlist_t *, rcm_info_t **);
1095895Syz147064 static int vlan_suspend(rcm_handle_t *, char *, id_t,
1105895Syz147064 timespec_t *, uint_t, char **, rcm_info_t **);
1115895Syz147064 static int vlan_resume(rcm_handle_t *, char *, id_t, uint_t,
1125895Syz147064 char **, rcm_info_t **);
1135895Syz147064 static int vlan_offline(rcm_handle_t *, char *, id_t, uint_t,
1145895Syz147064 char **, rcm_info_t **);
1155895Syz147064 static int vlan_undo_offline(rcm_handle_t *, char *, id_t, uint_t,
1165895Syz147064 char **, rcm_info_t **);
1175895Syz147064 static int vlan_remove(rcm_handle_t *, char *, id_t, uint_t,
1185895Syz147064 char **, rcm_info_t **);
1195895Syz147064 static int vlan_notify_event(rcm_handle_t *, char *, id_t, uint_t,
1205895Syz147064 char **, nvlist_t *, rcm_info_t **);
1215895Syz147064 static int vlan_configure(rcm_handle_t *, datalink_id_t);
1225895Syz147064
1235895Syz147064 /* Module private routines */
1245895Syz147064 static void cache_free();
1255895Syz147064 static int cache_update(rcm_handle_t *);
1265895Syz147064 static void cache_remove(link_cache_t *);
1275895Syz147064 static void node_free(link_cache_t *);
1285895Syz147064 static void cache_insert(link_cache_t *);
1295895Syz147064 static link_cache_t *cache_lookup(rcm_handle_t *, char *, char);
1305895Syz147064 static int vlan_consumer_offline(rcm_handle_t *, link_cache_t *,
1315895Syz147064 char **, uint_t, rcm_info_t **);
1325895Syz147064 static void vlan_consumer_online(rcm_handle_t *, link_cache_t *,
1335895Syz147064 char **, uint_t, rcm_info_t **);
1345895Syz147064 static int vlan_offline_vlan(link_cache_t *, uint32_t,
1355895Syz147064 cache_node_state_t);
1365895Syz147064 static void vlan_online_vlan(link_cache_t *);
1375895Syz147064 static char *vlan_usage(link_cache_t *);
1385895Syz147064 static void vlan_log_err(datalink_id_t, char **, char *);
1395895Syz147064 static int vlan_consumer_notify(rcm_handle_t *, datalink_id_t,
1405895Syz147064 char **, uint_t, rcm_info_t **);
1415895Syz147064
1425895Syz147064 /* Module-Private data */
1435895Syz147064 static struct rcm_mod_ops vlan_ops =
1445895Syz147064 {
1455895Syz147064 RCM_MOD_OPS_VERSION,
1465895Syz147064 vlan_register,
1475895Syz147064 vlan_unregister,
1485895Syz147064 vlan_get_info,
1495895Syz147064 vlan_suspend,
1505895Syz147064 vlan_resume,
1515895Syz147064 vlan_offline,
1525895Syz147064 vlan_undo_offline,
1535895Syz147064 vlan_remove,
1545895Syz147064 NULL,
1555895Syz147064 NULL,
1565895Syz147064 vlan_notify_event
1575895Syz147064 };
1585895Syz147064
1595895Syz147064 /*
1605895Syz147064 * rcm_mod_init() - Update registrations, and return the ops structure.
1615895Syz147064 */
1625895Syz147064 struct rcm_mod_ops *
rcm_mod_init(void)1635895Syz147064 rcm_mod_init(void)
1645895Syz147064 {
1658673SVasumathi.Sundaram@Sun.COM dladm_status_t status;
1668673SVasumathi.Sundaram@Sun.COM char errmsg[DLADM_STRSIZE];
1678673SVasumathi.Sundaram@Sun.COM
1685895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: mod_init\n");
1695895Syz147064
1705895Syz147064 cache_head.vc_next = &cache_tail;
1715895Syz147064 cache_head.vc_prev = NULL;
1725895Syz147064 cache_tail.vc_prev = &cache_head;
1735895Syz147064 cache_tail.vc_next = NULL;
1745895Syz147064 (void) mutex_init(&cache_lock, 0, NULL);
1755895Syz147064
1768673SVasumathi.Sundaram@Sun.COM if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) {
1778673SVasumathi.Sundaram@Sun.COM rcm_log_message(RCM_WARNING,
1788673SVasumathi.Sundaram@Sun.COM "VLAN: mod_init failed: cannot open datalink handle: %s\n",
1798673SVasumathi.Sundaram@Sun.COM dladm_status2str(status, errmsg));
1808673SVasumathi.Sundaram@Sun.COM return (NULL);
1818673SVasumathi.Sundaram@Sun.COM }
1828453SAnurag.Maskey@Sun.COM
1835895Syz147064 /* Return the ops vectors */
1845895Syz147064 return (&vlan_ops);
1855895Syz147064 }
1865895Syz147064
1875895Syz147064 /*
1885895Syz147064 * rcm_mod_info() - Return a string describing this module.
1895895Syz147064 */
1905895Syz147064 const char *
rcm_mod_info(void)1915895Syz147064 rcm_mod_info(void)
1925895Syz147064 {
1935895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: mod_info\n");
1945895Syz147064
1957202Svikram return ("VLAN module version 1.2");
1965895Syz147064 }
1975895Syz147064
1985895Syz147064 /*
1995895Syz147064 * rcm_mod_fini() - Destroy the network VLAN cache.
2005895Syz147064 */
2015895Syz147064 int
rcm_mod_fini(void)2025895Syz147064 rcm_mod_fini(void)
2035895Syz147064 {
2045895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: mod_fini\n");
2055895Syz147064
2065895Syz147064 /*
2075895Syz147064 * Note that vlan_unregister() does not seem to be called anywhere,
2085895Syz147064 * therefore we free the cache nodes here. In theory we should call
2095895Syz147064 * rcm_register_interest() for each node before we free it, the
2105895Syz147064 * framework does not provide the rcm_handle to allow us to do so.
2115895Syz147064 */
2125895Syz147064 cache_free();
2135895Syz147064 (void) mutex_destroy(&cache_lock);
2148453SAnurag.Maskey@Sun.COM
2158453SAnurag.Maskey@Sun.COM dladm_close(dld_handle);
2165895Syz147064 return (RCM_SUCCESS);
2175895Syz147064 }
2185895Syz147064
2195895Syz147064 /*
2205895Syz147064 * vlan_register() - Make sure the cache is properly sync'ed, and its
2215895Syz147064 * registrations are in order.
2225895Syz147064 */
2235895Syz147064 static int
vlan_register(rcm_handle_t * hd)2245895Syz147064 vlan_register(rcm_handle_t *hd)
2255895Syz147064 {
2265895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: register\n");
2275895Syz147064
2285895Syz147064 if (cache_update(hd) < 0)
2295895Syz147064 return (RCM_FAILURE);
2305895Syz147064
2315895Syz147064 /*
2325895Syz147064 * Need to register interest in all new resources
2335895Syz147064 * getting attached, so we get attach event notifications
2345895Syz147064 */
2355895Syz147064 if (!events_registered) {
2365895Syz147064 if (rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL)
2375895Syz147064 != RCM_SUCCESS) {
2385895Syz147064 rcm_log_message(RCM_ERROR,
2395895Syz147064 _("VLAN: failed to register %s\n"),
2405895Syz147064 RCM_RESOURCE_LINK_NEW);
2415895Syz147064 return (RCM_FAILURE);
2425895Syz147064 } else {
2435895Syz147064 rcm_log_message(RCM_DEBUG, "VLAN: registered %s\n",
2445895Syz147064 RCM_RESOURCE_LINK_NEW);
2455895Syz147064 events_registered++;
2465895Syz147064 }
2475895Syz147064 }
2485895Syz147064
2495895Syz147064 return (RCM_SUCCESS);
2505895Syz147064 }
2515895Syz147064
2525895Syz147064 /*
2535895Syz147064 * vlan_unregister() - Walk the cache, unregistering all the networks.
2545895Syz147064 */
2555895Syz147064 static int
vlan_unregister(rcm_handle_t * hd)2565895Syz147064 vlan_unregister(rcm_handle_t *hd)
2575895Syz147064 {
2585895Syz147064 link_cache_t *node;
2595895Syz147064
2605895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: unregister\n");
2615895Syz147064
2625895Syz147064 /* Walk the cache, unregistering everything */
2635895Syz147064 (void) mutex_lock(&cache_lock);
2645895Syz147064 node = cache_head.vc_next;
2655895Syz147064 while (node != &cache_tail) {
2665895Syz147064 if (rcm_unregister_interest(hd, node->vc_resource, 0)
2675895Syz147064 != RCM_SUCCESS) {
2685895Syz147064 rcm_log_message(RCM_ERROR,
2695895Syz147064 _("VLAN: failed to unregister %s\n"),
2705895Syz147064 node->vc_resource);
2715895Syz147064 (void) mutex_unlock(&cache_lock);
2725895Syz147064 return (RCM_FAILURE);
2735895Syz147064 }
2745895Syz147064 cache_remove(node);
2755895Syz147064 node_free(node);
2765895Syz147064 node = cache_head.vc_next;
2775895Syz147064 }
2785895Syz147064 (void) mutex_unlock(&cache_lock);
2795895Syz147064
2805895Syz147064 /*
2815895Syz147064 * Unregister interest in all new resources
2825895Syz147064 */
2835895Syz147064 if (events_registered) {
2845895Syz147064 if (rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0)
2855895Syz147064 != RCM_SUCCESS) {
2865895Syz147064 rcm_log_message(RCM_ERROR,
2875895Syz147064 _("VLAN: failed to unregister %s\n"),
2885895Syz147064 RCM_RESOURCE_LINK_NEW);
2895895Syz147064 return (RCM_FAILURE);
2905895Syz147064 } else {
2915895Syz147064 rcm_log_message(RCM_DEBUG, "VLAN: unregistered %s\n",
2925895Syz147064 RCM_RESOURCE_LINK_NEW);
2935895Syz147064 events_registered--;
2945895Syz147064 }
2955895Syz147064 }
2965895Syz147064
2975895Syz147064 return (RCM_SUCCESS);
2985895Syz147064 }
2995895Syz147064
3005895Syz147064 /*
3015895Syz147064 * vlan_offline() - Offline VLANs on a specific node.
3025895Syz147064 */
3035895Syz147064 static int
vlan_offline(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)3045895Syz147064 vlan_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
3055895Syz147064 char **errorp, rcm_info_t **info)
3065895Syz147064 {
3075895Syz147064 link_cache_t *node;
3085895Syz147064
3095895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: offline(%s)\n", rsrc);
3105895Syz147064
3115895Syz147064 /* Lock the cache and lookup the resource */
3125895Syz147064 (void) mutex_lock(&cache_lock);
3135895Syz147064 node = cache_lookup(hd, rsrc, CACHE_REFRESH);
3145895Syz147064 if (node == NULL) {
3155895Syz147064 /* should not happen because the resource is registered. */
316*12824SCathy.Zhou@Sun.COM vlan_log_err(DATALINK_INVALID_LINKID, errorp,
317*12824SCathy.Zhou@Sun.COM "unrecognized resource");
3185895Syz147064 (void) mutex_unlock(&cache_lock);
3195895Syz147064 return (RCM_SUCCESS);
3205895Syz147064 }
3215895Syz147064
3225895Syz147064 /*
3235895Syz147064 * Inform consumers (IP interfaces) of associated VLANs to be offlined
3245895Syz147064 */
3255895Syz147064 if (vlan_consumer_offline(hd, node, errorp, flags, info) ==
3265895Syz147064 RCM_SUCCESS) {
3275895Syz147064 rcm_log_message(RCM_DEBUG,
3285895Syz147064 "VLAN: consumers agreed on offline\n");
3295895Syz147064 } else {
3305895Syz147064 vlan_log_err(node->vc_linkid, errorp,
3315895Syz147064 "consumers failed to offline");
3325895Syz147064 (void) mutex_unlock(&cache_lock);
3335895Syz147064 return (RCM_FAILURE);
3345895Syz147064 }
3355895Syz147064
3365895Syz147064 /* Check if it's a query */
3375895Syz147064 if (flags & RCM_QUERY) {
3385895Syz147064 rcm_log_message(RCM_TRACE1,
3395895Syz147064 "VLAN: offline query succeeded(%s)\n", rsrc);
3405895Syz147064 (void) mutex_unlock(&cache_lock);
3415895Syz147064 return (RCM_SUCCESS);
3425895Syz147064 }
3435895Syz147064
3445895Syz147064 if (vlan_offline_vlan(node, VLAN_OFFLINED, CACHE_NODE_OFFLINED) !=
3455895Syz147064 RCM_SUCCESS) {
3465895Syz147064 vlan_online_vlan(node);
3475895Syz147064 vlan_log_err(node->vc_linkid, errorp, "offline failed");
3485895Syz147064 (void) mutex_unlock(&cache_lock);
3495895Syz147064 return (RCM_FAILURE);
3505895Syz147064 }
3515895Syz147064
3525895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: Offline succeeded(%s)\n", rsrc);
3535895Syz147064 (void) mutex_unlock(&cache_lock);
3545895Syz147064 return (RCM_SUCCESS);
3555895Syz147064 }
3565895Syz147064
3575895Syz147064 /*
3585895Syz147064 * vlan_undo_offline() - Undo offline of a previously offlined node.
3595895Syz147064 */
3605895Syz147064 /*ARGSUSED*/
3615895Syz147064 static int
vlan_undo_offline(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)3625895Syz147064 vlan_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
3635895Syz147064 char **errorp, rcm_info_t **info)
3645895Syz147064 {
3655895Syz147064 link_cache_t *node;
3665895Syz147064
3675895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: online(%s)\n", rsrc);
3685895Syz147064
3695895Syz147064 (void) mutex_lock(&cache_lock);
3705895Syz147064 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
3715895Syz147064 if (node == NULL) {
3725895Syz147064 vlan_log_err(DATALINK_INVALID_LINKID, errorp, "no such link");
3735895Syz147064 (void) mutex_unlock(&cache_lock);
3745895Syz147064 errno = ENOENT;
3755895Syz147064 return (RCM_FAILURE);
3765895Syz147064 }
3775895Syz147064
3785895Syz147064 /* Check if no attempt should be made to online the link here */
3795895Syz147064 if (!(node->vc_state & CACHE_NODE_OFFLINED)) {
3805895Syz147064 vlan_log_err(node->vc_linkid, errorp, "link not offlined");
3815895Syz147064 (void) mutex_unlock(&cache_lock);
3825895Syz147064 errno = ENOTSUP;
3835895Syz147064 return (RCM_SUCCESS);
3845895Syz147064 }
3855895Syz147064
3865895Syz147064 vlan_online_vlan(node);
3875895Syz147064
3885895Syz147064 /*
3895895Syz147064 * Inform IP interfaces on associated VLANs to be onlined
3905895Syz147064 */
3915895Syz147064 vlan_consumer_online(hd, node, errorp, flags, info);
3925895Syz147064
3935895Syz147064 node->vc_state &= ~CACHE_NODE_OFFLINED;
3945895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: online succeeded(%s)\n", rsrc);
3955895Syz147064 (void) mutex_unlock(&cache_lock);
3965895Syz147064 return (RCM_SUCCESS);
3975895Syz147064 }
3985895Syz147064
3995895Syz147064 static void
vlan_online_vlan(link_cache_t * node)4005895Syz147064 vlan_online_vlan(link_cache_t *node)
4015895Syz147064 {
4025895Syz147064 dl_vlan_t *vlan;
4035895Syz147064 dladm_status_t status;
4045895Syz147064 char errmsg[DLADM_STRSIZE];
4055895Syz147064
4065895Syz147064 /*
4075895Syz147064 * Try to bring on all offlined VLANs
4085895Syz147064 */
4095895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
4105895Syz147064 if (!(vlan->dv_flags & VLAN_OFFLINED))
4115895Syz147064 continue;
4125895Syz147064
4138453SAnurag.Maskey@Sun.COM if ((status = dladm_vlan_up(dld_handle, vlan->dv_vlanid)) !=
4145895Syz147064 DLADM_STATUS_OK) {
4155895Syz147064 /*
4165895Syz147064 * Print a warning message and continue to online
4175895Syz147064 * other VLANs.
4185895Syz147064 */
4195895Syz147064 rcm_log_message(RCM_WARNING,
4205895Syz147064 _("VLAN: VLAN online failed (%u): %s\n"),
4215895Syz147064 vlan->dv_vlanid, dladm_status2str(status, errmsg));
4225895Syz147064 } else {
4235895Syz147064 vlan->dv_flags &= ~VLAN_OFFLINED;
4245895Syz147064 }
4255895Syz147064 }
4265895Syz147064 }
4275895Syz147064
4285895Syz147064 static int
vlan_offline_vlan(link_cache_t * node,uint32_t flags,cache_node_state_t state)4295895Syz147064 vlan_offline_vlan(link_cache_t *node, uint32_t flags, cache_node_state_t state)
4305895Syz147064 {
4315895Syz147064 dl_vlan_t *vlan;
4325895Syz147064 dladm_status_t status;
4335895Syz147064 char errmsg[DLADM_STRSIZE];
4345895Syz147064
4355895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_offline_vlan (%s %u %u)\n",
4365895Syz147064 node->vc_resource, flags, state);
4375895Syz147064
4385895Syz147064 /*
4395895Syz147064 * Try to delete all explicit created VLAN
4405895Syz147064 */
4415895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
4428453SAnurag.Maskey@Sun.COM if ((status = dladm_vlan_delete(dld_handle, vlan->dv_vlanid,
4435895Syz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
4445895Syz147064 rcm_log_message(RCM_WARNING,
4455895Syz147064 _("VLAN: VLAN offline failed (%u): %s\n"),
4465895Syz147064 vlan->dv_vlanid, dladm_status2str(status, errmsg));
4475895Syz147064 return (RCM_FAILURE);
4485895Syz147064 } else {
4495895Syz147064 rcm_log_message(RCM_TRACE1,
4505895Syz147064 "VLAN: VLAN offline succeeded(%u)\n",
4515895Syz147064 vlan->dv_vlanid);
4525895Syz147064 vlan->dv_flags |= flags;
4535895Syz147064 }
4545895Syz147064 }
4555895Syz147064
4565895Syz147064 node->vc_state |= state;
4575895Syz147064 return (RCM_SUCCESS);
4585895Syz147064 }
4595895Syz147064
4605895Syz147064 /*
4615895Syz147064 * vlan_get_info() - Gather usage information for this resource.
4625895Syz147064 */
4635895Syz147064 /*ARGSUSED*/
4645895Syz147064 int
vlan_get_info(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** usagep,char ** errorp,nvlist_t * props,rcm_info_t ** info)4655895Syz147064 vlan_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
4665895Syz147064 char **usagep, char **errorp, nvlist_t *props, rcm_info_t **info)
4675895Syz147064 {
4685895Syz147064 link_cache_t *node;
4695895Syz147064
4705895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: get_info(%s)\n", rsrc);
4715895Syz147064
4725895Syz147064 (void) mutex_lock(&cache_lock);
4735895Syz147064 node = cache_lookup(hd, rsrc, CACHE_REFRESH);
4745895Syz147064 if (node == NULL) {
4755895Syz147064 rcm_log_message(RCM_INFO,
4765895Syz147064 _("VLAN: get_info(%s) unrecognized resource\n"), rsrc);
4775895Syz147064 (void) mutex_unlock(&cache_lock);
4785895Syz147064 errno = ENOENT;
4795895Syz147064 return (RCM_FAILURE);
4805895Syz147064 }
4815895Syz147064
4825895Syz147064 *usagep = vlan_usage(node);
4835895Syz147064 (void) mutex_unlock(&cache_lock);
4845895Syz147064 if (*usagep == NULL) {
4855895Syz147064 /* most likely malloc failure */
4865895Syz147064 rcm_log_message(RCM_ERROR,
4875895Syz147064 _("VLAN: get_info(%s) malloc failure\n"), rsrc);
4885895Syz147064 (void) mutex_unlock(&cache_lock);
4895895Syz147064 errno = ENOMEM;
4905895Syz147064 return (RCM_FAILURE);
4915895Syz147064 }
4925895Syz147064
4935895Syz147064 /* Set client/role properties */
4945895Syz147064 (void) nvlist_add_string(props, RCM_CLIENT_NAME, "VLAN");
4955895Syz147064
4965895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: get_info(%s) info = %s\n",
4975895Syz147064 rsrc, *usagep);
4985895Syz147064 return (RCM_SUCCESS);
4995895Syz147064 }
5005895Syz147064
5015895Syz147064 /*
5025895Syz147064 * vlan_suspend() - Nothing to do, always okay
5035895Syz147064 */
5045895Syz147064 /*ARGSUSED*/
5055895Syz147064 static int
vlan_suspend(rcm_handle_t * hd,char * rsrc,id_t id,timespec_t * interval,uint_t flags,char ** errorp,rcm_info_t ** info)5065895Syz147064 vlan_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval,
5075895Syz147064 uint_t flags, char **errorp, rcm_info_t **info)
5085895Syz147064 {
5095895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: suspend(%s)\n", rsrc);
5105895Syz147064 return (RCM_SUCCESS);
5115895Syz147064 }
5125895Syz147064
5135895Syz147064 /*
5145895Syz147064 * vlan_resume() - Nothing to do, always okay
5155895Syz147064 */
5165895Syz147064 /*ARGSUSED*/
5175895Syz147064 static int
vlan_resume(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)5185895Syz147064 vlan_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
5195895Syz147064 char **errorp, rcm_info_t **info)
5205895Syz147064 {
5215895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: resume(%s)\n", rsrc);
5225895Syz147064 return (RCM_SUCCESS);
5235895Syz147064 }
5245895Syz147064
5255895Syz147064 /*
5265895Syz147064 * vlan_consumer_remove()
5275895Syz147064 *
5285895Syz147064 * Notify VLAN consumers to remove cache.
5295895Syz147064 */
5305895Syz147064 static int
vlan_consumer_remove(rcm_handle_t * hd,link_cache_t * node,uint_t flags,rcm_info_t ** info)5315895Syz147064 vlan_consumer_remove(rcm_handle_t *hd, link_cache_t *node, uint_t flags,
5325895Syz147064 rcm_info_t **info)
5335895Syz147064 {
5345895Syz147064 dl_vlan_t *vlan = NULL;
5355895Syz147064 char rsrc[RCM_LINK_RESOURCE_MAX];
5365895Syz147064 int ret = RCM_SUCCESS;
5375895Syz147064
5385895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_remove (%s)\n",
5395895Syz147064 node->vc_resource);
5405895Syz147064
5415895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
5425895Syz147064
5435895Syz147064 /*
5445895Syz147064 * This will only be called when the offline operation
5455895Syz147064 * succeeds, so the VLAN consumers must have been offlined
5465895Syz147064 * at this point.
5475895Syz147064 */
5485895Syz147064 assert(vlan->dv_flags & VLAN_CONSUMER_OFFLINED);
5495895Syz147064
5505895Syz147064 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
5515895Syz147064 RCM_LINK_PREFIX, vlan->dv_vlanid);
5525895Syz147064
5535895Syz147064 ret = rcm_notify_remove(hd, rsrc, flags, info);
5545895Syz147064 if (ret != RCM_SUCCESS) {
5555895Syz147064 rcm_log_message(RCM_WARNING,
5565895Syz147064 _("VLAN: notify remove failed (%s)\n"), rsrc);
5575895Syz147064 break;
5585895Syz147064 }
5595895Syz147064 }
5605895Syz147064
5615895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_remove done\n");
5625895Syz147064 return (ret);
5635895Syz147064 }
5645895Syz147064
5655895Syz147064 /*
5665895Syz147064 * vlan_remove() - remove a resource from cache
5675895Syz147064 */
5685895Syz147064 /*ARGSUSED*/
5695895Syz147064 static int
vlan_remove(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)5705895Syz147064 vlan_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
5715895Syz147064 char **errorp, rcm_info_t **info)
5725895Syz147064 {
5735895Syz147064 link_cache_t *node;
5745895Syz147064 int rv;
5755895Syz147064
5765895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: remove(%s)\n", rsrc);
5775895Syz147064
5785895Syz147064 (void) mutex_lock(&cache_lock);
5795895Syz147064 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
5805895Syz147064 if (node == NULL) {
5815895Syz147064 rcm_log_message(RCM_INFO,
5825895Syz147064 _("VLAN: remove(%s) unrecognized resource\n"), rsrc);
5835895Syz147064 (void) mutex_unlock(&cache_lock);
5845895Syz147064 errno = ENOENT;
5855895Syz147064 return (RCM_FAILURE);
5865895Syz147064 }
5875895Syz147064
5885895Syz147064 /* remove the cached entry for the resource */
5895895Syz147064 cache_remove(node);
5905895Syz147064 (void) mutex_unlock(&cache_lock);
5915895Syz147064
5925895Syz147064 rv = vlan_consumer_remove(hd, node, flags, info);
5935895Syz147064 node_free(node);
5945895Syz147064 return (rv);
5955895Syz147064 }
5965895Syz147064
5975895Syz147064 /*
5985895Syz147064 * vlan_notify_event - Project private implementation to receive new resource
5995895Syz147064 * events. It intercepts all new resource events. If the
6005895Syz147064 * new resource is a network resource, pass up a notify
6015895Syz147064 * for it too. The new resource need not be cached, since
6025895Syz147064 * it is done at register again.
6035895Syz147064 */
6045895Syz147064 /*ARGSUSED*/
6055895Syz147064 static int
vlan_notify_event(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,nvlist_t * nvl,rcm_info_t ** info)6065895Syz147064 vlan_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
6075895Syz147064 char **errorp, nvlist_t *nvl, rcm_info_t **info)
6085895Syz147064 {
6095895Syz147064 nvpair_t *nvp = NULL;
6105895Syz147064 datalink_id_t linkid;
6115895Syz147064 uint64_t id64;
6125895Syz147064 int rv = RCM_SUCCESS;
6135895Syz147064
6145895Syz147064 rcm_log_message(RCM_TRACE1, "VLAN: notify_event(%s)\n", rsrc);
6155895Syz147064
6165895Syz147064 if (strcmp(rsrc, RCM_RESOURCE_LINK_NEW) != 0) {
6175895Syz147064 vlan_log_err(DATALINK_INVALID_LINKID, errorp,
6185895Syz147064 "unrecognized event");
6195895Syz147064 errno = EINVAL;
6205895Syz147064 return (RCM_FAILURE);
6215895Syz147064 }
6225895Syz147064
6235895Syz147064 /* Update cache to reflect latest VLANs */
6245895Syz147064 if (cache_update(hd) < 0) {
6255895Syz147064 vlan_log_err(DATALINK_INVALID_LINKID, errorp,
6265895Syz147064 "private Cache update failed");
6275895Syz147064 return (RCM_FAILURE);
6285895Syz147064 }
6295895Syz147064
6305895Syz147064 /*
6315895Syz147064 * Try best to recover all configuration.
6325895Syz147064 */
6335895Syz147064 rcm_log_message(RCM_DEBUG, "VLAN: process_nvlist\n");
6345895Syz147064 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
6355895Syz147064 if (strcmp(nvpair_name(nvp), RCM_NV_LINKID) != 0)
6365895Syz147064 continue;
6375895Syz147064
6385895Syz147064 if (nvpair_value_uint64(nvp, &id64) != 0) {
6395895Syz147064 vlan_log_err(DATALINK_INVALID_LINKID, errorp,
6405895Syz147064 "cannot get linkid");
6415895Syz147064 rv = RCM_FAILURE;
6425895Syz147064 continue;
6435895Syz147064 }
6445895Syz147064
6455895Syz147064 linkid = (datalink_id_t)id64;
6465895Syz147064 if (vlan_configure(hd, linkid) != 0) {
6475895Syz147064 vlan_log_err(linkid, errorp, "configuring failed");
6485895Syz147064 rv = RCM_FAILURE;
6495895Syz147064 continue;
6505895Syz147064 }
6515895Syz147064
6525895Syz147064 /* Notify all VLAN consumers */
6535895Syz147064 if (vlan_consumer_notify(hd, linkid, errorp, flags,
6545895Syz147064 info) != 0) {
6555895Syz147064 vlan_log_err(linkid, errorp, "consumer notify failed");
6565895Syz147064 rv = RCM_FAILURE;
6575895Syz147064 }
6585895Syz147064 }
6595895Syz147064
6605895Syz147064 rcm_log_message(RCM_TRACE1,
6615895Syz147064 "VLAN: notify_event: link configuration complete\n");
6625895Syz147064 return (rv);
6635895Syz147064 }
6645895Syz147064
6655895Syz147064 /*
6665895Syz147064 * vlan_usage - Determine the usage of a link.
6675895Syz147064 * The returned buffer is owned by caller, and the caller
6685895Syz147064 * must free it up when done.
6695895Syz147064 */
6705895Syz147064 static char *
vlan_usage(link_cache_t * node)6715895Syz147064 vlan_usage(link_cache_t *node)
6725895Syz147064 {
6735895Syz147064 dl_vlan_t *vlan;
6745895Syz147064 int nvlan;
6755895Syz147064 char *buf;
6765895Syz147064 const char *fmt;
6775895Syz147064 char *sep;
6785895Syz147064 char errmsg[DLADM_STRSIZE];
6795895Syz147064 char name[MAXLINKNAMELEN];
6805895Syz147064 dladm_status_t status;
6815895Syz147064 size_t bufsz;
6825895Syz147064
6835895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: usage(%s)\n", node->vc_resource);
6845895Syz147064
6855895Syz147064 assert(MUTEX_HELD(&cache_lock));
6868453SAnurag.Maskey@Sun.COM if ((status = dladm_datalink_id2info(dld_handle, node->vc_linkid, NULL,
6878453SAnurag.Maskey@Sun.COM NULL, NULL, name, sizeof (name))) != DLADM_STATUS_OK) {
6885895Syz147064 rcm_log_message(RCM_ERROR,
6895895Syz147064 _("VLAN: usage(%s) get link name failure(%s)\n"),
6905895Syz147064 node->vc_resource, dladm_status2str(status, errmsg));
6915895Syz147064 return (NULL);
6925895Syz147064 }
6935895Syz147064
6945895Syz147064 if (node->vc_state & CACHE_NODE_OFFLINED)
6955895Syz147064 fmt = _("%1$s offlined");
6965895Syz147064 else
6975895Syz147064 fmt = _("%1$s VLANs: ");
6985895Syz147064
6995895Syz147064 /* TRANSLATION_NOTE: separator used between VLAN linkids */
7005895Syz147064 sep = _(", ");
7015895Syz147064
7025895Syz147064 nvlan = 0;
7035895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next)
7045895Syz147064 nvlan++;
7055895Syz147064
7065895Syz147064 /* space for VLANs and separators, plus message */
7075895Syz147064 bufsz = nvlan * (MAXLINKNAMELEN + strlen(sep)) +
7085895Syz147064 strlen(fmt) + MAXLINKNAMELEN + 1;
7095895Syz147064 if ((buf = malloc(bufsz)) == NULL) {
7105895Syz147064 rcm_log_message(RCM_ERROR,
7115895Syz147064 _("VLAN: usage(%s) malloc failure(%s)\n"),
7125895Syz147064 node->vc_resource, strerror(errno));
7135895Syz147064 return (NULL);
7145895Syz147064 }
7155895Syz147064 (void) snprintf(buf, bufsz, fmt, name);
7165895Syz147064
7175895Syz147064 if (node->vc_state & CACHE_NODE_OFFLINED) {
7185895Syz147064 /* Nothing else to do */
7195895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: usage (%s) info = %s\n",
7205895Syz147064 node->vc_resource, buf);
7215895Syz147064 return (buf);
7225895Syz147064 }
7235895Syz147064
7245895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
7255895Syz147064 rcm_log_message(RCM_DEBUG, "VLAN:= %u\n", vlan->dv_vlanid);
7265895Syz147064
7278453SAnurag.Maskey@Sun.COM if ((status = dladm_datalink_id2info(dld_handle,
7288453SAnurag.Maskey@Sun.COM vlan->dv_vlanid, NULL, NULL, NULL, name,
7298453SAnurag.Maskey@Sun.COM sizeof (name))) != DLADM_STATUS_OK) {
7305895Syz147064 rcm_log_message(RCM_ERROR,
7315895Syz147064 _("VLAN: usage(%s) get vlan %u name failure(%s)\n"),
7325895Syz147064 node->vc_resource, vlan->dv_vlanid,
7335895Syz147064 dladm_status2str(status, errmsg));
7345895Syz147064 free(buf);
7355895Syz147064 return (NULL);
7365895Syz147064 }
7375895Syz147064
7385895Syz147064 (void) strlcat(buf, name, bufsz);
7395895Syz147064 if (vlan->dv_next != NULL)
7405895Syz147064 (void) strlcat(buf, sep, bufsz);
7415895Syz147064 }
7425895Syz147064
7435895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: usage (%s) info = %s\n",
7445895Syz147064 node->vc_resource, buf);
7455895Syz147064
7465895Syz147064 return (buf);
7475895Syz147064 }
7485895Syz147064
7495895Syz147064 /*
7505895Syz147064 * Cache management routines, all cache management functions should be
7515895Syz147064 * be called with cache_lock held.
7525895Syz147064 */
7535895Syz147064
7545895Syz147064 /*
7555895Syz147064 * cache_lookup() - Get a cache node for a resource.
7565895Syz147064 * Call with cache lock held.
7575895Syz147064 *
7585895Syz147064 * This ensures that the cache is consistent with the system state and
7595895Syz147064 * returns a pointer to the cache element corresponding to the resource.
7605895Syz147064 */
7615895Syz147064 static link_cache_t *
cache_lookup(rcm_handle_t * hd,char * rsrc,char options)7625895Syz147064 cache_lookup(rcm_handle_t *hd, char *rsrc, char options)
7635895Syz147064 {
7645895Syz147064 link_cache_t *node;
7655895Syz147064
7665895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: cache lookup(%s)\n", rsrc);
7675895Syz147064
7685895Syz147064 assert(MUTEX_HELD(&cache_lock));
7695895Syz147064 if (options & CACHE_REFRESH) {
7705895Syz147064 /* drop lock since update locks cache again */
7715895Syz147064 (void) mutex_unlock(&cache_lock);
7725895Syz147064 (void) cache_update(hd);
7735895Syz147064 (void) mutex_lock(&cache_lock);
7745895Syz147064 }
7755895Syz147064
7765895Syz147064 node = cache_head.vc_next;
7775895Syz147064 for (; node != &cache_tail; node = node->vc_next) {
7785895Syz147064 if (strcmp(rsrc, node->vc_resource) == 0) {
7795895Syz147064 rcm_log_message(RCM_TRACE2,
7805895Syz147064 "VLAN: cache lookup succeeded(%s)\n", rsrc);
7815895Syz147064 return (node);
7825895Syz147064 }
7835895Syz147064 }
7845895Syz147064 return (NULL);
7855895Syz147064 }
7865895Syz147064
7875895Syz147064 /*
7885895Syz147064 * node_free - Free a node from the cache
7895895Syz147064 */
7905895Syz147064 static void
node_free(link_cache_t * node)7915895Syz147064 node_free(link_cache_t *node)
7925895Syz147064 {
7935895Syz147064 dl_vlan_t *vlan, *next;
7945895Syz147064
7955895Syz147064 if (node != NULL) {
7965895Syz147064 free(node->vc_resource);
7975895Syz147064
7985895Syz147064 /* free the VLAN list */
7995895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = next) {
8005895Syz147064 next = vlan->dv_next;
8015895Syz147064 free(vlan);
8025895Syz147064 }
8035895Syz147064 free(node);
8045895Syz147064 }
8055895Syz147064 }
8065895Syz147064
8075895Syz147064 /*
8085895Syz147064 * cache_insert - Insert a resource node in cache
8095895Syz147064 */
8105895Syz147064 static void
cache_insert(link_cache_t * node)8115895Syz147064 cache_insert(link_cache_t *node)
8125895Syz147064 {
8135895Syz147064 assert(MUTEX_HELD(&cache_lock));
8145895Syz147064
8155895Syz147064 /* insert at the head for best performance */
8165895Syz147064 node->vc_next = cache_head.vc_next;
8175895Syz147064 node->vc_prev = &cache_head;
8185895Syz147064
8195895Syz147064 node->vc_next->vc_prev = node;
8205895Syz147064 node->vc_prev->vc_next = node;
8215895Syz147064 }
8225895Syz147064
8235895Syz147064 /*
8245895Syz147064 * cache_remove() - Remove a resource node from cache.
8255895Syz147064 */
8265895Syz147064 static void
cache_remove(link_cache_t * node)8275895Syz147064 cache_remove(link_cache_t *node)
8285895Syz147064 {
8295895Syz147064 assert(MUTEX_HELD(&cache_lock));
8305895Syz147064 node->vc_next->vc_prev = node->vc_prev;
8315895Syz147064 node->vc_prev->vc_next = node->vc_next;
8325895Syz147064 node->vc_next = NULL;
8335895Syz147064 node->vc_prev = NULL;
8345895Syz147064 }
8355895Syz147064
8365895Syz147064 typedef struct vlan_update_arg_s {
8375895Syz147064 rcm_handle_t *hd;
8385895Syz147064 int retval;
8395895Syz147064 } vlan_update_arg_t;
8405895Syz147064
8415895Syz147064 /*
8425895Syz147064 * vlan_update() - Update physical interface properties
8435895Syz147064 */
8445895Syz147064 static int
vlan_update(dladm_handle_t handle,datalink_id_t vlanid,void * arg)8458453SAnurag.Maskey@Sun.COM vlan_update(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
8465895Syz147064 {
8475895Syz147064 vlan_update_arg_t *vlan_update_argp = arg;
8485895Syz147064 rcm_handle_t *hd = vlan_update_argp->hd;
8495895Syz147064 link_cache_t *node;
8505895Syz147064 dl_vlan_t *vlan;
8515895Syz147064 char *rsrc;
8525895Syz147064 dladm_vlan_attr_t vlan_attr;
8535895Syz147064 dladm_status_t status;
8545895Syz147064 char errmsg[DLADM_STRSIZE];
8556151Syz147064 boolean_t newnode = B_FALSE;
8565895Syz147064 int ret = -1;
8575895Syz147064
8585895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_update(%u)\n", vlanid);
8595895Syz147064
8605895Syz147064 assert(MUTEX_HELD(&cache_lock));
8618453SAnurag.Maskey@Sun.COM status = dladm_vlan_info(handle, vlanid, &vlan_attr, DLADM_OPT_ACTIVE);
8625895Syz147064 if (status != DLADM_STATUS_OK) {
8635895Syz147064 rcm_log_message(RCM_TRACE1,
8645895Syz147064 "VLAN: vlan_update() cannot get vlan information for "
8655895Syz147064 "%u(%s)\n", vlanid, dladm_status2str(status, errmsg));
8665895Syz147064 return (DLADM_WALK_CONTINUE);
8675895Syz147064 }
8685895Syz147064
8695895Syz147064 rsrc = malloc(RCM_LINK_RESOURCE_MAX);
8705895Syz147064 if (rsrc == NULL) {
8715895Syz147064 rcm_log_message(RCM_ERROR, _("VLAN: malloc error(%s): %u\n"),
8725895Syz147064 strerror(errno), vlanid);
8735895Syz147064 goto done;
8745895Syz147064 }
8755895Syz147064
8765895Syz147064 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
8775895Syz147064 RCM_LINK_PREFIX, vlan_attr.dv_linkid);
8785895Syz147064
8795895Syz147064 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
8805895Syz147064 if (node != NULL) {
8815895Syz147064 rcm_log_message(RCM_DEBUG,
8825895Syz147064 "VLAN: %s already registered (vlanid:%d)\n",
8835895Syz147064 rsrc, vlan_attr.dv_vid);
8845895Syz147064 free(rsrc);
8855895Syz147064 } else {
8865895Syz147064 rcm_log_message(RCM_DEBUG,
8875895Syz147064 "VLAN: %s is a new resource (vlanid:%d)\n",
8885895Syz147064 rsrc, vlan_attr.dv_vid);
8895895Syz147064 if ((node = calloc(1, sizeof (link_cache_t))) == NULL) {
8905895Syz147064 free(rsrc);
8915895Syz147064 rcm_log_message(RCM_ERROR, _("VLAN: calloc: %s\n"),
8925895Syz147064 strerror(errno));
8935895Syz147064 goto done;
8945895Syz147064 }
8955895Syz147064
8965895Syz147064 node->vc_resource = rsrc;
8975895Syz147064 node->vc_vlan = NULL;
8985895Syz147064 node->vc_linkid = vlan_attr.dv_linkid;
8995895Syz147064 node->vc_state |= CACHE_NODE_NEW;
9006151Syz147064 newnode = B_TRUE;
9015895Syz147064 }
9025895Syz147064
9035895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
9045895Syz147064 if (vlan->dv_vlanid == vlanid) {
9055895Syz147064 vlan->dv_flags &= ~VLAN_STALE;
9065895Syz147064 break;
9075895Syz147064 }
9085895Syz147064 }
9095895Syz147064
9105895Syz147064 if (vlan == NULL) {
9115895Syz147064 if ((vlan = calloc(1, sizeof (dl_vlan_t))) == NULL) {
9125895Syz147064 rcm_log_message(RCM_ERROR, _("VLAN: malloc: %s\n"),
9135895Syz147064 strerror(errno));
9146151Syz147064 if (newnode) {
9155895Syz147064 free(rsrc);
9165895Syz147064 free(node);
9175895Syz147064 }
9185895Syz147064 goto done;
9195895Syz147064 }
9205895Syz147064 vlan->dv_vlanid = vlanid;
9215895Syz147064 vlan->dv_next = node->vc_vlan;
9225895Syz147064 vlan->dv_prev = NULL;
9235895Syz147064 if (node->vc_vlan != NULL)
9245895Syz147064 node->vc_vlan->dv_prev = vlan;
9255895Syz147064 node->vc_vlan = vlan;
9265895Syz147064 }
9275895Syz147064
9285895Syz147064 node->vc_state &= ~CACHE_NODE_STALE;
9295895Syz147064
9306151Syz147064 if (newnode)
9315895Syz147064 cache_insert(node);
9325895Syz147064
9335895Syz147064 rcm_log_message(RCM_TRACE3, "VLAN: vlan_update: succeeded(%u)\n",
9345895Syz147064 vlanid);
9355895Syz147064 ret = 0;
9365895Syz147064 done:
9375895Syz147064 vlan_update_argp->retval = ret;
9385895Syz147064 return (ret == 0 ? DLADM_WALK_CONTINUE : DLADM_WALK_TERMINATE);
9395895Syz147064 }
9405895Syz147064
9415895Syz147064 /*
9425895Syz147064 * vlan_update_all() - Determine all VLAN links in the system
9435895Syz147064 */
9445895Syz147064 static int
vlan_update_all(rcm_handle_t * hd)9455895Syz147064 vlan_update_all(rcm_handle_t *hd)
9465895Syz147064 {
9475895Syz147064 vlan_update_arg_t arg = {NULL, 0};
9485895Syz147064
9495895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_update_all\n");
9505895Syz147064
9515895Syz147064 assert(MUTEX_HELD(&cache_lock));
9525895Syz147064 arg.hd = hd;
9538453SAnurag.Maskey@Sun.COM (void) dladm_walk_datalink_id(vlan_update, dld_handle, &arg,
9548453SAnurag.Maskey@Sun.COM DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
9555895Syz147064 return (arg.retval);
9565895Syz147064 }
9575895Syz147064
9585895Syz147064 /*
9595895Syz147064 * cache_update() - Update cache with latest interface info
9605895Syz147064 */
9615895Syz147064 static int
cache_update(rcm_handle_t * hd)9625895Syz147064 cache_update(rcm_handle_t *hd)
9635895Syz147064 {
9645895Syz147064 link_cache_t *node, *nnode;
9655895Syz147064 dl_vlan_t *vlan;
9665895Syz147064 int rv;
9675895Syz147064
9685895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: cache_update\n");
9695895Syz147064
9705895Syz147064 (void) mutex_lock(&cache_lock);
9715895Syz147064
9725895Syz147064 /* first we walk the entire cache, marking each entry stale */
9735895Syz147064 node = cache_head.vc_next;
9745895Syz147064 for (; node != &cache_tail; node = node->vc_next) {
9755895Syz147064 node->vc_state |= CACHE_NODE_STALE;
9765895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next)
9775895Syz147064 vlan->dv_flags |= VLAN_STALE;
9785895Syz147064 }
9795895Syz147064
9805895Syz147064 rv = vlan_update_all(hd);
9815895Syz147064
9825895Syz147064 /*
9835895Syz147064 * Continue to delete all stale nodes from the cache even
9845895Syz147064 * vlan_update_all() failed. Unregister link that are not offlined
9855895Syz147064 * and still in cache
9865895Syz147064 */
9875895Syz147064 for (node = cache_head.vc_next; node != &cache_tail; node = nnode) {
9885895Syz147064 dl_vlan_t *vlan, *next;
9895895Syz147064
9905895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = next) {
9915895Syz147064 next = vlan->dv_next;
9925895Syz147064
9935895Syz147064 /* clear stale VLANs */
9945895Syz147064 if (vlan->dv_flags & VLAN_STALE) {
9955895Syz147064 if (vlan->dv_prev != NULL)
9965895Syz147064 vlan->dv_prev->dv_next = next;
9975895Syz147064 else
9985895Syz147064 node->vc_vlan = next;
9995895Syz147064
10005895Syz147064 if (next != NULL)
10015895Syz147064 next->dv_prev = vlan->dv_prev;
10025895Syz147064 free(vlan);
10035895Syz147064 }
10045895Syz147064 }
10055895Syz147064
10065895Syz147064 nnode = node->vc_next;
10075895Syz147064 if (node->vc_state & CACHE_NODE_STALE) {
10085895Syz147064 (void) rcm_unregister_interest(hd, node->vc_resource,
10095895Syz147064 0);
10105895Syz147064 rcm_log_message(RCM_DEBUG, "VLAN: unregistered %s\n",
10115895Syz147064 node->vc_resource);
10125895Syz147064 assert(node->vc_vlan == NULL);
10135895Syz147064 cache_remove(node);
10145895Syz147064 node_free(node);
10155895Syz147064 continue;
10165895Syz147064 }
10175895Syz147064
10185895Syz147064 if (!(node->vc_state & CACHE_NODE_NEW))
10195895Syz147064 continue;
10205895Syz147064
10215895Syz147064 if (rcm_register_interest(hd, node->vc_resource, 0, NULL) !=
10225895Syz147064 RCM_SUCCESS) {
10235895Syz147064 rcm_log_message(RCM_ERROR,
10245895Syz147064 _("VLAN: failed to register %s\n"),
10255895Syz147064 node->vc_resource);
10265895Syz147064 rv = -1;
10275895Syz147064 } else {
10285895Syz147064 rcm_log_message(RCM_DEBUG, "VLAN: registered %s\n",
10295895Syz147064 node->vc_resource);
10305895Syz147064 node->vc_state &= ~CACHE_NODE_NEW;
10315895Syz147064 }
10325895Syz147064 }
10335895Syz147064
10345895Syz147064 (void) mutex_unlock(&cache_lock);
10355895Syz147064 return (rv);
10365895Syz147064 }
10375895Syz147064
10385895Syz147064 /*
10395895Syz147064 * cache_free() - Empty the cache
10405895Syz147064 */
10415895Syz147064 static void
cache_free()10425895Syz147064 cache_free()
10435895Syz147064 {
10445895Syz147064 link_cache_t *node;
10455895Syz147064
10465895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: cache_free\n");
10475895Syz147064
10485895Syz147064 (void) mutex_lock(&cache_lock);
10495895Syz147064 node = cache_head.vc_next;
10505895Syz147064 while (node != &cache_tail) {
10515895Syz147064 cache_remove(node);
10525895Syz147064 node_free(node);
10535895Syz147064 node = cache_head.vc_next;
10545895Syz147064 }
10555895Syz147064 (void) mutex_unlock(&cache_lock);
10565895Syz147064 }
10575895Syz147064
10585895Syz147064 /*
10595895Syz147064 * vlan_log_err() - RCM error log wrapper
10605895Syz147064 */
10615895Syz147064 static void
vlan_log_err(datalink_id_t linkid,char ** errorp,char * errmsg)10625895Syz147064 vlan_log_err(datalink_id_t linkid, char **errorp, char *errmsg)
10635895Syz147064 {
10645895Syz147064 char link[MAXLINKNAMELEN];
10655895Syz147064 char errstr[DLADM_STRSIZE];
10665895Syz147064 dladm_status_t status;
10675895Syz147064 int len;
10685895Syz147064 const char *errfmt;
10695895Syz147064 char *error;
10705895Syz147064
10715895Syz147064 link[0] = '\0';
10725895Syz147064 if (linkid != DATALINK_INVALID_LINKID) {
10735895Syz147064 char rsrc[RCM_LINK_RESOURCE_MAX];
10745895Syz147064
10755895Syz147064 (void) snprintf(rsrc, sizeof (rsrc), "%s/%u",
10765895Syz147064 RCM_LINK_PREFIX, linkid);
10775895Syz147064
10785895Syz147064 rcm_log_message(RCM_ERROR, _("VLAN: %s(%s)\n"), errmsg, rsrc);
10798453SAnurag.Maskey@Sun.COM if ((status = dladm_datalink_id2info(dld_handle, linkid, NULL,
10808453SAnurag.Maskey@Sun.COM NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
10815895Syz147064 rcm_log_message(RCM_WARNING,
10825895Syz147064 _("VLAN: cannot get link name for (%s) %s\n"),
10835895Syz147064 rsrc, dladm_status2str(status, errstr));
10845895Syz147064 }
10855895Syz147064 } else {
10865895Syz147064 rcm_log_message(RCM_ERROR, _("VLAN: %s\n"), errmsg);
10875895Syz147064 }
10885895Syz147064
10895895Syz147064 errfmt = strlen(link) > 0 ? _("VLAN: %s(%s)") : _("VLAN: %s");
10905895Syz147064 len = strlen(errfmt) + strlen(errmsg) + MAXLINKNAMELEN + 1;
10915895Syz147064 if ((error = malloc(len)) != NULL) {
10925895Syz147064 if (strlen(link) > 0)
10935895Syz147064 (void) snprintf(error, len, errfmt, errmsg, link);
10945895Syz147064 else
10955895Syz147064 (void) snprintf(error, len, errfmt, errmsg);
10965895Syz147064 }
10975895Syz147064
10985895Syz147064 if (errorp != NULL)
10995895Syz147064 *errorp = error;
11005895Syz147064 }
11015895Syz147064
11025895Syz147064 /*
11035895Syz147064 * vlan_consumer_online()
11045895Syz147064 *
11055895Syz147064 * Notify online to VLAN consumers.
11065895Syz147064 */
11075895Syz147064 /* ARGSUSED */
11085895Syz147064 static void
vlan_consumer_online(rcm_handle_t * hd,link_cache_t * node,char ** errorp,uint_t flags,rcm_info_t ** info)11095895Syz147064 vlan_consumer_online(rcm_handle_t *hd, link_cache_t *node, char **errorp,
11105895Syz147064 uint_t flags, rcm_info_t **info)
11115895Syz147064 {
11125895Syz147064 dl_vlan_t *vlan;
11135895Syz147064 char rsrc[RCM_LINK_RESOURCE_MAX];
11145895Syz147064
11155895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_online (%s)\n",
11165895Syz147064 node->vc_resource);
11175895Syz147064
11185895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
11195895Syz147064 if (!(vlan->dv_flags & VLAN_CONSUMER_OFFLINED))
11205895Syz147064 continue;
11215895Syz147064
11225895Syz147064 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
11235895Syz147064 RCM_LINK_PREFIX, vlan->dv_vlanid);
11245895Syz147064
11255895Syz147064 if (rcm_notify_online(hd, rsrc, flags, info) == RCM_SUCCESS)
11265895Syz147064 vlan->dv_flags &= ~VLAN_CONSUMER_OFFLINED;
11275895Syz147064 }
11285895Syz147064
11295895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_online done\n");
11305895Syz147064 }
11315895Syz147064
11325895Syz147064 /*
11335895Syz147064 * vlan_consumer_offline()
11345895Syz147064 *
11355895Syz147064 * Offline VLAN consumers.
11365895Syz147064 */
11375895Syz147064 static int
vlan_consumer_offline(rcm_handle_t * hd,link_cache_t * node,char ** errorp,uint_t flags,rcm_info_t ** info)11385895Syz147064 vlan_consumer_offline(rcm_handle_t *hd, link_cache_t *node, char **errorp,
11395895Syz147064 uint_t flags, rcm_info_t **info)
11405895Syz147064 {
11415895Syz147064 dl_vlan_t *vlan;
11425895Syz147064 char rsrc[RCM_LINK_RESOURCE_MAX];
11435895Syz147064 int ret = RCM_SUCCESS;
11445895Syz147064
11455895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_offline (%s)\n",
11465895Syz147064 node->vc_resource);
11475895Syz147064
11485895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
11495895Syz147064 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
11505895Syz147064 RCM_LINK_PREFIX, vlan->dv_vlanid);
11515895Syz147064
11525895Syz147064 ret = rcm_request_offline(hd, rsrc, flags, info);
11535895Syz147064 if (ret != RCM_SUCCESS)
11545895Syz147064 break;
11555895Syz147064
11565895Syz147064 vlan->dv_flags |= VLAN_CONSUMER_OFFLINED;
11575895Syz147064 }
11585895Syz147064
11595895Syz147064 if (vlan != NULL)
11605895Syz147064 vlan_consumer_online(hd, node, errorp, flags, info);
11615895Syz147064
11625895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_offline done\n");
11635895Syz147064 return (ret);
11645895Syz147064 }
11655895Syz147064
11665895Syz147064 /*
11675895Syz147064 * Send RCM_RESOURCE_LINK_NEW events to other modules about new VLANs.
11685895Syz147064 * Return 0 on success, -1 on failure.
11695895Syz147064 */
11705895Syz147064 static int
vlan_notify_new_vlan(rcm_handle_t * hd,char * rsrc)11715895Syz147064 vlan_notify_new_vlan(rcm_handle_t *hd, char *rsrc)
11725895Syz147064 {
11735895Syz147064 link_cache_t *node;
11745895Syz147064 dl_vlan_t *vlan;
11755895Syz147064 nvlist_t *nvl = NULL;
11765895Syz147064 uint64_t id;
11775895Syz147064 int ret = -1;
11785895Syz147064
11795895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_notify_new_vlan (%s)\n", rsrc);
11805895Syz147064
11815895Syz147064 (void) mutex_lock(&cache_lock);
11825895Syz147064 if ((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) == NULL) {
11835895Syz147064 (void) mutex_unlock(&cache_lock);
11845895Syz147064 return (0);
11855895Syz147064 }
11865895Syz147064
11875895Syz147064 if (nvlist_alloc(&nvl, 0, 0) != 0) {
11885895Syz147064 (void) mutex_unlock(&cache_lock);
11895895Syz147064 rcm_log_message(RCM_WARNING,
11905895Syz147064 _("VLAN: failed to allocate nvlist\n"));
11915895Syz147064 goto done;
11925895Syz147064 }
11935895Syz147064
11945895Syz147064 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
11958275SEric Cheng rcm_log_message(RCM_TRACE2,
11968275SEric Cheng "VLAN: vlan_notify_new_vlan add (%u)\n",
11978275SEric Cheng vlan->dv_vlanid);
11985895Syz147064
11998275SEric Cheng id = vlan->dv_vlanid;
12008275SEric Cheng if (nvlist_add_uint64(nvl, RCM_NV_LINKID, id) != 0) {
12018275SEric Cheng rcm_log_message(RCM_ERROR,
12028275SEric Cheng _("VLAN: failed to construct nvlist\n"));
12038275SEric Cheng (void) mutex_unlock(&cache_lock);
12048275SEric Cheng goto done;
12055895Syz147064 }
12065895Syz147064 }
12075895Syz147064 (void) mutex_unlock(&cache_lock);
12085895Syz147064
12095895Syz147064 if (rcm_notify_event(hd, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) !=
12105895Syz147064 RCM_SUCCESS) {
12115895Syz147064 rcm_log_message(RCM_ERROR,
12125895Syz147064 _("VLAN: failed to notify %s event for %s\n"),
12135895Syz147064 RCM_RESOURCE_LINK_NEW, node->vc_resource);
12145895Syz147064 goto done;
12155895Syz147064 }
12165895Syz147064
12175895Syz147064 ret = 0;
12185895Syz147064 done:
12195895Syz147064 if (nvl != NULL)
12205895Syz147064 nvlist_free(nvl);
12215895Syz147064 return (ret);
12225895Syz147064 }
12235895Syz147064
12245895Syz147064 /*
12255895Syz147064 * vlan_consumer_notify() - Notify consumers of VLANs coming back online.
12265895Syz147064 */
12275895Syz147064 static int
vlan_consumer_notify(rcm_handle_t * hd,datalink_id_t linkid,char ** errorp,uint_t flags,rcm_info_t ** info)12285895Syz147064 vlan_consumer_notify(rcm_handle_t *hd, datalink_id_t linkid, char **errorp,
12295895Syz147064 uint_t flags, rcm_info_t **info)
12305895Syz147064 {
12315895Syz147064 char rsrc[RCM_LINK_RESOURCE_MAX];
12325895Syz147064 link_cache_t *node;
12335895Syz147064
12345895Syz147064 /* Check for the interface in the cache */
12355895Syz147064 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", RCM_LINK_PREFIX,
12365895Syz147064 linkid);
12375895Syz147064
12385895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_notify(%s)\n", rsrc);
12395895Syz147064
12405895Syz147064 /*
12415895Syz147064 * Inform IP consumers of the new link.
12425895Syz147064 */
12435895Syz147064 if (vlan_notify_new_vlan(hd, rsrc) != 0) {
12445895Syz147064 (void) mutex_lock(&cache_lock);
12455895Syz147064 if ((node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH)) != NULL) {
12465895Syz147064 (void) vlan_offline_vlan(node, VLAN_STALE,
12475895Syz147064 CACHE_NODE_STALE);
12485895Syz147064 }
12495895Syz147064 (void) mutex_unlock(&cache_lock);
12505895Syz147064 rcm_log_message(RCM_TRACE2,
12515895Syz147064 "VLAN: vlan_notify_new_vlan failed(%s)\n", rsrc);
12525895Syz147064 return (-1);
12535895Syz147064 }
12545895Syz147064
12555895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_notify succeeded\n");
12565895Syz147064 return (0);
12575895Syz147064 }
12585895Syz147064
12595895Syz147064 typedef struct vlan_up_arg_s {
12605895Syz147064 datalink_id_t linkid;
12615895Syz147064 int retval;
12625895Syz147064 } vlan_up_arg_t;
12635895Syz147064
12645895Syz147064 static int
vlan_up(dladm_handle_t handle,datalink_id_t vlanid,void * arg)12658453SAnurag.Maskey@Sun.COM vlan_up(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
12665895Syz147064 {
12675895Syz147064 vlan_up_arg_t *vlan_up_argp = arg;
12685895Syz147064 dladm_status_t status;
12695895Syz147064 dladm_vlan_attr_t vlan_attr;
12705895Syz147064 char errmsg[DLADM_STRSIZE];
12715895Syz147064
12728453SAnurag.Maskey@Sun.COM status = dladm_vlan_info(handle, vlanid, &vlan_attr, DLADM_OPT_PERSIST);
12735895Syz147064 if (status != DLADM_STATUS_OK) {
12745895Syz147064 rcm_log_message(RCM_TRACE1,
12755895Syz147064 "VLAN: vlan_up(): cannot get information for VLAN %u "
12765895Syz147064 "(%s)\n", vlanid, dladm_status2str(status, errmsg));
12775895Syz147064 return (DLADM_WALK_CONTINUE);
12785895Syz147064 }
12795895Syz147064
12805895Syz147064 if (vlan_attr.dv_linkid != vlan_up_argp->linkid)
12815895Syz147064 return (DLADM_WALK_CONTINUE);
12825895Syz147064
12835895Syz147064 rcm_log_message(RCM_TRACE3, "VLAN: vlan_up(%u)\n", vlanid);
12848453SAnurag.Maskey@Sun.COM if ((status = dladm_vlan_up(handle, vlanid)) == DLADM_STATUS_OK)
12855895Syz147064 return (DLADM_WALK_CONTINUE);
12865895Syz147064
12875895Syz147064 /*
12885895Syz147064 * Prompt the warning message and continue to UP other VLANs.
12895895Syz147064 */
12905895Syz147064 rcm_log_message(RCM_WARNING,
12915895Syz147064 _("VLAN: VLAN up failed (%u): %s\n"),
12925895Syz147064 vlanid, dladm_status2str(status, errmsg));
12935895Syz147064
12945895Syz147064 vlan_up_argp->retval = -1;
12955895Syz147064 return (DLADM_WALK_CONTINUE);
12965895Syz147064 }
12975895Syz147064
12985895Syz147064 /*
12995895Syz147064 * vlan_configure() - Configure VLANs over a physical link after it attaches
13005895Syz147064 */
13015895Syz147064 static int
vlan_configure(rcm_handle_t * hd,datalink_id_t linkid)13025895Syz147064 vlan_configure(rcm_handle_t *hd, datalink_id_t linkid)
13035895Syz147064 {
13045895Syz147064 char rsrc[RCM_LINK_RESOURCE_MAX];
13055895Syz147064 link_cache_t *node;
13065895Syz147064 vlan_up_arg_t arg = {DATALINK_INVALID_LINKID, 0};
13075895Syz147064
13085895Syz147064 /* Check for the VLANs in the cache */
13095895Syz147064 (void) snprintf(rsrc, sizeof (rsrc), "%s/%u", RCM_LINK_PREFIX, linkid);
13105895Syz147064
13115895Syz147064 rcm_log_message(RCM_TRACE2, "VLAN: vlan_configure(%s)\n", rsrc);
13125895Syz147064
13135895Syz147064 /* Check if the link is new or was previously offlined */
13145895Syz147064 (void) mutex_lock(&cache_lock);
13155895Syz147064 if (((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) != NULL) &&
13165895Syz147064 (!(node->vc_state & CACHE_NODE_OFFLINED))) {
13175895Syz147064 rcm_log_message(RCM_TRACE2,
13185895Syz147064 "VLAN: Skipping configured interface(%s)\n", rsrc);
13195895Syz147064 (void) mutex_unlock(&cache_lock);
13205895Syz147064 return (0);
13215895Syz147064 }
13225895Syz147064 (void) mutex_unlock(&cache_lock);
13235895Syz147064
13245895Syz147064 arg.linkid = linkid;
13258453SAnurag.Maskey@Sun.COM (void) dladm_walk_datalink_id(vlan_up, dld_handle, &arg,
13268453SAnurag.Maskey@Sun.COM DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
13275895Syz147064
13285895Syz147064 if (arg.retval == 0) {
13295895Syz147064 rcm_log_message(RCM_TRACE2,
13305895Syz147064 "VLAN: vlan_configure succeeded(%s)\n", rsrc);
13315895Syz147064 }
13325895Syz147064 return (arg.retval);
13335895Syz147064 }
1334