summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/udp_impl.h
blob: 0fc597ccf34812c4a9d032dfe278dfa4a6833dcf (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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (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 (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2015, Joyent, Inc.
 */

#ifndef	_UDP_IMPL_H
#define	_UDP_IMPL_H

/*
 * UDP implementation private declarations.  These interfaces are
 * used to build the IP module and are not meant to be accessed
 * by any modules except IP itself.  They are undocumented and are
 * subject to change without notice.
 */

#ifdef	__cplusplus
extern "C" {
#endif

#ifdef _KERNEL

#include <sys/int_types.h>
#include <sys/netstack.h>

#include <netinet/in.h>
#include <netinet/ip6.h>

#include <inet/common.h>
#include <inet/ip.h>
#include <inet/optcom.h>
#include <inet/tunables.h>

#define	UDP_MOD_ID		5607

/*
 * Bind hash list size and hash function.  It has to be a power of 2 for
 * hashing.
 */
#define	UDP_BIND_FANOUT_SIZE	512
#define	UDP_BIND_HASH(lport, size) \
	((ntohs((uint16_t)lport)) & (size - 1))

/* UDP bind fanout hash structure. */
typedef struct udp_fanout_s {
	struct udp_s *uf_udp;
	kmutex_t uf_lock;
#if defined(_LP64) || defined(_I32LPx)
	char	uf_pad[48];
#else
	char	uf_pad[56];
#endif
} udp_fanout_t;

/* Kstats */
typedef struct udp_stat {			/* Class "net" kstats */
	kstat_named_t	udp_sock_fallback;
	kstat_named_t	udp_out_opt;
	kstat_named_t	udp_out_err_notconn;
	kstat_named_t	udp_out_err_output;
	kstat_named_t	udp_out_err_tudr;
#ifdef DEBUG
	kstat_named_t	udp_data_conn;
	kstat_named_t	udp_data_notconn;
	kstat_named_t	udp_out_lastdst;
	kstat_named_t	udp_out_diffdst;
	kstat_named_t	udp_out_ipv6;
	kstat_named_t	udp_out_mapped;
	kstat_named_t	udp_out_ipv4;
#endif
} udp_stat_t;

/*
 * This struct contains only the counter part of udp_stat_t.  It is used
 * in udp_stats_cpu_t instead of udp_stat_t to save memory space.
 */
typedef struct {
	uint64_t	udp_sock_fallback;
	uint64_t	udp_out_opt;
	uint64_t	udp_out_err_notconn;
	uint64_t	udp_out_err_output;
	uint64_t	udp_out_err_tudr;
#ifdef DEBUG
	uint64_t	udp_data_conn;
	uint64_t	udp_data_notconn;
	uint64_t	udp_out_lastdst;
	uint64_t	udp_out_diffdst;
	uint64_t	udp_out_ipv6;
	uint64_t	udp_out_mapped;
	uint64_t	udp_out_ipv4;
#endif
} udp_stat_counter_t;

/* Per CPU stats: UDP MIB2 and UDP kstat. */
typedef struct {
	mib2_udp_t		udp_sc_mib;
	udp_stat_counter_t	udp_sc_stats;
} udp_stats_cpu_t;

#define	UDP_NUM_EPRIV_PORTS	64

/* Default buffer size and flow control wake up threshold. */
#define	UDP_RECV_HIWATER	(56 * 1024)
#define	UDP_RECV_LOWATER	128
#define	UDP_XMIT_HIWATER	(56 * 1024)
#define	UDP_XMIT_LOWATER	1024

/*
 * UDP stack instances
 */
struct udp_stack {
	netstack_t	*us_netstack;	/* Common netstack */

	uint_t		us_bind_fanout_size;
	udp_fanout_t	*us_bind_fanout;

	int		us_num_epriv_ports;
	in_port_t	us_epriv_ports[UDP_NUM_EPRIV_PORTS];
	kmutex_t	us_epriv_port_lock;

	/* Hint not protected by any lock */
	in_port_t	us_next_port_to_try;

	/* UDP tunables table */
	struct mod_prop_info_s	*us_propinfo_tbl;

	kstat_t		*us_mibkp;	/* kstats exporting mib data */
	kstat_t		*us_kstat;

/*
 * The smallest anonymous port in the priviledged port range which UDP
 * looks for free port.  Use in the option UDP_ANONPRIVBIND.
 */
	in_port_t	us_min_anonpriv_port;

	ldi_ident_t	us_ldi_ident;

	udp_stats_cpu_t	**us_sc;
	int		us_sc_cnt;
};

typedef struct udp_stack udp_stack_t;

/* Internal udp control structure, one per open stream */
typedef	struct udp_s {
	/*
	 * The addresses and ports in the conn_t and udp_state are protected by
	 * conn_lock and the fanout lock i.e. uf_lock. Need both locks to change
	 * the fields, either lock is sufficient for reading the field.
	 * conn_lock also protects the content of udp_t.
	 */
	uint32_t	udp_state;	/* TPI state */

	ip_pkt_t	udp_recv_ipp;	/* Used for IPv4 options received */

	/* Written to only once at the time of opening the endpoint */
	conn_t		*udp_connp;

	uint32_t
		udp_issocket : 1,	/* socket mode; sockfs is on top */
		udp_nat_t_endpoint : 1,	/* UDP_NAT_T_ENDPOINT option */
		udp_rcvhdr : 1,		/* UDP_RCVHDR option */

		udp_vxlanhash: 1,	/* UDP_SRCPORT_HASH option */
					/* Because there's only VXLAN, cheat */
					/* and only use a single bit */

		udp_pad_to_bit_31 : 28;

	/* Following 2 fields protected by the uf_lock */
	struct udp_s	*udp_bind_hash; /* Bind hash chain */
	struct udp_s	**udp_ptpbhn; /* Pointer to previous bind hash next. */

	kmutex_t	udp_recv_lock;		/* recv lock */
	size_t		udp_rcv_disply_hiwat;	/* user's view of rcvbuf */
	size_t		udp_rcv_hiwat;		/* receive high watermark */

	/* Set at open time and never changed */
	udp_stack_t	*udp_us;		/* Stack instance for zone */

	int		udp_delayed_error;
	mblk_t		*udp_fallback_queue_head;
	mblk_t		*udp_fallback_queue_tail;
	struct sockaddr_storage	udp_delayed_addr;
} udp_t;

/* UDP Protocol header aligned */
typedef	struct udpahdr_s {
	in_port_t	uha_src_port;		/* Source port */
	in_port_t	uha_dst_port;		/* Destination port */
	uint16_t	uha_length;		/* UDP length */
	uint16_t	uha_checksum;		/* UDP checksum */
} udpha_t;

#define	us_wroff_extra			us_propinfo_tbl[0].prop_cur_uval
#define	us_ipv4_ttl			us_propinfo_tbl[1].prop_cur_uval
#define	us_ipv6_hoplimit		us_propinfo_tbl[2].prop_cur_uval
#define	us_smallest_nonpriv_port	us_propinfo_tbl[3].prop_cur_uval
#define	us_do_checksum			us_propinfo_tbl[4].prop_cur_bval
#define	us_smallest_anon_port		us_propinfo_tbl[5].prop_cur_uval
#define	us_largest_anon_port		us_propinfo_tbl[6].prop_cur_uval
#define	us_xmit_hiwat			us_propinfo_tbl[7].prop_cur_uval
#define	us_xmit_lowat			us_propinfo_tbl[8].prop_cur_uval
#define	us_recv_hiwat			us_propinfo_tbl[9].prop_cur_uval
#define	us_max_buf			us_propinfo_tbl[10].prop_cur_uval
#define	us_pmtu_discovery		us_propinfo_tbl[11].prop_cur_bval
#define	us_sendto_ignerr		us_propinfo_tbl[12].prop_cur_bval

#define	UDPS_BUMP_MIB(us, x)	\
	BUMP_MIB(&(us)->us_sc[CPU->cpu_seqid]->udp_sc_mib, x)

#define	UDP_STAT(us, x)		((us)->us_sc[CPU->cpu_seqid]->udp_sc_stats.x++)
#define	UDP_STAT_UPDATE(us, x, n)	\
	((us)->us->sc[CPU->cpu_seqid]->udp_sc_stats.x.value.ui64 += (n))
#ifdef DEBUG
#define	UDP_DBGSTAT(us, x)	UDP_STAT(us, x)
#else
#define	UDP_DBGSTAT(us, x)
#endif /* DEBUG */

extern int	udp_opt_default(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
extern int	udp_tpi_opt_get(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
extern int	udp_tpi_opt_set(queue_t *, uint_t, int, int, uint_t, uchar_t *,
		    uint_t *, uchar_t *, void *, cred_t *);
extern mblk_t	*udp_snmp_get(queue_t *, mblk_t *, boolean_t);
extern int	udp_snmp_set(queue_t *, t_scalar_t, t_scalar_t, uchar_t *, int);
extern void	udp_ddi_g_init(void);
extern void	udp_ddi_g_destroy(void);
extern void	udp_output(conn_t *connp, mblk_t *mp, struct sockaddr *addr,
		    socklen_t addrlen);
extern int	udp_wput(queue_t *, mblk_t *);

extern void	*udp_kstat_init(netstackid_t stackid);
extern void	udp_kstat_fini(netstackid_t stackid, kstat_t *ksp);
extern void	*udp_kstat2_init(netstackid_t stackid);
extern void	udp_kstat2_fini(netstackid_t, kstat_t *);

extern void	udp_stack_cpu_add(udp_stack_t *, processorid_t);

/*
 * Object to represent database of options to search passed to
 * {sock,tpi}optcom_req() interface routine to take care of option
 * management and associated methods.
 */
extern optdb_obj_t	udp_opt_obj;
extern uint_t		udp_max_optsize;

extern sock_lower_handle_t udp_create(int, int, int, sock_downcalls_t **,
    uint_t *, int *, int, cred_t *);
extern int udp_fallback(sock_lower_handle_t, queue_t *, boolean_t,
    so_proto_quiesced_cb_t, sock_quiesce_arg_t *);

extern sock_downcalls_t sock_udp_downcalls;

#endif	/*  _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _UDP_IMPL_H */