1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #ifndef _PER_DSTORE_H
28 #define _PER_DSTORE_H
29
30 #pragma ident "%Z%%M% %I% %E% SMI"
31
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35
36 /*
37 * per_dnet.h -- DHCP-datastore database definitions.
38 */
39
40 /*
41 * DHCP thread deferred work structure. One per deferred client thread.
42 *
43 * Track clients who cannot be immediately serviced due
44 * to a lack of available client threads. Locked by thr_mtx.
45 */
46 typedef struct dsvc_pending {
47 uchar_t pnd_cid[DN_MAX_CID_LEN]; /* cid */
48 uchar_t pnd_cid_len; /* cid length */
49 struct dsvc_pending *pnd_next; /* next */
50 } dsvc_pendclnt_t;
51
52 /*
53 * DHCP thread structure. One per client thread.
54 *
55 * Performance: create and track each client thread, using
56 * thr_suspend/thr_resume, rather than slower thread creation
57 * and deletion. Locked by thr_mtx.
58 */
59 struct clnt;
60 typedef struct dsvc_free {
61 thread_t thr_tid; /* thread id */
62 cond_t thr_cv; /* suspend/resume cv */
63 mutex_t thr_mtx; /* suspend/resume mutex */
64 uint_t thr_flags; /* suspend/resume flags */
65 struct clnt *thr_pcd; /* per client data struct */
66 struct dsvc_free *thr_next; /* next */
67 } dsvc_thr_t;
68
69 /*
70 * DHCP thread structure flags
71 */
72 #define DHCP_THR_LIST 0x1 /* Thread is on freelist */
73 #define DHCP_THR_EXITING 0x2 /* Thread is exiting */
74
75 /*
76 * DHCP datastore table. One per active network or dhcptab datastore.
77 *
78 * Timestamps are used to age the datastore structure, and any cached
79 * datastore free or lru records managed in select_offer().
80 * The number of threads and clients can be controlled via MAX_THREADS
81 * and MAX_CLIENTS server parameters.
82 *
83 * Client and offer hashes provide fast lookup/reservation.
84 * Per-bucket rwlocks implemented in the hash routines reduce
85 * lock contention between clients.
86 *
87 * To minimize expensive datastore activity, threads synchronize to
88 * manage cached free and lru datastore records, which have the
89 * same lifetime as cached offers, which can be controlled via
90 * the OFFER_CACHE_TIMEOUT server parameter.
91 */
92 typedef struct dnet {
93 hash_handle hand; /* hash insertion handle */
94 time_t free_mtime; /* macro table purge time */
95 time_t free_stamp; /* D_OFFER freerec purge time */
96 time_t lru_mtime; /* macro table purge time */
97 time_t lru_stamp; /* D_OFFER lrurec purge time */
98 time_t clnt_stamp; /* D_OFFER client purge time */
99 uint_t flags; /* dnet flags */
100 struct in_addr net; /* network */
101 struct in_addr subnet; /* subnet mask */
102 int naddrs; /* # addrs owned by server */
103 int nthreads; /* number of active threads */
104 int nclients; /* number of active clients */
105 hash_tbl *ctable; /* per client hash table */
106 hash_tbl *itable; /* per ipaddr hash table */
107 dsvc_thr_t *thrhead; /* free thread list */
108 dsvc_thr_t *thrtail; /* free thread list tail */
109 dsvc_pendclnt_t *workhead; /* head of thread work list */
110 dsvc_pendclnt_t *worktail; /* tail of thread work list */
111 dn_rec_list_t *freerec; /* free records head */
112 dn_rec_list_t *lrurec; /* lru records head */
113 dn_rec_list_t **lrupage; /* lru records sort area */
114 size_t lrusize;
115
116 dsvc_handle_t dh; /* datastore handle */
117 mutex_t pnd_mtx; /* open/close mutex */
118 mutex_t free_mtx; /* lock for free records */
119 mutex_t lru_mtx; /* lock for lru records */
120 mutex_t lrupage_mtx; /* lock for lru page */
121 mutex_t thr_mtx; /* lock for thread work list */
122 cond_t thr_cv; /* cond var (nthreads == 0) */
123 char network[INET_ADDRSTRLEN]; /* display buffer */
124 } dsvc_dnet_t;
125
126 /*
127 * DHCP datastore table flags
128 */
129 #define DHCP_PND_CLOSING 0x1 /* Dstore is closing */
130 #define DHCP_PND_ERROR 0x2 /* Dstore experienced error */
131
132 /*
133 * DHCP datastore table macros
134 */
135 #define PND_FREE_TIMEOUT(pnd, now) ((pnd)->free_stamp < (now) || \
136 (pnd)->free_mtime != reinit_time)
137 #define PND_LRU_TIMEOUT(pnd, now) ((pnd)->lru_stamp < (now) || \
138 (pnd)->lru_mtime != reinit_time)
139
140 struct interfaces;
141
142 /*
143 * DHCP client. One per active client, per network.
144 *
145 * Timestamps are used to age the client structure, and any cached
146 * offer, which can be controlled via the OFFER_CACHE_TIMEOUT server
147 * parameter, and the -t option, and SIGHUP signal.
148 *
149 * The original datastore record is cached, along with offer information,
150 * for use if the datastore record is modified.
151 *
152 * The clnt struct may appear on the client hash table, and offer hash table,
153 * depending on the validity of the current offer. A different dsvc_clnt_t
154 * is used for each link, to allow independent aging of client and offer.
155 */
156 typedef struct clnt {
157 hash_handle chand; /* hash insertion handle: client hash */
158 hash_handle ihand; /* hash insertion handle: inet hash */
159 time_t mtime; /* macro table offer purge time */
160 uint_t flags; /* Client flags */
161 uint_t state; /* Client DHCP state */
162 struct in_addr off_ip; /* Offered address */
163 struct interfaces *ifp; /* the ifp the packet arrived on */
164 dsvc_dnet_t *pnd; /* the per network datastore */
165 PKT_LIST *pkthead; /* head of client packet list */
166 PKT_LIST *pkttail; /* tail of client packet list */
167 uint_t pending; /* # of pkts on client packet list */
168 lease_t lease; /* Offered lease time */
169 dsvc_thr_t *clnt_thread; /* client thread */
170
171 dn_rec_list_t *dnlp; /* Original datastore record */
172 mutex_t pcd_mtx; /* overall struct lock */
173 mutex_t pkt_mtx; /* lock for PKT_LIST */
174 cond_t pcd_cv; /* cond var (clnt_thread == 0) */
175 char cidbuf[DHCP_MAX_OPT_SIZE]; /* display buffer */
176 uchar_t cid[DN_MAX_CID_LEN]; /* Offered cid */
177 uchar_t cid_len; /* Offered cid length */
178 } dsvc_clnt_t;
179
180 /*
181 * Per Client flags and indices
182 */
183 #define DHCP_HDR_CLIENT 0x0 /* clnt dsvc_clnt_t */
184 #define DHCP_HDR_OFFER 0x1 /* offer dsvc_clnt_t */
185
186 #define DHCP_PCD_OFFER 0x1 /* Offered ip addr is valid */
187 #define DHCP_PCD_WORK 0x2 /* Client is on deferred work list */
188 #define DHCP_PCD_CLOSING 0x4 /* Client thread should exit */
189
190 /*
191 * Per Client macros
192 */
193 #define PCD_OFFER_TIMEOUT(pcd, now) (hash_Htime(pcd->ihand) < (now) || \
194 (pcd)->mtime != reinit_time)
195
196 /*
197 * Datastore hash table dynamic data free timeout values
198 */
199 #define DHCP_CLIENT_THRESHOLD 90 /* Time to free inactive clients */
200 #define DHCP_NET_THRESHOLD 900 /* Time to free inactive nets */
201
202 /*
203 * Datastore database access routines.
204 */
205 extern int open_dnet(dsvc_dnet_t **, struct in_addr *, struct in_addr *);
206 extern void close_dnet(dsvc_dnet_t *, boolean_t);
207
208 /*
209 * Per Client hash and utility routines.
210 */
211 extern int open_clnt(dsvc_dnet_t *, dsvc_clnt_t **, uchar_t *, uchar_t,
212 boolean_t);
213 extern void close_clnt(dsvc_clnt_t *, boolean_t);
214 extern int clnt_netcmp(dsvc_clnt_t *, dsvc_clnt_t *);
215 extern void close_clnts(void);
216 extern void purge_offer(dsvc_clnt_t *, boolean_t, boolean_t);
217
218 #ifdef __cplusplus
219 }
220 #endif
221
222 #endif /* _PER_DSTORE_H */