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.
26 * Copyright (c) 2016 by Delphix. All rights reserved.
30 * Datalink management routines.
33 #include <sys/types.h>
36 #include <sys/modctl.h>
38 #include <sys/modhash.h>
39 #include <sys/kstat.h>
40 #include <sys/vnode.h>
41 #include <sys/cmn_err.h>
42 #include <sys/softmac.h>
44 #include <sys/dls_impl.h>
45 #include <sys/stropts.h>
46 #include <sys/netstack.h>
47 #include <inet/iptun/iptun_impl.h>
50 * This vanity name management module is treated as part of the GLD framework
51 * and we don't hold any GLD framework lock across a call to any mac
52 * function that needs to acquire the mac perimeter. The hierarchy is
53 * mac perimeter -> framework locks
56 typedef struct dls_stack
{
60 static kmem_cache_t
*i_dls_devnet_cachep
;
61 static kmutex_t i_dls_mgmt_lock
;
62 static krwlock_t i_dls_devnet_lock
;
63 static mod_hash_t
*i_dls_devnet_id_hash
;
64 static mod_hash_t
*i_dls_devnet_hash
;
66 boolean_t devnet_need_rebuild
;
68 #define VLAN_HASHSZ 67 /* prime */
71 * The following macros take a link name without the trailing PPA as input.
72 * Opening a /dev/net node with one of these names causes a tunnel link to be
73 * implicitly created in dls_devnet_hold_by_name() for backward compatibility
74 * with Solaris 10 and prior.
76 #define IS_IPV4_TUN(name) (strcmp((name), "ip.tun") == 0)
77 #define IS_IPV6_TUN(name) (strcmp((name), "ip6.tun") == 0)
78 #define IS_6TO4_TUN(name) (strcmp((name), "ip.6to4tun") == 0)
79 #define IS_IPTUN_LINK(name) ( \
80 IS_IPV4_TUN(name) || IS_IPV6_TUN(name) || IS_6TO4_TUN(name))
82 /* Upcall door handle */
83 static door_handle_t dls_mgmt_dh
= NULL
;
85 /* dls_devnet_t dd_flags */
86 #define DD_CONDEMNED 0x1
87 #define DD_IMPLICIT_IPTUN 0x2 /* Implicitly-created ip*.*tun* tunnel */
90 * This structure is used to keep the <linkid, macname> mapping.
91 * This structure itself is not protected by the mac perimeter, but is
92 * protected by the dd_mutex and i_dls_devnet_lock. Thus most of the
93 * functions manipulating this structure such as dls_devnet_set/unset etc.
94 * may be called while not holding the mac perimeter.
96 typedef struct dls_devnet_s
{
97 datalink_id_t dd_linkid
;
98 char dd_linkname
[MAXLINKNAMELEN
];
99 char dd_mac
[MAXNAMELEN
];
100 kstat_t
*dd_ksp
; /* kstat in owner_zid */
101 kstat_t
*dd_zone_ksp
; /* in dd_zid if != owner_zid */
107 zoneid_t dd_owner_zid
; /* zone where node was created */
108 zoneid_t dd_zid
; /* current zone */
109 boolean_t dd_prop_loaded
;
110 taskqid_t dd_prop_taskid
;
113 static int i_dls_devnet_create_iptun(const char *, const char *,
115 static int i_dls_devnet_destroy_iptun(datalink_id_t
);
116 static int i_dls_devnet_setzid(dls_devnet_t
*, zoneid_t
, boolean_t
);
117 static int dls_devnet_unset(const char *, datalink_id_t
*, boolean_t
);
121 i_dls_devnet_constructor(void *buf
, void *arg
, int kmflag
)
123 dls_devnet_t
*ddp
= buf
;
125 bzero(buf
, sizeof (dls_devnet_t
));
126 mutex_init(&ddp
->dd_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
127 cv_init(&ddp
->dd_cv
, NULL
, CV_DEFAULT
, NULL
);
133 i_dls_devnet_destructor(void *buf
, void *arg
)
135 dls_devnet_t
*ddp
= buf
;
137 ASSERT(ddp
->dd_ksp
== NULL
);
138 ASSERT(ddp
->dd_ref
== 0);
139 ASSERT(ddp
->dd_tref
== 0);
140 mutex_destroy(&ddp
->dd_mutex
);
141 cv_destroy(&ddp
->dd_cv
);
146 dls_zone_remove(datalink_id_t linkid
, void *arg
)
150 if (dls_devnet_hold_tmp(linkid
, &ddp
) == 0) {
151 (void) dls_devnet_setzid(ddp
, GLOBAL_ZONEID
);
152 dls_devnet_rele_tmp(ddp
);
159 dls_stack_init(netstackid_t stackid
, netstack_t
*ns
)
163 dlss
= kmem_zalloc(sizeof (*dlss
), KM_SLEEP
);
164 dlss
->dlss_zoneid
= netstackid_to_zoneid(stackid
);
170 dls_stack_shutdown(netstackid_t stackid
, void *arg
)
172 dls_stack_t
*dlss
= (dls_stack_t
*)arg
;
174 /* Move remaining datalinks in this zone back to the global zone. */
175 (void) zone_datalink_walk(dlss
->dlss_zoneid
, dls_zone_remove
, NULL
);
180 dls_stack_fini(netstackid_t stackid
, void *arg
)
182 dls_stack_t
*dlss
= (dls_stack_t
*)arg
;
184 kmem_free(dlss
, sizeof (*dlss
));
188 * Module initialization and finalization functions.
193 mutex_init(&i_dls_mgmt_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
194 rw_init(&i_dls_devnet_lock
, NULL
, RW_DEFAULT
, NULL
);
197 * Create a kmem_cache of dls_devnet_t structures.
199 i_dls_devnet_cachep
= kmem_cache_create("dls_devnet_cache",
200 sizeof (dls_devnet_t
), 0, i_dls_devnet_constructor
,
201 i_dls_devnet_destructor
, NULL
, NULL
, NULL
, 0);
202 ASSERT(i_dls_devnet_cachep
!= NULL
);
205 * Create a hash table, keyed by dd_linkid, of dls_devnet_t.
207 i_dls_devnet_id_hash
= mod_hash_create_idhash("dls_devnet_id_hash",
208 VLAN_HASHSZ
, mod_hash_null_valdtor
);
211 * Create a hash table, keyed by dd_mac
213 i_dls_devnet_hash
= mod_hash_create_extended("dls_devnet_hash",
214 VLAN_HASHSZ
, mod_hash_null_keydtor
, mod_hash_null_valdtor
,
215 mod_hash_bystr
, NULL
, mod_hash_strkey_cmp
, KM_SLEEP
);
217 devnet_need_rebuild
= B_FALSE
;
219 netstack_register(NS_DLS
, dls_stack_init
, dls_stack_shutdown
,
226 netstack_unregister(NS_DLS
);
227 mod_hash_destroy_hash(i_dls_devnet_hash
);
228 mod_hash_destroy_hash(i_dls_devnet_id_hash
);
229 kmem_cache_destroy(i_dls_devnet_cachep
);
230 rw_destroy(&i_dls_devnet_lock
);
231 mutex_destroy(&i_dls_mgmt_lock
);
235 dls_mgmt_door_set(boolean_t start
)
239 /* handle daemon restart */
240 mutex_enter(&i_dls_mgmt_lock
);
241 if (dls_mgmt_dh
!= NULL
) {
242 door_ki_rele(dls_mgmt_dh
);
246 if (start
&& ((err
= door_ki_open(DLMGMT_DOOR
, &dls_mgmt_dh
)) != 0)) {
247 mutex_exit(&i_dls_mgmt_lock
);
251 mutex_exit(&i_dls_mgmt_lock
);
254 * Create and associate <link name, linkid> mapping for network devices
255 * which are already attached before the daemon is started.
263 i_dls_mgmt_door_revoked(door_handle_t dh
)
265 struct door_info info
;
266 extern int sys_shutdown
;
271 cmn_err(CE_NOTE
, "dls_mgmt_door: shutdown observed\n");
275 if (door_ki_info(dh
, &info
) != 0)
278 return ((info
.di_attributes
& DOOR_REVOKED
) != 0);
282 * Upcall to the datalink management daemon (dlmgmtd).
285 i_dls_mgmt_upcall(void *arg
, size_t asize
, void *rbuf
, size_t rsize
)
287 door_arg_t darg
, save_arg
;
292 #define MAXRETRYNUM 3
296 darg
.data_size
= asize
;
297 darg
.desc_ptr
= NULL
;
304 mutex_enter(&i_dls_mgmt_lock
);
306 if ((dh
== NULL
) || i_dls_mgmt_door_revoked(dh
)) {
307 mutex_exit(&i_dls_mgmt_lock
);
311 mutex_exit(&i_dls_mgmt_lock
);
315 if ((err
= door_ki_upcall_limited(dh
, &darg
, zone_kcred(),
320 * handle door call errors
326 * If the operation which caused this door upcall gets
327 * interrupted, return directly.
332 * Repeat upcall if the maximum attempt limit has not
335 if (retry
< MAXRETRYNUM
) {
339 cmn_err(CE_WARN
, "dls: dlmgmtd fatal error %d\n", err
);
342 /* A fatal door error */
343 if (i_dls_mgmt_door_revoked(dh
)) {
345 "dls: dlmgmtd door service revoked\n");
347 if (retry
< MAXRETRYNUM
) {
352 cmn_err(CE_WARN
, "dls: dlmgmtd fatal error %d\n", err
);
357 if (darg
.rbuf
!= rbuf
) {
359 * The size of the input rbuf was not big enough, so the
360 * upcall allocated the rbuf itself. If this happens, assume
361 * that this was an invalid door call request.
363 kmem_free(darg
.rbuf
, darg
.rsize
);
368 if (darg
.rsize
!= rsize
) {
373 err
= ((dlmgmt_retval_t
*)rbuf
)->lr_err
;
381 * Request the datalink management daemon to create a link with the attributes
382 * below. Upon success, zero is returned and linkidp contains the linkid for
383 * the new link; otherwise, an errno is returned.
385 * - dev physical dev_t. required for all physical links,
386 * including GLDv3 links. It will be used to force the
387 * attachment of a physical device, hence the
388 * registration of its mac
389 * - class datalink class
390 * - media type media type; DL_OTHER means unknown
391 * - persist whether to persist the datalink
394 dls_mgmt_create(const char *devname
, dev_t dev
, datalink_class_t
class,
395 uint32_t media
, boolean_t persist
, datalink_id_t
*linkidp
)
397 dlmgmt_upcall_arg_create_t create
;
398 dlmgmt_create_retval_t retval
;
401 create
.ld_cmd
= DLMGMT_CMD_DLS_CREATE
;
402 create
.ld_class
= class;
403 create
.ld_media
= media
;
404 create
.ld_phymaj
= getmajor(dev
);
405 create
.ld_phyinst
= getminor(dev
);
406 create
.ld_persist
= persist
;
407 if (strlcpy(create
.ld_devname
, devname
, sizeof (create
.ld_devname
)) >=
408 sizeof (create
.ld_devname
))
411 if ((err
= i_dls_mgmt_upcall(&create
, sizeof (create
), &retval
,
412 sizeof (retval
))) == 0) {
413 *linkidp
= retval
.lr_linkid
;
419 * Request the datalink management daemon to destroy the specified link.
420 * Returns zero upon success, or an errno upon failure.
423 dls_mgmt_destroy(datalink_id_t linkid
, boolean_t persist
)
425 dlmgmt_upcall_arg_destroy_t destroy
;
426 dlmgmt_destroy_retval_t retval
;
428 destroy
.ld_cmd
= DLMGMT_CMD_DLS_DESTROY
;
429 destroy
.ld_linkid
= linkid
;
430 destroy
.ld_persist
= persist
;
432 return (i_dls_mgmt_upcall(&destroy
, sizeof (destroy
),
433 &retval
, sizeof (retval
)));
437 * Request the datalink management daemon to verify/update the information
438 * for a physical link. Upon success, get its linkid.
440 * - media type media type
441 * - novanity whether this physical datalink supports vanity naming.
442 * physical links that do not use the GLDv3 MAC plugin
443 * cannot suport vanity naming
445 * This function could fail with ENOENT or EEXIST. Two cases return EEXIST:
447 * 1. A link with devname already exists, but the media type does not match.
448 * In this case, mediap will bee set to the media type of the existing link.
449 * 2. A link with devname already exists, but its link name does not match
450 * the device name, although this link does not support vanity naming.
453 dls_mgmt_update(const char *devname
, uint32_t media
, boolean_t novanity
,
454 uint32_t *mediap
, datalink_id_t
*linkidp
)
456 dlmgmt_upcall_arg_update_t update
;
457 dlmgmt_update_retval_t retval
;
460 update
.ld_cmd
= DLMGMT_CMD_DLS_UPDATE
;
462 if (strlcpy(update
.ld_devname
, devname
, sizeof (update
.ld_devname
)) >=
463 sizeof (update
.ld_devname
))
466 update
.ld_media
= media
;
467 update
.ld_novanity
= novanity
;
469 if ((err
= i_dls_mgmt_upcall(&update
, sizeof (update
), &retval
,
470 sizeof (retval
))) == EEXIST
) {
471 *linkidp
= retval
.lr_linkid
;
472 *mediap
= retval
.lr_media
;
473 } else if (err
== 0) {
474 *linkidp
= retval
.lr_linkid
;
481 * Request the datalink management daemon to get the information for a link.
482 * Returns zero upon success, or an errno upon failure.
484 * Only fills in information for argument pointers that are non-NULL.
485 * Note that the link argument is expected to be MAXLINKNAMELEN bytes.
488 dls_mgmt_get_linkinfo(datalink_id_t linkid
, char *link
,
489 datalink_class_t
*classp
, uint32_t *mediap
, uint32_t *flagsp
)
491 dlmgmt_door_getname_t getname
;
492 dlmgmt_getname_retval_t retval
;
495 getname
.ld_cmd
= DLMGMT_CMD_GETNAME
;
496 getname
.ld_linkid
= linkid
;
498 if ((err
= i_dls_mgmt_upcall(&getname
, sizeof (getname
), &retval
,
499 sizeof (retval
))) != 0) {
503 len
= strlen(retval
.lr_link
);
504 if (len
<= 1 || len
>= MAXLINKNAMELEN
)
508 (void) strlcpy(link
, retval
.lr_link
, MAXLINKNAMELEN
);
510 *classp
= retval
.lr_class
;
512 *mediap
= retval
.lr_media
;
514 *flagsp
= retval
.lr_flags
;
519 * Request the datalink management daemon to get the linkid for a link.
520 * Returns a non-zero error code on failure. The linkid argument is only
521 * set on success (when zero is returned.)
524 dls_mgmt_get_linkid(const char *link
, datalink_id_t
*linkid
)
526 dlmgmt_door_getlinkid_t getlinkid
;
527 dlmgmt_getlinkid_retval_t retval
;
530 getlinkid
.ld_cmd
= DLMGMT_CMD_GETLINKID
;
531 (void) strlcpy(getlinkid
.ld_link
, link
, MAXLINKNAMELEN
);
533 if ((err
= i_dls_mgmt_upcall(&getlinkid
, sizeof (getlinkid
), &retval
,
534 sizeof (retval
))) == 0) {
535 *linkid
= retval
.lr_linkid
;
541 dls_mgmt_get_next(datalink_id_t linkid
, datalink_class_t
class,
542 datalink_media_t dmedia
, uint32_t flags
)
544 dlmgmt_door_getnext_t getnext
;
545 dlmgmt_getnext_retval_t retval
;
547 getnext
.ld_cmd
= DLMGMT_CMD_GETNEXT
;
548 getnext
.ld_class
= class;
549 getnext
.ld_dmedia
= dmedia
;
550 getnext
.ld_flags
= flags
;
551 getnext
.ld_linkid
= linkid
;
553 if (i_dls_mgmt_upcall(&getnext
, sizeof (getnext
), &retval
,
554 sizeof (retval
)) != 0) {
555 return (DATALINK_INVALID_LINKID
);
558 return (retval
.lr_linkid
);
562 i_dls_mgmt_get_linkattr(const datalink_id_t linkid
, const char *attr
,
563 void *attrval
, size_t *attrszp
)
565 dlmgmt_upcall_arg_getattr_t getattr
;
566 dlmgmt_getattr_retval_t retval
;
569 getattr
.ld_cmd
= DLMGMT_CMD_DLS_GETATTR
;
570 getattr
.ld_linkid
= linkid
;
571 (void) strlcpy(getattr
.ld_attr
, attr
, MAXLINKATTRLEN
);
573 if ((err
= i_dls_mgmt_upcall(&getattr
, sizeof (getattr
), &retval
,
574 sizeof (retval
))) == 0) {
575 if (*attrszp
< retval
.lr_attrsz
)
577 *attrszp
= retval
.lr_attrsz
;
578 bcopy(retval
.lr_attrval
, attrval
, retval
.lr_attrsz
);
585 * Note that this function can only get devp successfully for non-VLAN link.
588 dls_mgmt_get_phydev(datalink_id_t linkid
, dev_t
*devp
)
591 size_t attrsz
= sizeof (uint64_t);
593 if (i_dls_mgmt_get_linkattr(linkid
, FPHYMAJ
, &maj
, &attrsz
) != 0 ||
594 attrsz
!= sizeof (uint64_t) ||
595 i_dls_mgmt_get_linkattr(linkid
, FPHYINST
, &inst
, &attrsz
) != 0 ||
596 attrsz
!= sizeof (uint64_t)) {
600 *devp
= makedevice((major_t
)maj
, (minor_t
)inst
);
605 * Request the datalink management daemon to push in
606 * all properties associated with the link.
607 * Returns a non-zero error code on failure.
610 dls_mgmt_linkprop_init(datalink_id_t linkid
)
612 dlmgmt_door_linkprop_init_t li
;
613 dlmgmt_linkprop_init_retval_t retval
;
616 li
.ld_cmd
= DLMGMT_CMD_LINKPROP_INIT
;
617 li
.ld_linkid
= linkid
;
619 err
= i_dls_mgmt_upcall(&li
, sizeof (li
), &retval
, sizeof (retval
));
624 dls_devnet_prop_task(void *arg
)
626 dls_devnet_t
*ddp
= arg
;
628 (void) dls_mgmt_linkprop_init(ddp
->dd_linkid
);
630 mutex_enter(&ddp
->dd_mutex
);
631 ddp
->dd_prop_loaded
= B_TRUE
;
632 ddp
->dd_prop_taskid
= (uintptr_t)NULL
;
633 cv_broadcast(&ddp
->dd_cv
);
634 mutex_exit(&ddp
->dd_mutex
);
638 * Ensure property loading task is completed.
641 dls_devnet_prop_task_wait(dls_dl_handle_t ddp
)
643 mutex_enter(&ddp
->dd_mutex
);
644 while (ddp
->dd_prop_taskid
!= (uintptr_t)NULL
)
645 cv_wait(&ddp
->dd_cv
, &ddp
->dd_mutex
);
646 mutex_exit(&ddp
->dd_mutex
);
650 dls_devnet_rele_tmp(dls_dl_handle_t dlh
)
652 dls_devnet_t
*ddp
= dlh
;
654 mutex_enter(&ddp
->dd_mutex
);
655 ASSERT(ddp
->dd_tref
!= 0);
656 if (--ddp
->dd_tref
== 0)
657 cv_signal(&ddp
->dd_cv
);
658 mutex_exit(&ddp
->dd_mutex
);
662 dls_devnet_hold_link(datalink_id_t linkid
, dls_dl_handle_t
*ddhp
,
669 if ((err
= dls_devnet_hold_tmp(linkid
, &dlh
)) != 0)
672 if ((err
= dls_link_hold(dls_devnet_mac(dlh
), &dlp
)) != 0) {
673 dls_devnet_rele_tmp(dlh
);
677 ASSERT(MAC_PERIM_HELD(dlp
->dl_mh
));
685 dls_devnet_rele_link(dls_dl_handle_t dlh
, dls_link_t
*dlp
)
687 ASSERT(MAC_PERIM_HELD(dlp
->dl_mh
));
690 dls_devnet_rele_tmp(dlh
);
694 * "link" kstats related functions.
698 * Query the "link" kstats.
700 * We may be called from the kstat subsystem in an arbitrary context.
701 * If the caller is the stack, the context could be an upcall data
702 * thread. Hence we can't acquire the mac perimeter in this function
703 * for fear of deadlock.
706 dls_devnet_stat_update(kstat_t
*ksp
, int rw
)
708 datalink_id_t linkid
= (datalink_id_t
)(uintptr_t)ksp
->ks_private
;
713 if ((err
= dls_devnet_hold_tmp(linkid
, &ddp
)) != 0) {
718 * If a device detach happens at this time, it will block in
719 * dls_devnet_unset since the dd_tref has been bumped in
720 * dls_devnet_hold_tmp(). So the access to 'dlp' is safe even though
721 * we don't hold the mac perimeter.
723 if (mod_hash_find(i_dls_link_hash
, (mod_hash_key_t
)ddp
->dd_mac
,
724 (mod_hash_val_t
*)&dlp
) != 0) {
725 dls_devnet_rele_tmp(ddp
);
729 err
= dls_stat_update(ksp
, dlp
, rw
);
731 dls_devnet_rele_tmp(ddp
);
736 * Create the "link" kstats.
739 dls_devnet_stat_create(dls_devnet_t
*ddp
, zoneid_t zoneid
)
743 if (dls_stat_create("link", 0, ddp
->dd_linkname
, zoneid
,
744 dls_devnet_stat_update
, (void *)(uintptr_t)ddp
->dd_linkid
,
747 if (zoneid
== ddp
->dd_owner_zid
) {
748 ASSERT(ddp
->dd_ksp
== NULL
);
751 ASSERT(ddp
->dd_zone_ksp
== NULL
);
752 ddp
->dd_zone_ksp
= ksp
;
758 * Destroy the "link" kstats.
761 dls_devnet_stat_destroy(dls_devnet_t
*ddp
, zoneid_t zoneid
)
763 if (zoneid
== ddp
->dd_owner_zid
) {
764 if (ddp
->dd_ksp
!= NULL
) {
765 kstat_delete(ddp
->dd_ksp
);
769 if (ddp
->dd_zone_ksp
!= NULL
) {
770 kstat_delete(ddp
->dd_zone_ksp
);
771 ddp
->dd_zone_ksp
= NULL
;
777 * The link has been renamed. Destroy the old non-legacy kstats ("link kstats")
778 * and create the new set using the new name.
781 dls_devnet_stat_rename(dls_devnet_t
*ddp
)
783 if (ddp
->dd_ksp
!= NULL
) {
784 kstat_delete(ddp
->dd_ksp
);
787 /* We can't rename a link while it's assigned to a non-global zone. */
788 ASSERT(ddp
->dd_zone_ksp
== NULL
);
789 dls_devnet_stat_create(ddp
, ddp
->dd_owner_zid
);
793 * Associate a linkid with a given link (identified by macname)
796 dls_devnet_set(const char *macname
, datalink_id_t linkid
, zoneid_t zoneid
,
799 dls_devnet_t
*ddp
= NULL
;
800 datalink_class_t
class;
802 boolean_t stat_create
= B_FALSE
;
803 char linkname
[MAXLINKNAMELEN
];
805 rw_enter(&i_dls_devnet_lock
, RW_WRITER
);
808 * Don't allow callers to set a link name with a linkid that already
809 * has a name association (that's what rename is for).
811 if (linkid
!= DATALINK_INVALID_LINKID
) {
812 if (mod_hash_find(i_dls_devnet_id_hash
,
813 (mod_hash_key_t
)(uintptr_t)linkid
,
814 (mod_hash_val_t
*)&ddp
) == 0) {
818 if ((err
= dls_mgmt_get_linkinfo(linkid
, linkname
, &class,
823 if ((err
= mod_hash_find(i_dls_devnet_hash
,
824 (mod_hash_key_t
)macname
, (mod_hash_val_t
*)&ddp
)) == 0) {
825 if (ddp
->dd_linkid
!= DATALINK_INVALID_LINKID
) {
831 * This might be a physical link that has already
832 * been created, but which does not have a linkid
833 * because dlmgmtd was not running when it was created.
835 if (linkid
== DATALINK_INVALID_LINKID
||
836 class != DATALINK_CLASS_PHYS
) {
841 ddp
= kmem_cache_alloc(i_dls_devnet_cachep
, KM_SLEEP
);
844 ddp
->dd_owner_zid
= zoneid
;
845 (void) strlcpy(ddp
->dd_mac
, macname
, sizeof (ddp
->dd_mac
));
846 VERIFY(mod_hash_insert(i_dls_devnet_hash
,
847 (mod_hash_key_t
)ddp
->dd_mac
, (mod_hash_val_t
)ddp
) == 0);
850 if (linkid
!= DATALINK_INVALID_LINKID
) {
851 ddp
->dd_linkid
= linkid
;
852 (void) strlcpy(ddp
->dd_linkname
, linkname
,
853 sizeof (ddp
->dd_linkname
));
854 VERIFY(mod_hash_insert(i_dls_devnet_id_hash
,
855 (mod_hash_key_t
)(uintptr_t)linkid
,
856 (mod_hash_val_t
)ddp
) == 0);
857 devnet_need_rebuild
= B_TRUE
;
858 stat_create
= B_TRUE
;
859 mutex_enter(&ddp
->dd_mutex
);
860 if (!ddp
->dd_prop_loaded
&& (ddp
->dd_prop_taskid
861 == (uintptr_t)NULL
)) {
862 ddp
->dd_prop_taskid
= taskq_dispatch(system_taskq
,
863 dls_devnet_prop_task
, ddp
, TQ_SLEEP
);
865 mutex_exit(&ddp
->dd_mutex
);
870 * It is safe to drop the i_dls_devnet_lock at this point. In the case
871 * of physical devices, the softmac framework will fail the device
872 * detach based on the smac_state or smac_hold_cnt. Other cases like
873 * vnic and aggr use their own scheme to serialize creates and deletes
874 * and ensure that *ddp is valid.
876 rw_exit(&i_dls_devnet_lock
);
878 if (zoneid
!= GLOBAL_ZONEID
&&
879 (err
= i_dls_devnet_setzid(ddp
, zoneid
, B_FALSE
)) != 0)
880 (void) dls_devnet_unset(macname
, &linkid
, B_TRUE
);
882 * The kstat subsystem holds its own locks (rather perimeter)
883 * before calling the ks_update (dls_devnet_stat_update) entry
884 * point which in turn grabs the i_dls_devnet_lock. So the
885 * lock hierarchy is kstat locks -> i_dls_devnet_lock.
888 dls_devnet_stat_create(ddp
, zoneid
);
896 * Disassociate a linkid with a given link (identified by macname)
897 * This waits until temporary references to the dls_devnet_t are gone.
900 dls_devnet_unset(const char *macname
, datalink_id_t
*id
, boolean_t wait
)
906 rw_enter(&i_dls_devnet_lock
, RW_WRITER
);
907 if ((err
= mod_hash_find(i_dls_devnet_hash
,
908 (mod_hash_key_t
)macname
, (mod_hash_val_t
*)&ddp
)) != 0) {
909 ASSERT(err
== MH_ERR_NOTFOUND
);
910 rw_exit(&i_dls_devnet_lock
);
914 mutex_enter(&ddp
->dd_mutex
);
917 * Make sure downcalls into softmac_create or softmac_destroy from
918 * devfs don't cv_wait on any devfs related condition for fear of
919 * deadlock. Return EBUSY if the asynchronous thread started for
920 * property loading as part of the post attach hasn't yet completed.
922 ASSERT(ddp
->dd_ref
!= 0);
923 if ((ddp
->dd_ref
!= 1) || (!wait
&&
924 (ddp
->dd_tref
!= 0 || ddp
->dd_prop_taskid
!= (uintptr_t)NULL
))) {
925 mutex_exit(&ddp
->dd_mutex
);
926 rw_exit(&i_dls_devnet_lock
);
930 ddp
->dd_flags
|= DD_CONDEMNED
;
932 *id
= ddp
->dd_linkid
;
934 if (ddp
->dd_zid
!= GLOBAL_ZONEID
)
935 (void) i_dls_devnet_setzid(ddp
, GLOBAL_ZONEID
, B_FALSE
);
938 * Remove this dls_devnet_t from the hash table.
940 VERIFY(mod_hash_remove(i_dls_devnet_hash
,
941 (mod_hash_key_t
)ddp
->dd_mac
, &val
) == 0);
943 if (ddp
->dd_linkid
!= DATALINK_INVALID_LINKID
) {
944 VERIFY(mod_hash_remove(i_dls_devnet_id_hash
,
945 (mod_hash_key_t
)(uintptr_t)ddp
->dd_linkid
, &val
) == 0);
947 devnet_need_rebuild
= B_TRUE
;
949 rw_exit(&i_dls_devnet_lock
);
953 * Wait until all temporary references are released.
955 while ((ddp
->dd_tref
!= 0) ||
956 (ddp
->dd_prop_taskid
!= (uintptr_t)NULL
))
957 cv_wait(&ddp
->dd_cv
, &ddp
->dd_mutex
);
959 ASSERT(ddp
->dd_tref
== 0 &&
960 ddp
->dd_prop_taskid
== (uintptr_t)NULL
);
963 if (ddp
->dd_linkid
!= DATALINK_INVALID_LINKID
)
964 dls_devnet_stat_destroy(ddp
, ddp
->dd_owner_zid
);
966 ddp
->dd_prop_loaded
= B_FALSE
;
967 ddp
->dd_linkid
= DATALINK_INVALID_LINKID
;
969 mutex_exit(&ddp
->dd_mutex
);
970 kmem_cache_free(i_dls_devnet_cachep
, ddp
);
976 dls_devnet_hold_common(datalink_id_t linkid
, dls_devnet_t
**ddpp
,
982 rw_enter(&i_dls_devnet_lock
, RW_READER
);
983 if ((err
= mod_hash_find(i_dls_devnet_id_hash
,
984 (mod_hash_key_t
)(uintptr_t)linkid
, (mod_hash_val_t
*)&ddp
)) != 0) {
985 ASSERT(err
== MH_ERR_NOTFOUND
);
986 rw_exit(&i_dls_devnet_lock
);
990 mutex_enter(&ddp
->dd_mutex
);
991 ASSERT(ddp
->dd_ref
> 0);
992 if (ddp
->dd_flags
& DD_CONDEMNED
) {
993 mutex_exit(&ddp
->dd_mutex
);
994 rw_exit(&i_dls_devnet_lock
);
1001 mutex_exit(&ddp
->dd_mutex
);
1002 rw_exit(&i_dls_devnet_lock
);
1009 dls_devnet_hold(datalink_id_t linkid
, dls_devnet_t
**ddpp
)
1011 return (dls_devnet_hold_common(linkid
, ddpp
, B_FALSE
));
1015 * Hold the vanity naming structure (dls_devnet_t) temporarily. The request to
1016 * delete the dls_devnet_t will wait until the temporary reference is released.
1019 dls_devnet_hold_tmp(datalink_id_t linkid
, dls_devnet_t
**ddpp
)
1021 return (dls_devnet_hold_common(linkid
, ddpp
, B_TRUE
));
1025 * This funtion is called when a DLS client tries to open a device node.
1026 * This dev_t could be a result of a /dev/net node access (returned by
1027 * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access.
1028 * In both cases, this function bumps up the reference count of the
1029 * dls_devnet_t structure. The reference is held as long as the device node
1030 * is open. In the case of /dev/net while it is true that the initial reference
1031 * is held when the devnet_create_rvp->dls_devnet_open call happens, this
1032 * initial reference is released immediately in devnet_inactive_callback ->
1033 * dls_devnet_close(). (Note that devnet_inactive_callback() is called right
1034 * after dld_open completes, not when the /dev/net node is being closed).
1035 * To undo this function, call dls_devnet_rele()
1038 dls_devnet_hold_by_dev(dev_t dev
, dls_dl_handle_t
*ddhp
)
1040 char name
[MAXNAMELEN
];
1045 if ((drv
= ddi_major_to_name(getmajor(dev
))) == NULL
)
1048 (void) snprintf(name
, sizeof (name
), "%s%d", drv
,
1049 DLS_MINOR2INST(getminor(dev
)));
1051 rw_enter(&i_dls_devnet_lock
, RW_READER
);
1052 if ((err
= mod_hash_find(i_dls_devnet_hash
,
1053 (mod_hash_key_t
)name
, (mod_hash_val_t
*)&ddp
)) != 0) {
1054 ASSERT(err
== MH_ERR_NOTFOUND
);
1055 rw_exit(&i_dls_devnet_lock
);
1058 mutex_enter(&ddp
->dd_mutex
);
1059 ASSERT(ddp
->dd_ref
> 0);
1060 if (ddp
->dd_flags
& DD_CONDEMNED
) {
1061 mutex_exit(&ddp
->dd_mutex
);
1062 rw_exit(&i_dls_devnet_lock
);
1066 mutex_exit(&ddp
->dd_mutex
);
1067 rw_exit(&i_dls_devnet_lock
);
1074 dls_devnet_rele(dls_devnet_t
*ddp
)
1076 mutex_enter(&ddp
->dd_mutex
);
1077 ASSERT(ddp
->dd_ref
> 1);
1079 if ((ddp
->dd_flags
& DD_IMPLICIT_IPTUN
) && ddp
->dd_ref
== 1) {
1080 mutex_exit(&ddp
->dd_mutex
);
1081 if (i_dls_devnet_destroy_iptun(ddp
->dd_linkid
) != 0)
1082 ddp
->dd_flags
|= DD_IMPLICIT_IPTUN
;
1085 mutex_exit(&ddp
->dd_mutex
);
1089 dls_devnet_hold_by_name(const char *link
, dls_devnet_t
**ddpp
)
1091 char drv
[MAXLINKNAMELEN
];
1094 dev_t phy_dev
, tmp_dev
;
1095 datalink_id_t linkid
;
1096 dls_dev_handle_t ddh
;
1099 if ((err
= dls_mgmt_get_linkid(link
, &linkid
)) == 0)
1100 return (dls_devnet_hold(linkid
, ddpp
));
1103 * If we failed to get the link's linkid because the dlmgmtd daemon
1104 * has not been started, return ENOENT so that the application can
1105 * fallback to open the /dev node.
1114 * If we reach this point it means dlmgmtd is up but has no
1115 * mapping for the link name.
1117 if (ddi_parse(link
, drv
, &ppa
) != DDI_SUCCESS
)
1120 if (IS_IPTUN_LINK(drv
)) {
1121 if ((err
= i_dls_devnet_create_iptun(link
, drv
, &linkid
)) != 0)
1124 * At this point, an IP tunnel MAC has registered, which
1125 * resulted in a link being created.
1127 err
= dls_devnet_hold(linkid
, ddpp
);
1129 VERIFY(i_dls_devnet_destroy_iptun(linkid
) == 0);
1133 * dls_devnet_rele() will know to destroy the implicit IP
1134 * tunnel on last reference release if DD_IMPLICIT_IPTUN is
1137 (*ddpp
)->dd_flags
|= DD_IMPLICIT_IPTUN
;
1143 * (a) is a physical device, (b) this is the first boot, (c) the MAC
1144 * is not registered yet, and (d) we cannot find its linkid, then the
1145 * linkname is the same as the devname.
1147 * First filter out invalid names.
1149 if ((major
= ddi_name_to_major(drv
)) == (major_t
)-1)
1152 phy_dev
= makedevice(major
, DLS_PPA2MINOR(ppa
));
1153 if (softmac_hold_device(phy_dev
, &ddh
) != 0)
1157 * At this time, the MAC should be registered, check its phy_dev using
1160 if ((err
= dls_mgmt_get_linkid(link
, &linkid
)) != 0 ||
1161 (err
= dls_mgmt_get_phydev(linkid
, &tmp_dev
)) != 0) {
1162 softmac_rele_device(ddh
);
1165 if (tmp_dev
!= phy_dev
) {
1166 softmac_rele_device(ddh
);
1170 err
= dls_devnet_hold(linkid
, ddpp
);
1171 softmac_rele_device(ddh
);
1176 dls_devnet_macname2linkid(const char *macname
, datalink_id_t
*linkidp
)
1180 rw_enter(&i_dls_devnet_lock
, RW_READER
);
1181 if (mod_hash_find(i_dls_devnet_hash
, (mod_hash_key_t
)macname
,
1182 (mod_hash_val_t
*)&ddp
) != 0) {
1183 rw_exit(&i_dls_devnet_lock
);
1187 *linkidp
= ddp
->dd_linkid
;
1188 rw_exit(&i_dls_devnet_lock
);
1193 * Get linkid for the given dev.
1196 dls_devnet_dev2linkid(dev_t dev
, datalink_id_t
*linkidp
)
1198 char macname
[MAXNAMELEN
];
1201 if ((drv
= ddi_major_to_name(getmajor(dev
))) == NULL
)
1204 (void) snprintf(macname
, sizeof (macname
), "%s%d", drv
,
1205 DLS_MINOR2INST(getminor(dev
)));
1206 return (dls_devnet_macname2linkid(macname
, linkidp
));
1210 * Get the link's physical dev_t. It this is a VLAN, get the dev_t of the
1211 * link this VLAN is created on.
1214 dls_devnet_phydev(datalink_id_t vlanid
, dev_t
*devp
)
1219 if ((err
= dls_devnet_hold_tmp(vlanid
, &ddp
)) != 0)
1222 err
= dls_mgmt_get_phydev(ddp
->dd_linkid
, devp
);
1223 dls_devnet_rele_tmp(ddp
);
1228 * Handle the renaming requests. There are two rename cases:
1230 * 1. Request to rename a valid link (id1) to an non-existent link name
1231 * (id2). In this case id2 is DATALINK_INVALID_LINKID. Just check whether
1232 * id1 is held by any applications.
1234 * In this case, the link's kstats need to be updated using the given name.
1236 * 2. Request to rename a valid link (id1) to the name of a REMOVED
1237 * physical link (id2). In this case, check that id1 and its associated
1238 * mac is not held by any application, and update the link's linkid to id2.
1240 * This case does not change the <link name, linkid> mapping, so the link's
1241 * kstats need to be updated with using name associated the given id2.
1244 dls_devnet_rename(datalink_id_t id1
, datalink_id_t id2
, const char *link
)
1246 dls_dev_handle_t ddh
= NULL
;
1250 mac_perim_handle_t mph
= NULL
;
1255 * In the second case, id2 must be a REMOVED physical link.
1257 if ((id2
!= DATALINK_INVALID_LINKID
) &&
1258 (dls_mgmt_get_phydev(id2
, &phydev
) == 0) &&
1259 softmac_hold_device(phydev
, &ddh
) == 0) {
1260 softmac_rele_device(ddh
);
1265 * Hold id1 to prevent it from being detached (if a physical link).
1267 if (dls_mgmt_get_phydev(id1
, &phydev
) == 0)
1268 (void) softmac_hold_device(phydev
, &ddh
);
1271 * The framework does not hold hold locks across calls to the
1272 * mac perimeter, hence enter the perimeter first. This also waits
1273 * for the property loading to finish.
1275 if ((err
= mac_perim_enter_by_linkid(id1
, &mph
)) != 0) {
1276 softmac_rele_device(ddh
);
1280 rw_enter(&i_dls_devnet_lock
, RW_WRITER
);
1281 if ((err
= mod_hash_find(i_dls_devnet_id_hash
,
1282 (mod_hash_key_t
)(uintptr_t)id1
, (mod_hash_val_t
*)&ddp
)) != 0) {
1283 ASSERT(err
== MH_ERR_NOTFOUND
);
1288 mutex_enter(&ddp
->dd_mutex
);
1289 if (ddp
->dd_ref
> 1) {
1290 mutex_exit(&ddp
->dd_mutex
);
1294 mutex_exit(&ddp
->dd_mutex
);
1296 if (id2
== DATALINK_INVALID_LINKID
) {
1297 (void) strlcpy(ddp
->dd_linkname
, link
,
1298 sizeof (ddp
->dd_linkname
));
1300 /* rename mac client name and its flow if exists */
1301 if ((err
= mac_open(ddp
->dd_mac
, &mh
)) != 0)
1303 (void) mac_rename_primary(mh
, link
);
1309 * The second case, check whether the MAC is used by any MAC
1310 * user. This must be a physical link so ddh must not be NULL.
1317 if ((err
= mac_open(ddp
->dd_mac
, &mh
)) != 0)
1321 * We release the reference of the MAC which mac_open() is
1322 * holding. Note that this mac will not be unregistered
1323 * because the physical device is held.
1328 * Check if there is any other MAC clients, if not, hold this mac
1329 * exclusively until we are done.
1331 if ((err
= mac_mark_exclusive(mh
)) != 0)
1335 * Update the link's linkid.
1337 if ((err
= mod_hash_find(i_dls_devnet_id_hash
,
1338 (mod_hash_key_t
)(uintptr_t)id2
, &val
)) != MH_ERR_NOTFOUND
) {
1339 mac_unmark_exclusive(mh
);
1344 err
= dls_mgmt_get_linkinfo(id2
, ddp
->dd_linkname
, NULL
, NULL
, NULL
);
1346 mac_unmark_exclusive(mh
);
1350 (void) mod_hash_remove(i_dls_devnet_id_hash
,
1351 (mod_hash_key_t
)(uintptr_t)id1
, &val
);
1353 ddp
->dd_linkid
= id2
;
1354 (void) mod_hash_insert(i_dls_devnet_id_hash
,
1355 (mod_hash_key_t
)(uintptr_t)ddp
->dd_linkid
, (mod_hash_val_t
)ddp
);
1357 mac_unmark_exclusive(mh
);
1359 /* load properties for new id */
1360 mutex_enter(&ddp
->dd_mutex
);
1361 ddp
->dd_prop_loaded
= B_FALSE
;
1362 ddp
->dd_prop_taskid
= taskq_dispatch(system_taskq
,
1363 dls_devnet_prop_task
, ddp
, TQ_SLEEP
);
1364 mutex_exit(&ddp
->dd_mutex
);
1367 rw_exit(&i_dls_devnet_lock
);
1370 dls_devnet_stat_rename(ddp
);
1373 mac_perim_exit(mph
);
1374 softmac_rele_device(ddh
);
1379 i_dls_devnet_setzid(dls_devnet_t
*ddp
, zoneid_t new_zoneid
, boolean_t setprop
)
1382 mac_perim_handle_t mph
;
1383 boolean_t upcall_done
= B_FALSE
;
1384 datalink_id_t linkid
= ddp
->dd_linkid
;
1385 zoneid_t old_zoneid
= ddp
->dd_zid
;
1386 dlmgmt_door_setzoneid_t setzid
;
1387 dlmgmt_setzoneid_retval_t retval
;
1389 if (old_zoneid
== new_zoneid
)
1392 if ((err
= mac_perim_enter_by_macname(ddp
->dd_mac
, &mph
)) != 0)
1396 * When changing the zoneid of an existing link, we need to tell
1397 * dlmgmtd about it. dlmgmtd already knows the zoneid associated with
1398 * newly created links.
1401 setzid
.ld_cmd
= DLMGMT_CMD_SETZONEID
;
1402 setzid
.ld_linkid
= linkid
;
1403 setzid
.ld_zoneid
= new_zoneid
;
1404 err
= i_dls_mgmt_upcall(&setzid
, sizeof (setzid
), &retval
,
1408 upcall_done
= B_TRUE
;
1410 if ((err
= dls_link_setzid(ddp
->dd_mac
, new_zoneid
)) == 0) {
1411 ddp
->dd_zid
= new_zoneid
;
1412 devnet_need_rebuild
= B_TRUE
;
1416 if (err
!= 0 && upcall_done
) {
1417 setzid
.ld_zoneid
= old_zoneid
;
1418 (void) i_dls_mgmt_upcall(&setzid
, sizeof (setzid
), &retval
,
1421 mac_perim_exit(mph
);
1426 dls_devnet_setzid(dls_dl_handle_t ddh
, zoneid_t new_zid
)
1431 boolean_t refheld
= B_FALSE
;
1433 old_zid
= ddh
->dd_zid
;
1435 if (old_zid
== new_zid
)
1439 * Acquire an additional reference to the link if it is being assigned
1440 * to a non-global zone from the global zone.
1442 if (old_zid
== GLOBAL_ZONEID
&& new_zid
!= GLOBAL_ZONEID
) {
1443 if ((err
= dls_devnet_hold(ddh
->dd_linkid
, &ddp
)) != 0)
1448 if ((err
= i_dls_devnet_setzid(ddh
, new_zid
, B_TRUE
)) != 0) {
1450 dls_devnet_rele(ddp
);
1455 * Release the additional reference if the link is returning to the
1456 * global zone from a non-global zone.
1458 if (old_zid
!= GLOBAL_ZONEID
&& new_zid
== GLOBAL_ZONEID
)
1459 dls_devnet_rele(ddh
);
1461 /* Re-create kstats in the appropriate zones. */
1462 if (old_zid
!= GLOBAL_ZONEID
)
1463 dls_devnet_stat_destroy(ddh
, old_zid
);
1464 if (new_zid
!= GLOBAL_ZONEID
)
1465 dls_devnet_stat_create(ddh
, new_zid
);
1471 dls_devnet_getzid(dls_dl_handle_t ddh
)
1473 return (((dls_devnet_t
*)ddh
)->dd_zid
);
1477 dls_devnet_getownerzid(dls_dl_handle_t ddh
)
1479 return (((dls_devnet_t
*)ddh
)->dd_owner_zid
);
1483 * Is linkid visible from zoneid? A link is visible if it was created in the
1484 * zone, or if it is currently assigned to the zone.
1487 dls_devnet_islinkvisible(datalink_id_t linkid
, zoneid_t zoneid
)
1492 if (dls_devnet_hold_tmp(linkid
, &ddp
) != 0)
1494 result
= (ddp
->dd_owner_zid
== zoneid
|| ddp
->dd_zid
== zoneid
);
1495 dls_devnet_rele_tmp(ddp
);
1500 * Access a vanity naming node.
1503 dls_devnet_open(const char *link
, dls_dl_handle_t
*dhp
, dev_t
*devp
)
1507 zoneid_t zid
= getzoneid();
1509 mac_perim_handle_t mph
;
1511 if ((err
= dls_devnet_hold_by_name(link
, &ddp
)) != 0)
1514 dls_devnet_prop_task_wait(ddp
);
1517 * Opening a link that does not belong to the current non-global zone
1520 if (zid
!= GLOBAL_ZONEID
&& ddp
->dd_zid
!= zid
) {
1521 dls_devnet_rele(ddp
);
1525 err
= mac_perim_enter_by_macname(ddp
->dd_mac
, &mph
);
1527 dls_devnet_rele(ddp
);
1531 err
= dls_link_hold_create(ddp
->dd_mac
, &dlp
);
1532 mac_perim_exit(mph
);
1535 dls_devnet_rele(ddp
);
1540 *devp
= dls_link_dev(dlp
);
1545 * Close access to a vanity naming node.
1548 dls_devnet_close(dls_dl_handle_t dlh
)
1550 dls_devnet_t
*ddp
= dlh
;
1552 mac_perim_handle_t mph
;
1554 VERIFY(mac_perim_enter_by_macname(ddp
->dd_mac
, &mph
) == 0);
1555 VERIFY(dls_link_hold(ddp
->dd_mac
, &dlp
) == 0);
1558 * One rele for the hold placed in dls_devnet_open, another for
1559 * the hold done just above
1563 mac_perim_exit(mph
);
1565 dls_devnet_rele(ddp
);
1569 * This is used by /dev/net to rebuild the nodes for readdir(). It is not
1570 * critical and no protection is needed.
1573 dls_devnet_rebuild()
1575 boolean_t updated
= devnet_need_rebuild
;
1577 devnet_need_rebuild
= B_FALSE
;
1582 dls_devnet_create(mac_handle_t mh
, datalink_id_t linkid
, zoneid_t zoneid
)
1587 mac_perim_handle_t mph
;
1590 * Holding the mac perimeter ensures that the downcall from the
1591 * dlmgmt daemon which does the property loading does not proceed
1592 * until we relinquish the perimeter.
1594 mac_perim_enter_by_mh(mh
, &mph
);
1596 * Make this association before we call dls_link_hold_create as
1597 * we need to use the linkid to get the user name for the link
1598 * when we create the MAC client.
1600 if ((err
= dls_devnet_set(mac_name(mh
), linkid
, zoneid
, &ddp
)) == 0) {
1601 if ((err
= dls_link_hold_create(mac_name(mh
), &dlp
)) != 0) {
1602 mac_perim_exit(mph
);
1603 (void) dls_devnet_unset(mac_name(mh
), &linkid
, B_TRUE
);
1607 mac_perim_exit(mph
);
1612 * Set the linkid of the dls_devnet_t and add it into the i_dls_devnet_id_hash.
1613 * This is called in the case that the dlmgmtd daemon is started later than
1614 * the physical devices get attached, and the linkid is only known after the
1618 dls_devnet_recreate(mac_handle_t mh
, datalink_id_t linkid
)
1620 ASSERT(linkid
!= DATALINK_INVALID_LINKID
);
1621 return (dls_devnet_set(mac_name(mh
), linkid
, GLOBAL_ZONEID
, NULL
));
1625 dls_devnet_destroy(mac_handle_t mh
, datalink_id_t
*idp
, boolean_t wait
)
1628 mac_perim_handle_t mph
;
1630 *idp
= DATALINK_INVALID_LINKID
;
1631 err
= dls_devnet_unset(mac_name(mh
), idp
, wait
);
1632 if (err
!= 0 && err
!= ENOENT
)
1635 mac_perim_enter_by_mh(mh
, &mph
);
1636 err
= dls_link_rele_by_name(mac_name(mh
));
1637 mac_perim_exit(mph
);
1641 * XXX It is a general GLDv3 bug that dls_devnet_set() has to
1642 * be called to re-set the link when destroy fails. The
1643 * zoneid below will be incorrect if this function is ever
1644 * called from kernel context or from a zone other than that
1645 * which initially created the link.
1647 (void) dls_devnet_set(mac_name(mh
), *idp
, crgetzoneid(CRED()),
1654 * Implicitly create an IP tunnel link.
1657 i_dls_devnet_create_iptun(const char *linkname
, const char *drvname
,
1658 datalink_id_t
*linkid
)
1664 major_t iptun_major
;
1665 dev_info_t
*iptun_dip
;
1667 /* First ensure that the iptun device is attached. */
1668 if ((iptun_major
= ddi_name_to_major(IPTUN_DRIVER_NAME
)) == (major_t
)-1)
1670 if ((iptun_dip
= ddi_hold_devi_by_instance(iptun_major
, 0, 0)) == NULL
)
1673 if (IS_IPV4_TUN(drvname
)) {
1674 ik
.iptun_kparam_type
= IPTUN_TYPE_IPV4
;
1676 } else if (IS_6TO4_TUN(drvname
)) {
1677 ik
.iptun_kparam_type
= IPTUN_TYPE_6TO4
;
1679 } else if (IS_IPV6_TUN(drvname
)) {
1680 ik
.iptun_kparam_type
= IPTUN_TYPE_IPV6
;
1683 ik
.iptun_kparam_flags
= (IPTUN_KPARAM_TYPE
| IPTUN_KPARAM_IMPLICIT
);
1685 /* Obtain a datalink id for this tunnel. */
1686 err
= dls_mgmt_create((char *)linkname
, 0, DATALINK_CLASS_IPTUN
, media
,
1687 B_FALSE
, &ik
.iptun_kparam_linkid
);
1689 ddi_release_devi(iptun_dip
);
1693 ns
= netstack_get_current();
1694 err
= iptun_create(&ik
, CRED());
1698 VERIFY(dls_mgmt_destroy(ik
.iptun_kparam_linkid
, B_FALSE
) == 0);
1700 *linkid
= ik
.iptun_kparam_linkid
;
1702 ddi_release_devi(iptun_dip
);
1707 i_dls_devnet_destroy_iptun(datalink_id_t linkid
)
1712 * Note the use of zone_kcred() here as opposed to CRED(). This is
1713 * because the process that does the last close of this /dev/net node
1714 * may not have necessary privileges to delete this IP tunnel, but the
1715 * tunnel must always be implicitly deleted on last close.
1717 if ((err
= iptun_delete(linkid
, zone_kcred())) == 0)
1718 (void) dls_mgmt_destroy(linkid
, B_FALSE
);
1723 dls_devnet_mac(dls_dl_handle_t ddh
)
1725 return (ddh
->dd_mac
);
1729 dls_devnet_linkid(dls_dl_handle_t ddh
)
1731 return (ddh
->dd_linkid
);