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>
48 #define _(x) gettext(x)
53 /* Some generic well-knowns and defaults used in this module */
54 #define RCM_LINK_PREFIX "SUNW_datalink" /* RCM datalink name prefix */
55 #define RCM_LINK_RESOURCE_MAX (13 + LINKID_STR_WIDTH)
57 /* Bridge Cache state flags */
59 CACHE_NODE_STALE
= 0x1, /* stale cached data */
60 CACHE_NODE_NEW
= 0x2, /* new cached nodes */
61 CACHE_NODE_OFFLINED
= 0x4 /* nodes offlined */
64 /* Network Cache lookup options */
65 #define CACHE_NO_REFRESH 0x1 /* cache refresh not needed */
66 #define CACHE_REFRESH 0x2 /* refresh cache */
69 typedef struct link_cache
{
70 struct link_cache
*vc_next
; /* next cached resource */
71 struct link_cache
*vc_prev
; /* prev cached resource */
72 char *vc_resource
; /* resource name */
73 datalink_id_t vc_linkid
; /* linkid */
74 cache_node_state_t vc_state
; /* cache state flags */
75 char vc_bridge
[MAXLINKNAMELEN
];
79 * Global cache for network Bridges
81 static link_cache_t cache_head
;
82 static link_cache_t cache_tail
;
83 static mutex_t cache_lock
;
84 static boolean_t events_registered
= B_FALSE
;
86 static dladm_handle_t dld_handle
= NULL
;
89 * RCM module interface prototypes
91 static int bridge_register(rcm_handle_t
*);
92 static int bridge_unregister(rcm_handle_t
*);
93 static int bridge_get_info(rcm_handle_t
*, char *, id_t
, uint_t
,
94 char **, char **, nvlist_t
*, rcm_info_t
**);
95 static int bridge_suspend(rcm_handle_t
*, char *, id_t
,
96 timespec_t
*, uint_t
, char **, rcm_info_t
**);
97 static int bridge_resume(rcm_handle_t
*, char *, id_t
, uint_t
,
98 char **, rcm_info_t
**);
99 static int bridge_offline(rcm_handle_t
*, char *, id_t
, uint_t
,
100 char **, rcm_info_t
**);
101 static int bridge_undo_offline(rcm_handle_t
*, char *, id_t
,
102 uint_t
, char **, rcm_info_t
**);
103 static int bridge_remove(rcm_handle_t
*, char *, id_t
, uint_t
,
104 char **, rcm_info_t
**);
105 static int bridge_notify_event(rcm_handle_t
*, char *, id_t
,
106 uint_t
, char **, nvlist_t
*, rcm_info_t
**);
107 static int bridge_configure(rcm_handle_t
*, datalink_id_t
);
109 /* Module private routines */
110 static void cache_free(void);
111 static int cache_update(rcm_handle_t
*);
112 static void cache_remove(link_cache_t
*);
113 static void node_free(link_cache_t
*);
114 static void cache_insert(link_cache_t
*);
115 static link_cache_t
*cache_lookup(rcm_handle_t
*, char *, uint_t
);
116 static char *bridge_usage(link_cache_t
*);
117 static void bridge_log_err(datalink_id_t
, char **, char *);
119 /* Module-Private data */
120 static struct rcm_mod_ops bridge_ops
=
137 * rcm_mod_init() - Update registrations, and return the ops structure.
142 dladm_status_t status
;
143 char errmsg
[DLADM_STRSIZE
];
145 rcm_log_message(RCM_TRACE1
, "Bridge: mod_init\n");
147 cache_head
.vc_next
= &cache_tail
;
148 cache_head
.vc_prev
= NULL
;
149 cache_tail
.vc_prev
= &cache_head
;
150 cache_tail
.vc_next
= NULL
;
151 (void) mutex_init(&cache_lock
, 0, NULL
);
153 if ((status
= dladm_open(&dld_handle
)) != DLADM_STATUS_OK
) {
154 rcm_log_message(RCM_WARNING
,
155 "Bridge: cannot open datalink handle: %s\n",
156 dladm_status2str(status
, errmsg
));
160 /* Return the ops vectors */
161 return (&bridge_ops
);
165 * rcm_mod_info() - Return a string describing this module.
170 rcm_log_message(RCM_TRACE1
, "Bridge: mod_info\n");
172 return ("Bridge module version 1.0");
176 * rcm_mod_fini() - Destroy the network Bridge cache.
181 rcm_log_message(RCM_TRACE1
, "Bridge: mod_fini\n");
184 * Note that bridge_unregister() does not seem to be called anywhere,
185 * therefore we free the cache nodes here. In theory we should call
186 * rcm_register_interest() for each node before we free it, but the
187 * framework does not provide the rcm_handle to allow us to do so.
190 (void) mutex_destroy(&cache_lock
);
192 dladm_close(dld_handle
);
193 return (RCM_SUCCESS
);
197 * bridge_register() - Make sure the cache is properly sync'ed, and its
198 * registrations are in order.
201 bridge_register(rcm_handle_t
*hd
)
205 rcm_log_message(RCM_TRACE1
, "Bridge: register\n");
207 if ((retv
= cache_update(hd
)) != RCM_SUCCESS
)
211 * Need to register interest in all new resources
212 * getting attached, so we get attach event notifications
214 if (!events_registered
) {
215 retv
= rcm_register_event(hd
, RCM_RESOURCE_LINK_NEW
, 0, NULL
);
216 if (retv
!= RCM_SUCCESS
) {
217 rcm_log_message(RCM_ERROR
,
218 _("Bridge: failed to register %s\n"),
219 RCM_RESOURCE_LINK_NEW
);
221 rcm_log_message(RCM_DEBUG
, "Bridge: registered %s\n",
222 RCM_RESOURCE_LINK_NEW
);
223 events_registered
= B_TRUE
;
231 * bridge_unregister() - Walk the cache, unregistering all the links.
234 bridge_unregister(rcm_handle_t
*hd
)
237 int retv
= RCM_SUCCESS
;
239 rcm_log_message(RCM_TRACE1
, "Bridge: unregister\n");
241 /* Walk the cache, unregistering everything */
242 (void) mutex_lock(&cache_lock
);
243 node
= cache_head
.vc_next
;
244 while (node
!= &cache_tail
) {
245 retv
= rcm_unregister_interest(hd
, node
->vc_resource
, 0);
246 if (retv
!= RCM_SUCCESS
)
250 node
= cache_head
.vc_next
;
252 (void) mutex_unlock(&cache_lock
);
253 if (retv
!= RCM_SUCCESS
) {
254 rcm_log_message(RCM_ERROR
,
255 _("Bridge: failed to unregister %s\n"), node
->vc_resource
);
260 * Unregister interest in all new resources
262 if (events_registered
) {
263 retv
= rcm_unregister_event(hd
, RCM_RESOURCE_LINK_NEW
, 0);
264 if (retv
!= RCM_SUCCESS
) {
265 rcm_log_message(RCM_ERROR
,
266 _("Bridge: failed to unregister %s\n"),
267 RCM_RESOURCE_LINK_NEW
);
269 rcm_log_message(RCM_DEBUG
, "Bridge: unregistered %s\n",
270 RCM_RESOURCE_LINK_NEW
);
271 events_registered
= B_FALSE
;
279 * bridge_offline() - Offline the bridge on a specific link.
282 bridge_offline(rcm_handle_t
*hd
, char *rsrc
, id_t id
, uint_t flags
,
283 char **errorp
, rcm_info_t
**info
)
286 dladm_status_t status
;
288 rcm_log_message(RCM_TRACE1
, "Bridge: offline(%s)\n", rsrc
);
290 /* Lock the cache and lookup the resource */
291 (void) mutex_lock(&cache_lock
);
292 node
= cache_lookup(hd
, rsrc
, CACHE_REFRESH
);
294 /* should not happen because the resource is registered. */
295 bridge_log_err(DATALINK_INVALID_LINKID
, errorp
,
296 "unrecognized resource");
297 (void) mutex_unlock(&cache_lock
);
298 return (RCM_SUCCESS
);
301 /* Check if it's a query */
302 if (flags
& RCM_QUERY
) {
303 rcm_log_message(RCM_TRACE1
,
304 "Bridge: offline query succeeded(%s)\n", rsrc
);
305 (void) mutex_unlock(&cache_lock
);
306 return (RCM_SUCCESS
);
309 status
= dladm_bridge_setlink(dld_handle
, node
->vc_linkid
, "");
310 if (status
!= DLADM_STATUS_OK
) {
311 bridge_log_err(node
->vc_linkid
, errorp
, "offline failed");
312 (void) mutex_unlock(&cache_lock
);
313 return (RCM_FAILURE
);
316 node
->vc_state
|= CACHE_NODE_OFFLINED
;
318 rcm_log_message(RCM_TRACE1
, "Bridge: Offline succeeded(%s %s)\n", rsrc
,
320 (void) mutex_unlock(&cache_lock
);
321 return (RCM_SUCCESS
);
325 * bridge_undo_offline() - Undo offline of a previously offlined node.
329 bridge_undo_offline(rcm_handle_t
*hd
, char *rsrc
, id_t id
, uint_t flags
,
330 char **errorp
, rcm_info_t
**info
)
333 dladm_status_t status
;
334 char errmsg
[DLADM_STRSIZE
];
336 rcm_log_message(RCM_TRACE1
, "Bridge: online(%s)\n", rsrc
);
338 (void) mutex_lock(&cache_lock
);
339 node
= cache_lookup(hd
, rsrc
, CACHE_NO_REFRESH
);
341 bridge_log_err(DATALINK_INVALID_LINKID
, errorp
, "no such link");
342 (void) mutex_unlock(&cache_lock
);
344 return (RCM_FAILURE
);
347 /* Check if no attempt should be made to online the link here */
348 if (!(node
->vc_state
& CACHE_NODE_OFFLINED
)) {
349 bridge_log_err(node
->vc_linkid
, errorp
, "link not offlined");
350 (void) mutex_unlock(&cache_lock
);
352 return (RCM_SUCCESS
);
356 * Try to bring on an offlined bridge link.
358 status
= dladm_bridge_setlink(dld_handle
, node
->vc_linkid
,
360 if (status
!= DLADM_STATUS_OK
) {
362 * Print a warning message.
364 rcm_log_message(RCM_WARNING
,
365 _("Bridge: Bridge online failed %u %s: %s\n"),
366 node
->vc_linkid
, node
->vc_bridge
,
367 dladm_status2str(status
, errmsg
));
370 node
->vc_state
&= ~CACHE_NODE_OFFLINED
;
371 rcm_log_message(RCM_TRACE1
, "Bridge: online succeeded(%s)\n", rsrc
);
372 (void) mutex_unlock(&cache_lock
);
373 return (RCM_SUCCESS
);
377 * bridge_get_info() - Gather usage information for this resource.
381 bridge_get_info(rcm_handle_t
*hd
, char *rsrc
, id_t id
, uint_t flags
,
382 char **usagep
, char **errorp
, nvlist_t
*props
, rcm_info_t
**info
)
386 rcm_log_message(RCM_TRACE1
, "Bridge: get_info(%s)\n", rsrc
);
388 (void) mutex_lock(&cache_lock
);
389 node
= cache_lookup(hd
, rsrc
, CACHE_REFRESH
);
391 rcm_log_message(RCM_INFO
,
392 _("Bridge: get_info(%s) unrecognized resource\n"), rsrc
);
393 (void) mutex_unlock(&cache_lock
);
395 return (RCM_FAILURE
);
398 *usagep
= bridge_usage(node
);
399 (void) mutex_unlock(&cache_lock
);
400 if (*usagep
== NULL
) {
401 /* most likely malloc failure */
402 rcm_log_message(RCM_ERROR
,
403 _("Bridge: get_info(%s) malloc failure\n"), rsrc
);
404 (void) mutex_unlock(&cache_lock
);
406 return (RCM_FAILURE
);
409 /* Set client/role properties */
410 (void) nvlist_add_string(props
, RCM_CLIENT_NAME
, "Bridge");
412 rcm_log_message(RCM_TRACE1
, "Bridge: get_info(%s) info = %s\n",
414 return (RCM_SUCCESS
);
418 * bridge_suspend() - Nothing to do, always okay
422 bridge_suspend(rcm_handle_t
*hd
, char *rsrc
, id_t id
, timespec_t
*interval
,
423 uint_t flags
, char **errorp
, rcm_info_t
**info
)
425 rcm_log_message(RCM_TRACE1
, "Bridge: suspend(%s)\n", rsrc
);
426 return (RCM_SUCCESS
);
430 * bridge_resume() - Nothing to do, always okay
434 bridge_resume(rcm_handle_t
*hd
, char *rsrc
, id_t id
, uint_t flags
,
435 char **errorp
, rcm_info_t
**info
)
437 rcm_log_message(RCM_TRACE1
, "Bridge: resume(%s)\n", rsrc
);
438 return (RCM_SUCCESS
);
442 * bridge_remove() - remove a resource from cache
446 bridge_remove(rcm_handle_t
*hd
, char *rsrc
, id_t id
, uint_t flags
,
447 char **errorp
, rcm_info_t
**info
)
451 rcm_log_message(RCM_TRACE1
, "Bridge: remove(%s)\n", rsrc
);
453 (void) mutex_lock(&cache_lock
);
454 node
= cache_lookup(hd
, rsrc
, CACHE_NO_REFRESH
);
456 rcm_log_message(RCM_INFO
,
457 _("Bridge: remove(%s) unrecognized resource\n"), rsrc
);
458 (void) mutex_unlock(&cache_lock
);
460 return (RCM_FAILURE
);
463 /* remove the cached entry for the resource */
464 rcm_log_message(RCM_TRACE2
,
465 "Bridge: remove succeeded(%s, %s)\n", rsrc
, node
->vc_bridge
);
467 (void) mutex_unlock(&cache_lock
);
470 return (RCM_SUCCESS
);
474 * bridge_notify_event - Project private implementation to receive new resource
475 * events. It intercepts all new resource events. If the
476 * new resource is a network resource, pass up a notify
477 * for it too. The new resource need not be cached, since
478 * it is done at register again.
482 bridge_notify_event(rcm_handle_t
*hd
, char *rsrc
, id_t id
, uint_t flags
,
483 char **errorp
, nvlist_t
*nvl
, rcm_info_t
**info
)
485 nvpair_t
*nvp
= NULL
;
486 datalink_id_t linkid
;
490 rcm_log_message(RCM_TRACE1
, "Bridge: notify_event(%s)\n", rsrc
);
492 if (strcmp(rsrc
, RCM_RESOURCE_LINK_NEW
) != 0) {
493 bridge_log_err(DATALINK_INVALID_LINKID
, errorp
,
494 "unrecognized event");
496 return (RCM_FAILURE
);
499 /* Update cache to reflect latest Bridges */
500 if ((lastrv
= cache_update(hd
)) != RCM_SUCCESS
) {
501 bridge_log_err(DATALINK_INVALID_LINKID
, errorp
,
502 "private Cache update failed");
507 * Try best to recover all configuration.
509 rcm_log_message(RCM_DEBUG
, "Bridge: process_nvlist\n");
510 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)) != NULL
) {
511 if (strcmp(nvpair_name(nvp
), RCM_NV_LINKID
) != 0)
514 if (nvpair_value_uint64(nvp
, &id64
) != 0) {
515 bridge_log_err(DATALINK_INVALID_LINKID
, errorp
,
516 "cannot get linkid");
517 lastrv
= RCM_FAILURE
;
521 linkid
= (datalink_id_t
)id64
;
522 if ((rv
= bridge_configure(hd
, linkid
)) != RCM_SUCCESS
) {
523 bridge_log_err(linkid
, errorp
, "configuring failed");
528 rcm_log_message(RCM_TRACE1
,
529 "Bridge: notify_event: link configuration complete\n");
534 * bridge_usage - Determine the usage of a link.
535 * The returned buffer is owned by caller, and the caller
536 * must free it up when done.
539 bridge_usage(link_cache_t
*node
)
543 char errmsg
[DLADM_STRSIZE
];
544 char name
[MAXLINKNAMELEN
];
545 char bridge
[MAXLINKNAMELEN
];
546 dladm_status_t status
;
548 rcm_log_message(RCM_TRACE2
, "Bridge: usage(%s)\n", node
->vc_resource
);
550 assert(MUTEX_HELD(&cache_lock
));
552 status
= dladm_datalink_id2info(dld_handle
, node
->vc_linkid
, NULL
,
553 NULL
, NULL
, name
, sizeof (name
));
555 if (status
!= DLADM_STATUS_OK
) {
556 rcm_log_message(RCM_ERROR
,
557 _("Bridge: usage(%s) get link name failure(%s)\n"),
558 node
->vc_resource
, dladm_status2str(status
, errmsg
));
562 (void) dladm_bridge_getlink(dld_handle
, node
->vc_linkid
, bridge
,
565 if (node
->vc_state
& CACHE_NODE_OFFLINED
)
566 fmt
= _("%1$s offlined");
567 else if (bridge
[0] == '\0')
568 fmt
= _("%1$s not bridged");
570 fmt
= _("%1$s bridge: %2$s");
572 (void) asprintf(&buf
, fmt
, name
, bridge
);
574 rcm_log_message(RCM_TRACE2
, "Bridge: usage (%s) info = %s\n",
575 node
->vc_resource
, buf
);
581 * Cache management routines, all cache management functions should be
582 * be called with cache_lock held.
586 * cache_lookup() - Get a cache node for a resource.
587 * Call with cache lock held.
589 * This ensures that the cache is consistent with the system state and
590 * returns a pointer to the cache element corresponding to the resource.
592 static link_cache_t
*
593 cache_lookup(rcm_handle_t
*hd
, char *rsrc
, uint_t options
)
597 rcm_log_message(RCM_TRACE2
, "Bridge: cache lookup(%s)\n", rsrc
);
599 assert(MUTEX_HELD(&cache_lock
));
600 if (options
& CACHE_REFRESH
) {
601 /* drop lock since update locks cache again */
602 (void) mutex_unlock(&cache_lock
);
603 (void) cache_update(hd
);
604 (void) mutex_lock(&cache_lock
);
607 node
= cache_head
.vc_next
;
608 for (; node
!= &cache_tail
; node
= node
->vc_next
) {
609 if (strcmp(rsrc
, node
->vc_resource
) == 0) {
610 rcm_log_message(RCM_TRACE2
,
611 "Bridge: cache lookup succeeded(%s, %s)\n", rsrc
,
620 * node_free - Free a node from the cache
623 node_free(link_cache_t
*node
)
626 free(node
->vc_resource
);
632 * cache_insert - Insert a resource node in cache
635 cache_insert(link_cache_t
*node
)
637 assert(MUTEX_HELD(&cache_lock
));
639 /* insert at the head for best performance */
640 node
->vc_next
= cache_head
.vc_next
;
641 node
->vc_prev
= &cache_head
;
643 node
->vc_next
->vc_prev
= node
;
644 node
->vc_prev
->vc_next
= node
;
648 * cache_remove() - Remove a resource node from cache.
651 cache_remove(link_cache_t
*node
)
653 assert(MUTEX_HELD(&cache_lock
));
654 node
->vc_next
->vc_prev
= node
->vc_prev
;
655 node
->vc_prev
->vc_next
= node
->vc_next
;
656 node
->vc_next
= NULL
;
657 node
->vc_prev
= NULL
;
660 typedef struct bridge_update_arg_s
{
663 } bridge_update_arg_t
;
666 * bridge_update() - Update physical interface properties
669 bridge_update(dladm_handle_t handle
, datalink_id_t linkid
, void *arg
)
671 bridge_update_arg_t
*bua
= arg
;
672 rcm_handle_t
*hd
= bua
->hd
;
675 dladm_status_t status
;
676 char errmsg
[DLADM_STRSIZE
];
677 char bridge
[MAXLINKNAMELEN
];
678 int ret
= RCM_FAILURE
;
680 rcm_log_message(RCM_TRACE2
, "Bridge: bridge_update(%u)\n", linkid
);
682 assert(MUTEX_HELD(&cache_lock
));
683 status
= dladm_bridge_getlink(dld_handle
, linkid
, bridge
,
685 if (status
!= DLADM_STATUS_OK
) {
686 rcm_log_message(RCM_TRACE1
,
687 "Bridge: no bridge information for %u (%s)\n",
688 linkid
, dladm_status2str(status
, errmsg
));
689 return (DLADM_WALK_CONTINUE
);
692 (void) asprintf(&rsrc
, "%s/%u", RCM_LINK_PREFIX
, linkid
);
694 rcm_log_message(RCM_ERROR
,
695 _("Bridge: allocation failure: %s %u: %s\n"),
696 bridge
, linkid
, strerror(errno
));
700 node
= cache_lookup(hd
, rsrc
, CACHE_NO_REFRESH
);
702 rcm_log_message(RCM_DEBUG
, "Bridge: %s already registered\n",
705 node
->vc_state
&= ~CACHE_NODE_STALE
;
707 rcm_log_message(RCM_DEBUG
,
708 "Bridge: %s is a new resource (bridge %s)\n",
710 if ((node
= calloc(1, sizeof (link_cache_t
))) == NULL
) {
712 rcm_log_message(RCM_ERROR
, _("Bridge: calloc: %s\n"),
717 node
->vc_resource
= rsrc
;
718 node
->vc_linkid
= linkid
;
719 (void) strlcpy(node
->vc_bridge
, bridge
,
720 sizeof (node
->vc_bridge
));
721 node
->vc_state
|= CACHE_NODE_NEW
;
725 rcm_log_message(RCM_TRACE3
, "Bridge: bridge_update: succeeded(%u %s)\n",
726 linkid
, node
->vc_bridge
);
730 return (ret
== RCM_SUCCESS
? DLADM_WALK_CONTINUE
:
731 DLADM_WALK_TERMINATE
);
735 * cache_update() - Update cache with latest interface info
738 cache_update(rcm_handle_t
*hd
)
740 link_cache_t
*node
, *nnode
;
742 bridge_update_arg_t bua
;
744 rcm_log_message(RCM_TRACE2
, "Bridge: cache_update\n");
746 (void) mutex_lock(&cache_lock
);
748 /* first we walk the entire cache, marking each entry stale */
749 node
= cache_head
.vc_next
;
750 for (; node
!= &cache_tail
; node
= node
->vc_next
)
751 node
->vc_state
|= CACHE_NODE_STALE
;
753 /* now walk the links and update all of the entries */
755 bua
.retval
= RCM_SUCCESS
;
756 (void) dladm_walk_datalink_id(bridge_update
, dld_handle
, &bua
,
757 DATALINK_CLASS_AGGR
| DATALINK_CLASS_PHYS
|
758 DATALINK_CLASS_ETHERSTUB
, DATALINK_ANY_MEDIATYPE
, DLADM_OPT_ACTIVE
);
762 * Continue to delete all stale nodes from the cache even if the walk
763 * above failed. Unregister links that are not offlined and still in
766 for (node
= cache_head
.vc_next
; node
!= &cache_tail
; node
= nnode
) {
767 nnode
= node
->vc_next
;
769 if (node
->vc_state
& CACHE_NODE_STALE
) {
770 (void) rcm_unregister_interest(hd
, node
->vc_resource
,
772 rcm_log_message(RCM_DEBUG
,
773 "Bridge: unregistered %s %s\n",
774 node
->vc_resource
, node
->vc_bridge
);
780 if (!(node
->vc_state
& CACHE_NODE_NEW
))
783 rv
= rcm_register_interest(hd
, node
->vc_resource
, 0, NULL
);
784 if (rv
!= RCM_SUCCESS
) {
785 rcm_log_message(RCM_ERROR
,
786 _("Bridge: failed to register %s\n"),
790 rcm_log_message(RCM_DEBUG
, "Bridge: registered %s\n",
792 node
->vc_state
&= ~CACHE_NODE_NEW
;
796 (void) mutex_unlock(&cache_lock
);
801 * cache_free() - Empty the cache
808 rcm_log_message(RCM_TRACE2
, "Bridge: cache_free\n");
810 (void) mutex_lock(&cache_lock
);
811 node
= cache_head
.vc_next
;
812 while (node
!= &cache_tail
) {
815 node
= cache_head
.vc_next
;
817 (void) mutex_unlock(&cache_lock
);
821 * bridge_log_err() - RCM error log wrapper
824 bridge_log_err(datalink_id_t linkid
, char **errorp
, char *errmsg
)
826 char link
[MAXLINKNAMELEN
];
827 char errstr
[DLADM_STRSIZE
];
828 dladm_status_t status
;
832 if (linkid
!= DATALINK_INVALID_LINKID
) {
833 char rsrc
[RCM_LINK_RESOURCE_MAX
];
835 (void) snprintf(rsrc
, sizeof (rsrc
), "%s/%u",
836 RCM_LINK_PREFIX
, linkid
);
838 rcm_log_message(RCM_ERROR
, _("Bridge: %s(%s)\n"), errmsg
, rsrc
);
839 if ((status
= dladm_datalink_id2info(dld_handle
, linkid
, NULL
,
840 NULL
, NULL
, link
, sizeof (link
))) != DLADM_STATUS_OK
) {
841 rcm_log_message(RCM_WARNING
,
842 _("Bridge: cannot get link name for (%s) %s\n"),
843 rsrc
, dladm_status2str(status
, errstr
));
846 rcm_log_message(RCM_ERROR
, _("Bridge: %s\n"), errmsg
);
850 (void) asprintf(&error
, _("Bridge: %s(%s)"), errmsg
, link
);
852 (void) asprintf(&error
, _("Bridge: %s"), errmsg
);
859 * bridge_configure() - Configure bridge on a physical link after it attaches
862 bridge_configure(rcm_handle_t
*hd
, datalink_id_t linkid
)
864 char rsrc
[RCM_LINK_RESOURCE_MAX
];
866 char bridge
[MAXLINKNAMELEN
];
868 /* Check for the bridge links in the cache */
869 (void) snprintf(rsrc
, sizeof (rsrc
), "%s/%u", RCM_LINK_PREFIX
, linkid
);
871 rcm_log_message(RCM_TRACE2
, "Bridge: bridge_configure(%s)\n", rsrc
);
873 /* Check if the link is new or was previously offlined */
874 (void) mutex_lock(&cache_lock
);
875 if (((node
= cache_lookup(hd
, rsrc
, CACHE_REFRESH
)) != NULL
) &&
876 (!(node
->vc_state
& CACHE_NODE_OFFLINED
))) {
877 rcm_log_message(RCM_TRACE2
,
878 "Bridge: Skipping configured interface(%s)\n", rsrc
);
879 (void) mutex_unlock(&cache_lock
);
880 return (RCM_SUCCESS
);
882 (void) mutex_unlock(&cache_lock
);
884 /* clear out previous bridge, if any */
885 if (dladm_bridge_getlink(dld_handle
, linkid
, bridge
, sizeof (bridge
)) ==
887 if (bridge
[0] != '\0')
888 (void) dladm_bridge_setlink(dld_handle
, linkid
, "");
891 /* now set up the new one */
892 if (node
!= NULL
&& node
->vc_bridge
[0] != '\0' &&
893 dladm_bridge_setlink(dld_handle
, linkid
, node
->vc_bridge
) !=
895 return (RCM_FAILURE
);
897 return (RCM_SUCCESS
);