sctp_impl.h revision a215d4eb400e2ff52f7a17e0781964c37aabfc04
/*
* 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
* 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
*/
/*
*/
#ifndef _INET_SCTP_SCTP_IMPL_H
#define _INET_SCTP_SCTP_IMPL_H
#include <sys/inttypes.h>
#include <sys/clock_impl.h>
#include <inet/tunables.h>
#include <inet/sctp_itf.h>
#include "sctp_stack.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Streams device identifying info and version */
#define SCTP_DEV_IDINFO "SCTP Streams device 1.0"
/* Default buffer size and flow control wake up threshold. */
#define SCTP_XMIT_LOWATER 8192
#define SCTP_XMIT_HIWATER 102400
#define SCTP_RECV_LOWATER 8192
#define SCTP_RECV_HIWATER 102400
/* SCTP Timer control structure */
typedef struct sctpt_s {
struct sctp_faddr_s *sctpt_faddr;
} sctpt_t;
/*
* Maximum number of duplicate TSNs we can report. This is currently
* static, and governs the size of the mblk used to hold the duplicate
* reports. The use of duplcate TSN reports is currently experimental,
* so for now a static limit should suffice.
*/
#define SCTP_DUP_MBLK_SZ 64
/*
* SCTP properties/tunables
*/
/*
* Retransmission timer start and stop macro for a given faddr.
*/
{ \
}
#define SCTP_FADDR_TIMER_STOP(fp) \
if ((fp)->sf_timer_running) { \
(fp)->sf_timer_running = 0; \
}
/* For per endpoint association statistics */
/* \
* Record the maximum observed RTO, \
* sctp_maxrto is zeroed elsewhere \
* at the end of each stats request. \
*/ \
(sctp)->sctp_maxrto = \
}
{ \
}
#define SCTP_MAX_HDR_LENGTH 60
#define SCTP_SECRET_LEN 16
#define SCTP_REFHOLD(sctp) { \
(sctp)->sctp_refcnt++; \
}
#define SCTP_REFRELE(sctp) { \
if (--(sctp)->sctp_refcnt == 0) { \
} else { \
} \
}
/*
* Outbound data, flags and macros for per-message, per-chunk info
*/
typedef struct {
#define SCTP_CHUNK_FLAG_SENT 0x01
#define SCTP_CHUNK_FLAG_REXMIT 0x02
#define SCTP_CHUNK_FLAG_ACKED 0x04
#define SCTP_MSG_FLAG_CHUNKED 0x08
#define SCTP_MSG_FLAG_ABANDONED 0x10
#define SCTP_CHUNK_FLAG_ABANDONED 0x20
/*
* If we are transmitting the chunk for the first time we assign the TSN and
* SSN here. The reason we assign the SSN here (as opposed to doing it in
* sctp_chunkify()) is that the chunk may expire, if PRSCTP is enabled, before
* we get a chance to send it out. If we assign the SSN in sctp_chunkify()
* and this happens, then we need to send a Forward TSN to the peer, which
* will be expecting this SSN, assuming ordered. If we assign it here we
* can just take out the chunk from the transmit list without having to
* send a Forward TSN chunk. While assigning the SSN we use (meta)->b_cont
* to determine if it needs a new SSN (i.e. the next SSN for the stream),
* since (meta)->b_cont signifies the first chunk of a message (if the message
* is unordered, then the SSN is 0).
*
*/
if (!SCTP_CHUNK_ISSENT(mp)) { \
} else { \
} \
} \
} else { \
if (SCTP_CHUNK_ISACKED(mp)) { \
} else { \
sizeof (*sdc))); \
sizeof (*sdc)); \
} \
SCTP_CHUNK_SET_SACKCNT(mp, 0); \
} \
}
#define SCTP_CHUNK_CANSEND(mp) \
(!(SCTP_CHUNK_ABANDONED(mp)) && \
mp); \
}
#define SCTP_CHUNK_ACKED(mp) \
mp); \
}
/* For PR-SCTP */
#define SCTP_CHUNK_ABANDONED(mp) \
#define SCTP_MSG_SET_ABANDONED(mp) \
/*
* Check if a message has expired. A message is expired if
* 1. It has a non-zero time to live value and has not been sent before
* that time expires.
* 2. It is sent using PRSCTP and it has not been SACK'ed before
* its lifetime expires.
*/
/* SCTP association hash function. */
/*
* Linked list struct to store SCTP listener association limit configuration
* per IP stack. The list is stored at sctps_listener_conf in sctp_stack_t.
*
* sl_port: the listener port of this limit configuration
* sl_ratio: the maximum amount of memory consumed by all concurrent SCTP
* connections created by a listener does not exceed 1/tl_ratio
* of the total system memory. Note that this is only an
* approximation.
* sl_link: linked list struct
*/
typedef struct sctp_listener_s {
/*
* If there is a limit set on the number of association allowed per each
* listener, the following struct is used to store that counter. It keeps
* the number of SCTP association created by a listener. Note that this needs
* to be separated from the listener since the listener can go away before
* all the associations are gone.
*
* When the struct is allocated, slc_cnt is set to 1. When a new association
* is created by the listener, slc_cnt is incremented by 1. When an
* association created by the listener goes away, slc_count is decremented by
* 1. When the listener itself goes away, slc_cnt is decremented by one.
* The last association (or the listener) which decrements slc_cnt to zero
* frees the struct.
*
* slc_max is the maximum number of concurrent associations created from a
* listener. It is calculated when the sctp_listen_cnt_t is allocated.
*
* slc_report_time stores the time when cmn_err() is called to report that the
* max has been exceeeded. Report is done at most once every
* SCTP_SLC_REPORT_INTERVAL mins for a listener.
*
* slc_drop stores the number of connection attempt dropped because the
* limit has reached.
*/
typedef struct sctp_listen_cnt_s {
#define SCTP_DECR_LISTEN_CNT(sctp) \
{ \
}
/* Increment and decrement the number of associations in sctp_stack_t. */
#define SCTPS_ASSOC_INC(sctps) \
#define SCTPS_ASSOC_DEC(sctps) \
{ \
SCTPS_ASSOC_INC(sctps); \
}
/*
* Bind hash array size and hash function. The size must be a power
* of 2 and lport must be in host byte order.
*/
#define SCTP_BIND_FANOUT_SIZE 2048
/* options that SCTP negotiates during association establishment */
#define SCTP_PRSCTP_OPTION 0x01
/*
* Listener hash array size and hash function. The size must be a power
* of 2 and lport must be in host byte order.
*/
#define SCTP_LISTEN_FANOUT_SIZE 512
typedef struct sctp_tf_s {
} sctp_tf_t;
/* Round up the value to the nearest mss. */
/* Data structure used to track received TSNs */
typedef struct sctp_set_s {
struct sctp_set_s *next;
struct sctp_set_s *prev;
} sctp_set_t;
/* Data structure used to track TSNs for PR-SCTP */
typedef struct sctp_ftsn_set_s {
struct sctp_ftsn_set_s *next;
/* Data structure used to track incoming SCTP streams */
typedef struct sctp_instr_s {
int istr_nmsgs;
} sctp_instr_t;
/* Reassembly data structure (per-stream) */
typedef struct sctp_reass_s {
/* from the begining (B-bit) */
/* a B-bit set chunk */
/* are expecting */
} sctp_reass_t;
/* debugging */
#ifdef DEBUG
extern int sctpdebug;
#else
#endif
/* Peer address tracking */
/*
* States for peer addresses
*
* SCTP_FADDRS_UNCONFIRMED: we have not communicated with this peer address
* before, mark it as unconfirmed so that we will not send data to it.
* All addresses initially are in unconfirmed state and required
* validation. SCTP sends a heartbeat to each of them and when it gets
* back a heartbeat ACK, the address will be marked as alive. This
* validation fixes a security issue with multihoming. If an attacker
* establishes an association with us and tells us that it has addresses
* belonging to another host A, this will prevent A from communicating
* with us. This is fixed by peer address validation. In the above case,
* A will respond with an abort.
*
* SCTP_FADDRS_ALIVE: this peer address is alive and we can communicate with
* it with no problem.
*
* SCTP_FADDRS_DOWN: we have exceeded the retransmission limit to this
* peer address. Once an address is marked down, we will only send
* a heartbeat to it every hb_interval in case it becomes alive now.
*
* SCTP_FADDRS_UNREACH: there is no suitable source address to send to
* this peer address. For example, the peer address is v6 but we only
* have v4 addresses. It is marked unreachable until there is an
* address configuration change. At that time, mark these addresses
* as unconfirmed and try again to see if those unreachable addresses
* are OK as we may have more source addresses.
*/
typedef enum {
typedef struct sctp_faddr_s {
struct sctp_faddr_s *sf_next;
int sf_rto; /* RTO in tick */
int sf_srtt; /* Smoothed RTT in tick */
int sf_rttvar; /* RTT variance in tick */
int sf_strikes;
int sf_max_retr;
sf_hb_pending : 1,
sf_timer_running : 1,
sf_df : 1,
sf_pmtu_discovered : 1,
sf_rc_timer_running : 1,
sf_isv4 : 1,
sf_hb_enabled : 1;
} sctp_faddr_t;
/* Flags to indicate supported address type in the PARM_SUP_ADDRS. */
#define PARM_SUPP_V6 0x1
#define PARM_SUPP_V4 0x2
/*
* Set heartbeat interval plus jitter. The jitter is supposed to be random,
* up to +/- 50% of the RTO. We use gethrtime() here for performance reason
* as the jitter does not really need to be "very" random.
*/
#define SET_HB_INTVL(fp) \
#define SCTP_IPIF_HASH 16
typedef struct sctp_ipif_hash_s {
int ipif_count;
/*
* Initialize cwnd according to RFC 3390. def_max_init_cwnd is
* either sctp_slow_start_initial or sctp_slow_start_after idle
* depending on the caller.
*/
{ \
}
struct sctp_s;
/*
* Control structure for each open SCTP stream,
* defined only within the kernel or for a kmem user.
* NOTE: sctp_reinit_values MUST have a line for each field in this structure!
*/
typedef struct sctp_s {
/*
* The following is shared with (and duplicated) in IP, so if you
* make changes, make sure you also change things in ip_sctp.c.
*/
struct sctp_s *sctp_conn_hash_next;
struct sctp_s *sctp_conn_hash_prev;
struct sctp_s *sctp_listen_hash_next;
struct sctp_s *sctp_listen_hash_prev;
/* Global list of sctp */
int sctp_nfaddrs;
int sctp_nsaddrs;
/* Peer address tracking */
/* Outbound data tracking */
/* sendmsg() default parameters */
/* Inbound data tracking */
/* RTT calculation */
/* Stats can be reset by snmp users kstat, netstat and snmp agents */
/* Inbound flow control */
/* Pre-initialized composite headers */
/* Path MTU Discovery */
/* structs sctp_bits, sctp_events are for clearing all bits at once */
struct {
sctp_force_sack : 1,
sctp_bound_to_all : 1,
sctp_dummy : 5;
} sctp_bits;
struct {
sctp_recvsndrcvinfo : 1,
sctp_recvassocevnt : 1,
sctp_recvpathevnt : 1,
sctp_recvpeererr : 1,
sctp_recvpdevnt : 1,
sctp_recvalevnt : 1;
} sctp_events;
/* Retransmit info */
/* Bind hash tables */
struct sctp_s *sctp_bind_hash;
struct sctp_s **sctp_ptpbhn;
/* Shutdown / cleanup */
/* Reliable control chunks */
/* Per association receive queue */
/* IPv6 ancillary data */
/* Stats */
int sctp_pd_point; /* Partial delivery point */
/* additional source data for per endpoint association statistics */
/*
* Add the current data from the counters which are reset by snmp
* to these cumulative counters to use in per endpoint statistics.
*/
/*
* When non-zero, this is the maximum observed RTO since assoc stats
* were last requested. When zero, no RTO update has occurred since
* the previous user request for stats on this endpoint.
*/
int sctp_maxrto;
/*
* The stored value of sctp_maxrto passed to user during the previous
* user request for stats on this endpoint.
*/
int sctp_prev_maxrto;
/* For association counting. */
} sctp_t;
#define SCTP_TXQ_UPDATE(sctp) \
(sctp)->sctp_txq_full = 0; \
B_FALSE); \
}
#endif /* (defined(_KERNEL) || defined(_KMEMUSER)) */
extern void sctp_ack_timer(sctp_t *);
extern void sctp_adaptation_event(sctp_t *);
sctp_faddr_t *);
ip_recv_attr_t *);
int *);
zoneid_t, sctp_stack_t *);
sctp_chunk_hdr_t *);
extern void sctp_bind_hash_remove(sctp_t *);
extern int sctp_build_hdrs(sctp_t *, int);
extern void sctp_clean_death(sctp_t *, int);
extern void sctp_close_eager(sctp_t *);
extern void sctp_congest_reset(sctp_t *);
extern void sctp_conn_hash_remove(sctp_t *);
extern void sctp_conn_init(conn_t *);
extern void sctp_conn_reclaim(void *);
sctp_init_chunk_t *, ip_recv_attr_t *);
extern char *sctp_display(sctp_t *, char *);
extern void sctp_display_all(sctp_stack_t *);
extern void sctp_faddr_fini(void);
extern void sctp_faddr_init(void);
extern void sctp_fast_rexmit(sctp_t *);
extern void sctp_fill_sack(sctp_t *, unsigned char *, int);
extern void sctp_free_faddr_timers(sctp_t *);
extern void sctp_free_ftsn_set(sctp_ftsn_set_t *);
extern void sctp_free_msg(mblk_t *);
extern void sctp_free_reass(sctp_instr_t *);
extern void sctp_free_set(sctp_set_t *);
extern void sctp_ftsn_sets_fini(void);
extern void sctp_ftsn_sets_init(void);
sctp_chunk_hdr_t *, uint_t *);
mblk_t *, ip_recv_attr_t *);
extern void sctp_hash_destroy(sctp_stack_t *);
extern void sctp_hash_init(sctp_stack_t *);
extern void sctp_heartbeat_timer(sctp_t *);
extern void sctp_inc_taskq(sctp_stack_t *);
extern void *sctp_kstat_init(netstackid_t);
extern void *sctp_kstat2_init(netstackid_t);
extern void sctp_listen_hash_remove(sctp_t *);
extern void sctp_listener_conf_cleanup(sctp_stack_t *);
int);
sctp_faddr_t *, uint32_t *);
extern void sctp_maxpsz_set(sctp_t *);
ip_stack_t *);
extern void sctp_partial_delivery_event(sctp_t *);
ip_recv_attr_t *);
extern void sctp_process_err(sctp_t *);
extern void sctp_process_timer(sctp_t *);
extern void sctp_redo_faddr_srcs(sctp_t *);
extern void sctp_regift_xmitlist(sctp_t *);
sctp_faddr_t *, uint_t *);
ip_stack_t *);
extern void sctp_send_cookie_ack(sctp_t *);
ip_recv_attr_t *);
mblk_t *, ip_recv_attr_t *);
extern void sctp_send_shutdown(sctp_t *, int);
extern int sctp_set_hdraddrs(sctp_t *);
extern void sctp_sets_init(void);
extern void sctp_sets_fini(void);
extern void sctp_shutdown_event(sctp_t *);
extern void sctp_stop_faddr_timers(sctp_t *);
boolean_t, sctp_faddr_t *);
extern void sctp_shutdown_complete(sctp_t *);
extern void sctp_set_if_mtu(sctp_t *);
extern void sctp_set_ulp_prop(sctp_t *);
extern void sctp_ss_rexmit(sctp_t *);
extern void sctp_timer_free(mblk_t *);
extern void sctp_timer_stop(mblk_t *);
extern void sctp_validate_peer(sctp_t *);
extern void sctp_zap_addrs(sctp_t *);
extern void sctp_zap_faddrs(sctp_t *, int);
/* Contract private interface between SCTP and Clustering - PSARC/2005/602 */
{ \
while ((sctp)->sctp_running) \
}
/* Wake up recvq taskq */
{ \
}
#ifdef __cplusplus
}
#endif
#endif /* _INET_SCTP_SCTP_IMPL_H */