xref: /illumos-gate/usr/src/cmd/dlmgmtd/dlmgmt_util.c (revision c6d054cb)
1d62bc4baSyz /*
2d62bc4baSyz  * CDDL HEADER START
3d62bc4baSyz  *
4d62bc4baSyz  * The contents of this file are subject to the terms of the
5d62bc4baSyz  * Common Development and Distribution License (the "License").
6d62bc4baSyz  * You may not use this file except in compliance with the License.
7d62bc4baSyz  *
8d62bc4baSyz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d62bc4baSyz  * or http://www.opensolaris.org/os/licensing.
10d62bc4baSyz  * See the License for the specific language governing permissions
11d62bc4baSyz  * and limitations under the License.
12d62bc4baSyz  *
13d62bc4baSyz  * When distributing Covered Code, include this CDDL HEADER in each
14d62bc4baSyz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d62bc4baSyz  * If applicable, add the following below this CDDL HEADER, with the
16d62bc4baSyz  * fields enclosed by brackets "[]" replaced with your own identifying
17d62bc4baSyz  * information: Portions Copyright [yyyy] [name of copyright owner]
18d62bc4baSyz  *
19d62bc4baSyz  * CDDL HEADER END
20d62bc4baSyz  */
21d62bc4baSyz 
22d62bc4baSyz /*
2332715170SCathy Zhou  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24d62bc4baSyz  */
25d62bc4baSyz 
26d62bc4baSyz /*
27d62bc4baSyz  * Utility functions used by the dlmgmtd daemon.
28d62bc4baSyz  */
29d62bc4baSyz 
30d62bc4baSyz #include <assert.h>
31d62bc4baSyz #include <pthread.h>
32d62bc4baSyz #include <stddef.h>
33d62bc4baSyz #include <stdlib.h>
34d62bc4baSyz #include <stdio.h>
352b24ab6bSSebastien Roy #include <errno.h>
36d62bc4baSyz #include <strings.h>
372b24ab6bSSebastien Roy #include <string.h>
38d62bc4baSyz #include <syslog.h>
39d62bc4baSyz #include <stdarg.h>
402b24ab6bSSebastien Roy #include <zone.h>
4182a2fc47SJames Carlson #include <errno.h>
42d62bc4baSyz #include <libdlpi.h>
43d62bc4baSyz #include "dlmgmt_impl.h"
44d62bc4baSyz 
45d62bc4baSyz /*
462b24ab6bSSebastien Roy  * There are three datalink AVL tables.  The dlmgmt_name_avl tree contains all
472b24ab6bSSebastien Roy  * datalinks and is keyed by zoneid and link name.  The dlmgmt_id_avl also
482b24ab6bSSebastien Roy  * contains all datalinks, and it is keyed by link ID.  The dlmgmt_loan_avl is
492b24ab6bSSebastien Roy  * keyed by link name, and contains the set of global-zone links that are
502b24ab6bSSebastien Roy  * currently on loan to non-global zones.
51d62bc4baSyz  */
52d62bc4baSyz avl_tree_t	dlmgmt_name_avl;
53d62bc4baSyz avl_tree_t	dlmgmt_id_avl;
542b24ab6bSSebastien Roy avl_tree_t	dlmgmt_loan_avl;
55d62bc4baSyz 
56d62bc4baSyz avl_tree_t	dlmgmt_dlconf_avl;
57d62bc4baSyz 
58d62bc4baSyz static pthread_rwlock_t	dlmgmt_avl_lock = PTHREAD_RWLOCK_INITIALIZER;
59d62bc4baSyz static pthread_mutex_t  dlmgmt_avl_mutex = PTHREAD_MUTEX_INITIALIZER;
60d62bc4baSyz static pthread_cond_t	dlmgmt_avl_cv = PTHREAD_COND_INITIALIZER;
61d62bc4baSyz static pthread_rwlock_t	dlmgmt_dlconf_lock = PTHREAD_RWLOCK_INITIALIZER;
62d62bc4baSyz 
63d62bc4baSyz typedef struct dlmgmt_prefix {
64d62bc4baSyz 	struct dlmgmt_prefix	*lp_next;
65d62bc4baSyz 	char			lp_prefix[MAXLINKNAMELEN];
662b24ab6bSSebastien Roy 	zoneid_t		lp_zoneid;
67d62bc4baSyz 	uint_t			lp_nextppa;
68d62bc4baSyz } dlmgmt_prefix_t;
692b24ab6bSSebastien Roy static dlmgmt_prefix_t	dlmgmt_prefixlist;
70d62bc4baSyz 
712b24ab6bSSebastien Roy datalink_id_t		dlmgmt_nextlinkid;
72d62bc4baSyz static datalink_id_t	dlmgmt_nextconfid = 1;
73d62bc4baSyz 
74d62bc4baSyz static void		dlmgmt_advance_linkid(dlmgmt_link_t *);
75d62bc4baSyz static void		dlmgmt_advance_ppa(dlmgmt_link_t *);
76d62bc4baSyz 
77d62bc4baSyz void
dlmgmt_log(int pri,const char * fmt,...)78d62bc4baSyz dlmgmt_log(int pri, const char *fmt, ...)
79d62bc4baSyz {
80d62bc4baSyz 	va_list alist;
81d62bc4baSyz 
82d62bc4baSyz 	va_start(alist, fmt);
83d62bc4baSyz 	if (debug) {
84d62bc4baSyz 		(void) vfprintf(stderr, fmt, alist);
85d62bc4baSyz 		(void) fputc('\n', stderr);
86d62bc4baSyz 	} else {
87d62bc4baSyz 		vsyslog(pri, fmt, alist);
88d62bc4baSyz 	}
89d62bc4baSyz 	va_end(alist);
90d62bc4baSyz }
91d62bc4baSyz 
92d62bc4baSyz static int
cmp_link_by_name(const void * v1,const void * v2)93d62bc4baSyz cmp_link_by_name(const void *v1, const void *v2)
94d62bc4baSyz {
95d62bc4baSyz 	const dlmgmt_link_t *link1 = v1;
96d62bc4baSyz 	const dlmgmt_link_t *link2 = v2;
97d62bc4baSyz 	int cmp;
98d62bc4baSyz 
99d62bc4baSyz 	cmp = strcmp(link1->ll_link, link2->ll_link);
100d62bc4baSyz 	return ((cmp == 0) ? 0 : ((cmp < 0) ? -1 : 1));
101d62bc4baSyz }
102d62bc4baSyz 
1032b24ab6bSSebastien Roy /*
1042b24ab6bSSebastien Roy  * Note that the zoneid associated with a link is effectively part of its
1052b24ab6bSSebastien Roy  * name.  This is essentially what results in having each zone have disjoint
1062b24ab6bSSebastien Roy  * datalink namespaces.
1072b24ab6bSSebastien Roy  */
1082b24ab6bSSebastien Roy static int
cmp_link_by_zname(const void * v1,const void * v2)1092b24ab6bSSebastien Roy cmp_link_by_zname(const void *v1, const void *v2)
1102b24ab6bSSebastien Roy {
1112b24ab6bSSebastien Roy 	const dlmgmt_link_t *link1 = v1;
1122b24ab6bSSebastien Roy 	const dlmgmt_link_t *link2 = v2;
1132b24ab6bSSebastien Roy 
1142b24ab6bSSebastien Roy 	if (link1->ll_zoneid < link2->ll_zoneid)
1152b24ab6bSSebastien Roy 		return (-1);
1162b24ab6bSSebastien Roy 	if (link1->ll_zoneid > link2->ll_zoneid)
1172b24ab6bSSebastien Roy 		return (1);
1182b24ab6bSSebastien Roy 	return (cmp_link_by_name(link1, link2));
1192b24ab6bSSebastien Roy }
1202b24ab6bSSebastien Roy 
121d62bc4baSyz static int
cmp_link_by_id(const void * v1,const void * v2)122d62bc4baSyz cmp_link_by_id(const void *v1, const void *v2)
123d62bc4baSyz {
124d62bc4baSyz 	const dlmgmt_link_t *link1 = v1;
125d62bc4baSyz 	const dlmgmt_link_t *link2 = v2;
126d62bc4baSyz 
127d62bc4baSyz 	if ((uint64_t)(link1->ll_linkid) == (uint64_t)(link2->ll_linkid))
128d62bc4baSyz 		return (0);
129d62bc4baSyz 	else if ((uint64_t)(link1->ll_linkid) < (uint64_t)(link2->ll_linkid))
130d62bc4baSyz 		return (-1);
131d62bc4baSyz 	else
132d62bc4baSyz 		return (1);
133d62bc4baSyz }
134d62bc4baSyz 
135d62bc4baSyz static int
cmp_dlconf_by_id(const void * v1,const void * v2)136d62bc4baSyz cmp_dlconf_by_id(const void *v1, const void *v2)
137d62bc4baSyz {
138d62bc4baSyz 	const dlmgmt_dlconf_t *dlconfp1 = v1;
139d62bc4baSyz 	const dlmgmt_dlconf_t *dlconfp2 = v2;
140d62bc4baSyz 
141d62bc4baSyz 	if (dlconfp1->ld_id == dlconfp2->ld_id)
142d62bc4baSyz 		return (0);
143d62bc4baSyz 	else if (dlconfp1->ld_id < dlconfp2->ld_id)
144d62bc4baSyz 		return (-1);
145d62bc4baSyz 	else
146d62bc4baSyz 		return (1);
147d62bc4baSyz }
148d62bc4baSyz 
1492b24ab6bSSebastien Roy void
dlmgmt_linktable_init(void)1502b24ab6bSSebastien Roy dlmgmt_linktable_init(void)
151d62bc4baSyz {
152d62bc4baSyz 	/*
1532b24ab6bSSebastien Roy 	 * Initialize the prefix list. First add the "net" prefix for the
1542b24ab6bSSebastien Roy 	 * global zone to the list.
155d62bc4baSyz 	 */
1562b24ab6bSSebastien Roy 	dlmgmt_prefixlist.lp_next = NULL;
1572b24ab6bSSebastien Roy 	dlmgmt_prefixlist.lp_zoneid = GLOBAL_ZONEID;
1582b24ab6bSSebastien Roy 	dlmgmt_prefixlist.lp_nextppa = 0;
1592b24ab6bSSebastien Roy 	(void) strlcpy(dlmgmt_prefixlist.lp_prefix, "net", MAXLINKNAMELEN);
160d62bc4baSyz 
1612b24ab6bSSebastien Roy 	avl_create(&dlmgmt_name_avl, cmp_link_by_zname, sizeof (dlmgmt_link_t),
1622b24ab6bSSebastien Roy 	    offsetof(dlmgmt_link_t, ll_name_node));
163d62bc4baSyz 	avl_create(&dlmgmt_id_avl, cmp_link_by_id, sizeof (dlmgmt_link_t),
1642b24ab6bSSebastien Roy 	    offsetof(dlmgmt_link_t, ll_id_node));
1652b24ab6bSSebastien Roy 	avl_create(&dlmgmt_loan_avl, cmp_link_by_name, sizeof (dlmgmt_link_t),
1662b24ab6bSSebastien Roy 	    offsetof(dlmgmt_link_t, ll_loan_node));
167d62bc4baSyz 	avl_create(&dlmgmt_dlconf_avl, cmp_dlconf_by_id,
168d62bc4baSyz 	    sizeof (dlmgmt_dlconf_t), offsetof(dlmgmt_dlconf_t, ld_node));
169d62bc4baSyz 	dlmgmt_nextlinkid = 1;
170d62bc4baSyz }
171d62bc4baSyz 
172d62bc4baSyz void
dlmgmt_linktable_fini(void)1732b24ab6bSSebastien Roy dlmgmt_linktable_fini(void)
174d62bc4baSyz {
1752b24ab6bSSebastien Roy 	dlmgmt_prefix_t *lpp, *next;
176d62bc4baSyz 
1772b24ab6bSSebastien Roy 	for (lpp = dlmgmt_prefixlist.lp_next; lpp != NULL; lpp = next) {
178d62bc4baSyz 		next = lpp->lp_next;
179d62bc4baSyz 		free(lpp);
180d62bc4baSyz 	}
181d62bc4baSyz 
182d62bc4baSyz 	avl_destroy(&dlmgmt_dlconf_avl);
183d62bc4baSyz 	avl_destroy(&dlmgmt_name_avl);
1842b24ab6bSSebastien Roy 	avl_destroy(&dlmgmt_loan_avl);
185d62bc4baSyz 	avl_destroy(&dlmgmt_id_avl);
186d62bc4baSyz }
187d62bc4baSyz 
1882b24ab6bSSebastien Roy static void
linkattr_add(dlmgmt_linkattr_t ** headp,dlmgmt_linkattr_t * attrp)189d62bc4baSyz linkattr_add(dlmgmt_linkattr_t **headp, dlmgmt_linkattr_t *attrp)
190d62bc4baSyz {
191d62bc4baSyz 	if (*headp == NULL) {
192d62bc4baSyz 		*headp = attrp;
193d62bc4baSyz 	} else {
194d62bc4baSyz 		(*headp)->lp_prev = attrp;
195d62bc4baSyz 		attrp->lp_next = *headp;
196d62bc4baSyz 		*headp = attrp;
197d62bc4baSyz 	}
198d62bc4baSyz }
199d62bc4baSyz 
200