Files
m241Neelima/components/ip_net2-6.9/ipsctp/src/ipsctp_h.h
T
2026-07-30 11:19:44 +05:30

1966 lines
86 KiB
C

/* ipsctp_h.h - IPNET SCTP header template file */
/*
* Copyright (c) 2007 Wind River Systems, Inc.
*
* The right to copy, distribute or otherwise make use of this software
* may be licensed only pursuant to the terms of an applicable Wind River
* license agreement. No license to Wind River intellectual property rights
* is granted herein. All rights not licensed by Wind River are reserved
* by Wind River.
*/
/*
modification history
--------------------
*/
#ifndef IPSCTP_H_H
#define IPSCTP_H_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/* IPSCTP private definitions */
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipsctp_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef IPNET
#include <ipnet.h>
#include <ipnet_h.h>
#endif
#ifdef _WRS_KERNEL
#include <sys/times.h>
#endif
#ifdef IPCOM_USE_BITARRAY
#include <ipcom_bitarray.h>
#endif
#include <ipcom_type.h>
#include <ipcom_time.h>
#include <ipsctp.h>
#include <ipsctp_sock.h>
#include "ipsctp_pkt.h"
#include "ipsctp_hash.h"
#ifdef IPMCRYPTO
#include <ip/openssl/md5.h>
#else
#include <openssl/md5.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#ifdef IPCOM_SYSLOG_PRIORITY
#undef IPCOM_SYSLOG_PRIORITY
#endif
#define IPCOM_SYSLOG_PRIORITY IPSCTP_SYSLOG_PRIORITY
#ifdef IPCOM_SYSLOG_FACILITY
#undef IPCOM_SYSLOG_FACILITY
#endif
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPSCTP
/*
*===========================================================================
* DEBUG/ASSERT
*===========================================================================
*/
#ifdef IPSCTP_DEBUG
#define IPSCTP_DEBUG_LINE(x) x
#else
#define IPSCTP_DEBUG_LINE(x) IP_NOOP
#endif /* IPSCTP_DEBUG */
#define IPSCTP_DBG_STATE 0x00000001
#define IPSCTP_DBG_TIMER 0x00000002
#define IPSCTP_DBG_INPUT 0x00000004
#define IPSCTP_DBG_OUTPUT 0x00000008
#define IPSCTP_DBG_SOCK 0x00000010
#define IPSCTP_DBG_PKT 0x00000020
#define IPSCTP_DBG_CC 0x00000040
#define IPSCTP_DBG_RWND 0x00000080
#define IPSCTP_DBG_PATH 0x00000100
#define IPSCTP_DBG_MTU 0x00000200
#define IPSCTP_DBG_BUF 0x00000400
#define IPSCTP_DBG_ALL 0xFFFFFFFF
#ifdef IPSCTP_DEBUG
extern IP_PUBLIC Ip_u32 ipsctp_debug_flags;
#define IPSCTP_DBG0(flag, fm) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG0(DEBUG, fm); \
} \
} while(0)
#define IPSCTP_DBG1(flag, fm, a) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG1(DEBUG, (fm), (a)); \
} \
} while(0)
#define IPSCTP_DBG2(flag, fm, a, b) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG2(DEBUG, fm, a, b); \
} \
} while(0)
#define IPSCTP_DBG3(flag, fm, a, b, c) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG3(DEBUG, fm, a, b, c); \
} \
} while(0)
#define IPSCTP_DBG4(flag, fm, a, b, c, d) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG4(DEBUG, fm, a, b, c, d); \
} \
} while(0)
#define IPSCTP_DBG5(flag, fm, a, b, c, d, e) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG5(DEBUG, fm, a, b, c, d, e); \
} \
} while(0)
#define IPSCTP_DBG6(flag, fm, a, b, c, d, e, f) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG6(DEBUG, fm, a, b, c, d, e, f); \
} \
} while(0)
#define IPSCTP_DBG7(flag, fm, a, b, c, d, e, f, g) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG7(DEBUG, fm, a, b, c, d, e, f, g); \
} \
} while(0)
#define IPSCTP_DBG8(flag, fm, a, b, c, d, e, f, g, h) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG8(DEBUG, fm, a, b, c, d, e, f, g, h); \
} \
} while(0)
#define IPSCTP_DBG9(flag, fm, a, b, c, d, e, f, g, h, i) \
do \
{ \
if ((ipsctp_debug_flags & flag) == flag) \
{ \
IPCOM_LOG9(DEBUG, fm, a, b, c, d, e, f, g, h, i); \
} \
} while(0)
#else /* !IPSCTP_DEBUG */
#define IPSCTP_DBG0(flag, fm) IP_NOOP
#define IPSCTP_DBG1(flag, fm, a) IP_NOOP
#define IPSCTP_DBG2(flag, fm, a, b) IP_NOOP
#define IPSCTP_DBG3(flag, fm, a, b, c) IP_NOOP
#define IPSCTP_DBG4(flag, fm, a, b, c, d) IP_NOOP
#define IPSCTP_DBG5(flag, fm, a, b, c, d, e) IP_NOOP
#define IPSCTP_DBG6(flag, fm, a, b, c, d, e, f) IP_NOOP
#define IPSCTP_DBG7(flag, fm, a, b, c, d, e, f, g) IP_NOOP
#define IPSCTP_DBG8(flag, fm, a, b, c, d, e, f, g, h) IP_NOOP
#define IPSCTP_DBG9(flag, fm, a, b, c, d, e, f, g, h, i ) IP_NOOP
#endif
/* Stack specific types */
#ifdef IPNET
#ifndef IP_STACK
#define IP_STACK(x) ipnet_ ## x
#endif
#ifndef IP_STACK_CONST
#define IP_STACK_CONST(x) IPNET_ ## x
#endif
#ifndef ipstack
#define ipstack ipnet
#endif
#elif defined(IPLITE)
#ifndef IP_STACK
#define IP_STACK(x) iplite_ ## x
#endif
#ifndef IP_STACK_CONST
#define IP_STACK_CONST(x) IPLITE_ ## x
#endif
#ifndef ipstack
#define ipstack (&iplite)
#endif
#ifndef iplite_conf_max_sockets
#define iplite_conf_max_sockets IPLITE_CONF_MAX_SOCKETS
#endif
#else
#error "IPNET or IPLITE must be defined"
#endif
/* NOTE : Ipcom_list next pointer must be the first place in your structure */
#define ipsctp_list_for_each(head, cur, TYPE) \
for ((cur) = (TYPE *)ipcom_list_first(head); \
IP_NULL != (cur); \
(cur) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)))
/* differ with Ipsctp_list_for_each for you can delete element in this loop */
#define ipsctp_list_for_each_safe(head, cur, tmp, TYPE) \
for ((cur) = (TYPE *)ipcom_list_first(head), ((cur) ? (tmp) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)) : IP_NULL); \
IP_NULL != (cur); \
(cur) = (tmp), ((cur) ? (tmp) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)) : IP_NULL))
/* differ with Ipsctp_list_for_each for you can delete element in this loop */
#define ipsctp_list_for_current_each_safe(cur, tmp, TYPE) \
for (((cur) ? (tmp) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)) : IP_NULL); \
IP_NULL != (cur); \
(cur) = (tmp), ((cur) ? (tmp) = (TYPE *)ipcom_list_next((Ipcom_list *)(cur)) : IP_NULL))
#define Ipsctp_vtag Ip_u32
/* SCTP constants */
/* End-of-file marker */
/*#define IPSCTP_EOF (-1)*/
#define IPSCTP_MAX_STREAMS 2048
#define IPSCTP_MAX_DUP_TSNS 20
#define IPSCTP_LARGEST_INIT_ACCEPTED (65535 - 2048)
#define IPSCTP_INITIAL_TSN_BITMAP_SIZE 16
#define IPSCTP_MINIMAL_RWND 4960
#define IPSCTP_MIN_RWND 1500
#define IPSCTP_MAX_TSN 0xffffffff
#define IPSCTP_ADDR_IS_CONFIRMED 1
#define IPSCTP_INITIAL_CWND 4380
#define IPSCTP_MAX_TSN_BITMAP_SIZE 512
#define IPSCTP_TSN_BITMAP_INCR 32
#define IPSCTP_GET_TSN_BITMAP_SIZE_NEXT(oldsize, gap) \
((oldsize)*2 > ((gap + 7)/8 + IPSCTP_TSN_BITMAP_INCR))?((oldsize)*2):((gap + 7)/8 + IPSCTP_TSN_BITMAP_INCR)
/* silly window syndrome */
#define IPSCTP_SWS_SENDER_DEF 1420
#define IPSCTP_SWS_RECEIVER_DEF 3000
#define ipsctp_memzero(buf, size) (void)ipcom_memset((void *)(buf), 0 , (size))
typedef enum Ipsctp_notify_type_enum
{
SCTP_NOTIFY_NONE = 0,
SCTP_NOTIFY_ASSOC_UP = 1,
SCTP_NOTIFY_ASSOC_DOWN = 2,
SCTP_NOTIFY_INTERFACE_DOWN = 3,
SCTP_NOTIFY_INTERFACE_UP = 4,
SCTP_NOTIFY_SEND_FAIL = 5,
SCTP_NOTIFY_ASSOC_ABORTED = 6,
SCTP_NOTIFY_ASSOC_RESTART = 7,
SCTP_NOTIFY_PEER_SHUTDOWN = 8,
SCTP_NOTIFY_INTERFACE_CONFIRMED = 9,
SCTP_NOTIFY_REMOTE_ERROR = 10,
SCTP_NOTIFY_MAX = 11
}
Ipsctp_notify_type;
#define IPSCTP_INVALID_NOTIFY_ERR 0xffffffff
#define IPSCTP_INVALID_LINGER_TIME 0xffffffff
#define ipsctp_sock_state(sock, state) \
IP_BIT_ISSET(sock->sctp_inst->inst_flags, IPSCTP_SOCKET_##state)
#define ipsctp_list_size(list_head) ((list_head)->head->size)
#define ipsctp_check_hdr_len(stru, ch_hdr) (sizeof(stru) != ip_ntohs((ch_hdr)->length))
#define IPSCTP_GET_ASSOCID(tcb) ((tcb)->my_vtag)
/* Socket Event Options for sctp_event_subscribe */
#define IPSCTP_EVNT_FLAGS_DATA_IO (1u << 1)
#define IPSCTP_EVNT_FLAGS_ASSOCIATION (1u << 2)
#define IPSCTP_EVNT_FLAGS_ADDRESS (1u << 3)
#define IPSCTP_EVNT_FLAGS_SEND_FAILURE (1u << 4)
#define IPSCTP_EVNT_FLAGS_PEER_ERROR (1u << 5)
#define IPSCTP_EVNT_FLAGS_SHUTDOWN (1u << 6)
#define IPSCTP_EVNT_FLAGS_PARTIAL_DELIVERY (1u << 7)
#define IPSCTP_EVNT_FLAGS_ADAPTATION_LAYER (1u << 8)
#define IPSCTP_EVNT_FLAGS_AUTHENTICATION (1u << 9)
#define IPSCTP_INST_FLAG_HB_DISABLED (1u << 10)
#define IPSCTP_INST_FLAG_EXPLICIT_EOR (1u << 11)
#define IPSCTP_INST_FLAG_FRAG_INTERLEAVE (1u << 12)
#define IPSCTP_INST_FLAG_INTERLEAVE_STRMS (1u << 13)
#define IPSCTP_INST_FLAG_EXT_RCVINFO (1u << 14)
#define IPSCTP_INST_FLAG_WANT_MAPPED_V4 (1u << 15)
#define IPSCTP_INST_FLAGS_NO_FRAGMENT (1u << 16)
#define IPSCTP_INST_FLAGS_NODELAY (1u << 17)
/* Socket stack specific defines */
#ifdef IPNET
#define IPSCTP_STACK_BIND(s, n, l, r) (s)->ops->bind(s, n, l, r)
#define IPSCTP_SOCK_VR(s) ((s)->vr_index)
#define IPSCTP_SOCK_TYPE(sk) ((sk)->ipcom.type)
#define IPSCTP_SOCK_DOMAIN(sk) ((sk)->ipcom.domain)
#define IPSCTP_IS_SOCK_TYPE(sk, type) (type == ((sk)->ipcom.type))
#else /* IPLITE */
#define IPSCTP_STACK_BIND(s, n, l, r) iplite_do_bind(s, n, l, r)
#define IPSCTP_SOCK_VR(s) 0
#endif
/* socket other MACROS */
#define IPSCTP_SIZE_LADDR_ENTRY (sizeof(Ipsctp_laddr_entry))
#define IPSCTP_SIZE_TCB_ENTRY (sizeof(Ipsctp_tcb))
#define IPSCTP_SIZE_LADDR (sizeof(Ipsctp_addr))
#define IPSCTP_SIZE_TCB (sizeof(Ipsctp_tcb))
#define IPSCTP_SIZE_SNDRCVINFO (sizeof(Ipsctp_sctp_sndrcvinfo))
/* SCTP tcb control flags */
#define IPSCTP_TCBC_FLAG_ASSOC_UP_SENT (1 << 0) /* */
#define IPSCTP_TCBC_FLAG_ASSOC_RESTART (1 << 1) /* */
#define IPSCTP_TCBC_FLAG_SAW_GAP_SACK (1 << 2) /* Is previous ack gap? used to revoke the sack */
#define IPSCTP_TCBC_FLAG_HAD_ENOBUF (1 << 3)
#define IPSCTP_TCBC_FLAG_DELAY_CONNECT (1 << 4) /* delayed connection flag */
#define IPSCTP_TCBC_FLAG_HB_DISABLED (1 << 5) /* heartbeat disabled */
#define IPSCTP_TCBC_FLAG_NEED_SEND_ACK (1 << 6) /* whether it is in partial delivery? */
#define IPSCTP_TCBC_FLAG_LISTEN (1 << 7) /* This is a dummy TCB for listening socket */
#define IPSCTP_TCBC_FLAG_DACK_PENDING (1 << 8) /* delay ack timer is running */
#define IPSCTP_TCBC_FLAG_HB_PENDING (1 << 9) /* heartbeat timer is running */
#define IPSCTP_TCBC_FLAG_FAST_RECOVERY (1 << 10) /* RFC2582 fast recovery */
#define IPSCTP_TCBC_FLAG_SAT_T3_LOSS_RECOVERY (1 << 11) /* set this flag in t3 timer */
#define IPSCTP_TCBC_FLAG_IPV4_ALLOW (1 << 12) /* allow bound ipv4 address */
#define IPSCTP_TCBC_FLAG_IPV6_ALLOW (1 << 13) /* allow bound ipv6 address */
#define IPSCTP_TCBC_FLAG_SCOPE_V6LOCAL (1 << 14) /* ipv6 local address */
#define IPSCTP_TCBC_FLAG_SCOPE_V6SITE (1 << 15) /* ipv6 site address */
#define IPSCTP_TCBC_FLAG_SCOPE_V4LOCAL (1 << 16) /* ipv4 private address */
#define IPSCTP_TCBC_FLAG_SCOPE_V4LOOPBACK (1 << 17) /* ipv4 loopback address */
#define IPSCTP_TCBC_FLAG_CONNECTING (1 << 18) /* TCB is connecting */
#define IPSCTP_TCBC_FLAG_CONNECTED (1 << 19) /* TCB is connected */
#define IPSCTP_TCBC_FLAG_ABORT (1 << 20) /* TCB has aborted */
#define IPSCTP_IS_LISTEN_INSTANCE(inst) (IP_BIT_ISSET((inst)->inst_flags, IPSCTP_SOCKET_LISTENING))
#define IPSCTP_IS_LISTEN_TCB(tcb) (IP_BIT_ISSET((tcb)->tcb_flags, IPSCTP_TCBC_FLAG_LISTEN))
#define IPSCTP_GET_STATE(tcb) (tcb)->state
#define IPSCTP_SET_STATE(tcb, tcb_state) (tcb)->state = tcb_state
#if 0
#define IPSCTP_ZERO_SUB(a,b) (((a) > (b)) ? ((a) - (b)) : 0)
#else
#define IPSCTP_UNSIGNED_SUB(a,b) (((a) > (b)) ? ((a) - (b)) : 0)
#define IPSCTP_ZERO_SUB(a,b) (((a) >= (b)) ? ((a) - (b))\
: (ipsctp_log3int(IPCOM_LOG_ERR, 0, "FILE "__FILE__" LINE %d IPSCTP_ZERO_SUB abnormal a %u b %u\n",\
__LINE__, a, b)\
,0))
#endif
#if 0
#define IPSCTP_ATOMIC_ZERO_SUB(a,b)\
((ipcom_atomic_get((Ipcom_atomic_t *)&a) > (b)) ? \
ipcom_atomic_sub((Ipcom_atomic_t *)&a,(b))\
: ipcom_atomic_set((Ipcom_atomic_t *)&a, 0))
#else
#define IPSCTP_ATOMIC_ZERO_SUB(a,b)\
((ipcom_atomic_get((Ipcom_atomic_t *)&a) >= (b)) ? \
ipcom_atomic_sub((Ipcom_atomic_t *)&a,(b))\
: ((void)ipsctp_log3int(IPCOM_LOG_ERR, 0, "FILE "__FILE__" LINE %d IPSCTP_ATOMIC_ZERO_SUB abnormal a %d b %d\n",\
__LINE__, ipcom_atomic_get((Ipcom_atomic_t *)&a),b)\
,ipcom_atomic_set((Ipcom_atomic_t *)&a, 0)))
#endif
#if 0
#define IPSCTP_ZERO_SUB_ASSIGN(a,b) ((a) = (((a) > (b)) ? ((a) - (b)) : 0))
#else
#define IPSCTP_ZERO_SUB_ASSIGN(a,b) ((a) = (((a) >= (b)) ? ((a) - (b))\
: (ipsctp_log3int(IPCOM_LOG_ERR, 0, "FILE "__FILE__" LINE %d IPSCTP_ZERO_SUB_ASSIGN abnormal a %d b %d\n",\
__LINE__, a, b)\
,0)))
#define IPSCTP_UNSIGNED_SUB_ASSIGN(a,b) ((a) = (((a) >= (b)) ? ((a) - (b)) : 0))
#endif
#define IPSCTP_TSN_SUB(a, b) (((a) > (b)) ? ((a) - (b)) : (IPSCTP_MAX_TSN - (b) + (a) + 1))
#define IPSCTP_IS_GT_16(s1, s2) ((Ip_s16) ((s1) - (s2)) > 0)
#define IPSCTP_IS_GEQ_16(s1, s2) ((Ip_s16) ((s1) - (s2)) >= 0)
#define IPSCTP_IS_LT_16(s1, s2) ((Ip_s16) ((s1) - (s2)) < 0)
#define IPSCTP_IS_LEQ_16(s1, s2) ((Ip_s16) ((s1) - (s2)) <= 0)
#define ipsctp_copy_to_user(sock,s1,s2,n) ( IPCOM_UNUSED_ARG(sock), ipcom_copy_to_user(s1,s2,n) )
#define ipsctp_copy_from_user(sock,s1,s2,n) ( IPCOM_UNUSED_ARG(sock), ipcom_copy_from_user(s1,s2,n) )
#define IPSCTP_DATA_LEN_ALIGN(len) (((len) + 3) & ~0x3)
/* SCTP tcb peer control flags */
#define IPSCTP_TCBC_FLAG_SUPPORT_PKT_DROP (1 << 0) /* support packet drop draft */
#define IPSCTP_TCBC_FLAG_SUPPORT_STREAM_RESET (1 << 0) /* support stream reset draft */
#define IPSCTP_TCBC_FLAG_SUPPORT_AUTH (1 << 0) /* support auth rfc */
#define IPSCTP_TCBC_FLAG_SUPPORT_PRSCTP (1 << 0) /* support prsctp */
#define IPSCTP_TCBC_FLAG_SUPPORT_ASCONF (1 << 0) /* support acconf */
/* SCTP chunk control flag, for receive or send status of chunks */
/* the lower 4 bits store the chunk send state, like IPSCTP_CHUNK_FLAG_SEND_STATE_XXX */
#define IPSCTP_CHUNK_FLAG_SEND_STATE_UNSENT 0
#define IPSCTP_CHUNK_FLAG_SEND_STATE_SENT 1
#define IPSCTP_CHUNK_FLAG_SEND_STATE_RESEND 4
#define IPSCTP_CHUNK_FLAG_SEND_STATE_ACKED 5 /* has been acked */
#define IPSCTP_CHUNK_FLAG_SEND_STATE_MARKED 6 /* SACKED by SACK GAP in current SACK chunk */
#define IPSCTP_CHUNK_FLAG_GET_SEND_STATE(flag) ((flag) & 0x000f)
#define IPSCTP_CHUNK_FLAG_SET_SEND_STATE(flag, state) ((flag) = ((flag) & 0xfff0) | ((state) & 0x0f))
#define IPSCTP_CHUNK_FLAG_INC_SEND_STATE(flag) ((flag) = ((flag) & 0xfff0) | ((((flag) & 0x0f) + 1) & 0x0f))
#define IPSCTP_CHUNK_FLAG_SEND (1 << 4) /* chunks in receive queue */
#define IPSCTP_CHUNK_FLAG_SEND_REVOKED (1 << 5) /* this chunk was revoked */
#define IPSCTP_CHUNK_FLAG_SEND_DO_RTT (1 << 6) /* this chunk will do rtt */
#define IPSCTP_CHUNK_FLAG_SEND_DO_FR (1 << 7) /* this chunk is doing fast retransmitting */
#define IPSCTP_CHUNK_FLAG_SEND_END (1 << 8) /* The (E)nding fragment bit, if set, indicates
the last fragment of a user message.*/
#define IPSCTP_CHUNK_FLAG_SEND_BEGIN (1 << 9) /* The (B)eginning fragment bit, if set, indicates
the first fragment of a user message. */
#define IPSCTP_CHUNK_FLAG_SEND_WIN_PROBE (1 << 10) /* this chunk is doing window probe */
#define IPSCTP_CHUNK_FLAG_SEND_ND_ADJUST (1 << 11) /* The Start and End position should be adjust
* for retransmission. */
#define IPSCTP_CHUNK_FLAG_RECV (1 << 4) /* chunks in send queue */
#define IPSCTP_CHUNK_FLAG_RECV_FRAGMENT (1 << 5) /* the fragment flag in socket receive buffer
* or input stream queue */
#define IPSCTP_CHUNK_FLAG_USR_RECV_IN (1 << 6) /* in the process of user receiving */
#define IPSCTP_CHUNK_FLAG_RECV_FIN (1 << 7) /* the whole chunk has been delivered to
* socket receive buffer or input stream queue completely.
* For fragmented chunk, this flag means all chunk fragments
* are received; for unfragmented chunk, this flag is not
* applicable. */
#define IPSCTP_CHUNK_FLAG_RECV_NOTIFICATION (1 << 8)
#define IPSCTP_IS_FIRST_FRAGMENT(chunk) \
((((chunk)->sndrcv_info.sinfo_flags >> 8) & IPSCTP_FLAG_DATA_FRAG_MASK) == IPSCTP_FLAG_DATA_FIRST_FRAG)
#define IPSCTP_IS_MIDDLE_FRAGMENT(chunk) \
((((chunk)->sndrcv_info.sinfo_flags >> 8) & IPSCTP_FLAG_DATA_FRAG_MASK) == IPSCTP_FLAG_DATA_MIDDLE_FRAG)
#define IPSCTP_IS_LAST_FRAGMENT(chunk) \
((((chunk)->sndrcv_info.sinfo_flags >> 8) & IPSCTP_FLAG_DATA_FRAG_MASK) == IPSCTP_FLAG_DATA_LAST_FRAG)
#if 0 /* defined in ipsctp_pkt.h*/
/*
* SCTP error cause, RFC4960
*/
#define IPSCTP_CAUSE_NO_ERROR 0x0000
#define IPSCTP_CAUSE_INVALID_STREAM 0x0001
#define IPSCTP_CAUSE_MISSING_PARAM 0x0002
#define IPSCTP_CAUSE_STALE_COOKIE 0x0003
#define IPSCTP_CAUSE_OUT_OF_RESC 0x0004
#define IPSCTP_CAUSE_UNRESOLVABLE_ADDR 0x0005
#define IPSCTP_CAUSE_UNRECOG_CHUNK 0x0006
#define IPSCTP_CAUSE_INVALID_PARAM 0x0007
#define IPSCTP_CAUSE_UNRECOG_PARAM 0x0008
#define IPSCTP_CAUSE_NO_USER_DATA 0x0009
#define IPSCTP_CAUSE_COOKIE_IN_SHUTDOWN 0x000a
#define IPSCTP_CAUSE_RESTART_W_NEWADDR 0x000b
#define IPSCTP_CAUSE_USER_INITIATED_ABT 0x000c
#define IPSCTP_CAUSE_PROTOCOL_VIOLATION 0x000d
#define IPSCTP_CAUSE_SET(flag, cause) IP_BIT_SET(flag, (1 << cause) )
#endif
/*The action when returning from input processing */
#define IPSCTP_ACTION_SEND_ABORT (1 << 0)
#define IPSCTP_ACTION_SEND_COOKIE_ECHO (1 << 1)
#ifdef IPNET_STATISTICS
#define IPSCTP_STATISTICS
#endif
#define IPSCTP_INPUT_DONE 0
#define IPSCTP_INPUT_STOP_PROCESSING 1 /* Drop the packet, no internal state must change */
#define IPSCTP_INPUT_IN_ORDER_SUCCESS 2 /* Packet delivered successfully */
#define IPSCTP_INPUT_CONT 3
#define IPSCTP_INPUT_IGNORE_CHUNK 4
#define IPSCTP_INPUT_NOTIFY_USER_READ 5
/* hmac definition */
#define IPSCTP_SIG_MAX_SIZE MD5_LBLOCK
#define IPSCTP_BLK_MAX_SIZE MD5_CBLOCK
/*
*===========================================================================
* IPSCTP code lock
*===========================================================================
*/
#ifdef IPNET
# define IPSCTP_CODE_LOCK_READ() IPNET_CODE_LOCK_READ()
# define IPSCTP_CODE_LOCK_WRITE() IPNET_CODE_LOCK_WRITE()
# define IPSCTP_CODE_LOCK() IPSCTP_CODE_LOCK_WRITE()
# define IPSCTP_CODE_UNLOCK() IPNET_CODE_UNLOCK()
#ifdef IPCOM_FORWARDER_NAE
#define IPSCTP_DATA_TCBLOCK(sl) do {} while(0)
#define IPSCTP_DATA_TCBUNLOCK(sl) do {} while(0)
#define IPSCTP_DATA_LOCK(sl) ipcom_enter_critical_region()
#define IPSCTP_DATA_UNLOCK(sl) ipcom_exit_critical_region()
#else
#define IPSCTP_DATA_TCBLOCK(sl) IPNET_DATA_LOCK(sl)
#define IPSCTP_DATA_TCBUNLOCK(sl) IPNET_DATA_UNLOCK(sl)
#define IPSCTP_DATA_LOCK(sl) IPNET_DATA_LOCK(sl)
#define IPSCTP_DATA_UNLOCK(sl) IPNET_DATA_UNLOCK(sl)
#endif
# define IPSCTP_DATA_ISLOCKED(sl) IPNET_DATA_ISLOCKED(sl)
# define IPSCTP_DATA_ISLOCKED_ASSERT(sl) IPNET_DATA_ISLOCKED_ASSERT(sl)
# ifdef IPNET_SMP_OPTIMIZED
# define IPSCTP_SMP_OPTIMIZED
# endif
#else /* IPLITE */
# define IPSCTP_CODE_LOCK_READ() IPLITE_CODE_LOCK()
# define IPSCTP_CODE_LOCK_WRITE() IPLITE_CODE_LOCK()
# define IPSCTP_CODE_LOCK() IPSCTP_CODE_LOCK_WRITE()
# define IPSCTP_CODE_UNLOCK() IPLITE_CODE_UNLOCK()
# define IPSCTP_DATA_LOCK(x) IP_NOOP
# define IPSCTP_DATA_UNLOCK(x) IP_NOOP
# define IPSCTP_DATA_ISLOCKED(x) IP_FALSE
# define IPSCTP_DATA_ISLOCKED_ASSERT(sl) IP_NOOP
#endif
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
*===========================================================================
* IPSCTP association states
*===========================================================================
* Current state information for an association.
*/
typedef enum
{
IPSCTP_STATE_LISTEN = 0,
IPSCTP_STATE_CLOSED = 1,
IPSCTP_STATE_COOKIE_WAIT,
IPSCTP_STATE_COOKIE_ECHOED,
IPSCTP_STATE_ESTABLISHED,
IPSCTP_STATE_SHUTDOWN_PENDING,
IPSCTP_STATE_SHUTDOWN_RECEIVED,
IPSCTP_STATE_SHUTDOWN_SENT,
IPSCTP_STATE_SHUTDOWN_ACK_SENT,
IPSCTP_STATE_MAX
}
Ipsctp_state;
/* SCTP reachability state for each remote address */
#define IPSCTP_ADDR_REACHABLE 0x001
#define IPSCTP_ADDR_NOHB 0x004
#define IPSCTP_ADDR_BEING_DELETED 0x008
#define IPSCTP_ADDR_NOT_IN_ASSOC 0x010
#define IPSCTP_ADDR_USER_PRIMARY 0x040 /* specified as primary by user, \
* or as primary during connection establishment. \
*/
#define IPSCTP_ADDR_OUT_OF_SCOPE 0x080
#define IPSCTP_ADDR_DOUBLE_SWITCH 0x100
#define IPSCTP_ADDR_UNCONFIRMED 0x200
#define IPSCTP_ADDR_REQ_PRIMARY 0x400 /* request for being primary,but now maybe UNCONFIRMED */
#define IPSCTP_ADDR_RXT_PENDING 0x800 /* T3 timer running */
#define IPSCTP_ADDR_FR_PENDING 0x1000 /* FR timer running */
#define IPSCTP_ADDR_FLAG_NO_SMDE 0x2000 /* No Smooth mean deviation estimator calculated yet */
#define IPSCTP_ADDR_FLAG_RTT 0x4000 /* Flag to track if one of the DATA chunks
* sent to this address is currently being
* used to compute an RTT. If this flag is 0,
* the next DATA chunk sent to this
* destination should be used to compute an
* RTT and this flag should be set. Every
* time the RTT calculation completes (i.e.,
* the DATA chunk is SACK'd), the flag is
* cleared.
*/
#define IPSCTP_ADDR_SRC_SELECTED 0x8000 /* selected source address for peer */
#define IPSCTP_ADDR_WINDOW_PROBE 0x10000 /* doing a window probe */
#define IPSCTP_ADDR_DATA_SENT 0x20000 /* some data sent during heartbeat interval.
* Set when data is sent and clear in heartbeat timer
*/
#define IPSCTP_ADDR_NOT_IN_RT 0x40000 /* the selected source address doesn't belong to rt_entry */
#define IPSCTP_ADDR_EVER_SELECTED 0x80000 /* this transport has ever been selected */
/*
*===========================================================================
* IPSCTP local address parameters
*===========================================================================
* This union are defined for handling SCTP socket address.
*/
typedef union Ip_sockaddr_union Ipsctp_addr;
/*#define Ipsctp_addr Ip_sockaddr_union*/
#if 0
#define IPSCTP_ADDR_SET_PORT(sctp_addr, port)
#define IPSCTP_GET_PORT_FROM_SCTP_ADDR(addr) (((addr)->sa.sa_family == IP_AF_INET)?\
((addr)->sin.sin_port):((addr)->sin6.sin6_port)
#define IPSCTP_SET_PORT_FOR_SOADDRESS(soaddr, port) (((soaddr)->sa_family == IP_AF_INET)?\
(((Ip_sockaddr_in *)(soaddr))->sin_port = (port)):(((Ip_sockaddr_in6 *)(soaddr))->sin6_port = (port))
#endif
typedef struct Ipsctp_af_ops_struct
{
Ipcom_list list;
/* compare two sctp addresses */
Ip_bool (*cmp_addr)(const Ipsctp_addr *addr1, const Ipsctp_addr *addr2);
/* compare lookup key with sctp address*/
Ip_bool (*cmp_addr_key)(IP_CONST Ipsctp_addr *addr, IP_CONST union Ip_in_addr_union *key, Ip_u16 domain);
/* get internet address from input buffer */
void (*load_in_addr)(IP_CONST void *addr, union Ip_in_addr_union * in_address);
/* get in_addr from sctp address */
void * (*get_in_addr)(IP_CONST Ipsctp_addr *addr);
Ip_u32 (*get_scope_id)(IP_CONST Ipsctp_addr *addr);
void (*ip_transmit)(IP_CONST void *dst, IP_CONST void *src, Ipcom_pkt *pkt);
void (*load_soaddr)(IP_CONST void *addr, IP_CONST Ip_u16 port, Ipsctp_addr *sock_addr);
void (*get_mtu_and_mss)(struct Ipsctp_tcb_struct *tcb,\
struct Ipsctp_transport_struct *transport,\
Ipnet_route_entry **rt_ret);
void (*addr_set_port)(Ipsctp_addr *sctp_addr, IP_CONST Ip_u16 port);
int (*src_addr_selection)(struct Ipsctp_tcb_struct *tcb, Ipnet_route_entry *rt,\
Ip_u16 lport, struct Ipsctp_transport_struct *transport);
void (*rotate_src_addr)(struct Ipsctp_tcb_struct *tcb, struct Ipsctp_transport_struct *transport);
void (*set_addr_for_socket)(struct Ipsctp_transport_struct *transport, Ipsctp_socket *sock);
Ip_sa_family_t sa_family;
}Ipsctp_af_ops;
typedef enum Ipsctp_laddr_state_enum
{
IPSCTP_LADDR_NORMAL = 1 /* normal state local IP address */
/* need to extend... */
}
Ipsctp_laddr_state;
/*
*===========================================================================
* IPSCTP local address entry parameters
*===========================================================================
* The structure are defined for the entry of list(laddrs_list) in structure
* Ipsctp_instance_struct.
*/
typedef struct Ipsctp_laddrs_entry_struct
{
Ipcom_list next; /* Keep list entry first */
Ipsctp_addr laddr; /* Local sctp bind address */
Ipsctp_laddr_state state; /* Local IP address state */
Ip_u32 start_time; /* sctpAssocLocalAddrStartTime, mib*/
}
Ipsctp_laddr_entry;
#ifdef IPSCTP_MIB
#define IPSCTP_MIB_STATS(xvar) ipsctp->mib_stats.xvar
#define IPSCTP_MIB_STAT_LINE(xline) xline
#else /* No SCTP mib stats */
#define IPSCTP_MIB_STATS(xvar) IP_NOOP
#define IPSCTP_MIB_STAT_LINE(xline) IP_NOOP
#endif /* ifdef IPSCTP_MIB */
#if defined(IPSCTP_DEBUG) || defined(IPSCTP_STATISTICS)
typedef struct Ipsctp_stats_struct
{
/* Other Statistics */
Ip_u32 sctp_input;
Ip_u32 sctp_input_hdr_trunc;
Ip_u32 sctp_input_tcb_nomatch;
Ip_u32 sctp_input_tcb_match;
Ip_u32 sctp_input_bad_vtag;
Ip_u32 sctp_input_dup_chunks;
Ip_u32 sctp_tsn_bitmap_expand;
Ip_u32 sctp_input_drop_chunks_bitmap;
Ip_u32 sctp_input_drop_chunks_invalid_sid;
Ip_u32 sctp_input_drop_chunks_no_buf;
Ip_u32 sctp_input_chunks_express;
Ip_u32 sctp_input_chunks_express_pd;
Ip_u32 sctp_input_chunks_queue2buf;
Ip_u32 sctp_input_chunks_queue2pd;
Ip_u32 sctp_input_chunks_pd;
Ip_u32 sctp_input_chunks_fragment;
Ip_u32 sctp_input_chunks_queued_fragment;
Ip_u32 sctp_input_chunks_not_fragment; /* all input non-fragment chunks*/
Ip_u32 sctp_input_chunks_queued_not_fragment; /* all input non-fragment chunks
* queued in input stream queue.
*/
Ip_u32 sctp_input_msgs_reasm_queued;
Ip_u32 sctp_input_chunks_buf2user;
Ip_u32 sctp_input_chunks_fragment2user;
Ip_u32 sctp_input_msgs_reasm_2user;
Ip_u32 sctp_output_window_update;
Ip_u32 sctp_read_peeks;
Ip_u32 sctp_output_data; /* number of usr send data times(all) */
Ip_u32 sctp_output_data_err; /* number of usr send data times(failure) */
Ip_u32 sctp_output_data_chunk; /* number of the output data chunks(all) */
Ip_u32 sctp_output_data_chunk_err; /* number of the output data chunks(failure) */
Ip_u32 sctp_output_data_chunk_retr; /* number of the retransmit data chunks(all) */
Ip_u32 sctp_output_data_chunk_retr_err; /* number of the retransmit data chunks(failure) */
Ip_u32 sctp_output_ctrl_chunk; /* number of the output control chunks(all) */
Ip_u32 sctp_output_ctrl_chunk_err; /* number of the output control chunks(failure) */
Ip_u32 sctp_output_pkt; /* number of output sctp packets(all) */
Ip_u32 sctp_output_pkt_err; /* number of output sctp packets(failure) */
Ip_u32 sctp_output_data_chunk_cwnd; /* number of output new data not allowed by cwnd */
Ip_u32 sctp_output_data_chunk_cwnd_retr; /* number of output retransmit data not allowed by cwnd */
Ip_u32 sctp_output_data_chunk_nagle; /* number of output retransmit data not allowed by Nagle */
Ip_u32 sctp_output_data_chunk_mult_owner; /* number of output retransmit data not allowed by Multi_owner */
}
Ipsctp_stats;
#define IPSCTP_STATS(xvar) ipsctp->stats.xvar
#define IPSCTP_STAT_LINE(xline) xline
#else /* No SCTP stats */
#define IPSCTP_STATS(xvar) IP_NOOP
#define IPSCTP_STAT_LINE(xline) IP_NOOP
#endif /* defined(IPSCTP_DEBUG) || defined(IPSCTP_STATISTICS) */
/*
*===========================================================================
* IPSCTP DATA CONTROL (IPSCTP DATA)
*===========================================================================
*/
typedef struct Ipsctp_data_struct
{
Ipcom_list address_families; /* address families list*/
Ipcom_list free_chunk_list; /* List of free SCTP chunk structures */
Ip_u32 msec_last_sock_create; /* The time a socket was last created */
Ipsctp_hash *tcb_hashtable; /* indexed by vtag
* All sctp assocation in hash table
* size hidden in Ipsctp_hash
* hash key(v-tag) */
Ipsctp_hash *tcb_hashtable_port; /* indexed by local port and remote port
* All sctp assocation in hash table
* size hidden in Ipsctp_hash
* hash key(local port and remote port) */
Ipsctp_hash *vtag_timewait;
Ipcom_list vtag_timers;
Ip_u32 cnt_tcb; /* Current count of TCB */
#ifndef IPCOM_FORWARDER_NAE
/*
* List of active socket instances. All of the sockets in this list must be
* checked for timeouts each tick.
*/
Ipcom_list active_head;
#endif
#if defined(IPSCTP_DEBUG) || defined(IPSCTP_STATISTICS)
Ipsctp_stats stats; /* Statistics */
#endif
#ifdef IPSCTP_MIB
Ipsctp_mib_stats mib_stats; /* Statistics */
#endif
int opt_tcb_lookup; /* optimize tcb lookup */
Ip_u32 max_chunks_on_queue; /* max chunks on queue per association */
#ifdef IPSCTP_FAST_RETRANSMITE
Ip_bool early_fr; /* early fast retransmission */
#endif
}
Ipsctp_data;
IP_EXTERN Ipsctp_data *ipsctp;
IP_EXTERN Ipcom_pkt *ipsctp_tx_list; /* List of SCTP finished segments that are
waiting to be transmitted. This list
points to the last SCTP segment to be
sent */
#define IPSCTP_RTO_ALPHA (3)
#define IPSCTP_RTO_BETA (2)
#define IPSCTP_CLOCK_GRANULARITY (1)
/*
*===========================================================================
* IPSCTP peer transport parameters
*===========================================================================
* One instance of this structure exists for each destination transport
* address in the sctp association's address list derived from the INIT
* or INIT ACK chunk.
* TODO: Considerations for alignment
* Whether or not to have more seperate timers or only one handler?
* rto_pending not clear yet?
pmtu_timer(mtu increase periodically?) need more investigation
fr_timer need more investigation
hb_timer per association or per transport? what is heartbeat random?
*/
typedef struct Ipsctp_transport_struct
{
Ipcom_list trans_next; /* next transport in list */
Ipsctp_addr paddr; /* the address to which this info belongs */
Ipsctp_addr saddr; /* the selected source address */
#ifdef IPCOM_FORWARDER_NAE
Ip_sa_family_t address_family; /* just save the address family */
#else
Ipsctp_af_ops *af_ops; /* address family specific operations*/
#endif
int ops_handle; /* handle to socket family specific operations*/
/* Following is from rfc 13.3. Per Transport Address Data */
Ip_u32 err_cnt; /* The current error count for this destination */
Ip_u32 err_thresh; /* Current error threshold for this destination, i.e.,
* what value marks the destination down if error count
* reaches this value. sctpAssocRemAddrMaxPathRtx */
Ip_u32 cwnd; /* The current congestion window */
Ip_u32 ssthresh; /* The current ssthresh value */
Ip_u32 rto; /* The current retransmission timeout value */
Ip_u32 srtt; /* The current smoothed round-trip time */
Ip_u32 rttvar; /* The current RTT variation */
Ip_u32 pt_bytes_acked; /* The tracking method for increase of cwnd when in
* bytes acked : congestion avoidance mode (see Section 7.2.2).*/
Ip_u32 flight_size; /* bytes of sent and not acked chunks */
Ip_u32 net_ack; /* The total byte count acked */
Ip_u32 net_ack2; /* track the total bytes acked that are unambiguous and were never retransmitted*/
Ip_u32 state; /* The current state of this destination, i.e., DOWN, UP,
* ALLOW-HB, NO-HEARTBEAT, etc. See IPSCTP_ADDR_XXX */
Ip_u32 pmtu; /* The current known path MTU */
Ip_u32 mss; /* The current known mss, incluing chunk header */
Ipsctp_timer rxt_timer;
/* Timer used by each destination */
Ip_u32 tos_flowlabel;
struct Ip_timeval last_sent_time; /* The time to which this destination was last sent.
* This can be to determine if a HEARTBEAT is needed. */
Ip_u32 hbinterval; /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
* the destination address every heartbeat interval.*/
/* Remote Address Statistic in RFC3873. */
Ip_u32 start_time; /* sctpAssocRemAddrStartTime.
* The value of sysUpTime at the time that this row was
* created. */
#ifdef IPSCTP_MIB
Ip_u32 marked_retrans; /* sctpAssocRemAddrRtx.
* Number of DATA chunks retransmissions to this specific IP
* address. When T3-rtx expires, the DATA chunk that triggered
* the T3 timer will be re-sent according to the retransmissions
* rules. Every DATA chunk that is included in a SCTP packet and
* was transmitted to this specific IP address before, will be
* included in this counter */
#endif
Ip_u32 cur_marked_retrans_bytes; /* Bytes of DATA chunk marked for retransmission now to this
* specific IP address, 4B-aligned including data chunk hdr
*/
Ip_u32 unsent_bytes; /* all the 4B-aligned unsent data including data chunk hdr to this transport(bytes) */
Ip_u8 hb_responded; /* check if need backoff */
Ipsctp_timer hb_timer; /* HB timer */
Ipsctp_timer fr_timer; /* FR timer */
Ip_u32 random_v1; /* random value1 number used for heartbeat */
Ip_u32 random_v2; /* random value1 number used for heartbeat */
}
Ipsctp_transport;
#ifdef IPSCTP_USE_SLAB_MEMORY
#else
/* get the data chunk length including payload and data chunk hdr */
#define IPSCTP_GET_DATA_CHUNK_TRANS_LEN(chunk_send)\
((chunk_send)->length + sizeof(Ipsctp_data_chunk_hdr))
/* get the data chunk length including payload and data chunk hdr (4B-aligned) */
#define IPSCTP_GET_DATA_CHUNK_TRANS_ALIGN_LEN(chunk_send)\
(IP_ROUNDUP(IPSCTP_GET_DATA_CHUNK_TRANS_LEN(chunk_send),4))
/* get the chunk length for cc window related calculation(only payload) */
#define IPSCTP_GET_DATA_CHUNK_WIND_LEN(chunk_send) (chunk_send)->length
/* get the control chunk length */
#define IPSCTP_GET_CRTL_CHUNK_TRANS_LEN(chunk_send) (chunk_send)->length
/* get the control chunk length (4B-aligned) */
#define IPSCTP_GET_CRTL_CHUNK_TRANS_ALIGN_LEN(chunk_send)\
(IP_ROUNDUP(IPSCTP_GET_CRTL_CHUNK_TRANS_LEN(chunk_send),4))
#ifdef IPCOM_FORWARDER_NAE
#define IPSCTP_GET_SEND_CHUNK ipcom_shm_malloc(sizeof(Ipsctp_chunk_send))
#define IPSCTP_FREE_SEND_CHUNK(chunk_send) \
do {\
if(chunk_send->chunk.pkt)\
ipcom_pkt_free(chunk_send->chunk.pkt);\
ipcom_shm_free(chunk_send);\
}while(0)
#define IPSCTP_GET_RECV_CHUNK ipcom_shm_malloc(sizeof(Ipsctp_chunk_recv))
#define IPSCTP_FREE_RECV_CHUNK(recv_chunk) \
do {\
if(recv_chunk->chunk.pkt)\
ipcom_pkt_free(recv_chunk->chunk.pkt);\
ipcom_shm_free(recv_chunk);\
}while(0)
#else /* !IPCOM_FORWARDER_NAE */
#define IPSCTP_GET_SEND_CHUNK ipcom_malloc(sizeof(Ipsctp_chunk_send))
#define IPSCTP_FREE_SEND_CHUNK(chunk_send) \
do {\
if(chunk_send->chunk.pkt)\
ipcom_pkt_free(chunk_send->chunk.pkt);\
ipcom_free(chunk_send);\
}while(0)
#define IPSCTP_GET_RECV_CHUNK ipcom_malloc(sizeof(Ipsctp_chunk_recv))
#if 0
#define IPSCTP_FREE_RECV_CHUNK(recv_chunk) \
do {\
Ipsctp_chunk_recv *cur_frag, *next_frag;\
next_frag = recv_chunk->next_fragment;\
while(next_frag)\
{\
cur_frag = next_frag;\
next_frag = cur_frag->next_fragment;\
if(cur_frag->chunk.pkt)\
ipcom_pkt_free(cur_frag->chunk.pkt);\
ipcom_free(cur_frag);\
}\
if(recv_chunk->chunk.pkt)\
ipcom_pkt_free(recv_chunk->chunk.pkt);\
ipcom_free(recv_chunk);\
}while(0)
#else
#define IPSCTP_FREE_RECV_CHUNK(recv_chunk) \
do {\
if(recv_chunk->chunk.pkt)\
ipcom_pkt_free(recv_chunk->chunk.pkt);\
ipcom_free(recv_chunk);\
}while(0)
#endif
#endif /* end IPCOM_FORWARDER_NAE */
#endif /* IPSCTP_USE_SLAB_MEMORY*/
#define IPSCTP_INIT_RECV_CHUNK(tcb1, transport1, pkt1, chunk_type1, chunk_start1, length1,\
sid, ssn, chunk_flags, ppid, tsn, chunk_recv) \
do {\
ip_assert(IP_NULL != chunk_recv); \
chunk_recv->chunk.pkt = pkt1;\
chunk_recv->chunk.tcb = tcb1;\
chunk_recv->chunk.transport = transport1;\
chunk_recv->chunk.flag = 0;\
IP_BIT_SET(chunk_recv->chunk.flag, IPSCTP_CHUNK_FLAG_RECV);\
chunk_recv->chunk.chunk_type = chunk_type1;\
chunk_recv->chunk.chunk_start = chunk_start1;\
chunk_recv->chunk.chunk_end = (chunk_start1 + length1);\
/*chunk_recv->next_fragment = NULL;*/\
chunk_recv->length = length1;\
/*chunk_recv->chunk_cnt = 1;*/\
chunk_recv->sndrcv_info.sinfo_context = tcb1->context;\
chunk_recv->sndrcv_info.sinfo_cumtsn = tcb1->cumulative_tsn; /* ? */\
chunk_recv->sndrcv_info.sinfo_flags = chunk_flags;\
chunk_recv->sndrcv_info.sinfo_ppid = ppid;\
chunk_recv->sndrcv_info.sinfo_pr_policy = 0;\
chunk_recv->sndrcv_info.sinfo_pr_value = 0;\
chunk_recv->sndrcv_info.sinfo_ssn = ssn;\
chunk_recv->sndrcv_info.sinfo_stream = sid;\
chunk_recv->sndrcv_info.sinfo_tsn = tsn;\
chunk_recv->sndrcv_info.sinfo_assoc_id = tcb1->my_vtag;\
chunk_recv->from_addr = transport1->paddr;\
}while(0)
/*
*===========================================================================
* IPSCTP Transmission Chunk (IPSCTP CHUNK for send)
*===========================================================================
Ipsctp_chunk is the list element in stream queue, control queue, transmitted queue.
TODO: we can use next_fragment in Ipcom_pkt?
statistics should be added
*/
typedef struct Ipsctp_chunk_struct
{
Ipcom_list chunk_next; /* Chunk entry in list*/
Ipcom_pkt *pkt; /* Pkt in this list ,transform
* The buffer in pkt to each type of chunk per chunk_type */
int chunk_start; /* The start location of this chunk's data ,specially for receive */
int chunk_end; /* The end location of this chunk's data , specially for receive */
Ip_u16 chunk_type; /* Chunk Type */
struct Ipsctp_tcb_struct *tcb; /* Which association does this belong to */
Ipsctp_transport *transport; /* The destination this chunk sent to, or received from */
Ip_u16 flag; /* The send status, or receive control flag, see IPSCTP_CHUNK_FLAG_XXX.
* the lower 4 bits of send staus refer to IPSCTP_CHUNK_FLAG_SEND_STATE_XX
*/
}
Ipsctp_chunk;
/*
*===========================================================================
* Ipsctp_chunk_recv
*===========================================================================
* Ipsctp_chunk_recv is the list element in recv queue.
*/
typedef struct Ipsctp_chunk_recv_struct
{
Ipsctp_chunk chunk;
struct Ipsctp_sndrcvinfo sndrcv_info;
Ipsctp_addr from_addr;
#if 0
struct Ipsctp_chunk_recv_struct *next_fragment; /* next fragment of the chunk */
Ip_u32 chunk_cnt; /* the count of all chunk frgments */
#endif
Ip_u32 length; /* length of all chunk fragments */
}
Ipsctp_chunk_recv;
/*
*===========================================================================
* Ipsctp_chunk_send
*===========================================================================
* Ipsctp_chunk_snd is the list element in send queue.
*/
typedef struct Ipsctp_chunk_send_struct
{
Ipsctp_chunk chunk;
struct Ipsctp_sndrcvinfo sndrcv_info;
Ip_u16 snd_count; /* number of times sent */
Ip_u32 fr_tsn; /* sending tsn at the time of FR */
struct Ip_timeval snd_time;
Ip_u32 length; /* for DATA type: actual payload length(no alignment) excluding data chunk header
* for CONTROL type: chunk length(no alignment) including Ipsctp_chunk_hdr.
*/
}
Ipsctp_chunk_send;
/*
*===========================================================================
* IPSCTP INPUT PARA (IPSCTP INPUT PARAMETER)
*===========================================================================
*/
#define IPSCTP_STREAM_IN_FLAG_DELIVERY_STARTED (1 << 0) /* Set when in the process of delivering a record with socket */
#if 0
#define IPSCTP_STREAM_IN_FLAG_INIT (1 << 1) /* Set when this stream receives first chunk */
#endif
typedef struct Ipsctp_stream_in_struct
{
Ip_u16 stream_number;
Ip_u16 last_ssn_delivered; /* used for re-order;
* for unordered chunk, don't update last_ssn_delivered
*/
Ip_u32 last_tsn_delivered; /* last tsn delivered to socket buffer;
* for unordered chunk, don't update last_tsn_delivered
*/
Ipcom_list queue_chunks; /* Chunks received to be re-order or reassemble */
#if 0
Ip_u8 delivery_started;
#endif
Ip_u8 flag; /* see IPSCTP_STREAM_IN_FLAG_XXX */
#ifdef IPSCTP_USE_PARTIAL_DELIVERY
Ipsctp_chunk_recv *chunk_pd_first; /* partial delivery chunk */
Ipsctp_chunk_recv *chunk_pd_end; /* latest fragment of partial delivery chunk */
#endif
}
Ipsctp_stream_in;
/*
*===========================================================================
* IPSCTP Transmission Stream (IPSCTP STREAM)
*===========================================================================
*/
typedef struct Ipsctp_stream_out_struct
{
Ipcom_list stream_next; /* stream entry in list */
Ipcom_list chunk_list; /* chunk queue head */
Ip_u16 stream_number; /* stream number */
Ip_u16 next_ssn_sent; /* next one I expect to send out */
Ip_u8 last_msg_incomplete; /* last msg in this stream is incomplete.
* if the following part of this msg arrives,
* complete this msg.
* may have to fragment if the whole msg too big */
Ipsctp_chunk *selected_chunk; /* by now the selected chunk to send in this stream */
}
Ipsctp_stream_out;
/* Congestion control modules for pluggable
* congestion control.
* By now only IPSCTP_CC_RFC2581 is supported.
*/
typedef enum Ipsctp_cc_module_enum {
IPSCTP_CC_RFC2581 = 0 , /* Standard TCP Congestion Control */
IPSCTP_CC_HSTCP, /* High Speed TCP Congestion Control (Floyd) */
IPSCTP_CC_HTCP, /* HTCP Congestion Control */
IPSCTP_CC_MAX
}Ipsctp_cc_module;
typedef struct Ipsctp_cc_functions_struct {
void (*init)(struct Ipsctp_tcb_struct *tcb,
Ipsctp_transport *transport);
void (*cwnd_update_sack)(struct Ipsctp_tcb_struct *tcb,
Ip_bool cum_ack_moved,
Ip_bool will_exit_fast_recovery);
void (*cwnd_update_fr)(struct Ipsctp_tcb_struct *tcb);
void (*cwnd_update_tmo)(struct Ipsctp_tcb_struct *tcb,
Ipsctp_transport *transport);
void (*cwnd_update_output)(struct Ipsctp_tcb_struct *tcb,
Ipsctp_transport *transport);
#if 0
void (*sctp_cwnd_update_after_ecn_echo) (struct Ipsctp_tcb_struct *stcb,
Ipsctp_transport *transport);
void (*sctp_cwnd_update_after_packet_dropped) (struct Ipsctp_tcb_struct *stcb,
Ipsctp_transport *transport,
struct sctp_pktdrop_chunk *cp,
uint32_t * bottle_bw,
uint32_t * on_queue);
void (*sctp_cwnd_update_after_fr_timer) (struct sctp_inpcb *inp,
struct sctp_tcb *stcb, struct sctp_nets *net);
#endif
}Ipsctp_cc_functions;
/* sock->ipcom.rcv_bytes: bytes of all TCBs' chunks in the socket */
#ifdef IPSCTP_USE_MULTIBUF
#define IPSCTP_RECVBUF_MAX(tcb) tcb->sock->recv_max_bytes /*tcb->recv_max_bytes*/
#define IPSCTP_RECVBUF_LEN(tcb) tcb->recv_bytes
#define IPSCTP_RECVBUF_LEN_ADD(tcb, len) \
do {\
tcb->recv_bytes += (len);\
tcb->sock->ipcom.rcv_bytes += (len);\
}while(0)
#define IPSCTP_RECVBUF_LEN_SUB(sock, tcb, len) \
do {\
if (tcb)\
{\
tcb->recv_bytes -= (len);\
tcb->sock->ipcom.rcv_bytes -= (len);\
}\
}while(0)
#define IPSCTP_RECVBUF_CNT(sock, tcb) tcb->recv_chunks_cnt
#define IPSCTP_RECVBUF_CNT_SUB(sock, tcb, len) \
do {\
if (tcb)\
tcb->recv_chunks_cnt -= (len);\
}while(0)
#define IPSCTP_RECVBUF_QUEUE_LEN(tcb) tcb->size_on_in_queue
#define IPSCTP_RECVBUF_QUEUE_CNT(tcb) tcb->cnt_on_in_queue
#define IPSCTP_SENDBUF_LEN(tcb) tcb->sock->snd_bytes /*tcb->send_bytes*/
#define IPSCTP_SENDBUF_MAX(tcb) tcb->sock->send_max_bytes
#define IPSCTP_SENDBUF_CNT(tcb) tcb->send_chunks_cnt
#else
#define IPSCTP_RECVBUF_MAX(tcb) tcb->sock->recv_max_bytes
#define IPSCTP_RECVBUF_LEN(tcb) tcb->sock->ipcom.rcv_bytes
#define IPSCTP_RECVBUF_LEN_ADD(tcb, len) tcb->sock->ipcom.rcv_bytes += (len) \
, ipsctp_log3int(IPCOM_LOG_DEBUG, IPSCTP_DBG_BUF, "FILE "__FILE__" LINE %d BufSize: %d, add: %d\n",\
__LINE__, tcb->sock->ipcom.rcv_bytes, len)
#define IPSCTP_RECVBUF_LEN_SUB(sock, tcb, len) sock->ipcom.rcv_bytes -= (len)\
, ipsctp_log3int(IPCOM_LOG_DEBUG, IPSCTP_DBG_BUF, "FILE "__FILE__" LINE %d BufSize: %d, sub: %d\n",\
__LINE__, sock->ipcom.rcv_bytes, len)
#define IPSCTP_RECVBUF_CNT(sock, tcb) sock->sctp_inst->recv_chunks_cnt
#define IPSCTP_RECVBUF_CNT_SUB(sock, tcb, len) sock->sctp_inst->recv_chunks_cnt -= (len)
#define IPSCTP_RECVBUF_QUEUE_LEN(tcb) tcb->instance->size_on_in_queue
#define IPSCTP_RECVBUF_QUEUE_CNT(tcb) tcb->instance->cnt_on_in_queue
#define IPSCTP_SENDBUF_LEN(tcb) tcb->sock->snd_bytes /* only user data length */
#define IPSCTP_SENDBUF_MAX(tcb) tcb->sock->send_max_bytes
#define IPSCTP_SENDBUF_CNT(tcb) tcb->instance->send_chunks_cnt
#endif
#ifdef IPCOM_FORWARDER_NAE
#define IPSCTP_APPEND_RECV_CHUNK(tcb, chunk_recv) ipsctp_append_recv_chunk(tcb,chunk_recv)
IP_INLINE int ipsctp_append_recv_chunk( struct Ipsctp_tcb_struct * tcb,Ipsctp_chunk_recv* chunk_recv);
#define IPSCTP_INSERT_RECV_CHUNK(tcb, chunk_recv_pre, chunk_recv) \
do {\
Ipcom_socket_eventcb event_cb = tcb->sock->ipcom.event_cb;\
/* add the chunk to socket receive buffer */\
IPSCTP_DATA_LOCK(tcb->sock->rcv_lock);\
ipcom_list_insert_after(&chunk_recv_pre->chunk.chunk_next, &chunk_recv->chunk.chunk_next);\
IPSCTP_RECVBUF_CNT(tcb->sock, tcb)++;\
IPSCTP_RECVBUF_LEN_ADD(tcb, chunk_recv->length);\
IPSCTP_DATA_UNLOCK(tcb->sock->rcv_lock);\
if (event_cb != IP_NULL)\
{\
(void)event_cb(&tcb->sock->ipcom, (Ipcom_pkt *)chunk_recv, IP_SOEVENT_CB_INPKT);\
}\
}while(0)
#else
#define IPSCTP_APPEND_RECV_CHUNK(tcb, chunk_recv)\
do {\
Ipcom_socket_eventcb event_cb = tcb->sock->ipcom.event_cb;\
/* add the chunk to socket receive buffer */\
IPSCTP_DATA_LOCK(tcb->sock->rcv_lock);\
ipcom_list_insert_last(&tcb->instance->recv_list, &chunk_recv->chunk.chunk_next);\
IPSCTP_RECVBUF_CNT(tcb->sock, tcb)++;\
IPSCTP_RECVBUF_LEN_ADD(tcb, chunk_recv->length);\
IPSCTP_DATA_UNLOCK(tcb->sock->rcv_lock);\
if (event_cb != IP_NULL)\
{\
(void)event_cb(&tcb->sock->ipcom, (Ipcom_pkt *)chunk_recv, IP_SOEVENT_CB_INPKT);\
}\
}while(0)
#define IPSCTP_INSERT_RECV_CHUNK(tcb, chunk_recv_pre, chunk_recv) \
do {\
Ipcom_socket_eventcb event_cb = tcb->sock->ipcom.event_cb;\
/* add the chunk to socket receive buffer */\
IPSCTP_DATA_LOCK(tcb->sock->rcv_lock);\
ipcom_list_insert_after(&chunk_recv_pre->chunk.chunk_next, &chunk_recv->chunk.chunk_next);\
IPSCTP_RECVBUF_CNT(tcb->sock, tcb)++;\
IPSCTP_RECVBUF_LEN_ADD(tcb, chunk_recv->length);\
IPSCTP_DATA_UNLOCK(tcb->sock->rcv_lock);\
if (event_cb != IP_NULL)\
{\
(void)event_cb(&tcb->sock->ipcom, (Ipcom_pkt *)chunk_recv, IP_SOEVENT_CB_INPKT);\
}\
}while(0)
#endif
#define IPSCTP_FREE_PKT_LIST(pkt_list)\
do {\
Ipcom_pkt *free_pkt = IP_NULL;\
Ipcom_pkt *free_pkt_next = IP_NULL;\
free_pkt = pkt_list;\
while (IP_NULL != free_pkt)\
{\
free_pkt_next = free_pkt->next;\
ipcom_pkt_free(free_pkt);\
free_pkt = free_pkt_next;\
}\
} while(0)
/*
*===========================================================================
* IPSCTP Transmission Control Block (IPSCTP TCB)
*===========================================================================
* The members of this structure are defined partially per recommendation in
* Section 13 of RFC4960 and partially per Iptcp_tcb definitions.
* Notes: sctpAssocPrimProcess in RFC3873 is not supported, should be zero.
*/
typedef struct Ipsctp_tcb_struct
{
Ipcom_list next; /* next pointer in the same instance */
Ipsctp_instance *instance; /* points back to the IPSCTP instance owning this TCB */
Ipsctp_socket *sock; /* Points to the socket this TCb is bound to */
Ip_u32 tcb_flags; /* IPSCTP_TCBC_FLAG_XXX*/
Ip_u32 tcb_peer_flags; /* IPSCTP_TCBC_FLAG_XXX*/
int tcb_errno; /* Socket errno (IP_ERRNO_xxx) */
Ipsctp_vtag peer_vtag; /* peer verification tag value (transmitted in all
* packets, recieved from INIT/INIT ACK chunks. */
Ipsctp_vtag my_vtag; /* verification tag value (expected in all recieved
* packets and trnasmitted in INIT/INIT ACK chunks.
* Also as association id, sctpAssocId.
*/
Ip_u32 my_vtag_nonce;
Ip_u32 peer_vtag_nonce;
/* Configurable variable */
Ip_u16 max_init_times;
Ip_u16 max_send_times; /* Mib: sctpAssocMaxRetr */
Ip_u16 max_transport_retrans; /* max retransmissions */
Ip_u32 initial_init_rto_max; /* initial RTO for INIT's */
Ip_u32 initial_rto; /* initial send RTO */
Ip_u32 min_rto; /* per assoc RTO-MIN */
Ip_u32 max_rto; /* per assoc RTO-MAX */
#ifdef IPCOM_USE_INET6
Ip_u32 ipv6_flowlabel; /* flow label */
#endif
#ifdef IPCOM_USE_INET
Ip_u8 ipv4_tos;
#endif
Ip_u32 context; /* Set or get by SCTP_CONTEXT */
Ipsctp_state state; /* association state: assumes all state values except
* IPSCTP_STATE_CLOSED as there is no TCB in IPSCTP_STATE_CLOSED state */
Ipcom_list transport_list; /* peer addresses and parameters struct list*/
Ipsctp_transport *primary_transport; /* points to the primary path info */
Ipsctp_transport *last_ctrl_from;
Ipsctp_transport *last_data_from;
Ip_u32 pmtu; /* smallest PMTU discovered for all of peer addresses. */
Ip_u32 mss;
Ip_u32 frag_point; /* size to do fragments */
Ip_u16 rport; /* remote port, in host order */
Ipsctp_sctp_sndrcvinfo def_send; /* default send info */
Ip_u32 oa_err_cnt; /* overall error count on this association*/
Ip_u32 total_flight; /* amount of data (bytes) currently in flight (on all destinations)
* Total book size in flight, excluding any acked(cumulative and gap) data
*/
Ip_u32 max_burst; /* maximum burst of packets
* that can be emitted by this association
*/
#if 0 /* we can get this value from transmitted_chunk_list's size */
Ip_u32 total_flight_count; /* count of chunks used with book total */
Ip_u32 send_max_bytes;
Ip_u32 recv_max_bytes; /* max receive buffer size for this association */
#endif
Ip_u32 sent_queue_retran_cnt; /* Number on sent queue that are marked for retran until this value
* is 0 we only send one packet of retran'ed data.
??*/
#ifdef IPSCTP_USE_MULTIBUF
Ipcom_atomic_t send_bytes; /* all the data bytes in send queue,including all unsent and unacked. */
Ip_u32 send_chunks_cnt;
Ip_u32 recv_bytes; /* chunks bytes in receive buffer,
= size_on_in_queue? */
Ip_u32 recv_chunks_cnt; /* chunks count in receive buffer */
Ip_u32 size_on_in_queue; /* chunk bytes in input stream's chunk queue,
haven't been delivered to socket receive buffer.*/
Ip_u32 cnt_on_in_queue; /* chunk count in input stream's chunk queue,
haven't been delivered to socket receive buffer.*/
#endif
#if 0
Ip_u32 size_on_reasm_queue;
Ip_u32 cnt_on_reasm_queue;
#endif
/* window state information */
Ip_u32 peers_rwnd;
Ip_u32 my_last_reported_rwnd;
Ipsctp_cc_functions cc_functions; /* value to store the currently loaded congestion control module */
Ip_u32 congestion_control_module;
Ipcom_bitarray *recv_tsn_bitmap; /* array of bits indicating which out-of-order
* TSNs have been received */
Ip_u16 recv_tsn_bitmap_size;
Ip_u32 recv_tsn_bitmap_base; /* Used to track the tsn bitmap and its offset bits. This MAY be
* lower then cumulative_tsn.*/
Ip_u32 cumulative_tsn; /* The highest consequetive TSN at the bottom of the mapping array
* (for his sends).*/
Ip_u32 highest_tsn_inside_map; /* used to track highest TSN we have received
* and is listed in the mapping array.*/
Ip_u32 numduptsns;
Ip_u32 dup_tsns[IPSCTP_MAX_DUP_TSNS]; /* Duplicated TSN packets received */
Ip_u32 tsn_last_delivered; /* need it? */
Ip_u32 init_tsn_number; /* Original tsn number I used */
Ip_u32 tsn_next; /* next TSN number to be assigned to a
* new DATA chunk. Sent in INIT/INIT ACK
* chunk to peer and incremented each time
* DATA chunk is assigned a TSN. */
Ip_u32 fast_recovery_tsn; /* set when fast retransmit */
Ip_u32 sat_t3_recovery_tsn; /* set in t3 timer */
Ip_u32 this_sack_highest_gap; /* Special hook for Fast retransmit, allows us to track the highest
* TSN that is NEW in this SACK if gap ack blocks are present.*/
Ip_u32 last_acked_tsn; /* The highest consecutive TSN that has been acked by peer on my sends */
#if 0
Ipsctp_chunk_recv *chunk_pd; /* chunk in partial delivery */
Ip_u16 ssn_pd; /* stream sequence number for partial delivery */
Ip_u16 sid_pd; /* stream id for partial delivery */
Ip_u32 tsn_pd; /* tsn of partial delivery chunk */
Ip_u16 fragment_flags;
#endif
Ip_u32 sack_freq; /*to control the sack*/
Ip_u32 data_pkts_seen; /*to control the sack, if data_pkts_seen > sack_freq, send sack*/
Ipsctp_stream_in *streams_in; /* tracks inbound streams */
Ipsctp_stream_out *streams_out; /* Out stream queue head,list all streams */
Ipcom_list streams_out_sched_list; /* Out sched for stream schedule,
* e.g. for Round-robin the list link all streams who have packets */
Ipcom_list control_chunk_list; /* Control chunk queue list head */
Ipcom_list transmitted_chunk_list; /* Transmitted chunk queue */
Ip_u16 streamincnt; /* sctpAssocInStreams */
Ip_u16 streamoutcnt; /* sctpAssocOutStreams */
Ip_u16 max_inbound_streams; /* How many streams I support coming into me */
Ip_u16 pre_open_streams; /* how many preopen streams we have */
Ip_u32 total_sends;
Ip_u32 total_recvs;
struct Ip_timeval time_entered; /* time we entered state */
struct Ip_timeval time_last_rcvd;
struct Ip_timeval time_last_sent;
Ip_u32 start_time; /* time we start the association*/
Ip_u32 discontinuity_time; /* sctpAssocDiscontinuityTime */
Ip_u32 hb_interval; /* Heart Beat interval in MSEC, sctpAssocHeartBeatInterval*/
Ip_u32 autoclose_time; /* autoclose time, im MSEC */
Ip_u32 delayed_ack; /*time of delay ack timer */
/* timer */
Ipsctp_timer dack_timer; /* Delayed ack timer */
Ipsctp_timer asconf_timer; /* asconf */
Ipsctp_timer shut_guard_timer; /* shutdown guard */
Ipsctp_timer autoclose_timer; /* automatic close timer */
Ipsctp_timer delayed_event_timer; /* timer for delayed events */
Ipsctp_timer delete_prim_timer; /* deleting primary dst */
Ip_u32 cookie_life;
Ip_u8 cookie_how[8]; /*record different accasions in cookie_existing,yjg*/
Ip_u16 stale_cookie_count;
Ip_u32 cookie_preserve_req; /*required cookie time*/
/* Mib in RFC3872 */
#ifdef IPSCTP_MIB
Ip_u32 marked_retrans; /* sctpAssocRtxChunks */
Ip_u32 cnt_timo_init; /* sctpAssocT1expireds = cnt_timo_init + cnt_timo_cookie */
Ip_u32 cnt_timo_cookie;
Ip_u32 cnt_timo_shutdown; /* sctpAssocT2expireds = cnt_timo_shutdown+ cnt_timo_shutdownack */
Ip_u32 cnt_timo_shutdownack;
#endif
}
Ipsctp_tcb;
/*
*===========================================================================
* Ipsctp_tcb_lookup_key
*===========================================================================
*/
typedef struct Ipsctp_tcb_lookup_key_struct
{
Ip_u32 vr; /* The virtual router */
Ip_u16 domain; /* The domain */
Ip_u16 strict_match; /* Whether match port and address or not */
Ip_u16 local_port; /* The local port */
Ip_u16 peer_port; /* The peer port */
union Ip_in_addr_union local_addr; /* The local address */
union Ip_in_addr_union peer_addr; /* The peer address */
Ip_u32 vtag; /* if zero, lookup using ports and addresses,
if non-zero, lookup using vtag */
Ipsctp_transport **transport; /* return matching transport */
Ipsctp_af_ops *af_ops; /* address family related operations */
}
Ipsctp_tcb_lookup_key;
/*
*===========================================================================
* Ipsctp_tag_timewait
*===========================================================================
*/
typedef struct Ipsctp_vtag_timewait_struct
{
Ip_u32 vtag;
Ipsctp_timer timer;
}
Ipsctp_vtag_timewait;
/*
*===========================================================================
* IPSCTP INPUT PARA (IPSCTP INPUT PARAMETER)
*===========================================================================
*/
#define IPSCTP_MAX_CHUNK_IN_ONE_PKT 256 /*IPSCTP_MAX_BUNDLING*/
/* Parameters used when processing incoming SCTP packets */
typedef struct Ipsctp_input_param_struct
{
Ipcom_pkt *pkt;
Ipsctp_tcb *tcb;
Ipsctp_transport *transport; /* points to the path info of this packet */
Ipsctp_af_ops *af_ops; /* address family related operations */
Ip_u16 pkt_len;
Ip_u16 remain_len;
Ip_u8 *error_cause;
Ip_u32 error_cause_len; /* actual error data length in error_cause */
Ip_u32 error_data_len; /* total buffer length of error_cause */
Ip_u32 error_code; /* error code notified to ULP */
Ip_u32 action; /* the action when return from input processing,
* see IPSCTP_ACTION_SEND_ABORT */
IP_CONST void * dst_addr;
IP_CONST void * src_addr;
Ip_u16 src_port; /* Source (peer) TCP port */
Ip_u16 dst_port; /* Destination (local) TCP port */
Ip_bool free_packet; /* IP_TRUE if the packet should be freed */
#ifdef IPCOM_FORWARDER_NAE
Ipcom_pkt *nae_rx_pkt[IPSCTP_MAX_CHUNK_IN_ONE_PKT]; /* [IPSCTP_MAX_BUNDLING]; */
/* Packet that should be
delivered to the
action/notifier */
int chunk_start[IPSCTP_MAX_CHUNK_IN_ONE_PKT];
int chunk_end[IPSCTP_MAX_CHUNK_IN_ONE_PKT];
int position;
#endif
}
Ipsctp_input_param;
#ifdef IPSCTP_DBGSTAT
/* NOTE : please add string in ipsctp_dbgstat_ctl_str */
enum Ipsctp_debug_statistics_enmu
{
IPSCTP_DBGSTAT_BASE = 0, /* NOTE : please add string in ipsctp_dbgstat_ctl_str */
IPSCTP_DBGSTAT_SYS_SEND_INIT,
IPSCTP_DBGSTAT_RESTART_AND_OPEN,
IPSCTP_DBGSTAT_SEND_INIT_PIPE,
IPSCTP_DBGSTAT_COOKIE_TIMER,
IPSCTP_DBGSTAT_SEND_INIT_ERR,
IPSCTP_DBGSTAT_RECV_INIT,
IPSCTP_DBGSTAT_SEND_INIT_ACK,
IPSCTP_DBGSTAT_RECV_INIT_ACK,
IPSCTP_DBGSTAT_SEND_COOKIE_ECHO,
IPSCTP_DBGSTAT_RECV_COOKIE_ECHO,
IPSCTP_DBGSTAT_SEND_COOKIE_ACK,
IPSCTP_DBGSTAT_RECV_COOKIE_ACK,
IPSCTP_DBGSTAT_MAX /* NOTE : please add string in ipsctp_dbgstat_ctl_str */
};
IP_EXTERN IP_PUBLIC Ip_u32 ipsctp_debug_statistics[IPSCTP_DBGSTAT_MAX];
/* NOTE : no valid paremeter check. */
#define IPSCTP_DBGSTAT_INIT(enum_num) (ipsctp_debug_statistics[(Ip_u32)enum_num] = 0)
#define IPSCTP_DBGSTAT_INC(enum_num) (ipsctp_debug_statistics[(Ip_u32)enum_num]++)
#define IPSCTP_DBGSTAT_DEC(enum_num) (ipsctp_debug_statistics[(Ip_u32)enum_num]--)
#define IPSCTP_DBGSTAT_GET(enum_num) (ipsctp_debug_statistics[(Ip_u32)enum_num])
#else
#define IPSCTP_DBGSTAT_INIT(enum_num) IP_NOOP
#define IPSCTP_DBGSTAT_INC(enum_num) IP_NOOP
#define IPSCTP_DBGSTAT_DEC(enum_num) IP_NOOP
#define IPSCTP_DBGSTAT_GET(enum_num) IP_NOOP
#endif
typedef struct Ipsctp_init_para_val_struct
{
Ip_u32 cookie_lifetime_inc;
} Ipsctp_init_para_val;
/*
****************************************************************************
* 6 PUBLIC FUNCTIONS
****************************************************************************
*/
IP_PUBLIC unsigned
ipsctp_tcb_obj_hash(Ipsctp_tcb *tcb);
IP_PUBLIC unsigned
ipsctp_tcb_key_hash(Ipsctp_tcb_lookup_key *key);
IP_PUBLIC Ip_bool
ipsctp_tcb_hash_cmp(Ipsctp_tcb *tcb, Ipsctp_tcb_lookup_key *key);
IP_PUBLIC unsigned
ipsctp_tcb_port_obj_hash(Ipsctp_tcb *tcb);
IP_PUBLIC unsigned
ipsctp_tcb_port_key_hash(Ipsctp_tcb_lookup_key *key);
IP_PUBLIC Ip_bool
ipsctp_tcb_port_hash_cmp(Ipsctp_tcb *tcb, Ipsctp_tcb_lookup_key *key);
IP_PUBLIC unsigned
ipsctp_vtag_timewait_obj_hash(Ipsctp_vtag_timewait *vtag_timewait);
IP_PUBLIC unsigned
ipsctp_vtag_timewait_key_hash(Ip_u32* vtag);
IP_PUBLIC Ip_bool
ipsctp_vtag_timewait_hash_cmp(Ipsctp_vtag_timewait *vtag_timewait, Ip_u32* vtag);
/*
*===========================================================================
* ipsctp_tcb_lookup
*===========================================================================
* Description: Look up SCTP TCB based on given criteria. If vtag is non-zero,
* search the hash table using vtag, and also check the local&peer
* ports and addresses if necessary (TCB lookup optimization is off).
* If vtag is zero, search the hash table using local&peer ports and
* addresses.
* Parameters:
* Returns: Matched SCTP TCB and transport if existing, or NULL.
*
*/
IP_PUBLIC Ipsctp_tcb *
ipsctp_tcb_lookup(
Ip_u32 vtag, /* local's verification tag */
Ip_u16 vr, /* the using virtual router */
int proto, /* protocol type */
IP_CONST void *local_addr, /* The local IPv4 address in network order, IP_NULL for any address */
Ip_u16 local_port, /* port in host order, 0 for any port.*/
IP_CONST void *peer_addr, /* The peer IPv4 address in network order, IP_NULL for any address */
Ip_u16 peer_port, /* port in host order, 0 for any port.*/
Ipsctp_af_ops *af_ops, /* Address Family related operations. */
Ipsctp_transport **transport /* transport matching the peer address, don't return transport if NULL */
);
IP_PUBLIC Ip_bool ipsctp_address_equal(IP_CONST Ipsctp_addr *addr1, IP_CONST Ipsctp_addr *addr2);
IP_PUBLIC Ip_u32 ipsctp_select_tag(Ipsctp_tcb *tcb, Ip_u32 save_timewait);
IP_PUBLIC Ip_s32 ipsctp_add_remote_addr(Ipsctp_tcb *tcb,
IP_CONST Ipsctp_addr *addr,
Ip_u32 addr_state,
Ipsctp_transport **newtransport);
IP_PUBLIC Ipsctp_param_hdr * ipsctp_get_next_param(Ip_u8 **inputbuf,Ip_u16 *remain_len);
IP_PUBLIC Ipsctp_af_ops *ipsctp_get_af_ops(Ip_sa_family_t family);
IP_PUBLIC int ipsctp_src_addr_selection(Ipsctp_tcb *tcb,
Ipsctp_addr *dstaddr,
Ipnet_route_entry *rt,
Ip_u16 lport,
Ipsctp_addr *srcaddr);
IP_PUBLIC Ip_u32 ipsctp_addr_match_len(void *addr1, void *addr2, Ip_u32 lenofint);
#ifdef IPSCTP_DEBUG
IP_GLOBAL IP_CONST char * ipsctp_timer_to_str(Ipsctp_timo type);
IP_GLOBAL IP_CONST char * ipsctp_notification_to_str(Ipsctp_notify_type type);
#endif
IP_PUBLIC void
ipsctp_send_init_ack(Ipsctp_input_param *param,
Ipsctp_chunk_hdr *init,
Ipsctp_sctp_hdr *sctp_hdr_init);
IP_PUBLIC void
ipsctp_send_err(Ipsctp_input_param *param,
Ip_u32 error_type,
Ip_u8 *error_cause,
Ip_u32 error_cause_len);
IP_PUBLIC void
ipsctp_notify_ulp(Ipsctp_notify_type type,
Ipsctp_tcb *tcb,
Ip_u32 err,
void *cookie);
IP_PUBLIC void
ipsctp_init_para_processing(Ipsctp_input_param *param,
Ip_u32 chunk_type,
Ipsctp_init_chunk_hdr *init_chunk,
Ipsctp_init_para_val *pval);
IP_PUBLIC Ip_s32
ipsctp_send_cookie_echo(Ipsctp_tcb *stcb,
Ipsctp_state_cookie *state_cookie,
Ip_u32 state_cookie_len,
Ipsctp_transport *transport);
IP_PUBLIC Ip_s32
ipsctp_hmac(Ip_u16 mac_type,
Ip_u8 *key,
Ip_u16 key_size,
void *data,
Ip_u32 data_size,
void *signature);
IP_PUBLIC Ip_s32
ipsctp_hmac_get_sig_size(Ip_u16 mac_id);
IP_PUBLIC Ip_s32
ipsctp_hmac_get_blk_size(Ip_u16 mac_id);
IP_PUBLIC Ipsctp_socket *
ipsctp_server_socket_new(Ipsctp_socket *listen_sock,
IP_CONST void *local_addr,
Ip_u16 local_port,
IP_CONST void *peer_addr,
Ip_u16 peer_port,
Ipsctp_netif *netif,
Ip_u16 vr,
Ip_sa_family_t sa_family);
IP_PUBLIC int
ipsctp_set_primary_addr(Ipsctp_tcb *tcb,
Ipsctp_addr *addr,
Ipsctp_transport *transport,
Ip_bool if_user,
Ip_bool if_init);
IP_PUBLIC int
ipsctp_alloc_tcb(Ipsctp_instance* instance, /* pointer to instance */
Ipsctp_addr * addr, /* add this address to new created tcb */
Ip_u32 tag, /* choose a tag if 0, and use specified tag for non-0*/
Ipsctp_tcb **newtcb, /* TCB of the new created association */
Ipsctp_transport **newtransport /* the new created transport */
);
IP_PUBLIC void
ipsctp_report_all_outbound(Ipsctp_tcb *tcb);
IP_PUBLIC int
ipsctp_free_tcb(Ipsctp_tcb *tcb /* TCB to be freed */
);
IP_PUBLIC Ipsctp_tcb *
ipsctp_tcb_lookup_by_instance(
Ipsctp_instance* instance, /* pointer to instance */
Ip_u32 vtag, /* local's verification tag, 0 for unspecified */
IP_CONST Ipsctp_addr *peer_soaddr,/* The peer socket address, IP_NULL for unspecified */
Ipsctp_transport **transport_ret /* transport matching the peer address, don't return transport if NULL */
);
IP_PUBLIC Ipsctp_chunk *
ipsctp_alloc_chunk(Ipsctp_tcb *tcb, Ip_u32 len);
IP_PUBLIC void
ipsctp_set_error(Ipsctp_input_param *param,
Ip_u16 error_type,
void *error_info);
IP_PUBLIC int
ipsctp_send_abort(Ipcom_pkt *pkt_in,
Ipsctp_sctp_hdr *hdr,
Ipsctp_vtag vtag,
Ip_u8 *error_cause,
Ip_u32 error_cause_len);
IP_PUBLIC int
ipsctp_send_OOTB_shutcompl(Ipcom_pkt *pkt_in,
Ipsctp_sctp_hdr *hdr);
IP_PUBLIC int ipsctp_send_shutdown(Ipsctp_tcb *tcb, Ipsctp_transport *tp);
IP_PUBLIC int ipsctp_send_shutdown_complete(Ipsctp_tcb *tcb);
IP_PUBLIC int ipsctp_send_shutdown_ack(Ipsctp_tcb *tcb, Ipsctp_transport *tp);
IP_PUBLIC int ipsctp_handle_abort(Ipsctp_input_param *param, Ipsctp_chunk_hdr *ch);
IP_PUBLIC int ipsctp_handle_abort_for_icmp(Ipsctp_tcb *tcb);
#if 0/* no use in SCTP */
IP_PUBLIC void ipsctp_abort_assoc(Ipcom_pkt *pkt_in,
Ipsctp_sctp_hdr *hdr,
Ip_u8 *error_cause,
Ip_u32 error_cause_len);
#endif
IP_PUBLIC void ipsctp_abort_assoc_tcb(Ipsctp_tcb *tcb,
int ab_err,
Ip_u8 *error_cause,
Ip_u32 error_cause_len);
IP_PUBLIC void
ipsctp_abort_assoc_tcb_with_err(Ipsctp_tcb *tcb,
int ab_err,
Ip_u16 ca_type,
Ip_u32 ca_data);
IP_PUBLIC Ip_s32 ipsctp_create_output_seg(Ipsctp_tcb *tcb, Ip_bool msg_more);
IP_PUBLIC void ipsctp_send_sack(Ipsctp_tcb *tcb);
IP_PUBLIC int ipsctp_send_heartbeat(Ipsctp_tcb *tcb, Ipsctp_transport *tp);
IP_PUBLIC int ipsctp_send_heartbeat_ack(Ipsctp_tcb *tcb, Ipsctp_transport *tp, Ipsctp_hb_chunk_hdr *in_ch);
IP_PUBLIC Ip_u32 ipsctp_calc_rto(Ipsctp_tcb *tcb,
Ipsctp_transport *transport,
struct Ip_timeval *tv);
IP_PUBLIC Ip_u8 * ipsctp_get_error_cause_space(Ipsctp_input_param *param, Ip_u16 len);
IP_PUBLIC void ipsctp_stop_timers_for_shutdown(Ipsctp_tcb *tcb);
IP_PUBLIC int ipsctp_change_state(Ipsctp_tcb *tcb, Ipsctp_state new_state);
IP_PUBLIC void ipsctp_timer_add(Ipsctp_instance *inst,
Ipsctp_tcb *tcb,
Ipsctp_transport *transport,
Ipsctp_timo type);
IP_PUBLIC void ipsctp_timer_remove(Ipsctp_instance *inst,
Ipsctp_tcb *tcb,
Ipsctp_transport *transport,
Ipsctp_timo type);
IP_PUBLIC void ipsctp_stop_all_cookie_timers(Ipsctp_tcb *tcb);
IP_PUBLIC Ipsctp_chunk_hdr * ipsctp_get_next_ctrl_chunk(void ** inputbuf, Ip_u16 *remain_len);
IP_PUBLIC Ipsctp_chunk_hdr * ipsctp_get_next_chunk(void ** inputbuf, Ip_u16 *remain_len);
IP_PUBLIC int ipsctp_queue_chunk_op_err(Ipsctp_tcb *tcb,
Ip_u16 param_type,
Ip_u8 *data,
Ip_u16 data_len);
IP_PUBLIC void
ipsctp_queue_chunk_mult_errs(Ipsctp_tcb *stcb,
void *errs_buf,
Ip_u32 errs_buf_len);
IP_PUBLIC Ip_u32 ipsctp_calc_rwnd(Ipsctp_tcb *tcb);
IP_PUBLIC Ip_bool ipsctp_is_known_chunk(Ip_u8 type);
IP_PUBLIC int ipsctp_sack_check(Ipsctp_tcb *tcb, Ip_bool gap_existed, Ip_bool send_sack);
IP_PUBLIC void ipsctp_v4_init(void);
IP_PUBLIC void ipsctp_register_af(Ipsctp_af_ops *sctp_af);
IP_PUBLIC Ipsctp_transport *
ipsctp_transport_lookup(Ipsctp_tcb * tcb, /* TCB of the association */
IP_CONST Ipsctp_addr *peer_soaddr); /* The peer socket address */
IP_PUBLIC Ipsctp_transport *
ipsctp_alt_transport_lookup(
Ipsctp_tcb * tcb, /* TCB of the association */
Ipsctp_transport *transport /* The SCTP transport */
);
IP_PUBLIC void
ipsctp_send_cookie_ack(Ipsctp_tcb *stcb);
IP_PUBLIC void ipsctp_v6_init(void);
IP_PUBLIC void ipsctp_free_in_stream(Ipsctp_tcb *tcb, Ipsctp_stream_in *streams_in);
IP_PUBLIC void ipsctp_free_out_stream(Ipsctp_tcb *tcb, Ipsctp_stream_out *streams_out);
IP_PUBLIC void ipsctp_init_in_stream(Ipsctp_tcb *tcb, Ipsctp_stream_in *streams_out, Ip_u16 stream_number);
IP_PUBLIC int ipsctp_threshold_management(Ipsctp_tcb *tcb, Ipsctp_transport *transport, Ip_u16 threshold);
IP_PUBLIC Ip_s32 ipsctp_send_init(Ipsctp_tcb *stcb);
IP_PUBLIC void
ipsctp_sin_v4_map_v6(void *v4, void *v6);
IP_PUBLIC Ip_bool
ipsctp_is_output_queue_empty(Ipsctp_tcb *tcb);
#ifdef IPSCTP_DEBUG
IP_PUBLIC const char *
ipsctp_addr_ntop(Ipsctp_addr *addr,
char *dst,
int len);
#endif
IP_PUBLIC int ipsctp_alloc_dummy_tcb(Ipsctp_instance* instance, Ipsctp_tcb **newtcb);
IP_PUBLIC Ip_u32 ipsctp_log3int(Ip_u32 priority, Ip_u32 debug_flag, const char *format, int line, int a, int b);
IP_PUBLIC void ipsctp_notify_cb(Ipsctp_tcb *tcb, Ipsctp_transport *transport, int event);
IP_PUBLIC Ip_u32 ipsctp_time_now(void);
IP_PUBLIC void
ipsctp_tx_segments(Ipsctp_tcb *tcb);
IP_PUBLIC int
ipsctp_handle_sendall(Ipsctp_tcb *tcb,
struct Ipsctp_sndrcvinfo *sndrcv,
Ipcom_pkt *pkt,
Ip_bool snd_btypes_check_flag);
/*+++++++++ ipsctp_sock.c +++++++++*/
IP_PUBLIC void
ipsctp_server_remove_from_backlog(Ipsctp_socket *listen_sock,
Ipsctp_socket *sock,
Ip_bool from_done);
IP_PUBLIC void
ipsctp_server_handshake_done(Ipsctp_socket *sock);
IP_PUBLIC void
ipsctp_sock_cleanup(Ipsctp_socket *sock);
IP_PUBLIC void
ipsctp_sock_kclose(Ipsctp_socket *sock);
IP_GLOBAL int ipsctp_drop_tcb(Ipsctp_tcb *tcb, int error_code);
IP_PUBLIC void
ipsctp_close_association(Ipsctp_tcb *tcb);
IP_PUBLIC Ipsctp_tcb *
ipsctp_sock_lookup_da(Ipsctp_socket *sock,
struct Ip_sockaddr *dst_addr);
/*+++++++++ ipsctp_debug.c +++++++++*/
#ifdef IPSCTP_DEBUG
IP_PUBLIC void
ipsctp_print_hex(void *buf,
const char *prompt,
Ip_u32 len);
IP_GLOBAL IP_CONST char *
ipsctp_state_to_str(int state);
IP_PUBLIC Ip_u32 ipsctp_show_buffer(Ipsctp_socket *sock);
#endif
#ifdef IPNET_DEBUG
IP_GLOBAL int ipsctp_tick_to_string(void *unused, char *buf, Ip_size_t buf_len);
#endif
#ifdef __cplusplus
}
#endif
#endif /* IPSCTP_H_H */