xref: /illumos-gate/usr/src/uts/common/inet/ilb/ilb_impl.h (revision afab0816ecb604f0099a09ad8ee398f0d7b77b1c)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _INET_ILB_IMPL_H
28 #define	_INET_ILB_IMPL_H
29 
30 #include <sys/types.h>
31 #include <sys/kstat.h>
32 #include <sys/netstack.h>
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /*
39  * Statistics in ILB is stored in several kstat structures.  ilb_g_kstat
40  * represents the global statistics.  ilb_rule_kstat represents the statistics
41  * of a rule.  ilb_server_kstat represents the statistics of a server.
42  */
43 #define	ILB_KSTAT_MOD_NAME	"ilb"
44 
45 typedef struct ilb_g_kstat_s {
46 	kstat_named_t	num_rules;	/* Number of rules */
47 	kstat_named_t	ip_frag_in;	/* Number of input fragments */
48 	kstat_named_t	ip_frag_dropped; /* Number of fragments dropped */
49 } ilb_g_kstat_t;
50 
51 #define	ILB_KSTAT_UPDATE(ilbs, x, y)				\
52 {								\
53 	DTRACE_PROBE1(ilb__g__kstat__##x, ilb_stack_t *,	\
54 	    (ilbs));						\
55 	((ilbs)->ilbs_kstat->x.value.ui64 += (y));		\
56 }
57 
58 typedef struct ilb_rule_kstat {
59 	kstat_named_t	num_servers;	/* Number of back end servers */
60 	kstat_named_t	bytes_not_processed; /* Num of bytes not processed. */
61 	kstat_named_t	pkt_not_processed; /* Num of packets not processed. */
62 	kstat_named_t	bytes_dropped;	/* Number of bytes dropped */
63 	kstat_named_t	pkt_dropped;	/* Number of packets dropped */
64 	kstat_named_t	nomem_bytes_dropped; /* Bytes dropped due to nomem */
65 	kstat_named_t	nomem_pkt_dropped; /* Packets dropped due to nomem */
66 	kstat_named_t	noport_bytes_dropped; /* No NAT sport bytes drop */
67 	kstat_named_t	noport_pkt_dropped; /* No NAT sport packet drop */
68 	kstat_named_t	icmp_echo_processed; /* No of ICMP echo processed */
69 	kstat_named_t	icmp_dropped;	/* No of ICMP packets dropped */
70 	kstat_named_t	icmp_2big_processed; /* No of ICMP 2big processed */
71 	kstat_named_t	icmp_2big_dropped; /* No of ICMP 2big dropped */
72 } ilb_rule_kstat_t;
73 
74 #define	ILB_R_KSTAT(rule, x)					\
75 {								\
76 	DTRACE_PROBE1(ilb__r__kstat__##x, ilb_rule_t *,	\
77 	    (rule));						\
78 	((rule)->ir_kstat.x.value.ui64++);			\
79 }
80 #define	ILB_R_KSTAT_UPDATE(rule, x, y) 				\
81 {								\
82 	DTRACE_PROBE1(ilb__r__kstat__##x, ilb_rule_t *,	\
83 	    (rule));						\
84 	((rule)->ir_kstat.x.value.ui64 += (y));			\
85 }
86 
87 typedef struct ilb_server_kstat {
88 	kstat_named_t	bytes_processed; /* Number of bytes processed */
89 	kstat_named_t	pkt_processed;	/* Number of packets processed */
90 	kstat_named_t	ip_address;	/* IP address of the server */
91 } ilb_server_kstat_t;
92 
93 #define	ILB_S_KSTAT(host, x)					\
94 {								\
95 	DTRACE_PROBE1(ilb__s__kstat__##x, ilb_server_t *,	\
96 	    (host));						\
97 	((host)->iser_kstat.x.value.ui64++);			\
98 }
99 #define	ILB_S_KSTAT_UPDATE(host, x, y)				\
100 {								\
101 	DTRACE_PROBE1(ilb__s__kstat__##x, ilb_server_t *,	\
102 	    (host));						\
103 	((host)->iser_kstat.x.value.ui64 += (y));		\
104 }
105 
106 /* The maximum port range, meaning all ports (65535 - 1). */
107 #define	ILB_ALL_PORTS_RANGE	65534
108 
109 struct ilb_nat_src_s;
110 
111 /*
112  * This structure reprensents a server.
113  */
114 typedef struct ilb_server_s {
115 	in6_addr_t		iser_addr_v6;
116 	in6_addr_t		iser_prefix_v6;
117 #define	iser_addr_v4		iser_addr_v6.s6_addr32[3]
118 #define	iser_prefix_v4		iser_prefix_v6.s6_addr32[3]
119 
120 	boolean_t		iser_port_range;
121 	in_port_t		iser_min_port;	/* In host byte order */
122 	in_port_t		iser_max_port;
123 
124 	char			iser_name[ILB_SERVER_NAMESZ];
125 	char			iser_ip_addr[INET6_ADDRSTRLEN];
126 	netstackid_t		iser_stackid;
127 	kstat_t			*iser_ksp;
128 	ilb_server_kstat_t	iser_kstat;
129 	struct ilb_server_s	*iser_next;
130 
131 	boolean_t		iser_enabled;
132 	kmutex_t		iser_lock;
133 	kcondvar_t		iser_cv;
134 	uint64_t		iser_refcnt;
135 
136 	int64_t			iser_die_time;
137 
138 	struct ilb_nat_src_s	*iser_nat_src;
139 } ilb_server_t;
140 
141 #define	ILB_SERVER_REFHOLD(host)	\
142 {					\
143 	mutex_enter(&(host)->iser_lock);	\
144 	(host)->iser_refcnt++;		\
145 	ASSERT((host)->iser_refcnt != 1);	\
146 	mutex_exit(&(host)->iser_lock);	\
147 }
148 
149 #define	ILB_SERVER_REFRELE(host)		\
150 {						\
151 	mutex_enter(&(host)->iser_lock);		\
152 	(host)->iser_refcnt--;			\
153 	if ((host)->iser_refcnt == 1)		\
154 		cv_signal(&(host)->iser_cv);	\
155 	mutex_exit(&(host)->iser_lock);		\
156 }
157 
158 struct ilb_rule_s;
159 struct ilb_hash_s;
160 
161 typedef struct ilb_alg_data_s {
162 	boolean_t	(*ilb_alg_lb)(in6_addr_t *, in_port_t, in6_addr_t *,
163 			    in_port_t, void *, ilb_server_t **);
164 	int		(*ilb_alg_server_add)(ilb_server_t *, void *);
165 	int		(*ilb_alg_server_del)(ilb_server_t *, void *);
166 	int		(*ilb_alg_server_enable)(ilb_server_t *, void *);
167 	int		(*ilb_alg_server_disable)(ilb_server_t *, void *);
168 	void		(*ilb_alg_fini)(struct ilb_alg_data_s **);
169 
170 	void		*ilb_alg_data;
171 } ilb_alg_data_t;
172 
173 /*
174  * A load balance rule has
175  *
176  * 1. a name
177  * 2. a network protocol
178  * 3. a transport protocol
179  * 4. a load balance mechanism (DSR, NAT, ...)
180  * 5. a target address (VIP)
181  * 6. a target port (or port ranges)
182  * 7. a pool of back end servers
183  * 8. a load balance algorithm (round robin, hashing, ...)
184  */
185 typedef struct ilb_rule_s {
186 	char			ir_name[ILB_RULE_NAMESZ];
187 	uint8_t			ir_ipver;
188 	uint8_t			ir_proto;
189 	ilb_topo_impl_t		ir_topo;
190 	zoneid_t		ir_zoneid;
191 	uint32_t		ir_flags;
192 
193 	in6_addr_t		ir_target_v6;
194 #define	ir_target_v4		ir_target_v6.s6_addr32[3]
195 	in6_addr_t		ir_prefix_v6;
196 #define	ir_target_prefix_v4	ir_prefix_v6.s6_addr32[3]
197 
198 	boolean_t		ir_port_range;
199 	in_port_t		ir_min_port;	/* In host byte order */
200 	in_port_t		ir_max_port;
201 
202 	ilb_server_t		*ir_servers;
203 
204 	uint32_t		ir_nat_expiry;
205 	uint32_t		ir_conn_drain_timeout;
206 	in6_addr_t		ir_nat_src_start;
207 	in6_addr_t		ir_nat_src_end;
208 
209 	boolean_t		ir_sticky;
210 	in6_addr_t		ir_sticky_mask;
211 	uint32_t		ir_sticky_expiry;
212 
213 	struct ilb_rule_s	*ir_next;
214 
215 	struct ilb_rule_s	*ir_hash_next;
216 	struct ilb_rule_s	*ir_hash_prev;
217 	struct ilb_hash_s	*ir_hash;
218 
219 	ilb_algo_impl_t		ir_alg_type;
220 	ilb_alg_data_t		*ir_alg;
221 
222 	kstat_t			*ir_ksp;
223 	ilb_rule_kstat_t	ir_kstat;
224 	uint_t			ir_ks_instance;
225 
226 	kmutex_t		ir_lock;
227 	kcondvar_t		ir_cv;
228 	uint32_t		ir_refcnt;
229 } ilb_rule_t;
230 
231 #define	ILB_RULE_REFHOLD(rule)			\
232 {						\
233 	mutex_enter(&(rule)->ir_lock);		\
234 	(rule)->ir_refcnt++;			\
235 	ASSERT((rule)->ir_refcnt != 1);		\
236 	mutex_exit(&(rule)->ir_lock);		\
237 }
238 
239 #define	ILB_RULE_REFRELE(rule)			\
240 {						\
241 	mutex_enter(&(rule)->ir_lock);		\
242 	ASSERT((rule)->ir_refcnt >= 2);		\
243 	if (--(rule)->ir_refcnt <= 2)		\
244 		cv_signal(&(rule)->ir_cv);	\
245 	mutex_exit(&(rule)->ir_lock);		\
246 }
247 
248 
249 typedef struct ilb_hash_s {
250 	ilb_rule_t	*ilb_hash_rule;
251 	kmutex_t	ilb_hash_lock;
252 #if defined(_LP64) || defined(_I32LPx)
253 	char		ilb_hash_pad[48];
254 #else
255 	char		ilb_hash_pad[56];
256 #endif
257 } ilb_hash_t;
258 
259 struct ilb_nat_src_entry_s;
260 
261 /*
262  * Structure to store NAT info.
263  *
264  * Half NAT only uses the first 4 fields in the structure.
265  */
266 typedef struct {
267 	in6_addr_t			vip;
268 	in6_addr_t			nat_dst;
269 	in_port_t			dport;
270 	in_port_t			nat_dport;
271 
272 	in6_addr_t			src;
273 	in6_addr_t			nat_src;
274 	in_port_t			sport;
275 	in_port_t			nat_sport;
276 
277 	struct ilb_nat_src_entry_s	*src_ent;
278 } ilb_nat_info_t;
279 
280 extern int ilb_kmem_flags;
281 
282 #ifdef __cplusplus
283 }
284 #endif
285 
286 #endif /* _INET_ILB_IMPL_H */
287