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]
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
34 #include <sys/types.h>
38 #include "rcm_module.h"
40 #include <libdllink.h>
41 #include <libdlbridge.h>
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 */
55 CACHE_NODE_STALE
= 0x1, /* stale cached data */
56 CACHE_NODE_NEW
= 0x2, /* new cached nodes */
57 CACHE_NODE_OFFLINED
= 0x4 /* nodes offlined */
60 /* Network Cache lookup options */
61 #define CACHE_NO_REFRESH 0x1 /* cache refresh not needed */
62 #define CACHE_REFRESH 0x2 /* refresh cache */
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
];
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
=
133 * rcm_mod_init() - Update registrations, and return the ops structure.
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
));
156 /* Return the ops vectors */
157 return (&bridge_ops
);
161 * rcm_mod_info() - Return a string describing this module.
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.
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.
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.
197 bridge_register(rcm_handle_t
*hd
)
201 rcm_log_message(RCM_TRACE1
, "Bridge: register\n");
203 if ((retv
= cache_update(hd
)) != RCM_SUCCESS
)
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
);
217 rcm_log_message(RCM_DEBUG
, "Bridge: registered %s\n",
218 RCM_RESOURCE_LINK_NEW
);
219 events_registered
= B_TRUE
;
227 * bridge_unregister() - Walk the cache, unregistering all the links.
230 bridge_unregister(rcm_handle_t
*hd
)
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
)
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
);
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
);
265 rcm_log_message(RCM_DEBUG
, "Bridge: unregistered %s\n",
266 RCM_RESOURCE_LINK_NEW
);
267 events_registered
= B_FALSE
;
275 * bridge_offline() - Offline the bridge on a specific link.
278 bridge_offline(rcm_handle_t
*hd
, char *rsrc
, id_t id
, uint_t flags
,
279 char **errorp
, rcm_info_t
**info
)
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
);
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
,
316 (void) mutex_unlock(&cache_lock
);
317 return (RCM_SUCCESS
);
321 * bridge_undo_offline() - Undo offline of a previously offlined node.
325 bridge_undo_offline(rcm_handle_t
*hd
, char *rsrc
, id_t id
, uint_t flags
,
326 char **errorp
, rcm_info_t
**info
)
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
);
337 bridge_log_err(DATALINK_INVALID_LINKID
, errorp
, "no such link");
338 (void) mutex_unlock(&cache_lock
);
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
);
348 return (RCM_SUCCESS
);
352 * Try to bring on an offlined bridge link.
354 status
= dladm_bridge_setlink(dld_handle
, node
->vc_linkid
,
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.
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
)
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
);
387 rcm_log_message(RCM_INFO
,
388 _("Bridge: get_info(%s) unrecognized resource\n"), rsrc
);
389 (void) mutex_unlock(&cache_lock
);
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
);
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",
410 return (RCM_SUCCESS
);
414 * bridge_suspend() - Nothing to do, always okay
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
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
442 bridge_remove(rcm_handle_t
*hd
, char *rsrc
, id_t id
, uint_t flags
,
443 char **errorp
, rcm_info_t
**info
)
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
);
452 rcm_log_message(RCM_INFO
,
453 _("Bridge: remove(%s) unrecognized resource\n"), rsrc
);
454 (void) mutex_unlock(&cache_lock
);
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
);
463 (void) mutex_unlock(&cache_lock
);
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.
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
;
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");
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");
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)
510 if (nvpair_value_uint64(nvp
, &id64
) != 0) {
511 bridge_log_err(DATALINK_INVALID_LINKID
, errorp
,
512 "cannot get linkid");
513 lastrv
= RCM_FAILURE
;
517 linkid
= (datalink_id_t
)id64
;
518 if ((rv
= bridge_configure(hd
, linkid
)) != RCM_SUCCESS
) {
519 bridge_log_err(linkid
, errorp
, "configuring failed");
524 rcm_log_message(RCM_TRACE1
,
525 "Bridge: notify_event: link configuration complete\n");
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.
535 bridge_usage(link_cache_t
*node
)
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
));
558 (void) dladm_bridge_getlink(dld_handle
, node
->vc_linkid
, 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");
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
);
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
)
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
,
616 * node_free - Free a node from the cache
619 node_free(link_cache_t
*node
)
622 free(node
->vc_resource
);
628 * cache_insert - Insert a resource node in cache
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.
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
{
659 } bridge_update_arg_t
;
662 * bridge_update() - Update physical interface properties
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
;
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
,
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
);
690 rcm_log_message(RCM_ERROR
,
691 _("Bridge: allocation failure: %s %u: %s\n"),
692 bridge
, linkid
, strerror(errno
));
696 node
= cache_lookup(hd
, rsrc
, CACHE_NO_REFRESH
);
698 rcm_log_message(RCM_DEBUG
, "Bridge: %s already registered\n",
701 node
->vc_state
&= ~CACHE_NODE_STALE
;
703 rcm_log_message(RCM_DEBUG
,
704 "Bridge: %s is a new resource (bridge %s)\n",
706 if ((node
= calloc(1, sizeof (link_cache_t
))) == NULL
) {
708 rcm_log_message(RCM_ERROR
, _("Bridge: calloc: %s\n"),
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
;
721 rcm_log_message(RCM_TRACE3
, "Bridge: bridge_update: succeeded(%u %s)\n",
722 linkid
, node
->vc_bridge
);
726 return (ret
== RCM_SUCCESS
? DLADM_WALK_CONTINUE
:
727 DLADM_WALK_TERMINATE
);
731 * cache_update() - Update cache with latest interface info
734 cache_update(rcm_handle_t
*hd
)
736 link_cache_t
*node
, *nnode
;
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 */
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
);
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
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
);
776 if (!(node
->vc_state
& CACHE_NODE_NEW
))
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"),
786 rcm_log_message(RCM_DEBUG
, "Bridge: registered %s\n",
788 node
->vc_state
&= ~CACHE_NODE_NEW
;
792 (void) mutex_unlock(&cache_lock
);
797 * cache_free() - Empty the cache
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
) {
811 node
= cache_head
.vc_next
;
813 (void) mutex_unlock(&cache_lock
);
817 * bridge_log_err() - RCM error log wrapper
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
;
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
));
842 rcm_log_message(RCM_ERROR
, _("Bridge: %s\n"), errmsg
);
846 (void) asprintf(&error
, _("Bridge: %s(%s)"), errmsg
, link
);
848 (void) asprintf(&error
, _("Bridge: %s"), errmsg
);
855 * bridge_configure() - Configure bridge on a physical link after it attaches
858 bridge_configure(rcm_handle_t
*hd
, datalink_id_t linkid
)
860 char rsrc
[RCM_LINK_RESOURCE_MAX
];
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
)) ==
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
) !=
891 return (RCM_FAILURE
);
893 return (RCM_SUCCESS
);