Add TCP reassembly metrics on session
This commit is contained in:
@@ -181,19 +181,28 @@ void *session_get_user_data(const struct session *sess)
|
|||||||
|
|
||||||
struct tcp_segment *session_get_tcp_segment(struct session *sess)
|
struct tcp_segment *session_get_tcp_segment(struct session *sess)
|
||||||
{
|
{
|
||||||
struct tcp_pcb *pcb = &sess->tcp_pcb;
|
struct tcp_half *half = NULL;
|
||||||
if (pcb->order_seg.data != NULL && pcb->order_seg.len > 0)
|
|
||||||
{
|
|
||||||
return &pcb->order_seg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session_get_cur_dir(sess) == SESSION_DIR_C2S)
|
if (session_get_cur_dir(sess) == SESSION_DIR_C2S)
|
||||||
{
|
{
|
||||||
return tcp_reassembly_pop(pcb->c2s_assembler);
|
half = &sess->tcp_pcb.c2s;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return tcp_reassembly_pop(pcb->s2c_assembler);
|
half = &sess->tcp_pcb.s2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (half->order.data != NULL && half->order.len > 0)
|
||||||
|
{
|
||||||
|
return &half->order;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct tcp_segment *seg = tcp_reassembly_pop(half->assembler);
|
||||||
|
if (seg)
|
||||||
|
{
|
||||||
|
half->nr_seg_reorded++;
|
||||||
|
}
|
||||||
|
return seg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,117 +213,29 @@ void session_free_tcp_segment(struct session *sess, struct tcp_segment *seg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seg == &sess->tcp_pcb.order_seg)
|
struct tcp_half *half = NULL;
|
||||||
|
if (session_get_cur_dir(sess) == SESSION_DIR_C2S)
|
||||||
{
|
{
|
||||||
sess->tcp_pcb.order_seg.data = NULL;
|
half = &sess->tcp_pcb.c2s;
|
||||||
sess->tcp_pcb.order_seg.len = 0;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
half = &sess->tcp_pcb.s2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seg == &half->order)
|
||||||
|
{
|
||||||
|
half->order.data = NULL;
|
||||||
|
half->order.len = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
half->nr_seg_released++;
|
||||||
tcp_segment_free(seg);
|
tcp_segment_free(seg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* to string
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
const char *closing_reason_to_str(enum closing_reason reason)
|
|
||||||
{
|
|
||||||
switch (reason)
|
|
||||||
{
|
|
||||||
case CLOSING_BY_TIMEOUT:
|
|
||||||
return "closing by timeout";
|
|
||||||
case CLOSING_BY_EVICTED:
|
|
||||||
return "closing by evicted";
|
|
||||||
case CLOSING_BY_CLIENT_FIN:
|
|
||||||
return "closing by client FIN";
|
|
||||||
case CLOSING_BY_CLIENT_RST:
|
|
||||||
return "closing by client RST";
|
|
||||||
case CLOSING_BY_SERVER_FIN:
|
|
||||||
return "closing by server FIN";
|
|
||||||
case CLOSING_BY_SERVER_RST:
|
|
||||||
return "closing by server RST";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *session_state_to_str(enum session_state state)
|
|
||||||
{
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case SESSION_STATE_INIT:
|
|
||||||
return "init";
|
|
||||||
case SESSION_STATE_OPENING:
|
|
||||||
return "opening";
|
|
||||||
case SESSION_STATE_ACTIVE:
|
|
||||||
return "active";
|
|
||||||
case SESSION_STATE_CLOSING:
|
|
||||||
return "closing";
|
|
||||||
case SESSION_STATE_DISCARD:
|
|
||||||
return "discard";
|
|
||||||
case SESSION_STATE_CLOSED:
|
|
||||||
return "closed";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *session_type_to_str(enum session_type type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case SESSION_TYPE_TCP:
|
|
||||||
return "TCP";
|
|
||||||
case SESSION_TYPE_UDP:
|
|
||||||
return "UDP";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *session_dir_to_str(enum session_dir dir)
|
|
||||||
{
|
|
||||||
switch (dir)
|
|
||||||
{
|
|
||||||
case SESSION_DIR_C2S:
|
|
||||||
return "C2S";
|
|
||||||
case SESSION_DIR_S2C:
|
|
||||||
return "S2C";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void session_dump(struct session *sess)
|
|
||||||
{
|
|
||||||
char buffer[1024] = {0};
|
|
||||||
tuple6_to_str(session_get_tuple(sess), buffer, sizeof(buffer));
|
|
||||||
|
|
||||||
printf("session id : %" PRIu64 "\n", session_get_id(sess));
|
|
||||||
printf("session tuple : %s\n", buffer);
|
|
||||||
printf("session tuple dir : %s\n", session_dir_to_str(session_get_tuple_dir(sess)));
|
|
||||||
printf("session state : %s\n", session_state_to_str(session_get_state(sess)));
|
|
||||||
printf("session type : %s\n", session_type_to_str(session_get_type(sess)));
|
|
||||||
printf("session dup traffic : %d\n", session_has_dup_traffic(sess));
|
|
||||||
printf("session closing reason : %s\n", closing_reason_to_str(session_get_closing_reason(sess)));
|
|
||||||
printf("session C2S packets : %" PRIu64 "\n", session_get_metric(sess, SESSION_METRIC_C2S_PACKETS));
|
|
||||||
printf("session C2S bytes : %" PRIu64 "\n", session_get_metric(sess, SESSION_METRIC_C2S_BYTES));
|
|
||||||
printf("session S2C packets : %" PRIu64 "\n", session_get_metric(sess, SESSION_METRIC_S2C_PACKETS));
|
|
||||||
printf("session S2C bytes : %" PRIu64 "\n", session_get_metric(sess, SESSION_METRIC_S2C_BYTES));
|
|
||||||
printf("session new time : %" PRIu64 "\n", session_get_timestamp(sess, SESSION_TIMESTAMP_NEW));
|
|
||||||
printf("session last time : %" PRIu64 "\n", session_get_timestamp(sess, SESSION_TIMESTAMP_LAST));
|
|
||||||
printf("session current packet ptr : %p\n", (void *)session_get_packet(sess, SESSION_PACKET_CURRENT));
|
|
||||||
printf("session current packet dir : %s\n", session_dir_to_str(session_get_cur_dir(sess)));
|
|
||||||
printf("session ex data: \n");
|
|
||||||
for (uint8_t i = 0; i < g_ex_manager.count; i++)
|
|
||||||
{
|
|
||||||
printf(" ex_idx: %d, ex_key: %s, ex_data: %p\n", i, g_ex_manager.schemas[i].key, sess->ex_data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* session ex data
|
* session ex data
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -416,3 +337,141 @@ void session_free_all_ex_data(struct session *sess)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* to string
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
const char *closing_reason_to_str(enum closing_reason reason)
|
||||||
|
{
|
||||||
|
switch (reason)
|
||||||
|
{
|
||||||
|
case CLOSING_BY_TIMEOUT:
|
||||||
|
return "closing by timeout";
|
||||||
|
case CLOSING_BY_EVICTED:
|
||||||
|
return "closing by evicted";
|
||||||
|
case CLOSING_BY_CLIENT_FIN:
|
||||||
|
return "closing by client FIN";
|
||||||
|
case CLOSING_BY_CLIENT_RST:
|
||||||
|
return "closing by client RST";
|
||||||
|
case CLOSING_BY_SERVER_FIN:
|
||||||
|
return "closing by server FIN";
|
||||||
|
case CLOSING_BY_SERVER_RST:
|
||||||
|
return "closing by server RST";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *session_state_to_str(enum session_state state)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case SESSION_STATE_INIT:
|
||||||
|
return "init";
|
||||||
|
case SESSION_STATE_OPENING:
|
||||||
|
return "opening";
|
||||||
|
case SESSION_STATE_ACTIVE:
|
||||||
|
return "active";
|
||||||
|
case SESSION_STATE_CLOSING:
|
||||||
|
return "closing";
|
||||||
|
case SESSION_STATE_DISCARD:
|
||||||
|
return "discard";
|
||||||
|
case SESSION_STATE_CLOSED:
|
||||||
|
return "closed";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *session_type_to_str(enum session_type type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SESSION_TYPE_TCP:
|
||||||
|
return "TCP";
|
||||||
|
case SESSION_TYPE_UDP:
|
||||||
|
return "UDP";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *session_dir_to_str(enum session_dir dir)
|
||||||
|
{
|
||||||
|
switch (dir)
|
||||||
|
{
|
||||||
|
case SESSION_DIR_C2S:
|
||||||
|
return "C2S";
|
||||||
|
case SESSION_DIR_S2C:
|
||||||
|
return "S2C";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_half_dump(const struct tcp_half *half)
|
||||||
|
{
|
||||||
|
char buffer[32] = {0};
|
||||||
|
int used = 0;
|
||||||
|
|
||||||
|
if (half->flags & TH_SYN)
|
||||||
|
{
|
||||||
|
used += snprintf(buffer + used, sizeof(buffer) - used, "SYN ");
|
||||||
|
}
|
||||||
|
if (half->flags & TH_ACK)
|
||||||
|
{
|
||||||
|
used += snprintf(buffer + used, sizeof(buffer) - used, "ACK ");
|
||||||
|
}
|
||||||
|
if (half->flags & TH_FIN)
|
||||||
|
{
|
||||||
|
used += snprintf(buffer + used, sizeof(buffer) - used, "FIN ");
|
||||||
|
}
|
||||||
|
if (half->flags & TH_RST)
|
||||||
|
{
|
||||||
|
used += snprintf(buffer + used, sizeof(buffer) - used, "RST ");
|
||||||
|
}
|
||||||
|
printf(" flags : %s\n", buffer);
|
||||||
|
printf(" nr_seg_received : %lu\n", half->nr_seg_received);
|
||||||
|
printf(" nr_seg_expired : %lu\n", half->nr_seg_expired);
|
||||||
|
printf(" nr_seg_overlap : %lu\n", half->nr_seg_overlap);
|
||||||
|
printf(" nr_seg_no_space : %lu\n", half->nr_seg_no_space);
|
||||||
|
printf(" nr_seg_inorder : %lu\n", half->nr_seg_inorder);
|
||||||
|
printf(" nr_seg_reorded : %lu\n", half->nr_seg_reorded);
|
||||||
|
printf(" nr_seg_buffered : %lu\n", half->nr_seg_buffered);
|
||||||
|
printf(" nr_seg_released : %lu\n", half->nr_seg_released);
|
||||||
|
}
|
||||||
|
|
||||||
|
void session_dump(struct session *sess)
|
||||||
|
{
|
||||||
|
char buffer[1024] = {0};
|
||||||
|
tuple6_to_str(session_get_tuple(sess), buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
printf("session id : %" PRIu64 "\n", session_get_id(sess));
|
||||||
|
printf("session tuple : %s\n", buffer);
|
||||||
|
printf("session tuple dir : %s\n", session_dir_to_str(session_get_tuple_dir(sess)));
|
||||||
|
printf("session state : %s\n", session_state_to_str(session_get_state(sess)));
|
||||||
|
printf("session type : %s\n", session_type_to_str(session_get_type(sess)));
|
||||||
|
printf("session dup traffic : %d\n", session_has_dup_traffic(sess));
|
||||||
|
printf("session closing reason : %s\n", closing_reason_to_str(session_get_closing_reason(sess)));
|
||||||
|
printf("session C2S packets : %" PRIu64 "\n", session_get_metric(sess, SESSION_METRIC_C2S_PACKETS));
|
||||||
|
printf("session C2S bytes : %" PRIu64 "\n", session_get_metric(sess, SESSION_METRIC_C2S_BYTES));
|
||||||
|
printf("session S2C packets : %" PRIu64 "\n", session_get_metric(sess, SESSION_METRIC_S2C_PACKETS));
|
||||||
|
printf("session S2C bytes : %" PRIu64 "\n", session_get_metric(sess, SESSION_METRIC_S2C_BYTES));
|
||||||
|
printf("session new time : %" PRIu64 "\n", session_get_timestamp(sess, SESSION_TIMESTAMP_NEW));
|
||||||
|
printf("session last time : %" PRIu64 "\n", session_get_timestamp(sess, SESSION_TIMESTAMP_LAST));
|
||||||
|
printf("session current packet ptr : %p\n", (void *)session_get_packet(sess, SESSION_PACKET_CURRENT));
|
||||||
|
printf("session current packet dir : %s\n", session_dir_to_str(session_get_cur_dir(sess)));
|
||||||
|
printf("session ex data:\n");
|
||||||
|
for (uint8_t i = 0; i < g_ex_manager.count; i++)
|
||||||
|
{
|
||||||
|
printf(" ex_idx: %d, ex_key: %s, ex_data: %p\n", i, g_ex_manager.schemas[i].key, sess->ex_data[i]);
|
||||||
|
}
|
||||||
|
if (session_get_type(sess) == SESSION_TYPE_TCP)
|
||||||
|
{
|
||||||
|
printf("session TCP C2S:\n");
|
||||||
|
tcp_half_dump(&sess->tcp_pcb.c2s);
|
||||||
|
printf("session TCP S2C:\n");
|
||||||
|
tcp_half_dump(&sess->tcp_pcb.s2c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -75,35 +75,32 @@ enum session_packet_index
|
|||||||
MAX_PACKETS,
|
MAX_PACKETS,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum tcp_state
|
struct tcp_half
|
||||||
{
|
{
|
||||||
TCP_SYN_RCVD = 1 << 0,
|
struct tcp_reassembly *assembler;
|
||||||
TCP_SYN_ACK_RCVD = 1 << 1,
|
struct tcp_segment order;
|
||||||
|
|
||||||
TCP_C2S_FIN_RCVD = 1 << 2,
|
uint64_t nr_seg_received;
|
||||||
TCP_S2C_FIN_RCVD = 1 << 3,
|
uint64_t nr_seg_expired;
|
||||||
|
uint64_t nr_seg_overlap; //(retransmission)
|
||||||
|
uint64_t nr_seg_no_space;
|
||||||
|
|
||||||
TCP_C2S_RST_RCVD = 1 << 4,
|
uint64_t nr_seg_inorder;
|
||||||
TCP_S2C_RST_RCVD = 1 << 5,
|
uint64_t nr_seg_reorded;
|
||||||
|
|
||||||
TCP_C2S_UNVERIFIED_RST_RCVD = 1 << 6,
|
uint64_t nr_seg_buffered;
|
||||||
TCP_S2C_UNVERIFIED_RST_RCVD = 1 << 7,
|
uint64_t nr_seg_released;
|
||||||
|
|
||||||
|
uint32_t seq;
|
||||||
|
uint32_t ack;
|
||||||
|
uint8_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
// the TCP protocol control block
|
// the TCP protocol control block
|
||||||
struct tcp_pcb
|
struct tcp_pcb
|
||||||
{
|
{
|
||||||
struct tcp_reassembly *c2s_assembler;
|
struct tcp_half c2s;
|
||||||
struct tcp_reassembly *s2c_assembler;
|
struct tcp_half s2c;
|
||||||
|
|
||||||
struct tcp_segment order_seg; // order segment from raw packet
|
|
||||||
uint16_t sub_state; // tcp sub state
|
|
||||||
|
|
||||||
uint32_t c2s_seq;
|
|
||||||
uint32_t s2c_seq;
|
|
||||||
|
|
||||||
uint32_t c2s_ack;
|
|
||||||
uint32_t s2c_ack;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct session
|
struct session
|
||||||
@@ -181,16 +178,6 @@ void *session_get_user_data(const struct session *sess);
|
|||||||
struct tcp_segment *session_get_tcp_segment(struct session *sess);
|
struct tcp_segment *session_get_tcp_segment(struct session *sess);
|
||||||
void session_free_tcp_segment(struct session *sess, struct tcp_segment *seg);
|
void session_free_tcp_segment(struct session *sess, struct tcp_segment *seg);
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* to string
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
const char *closing_reason_to_str(enum closing_reason reason);
|
|
||||||
const char *session_state_to_str(enum session_state state);
|
|
||||||
const char *session_type_to_str(enum session_type type);
|
|
||||||
const char *session_dir_to_str(enum session_dir dir);
|
|
||||||
void session_dump(struct session *sess);
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* session ex data
|
* session ex data
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -222,6 +209,16 @@ void *session_get0_ex_data(const struct session *sess, uint8_t idx);
|
|||||||
void session_free_ex_data(struct session *sess, uint8_t idx);
|
void session_free_ex_data(struct session *sess, uint8_t idx);
|
||||||
void session_free_all_ex_data(struct session *sess);
|
void session_free_all_ex_data(struct session *sess);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* to string
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
const char *closing_reason_to_str(enum closing_reason reason);
|
||||||
|
const char *session_state_to_str(enum session_state state);
|
||||||
|
const char *session_type_to_str(enum session_type type);
|
||||||
|
const char *session_dir_to_str(enum session_dir dir);
|
||||||
|
void session_dump(struct session *sess);
|
||||||
|
|
||||||
#ifdef __cpluscplus
|
#ifdef __cpluscplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,25 +15,7 @@
|
|||||||
|
|
||||||
struct session_manager
|
struct session_manager
|
||||||
{
|
{
|
||||||
// max session number
|
struct session_manager_options opts;
|
||||||
uint64_t max_tcp_session_num;
|
|
||||||
uint64_t max_udp_session_num;
|
|
||||||
// session overload
|
|
||||||
uint8_t tcp_overload_evict_old_sess; // 1: evict old session, 0: bypass new session
|
|
||||||
uint8_t udp_overload_evict_old_sess; // 1: evict old session, 0: bypass new session
|
|
||||||
// TCP timeout
|
|
||||||
uint64_t tcp_init_timeout; // range: [1, 60000]
|
|
||||||
uint64_t tcp_handshake_timeout; // range: [1, 60000]
|
|
||||||
uint64_t tcp_data_timeout; // range: [1, 15999999000]
|
|
||||||
uint64_t tcp_half_closed_timeout; // range: [1, 604800000]
|
|
||||||
uint64_t tcp_time_wait_timeout; // range: [1, 600000]
|
|
||||||
uint64_t tcp_discard_timeout; // range: [1, 15999999000]
|
|
||||||
uint64_t tcp_unverified_rst_timeout; // range: [1, 600000]
|
|
||||||
// UDP timeout
|
|
||||||
uint64_t udp_data_timeout; // range: [1, 15999999000]
|
|
||||||
// TCP reassembly
|
|
||||||
uint32_t tcp_reassembly_max_timeout; // range: [1, 60000] (ms)
|
|
||||||
uint32_t tcp_reassembly_max_segments; // range: [2, 32]
|
|
||||||
|
|
||||||
struct session_pool *sess_pool;
|
struct session_pool *sess_pool;
|
||||||
struct session_table *tcp_sess_table;
|
struct session_table *tcp_sess_table;
|
||||||
@@ -58,6 +40,16 @@ int check_options(const struct session_manager_options *opts)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts->max_tcp_session_num < EVICTE_SESSION_BURST * 2)
|
||||||
|
{
|
||||||
|
SESSION_LOG_ERROR("invalid max_tcp_session_num: %lu, supported range: [%u, %lu]", opts->max_tcp_session_num, EVICTE_SESSION_BURST * 2, UINT64_MAX);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (opts->max_udp_session_num < EVICTE_SESSION_BURST * 2)
|
||||||
|
{
|
||||||
|
SESSION_LOG_ERROR("invalid max_udp_session_num: %lu, supported range: [%u, %lu]", opts->max_udp_session_num, EVICTE_SESSION_BURST * 2, UINT64_MAX);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (opts->tcp_init_timeout < 1 || opts->tcp_init_timeout > 60000)
|
if (opts->tcp_init_timeout < 1 || opts->tcp_init_timeout > 60000)
|
||||||
{
|
{
|
||||||
SESSION_LOG_ERROR("invalid tcp_init_timeout: %lu, supported range: [1, 60000]", opts->tcp_init_timeout);
|
SESSION_LOG_ERROR("invalid tcp_init_timeout: %lu, supported range: [1, 60000]", opts->tcp_init_timeout);
|
||||||
@@ -116,16 +108,16 @@ static void tcp_pcb_clean(struct tcp_pcb *pcb)
|
|||||||
{
|
{
|
||||||
if (pcb)
|
if (pcb)
|
||||||
{
|
{
|
||||||
tcp_reassembly_free(pcb->c2s_assembler);
|
tcp_reassembly_free(pcb->c2s.assembler);
|
||||||
tcp_reassembly_free(pcb->s2c_assembler);
|
tcp_reassembly_free(pcb->s2c.assembler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tcp_pcb_init(struct tcp_pcb *pcb, uint64_t max_timeout, uint64_t max_seg_num)
|
static int tcp_pcb_init(struct tcp_pcb *pcb, uint64_t max_timeout, uint64_t max_seg_num)
|
||||||
{
|
{
|
||||||
pcb->c2s_assembler = tcp_reassembly_new(max_timeout, max_seg_num);
|
pcb->c2s.assembler = tcp_reassembly_new(max_timeout, max_seg_num);
|
||||||
pcb->s2c_assembler = tcp_reassembly_new(max_timeout, max_seg_num);
|
pcb->s2c.assembler = tcp_reassembly_new(max_timeout, max_seg_num);
|
||||||
if (pcb->c2s_assembler == NULL || pcb->s2c_assembler == NULL)
|
if (pcb->c2s.assembler == NULL || pcb->s2c.assembler == NULL)
|
||||||
{
|
{
|
||||||
tcp_pcb_clean(pcb);
|
tcp_pcb_clean(pcb);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -134,100 +126,69 @@ static int tcp_pcb_init(struct tcp_pcb *pcb, uint64_t max_timeout, uint64_t max_
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcp_pcb_update(struct tcp_pcb *pcb, enum session_dir dir, const struct pkt_layer *tcp_layer, uint64_t now)
|
static void tcp_half_update(struct tcp_half *half, const struct pkt_layer *tcp_layer, uint64_t now)
|
||||||
{
|
{
|
||||||
struct tcp_segment *seg;
|
struct tcp_segment *seg;
|
||||||
struct tcp_reassembly *assembler;
|
|
||||||
struct tcphdr *hdr = (struct tcphdr *)tcp_layer->hdr_ptr;
|
struct tcphdr *hdr = (struct tcphdr *)tcp_layer->hdr_ptr;
|
||||||
|
|
||||||
uint32_t seq = tcp_hdr_get_seq(hdr);
|
|
||||||
uint32_t ack = tcp_hdr_get_ack(hdr);
|
|
||||||
uint8_t flags = tcp_hdr_get_flags(hdr);
|
uint8_t flags = tcp_hdr_get_flags(hdr);
|
||||||
uint32_t rcv_nxt;
|
|
||||||
|
|
||||||
/*
|
half->flags |= flags;
|
||||||
* https://www.rfc-editor.org/rfc/rfc5961#section-3.2
|
half->seq = tcp_hdr_get_seq(hdr);
|
||||||
*
|
half->ack = tcp_hdr_get_ack(hdr);
|
||||||
* If the RST bit is set and the sequence number exactly matches the
|
|
||||||
* next expected sequence number (RCV.NXT), then TCP MUST reset the
|
|
||||||
* connection.
|
|
||||||
*
|
|
||||||
* if fin is received, the expected sequence number should be increased by 1
|
|
||||||
*/
|
|
||||||
uint16_t expect = 0;
|
|
||||||
if (dir == SESSION_DIR_C2S)
|
|
||||||
{
|
|
||||||
pcb->c2s_seq = seq;
|
|
||||||
pcb->c2s_ack = ack;
|
|
||||||
assembler = pcb->c2s_assembler;
|
|
||||||
|
|
||||||
expect = pcb->s2c_ack;
|
|
||||||
expect += pcb->sub_state & TCP_S2C_FIN_RCVD ? 1 : 0;
|
|
||||||
|
|
||||||
pcb->sub_state |= (flags & TH_SYN) ? TCP_SYN_RCVD : 0;
|
|
||||||
pcb->sub_state |= (flags & TH_FIN) ? TCP_C2S_FIN_RCVD : 0;
|
|
||||||
pcb->sub_state |= ((flags & TH_RST) && (seq == expect)) ? TCP_C2S_RST_RCVD : 0;
|
|
||||||
pcb->sub_state |= ((flags & TH_RST) && (seq != expect)) ? TCP_C2S_UNVERIFIED_RST_RCVD : 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pcb->s2c_seq = seq;
|
|
||||||
pcb->s2c_ack = ack;
|
|
||||||
assembler = pcb->s2c_assembler;
|
|
||||||
|
|
||||||
expect = pcb->c2s_ack;
|
|
||||||
expect += pcb->sub_state & TCP_C2S_FIN_RCVD ? 1 : 0;
|
|
||||||
|
|
||||||
pcb->sub_state |= (flags & TH_SYN) ? TCP_SYN_ACK_RCVD : 0;
|
|
||||||
pcb->sub_state |= (flags & TH_FIN) ? TCP_S2C_FIN_RCVD : 0;
|
|
||||||
pcb->sub_state |= ((flags & TH_RST) && (seq == expect)) ? TCP_S2C_RST_RCVD : 0;
|
|
||||||
pcb->sub_state |= ((flags & TH_RST) && (seq != expect)) ? TCP_S2C_UNVERIFIED_RST_RCVD : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & TH_SYN)
|
if (flags & TH_SYN)
|
||||||
{
|
{
|
||||||
tcp_reassembly_set_recv_next(assembler, seq + 1);
|
tcp_reassembly_set_recv_next(half->assembler, half->seq + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
seg = tcp_reassembly_expire(assembler, now);
|
seg = tcp_reassembly_expire(half->assembler, now);
|
||||||
if (seg)
|
if (seg)
|
||||||
{
|
{
|
||||||
// TODO add metric (expire)
|
half->nr_seg_expired++;
|
||||||
|
half->nr_seg_released++;
|
||||||
tcp_segment_free(seg);
|
tcp_segment_free(seg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcp_layer->pld_len)
|
if (tcp_layer->pld_len)
|
||||||
{
|
{
|
||||||
rcv_nxt = tcp_reassembly_get_recv_next(assembler);
|
half->nr_seg_received++;
|
||||||
if (seq == rcv_nxt)
|
uint32_t rcv_nxt = tcp_reassembly_get_recv_next(half->assembler);
|
||||||
|
if (half->seq == rcv_nxt)
|
||||||
{
|
{
|
||||||
pcb->order_seg.data = tcp_layer->pld_ptr;
|
half->nr_seg_inorder++;
|
||||||
pcb->order_seg.len = tcp_layer->pld_len;
|
half->order.data = tcp_layer->pld_ptr;
|
||||||
tcp_reassembly_inc_recv_next(assembler, tcp_layer->pld_len);
|
half->order.len = tcp_layer->pld_len;
|
||||||
|
tcp_reassembly_inc_recv_next(half->assembler, tcp_layer->pld_len);
|
||||||
}
|
}
|
||||||
else if (before(seq, rcv_nxt))
|
else if (before(half->seq, rcv_nxt))
|
||||||
{
|
{
|
||||||
// TODO add metric (overlap)
|
// TODO add metric (overlap)
|
||||||
|
half->nr_seg_overlap++;
|
||||||
}
|
}
|
||||||
else if ((seg = tcp_segment_new(seq, tcp_layer->pld_ptr, tcp_layer->pld_len)))
|
else if ((seg = tcp_segment_new(half->seq, tcp_layer->pld_ptr, tcp_layer->pld_len)))
|
||||||
{
|
{
|
||||||
switch (tcp_reassembly_push(assembler, seg, now))
|
switch (tcp_reassembly_push(half->assembler, seg, now))
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
// TODO add metric (assembler full)
|
half->nr_seg_no_space++;
|
||||||
tcp_segment_free(seg);
|
tcp_segment_free(seg);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
// TODO add metric (assembler push success)
|
half->nr_seg_buffered++;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// TODO add metric (assembler push success, overlap)
|
half->nr_seg_buffered++;
|
||||||
|
half->nr_seg_overlap++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
half->nr_seg_no_space++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,7 +324,7 @@ static int session_manager_self_protection(struct session_manager *mgr, struct s
|
|||||||
switch (key->ip_proto)
|
switch (key->ip_proto)
|
||||||
{
|
{
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
if (stat->tcp_sess.nr_sess_used >= mgr->max_tcp_session_num)
|
if (stat->tcp_sess.nr_sess_used >= mgr->opts.max_tcp_session_num)
|
||||||
{
|
{
|
||||||
stat->evc_pkt.nr_pkts++;
|
stat->evc_pkt.nr_pkts++;
|
||||||
stat->evc_pkt.nr_bytes += packet_get_len(pkt);
|
stat->evc_pkt.nr_bytes += packet_get_len(pkt);
|
||||||
@@ -372,7 +333,7 @@ static int session_manager_self_protection(struct session_manager *mgr, struct s
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IPPROTO_UDP:
|
case IPPROTO_UDP:
|
||||||
if (stat->udp_sess.nr_sess_used >= mgr->max_udp_session_num)
|
if (stat->udp_sess.nr_sess_used >= mgr->opts.max_udp_session_num)
|
||||||
{
|
{
|
||||||
stat->evc_pkt.nr_pkts++;
|
stat->evc_pkt.nr_pkts++;
|
||||||
stat->evc_pkt.nr_bytes += packet_get_len(pkt);
|
stat->evc_pkt.nr_bytes += packet_get_len(pkt);
|
||||||
@@ -559,7 +520,7 @@ static struct session *session_manager_new_tcp_session(struct session_manager *m
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tcp table full evict old session
|
// tcp table full evict old session
|
||||||
if (mgr->tcp_overload_evict_old_sess && mgr->stat.tcp_sess.nr_sess_used >= mgr->max_tcp_session_num - EVICTE_SESSION_BURST)
|
if (mgr->opts.tcp_overload_evict_old_sess && mgr->stat.tcp_sess.nr_sess_used >= mgr->opts.max_tcp_session_num - EVICTE_SESSION_BURST)
|
||||||
{
|
{
|
||||||
struct session *evic_sess = session_table_find_lru(mgr->tcp_sess_table);
|
struct session *evic_sess = session_table_find_lru(mgr->tcp_sess_table);
|
||||||
session_manager_evicte_session(mgr, evic_sess, now);
|
session_manager_evicte_session(mgr, evic_sess, now);
|
||||||
@@ -575,20 +536,21 @@ static struct session *session_manager_new_tcp_session(struct session_manager *m
|
|||||||
session_init(sess);
|
session_init(sess);
|
||||||
session_set_id(sess, id_generator_alloc());
|
session_set_id(sess, id_generator_alloc());
|
||||||
|
|
||||||
if (tcp_pcb_init(&sess->tcp_pcb, mgr->tcp_reassembly_max_timeout, mgr->tcp_reassembly_max_segments) == -1)
|
if (tcp_pcb_init(&sess->tcp_pcb, mgr->opts.tcp_reassembly_max_timeout, mgr->opts.tcp_reassembly_max_segments) == -1)
|
||||||
{
|
{
|
||||||
assert(0);
|
assert(0);
|
||||||
session_pool_push(mgr->sess_pool, sess);
|
session_pool_push(mgr->sess_pool, sess);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
tcp_pcb_update(&sess->tcp_pcb, dir, tcp_layer, now);
|
struct tcp_half *curr = (dir == SESSION_DIR_C2S) ? &sess->tcp_pcb.c2s : &sess->tcp_pcb.s2c;
|
||||||
|
tcp_half_update(curr, tcp_layer, now);
|
||||||
|
|
||||||
enum session_state next_state = session_transition_run(SESSION_STATE_INIT, TCP_SYN);
|
enum session_state next_state = session_transition_run(SESSION_STATE_INIT, TCP_SYN);
|
||||||
session_update(sess, next_state, pkt, key, dir, now);
|
session_update(sess, next_state, pkt, key, dir, now);
|
||||||
session_transition_log(sess, SESSION_STATE_INIT, next_state, TCP_SYN);
|
session_transition_log(sess, SESSION_STATE_INIT, next_state, TCP_SYN);
|
||||||
session_stat_inc(&mgr->stat.tcp_sess, next_state);
|
session_stat_inc(&mgr->stat.tcp_sess, next_state);
|
||||||
|
|
||||||
uint64_t timeout = (flags & TH_ACK) ? mgr->tcp_handshake_timeout : mgr->tcp_init_timeout;
|
uint64_t timeout = (flags & TH_ACK) ? mgr->opts.tcp_handshake_timeout : mgr->opts.tcp_init_timeout;
|
||||||
session_timer_update(mgr->sess_timer, sess, now + timeout);
|
session_timer_update(mgr->sess_timer, sess, now + timeout);
|
||||||
session_table_add(mgr->tcp_sess_table, key, sess);
|
session_table_add(mgr->tcp_sess_table, key, sess);
|
||||||
|
|
||||||
@@ -601,7 +563,7 @@ static struct session *session_manager_new_tcp_session(struct session_manager *m
|
|||||||
static struct session *session_manager_new_udp_session(struct session_manager *mgr, const struct packet *pkt, const struct tuple6 *key, uint64_t now)
|
static struct session *session_manager_new_udp_session(struct session_manager *mgr, const struct packet *pkt, const struct tuple6 *key, uint64_t now)
|
||||||
{
|
{
|
||||||
// udp table full evict old session
|
// udp table full evict old session
|
||||||
if (mgr->udp_overload_evict_old_sess && mgr->stat.udp_sess.nr_sess_used >= mgr->max_udp_session_num - EVICTE_SESSION_BURST)
|
if (mgr->opts.udp_overload_evict_old_sess && mgr->stat.udp_sess.nr_sess_used >= mgr->opts.max_udp_session_num - EVICTE_SESSION_BURST)
|
||||||
{
|
{
|
||||||
struct session *evic_sess = session_table_find_lru(mgr->udp_sess_table);
|
struct session *evic_sess = session_table_find_lru(mgr->udp_sess_table);
|
||||||
session_manager_evicte_session(mgr, evic_sess, now);
|
session_manager_evicte_session(mgr, evic_sess, now);
|
||||||
@@ -623,7 +585,7 @@ static struct session *session_manager_new_udp_session(struct session_manager *m
|
|||||||
session_transition_log(sess, SESSION_STATE_INIT, next_state, UDP_DATA);
|
session_transition_log(sess, SESSION_STATE_INIT, next_state, UDP_DATA);
|
||||||
session_stat_inc(&mgr->stat.udp_sess, next_state);
|
session_stat_inc(&mgr->stat.udp_sess, next_state);
|
||||||
|
|
||||||
session_timer_update(mgr->sess_timer, sess, now + mgr->udp_data_timeout);
|
session_timer_update(mgr->sess_timer, sess, now + mgr->opts.udp_data_timeout);
|
||||||
session_table_add(mgr->udp_sess_table, key, sess);
|
session_table_add(mgr->udp_sess_table, key, sess);
|
||||||
|
|
||||||
return sess;
|
return sess;
|
||||||
@@ -635,65 +597,74 @@ static int session_manager_update_tcp_session(struct session_manager *mgr, struc
|
|||||||
const struct tcphdr *hdr = (const struct tcphdr *)tcp_layer->hdr_ptr;
|
const struct tcphdr *hdr = (const struct tcphdr *)tcp_layer->hdr_ptr;
|
||||||
enum session_dir dir = identify_direction_by_history(sess, key);
|
enum session_dir dir = identify_direction_by_history(sess, key);
|
||||||
uint8_t flags = tcp_hdr_get_flags(hdr);
|
uint8_t flags = tcp_hdr_get_flags(hdr);
|
||||||
int inputs = (flags & TH_SYN) ? TCP_SYN : NONE;
|
int inputs = 0;
|
||||||
|
inputs |= (flags & TH_SYN) ? TCP_SYN : NONE;
|
||||||
inputs |= (flags & TH_FIN) ? TCP_FIN : NONE;
|
inputs |= (flags & TH_FIN) ? TCP_FIN : NONE;
|
||||||
inputs |= (flags & TH_RST) ? TCP_RST : NONE;
|
inputs |= (flags & TH_RST) ? TCP_RST : NONE;
|
||||||
inputs |= tcp_layer->pld_len ? TCP_DATA : NONE;
|
inputs |= tcp_layer->pld_len ? TCP_DATA : NONE;
|
||||||
|
|
||||||
|
// update state
|
||||||
enum session_state curr_state = session_get_state(sess);
|
enum session_state curr_state = session_get_state(sess);
|
||||||
enum session_state next_state = session_transition_run(curr_state, inputs);
|
enum session_state next_state = session_transition_run(curr_state, inputs);
|
||||||
session_update(sess, next_state, pkt, key, dir, now);
|
|
||||||
session_transition_log(sess, curr_state, next_state, inputs);
|
|
||||||
session_stat_update(mgr, sess, curr_state, next_state);
|
|
||||||
|
|
||||||
tcp_pcb_update(&sess->tcp_pcb, dir, tcp_layer, now);
|
// update session
|
||||||
|
session_update(sess, next_state, pkt, key, dir, now);
|
||||||
|
session_stat_update(mgr, sess, curr_state, next_state);
|
||||||
|
session_transition_log(sess, curr_state, next_state, inputs);
|
||||||
|
|
||||||
|
// update tcp pcb
|
||||||
|
struct tcp_half *curr = (dir == SESSION_DIR_C2S) ? &sess->tcp_pcb.c2s : &sess->tcp_pcb.s2c;
|
||||||
|
struct tcp_half *peer = (dir == SESSION_DIR_C2S) ? &sess->tcp_pcb.s2c : &sess->tcp_pcb.c2s;
|
||||||
|
tcp_half_update(curr, tcp_layer, now);
|
||||||
|
|
||||||
// set closing reason
|
// set closing reason
|
||||||
if (next_state == SESSION_STATE_CLOSING && !session_get_closing_reason(sess))
|
if (next_state == SESSION_STATE_CLOSING && !session_get_closing_reason(sess))
|
||||||
{
|
{
|
||||||
if (tcp_hdr_get_fin_flag(hdr))
|
if (flags & TH_FIN)
|
||||||
{
|
{
|
||||||
session_set_closing_reason(sess, (dir == SESSION_DIR_C2S ? CLOSING_BY_CLIENT_FIN : CLOSING_BY_SERVER_FIN));
|
session_set_closing_reason(sess, (dir == SESSION_DIR_C2S ? CLOSING_BY_CLIENT_FIN : CLOSING_BY_SERVER_FIN));
|
||||||
}
|
}
|
||||||
if (tcp_hdr_get_rst_flag(hdr))
|
if (flags & TH_RST)
|
||||||
{
|
{
|
||||||
session_set_closing_reason(sess, (dir == SESSION_DIR_C2S ? CLOSING_BY_CLIENT_RST : CLOSING_BY_SERVER_RST));
|
session_set_closing_reason(sess, (dir == SESSION_DIR_C2S ? CLOSING_BY_CLIENT_RST : CLOSING_BY_SERVER_RST));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t sub_state = sess->tcp_pcb.sub_state;
|
// update timeout
|
||||||
|
|
||||||
uint64_t timeout = 0;
|
uint64_t timeout = 0;
|
||||||
switch (next_state)
|
switch (next_state)
|
||||||
{
|
{
|
||||||
case SESSION_STATE_OPENING:
|
case SESSION_STATE_OPENING:
|
||||||
if (flags & TH_SYN)
|
if (flags & TH_SYN)
|
||||||
{
|
{
|
||||||
timeout = (flags & TH_ACK) ? mgr->tcp_handshake_timeout : mgr->tcp_init_timeout;
|
timeout = (flags & TH_ACK) ? mgr->opts.tcp_handshake_timeout : mgr->opts.tcp_init_timeout;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timeout = mgr->tcp_data_timeout;
|
timeout = mgr->opts.tcp_data_timeout;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SESSION_STATE_ACTIVE:
|
case SESSION_STATE_ACTIVE:
|
||||||
timeout = mgr->tcp_data_timeout;
|
timeout = mgr->opts.tcp_data_timeout;
|
||||||
break;
|
break;
|
||||||
case SESSION_STATE_CLOSING:
|
case SESSION_STATE_CLOSING:
|
||||||
if (flags & TH_FIN)
|
if (flags & TH_FIN)
|
||||||
{
|
{
|
||||||
timeout = (sub_state & TCP_C2S_FIN_RCVD && sub_state & TCP_S2C_FIN_RCVD) ? mgr->tcp_time_wait_timeout : mgr->tcp_half_closed_timeout;
|
timeout = (peer->flags & TH_FIN) ? mgr->opts.tcp_time_wait_timeout : mgr->opts.tcp_half_closed_timeout;
|
||||||
}
|
}
|
||||||
else if (flags & TH_RST)
|
else if (flags & TH_RST)
|
||||||
{
|
{
|
||||||
timeout = (sub_state & TCP_C2S_RST_RCVD || sub_state & TCP_S2C_RST_RCVD) ? mgr->tcp_time_wait_timeout : mgr->tcp_unverified_rst_timeout;
|
// if fin is received, the expected sequence number should be increased by 1
|
||||||
|
uint32_t expected = (peer->flags & TH_FIN) ? peer->ack + 1 : peer->ack;
|
||||||
|
timeout = (expected == curr->seq) ? mgr->opts.tcp_time_wait_timeout : mgr->opts.tcp_unverified_rst_timeout;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timeout = mgr->tcp_data_timeout;
|
timeout = mgr->opts.tcp_data_timeout;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SESSION_STATE_DISCARD:
|
case SESSION_STATE_DISCARD:
|
||||||
timeout = mgr->tcp_discard_timeout;
|
timeout = mgr->opts.tcp_discard_timeout;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -712,7 +683,7 @@ static int session_manager_update_udp_session(struct session_manager *mgr, struc
|
|||||||
session_update(sess, next_state, pkt, key, dir, now);
|
session_update(sess, next_state, pkt, key, dir, now);
|
||||||
session_transition_log(sess, curr_state, next_state, UDP_DATA);
|
session_transition_log(sess, curr_state, next_state, UDP_DATA);
|
||||||
session_stat_update(mgr, sess, curr_state, next_state);
|
session_stat_update(mgr, sess, curr_state, next_state);
|
||||||
session_timer_update(mgr->sess_timer, sess, now + mgr->udp_data_timeout);
|
session_timer_update(mgr->sess_timer, sess, now + mgr->opts.udp_data_timeout);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -733,26 +704,9 @@ struct session_manager *session_manager_new(struct session_manager_options *opts
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// max session number
|
|
||||||
mgr->max_tcp_session_num = (opts->max_tcp_session_num < EVICTE_SESSION_BURST * 2) ? EVICTE_SESSION_BURST * 2 : opts->max_tcp_session_num;
|
|
||||||
mgr->max_udp_session_num = (opts->max_udp_session_num < EVICTE_SESSION_BURST * 2) ? EVICTE_SESSION_BURST * 2 : opts->max_udp_session_num;
|
|
||||||
// session overload
|
|
||||||
mgr->stat.tcp_sess.nr_sess_init = 0;
|
|
||||||
mgr->tcp_overload_evict_old_sess = opts->tcp_overload_evict_old_sess;
|
|
||||||
mgr->udp_overload_evict_old_sess = opts->udp_overload_evict_old_sess;
|
|
||||||
// session timeout
|
|
||||||
mgr->tcp_init_timeout = opts->tcp_init_timeout;
|
|
||||||
mgr->tcp_handshake_timeout = opts->tcp_handshake_timeout;
|
|
||||||
mgr->tcp_data_timeout = opts->tcp_data_timeout;
|
|
||||||
mgr->tcp_half_closed_timeout = opts->tcp_half_closed_timeout;
|
|
||||||
mgr->tcp_time_wait_timeout = opts->tcp_time_wait_timeout;
|
|
||||||
mgr->tcp_discard_timeout = opts->tcp_discard_timeout;
|
|
||||||
mgr->tcp_unverified_rst_timeout = opts->tcp_unverified_rst_timeout;
|
|
||||||
mgr->udp_data_timeout = opts->udp_data_timeout;
|
|
||||||
|
|
||||||
// tcp reassembly
|
memcpy(&mgr->opts, opts, sizeof(struct session_manager_options));
|
||||||
mgr->tcp_reassembly_max_timeout = opts->tcp_reassembly_max_timeout;
|
|
||||||
mgr->tcp_reassembly_max_segments = opts->tcp_reassembly_max_segments;
|
|
||||||
// duplicated packet filter
|
// duplicated packet filter
|
||||||
struct duplicated_packet_filter_options duplicated_packet_filter_opts = {
|
struct duplicated_packet_filter_options duplicated_packet_filter_opts = {
|
||||||
.enable = opts->duplicated_packet_filter_enable,
|
.enable = opts->duplicated_packet_filter_enable,
|
||||||
@@ -768,7 +722,7 @@ struct session_manager *session_manager_new(struct session_manager_options *opts
|
|||||||
.error_rate = opts->evicted_session_filter_error_rate,
|
.error_rate = opts->evicted_session_filter_error_rate,
|
||||||
};
|
};
|
||||||
|
|
||||||
mgr->sess_pool = session_pool_new(mgr->max_tcp_session_num + mgr->max_udp_session_num);
|
mgr->sess_pool = session_pool_new(mgr->opts.max_tcp_session_num + mgr->opts.max_udp_session_num);
|
||||||
mgr->tcp_sess_table = session_table_new();
|
mgr->tcp_sess_table = session_table_new();
|
||||||
mgr->udp_sess_table = session_table_new();
|
mgr->udp_sess_table = session_table_new();
|
||||||
mgr->sess_timer = session_timer_new(now);
|
mgr->sess_timer = session_timer_new(now);
|
||||||
@@ -946,10 +900,10 @@ struct session *session_manager_get_expired_session(struct session_manager *mgr,
|
|||||||
switch (session_get_type(sess))
|
switch (session_get_type(sess))
|
||||||
{
|
{
|
||||||
case SESSION_TYPE_TCP:
|
case SESSION_TYPE_TCP:
|
||||||
timeout = mgr->tcp_data_timeout;
|
timeout = mgr->opts.tcp_data_timeout;
|
||||||
break;
|
break;
|
||||||
case SESSION_TYPE_UDP:
|
case SESSION_TYPE_UDP:
|
||||||
timeout = mgr->udp_data_timeout;
|
timeout = mgr->opts.udp_data_timeout;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user