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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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