dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / rcm_daemon / common / bridge_rcm.c
blob7b7717e233857e9a0547bead1a3085a9748ef6be
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * This RCM module adds support to the RCM framework for Bridge links
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <synch.h>
36 #include <assert.h>
37 #include <strings.h>
38 #include "rcm_module.h"
39 #include <libintl.h>
40 #include <libdllink.h>
41 #include <libdlbridge.h>
42 #include <libdlpi.h>
45 * Definitions
47 #define _(x) gettext(x)
49 /* Some generic well-knowns and defaults used in this module */
50 #define RCM_LINK_PREFIX "SUNW_datalink" /* RCM datalink name prefix */
51 #define RCM_LINK_RESOURCE_MAX (13 + LINKID_STR_WIDTH)
53 /* Bridge Cache state flags */
54 typedef enum {
55 CACHE_NODE_STALE = 0x1, /* stale cached data */
56 CACHE_NODE_NEW = 0x2, /* new cached nodes */
57 CACHE_NODE_OFFLINED = 0x4 /* nodes offlined */
58 } cache_node_state_t;
60 /* Network Cache lookup options */
61 #define CACHE_NO_REFRESH 0x1 /* cache refresh not needed */
62 #define CACHE_REFRESH 0x2 /* refresh cache */
64 /* Cache element */
65 typedef struct link_cache {
66 struct link_cache *vc_next; /* next cached resource */
67 struct link_cache *vc_prev; /* prev cached resource */
68 char *vc_resource; /* resource name */
69 datalink_id_t vc_linkid; /* linkid */
70 cache_node_state_t vc_state; /* cache state flags */
71 char vc_bridge[MAXLINKNAMELEN];
72 } link_cache_t;
75 * Global cache for network Bridges
77 static link_cache_t cache_head;
78 static link_cache_t cache_tail;
79 static mutex_t cache_lock;
80 static boolean_t events_registered = B_FALSE;
82 static dladm_handle_t dld_handle = NULL;
85 * RCM module interface prototypes
87 static int bridge_register(rcm_handle_t *);
88 static int bridge_unregister(rcm_handle_t *);
89 static int bridge_get_info(rcm_handle_t *, char *, id_t, uint_t,
90 char **, char **, nvlist_t *, rcm_info_t **);
91 static int bridge_suspend(rcm_handle_t *, char *, id_t,
92 timespec_t *, uint_t, char **, rcm_info_t **);
93 static int bridge_resume(rcm_handle_t *, char *, id_t, uint_t,
94 char **, rcm_info_t **);
95 static int bridge_offline(rcm_handle_t *, char *, id_t, uint_t,
96 char **, rcm_info_t **);
97 static int bridge_undo_offline(rcm_handle_t *, char *, id_t,
98 uint_t, char **, rcm_info_t **);
99 static int bridge_remove(rcm_handle_t *, char *, id_t, uint_t,
100 char **, rcm_info_t **);
101 static int bridge_notify_event(rcm_handle_t *, char *, id_t,
102 uint_t, char **, nvlist_t *, rcm_info_t **);
103 static int bridge_configure(rcm_handle_t *, datalink_id_t);
105 /* Module private routines */
106 static void cache_free(void);
107 static int cache_update(rcm_handle_t *);
108 static void cache_remove(link_cache_t *);
109 static void node_free(link_cache_t *);
110 static void cache_insert(link_cache_t *);
111 static link_cache_t *cache_lookup(rcm_handle_t *, char *, uint_t);
112 static char *bridge_usage(link_cache_t *);
113 static void bridge_log_err(datalink_id_t, char **, char *);
115 /* Module-Private data */
116 static struct rcm_mod_ops bridge_ops =
118 RCM_MOD_OPS_VERSION,
119 bridge_register,
120 bridge_unregister,
121 bridge_get_info,
122 bridge_suspend,
123 bridge_resume,
124 bridge_offline,
125 bridge_undo_offline,
126 bridge_remove,
127 NULL,
128 NULL,
129 bridge_notify_event
133 * rcm_mod_init() - Update registrations, and return the ops structure.
135 struct rcm_mod_ops *
136 rcm_mod_init(void)
138 dladm_status_t status;
139 char errmsg[DLADM_STRSIZE];
141 rcm_log_message(RCM_TRACE1, "Bridge: mod_init\n");
143 cache_head.vc_next = &cache_tail;
144 cache_head.vc_prev = NULL;
145 cache_tail.vc_prev = &cache_head;
146 cache_tail.vc_next = NULL;
147 (void) mutex_init(&cache_lock, 0, NULL);
149 if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) {
150 rcm_log_message(RCM_WARNING,
151 "Bridge: cannot open datalink handle: %s\n",
152 dladm_status2str(status, errmsg));
153 return (NULL);
156 /* Return the ops vectors */
157 return (&bridge_ops);
161 * rcm_mod_info() - Return a string describing this module.
163 const char *
164 rcm_mod_info(void)
166 rcm_log_message(RCM_TRACE1, "Bridge: mod_info\n");
168 return ("Bridge module version 1.0");
172 * rcm_mod_fini() - Destroy the network Bridge cache.
175 rcm_mod_fini(void)
177 rcm_log_message(RCM_TRACE1, "Bridge: mod_fini\n");
180 * Note that bridge_unregister() does not seem to be called anywhere,
181 * therefore we free the cache nodes here. In theory we should call
182 * rcm_register_interest() for each node before we free it, but the
183 * framework does not provide the rcm_handle to allow us to do so.
185 cache_free();
186 (void) mutex_destroy(&cache_lock);
188 dladm_close(dld_handle);
189 return (RCM_SUCCESS);
193 * bridge_register() - Make sure the cache is properly sync'ed, and its
194 * registrations are in order.
196 static int
197 bridge_register(rcm_handle_t *hd)
199 int retv;
201 rcm_log_message(RCM_TRACE1, "Bridge: register\n");
203 if ((retv = cache_update(hd)) != RCM_SUCCESS)
204 return (retv);
207 * Need to register interest in all new resources
208 * getting attached, so we get attach event notifications
210 if (!events_registered) {
211 retv = rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL);
212 if (retv != RCM_SUCCESS) {
213 rcm_log_message(RCM_ERROR,
214 _("Bridge: failed to register %s\n"),
215 RCM_RESOURCE_LINK_NEW);
216 } else {
217 rcm_log_message(RCM_DEBUG, "Bridge: registered %s\n",
218 RCM_RESOURCE_LINK_NEW);
219 events_registered = B_TRUE;
223 return (retv);
227 * bridge_unregister() - Walk the cache, unregistering all the links.
229 static int
230 bridge_unregister(rcm_handle_t *hd)
232 link_cache_t *node;
233 int retv = RCM_SUCCESS;
235 rcm_log_message(RCM_TRACE1, "Bridge: unregister\n");
237 /* Walk the cache, unregistering everything */
238 (void) mutex_lock(&cache_lock);
239 node = cache_head.vc_next;
240 while (node != &cache_tail) {
241 retv = rcm_unregister_interest(hd, node->vc_resource, 0);
242 if (retv != RCM_SUCCESS)
243 break;
244 cache_remove(node);
245 node_free(node);
246 node = cache_head.vc_next;
248 (void) mutex_unlock(&cache_lock);
249 if (retv != RCM_SUCCESS) {
250 rcm_log_message(RCM_ERROR,
251 _("Bridge: failed to unregister %s\n"), node->vc_resource);
252 return (retv);
256 * Unregister interest in all new resources
258 if (events_registered) {
259 retv = rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0);
260 if (retv != RCM_SUCCESS) {
261 rcm_log_message(RCM_ERROR,
262 _("Bridge: failed to unregister %s\n"),
263 RCM_RESOURCE_LINK_NEW);
264 } else {
265 rcm_log_message(RCM_DEBUG, "Bridge: unregistered %s\n",
266 RCM_RESOURCE_LINK_NEW);
267 events_registered = B_FALSE;
271 return (retv);
275 * bridge_offline() - Offline the bridge on a specific link.
277 static int
278 bridge_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
279 char **errorp, rcm_info_t **info)
281 link_cache_t *node;
282 dladm_status_t status;
284 rcm_log_message(RCM_TRACE1, "Bridge: offline(%s)\n", rsrc);
286 /* Lock the cache and lookup the resource */
287 (void) mutex_lock(&cache_lock);
288 node = cache_lookup(hd, rsrc, CACHE_REFRESH);
289 if (node == NULL) {
290 /* should not happen because the resource is registered. */
291 bridge_log_err(DATALINK_INVALID_LINKID, errorp,
292 "unrecognized resource");
293 (void) mutex_unlock(&cache_lock);
294 return (RCM_SUCCESS);
297 /* Check if it's a query */
298 if (flags & RCM_QUERY) {
299 rcm_log_message(RCM_TRACE1,
300 "Bridge: offline query succeeded(%s)\n", rsrc);
301 (void) mutex_unlock(&cache_lock);
302 return (RCM_SUCCESS);
305 status = dladm_bridge_setlink(dld_handle, node->vc_linkid, "");
306 if (status != DLADM_STATUS_OK) {
307 bridge_log_err(node->vc_linkid, errorp, "offline failed");
308 (void) mutex_unlock(&cache_lock);
309 return (RCM_FAILURE);
312 node->vc_state |= CACHE_NODE_OFFLINED;
314 rcm_log_message(RCM_TRACE1, "Bridge: Offline succeeded(%s %s)\n", rsrc,
315 node->vc_bridge);
316 (void) mutex_unlock(&cache_lock);
317 return (RCM_SUCCESS);
321 * bridge_undo_offline() - Undo offline of a previously offlined node.
323 /*ARGSUSED*/
324 static int
325 bridge_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
326 char **errorp, rcm_info_t **info)
328 link_cache_t *node;
329 dladm_status_t status;
330 char errmsg[DLADM_STRSIZE];
332 rcm_log_message(RCM_TRACE1, "Bridge: online(%s)\n", rsrc);
334 (void) mutex_lock(&cache_lock);
335 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
336 if (node == NULL) {
337 bridge_log_err(DATALINK_INVALID_LINKID, errorp, "no such link");
338 (void) mutex_unlock(&cache_lock);
339 errno = ENOENT;
340 return (RCM_FAILURE);
343 /* Check if no attempt should be made to online the link here */
344 if (!(node->vc_state & CACHE_NODE_OFFLINED)) {
345 bridge_log_err(node->vc_linkid, errorp, "link not offlined");
346 (void) mutex_unlock(&cache_lock);
347 errno = ENOTSUP;
348 return (RCM_SUCCESS);
352 * Try to bring on an offlined bridge link.
354 status = dladm_bridge_setlink(dld_handle, node->vc_linkid,
355 node->vc_bridge);
356 if (status != DLADM_STATUS_OK) {
358 * Print a warning message.
360 rcm_log_message(RCM_WARNING,
361 _("Bridge: Bridge online failed %u %s: %s\n"),
362 node->vc_linkid, node->vc_bridge,
363 dladm_status2str(status, errmsg));
366 node->vc_state &= ~CACHE_NODE_OFFLINED;
367 rcm_log_message(RCM_TRACE1, "Bridge: online succeeded(%s)\n", rsrc);
368 (void) mutex_unlock(&cache_lock);
369 return (RCM_SUCCESS);
373 * bridge_get_info() - Gather usage information for this resource.
375 /*ARGSUSED*/
377 bridge_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
378 char **usagep, char **errorp, nvlist_t *props, rcm_info_t **info)
380 link_cache_t *node;
382 rcm_log_message(RCM_TRACE1, "Bridge: get_info(%s)\n", rsrc);
384 (void) mutex_lock(&cache_lock);
385 node = cache_lookup(hd, rsrc, CACHE_REFRESH);
386 if (node == NULL) {
387 rcm_log_message(RCM_INFO,
388 _("Bridge: get_info(%s) unrecognized resource\n"), rsrc);
389 (void) mutex_unlock(&cache_lock);
390 errno = ENOENT;
391 return (RCM_FAILURE);
394 *usagep = bridge_usage(node);
395 (void) mutex_unlock(&cache_lock);
396 if (*usagep == NULL) {
397 /* most likely malloc failure */
398 rcm_log_message(RCM_ERROR,
399 _("Bridge: get_info(%s) malloc failure\n"), rsrc);
400 (void) mutex_unlock(&cache_lock);
401 errno = ENOMEM;
402 return (RCM_FAILURE);
405 /* Set client/role properties */
406 (void) nvlist_add_string(props, RCM_CLIENT_NAME, "Bridge");
408 rcm_log_message(RCM_TRACE1, "Bridge: get_info(%s) info = %s\n",
409 rsrc, *usagep);
410 return (RCM_SUCCESS);
414 * bridge_suspend() - Nothing to do, always okay
416 /*ARGSUSED*/
417 static int
418 bridge_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval,
419 uint_t flags, char **errorp, rcm_info_t **info)
421 rcm_log_message(RCM_TRACE1, "Bridge: suspend(%s)\n", rsrc);
422 return (RCM_SUCCESS);
426 * bridge_resume() - Nothing to do, always okay
428 /*ARGSUSED*/
429 static int
430 bridge_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
431 char **errorp, rcm_info_t **info)
433 rcm_log_message(RCM_TRACE1, "Bridge: resume(%s)\n", rsrc);
434 return (RCM_SUCCESS);
438 * bridge_remove() - remove a resource from cache
440 /*ARGSUSED*/
441 static int
442 bridge_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
443 char **errorp, rcm_info_t **info)
445 link_cache_t *node;
447 rcm_log_message(RCM_TRACE1, "Bridge: remove(%s)\n", rsrc);
449 (void) mutex_lock(&cache_lock);
450 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
451 if (node == NULL) {
452 rcm_log_message(RCM_INFO,
453 _("Bridge: remove(%s) unrecognized resource\n"), rsrc);
454 (void) mutex_unlock(&cache_lock);
455 errno = ENOENT;
456 return (RCM_FAILURE);
459 /* remove the cached entry for the resource */
460 rcm_log_message(RCM_TRACE2,
461 "Bridge: remove succeeded(%s, %s)\n", rsrc, node->vc_bridge);
462 cache_remove(node);
463 (void) mutex_unlock(&cache_lock);
465 node_free(node);
466 return (RCM_SUCCESS);
470 * bridge_notify_event - Project private implementation to receive new resource
471 * events. It intercepts all new resource events. If the
472 * new resource is a network resource, pass up a notify
473 * for it too. The new resource need not be cached, since
474 * it is done at register again.
476 /*ARGSUSED*/
477 static int
478 bridge_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
479 char **errorp, nvlist_t *nvl, rcm_info_t **info)
481 nvpair_t *nvp = NULL;
482 datalink_id_t linkid;
483 uint64_t id64;
484 int rv, lastrv;
486 rcm_log_message(RCM_TRACE1, "Bridge: notify_event(%s)\n", rsrc);
488 if (strcmp(rsrc, RCM_RESOURCE_LINK_NEW) != 0) {
489 bridge_log_err(DATALINK_INVALID_LINKID, errorp,
490 "unrecognized event");
491 errno = EINVAL;
492 return (RCM_FAILURE);
495 /* Update cache to reflect latest Bridges */
496 if ((lastrv = cache_update(hd)) != RCM_SUCCESS) {
497 bridge_log_err(DATALINK_INVALID_LINKID, errorp,
498 "private Cache update failed");
499 return (lastrv);
503 * Try best to recover all configuration.
505 rcm_log_message(RCM_DEBUG, "Bridge: process_nvlist\n");
506 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
507 if (strcmp(nvpair_name(nvp), RCM_NV_LINKID) != 0)
508 continue;
510 if (nvpair_value_uint64(nvp, &id64) != 0) {
511 bridge_log_err(DATALINK_INVALID_LINKID, errorp,
512 "cannot get linkid");
513 lastrv = RCM_FAILURE;
514 continue;
517 linkid = (datalink_id_t)id64;
518 if ((rv = bridge_configure(hd, linkid)) != RCM_SUCCESS) {
519 bridge_log_err(linkid, errorp, "configuring failed");
520 lastrv = rv;
524 rcm_log_message(RCM_TRACE1,
525 "Bridge: notify_event: link configuration complete\n");
526 return (lastrv);
530 * bridge_usage - Determine the usage of a link.
531 * The returned buffer is owned by caller, and the caller
532 * must free it up when done.
534 static char *
535 bridge_usage(link_cache_t *node)
537 char *buf;
538 const char *fmt;
539 char errmsg[DLADM_STRSIZE];
540 char name[MAXLINKNAMELEN];
541 char bridge[MAXLINKNAMELEN];
542 dladm_status_t status;
544 rcm_log_message(RCM_TRACE2, "Bridge: usage(%s)\n", node->vc_resource);
546 assert(MUTEX_HELD(&cache_lock));
548 status = dladm_datalink_id2info(dld_handle, node->vc_linkid, NULL,
549 NULL, NULL, name, sizeof (name));
551 if (status != DLADM_STATUS_OK) {
552 rcm_log_message(RCM_ERROR,
553 _("Bridge: usage(%s) get link name failure(%s)\n"),
554 node->vc_resource, dladm_status2str(status, errmsg));
555 return (NULL);
558 (void) dladm_bridge_getlink(dld_handle, node->vc_linkid, bridge,
559 sizeof (bridge));
561 if (node->vc_state & CACHE_NODE_OFFLINED)
562 fmt = _("%1$s offlined");
563 else if (bridge[0] == '\0')
564 fmt = _("%1$s not bridged");
565 else
566 fmt = _("%1$s bridge: %2$s");
568 (void) asprintf(&buf, fmt, name, bridge);
570 rcm_log_message(RCM_TRACE2, "Bridge: usage (%s) info = %s\n",
571 node->vc_resource, buf);
573 return (buf);
577 * Cache management routines, all cache management functions should be
578 * be called with cache_lock held.
582 * cache_lookup() - Get a cache node for a resource.
583 * Call with cache lock held.
585 * This ensures that the cache is consistent with the system state and
586 * returns a pointer to the cache element corresponding to the resource.
588 static link_cache_t *
589 cache_lookup(rcm_handle_t *hd, char *rsrc, uint_t options)
591 link_cache_t *node;
593 rcm_log_message(RCM_TRACE2, "Bridge: cache lookup(%s)\n", rsrc);
595 assert(MUTEX_HELD(&cache_lock));
596 if (options & CACHE_REFRESH) {
597 /* drop lock since update locks cache again */
598 (void) mutex_unlock(&cache_lock);
599 (void) cache_update(hd);
600 (void) mutex_lock(&cache_lock);
603 node = cache_head.vc_next;
604 for (; node != &cache_tail; node = node->vc_next) {
605 if (strcmp(rsrc, node->vc_resource) == 0) {
606 rcm_log_message(RCM_TRACE2,
607 "Bridge: cache lookup succeeded(%s, %s)\n", rsrc,
608 node->vc_bridge);
609 return (node);
612 return (NULL);
616 * node_free - Free a node from the cache
618 static void
619 node_free(link_cache_t *node)
621 if (node != NULL) {
622 free(node->vc_resource);
623 free(node);
628 * cache_insert - Insert a resource node in cache
630 static void
631 cache_insert(link_cache_t *node)
633 assert(MUTEX_HELD(&cache_lock));
635 /* insert at the head for best performance */
636 node->vc_next = cache_head.vc_next;
637 node->vc_prev = &cache_head;
639 node->vc_next->vc_prev = node;
640 node->vc_prev->vc_next = node;
644 * cache_remove() - Remove a resource node from cache.
646 static void
647 cache_remove(link_cache_t *node)
649 assert(MUTEX_HELD(&cache_lock));
650 node->vc_next->vc_prev = node->vc_prev;
651 node->vc_prev->vc_next = node->vc_next;
652 node->vc_next = NULL;
653 node->vc_prev = NULL;
656 typedef struct bridge_update_arg_s {
657 rcm_handle_t *hd;
658 int retval;
659 } bridge_update_arg_t;
662 * bridge_update() - Update physical interface properties
664 static int
665 bridge_update(dladm_handle_t handle, datalink_id_t linkid, void *arg)
667 bridge_update_arg_t *bua = arg;
668 rcm_handle_t *hd = bua->hd;
669 link_cache_t *node;
670 char *rsrc;
671 dladm_status_t status;
672 char errmsg[DLADM_STRSIZE];
673 char bridge[MAXLINKNAMELEN];
674 int ret = RCM_FAILURE;
676 rcm_log_message(RCM_TRACE2, "Bridge: bridge_update(%u)\n", linkid);
678 assert(MUTEX_HELD(&cache_lock));
679 status = dladm_bridge_getlink(dld_handle, linkid, bridge,
680 sizeof (bridge));
681 if (status != DLADM_STATUS_OK) {
682 rcm_log_message(RCM_TRACE1,
683 "Bridge: no bridge information for %u (%s)\n",
684 linkid, dladm_status2str(status, errmsg));
685 return (DLADM_WALK_CONTINUE);
688 (void) asprintf(&rsrc, "%s/%u", RCM_LINK_PREFIX, linkid);
689 if (rsrc == NULL) {
690 rcm_log_message(RCM_ERROR,
691 _("Bridge: allocation failure: %s %u: %s\n"),
692 bridge, linkid, strerror(errno));
693 goto done;
696 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
697 if (node != NULL) {
698 rcm_log_message(RCM_DEBUG, "Bridge: %s already registered\n",
699 rsrc);
700 free(rsrc);
701 node->vc_state &= ~CACHE_NODE_STALE;
702 } else {
703 rcm_log_message(RCM_DEBUG,
704 "Bridge: %s is a new resource (bridge %s)\n",
705 rsrc, bridge);
706 if ((node = calloc(1, sizeof (link_cache_t))) == NULL) {
707 free(rsrc);
708 rcm_log_message(RCM_ERROR, _("Bridge: calloc: %s\n"),
709 strerror(errno));
710 goto done;
713 node->vc_resource = rsrc;
714 node->vc_linkid = linkid;
715 (void) strlcpy(node->vc_bridge, bridge,
716 sizeof (node->vc_bridge));
717 node->vc_state |= CACHE_NODE_NEW;
718 cache_insert(node);
721 rcm_log_message(RCM_TRACE3, "Bridge: bridge_update: succeeded(%u %s)\n",
722 linkid, node->vc_bridge);
723 ret = RCM_SUCCESS;
724 done:
725 bua->retval = ret;
726 return (ret == RCM_SUCCESS ? DLADM_WALK_CONTINUE :
727 DLADM_WALK_TERMINATE);
731 * cache_update() - Update cache with latest interface info
733 static int
734 cache_update(rcm_handle_t *hd)
736 link_cache_t *node, *nnode;
737 int rv, lastrv;
738 bridge_update_arg_t bua;
740 rcm_log_message(RCM_TRACE2, "Bridge: cache_update\n");
742 (void) mutex_lock(&cache_lock);
744 /* first we walk the entire cache, marking each entry stale */
745 node = cache_head.vc_next;
746 for (; node != &cache_tail; node = node->vc_next)
747 node->vc_state |= CACHE_NODE_STALE;
749 /* now walk the links and update all of the entries */
750 bua.hd = hd;
751 bua.retval = RCM_SUCCESS;
752 (void) dladm_walk_datalink_id(bridge_update, dld_handle, &bua,
753 DATALINK_CLASS_AGGR | DATALINK_CLASS_PHYS |
754 DATALINK_CLASS_ETHERSTUB, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
755 lastrv = bua.retval;
758 * Continue to delete all stale nodes from the cache even if the walk
759 * above failed. Unregister links that are not offlined and still in
760 * the cache.
762 for (node = cache_head.vc_next; node != &cache_tail; node = nnode) {
763 nnode = node->vc_next;
765 if (node->vc_state & CACHE_NODE_STALE) {
766 (void) rcm_unregister_interest(hd, node->vc_resource,
768 rcm_log_message(RCM_DEBUG,
769 "Bridge: unregistered %s %s\n",
770 node->vc_resource, node->vc_bridge);
771 cache_remove(node);
772 node_free(node);
773 continue;
776 if (!(node->vc_state & CACHE_NODE_NEW))
777 continue;
779 rv = rcm_register_interest(hd, node->vc_resource, 0, NULL);
780 if (rv != RCM_SUCCESS) {
781 rcm_log_message(RCM_ERROR,
782 _("Bridge: failed to register %s\n"),
783 node->vc_resource);
784 lastrv = rv;
785 } else {
786 rcm_log_message(RCM_DEBUG, "Bridge: registered %s\n",
787 node->vc_resource);
788 node->vc_state &= ~CACHE_NODE_NEW;
792 (void) mutex_unlock(&cache_lock);
793 return (lastrv);
797 * cache_free() - Empty the cache
799 static void
800 cache_free(void)
802 link_cache_t *node;
804 rcm_log_message(RCM_TRACE2, "Bridge: cache_free\n");
806 (void) mutex_lock(&cache_lock);
807 node = cache_head.vc_next;
808 while (node != &cache_tail) {
809 cache_remove(node);
810 node_free(node);
811 node = cache_head.vc_next;
813 (void) mutex_unlock(&cache_lock);
817 * bridge_log_err() - RCM error log wrapper
819 static void
820 bridge_log_err(datalink_id_t linkid, char **errorp, char *errmsg)
822 char link[MAXLINKNAMELEN];
823 char errstr[DLADM_STRSIZE];
824 dladm_status_t status;
825 char *error;
827 link[0] = '\0';
828 if (linkid != DATALINK_INVALID_LINKID) {
829 char rsrc[RCM_LINK_RESOURCE_MAX];
831 (void) snprintf(rsrc, sizeof (rsrc), "%s/%u",
832 RCM_LINK_PREFIX, linkid);
834 rcm_log_message(RCM_ERROR, _("Bridge: %s(%s)\n"), errmsg, rsrc);
835 if ((status = dladm_datalink_id2info(dld_handle, linkid, NULL,
836 NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
837 rcm_log_message(RCM_WARNING,
838 _("Bridge: cannot get link name for (%s) %s\n"),
839 rsrc, dladm_status2str(status, errstr));
841 } else {
842 rcm_log_message(RCM_ERROR, _("Bridge: %s\n"), errmsg);
845 if (link[0] != '\0')
846 (void) asprintf(&error, _("Bridge: %s(%s)"), errmsg, link);
847 else
848 (void) asprintf(&error, _("Bridge: %s"), errmsg);
850 if (errorp != NULL)
851 *errorp = error;
855 * bridge_configure() - Configure bridge on a physical link after it attaches
857 static int
858 bridge_configure(rcm_handle_t *hd, datalink_id_t linkid)
860 char rsrc[RCM_LINK_RESOURCE_MAX];
861 link_cache_t *node;
862 char bridge[MAXLINKNAMELEN];
864 /* Check for the bridge links in the cache */
865 (void) snprintf(rsrc, sizeof (rsrc), "%s/%u", RCM_LINK_PREFIX, linkid);
867 rcm_log_message(RCM_TRACE2, "Bridge: bridge_configure(%s)\n", rsrc);
869 /* Check if the link is new or was previously offlined */
870 (void) mutex_lock(&cache_lock);
871 if (((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) != NULL) &&
872 (!(node->vc_state & CACHE_NODE_OFFLINED))) {
873 rcm_log_message(RCM_TRACE2,
874 "Bridge: Skipping configured interface(%s)\n", rsrc);
875 (void) mutex_unlock(&cache_lock);
876 return (RCM_SUCCESS);
878 (void) mutex_unlock(&cache_lock);
880 /* clear out previous bridge, if any */
881 if (dladm_bridge_getlink(dld_handle, linkid, bridge, sizeof (bridge)) ==
882 DLADM_STATUS_OK) {
883 if (bridge[0] != '\0')
884 (void) dladm_bridge_setlink(dld_handle, linkid, "");
887 /* now set up the new one */
888 if (node != NULL && node->vc_bridge[0] != '\0' &&
889 dladm_bridge_setlink(dld_handle, linkid, node->vc_bridge) !=
890 DLADM_STATUS_OK)
891 return (RCM_FAILURE);
892 else
893 return (RCM_SUCCESS);