typedef struct _sctp_sub_connection
{
transport_connection_t connection; /**< Common transport data. First! */
- void *parent; /**< Link to the parent-super connection */
+ u8 subconn_idx; /**< This indicates the position of this sub-connection in the super-set container of connections pool */
u32 error_count; /**< The current error count for this destination. */
u32 error_threshold; /**< Current error threshold for this destination,
i.e. what value marks the destination down if error count reaches this value. */
sctp_options_t snd_opts;
- u8 next_avail_sub_conn; /**< Represent the index of the next free slot in sub_conn */
+ u8 forming_association_changed; /**< This is a flag indicating whether the original association has been modified during
+ the life-span of the association itself. For instance, a new sub-connection might have been added. */
} sctp_connection_t;
typedef void (sctp_timer_expiration_handler) (u32 conn_index, u32 timer_id);
sctp_connection_t *sctp_connection_new (u8 thread_index);
-void sctp_sub_connection_add_ip4 (u8 thread_index,
- sctp_ipv4_addr_param_t * ipv4_addr);
-void sctp_sub_connection_add_ip6 (u8 thread_index,
- sctp_ipv6_addr_param_t * ipv6_addr);
+
+u8
+sctp_sub_connection_add_ip4 (vlib_main_t * vm,
+ ip4_address_t * lcl_addr,
+ ip4_address_t * rmt_addr);
+
+u8
+sctp_sub_connection_add_ip6 (vlib_main_t * vm,
+ ip6_address_t * lcl_addr,
+ ip6_address_t * rmt_addr);
+
+u8
+sctp_sub_connection_del_ip4 (ip4_address_t * lcl_addr,
+ ip4_address_t * rmt_addr);
+
+u8
+sctp_sub_connection_del_ip6 (ip6_address_t * lcl_addr,
+ ip6_address_t * rmt_addr);
+
void sctp_connection_close (sctp_connection_t * sctp_conn);
void sctp_connection_cleanup (sctp_connection_t * sctp_conn);
void sctp_connection_del (sctp_connection_t * sctp_conn);
void sctp_prepare_initack_chunk (sctp_connection_t * sctp_conn, u8 idx,
vlib_buffer_t * b, ip4_address_t * ip4_addr,
ip6_address_t * ip6_addr);
+void
+sctp_prepare_initack_chunk_for_collision (sctp_connection_t * sctp_conn,
+ u8 idx, vlib_buffer_t * b,
+ ip4_address_t * ip4_addr,
+ ip6_address_t * ip6_addr);
+void sctp_prepare_abort_for_collision (sctp_connection_t * sctp_conn, u8 idx,
+ vlib_buffer_t * b,
+ ip4_address_t * ip4_addr,
+ ip6_address_t * ip6_addr);
+void
+sctp_prepare_operation_error (sctp_connection_t * sctp_conn, u8 idx,
+ vlib_buffer_t * b, u8 err_cause);
void sctp_prepare_cookie_echo_chunk (sctp_connection_t * sctp_conn, u8 idx,
vlib_buffer_t * b,
sctp_state_cookie_param_t * sc);
u16 sctp_check_outstanding_data_chunks (sctp_connection_t * sctp_conn);
+void sctp_api_reference (void);
+
#define IP_PROTOCOL_SCTP 132
/** SSCTP FSM state definitions as per RFC4960. */
clib_spinlock_lock_if_init (&sctp_main.half_open_lock);
if (!pool_is_free_index (sctp_main.half_open_connections, conn_index))
tc = pool_elt_at_index (sctp_main.half_open_connections, conn_index);
- tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].parent = tc;
+ tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].subconn_idx = MAIN_SCTP_SUB_CONN_IDX;
clib_spinlock_unlock_if_init (&sctp_main.half_open_lock);
return tc;
}
always_inline void
sctp_half_open_connection_del (sctp_connection_t * tc)
{
- sctp_main_t *tm = vnet_get_sctp_main ();
- clib_spinlock_lock_if_init (&tm->half_open_lock);
- pool_put_index (tm->half_open_connections,
+ sctp_main_t *sctp_main = vnet_get_sctp_main ();
+ clib_spinlock_lock_if_init (&sctp_main->half_open_lock);
+ pool_put_index (sctp_main->half_open_connections,
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_c_index);
if (CLIB_DEBUG)
memset (tc, 0xFA, sizeof (*tc));
- clib_spinlock_unlock_if_init (&tm->half_open_lock);
+ clib_spinlock_unlock_if_init (&sctp_main->half_open_lock);
}
always_inline u32
if (sub->parent == NULL)
SCTP_ADV_DBG ("sub->parent == NULL");
#endif
- return (sctp_connection_t *) sub->parent;
+ if (sub->subconn_idx > 0)
+ return (sctp_connection_t *) sub -
+ (sizeof (sctp_sub_connection_t) * (sub->subconn_idx - 1));
+
+ return (sctp_connection_t *) sub;
}
always_inline u32
sctp_hdr_opts_len);
}
+always_inline u8
+sctp_next_avail_subconn (sctp_connection_t * sctp_conn)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
+ {
+ if (sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
+ return i;
+ }
+ return MAX_SCTP_CONNECTIONS;
+}
+
always_inline void
update_smallest_pmtu_idx (sctp_connection_t * sctp_conn)
{