dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / rcm_daemon / common / network_rcm.c
blobc916ea83063f62e719ae8a15b882e44372f1f9e2
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 an abstract
28 * namespace for network devices (DLPI providers).
30 #include <alloca.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <assert.h>
35 #include <string.h>
36 #include <synch.h>
37 #include <libintl.h>
38 #include <errno.h>
39 #include <libdevinfo.h>
40 #include <sys/types.h>
41 #include <net/if.h>
42 #include <libdllink.h>
43 #include "rcm_module.h"
46 * Definitions
48 #define _(x) gettext(x)
50 #define CACHE_STALE 1 /* flags */
51 #define CACHE_NEW 2 /* flags */
53 /* operations */
54 #define NET_OFFLINE 1
55 #define NET_ONLINE 2
56 #define NET_REMOVE 3
57 #define NET_SUSPEND 4
58 #define NET_RESUME 5
60 typedef struct net_cache
62 char *resource;
63 datalink_id_t linkid;
64 int flags;
65 struct net_cache *next;
66 struct net_cache *prev;
67 } net_cache_t;
69 static net_cache_t cache_head;
70 static net_cache_t cache_tail;
71 static mutex_t cache_lock;
72 static int events_registered = 0;
74 static dladm_handle_t dld_handle = NULL;
76 /* module interface routines */
77 static int net_register(rcm_handle_t *);
78 static int net_unregister(rcm_handle_t *);
79 static int net_getinfo(rcm_handle_t *, char *, id_t, uint_t, char **,
80 char **, nvlist_t *, rcm_info_t **);
81 static int net_suspend(rcm_handle_t *, char *, id_t, timespec_t *,
82 uint_t, char **, rcm_info_t **);
83 static int net_resume(rcm_handle_t *, char *, id_t, uint_t, char **,
84 rcm_info_t **);
85 static int net_offline(rcm_handle_t *, char *, id_t, uint_t, char **,
86 rcm_info_t **);
87 static int net_online(rcm_handle_t *, char *, id_t, uint_t, char **,
88 rcm_info_t **);
89 static int net_remove(rcm_handle_t *, char *, id_t, uint_t, char **,
90 rcm_info_t **);
91 static int net_notify_event(rcm_handle_t *, char *, id_t, uint_t,
92 char **, nvlist_t *, rcm_info_t **);
94 /* module private routines */
95 static void free_cache(void);
96 static void update_cache(rcm_handle_t *hd);
97 static int devfs_entry(di_node_t node, di_minor_t minor, void *arg);
98 static void cache_remove(net_cache_t *node);
99 static net_cache_t *cache_lookup(const char *resource);
100 static void free_node(net_cache_t *);
101 static void cache_insert(net_cache_t *);
104 * Module-Private data
106 static struct rcm_mod_ops net_ops = {
107 RCM_MOD_OPS_VERSION,
108 net_register,
109 net_unregister,
110 net_getinfo,
111 net_suspend,
112 net_resume,
113 net_offline,
114 net_online,
115 net_remove,
116 NULL,
117 NULL,
118 net_notify_event
122 * Module Interface Routines
126 * rcm_mod_init()
128 * Update registrations, and return the ops structure.
130 struct rcm_mod_ops *
131 rcm_mod_init(void)
133 dladm_status_t status;
134 char errmsg[DLADM_STRSIZE];
136 cache_head.next = &cache_tail;
137 cache_head.prev = NULL;
138 cache_tail.prev = &cache_head;
139 cache_tail.next = NULL;
140 (void) mutex_init(&cache_lock, 0, NULL);
142 if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) {
143 rcm_log_message(RCM_WARNING,
144 "NET: mod_init failed: cannot open datalink handle: %s\n",
145 dladm_status2str(status, errmsg));
146 return (NULL);
149 /* Return the ops vectors */
150 return (&net_ops);
154 * rcm_mod_info()
156 * Return a string describing this module.
158 const char *
159 rcm_mod_info(void)
161 return ("Network namespace module 1.13");
165 * rcm_mod_fini()
167 * Destroy the cache.
170 rcm_mod_fini(void)
172 free_cache();
173 (void) mutex_destroy(&cache_lock);
175 dladm_close(dld_handle);
176 return (RCM_SUCCESS);
180 * net_register()
182 * Make sure the cache is properly sync'ed, and its registrations
183 * are in order.
185 * Locking: the cache is locked by update_cache, and is held
186 * throughout update_cache's execution because it reads and
187 * possibly modifies cache links continuously.
189 static int
190 net_register(rcm_handle_t *hd)
192 update_cache(hd);
194 * Need to register interest in all new resources
195 * getting attached, so we get attach event notifications
197 if (!events_registered) {
198 if (rcm_register_event(hd, RCM_RESOURCE_PHYSLINK_NEW, 0, NULL)
199 != RCM_SUCCESS) {
200 rcm_log_message(RCM_ERROR,
201 _("NET: failed to register %s\n"),
202 RCM_RESOURCE_PHYSLINK_NEW);
203 return (RCM_FAILURE);
204 } else {
205 rcm_log_message(RCM_DEBUG, _("NET: registered %s \n"),
206 RCM_RESOURCE_PHYSLINK_NEW);
207 events_registered++;
211 return (RCM_SUCCESS);
215 * net_unregister()
217 * Manually walk through the cache, unregistering all the networks.
219 * Locking: the cache is locked throughout the execution of this routine
220 * because it reads and modifies cache links continuously.
222 static int
223 net_unregister(rcm_handle_t *hd)
225 net_cache_t *probe;
227 assert(hd != NULL);
229 /* Walk the cache, unregistering everything */
230 (void) mutex_lock(&cache_lock);
231 probe = cache_head.next;
232 while (probe != &cache_tail) {
233 (void) rcm_unregister_interest(hd, probe->resource, 0);
234 cache_remove(probe);
235 free_node(probe);
236 probe = cache_head.next;
238 (void) mutex_unlock(&cache_lock);
241 * Need to unregister interest in all new resources
243 if (events_registered) {
244 if (rcm_unregister_event(hd, RCM_RESOURCE_PHYSLINK_NEW, 0)
245 != RCM_SUCCESS) {
246 rcm_log_message(RCM_ERROR,
247 _("NET: failed to unregister %s\n"),
248 RCM_RESOURCE_PHYSLINK_NEW);
249 return (RCM_FAILURE);
250 } else {
251 rcm_log_message(RCM_DEBUG, _("NET: unregistered %s\n"),
252 RCM_RESOURCE_PHYSLINK_NEW);
253 events_registered--;
257 return (RCM_SUCCESS);
261 * Since all we do is pass operations thru, we provide a general
262 * routine for passing through operations.
264 /*ARGSUSED*/
265 static int
266 net_passthru(rcm_handle_t *hd, int op, const char *rsrc, uint_t flag,
267 char **reason, rcm_info_t **dependent_reason, void *arg)
269 net_cache_t *node;
270 char *exported;
271 datalink_id_t linkid;
272 int len;
273 int rv;
276 * Lock the cache just long enough to extract information about this
277 * resource.
279 (void) mutex_lock(&cache_lock);
280 node = cache_lookup(rsrc);
281 if (!node) {
282 rcm_log_message(RCM_WARNING,
283 _("NET: unrecognized resource %s\n"), rsrc);
284 (void) mutex_unlock(&cache_lock);
285 return (RCM_SUCCESS);
289 * Since node could be freed after we drop cache_lock, allocate a
290 * stack-local copy. We don't use malloc() because some of the
291 * operations (such as NET_REMOVE) are not allowed to fail. Note
292 * that exported is never more than MAXPATHLEN bytes.
294 len = strlen("SUNW_datalink/") + LINKID_STR_WIDTH + 1;
295 exported = alloca(len);
296 linkid = node->linkid;
297 (void) snprintf(exported, len, "SUNW_datalink/%u", linkid);
300 * Remove notifications are unconditional in the RCM state model,
301 * so it's safe to remove the node from the cache at this point.
302 * And we need to remove it so that we will recognize it as a new
303 * resource following the reattachment of the resource.
305 if (op == NET_REMOVE) {
306 cache_remove(node);
307 free_node(node);
309 (void) mutex_unlock(&cache_lock);
311 switch (op) {
312 case NET_SUSPEND:
313 rv = rcm_request_suspend(hd, exported, flag,
314 (timespec_t *)arg, dependent_reason);
315 break;
316 case NET_OFFLINE:
317 rv = rcm_request_offline(hd, exported, flag, dependent_reason);
318 break;
319 case NET_ONLINE:
320 rv = rcm_notify_online(hd, exported, flag, dependent_reason);
321 break;
322 case NET_REMOVE:
323 rv = rcm_notify_remove(hd, exported, flag, dependent_reason);
324 if (rv == RCM_SUCCESS) {
325 rcm_log_message(RCM_DEBUG,
326 _("NET: mark link %d as removed\n"), linkid);
329 * Delete active linkprop before this active link
330 * is deleted.
332 (void) dladm_set_linkprop(dld_handle, linkid, NULL,
333 NULL, 0, DLADM_OPT_ACTIVE);
334 (void) dladm_destroy_datalink_id(dld_handle, linkid,
335 DLADM_OPT_ACTIVE);
337 break;
338 case NET_RESUME:
339 rv = rcm_notify_resume(hd, exported, flag, dependent_reason);
340 break;
341 default:
342 rcm_log_message(RCM_WARNING,
343 _("NET: bad RCM operation %1$d for %2$s\n"), op, exported);
344 errno = EINVAL;
345 return (RCM_FAILURE);
348 if (rv != RCM_SUCCESS) {
349 char format[256];
350 (void) snprintf(format, sizeof (format),
351 _("RCM operation on dependent %s did not succeed"),
352 exported);
353 rcm_log_message(RCM_WARNING, "NET: %s\n", format);
355 return (rv);
360 * net_offline()
362 * Determine dependents of the resource being offlined, and offline
363 * them all.
365 static int
366 net_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
367 char **reason, rcm_info_t **dependent_reason)
369 assert(hd != NULL);
370 assert(rsrc != NULL);
371 assert(id == (id_t)0);
372 assert(reason != NULL);
373 assert(dependent_reason != NULL);
375 rcm_log_message(RCM_TRACE1, _("NET: offline(%s)\n"), rsrc);
377 return (net_passthru(hd, NET_OFFLINE, rsrc, flags, reason,
378 dependent_reason, NULL));
382 * net_online()
384 * Online the previously offlined resource, and online its dependents.
386 static int
387 net_online(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flag, char **reason,
388 rcm_info_t **dependent_reason)
390 assert(hd != NULL);
391 assert(rsrc != NULL);
392 assert(id == (id_t)0);
394 rcm_log_message(RCM_TRACE1, _("NET: online(%s)\n"), rsrc);
396 return (net_passthru(hd, NET_ONLINE, rsrc, flag, reason,
397 dependent_reason, NULL));
401 * net_getinfo()
403 * Gather usage information for this resource.
405 * Locking: the cache is locked while this routine looks up the
406 * resource and extracts copies of any piece of information it needs.
407 * The cache is then unlocked, and this routine performs the rest of
408 * its functions without touching any part of the cache.
410 /*ARGSUSED*/
411 static int
412 net_getinfo(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flag,
413 char **info, char **errstr, nvlist_t *proplist, rcm_info_t **depend_info)
415 int len;
416 dladm_status_t status;
417 char link[MAXLINKNAMELEN];
418 char errmsg[DLADM_STRSIZE];
419 char *exported;
420 const char *info_fmt;
421 net_cache_t *node;
423 assert(hd != NULL);
424 assert(rsrc != NULL);
425 assert(id == (id_t)0);
426 assert(info != NULL);
427 assert(depend_info != NULL);
429 rcm_log_message(RCM_TRACE1, _("NET: getinfo(%s)\n"), rsrc);
431 info_fmt = _("Network interface %s");
433 (void) mutex_lock(&cache_lock);
434 node = cache_lookup(rsrc);
435 if (!node) {
436 rcm_log_message(RCM_WARNING,
437 _("NET: unrecognized resource %s\n"), rsrc);
438 (void) mutex_unlock(&cache_lock);
439 errno = ENOENT;
440 return (RCM_FAILURE);
443 len = strlen(info_fmt) + MAXLINKNAMELEN + 1;
444 if ((status = dladm_datalink_id2info(dld_handle, node->linkid, NULL,
445 NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
446 rcm_log_message(RCM_ERROR,
447 _("NET: usage(%s) get link name failure(%s)\n"),
448 node->resource, dladm_status2str(status, errmsg));
449 (void) mutex_unlock(&cache_lock);
450 return (RCM_FAILURE);
451 } else if ((*info = (char *)malloc(len)) == NULL) {
452 rcm_log_message(RCM_ERROR, _("NET: malloc failure"));
453 (void) mutex_unlock(&cache_lock);
454 return (RCM_FAILURE);
457 /* Fill in the string */
458 (void) snprintf(*info, len, info_fmt, link);
460 len = strlen("SUNW_datalink/") + LINKID_STR_WIDTH + 1;
461 exported = malloc(len);
462 if (!exported) {
463 rcm_log_message(RCM_ERROR, _("NET: allocation failure"));
464 free(*info);
465 (void) mutex_unlock(&cache_lock);
466 return (RCM_FAILURE);
468 (void) snprintf(exported, len, "SUNW_datalink/%u", node->linkid);
469 (void) mutex_unlock(&cache_lock);
471 /* Get dependent info if requested */
472 if ((flag & RCM_INCLUDE_DEPENDENT) || (flag & RCM_INCLUDE_SUBTREE)) {
473 (void) rcm_get_info(hd, exported, flag, depend_info);
476 (void) nvlist_add_string(proplist, RCM_CLIENT_NAME, "SunOS");
477 (void) nvlist_add_string_array(proplist, RCM_CLIENT_EXPORTS,
478 &exported, 1);
480 free(exported);
481 return (RCM_SUCCESS);
485 * net_suspend()
487 * Notify all dependents that the resource is being suspended.
488 * Since no real operation is involved, QUERY or not doesn't matter.
490 * Locking: the cache is only used to retrieve some information about
491 * this resource, so it is only locked during that retrieval.
493 static int
494 net_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval,
495 uint_t flag, char **reason, rcm_info_t **dependent_reason)
497 assert(hd != NULL);
498 assert(rsrc != NULL);
499 assert(id == (id_t)0);
500 assert(interval != NULL);
501 assert(reason != NULL);
502 assert(dependent_reason != NULL);
504 rcm_log_message(RCM_TRACE1, _("NET: suspend(%s)\n"), rsrc);
506 return (net_passthru(hd, NET_SUSPEND, rsrc, flag, reason,
507 dependent_reason, (void *)interval));
511 * net_resume()
513 * Resume all the dependents of a suspended network.
515 * Locking: the cache is only used to retrieve some information about
516 * this resource, so it is only locked during that retrieval.
518 static int
519 net_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flag, char **info,
520 rcm_info_t **dependent_info)
522 assert(hd != NULL);
523 assert(rsrc != NULL);
524 assert(id == (id_t)0);
525 assert(info != NULL);
526 assert(dependent_info != NULL);
528 rcm_log_message(RCM_TRACE1, _("NET: resume(%s)\n"), rsrc);
530 return (net_passthru(hd, NET_RESUME, rsrc, flag, info, dependent_info,
531 NULL));
535 * net_remove()
537 * This is another NO-OP for us, we just passthru the information. We
538 * don't need to remove it from our cache. We don't unregister
539 * interest at this point either; the network device name is still
540 * around. This way we don't have to change this logic when we
541 * gain the ability to learn about DR attach operations.
543 static int
544 net_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flag, char **info,
545 rcm_info_t **dependent_info)
547 assert(hd != NULL);
548 assert(rsrc != NULL);
549 assert(id == (id_t)0);
550 assert(info != NULL);
551 assert(dependent_info != NULL);
553 rcm_log_message(RCM_TRACE1, _("NET: remove(%s)\n"), rsrc);
555 return (net_passthru(hd, NET_REMOVE, rsrc, flag, info, dependent_info,
556 NULL));
560 * Cache management routines. Note that the cache is implemented as a
561 * trivial linked list, and is only required because RCM doesn't
562 * provide enough state about our own registrations back to us. This
563 * linked list implementation probably clobbers the CPU cache pretty
564 * well.
568 * cache_lookup()
570 * Get a cache node for a resource. Call with cache lock held.
572 static net_cache_t *
573 cache_lookup(const char *resource)
575 net_cache_t *probe;
576 probe = cache_head.next;
577 while (probe != &cache_tail) {
578 if (probe->resource &&
579 (strcmp(resource, probe->resource) == 0)) {
580 return (probe);
582 probe = probe->next;
584 return (NULL);
588 * free_node()
590 * Free a node. Make sure it isn't in the list!
592 static void
593 free_node(net_cache_t *node)
595 if (node) {
596 free(node->resource);
597 free(node);
602 * cache_insert()
604 * Call with the cache_lock held.
606 static void
607 cache_insert(net_cache_t *node)
609 /* insert at the head for best performance */
610 node->next = cache_head.next;
611 node->prev = &cache_head;
613 node->next->prev = node;
614 node->prev->next = node;
618 * cache_remove()
620 * Call with the cache_lock held.
622 static void
623 cache_remove(net_cache_t *node)
625 node->next->prev = node->prev;
626 node->prev->next = node->next;
627 node->next = NULL;
628 node->prev = NULL;
632 * devfs_entry()
634 * Call with the cache_lock held.
636 /*ARGSUSED*/
637 static int
638 devfs_entry(di_node_t node, di_minor_t minor, void *arg)
640 char *devfspath;
641 char resource[MAXPATHLEN];
642 char dev[MAXNAMELEN];
643 datalink_id_t linkid;
644 char *drv;
645 char *cp;
646 net_cache_t *probe;
648 cp = di_minor_nodetype(minor);
649 if ((cp == NULL) || (strcmp(cp, DDI_NT_NET))) {
650 /* doesn't look like a network device */
651 return (DI_WALK_CONTINUE);
654 drv = di_driver_name(node);
655 if (drv == NULL) {
656 /* what else can we do? */
657 return (DI_WALK_CONTINUE);
660 devfspath = di_devfs_path(node);
661 if (!devfspath) {
662 /* no devfs path?!? */
663 rcm_log_message(RCM_DEBUG, _("NET: missing devfs path\n"));
664 return (DI_WALK_CONTINUE);
667 if (strncmp("/pseudo", devfspath, strlen("/pseudo")) == 0) {
668 /* ignore pseudo devices, probably not really NICs */
669 rcm_log_message(RCM_DEBUG,
670 _("NET: ignoring pseudo device %s\n"), devfspath);
671 di_devfs_path_free(devfspath);
672 return (DI_WALK_CONTINUE);
675 (void) snprintf(resource, sizeof (resource), "/devices%s", devfspath);
676 di_devfs_path_free(devfspath);
678 (void) snprintf(dev, sizeof (dev), "%s%d", drv, di_instance(node));
679 if (dladm_dev2linkid(dld_handle, dev, &linkid) != DLADM_STATUS_OK) {
680 rcm_log_message(RCM_DEBUG,
681 _("NET: failed to find the linkid for %s\n"), dev);
682 return (DI_WALK_CONTINUE);
685 probe = cache_lookup(resource);
686 if (probe != NULL) {
687 rcm_log_message(RCM_DEBUG,
688 _("NET: %s already registered (linkid %u)\n"),
689 resource, linkid);
690 probe->linkid = linkid;
691 probe->flags &= ~(CACHE_STALE);
692 } else {
693 rcm_log_message(RCM_DEBUG,
694 _("NET: %s is new resource (linkid %u)\n"),
695 resource, linkid);
696 probe = calloc(1, sizeof (net_cache_t));
697 if (!probe) {
698 rcm_log_message(RCM_ERROR, _("NET: malloc failure"));
699 return (DI_WALK_CONTINUE);
702 probe->resource = strdup(resource);
703 probe->linkid = linkid;
705 if (!probe->resource) {
706 free_node(probe);
707 return (DI_WALK_CONTINUE);
710 probe->flags |= CACHE_NEW;
711 cache_insert(probe);
714 return (DI_WALK_CONTINUE);
718 * update_cache()
720 * The devinfo tree walking code is lifted from ifconfig.c.
722 static void
723 update_cache(rcm_handle_t *hd)
725 net_cache_t *probe;
726 di_node_t root;
727 int rv;
729 (void) mutex_lock(&cache_lock);
731 /* first we walk the entire cache, marking each entry stale */
732 probe = cache_head.next;
733 while (probe != &cache_tail) {
734 probe->flags |= CACHE_STALE;
735 probe = probe->next;
738 root = di_init("/", DINFOSUBTREE | DINFOMINOR);
739 if (root == DI_NODE_NIL) {
740 goto done;
743 (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, NULL,
744 devfs_entry);
746 di_fini(root);
748 probe = cache_head.next;
749 while (probe != &cache_tail) {
750 net_cache_t *freeit;
751 if (probe->flags & CACHE_STALE) {
752 (void) rcm_unregister_interest(hd, probe->resource, 0);
753 rcm_log_message(RCM_DEBUG, _("NET: unregistered %s\n"),
754 probe->resource);
755 freeit = probe;
756 probe = probe->next;
757 cache_remove(freeit);
758 free_node(freeit);
759 continue;
762 if (!(probe->flags & CACHE_NEW)) {
763 probe = probe->next;
764 continue;
767 rcm_log_message(RCM_DEBUG, _("NET: registering %s\n"),
768 probe->resource);
769 rv = rcm_register_interest(hd, probe->resource, 0, NULL);
770 if (rv != RCM_SUCCESS) {
771 rcm_log_message(RCM_ERROR,
772 _("NET: failed to register %s\n"),
773 probe->resource);
774 } else {
775 rcm_log_message(RCM_DEBUG,
776 _("NET: registered %s as SUNW_datalink/%u\n"),
777 probe->resource, probe->linkid);
778 probe->flags &= ~(CACHE_NEW);
780 probe = probe->next;
783 done:
784 (void) mutex_unlock(&cache_lock);
788 * free_cache()
790 static void
791 free_cache(void)
793 net_cache_t *probe;
795 (void) mutex_lock(&cache_lock);
796 probe = cache_head.next;
797 while (probe != &cache_tail) {
798 cache_remove(probe);
799 free_node(probe);
800 probe = cache_head.next;
802 (void) mutex_unlock(&cache_lock);
806 * net_notify_event - Project private implementation to receive new
807 * resource events. It intercepts all new resource
808 * events. If the new resource is a network resource,
809 * update the physical link cache.
811 /*ARGSUSED*/
812 static int
813 net_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
814 char **errorp, nvlist_t *nvl, rcm_info_t **depend_info)
816 nvpair_t *nvp = NULL;
817 uint64_t id64 = (uint64_t)DATALINK_INVALID_LINKID;
818 boolean_t reconfigured = B_FALSE;
820 rcm_log_message(RCM_TRACE1, _("NET: notify_event(%s)\n"), rsrc);
822 if (strcmp(rsrc, RCM_RESOURCE_PHYSLINK_NEW) != 0) {
823 rcm_log_message(RCM_INFO,
824 _("NET: unrecognized event for %s\n"), rsrc);
825 errno = EINVAL;
826 return (RCM_FAILURE);
829 /* Update cache to reflect latest physical links */
830 update_cache(hd);
832 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
833 if (strcmp(nvpair_name(nvp), RCM_NV_RECONFIGURED) == 0) {
834 if (nvpair_value_boolean_value(nvp,
835 &reconfigured) != 0) {
836 rcm_log_message(RCM_INFO,
837 _("NET: unrecognized %s event data\n"),
838 RCM_NV_RECONFIGURED);
839 errno = EINVAL;
840 return (RCM_FAILURE);
843 rcm_log_message(RCM_TRACE1,
844 "NET: %s event data (%sreconfiguration)\n",
845 RCM_NV_RECONFIGURED, reconfigured ? "" : "not ");
848 if (strcmp(nvpair_name(nvp), RCM_NV_LINKID) == 0) {
849 if (nvpair_value_uint64(nvp, &id64) != 0) {
850 rcm_log_message(RCM_INFO,
851 _("NET: unrecognized %s event data\n"),
852 RCM_NV_LINKID);
853 errno = EINVAL;
854 return (RCM_FAILURE);
857 rcm_log_message(RCM_TRACE1,
858 "NET: %s event data (linkid %d)\n", RCM_NV_LINKID,
859 (datalink_id_t)id64);
863 if ((datalink_id_t)id64 == DATALINK_INVALID_LINKID) {
864 rcm_log_message(RCM_INFO, _("NET: invalid datalink\n"));
865 errno = EINVAL;
866 return (RCM_FAILURE);
870 * If this is device reconfiguration, populate the LINK_NEW event
871 * to start the DR process.
873 if (reconfigured) {
874 nvlist_t *nnvl = NULL;
876 rcm_log_message(RCM_TRACE1,
877 "NET: reconfigured data-link (id %d)\n",
878 (datalink_id_t)id64);
880 if ((nvlist_alloc(&nnvl, 0, 0) != 0) || (nvlist_add_uint64(nnvl,
881 RCM_NV_LINKID, id64) != 0) || (rcm_notify_event(hd,
882 RCM_RESOURCE_LINK_NEW, 0, nnvl, NULL) != RCM_SUCCESS)) {
883 nvlist_free(nnvl);
884 rcm_log_message(RCM_INFO,
885 _("NET: notify %s event failed\n"),
886 RCM_RESOURCE_LINK_NEW);
887 errno = EINVAL;
888 return (RCM_FAILURE);
890 nvlist_free(nnvl);
893 rcm_log_message(RCM_TRACE1,
894 _("NET: notify_event: device configuration complete\n"));
896 return (RCM_SUCCESS);