1*4eaa4710SRishi Srivatsavai /*
2*4eaa4710SRishi Srivatsavai  * CDDL HEADER START
3*4eaa4710SRishi Srivatsavai  *
4*4eaa4710SRishi Srivatsavai  * The contents of this file are subject to the terms of the
5*4eaa4710SRishi Srivatsavai  * Common Development and Distribution License (the "License").
6*4eaa4710SRishi Srivatsavai  * You may not use this file except in compliance with the License.
7*4eaa4710SRishi Srivatsavai  *
8*4eaa4710SRishi Srivatsavai  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4eaa4710SRishi Srivatsavai  * or http://www.opensolaris.org/os/licensing.
10*4eaa4710SRishi Srivatsavai  * See the License for the specific language governing permissions
11*4eaa4710SRishi Srivatsavai  * and limitations under the License.
12*4eaa4710SRishi Srivatsavai  *
13*4eaa4710SRishi Srivatsavai  * When distributing Covered Code, include this CDDL HEADER in each
14*4eaa4710SRishi Srivatsavai  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4eaa4710SRishi Srivatsavai  * If applicable, add the following below this CDDL HEADER, with the
16*4eaa4710SRishi Srivatsavai  * fields enclosed by brackets "[]" replaced with your own identifying
17*4eaa4710SRishi Srivatsavai  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4eaa4710SRishi Srivatsavai  *
19*4eaa4710SRishi Srivatsavai  * CDDL HEADER END
20*4eaa4710SRishi Srivatsavai  */
21*4eaa4710SRishi Srivatsavai /*
22*4eaa4710SRishi Srivatsavai  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*4eaa4710SRishi Srivatsavai  * Use is subject to license terms.
24*4eaa4710SRishi Srivatsavai  */
25*4eaa4710SRishi Srivatsavai 
26*4eaa4710SRishi Srivatsavai /*
27*4eaa4710SRishi Srivatsavai  * This RCM module adds support to the RCM framework for Bridge links
28*4eaa4710SRishi Srivatsavai  */
29*4eaa4710SRishi Srivatsavai 
30*4eaa4710SRishi Srivatsavai #include <stdio.h>
31*4eaa4710SRishi Srivatsavai #include <stdlib.h>
32*4eaa4710SRishi Srivatsavai #include <string.h>
33*4eaa4710SRishi Srivatsavai #include <errno.h>
34*4eaa4710SRishi Srivatsavai #include <sys/types.h>
35*4eaa4710SRishi Srivatsavai #include <synch.h>
36*4eaa4710SRishi Srivatsavai #include <assert.h>
37*4eaa4710SRishi Srivatsavai #include <strings.h>
38*4eaa4710SRishi Srivatsavai #include "rcm_module.h"
39*4eaa4710SRishi Srivatsavai #include <libintl.h>
40*4eaa4710SRishi Srivatsavai #include <libdllink.h>
41*4eaa4710SRishi Srivatsavai #include <libdlbridge.h>
42*4eaa4710SRishi Srivatsavai #include <libdlpi.h>
43*4eaa4710SRishi Srivatsavai 
44*4eaa4710SRishi Srivatsavai /*
45*4eaa4710SRishi Srivatsavai  * Definitions
46*4eaa4710SRishi Srivatsavai  */
47*4eaa4710SRishi Srivatsavai #ifndef lint
48*4eaa4710SRishi Srivatsavai #define	_(x)	gettext(x)
49*4eaa4710SRishi Srivatsavai #else
50*4eaa4710SRishi Srivatsavai #define	_(x)	x
51*4eaa4710SRishi Srivatsavai #endif
52*4eaa4710SRishi Srivatsavai 
53*4eaa4710SRishi Srivatsavai /* Some generic well-knowns and defaults used in this module */
54*4eaa4710SRishi Srivatsavai #define	RCM_LINK_PREFIX		"SUNW_datalink"	/* RCM datalink name prefix */
55*4eaa4710SRishi Srivatsavai #define	RCM_LINK_RESOURCE_MAX	(13 + LINKID_STR_WIDTH)
56*4eaa4710SRishi Srivatsavai 
57*4eaa4710SRishi Srivatsavai /* Bridge Cache state flags */
58*4eaa4710SRishi Srivatsavai typedef enum {
59*4eaa4710SRishi Srivatsavai 	CACHE_NODE_STALE	= 0x1,		/* stale cached data */
60*4eaa4710SRishi Srivatsavai 	CACHE_NODE_NEW		= 0x2,		/* new cached nodes */
61*4eaa4710SRishi Srivatsavai 	CACHE_NODE_OFFLINED	= 0x4		/* nodes offlined */
62*4eaa4710SRishi Srivatsavai } cache_node_state_t;
63*4eaa4710SRishi Srivatsavai 
64*4eaa4710SRishi Srivatsavai /* Network Cache lookup options */
65*4eaa4710SRishi Srivatsavai #define	CACHE_NO_REFRESH	0x1		/* cache refresh not needed */
66*4eaa4710SRishi Srivatsavai #define	CACHE_REFRESH		0x2		/* refresh cache */
67*4eaa4710SRishi Srivatsavai 
68*4eaa4710SRishi Srivatsavai /* Cache element */
69*4eaa4710SRishi Srivatsavai typedef struct link_cache {
70*4eaa4710SRishi Srivatsavai 	struct link_cache	*vc_next;	/* next cached resource */
71*4eaa4710SRishi Srivatsavai 	struct link_cache	*vc_prev;	/* prev cached resource */
72*4eaa4710SRishi Srivatsavai 	char			*vc_resource;	/* resource name */
73*4eaa4710SRishi Srivatsavai 	datalink_id_t		vc_linkid;	/* linkid */
74*4eaa4710SRishi Srivatsavai 	cache_node_state_t	vc_state;	/* cache state flags */
75*4eaa4710SRishi Srivatsavai 	char			vc_bridge[MAXLINKNAMELEN];
76*4eaa4710SRishi Srivatsavai } link_cache_t;
77*4eaa4710SRishi Srivatsavai 
78*4eaa4710SRishi Srivatsavai /*
79*4eaa4710SRishi Srivatsavai  * Global cache for network Bridges
80*4eaa4710SRishi Srivatsavai  */
81*4eaa4710SRishi Srivatsavai static link_cache_t	cache_head;
82*4eaa4710SRishi Srivatsavai static link_cache_t	cache_tail;
83*4eaa4710SRishi Srivatsavai static mutex_t		cache_lock;
84*4eaa4710SRishi Srivatsavai static boolean_t	events_registered = B_FALSE;
85*4eaa4710SRishi Srivatsavai 
86*4eaa4710SRishi Srivatsavai static dladm_handle_t	dld_handle = NULL;
87*4eaa4710SRishi Srivatsavai 
88*4eaa4710SRishi Srivatsavai /*
89*4eaa4710SRishi Srivatsavai  * RCM module interface prototypes
90*4eaa4710SRishi Srivatsavai  */
91*4eaa4710SRishi Srivatsavai static int		bridge_register(rcm_handle_t *);
92*4eaa4710SRishi Srivatsavai static int		bridge_unregister(rcm_handle_t *);
93*4eaa4710SRishi Srivatsavai static int		bridge_get_info(rcm_handle_t *, char *, id_t, uint_t,
94*4eaa4710SRishi Srivatsavai 			    char **, char **, nvlist_t *, rcm_info_t **);
95*4eaa4710SRishi Srivatsavai static int		bridge_suspend(rcm_handle_t *, char *, id_t,
96*4eaa4710SRishi Srivatsavai 			    timespec_t *, uint_t, char **, rcm_info_t **);
97*4eaa4710SRishi Srivatsavai static int		bridge_resume(rcm_handle_t *, char *, id_t, uint_t,
98*4eaa4710SRishi Srivatsavai 			    char **, rcm_info_t **);
99*4eaa4710SRishi Srivatsavai static int		bridge_offline(rcm_handle_t *, char *, id_t, uint_t,
100*4eaa4710SRishi Srivatsavai 			    char **, rcm_info_t **);
101*4eaa4710SRishi Srivatsavai static int		bridge_undo_offline(rcm_handle_t *, char *, id_t,
102*4eaa4710SRishi Srivatsavai 			    uint_t, char **, rcm_info_t **);
103*4eaa4710SRishi Srivatsavai static int		bridge_remove(rcm_handle_t *, char *, id_t, uint_t,
104*4eaa4710SRishi Srivatsavai 			    char **, rcm_info_t **);
105*4eaa4710SRishi Srivatsavai static int		bridge_notify_event(rcm_handle_t *, char *, id_t,
106*4eaa4710SRishi Srivatsavai 			    uint_t, char **, nvlist_t *, rcm_info_t **);
107*4eaa4710SRishi Srivatsavai static int		bridge_configure(rcm_handle_t *, datalink_id_t);
108*4eaa4710SRishi Srivatsavai 
109*4eaa4710SRishi Srivatsavai /* Module private routines */
110*4eaa4710SRishi Srivatsavai static void 		cache_free(void);
111*4eaa4710SRishi Srivatsavai static int 		cache_update(rcm_handle_t *);
112*4eaa4710SRishi Srivatsavai static void 		cache_remove(link_cache_t *);
113*4eaa4710SRishi Srivatsavai static void 		node_free(link_cache_t *);
114*4eaa4710SRishi Srivatsavai static void 		cache_insert(link_cache_t *);
115*4eaa4710SRishi Srivatsavai static link_cache_t	*cache_lookup(rcm_handle_t *, char *, uint_t);
116*4eaa4710SRishi Srivatsavai static char 		*bridge_usage(link_cache_t *);
117*4eaa4710SRishi Srivatsavai static void 		bridge_log_err(datalink_id_t, char **, char *);
118*4eaa4710SRishi Srivatsavai 
119*4eaa4710SRishi Srivatsavai /* Module-Private data */
120*4eaa4710SRishi Srivatsavai static struct rcm_mod_ops bridge_ops =
121*4eaa4710SRishi Srivatsavai {
122*4eaa4710SRishi Srivatsavai 	RCM_MOD_OPS_VERSION,
123*4eaa4710SRishi Srivatsavai 	bridge_register,
124*4eaa4710SRishi Srivatsavai 	bridge_unregister,
125*4eaa4710SRishi Srivatsavai 	bridge_get_info,
126*4eaa4710SRishi Srivatsavai 	bridge_suspend,
127*4eaa4710SRishi Srivatsavai 	bridge_resume,
128*4eaa4710SRishi Srivatsavai 	bridge_offline,
129*4eaa4710SRishi Srivatsavai 	bridge_undo_offline,
130*4eaa4710SRishi Srivatsavai 	bridge_remove,
131*4eaa4710SRishi Srivatsavai 	NULL,
132*4eaa4710SRishi Srivatsavai 	NULL,
133*4eaa4710SRishi Srivatsavai 	bridge_notify_event
134*4eaa4710SRishi Srivatsavai };
135*4eaa4710SRishi Srivatsavai 
136*4eaa4710SRishi Srivatsavai /*
137*4eaa4710SRishi Srivatsavai  * rcm_mod_init() - Update registrations, and return the ops structure.
138*4eaa4710SRishi Srivatsavai  */
139*4eaa4710SRishi Srivatsavai struct rcm_mod_ops *
rcm_mod_init(void)140*4eaa4710SRishi Srivatsavai rcm_mod_init(void)
141*4eaa4710SRishi Srivatsavai {
142*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
143*4eaa4710SRishi Srivatsavai 	char errmsg[DLADM_STRSIZE];
144*4eaa4710SRishi Srivatsavai 
145*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: mod_init\n");
146*4eaa4710SRishi Srivatsavai 
147*4eaa4710SRishi Srivatsavai 	cache_head.vc_next = &cache_tail;
148*4eaa4710SRishi Srivatsavai 	cache_head.vc_prev = NULL;
149*4eaa4710SRishi Srivatsavai 	cache_tail.vc_prev = &cache_head;
150*4eaa4710SRishi Srivatsavai 	cache_tail.vc_next = NULL;
151*4eaa4710SRishi Srivatsavai 	(void) mutex_init(&cache_lock, 0, NULL);
152*4eaa4710SRishi Srivatsavai 
153*4eaa4710SRishi Srivatsavai 	if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) {
154*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_WARNING,
155*4eaa4710SRishi Srivatsavai 		    "Bridge: cannot open datalink handle: %s\n",
156*4eaa4710SRishi Srivatsavai 		    dladm_status2str(status, errmsg));
157*4eaa4710SRishi Srivatsavai 		return (NULL);
158*4eaa4710SRishi Srivatsavai 	}
159*4eaa4710SRishi Srivatsavai 
160*4eaa4710SRishi Srivatsavai 	/* Return the ops vectors */
161*4eaa4710SRishi Srivatsavai 	return (&bridge_ops);
162*4eaa4710SRishi Srivatsavai }
163*4eaa4710SRishi Srivatsavai 
164*4eaa4710SRishi Srivatsavai /*
165*4eaa4710SRishi Srivatsavai  * rcm_mod_info() - Return a string describing this module.
166*4eaa4710SRishi Srivatsavai  */
167*4eaa4710SRishi Srivatsavai const char *
rcm_mod_info(void)168*4eaa4710SRishi Srivatsavai rcm_mod_info(void)
169*4eaa4710SRishi Srivatsavai {
170*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: mod_info\n");
171*4eaa4710SRishi Srivatsavai 
172*4eaa4710SRishi Srivatsavai 	return ("Bridge module version 1.0");
173*4eaa4710SRishi Srivatsavai }
174*4eaa4710SRishi Srivatsavai 
175*4eaa4710SRishi Srivatsavai /*
176*4eaa4710SRishi Srivatsavai  * rcm_mod_fini() - Destroy the network Bridge cache.
177*4eaa4710SRishi Srivatsavai  */
178*4eaa4710SRishi Srivatsavai int
rcm_mod_fini(void)179*4eaa4710SRishi Srivatsavai rcm_mod_fini(void)
180*4eaa4710SRishi Srivatsavai {
181*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: mod_fini\n");
182*4eaa4710SRishi Srivatsavai 
183*4eaa4710SRishi Srivatsavai 	/*
184*4eaa4710SRishi Srivatsavai 	 * Note that bridge_unregister() does not seem to be called anywhere,
185*4eaa4710SRishi Srivatsavai 	 * therefore we free the cache nodes here. In theory we should call
186*4eaa4710SRishi Srivatsavai 	 * rcm_register_interest() for each node before we free it, but the
187*4eaa4710SRishi Srivatsavai 	 * framework does not provide the rcm_handle to allow us to do so.
188*4eaa4710SRishi Srivatsavai 	 */
189*4eaa4710SRishi Srivatsavai 	cache_free();
190*4eaa4710SRishi Srivatsavai 	(void) mutex_destroy(&cache_lock);
191*4eaa4710SRishi Srivatsavai 
192*4eaa4710SRishi Srivatsavai 	dladm_close(dld_handle);
193*4eaa4710SRishi Srivatsavai 	return (RCM_SUCCESS);
194*4eaa4710SRishi Srivatsavai }
195*4eaa4710SRishi Srivatsavai 
196*4eaa4710SRishi Srivatsavai /*
197*4eaa4710SRishi Srivatsavai  * bridge_register() - Make sure the cache is properly sync'ed, and its
198*4eaa4710SRishi Srivatsavai  *		       registrations are in order.
199*4eaa4710SRishi Srivatsavai  */
200*4eaa4710SRishi Srivatsavai static int
bridge_register(rcm_handle_t * hd)201*4eaa4710SRishi Srivatsavai bridge_register(rcm_handle_t *hd)
202*4eaa4710SRishi Srivatsavai {
203*4eaa4710SRishi Srivatsavai 	int retv;
204*4eaa4710SRishi Srivatsavai 
205*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: register\n");
206*4eaa4710SRishi Srivatsavai 
207*4eaa4710SRishi Srivatsavai 	if ((retv = cache_update(hd)) != RCM_SUCCESS)
208*4eaa4710SRishi Srivatsavai 		return (retv);
209*4eaa4710SRishi Srivatsavai 
210*4eaa4710SRishi Srivatsavai 	/*
211*4eaa4710SRishi Srivatsavai 	 * Need to register interest in all new resources
212*4eaa4710SRishi Srivatsavai 	 * getting attached, so we get attach event notifications
213*4eaa4710SRishi Srivatsavai 	 */
214*4eaa4710SRishi Srivatsavai 	if (!events_registered) {
215*4eaa4710SRishi Srivatsavai 		retv = rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL);
216*4eaa4710SRishi Srivatsavai 		if (retv != RCM_SUCCESS) {
217*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_ERROR,
218*4eaa4710SRishi Srivatsavai 			    _("Bridge: failed to register %s\n"),
219*4eaa4710SRishi Srivatsavai 			    RCM_RESOURCE_LINK_NEW);
220*4eaa4710SRishi Srivatsavai 		} else {
221*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_DEBUG, "Bridge: registered %s\n",
222*4eaa4710SRishi Srivatsavai 			    RCM_RESOURCE_LINK_NEW);
223*4eaa4710SRishi Srivatsavai 			events_registered = B_TRUE;
224*4eaa4710SRishi Srivatsavai 		}
225*4eaa4710SRishi Srivatsavai 	}
226*4eaa4710SRishi Srivatsavai 
227*4eaa4710SRishi Srivatsavai 	return (retv);
228*4eaa4710SRishi Srivatsavai }
229*4eaa4710SRishi Srivatsavai 
230*4eaa4710SRishi Srivatsavai /*
231*4eaa4710SRishi Srivatsavai  * bridge_unregister() - Walk the cache, unregistering all the links.
232*4eaa4710SRishi Srivatsavai  */
233*4eaa4710SRishi Srivatsavai static int
bridge_unregister(rcm_handle_t * hd)234*4eaa4710SRishi Srivatsavai bridge_unregister(rcm_handle_t *hd)
235*4eaa4710SRishi Srivatsavai {
236*4eaa4710SRishi Srivatsavai 	link_cache_t *node;
237*4eaa4710SRishi Srivatsavai 	int retv = RCM_SUCCESS;
238*4eaa4710SRishi Srivatsavai 
239*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: unregister\n");
240*4eaa4710SRishi Srivatsavai 
241*4eaa4710SRishi Srivatsavai 	/* Walk the cache, unregistering everything */
242*4eaa4710SRishi Srivatsavai 	(void) mutex_lock(&cache_lock);
243*4eaa4710SRishi Srivatsavai 	node = cache_head.vc_next;
244*4eaa4710SRishi Srivatsavai 	while (node != &cache_tail) {
245*4eaa4710SRishi Srivatsavai 		retv = rcm_unregister_interest(hd, node->vc_resource, 0);
246*4eaa4710SRishi Srivatsavai 		if (retv != RCM_SUCCESS)
247*4eaa4710SRishi Srivatsavai 			break;
248*4eaa4710SRishi Srivatsavai 		cache_remove(node);
249*4eaa4710SRishi Srivatsavai 		node_free(node);
250*4eaa4710SRishi Srivatsavai 		node = cache_head.vc_next;
251*4eaa4710SRishi Srivatsavai 	}
252*4eaa4710SRishi Srivatsavai 	(void) mutex_unlock(&cache_lock);
253*4eaa4710SRishi Srivatsavai 	if (retv != RCM_SUCCESS) {
254*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_ERROR,
255*4eaa4710SRishi Srivatsavai 		    _("Bridge: failed to unregister %s\n"), node->vc_resource);
256*4eaa4710SRishi Srivatsavai 		return (retv);
257*4eaa4710SRishi Srivatsavai 	}
258*4eaa4710SRishi Srivatsavai 
259*4eaa4710SRishi Srivatsavai 	/*
260*4eaa4710SRishi Srivatsavai 	 * Unregister interest in all new resources
261*4eaa4710SRishi Srivatsavai 	 */
262*4eaa4710SRishi Srivatsavai 	if (events_registered) {
263*4eaa4710SRishi Srivatsavai 		retv = rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0);
264*4eaa4710SRishi Srivatsavai 		if (retv != RCM_SUCCESS) {
265*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_ERROR,
266*4eaa4710SRishi Srivatsavai 			    _("Bridge: failed to unregister %s\n"),
267*4eaa4710SRishi Srivatsavai 			    RCM_RESOURCE_LINK_NEW);
268*4eaa4710SRishi Srivatsavai 		} else {
269*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_DEBUG, "Bridge: unregistered %s\n",
270*4eaa4710SRishi Srivatsavai 			    RCM_RESOURCE_LINK_NEW);
271*4eaa4710SRishi Srivatsavai 			events_registered = B_FALSE;
272*4eaa4710SRishi Srivatsavai 		}
273*4eaa4710SRishi Srivatsavai 	}
274*4eaa4710SRishi Srivatsavai 
275*4eaa4710SRishi Srivatsavai 	return (retv);
276*4eaa4710SRishi Srivatsavai }
277*4eaa4710SRishi Srivatsavai 
278*4eaa4710SRishi Srivatsavai /*
279*4eaa4710SRishi Srivatsavai  * bridge_offline() - Offline the bridge on a specific link.
280*4eaa4710SRishi Srivatsavai  */
281*4eaa4710SRishi Srivatsavai static int
bridge_offline(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)282*4eaa4710SRishi Srivatsavai bridge_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
283*4eaa4710SRishi Srivatsavai     char **errorp, rcm_info_t **info)
284*4eaa4710SRishi Srivatsavai {
285*4eaa4710SRishi Srivatsavai 	link_cache_t *node;
286*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
287*4eaa4710SRishi Srivatsavai 
288*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: offline(%s)\n", rsrc);
289*4eaa4710SRishi Srivatsavai 
290*4eaa4710SRishi Srivatsavai 	/* Lock the cache and lookup the resource */
291*4eaa4710SRishi Srivatsavai 	(void) mutex_lock(&cache_lock);
292*4eaa4710SRishi Srivatsavai 	node = cache_lookup(hd, rsrc, CACHE_REFRESH);
293*4eaa4710SRishi Srivatsavai 	if (node == NULL) {
294*4eaa4710SRishi Srivatsavai 		/* should not happen because the resource is registered. */
295*4eaa4710SRishi Srivatsavai 		bridge_log_err(DATALINK_INVALID_LINKID, errorp,
296*4eaa4710SRishi Srivatsavai 		    "unrecognized resource");
297*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
298*4eaa4710SRishi Srivatsavai 		return (RCM_SUCCESS);
299*4eaa4710SRishi Srivatsavai 	}
300*4eaa4710SRishi Srivatsavai 
301*4eaa4710SRishi Srivatsavai 	/* Check if it's a query */
302*4eaa4710SRishi Srivatsavai 	if (flags & RCM_QUERY) {
303*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_TRACE1,
304*4eaa4710SRishi Srivatsavai 		    "Bridge: offline query succeeded(%s)\n", rsrc);
305*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
306*4eaa4710SRishi Srivatsavai 		return (RCM_SUCCESS);
307*4eaa4710SRishi Srivatsavai 	}
308*4eaa4710SRishi Srivatsavai 
309*4eaa4710SRishi Srivatsavai 	status = dladm_bridge_setlink(dld_handle, node->vc_linkid, "");
310*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK) {
311*4eaa4710SRishi Srivatsavai 		bridge_log_err(node->vc_linkid, errorp, "offline failed");
312*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
313*4eaa4710SRishi Srivatsavai 		return (RCM_FAILURE);
314*4eaa4710SRishi Srivatsavai 	}
315*4eaa4710SRishi Srivatsavai 
316*4eaa4710SRishi Srivatsavai 	node->vc_state |= CACHE_NODE_OFFLINED;
317*4eaa4710SRishi Srivatsavai 
318*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: Offline succeeded(%s %s)\n", rsrc,
319*4eaa4710SRishi Srivatsavai 	    node->vc_bridge);
320*4eaa4710SRishi Srivatsavai 	(void) mutex_unlock(&cache_lock);
321*4eaa4710SRishi Srivatsavai 	return (RCM_SUCCESS);
322*4eaa4710SRishi Srivatsavai }
323*4eaa4710SRishi Srivatsavai 
324*4eaa4710SRishi Srivatsavai /*
325*4eaa4710SRishi Srivatsavai  * bridge_undo_offline() - Undo offline of a previously offlined node.
326*4eaa4710SRishi Srivatsavai  */
327*4eaa4710SRishi Srivatsavai /*ARGSUSED*/
328*4eaa4710SRishi Srivatsavai static int
bridge_undo_offline(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)329*4eaa4710SRishi Srivatsavai bridge_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
330*4eaa4710SRishi Srivatsavai     char **errorp, rcm_info_t **info)
331*4eaa4710SRishi Srivatsavai {
332*4eaa4710SRishi Srivatsavai 	link_cache_t *node;
333*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
334*4eaa4710SRishi Srivatsavai 	char errmsg[DLADM_STRSIZE];
335*4eaa4710SRishi Srivatsavai 
336*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: online(%s)\n", rsrc);
337*4eaa4710SRishi Srivatsavai 
338*4eaa4710SRishi Srivatsavai 	(void) mutex_lock(&cache_lock);
339*4eaa4710SRishi Srivatsavai 	node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
340*4eaa4710SRishi Srivatsavai 	if (node == NULL) {
341*4eaa4710SRishi Srivatsavai 		bridge_log_err(DATALINK_INVALID_LINKID, errorp, "no such link");
342*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
343*4eaa4710SRishi Srivatsavai 		errno = ENOENT;
344*4eaa4710SRishi Srivatsavai 		return (RCM_FAILURE);
345*4eaa4710SRishi Srivatsavai 	}
346*4eaa4710SRishi Srivatsavai 
347*4eaa4710SRishi Srivatsavai 	/* Check if no attempt should be made to online the link here */
348*4eaa4710SRishi Srivatsavai 	if (!(node->vc_state & CACHE_NODE_OFFLINED)) {
349*4eaa4710SRishi Srivatsavai 		bridge_log_err(node->vc_linkid, errorp, "link not offlined");
350*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
351*4eaa4710SRishi Srivatsavai 		errno = ENOTSUP;
352*4eaa4710SRishi Srivatsavai 		return (RCM_SUCCESS);
353*4eaa4710SRishi Srivatsavai 	}
354*4eaa4710SRishi Srivatsavai 
355*4eaa4710SRishi Srivatsavai 	/*
356*4eaa4710SRishi Srivatsavai 	 * Try to bring on an offlined bridge link.
357*4eaa4710SRishi Srivatsavai 	 */
358*4eaa4710SRishi Srivatsavai 	status = dladm_bridge_setlink(dld_handle, node->vc_linkid,
359*4eaa4710SRishi Srivatsavai 	    node->vc_bridge);
360*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK) {
361*4eaa4710SRishi Srivatsavai 		/*
362*4eaa4710SRishi Srivatsavai 		 * Print a warning message.
363*4eaa4710SRishi Srivatsavai 		 */
364*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_WARNING,
365*4eaa4710SRishi Srivatsavai 		    _("Bridge: Bridge online failed %u %s: %s\n"),
366*4eaa4710SRishi Srivatsavai 		    node->vc_linkid, node->vc_bridge,
367*4eaa4710SRishi Srivatsavai 		    dladm_status2str(status, errmsg));
368*4eaa4710SRishi Srivatsavai 	}
369*4eaa4710SRishi Srivatsavai 
370*4eaa4710SRishi Srivatsavai 	node->vc_state &= ~CACHE_NODE_OFFLINED;
371*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: online succeeded(%s)\n", rsrc);
372*4eaa4710SRishi Srivatsavai 	(void) mutex_unlock(&cache_lock);
373*4eaa4710SRishi Srivatsavai 	return (RCM_SUCCESS);
374*4eaa4710SRishi Srivatsavai }
375*4eaa4710SRishi Srivatsavai 
376*4eaa4710SRishi Srivatsavai /*
377*4eaa4710SRishi Srivatsavai  * bridge_get_info() - Gather usage information for this resource.
378*4eaa4710SRishi Srivatsavai  */
379*4eaa4710SRishi Srivatsavai /*ARGSUSED*/
380*4eaa4710SRishi Srivatsavai int
bridge_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)381*4eaa4710SRishi Srivatsavai bridge_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
382*4eaa4710SRishi Srivatsavai     char **usagep, char **errorp, nvlist_t *props, rcm_info_t **info)
383*4eaa4710SRishi Srivatsavai {
384*4eaa4710SRishi Srivatsavai 	link_cache_t *node;
385*4eaa4710SRishi Srivatsavai 
386*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: get_info(%s)\n", rsrc);
387*4eaa4710SRishi Srivatsavai 
388*4eaa4710SRishi Srivatsavai 	(void) mutex_lock(&cache_lock);
389*4eaa4710SRishi Srivatsavai 	node = cache_lookup(hd, rsrc, CACHE_REFRESH);
390*4eaa4710SRishi Srivatsavai 	if (node == NULL) {
391*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_INFO,
392*4eaa4710SRishi Srivatsavai 		    _("Bridge: get_info(%s) unrecognized resource\n"), rsrc);
393*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
394*4eaa4710SRishi Srivatsavai 		errno = ENOENT;
395*4eaa4710SRishi Srivatsavai 		return (RCM_FAILURE);
396*4eaa4710SRishi Srivatsavai 	}
397*4eaa4710SRishi Srivatsavai 
398*4eaa4710SRishi Srivatsavai 	*usagep = bridge_usage(node);
399*4eaa4710SRishi Srivatsavai 	(void) mutex_unlock(&cache_lock);
400*4eaa4710SRishi Srivatsavai 	if (*usagep == NULL) {
401*4eaa4710SRishi Srivatsavai 		/* most likely malloc failure */
402*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_ERROR,
403*4eaa4710SRishi Srivatsavai 		    _("Bridge: get_info(%s) malloc failure\n"), rsrc);
404*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
405*4eaa4710SRishi Srivatsavai 		errno = ENOMEM;
406*4eaa4710SRishi Srivatsavai 		return (RCM_FAILURE);
407*4eaa4710SRishi Srivatsavai 	}
408*4eaa4710SRishi Srivatsavai 
409*4eaa4710SRishi Srivatsavai 	/* Set client/role properties */
410*4eaa4710SRishi Srivatsavai 	(void) nvlist_add_string(props, RCM_CLIENT_NAME, "Bridge");
411*4eaa4710SRishi Srivatsavai 
412*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: get_info(%s) info = %s\n",
413*4eaa4710SRishi Srivatsavai 	    rsrc, *usagep);
414*4eaa4710SRishi Srivatsavai 	return (RCM_SUCCESS);
415*4eaa4710SRishi Srivatsavai }
416*4eaa4710SRishi Srivatsavai 
417*4eaa4710SRishi Srivatsavai /*
418*4eaa4710SRishi Srivatsavai  * bridge_suspend() - Nothing to do, always okay
419*4eaa4710SRishi Srivatsavai  */
420*4eaa4710SRishi Srivatsavai /*ARGSUSED*/
421*4eaa4710SRishi Srivatsavai static int
bridge_suspend(rcm_handle_t * hd,char * rsrc,id_t id,timespec_t * interval,uint_t flags,char ** errorp,rcm_info_t ** info)422*4eaa4710SRishi Srivatsavai bridge_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval,
423*4eaa4710SRishi Srivatsavai     uint_t flags, char **errorp, rcm_info_t **info)
424*4eaa4710SRishi Srivatsavai {
425*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: suspend(%s)\n", rsrc);
426*4eaa4710SRishi Srivatsavai 	return (RCM_SUCCESS);
427*4eaa4710SRishi Srivatsavai }
428*4eaa4710SRishi Srivatsavai 
429*4eaa4710SRishi Srivatsavai /*
430*4eaa4710SRishi Srivatsavai  * bridge_resume() - Nothing to do, always okay
431*4eaa4710SRishi Srivatsavai  */
432*4eaa4710SRishi Srivatsavai /*ARGSUSED*/
433*4eaa4710SRishi Srivatsavai static int
bridge_resume(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)434*4eaa4710SRishi Srivatsavai bridge_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
435*4eaa4710SRishi Srivatsavai     char **errorp, rcm_info_t **info)
436*4eaa4710SRishi Srivatsavai {
437*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: resume(%s)\n", rsrc);
438*4eaa4710SRishi Srivatsavai 	return (RCM_SUCCESS);
439*4eaa4710SRishi Srivatsavai }
440*4eaa4710SRishi Srivatsavai 
441*4eaa4710SRishi Srivatsavai /*
442*4eaa4710SRishi Srivatsavai  * bridge_remove() - remove a resource from cache
443*4eaa4710SRishi Srivatsavai  */
444*4eaa4710SRishi Srivatsavai /*ARGSUSED*/
445*4eaa4710SRishi Srivatsavai static int
bridge_remove(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)446*4eaa4710SRishi Srivatsavai bridge_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
447*4eaa4710SRishi Srivatsavai     char **errorp, rcm_info_t **info)
448*4eaa4710SRishi Srivatsavai {
449*4eaa4710SRishi Srivatsavai 	link_cache_t *node;
450*4eaa4710SRishi Srivatsavai 
451*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: remove(%s)\n", rsrc);
452*4eaa4710SRishi Srivatsavai 
453*4eaa4710SRishi Srivatsavai 	(void) mutex_lock(&cache_lock);
454*4eaa4710SRishi Srivatsavai 	node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
455*4eaa4710SRishi Srivatsavai 	if (node == NULL) {
456*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_INFO,
457*4eaa4710SRishi Srivatsavai 		    _("Bridge: remove(%s) unrecognized resource\n"), rsrc);
458*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
459*4eaa4710SRishi Srivatsavai 		errno = ENOENT;
460*4eaa4710SRishi Srivatsavai 		return (RCM_FAILURE);
461*4eaa4710SRishi Srivatsavai 	}
462*4eaa4710SRishi Srivatsavai 
463*4eaa4710SRishi Srivatsavai 	/* remove the cached entry for the resource */
464*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE2,
465*4eaa4710SRishi Srivatsavai 	    "Bridge: remove succeeded(%s, %s)\n", rsrc, node->vc_bridge);
466*4eaa4710SRishi Srivatsavai 	cache_remove(node);
467*4eaa4710SRishi Srivatsavai 	(void) mutex_unlock(&cache_lock);
468*4eaa4710SRishi Srivatsavai 
469*4eaa4710SRishi Srivatsavai 	node_free(node);
470*4eaa4710SRishi Srivatsavai 	return (RCM_SUCCESS);
471*4eaa4710SRishi Srivatsavai }
472*4eaa4710SRishi Srivatsavai 
473*4eaa4710SRishi Srivatsavai /*
474*4eaa4710SRishi Srivatsavai  * bridge_notify_event - Project private implementation to receive new resource
475*4eaa4710SRishi Srivatsavai  *		   events. It intercepts all new resource events. If the
476*4eaa4710SRishi Srivatsavai  *		   new resource is a network resource, pass up a notify
477*4eaa4710SRishi Srivatsavai  *		   for it too. The new resource need not be cached, since
478*4eaa4710SRishi Srivatsavai  *		   it is done at register again.
479*4eaa4710SRishi Srivatsavai  */
480*4eaa4710SRishi Srivatsavai /*ARGSUSED*/
481*4eaa4710SRishi Srivatsavai static int
bridge_notify_event(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,nvlist_t * nvl,rcm_info_t ** info)482*4eaa4710SRishi Srivatsavai bridge_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
483*4eaa4710SRishi Srivatsavai     char **errorp, nvlist_t *nvl, rcm_info_t **info)
484*4eaa4710SRishi Srivatsavai {
485*4eaa4710SRishi Srivatsavai 	nvpair_t	*nvp = NULL;
486*4eaa4710SRishi Srivatsavai 	datalink_id_t	linkid;
487*4eaa4710SRishi Srivatsavai 	uint64_t	id64;
488*4eaa4710SRishi Srivatsavai 	int		rv, lastrv;
489*4eaa4710SRishi Srivatsavai 
490*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1, "Bridge: notify_event(%s)\n", rsrc);
491*4eaa4710SRishi Srivatsavai 
492*4eaa4710SRishi Srivatsavai 	if (strcmp(rsrc, RCM_RESOURCE_LINK_NEW) != 0) {
493*4eaa4710SRishi Srivatsavai 		bridge_log_err(DATALINK_INVALID_LINKID, errorp,
494*4eaa4710SRishi Srivatsavai 		    "unrecognized event");
495*4eaa4710SRishi Srivatsavai 		errno = EINVAL;
496*4eaa4710SRishi Srivatsavai 		return (RCM_FAILURE);
497*4eaa4710SRishi Srivatsavai 	}
498*4eaa4710SRishi Srivatsavai 
499*4eaa4710SRishi Srivatsavai 	/* Update cache to reflect latest Bridges */
500*4eaa4710SRishi Srivatsavai 	if ((lastrv = cache_update(hd)) != RCM_SUCCESS) {
501*4eaa4710SRishi Srivatsavai 		bridge_log_err(DATALINK_INVALID_LINKID, errorp,
502*4eaa4710SRishi Srivatsavai 		    "private Cache update failed");
503*4eaa4710SRishi Srivatsavai 		return (lastrv);
504*4eaa4710SRishi Srivatsavai 	}
505*4eaa4710SRishi Srivatsavai 
506*4eaa4710SRishi Srivatsavai 	/*
507*4eaa4710SRishi Srivatsavai 	 * Try best to recover all configuration.
508*4eaa4710SRishi Srivatsavai 	 */
509*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_DEBUG, "Bridge: process_nvlist\n");
510*4eaa4710SRishi Srivatsavai 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
511*4eaa4710SRishi Srivatsavai 		if (strcmp(nvpair_name(nvp), RCM_NV_LINKID) != 0)
512*4eaa4710SRishi Srivatsavai 			continue;
513*4eaa4710SRishi Srivatsavai 
514*4eaa4710SRishi Srivatsavai 		if (nvpair_value_uint64(nvp, &id64) != 0) {
515*4eaa4710SRishi Srivatsavai 			bridge_log_err(DATALINK_INVALID_LINKID, errorp,
516*4eaa4710SRishi Srivatsavai 			    "cannot get linkid");
517*4eaa4710SRishi Srivatsavai 			lastrv = RCM_FAILURE;
518*4eaa4710SRishi Srivatsavai 			continue;
519*4eaa4710SRishi Srivatsavai 		}
520*4eaa4710SRishi Srivatsavai 
521*4eaa4710SRishi Srivatsavai 		linkid = (datalink_id_t)id64;
522*4eaa4710SRishi Srivatsavai 		if ((rv = bridge_configure(hd, linkid)) != RCM_SUCCESS) {
523*4eaa4710SRishi Srivatsavai 			bridge_log_err(linkid, errorp, "configuring failed");
524*4eaa4710SRishi Srivatsavai 			lastrv = rv;
525*4eaa4710SRishi Srivatsavai 		}
526*4eaa4710SRishi Srivatsavai 	}
527*4eaa4710SRishi Srivatsavai 
528*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE1,
529*4eaa4710SRishi Srivatsavai 	    "Bridge: notify_event: link configuration complete\n");
530*4eaa4710SRishi Srivatsavai 	return (lastrv);
531*4eaa4710SRishi Srivatsavai }
532*4eaa4710SRishi Srivatsavai 
533*4eaa4710SRishi Srivatsavai /*
534*4eaa4710SRishi Srivatsavai  * bridge_usage - Determine the usage of a link.
535*4eaa4710SRishi Srivatsavai  *	    The returned buffer is owned by caller, and the caller
536*4eaa4710SRishi Srivatsavai  *	    must free it up when done.
537*4eaa4710SRishi Srivatsavai  */
538*4eaa4710SRishi Srivatsavai static char *
bridge_usage(link_cache_t * node)539*4eaa4710SRishi Srivatsavai bridge_usage(link_cache_t *node)
540*4eaa4710SRishi Srivatsavai {
541*4eaa4710SRishi Srivatsavai 	char *buf;
542*4eaa4710SRishi Srivatsavai 	const char *fmt;
543*4eaa4710SRishi Srivatsavai 	char errmsg[DLADM_STRSIZE];
544*4eaa4710SRishi Srivatsavai 	char name[MAXLINKNAMELEN];
545*4eaa4710SRishi Srivatsavai 	char bridge[MAXLINKNAMELEN];
546*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
547*4eaa4710SRishi Srivatsavai 
548*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE2, "Bridge: usage(%s)\n", node->vc_resource);
549*4eaa4710SRishi Srivatsavai 
550*4eaa4710SRishi Srivatsavai 	assert(MUTEX_HELD(&cache_lock));
551*4eaa4710SRishi Srivatsavai 
552*4eaa4710SRishi Srivatsavai 	status = dladm_datalink_id2info(dld_handle, node->vc_linkid, NULL,
553*4eaa4710SRishi Srivatsavai 	    NULL, NULL, name, sizeof (name));
554*4eaa4710SRishi Srivatsavai 
555*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK) {
556*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_ERROR,
557*4eaa4710SRishi Srivatsavai 		    _("Bridge: usage(%s) get link name failure(%s)\n"),
558*4eaa4710SRishi Srivatsavai 		    node->vc_resource, dladm_status2str(status, errmsg));
559*4eaa4710SRishi Srivatsavai 		return (NULL);
560*4eaa4710SRishi Srivatsavai 	}
561*4eaa4710SRishi Srivatsavai 
562*4eaa4710SRishi Srivatsavai 	(void) dladm_bridge_getlink(dld_handle, node->vc_linkid, bridge,
563*4eaa4710SRishi Srivatsavai 	    sizeof (bridge));
564*4eaa4710SRishi Srivatsavai 
565*4eaa4710SRishi Srivatsavai 	if (node->vc_state & CACHE_NODE_OFFLINED)
566*4eaa4710SRishi Srivatsavai 		fmt = _("%1$s offlined");
567*4eaa4710SRishi Srivatsavai 	else if (bridge[0] == '\0')
568*4eaa4710SRishi Srivatsavai 		fmt = _("%1$s not bridged");
569*4eaa4710SRishi Srivatsavai 	else
570*4eaa4710SRishi Srivatsavai 		fmt = _("%1$s bridge: %2$s");
571*4eaa4710SRishi Srivatsavai 
572*4eaa4710SRishi Srivatsavai 	(void) asprintf(&buf, fmt, name, bridge);
573*4eaa4710SRishi Srivatsavai 
574*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE2, "Bridge: usage (%s) info = %s\n",
575*4eaa4710SRishi Srivatsavai 	    node->vc_resource, buf);
576*4eaa4710SRishi Srivatsavai 
577*4eaa4710SRishi Srivatsavai 	return (buf);
578*4eaa4710SRishi Srivatsavai }
579*4eaa4710SRishi Srivatsavai 
580*4eaa4710SRishi Srivatsavai /*
581*4eaa4710SRishi Srivatsavai  * Cache management routines, all cache management functions should be
582*4eaa4710SRishi Srivatsavai  * be called with cache_lock held.
583*4eaa4710SRishi Srivatsavai  */
584*4eaa4710SRishi Srivatsavai 
585*4eaa4710SRishi Srivatsavai /*
586*4eaa4710SRishi Srivatsavai  * cache_lookup() - Get a cache node for a resource.
587*4eaa4710SRishi Srivatsavai  *		  Call with cache lock held.
588*4eaa4710SRishi Srivatsavai  *
589*4eaa4710SRishi Srivatsavai  * This ensures that the cache is consistent with the system state and
590*4eaa4710SRishi Srivatsavai  * returns a pointer to the cache element corresponding to the resource.
591*4eaa4710SRishi Srivatsavai  */
592*4eaa4710SRishi Srivatsavai static link_cache_t *
cache_lookup(rcm_handle_t * hd,char * rsrc,uint_t options)593*4eaa4710SRishi Srivatsavai cache_lookup(rcm_handle_t *hd, char *rsrc, uint_t options)
594*4eaa4710SRishi Srivatsavai {
595*4eaa4710SRishi Srivatsavai 	link_cache_t *node;
596*4eaa4710SRishi Srivatsavai 
597*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE2, "Bridge: cache lookup(%s)\n", rsrc);
598*4eaa4710SRishi Srivatsavai 
599*4eaa4710SRishi Srivatsavai 	assert(MUTEX_HELD(&cache_lock));
600*4eaa4710SRishi Srivatsavai 	if (options & CACHE_REFRESH) {
601*4eaa4710SRishi Srivatsavai 		/* drop lock since update locks cache again */
602*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
603*4eaa4710SRishi Srivatsavai 		(void) cache_update(hd);
604*4eaa4710SRishi Srivatsavai 		(void) mutex_lock(&cache_lock);
605*4eaa4710SRishi Srivatsavai 	}
606*4eaa4710SRishi Srivatsavai 
607*4eaa4710SRishi Srivatsavai 	node = cache_head.vc_next;
608*4eaa4710SRishi Srivatsavai 	for (; node != &cache_tail; node = node->vc_next) {
609*4eaa4710SRishi Srivatsavai 		if (strcmp(rsrc, node->vc_resource) == 0) {
610*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_TRACE2,
611*4eaa4710SRishi Srivatsavai 			    "Bridge: cache lookup succeeded(%s, %s)\n", rsrc,
612*4eaa4710SRishi Srivatsavai 			    node->vc_bridge);
613*4eaa4710SRishi Srivatsavai 			return (node);
614*4eaa4710SRishi Srivatsavai 		}
615*4eaa4710SRishi Srivatsavai 	}
616*4eaa4710SRishi Srivatsavai 	return (NULL);
617*4eaa4710SRishi Srivatsavai }
618*4eaa4710SRishi Srivatsavai 
619*4eaa4710SRishi Srivatsavai /*
620*4eaa4710SRishi Srivatsavai  * node_free - Free a node from the cache
621*4eaa4710SRishi Srivatsavai  */
622*4eaa4710SRishi Srivatsavai static void
node_free(link_cache_t * node)623*4eaa4710SRishi Srivatsavai node_free(link_cache_t *node)
624*4eaa4710SRishi Srivatsavai {
625*4eaa4710SRishi Srivatsavai 	if (node != NULL) {
626*4eaa4710SRishi Srivatsavai 		free(node->vc_resource);
627*4eaa4710SRishi Srivatsavai 		free(node);
628*4eaa4710SRishi Srivatsavai 	}
629*4eaa4710SRishi Srivatsavai }
630*4eaa4710SRishi Srivatsavai 
631*4eaa4710SRishi Srivatsavai /*
632*4eaa4710SRishi Srivatsavai  * cache_insert - Insert a resource node in cache
633*4eaa4710SRishi Srivatsavai  */
634*4eaa4710SRishi Srivatsavai static void
cache_insert(link_cache_t * node)635*4eaa4710SRishi Srivatsavai cache_insert(link_cache_t *node)
636*4eaa4710SRishi Srivatsavai {
637*4eaa4710SRishi Srivatsavai 	assert(MUTEX_HELD(&cache_lock));
638*4eaa4710SRishi Srivatsavai 
639*4eaa4710SRishi Srivatsavai 	/* insert at the head for best performance */
640*4eaa4710SRishi Srivatsavai 	node->vc_next = cache_head.vc_next;
641*4eaa4710SRishi Srivatsavai 	node->vc_prev = &cache_head;
642*4eaa4710SRishi Srivatsavai 
643*4eaa4710SRishi Srivatsavai 	node->vc_next->vc_prev = node;
644*4eaa4710SRishi Srivatsavai 	node->vc_prev->vc_next = node;
645*4eaa4710SRishi Srivatsavai }
646*4eaa4710SRishi Srivatsavai 
647*4eaa4710SRishi Srivatsavai /*
648*4eaa4710SRishi Srivatsavai  * cache_remove() - Remove a resource node from cache.
649*4eaa4710SRishi Srivatsavai  */
650*4eaa4710SRishi Srivatsavai static void
cache_remove(link_cache_t * node)651*4eaa4710SRishi Srivatsavai cache_remove(link_cache_t *node)
652*4eaa4710SRishi Srivatsavai {
653*4eaa4710SRishi Srivatsavai 	assert(MUTEX_HELD(&cache_lock));
654*4eaa4710SRishi Srivatsavai 	node->vc_next->vc_prev = node->vc_prev;
655*4eaa4710SRishi Srivatsavai 	node->vc_prev->vc_next = node->vc_next;
656*4eaa4710SRishi Srivatsavai 	node->vc_next = NULL;
657*4eaa4710SRishi Srivatsavai 	node->vc_prev = NULL;
658*4eaa4710SRishi Srivatsavai }
659*4eaa4710SRishi Srivatsavai 
660*4eaa4710SRishi Srivatsavai typedef struct bridge_update_arg_s {
661*4eaa4710SRishi Srivatsavai 	rcm_handle_t	*hd;
662*4eaa4710SRishi Srivatsavai 	int		retval;
663*4eaa4710SRishi Srivatsavai } bridge_update_arg_t;
664*4eaa4710SRishi Srivatsavai 
665*4eaa4710SRishi Srivatsavai /*
666*4eaa4710SRishi Srivatsavai  * bridge_update() - Update physical interface properties
667*4eaa4710SRishi Srivatsavai  */
668*4eaa4710SRishi Srivatsavai static int
bridge_update(dladm_handle_t handle,datalink_id_t linkid,void * arg)669*4eaa4710SRishi Srivatsavai bridge_update(dladm_handle_t handle, datalink_id_t linkid, void *arg)
670*4eaa4710SRishi Srivatsavai {
671*4eaa4710SRishi Srivatsavai 	bridge_update_arg_t *bua = arg;
672*4eaa4710SRishi Srivatsavai 	rcm_handle_t *hd = bua->hd;
673*4eaa4710SRishi Srivatsavai 	link_cache_t *node;
674*4eaa4710SRishi Srivatsavai 	char *rsrc;
675*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
676*4eaa4710SRishi Srivatsavai 	char errmsg[DLADM_STRSIZE];
677*4eaa4710SRishi Srivatsavai 	char bridge[MAXLINKNAMELEN];
678*4eaa4710SRishi Srivatsavai 	int ret = RCM_FAILURE;
679*4eaa4710SRishi Srivatsavai 
680*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE2, "Bridge: bridge_update(%u)\n", linkid);
681*4eaa4710SRishi Srivatsavai 
682*4eaa4710SRishi Srivatsavai 	assert(MUTEX_HELD(&cache_lock));
683*4eaa4710SRishi Srivatsavai 	status = dladm_bridge_getlink(dld_handle, linkid, bridge,
684*4eaa4710SRishi Srivatsavai 	    sizeof (bridge));
685*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK) {
686*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_TRACE1,
687*4eaa4710SRishi Srivatsavai 		    "Bridge: no bridge information for %u (%s)\n",
688*4eaa4710SRishi Srivatsavai 		    linkid, dladm_status2str(status, errmsg));
689*4eaa4710SRishi Srivatsavai 		return (DLADM_WALK_CONTINUE);
690*4eaa4710SRishi Srivatsavai 	}
691*4eaa4710SRishi Srivatsavai 
692*4eaa4710SRishi Srivatsavai 	(void) asprintf(&rsrc, "%s/%u", RCM_LINK_PREFIX, linkid);
693*4eaa4710SRishi Srivatsavai 	if (rsrc == NULL) {
694*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_ERROR,
695*4eaa4710SRishi Srivatsavai 		    _("Bridge: allocation failure: %s %u: %s\n"),
696*4eaa4710SRishi Srivatsavai 		    bridge, linkid, strerror(errno));
697*4eaa4710SRishi Srivatsavai 		goto done;
698*4eaa4710SRishi Srivatsavai 	}
699*4eaa4710SRishi Srivatsavai 
700*4eaa4710SRishi Srivatsavai 	node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
701*4eaa4710SRishi Srivatsavai 	if (node != NULL) {
702*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_DEBUG, "Bridge: %s already registered\n",
703*4eaa4710SRishi Srivatsavai 		    rsrc);
704*4eaa4710SRishi Srivatsavai 		free(rsrc);
705*4eaa4710SRishi Srivatsavai 		node->vc_state &= ~CACHE_NODE_STALE;
706*4eaa4710SRishi Srivatsavai 	} else {
707*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_DEBUG,
708*4eaa4710SRishi Srivatsavai 		    "Bridge: %s is a new resource (bridge %s)\n",
709*4eaa4710SRishi Srivatsavai 		    rsrc, bridge);
710*4eaa4710SRishi Srivatsavai 		if ((node = calloc(1, sizeof (link_cache_t))) == NULL) {
711*4eaa4710SRishi Srivatsavai 			free(rsrc);
712*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_ERROR, _("Bridge: calloc: %s\n"),
713*4eaa4710SRishi Srivatsavai 			    strerror(errno));
714*4eaa4710SRishi Srivatsavai 			goto done;
715*4eaa4710SRishi Srivatsavai 		}
716*4eaa4710SRishi Srivatsavai 
717*4eaa4710SRishi Srivatsavai 		node->vc_resource = rsrc;
718*4eaa4710SRishi Srivatsavai 		node->vc_linkid = linkid;
719*4eaa4710SRishi Srivatsavai 		(void) strlcpy(node->vc_bridge, bridge,
720*4eaa4710SRishi Srivatsavai 		    sizeof (node->vc_bridge));
721*4eaa4710SRishi Srivatsavai 		node->vc_state |= CACHE_NODE_NEW;
722*4eaa4710SRishi Srivatsavai 		cache_insert(node);
723*4eaa4710SRishi Srivatsavai 	}
724*4eaa4710SRishi Srivatsavai 
725*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE3, "Bridge: bridge_update: succeeded(%u %s)\n",
726*4eaa4710SRishi Srivatsavai 	    linkid, node->vc_bridge);
727*4eaa4710SRishi Srivatsavai 	ret = RCM_SUCCESS;
728*4eaa4710SRishi Srivatsavai done:
729*4eaa4710SRishi Srivatsavai 	bua->retval = ret;
730*4eaa4710SRishi Srivatsavai 	return (ret == RCM_SUCCESS ? DLADM_WALK_CONTINUE :
731*4eaa4710SRishi Srivatsavai 	    DLADM_WALK_TERMINATE);
732*4eaa4710SRishi Srivatsavai }
733*4eaa4710SRishi Srivatsavai 
734*4eaa4710SRishi Srivatsavai /*
735*4eaa4710SRishi Srivatsavai  * cache_update() - Update cache with latest interface info
736*4eaa4710SRishi Srivatsavai  */
737*4eaa4710SRishi Srivatsavai static int
cache_update(rcm_handle_t * hd)738*4eaa4710SRishi Srivatsavai cache_update(rcm_handle_t *hd)
739*4eaa4710SRishi Srivatsavai {
740*4eaa4710SRishi Srivatsavai 	link_cache_t *node, *nnode;
741*4eaa4710SRishi Srivatsavai 	int rv, lastrv;
742*4eaa4710SRishi Srivatsavai 	bridge_update_arg_t bua;
743*4eaa4710SRishi Srivatsavai 
744*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE2, "Bridge: cache_update\n");
745*4eaa4710SRishi Srivatsavai 
746*4eaa4710SRishi Srivatsavai 	(void) mutex_lock(&cache_lock);
747*4eaa4710SRishi Srivatsavai 
748*4eaa4710SRishi Srivatsavai 	/* first we walk the entire cache, marking each entry stale */
749*4eaa4710SRishi Srivatsavai 	node = cache_head.vc_next;
750*4eaa4710SRishi Srivatsavai 	for (; node != &cache_tail; node = node->vc_next)
751*4eaa4710SRishi Srivatsavai 		node->vc_state |= CACHE_NODE_STALE;
752*4eaa4710SRishi Srivatsavai 
753*4eaa4710SRishi Srivatsavai 	/* now walk the links and update all of the entries */
754*4eaa4710SRishi Srivatsavai 	bua.hd = hd;
755*4eaa4710SRishi Srivatsavai 	bua.retval = RCM_SUCCESS;
756*4eaa4710SRishi Srivatsavai 	(void) dladm_walk_datalink_id(bridge_update, dld_handle, &bua,
757*4eaa4710SRishi Srivatsavai 	    DATALINK_CLASS_AGGR | DATALINK_CLASS_PHYS |
758*4eaa4710SRishi Srivatsavai 	    DATALINK_CLASS_ETHERSTUB, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
759*4eaa4710SRishi Srivatsavai 	lastrv = bua.retval;
760*4eaa4710SRishi Srivatsavai 
761*4eaa4710SRishi Srivatsavai 	/*
762*4eaa4710SRishi Srivatsavai 	 * Continue to delete all stale nodes from the cache even if the walk
763*4eaa4710SRishi Srivatsavai 	 * above failed.  Unregister links that are not offlined and still in
764*4eaa4710SRishi Srivatsavai 	 * the cache.
765*4eaa4710SRishi Srivatsavai 	 */
766*4eaa4710SRishi Srivatsavai 	for (node = cache_head.vc_next; node != &cache_tail; node = nnode) {
767*4eaa4710SRishi Srivatsavai 		nnode = node->vc_next;
768*4eaa4710SRishi Srivatsavai 
769*4eaa4710SRishi Srivatsavai 		if (node->vc_state & CACHE_NODE_STALE) {
770*4eaa4710SRishi Srivatsavai 			(void) rcm_unregister_interest(hd, node->vc_resource,
771*4eaa4710SRishi Srivatsavai 			    0);
772*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_DEBUG,
773*4eaa4710SRishi Srivatsavai 			    "Bridge: unregistered %s %s\n",
774*4eaa4710SRishi Srivatsavai 			    node->vc_resource, node->vc_bridge);
775*4eaa4710SRishi Srivatsavai 			cache_remove(node);
776*4eaa4710SRishi Srivatsavai 			node_free(node);
777*4eaa4710SRishi Srivatsavai 			continue;
778*4eaa4710SRishi Srivatsavai 		}
779*4eaa4710SRishi Srivatsavai 
780*4eaa4710SRishi Srivatsavai 		if (!(node->vc_state & CACHE_NODE_NEW))
781*4eaa4710SRishi Srivatsavai 			continue;
782*4eaa4710SRishi Srivatsavai 
783*4eaa4710SRishi Srivatsavai 		rv = rcm_register_interest(hd, node->vc_resource, 0, NULL);
784*4eaa4710SRishi Srivatsavai 		if (rv != RCM_SUCCESS) {
785*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_ERROR,
786*4eaa4710SRishi Srivatsavai 			    _("Bridge: failed to register %s\n"),
787*4eaa4710SRishi Srivatsavai 			    node->vc_resource);
788*4eaa4710SRishi Srivatsavai 			lastrv = rv;
789*4eaa4710SRishi Srivatsavai 		} else {
790*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_DEBUG, "Bridge: registered %s\n",
791*4eaa4710SRishi Srivatsavai 			    node->vc_resource);
792*4eaa4710SRishi Srivatsavai 			node->vc_state &= ~CACHE_NODE_NEW;
793*4eaa4710SRishi Srivatsavai 		}
794*4eaa4710SRishi Srivatsavai 	}
795*4eaa4710SRishi Srivatsavai 
796*4eaa4710SRishi Srivatsavai 	(void) mutex_unlock(&cache_lock);
797*4eaa4710SRishi Srivatsavai 	return (lastrv);
798*4eaa4710SRishi Srivatsavai }
799*4eaa4710SRishi Srivatsavai 
800*4eaa4710SRishi Srivatsavai /*
801*4eaa4710SRishi Srivatsavai  * cache_free() - Empty the cache
802*4eaa4710SRishi Srivatsavai  */
803*4eaa4710SRishi Srivatsavai static void
cache_free(void)804*4eaa4710SRishi Srivatsavai cache_free(void)
805*4eaa4710SRishi Srivatsavai {
806*4eaa4710SRishi Srivatsavai 	link_cache_t *node;
807*4eaa4710SRishi Srivatsavai 
808*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE2, "Bridge: cache_free\n");
809*4eaa4710SRishi Srivatsavai 
810*4eaa4710SRishi Srivatsavai 	(void) mutex_lock(&cache_lock);
811*4eaa4710SRishi Srivatsavai 	node = cache_head.vc_next;
812*4eaa4710SRishi Srivatsavai 	while (node != &cache_tail) {
813*4eaa4710SRishi Srivatsavai 		cache_remove(node);
814*4eaa4710SRishi Srivatsavai 		node_free(node);
815*4eaa4710SRishi Srivatsavai 		node = cache_head.vc_next;
816*4eaa4710SRishi Srivatsavai 	}
817*4eaa4710SRishi Srivatsavai 	(void) mutex_unlock(&cache_lock);
818*4eaa4710SRishi Srivatsavai }
819*4eaa4710SRishi Srivatsavai 
820*4eaa4710SRishi Srivatsavai /*
821*4eaa4710SRishi Srivatsavai  * bridge_log_err() - RCM error log wrapper
822*4eaa4710SRishi Srivatsavai  */
823*4eaa4710SRishi Srivatsavai static void
bridge_log_err(datalink_id_t linkid,char ** errorp,char * errmsg)824*4eaa4710SRishi Srivatsavai bridge_log_err(datalink_id_t linkid, char **errorp, char *errmsg)
825*4eaa4710SRishi Srivatsavai {
826*4eaa4710SRishi Srivatsavai 	char link[MAXLINKNAMELEN];
827*4eaa4710SRishi Srivatsavai 	char errstr[DLADM_STRSIZE];
828*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
829*4eaa4710SRishi Srivatsavai 	char *error;
830*4eaa4710SRishi Srivatsavai 
831*4eaa4710SRishi Srivatsavai 	link[0] = '\0';
832*4eaa4710SRishi Srivatsavai 	if (linkid != DATALINK_INVALID_LINKID) {
833*4eaa4710SRishi Srivatsavai 		char rsrc[RCM_LINK_RESOURCE_MAX];
834*4eaa4710SRishi Srivatsavai 
835*4eaa4710SRishi Srivatsavai 		(void) snprintf(rsrc, sizeof (rsrc), "%s/%u",
836*4eaa4710SRishi Srivatsavai 		    RCM_LINK_PREFIX, linkid);
837*4eaa4710SRishi Srivatsavai 
838*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_ERROR, _("Bridge: %s(%s)\n"), errmsg, rsrc);
839*4eaa4710SRishi Srivatsavai 		if ((status = dladm_datalink_id2info(dld_handle, linkid, NULL,
840*4eaa4710SRishi Srivatsavai 		    NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
841*4eaa4710SRishi Srivatsavai 			rcm_log_message(RCM_WARNING,
842*4eaa4710SRishi Srivatsavai 			    _("Bridge: cannot get link name for (%s) %s\n"),
843*4eaa4710SRishi Srivatsavai 			    rsrc, dladm_status2str(status, errstr));
844*4eaa4710SRishi Srivatsavai 		}
845*4eaa4710SRishi Srivatsavai 	} else {
846*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_ERROR, _("Bridge: %s\n"), errmsg);
847*4eaa4710SRishi Srivatsavai 	}
848*4eaa4710SRishi Srivatsavai 
849*4eaa4710SRishi Srivatsavai 	if (link[0] != '\0')
850*4eaa4710SRishi Srivatsavai 		(void) asprintf(&error, _("Bridge: %s(%s)"), errmsg, link);
851*4eaa4710SRishi Srivatsavai 	else
852*4eaa4710SRishi Srivatsavai 		(void) asprintf(&error, _("Bridge: %s"), errmsg);
853*4eaa4710SRishi Srivatsavai 
854*4eaa4710SRishi Srivatsavai 	if (errorp != NULL)
855*4eaa4710SRishi Srivatsavai 		*errorp = error;
856*4eaa4710SRishi Srivatsavai }
857*4eaa4710SRishi Srivatsavai 
858*4eaa4710SRishi Srivatsavai /*
859*4eaa4710SRishi Srivatsavai  * bridge_configure() - Configure bridge on a physical link after it attaches
860*4eaa4710SRishi Srivatsavai  */
861*4eaa4710SRishi Srivatsavai static int
bridge_configure(rcm_handle_t * hd,datalink_id_t linkid)862*4eaa4710SRishi Srivatsavai bridge_configure(rcm_handle_t *hd, datalink_id_t linkid)
863*4eaa4710SRishi Srivatsavai {
864*4eaa4710SRishi Srivatsavai 	char rsrc[RCM_LINK_RESOURCE_MAX];
865*4eaa4710SRishi Srivatsavai 	link_cache_t *node;
866*4eaa4710SRishi Srivatsavai 	char bridge[MAXLINKNAMELEN];
867*4eaa4710SRishi Srivatsavai 
868*4eaa4710SRishi Srivatsavai 	/* Check for the bridge links in the cache */
869*4eaa4710SRishi Srivatsavai 	(void) snprintf(rsrc, sizeof (rsrc), "%s/%u", RCM_LINK_PREFIX, linkid);
870*4eaa4710SRishi Srivatsavai 
871*4eaa4710SRishi Srivatsavai 	rcm_log_message(RCM_TRACE2, "Bridge: bridge_configure(%s)\n", rsrc);
872*4eaa4710SRishi Srivatsavai 
873*4eaa4710SRishi Srivatsavai 	/* Check if the link is new or was previously offlined */
874*4eaa4710SRishi Srivatsavai 	(void) mutex_lock(&cache_lock);
875*4eaa4710SRishi Srivatsavai 	if (((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) != NULL) &&
876*4eaa4710SRishi Srivatsavai 	    (!(node->vc_state & CACHE_NODE_OFFLINED))) {
877*4eaa4710SRishi Srivatsavai 		rcm_log_message(RCM_TRACE2,
878*4eaa4710SRishi Srivatsavai 		    "Bridge: Skipping configured interface(%s)\n", rsrc);
879*4eaa4710SRishi Srivatsavai 		(void) mutex_unlock(&cache_lock);
880*4eaa4710SRishi Srivatsavai 		return (RCM_SUCCESS);
881*4eaa4710SRishi Srivatsavai 	}
882*4eaa4710SRishi Srivatsavai 	(void) mutex_unlock(&cache_lock);
883*4eaa4710SRishi Srivatsavai 
884*4eaa4710SRishi Srivatsavai 	/* clear out previous bridge, if any */
885*4eaa4710SRishi Srivatsavai 	if (dladm_bridge_getlink(dld_handle, linkid, bridge, sizeof (bridge)) ==
886*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK) {
887*4eaa4710SRishi Srivatsavai 		if (bridge[0] != '\0')
888*4eaa4710SRishi Srivatsavai 			(void) dladm_bridge_setlink(dld_handle, linkid, "");
889*4eaa4710SRishi Srivatsavai 	}
890*4eaa4710SRishi Srivatsavai 
891*4eaa4710SRishi Srivatsavai 	/* now set up the new one */
892*4eaa4710SRishi Srivatsavai 	if (node != NULL && node->vc_bridge[0] != '\0' &&
893*4eaa4710SRishi Srivatsavai 	    dladm_bridge_setlink(dld_handle, linkid, node->vc_bridge) !=
894*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK)
895*4eaa4710SRishi Srivatsavai 		return (RCM_FAILURE);
896*4eaa4710SRishi Srivatsavai 	else
897*4eaa4710SRishi Srivatsavai 		return (RCM_SUCCESS);
898*4eaa4710SRishi Srivatsavai }
899