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