summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-inet/usr.lib/in.dhcpd/README.caching
blob: a8f9dad855680d2b2c7183c8928e43a566fd34be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License").  You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
# 

The DHCP server cache implementation
Zhenghui.Xie@sun.com


#ident	"%Z%%M%	%I%	%E% SMI"

INTRODUCTION
============

The Solaris DHCP server implements a caching mechanism to:

 	* Ensure the ACK is consistent with the original OFFER, so that
	  subsequent requests get the same answer.
	* Ensure the same IP address isn't offered to a different client.
	* Improve performance by reducing the frequency of datastore lookups.

IMPLEMENTATION OVERVIEW
=======================

The cache implementation consists of a number of hash tables and lists,
enumerated below, along with a timeout and refresh mechanism:

	* A global DHCP table hash (ntable):

	  Each active network table (dvsc_dnet_t) is hashed by subnet number
	  into a global hash called 'ntable'.  The dsvc_dnet_t itself
	  contains a variety of information about each subnet, an access
	  handle to the underlying datastore, and a variety of caches which
	  we describe next.

	  An ntable hash entry will be removed after DHCP_NET_THRESHOLD
	  seconds of inactivity.

	* A per-network client hash (ctable):

	  Each client structure (dsvc_clnt_t) is hashed by client identifier
	  into the per-network ctable.  This table is used by the interface
	  worker thread to get client information.

	  A ctable hash entry will be removed if the client does not communicate
	  with the server for DHCP_CLIENT_THRESHOLD seconds.

	* A per-network offer hash (itable):

	  The IP address associated with each pending OFFER is hashed into
	  the per-network itable.  This table is used to reserve the offered
	  and in-use IP addresses on the given network.

	  An itable hash entry will be removed if more than DSVC_CV_OFFER_TTL
	  seconds elapse without update_offer() being called on it.

	* A per-network free record list (freerec):

	  This is a cache of free records, populated with any unused records
	  retrieved from previous datastore lookups or from IP addresses that
	  have been explicitly released by DHCP clients.  This is the first
	  list select_offer() consults.

	  An entry in the freerec list expires after DSVC_CV_CACHE_TTL seconds.

	* A per-network least recently used record list (lrurec)

	  This is a cache of least recently used records, populated with any
	  unused records retrieved from a previous datastore lookup for
	  LRU records.  This is the second list select_offer() consults, after
	  checking freerec.

	  An entry in the lrurec list expires after DSVC_CV_CACHE_TTL seconds.

The concurrency between the datastore and cached records is handled by the
underlying datastore implementation using perimeters and is transparent to
in.dhcpd.  $SRC/lib/libdhcpsvc/private/{private.c,public.c} implement the
functions used by in.dhcpd and DHCP server admin tools to lookup and modify
the underlying datastore records.

TRANSACTIONS
============

When in.dhcpd receives a packet from a client, the interface thread first
calls open_dnet() to retrieve the dsvc_dnet_t which describes the network.
The dsvc_dnet_t is either in the ntable hash, in which case it is returned,
or a new dsvc_dnet_t is allocated and inserted to ntable.  Then, using the
dsvc_dnet_t, the interface thread calls open_clnt(), which searches the
dsvc_dnet_t's ctable hash and returns the client structure (dsvc_clnt_t) if
found.  Otherwise, a new dsvc_clnt_t is allocated and inserted into the
ctable.  Finally, the packet is put to the client's packet list so that the
client thread can process it.

The client thread then processes the packet according to whether it's a
DISCOVER, REQUEST, RELEASE, or DECLINE.

For a DISCOVER:

	1. If there is a pre-assigned IP for this client and the cached offer
	   is not timed out, then use the IP and the record in the
	   dsvc_clnt_t and make an OFFER.

	2. If there is a pre-assigned IP but the cached offer is expired,
	   remove the cached OFFER from the itable, and try to find a new
	   record for the client (see below).

	3. If there is no pre-assigned IP for this client, just try to find
	   a new record for the client (see following text).

	To find a new record, the client thread first searches the datastore
	for a record matching the client identifier provided in the packet.
	If none is found, then the free record list (freerec) and least
	recently used record list (lrurec) are searched, in that order.  If
	either freerec or lrurec is empty, or the head record on either list
	is expired, in.dhcpd removes any existing records and attempts to
	repopulate them by performing datastore lookups.  Finally, any
	unused records are cached for later use.

	If a usable record is found, the server generates and sends an OFFER
	to the client.  Once sent, the client's dsvc_clnt_t is inserted to
	the dsvc_dnet_t's itable if it is a new IP, or the itable is refreshed
	if it is a pre-assigned IP.

For a REQUEST:

	1. If the REQUEST is a reply to a previous OFFER, it checks if the
	   OFFER has expired.  If not, the itable timer is reset, the client
	   record is updated, and the ACK is sent.  If it is expired and the
	   address cannot be confirmed to still be free, the REQUEST is 
	   silently ignored (and the client should eventually drop back
	   to DISCOVER).

	2. If the REQUEST is associated with a client INIT-REBOOT or a client
	   extending a lease, then the client thread does a datastore lookup
	   by client identifier.  If a match is found, the record is updated
	   and an ACK is sent.

If the packet is a RELEASE, the client thread modifies the record in the
datastore so that it is marked free, and, if successful, puts the record onto
the free record list (freerec).

Finally, if the packet is a DECLINE, the client thread modifies the record in
the datastore so that it is marked unusable.