session manager support tcp reassembly
This commit is contained in:
@@ -48,3 +48,9 @@ evicted_session_filter_enable = 1
|
||||
evicted_session_filter_capacity = 1000000
|
||||
evicted_session_filter_timeout = 10000 # ms, Range: 1-60,000
|
||||
evicted_session_filter_error_rate = 0.00001
|
||||
|
||||
# TCP reassembly (Per direction)
|
||||
tcp_reassembly_enable = 1
|
||||
tcp_reassembly_max_timeout = 10000 # ms, Range: 1-60,000
|
||||
tcp_reassembly_max_segments = 8 # 0: unlimited
|
||||
tcp_reassembly_max_bytes = 0 # 0: unlimited
|
||||
|
||||
@@ -357,6 +357,39 @@ static int parse_session_manager_options(toml_table_t *table, struct session_man
|
||||
}
|
||||
opts->evicted_session_filter_error_rate = atof(ptr);
|
||||
|
||||
// TCP reassembly
|
||||
ptr = toml_raw_in(session_manager, "tcp_reassembly_enable");
|
||||
if (ptr == NULL)
|
||||
{
|
||||
CONFIG_LOG_ERROR("config file missing session_manager.tcp_reassembly_enable");
|
||||
return -1;
|
||||
}
|
||||
opts->tcp_reassembly_enable = atoi(ptr);
|
||||
|
||||
ptr = toml_raw_in(session_manager, "tcp_reassembly_max_timeout");
|
||||
if (ptr == NULL)
|
||||
{
|
||||
CONFIG_LOG_ERROR("config file missing session_manager.tcp_reassembly_max_timeout");
|
||||
return -1;
|
||||
}
|
||||
opts->tcp_reassembly_max_timeout = atoi(ptr);
|
||||
|
||||
ptr = toml_raw_in(session_manager, "tcp_reassembly_max_segments");
|
||||
if (ptr == NULL)
|
||||
{
|
||||
CONFIG_LOG_ERROR("config file missing session_manager.tcp_reassembly_max_segments");
|
||||
return -1;
|
||||
}
|
||||
opts->tcp_reassembly_max_segments = atoi(ptr);
|
||||
|
||||
ptr = toml_raw_in(session_manager, "tcp_reassembly_max_bytes");
|
||||
if (ptr == NULL)
|
||||
{
|
||||
CONFIG_LOG_ERROR("config file missing session_manager.tcp_reassembly_max_bytes");
|
||||
return -1;
|
||||
}
|
||||
opts->tcp_reassembly_max_bytes = atoi(ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -485,4 +518,10 @@ void print_config_options(struct config *config)
|
||||
CONFIG_LOG_DEBUG("session_manager->evicted_session_filter_capacity : %d", sess_mgr_opts->evicted_session_filter_capacity);
|
||||
CONFIG_LOG_DEBUG("session_manager->evicted_session_filter_timeout : %d", sess_mgr_opts->evicted_session_filter_timeout);
|
||||
CONFIG_LOG_DEBUG("session_manager->evicted_session_filter_error_rate : %f", sess_mgr_opts->evicted_session_filter_error_rate);
|
||||
|
||||
// TCP reassembly
|
||||
CONFIG_LOG_DEBUG("session_manager->tcp_reassembly_enable : %d", sess_mgr_opts->tcp_reassembly_enable);
|
||||
CONFIG_LOG_DEBUG("session_manager->tcp_reassembly_max_timeout : %d", sess_mgr_opts->tcp_reassembly_max_timeout);
|
||||
CONFIG_LOG_DEBUG("session_manager->tcp_reassembly_max_segments : %d", sess_mgr_opts->tcp_reassembly_max_segments);
|
||||
CONFIG_LOG_DEBUG("session_manager->tcp_reassembly_max_bytes : %d", sess_mgr_opts->tcp_reassembly_max_bytes);
|
||||
}
|
||||
|
||||
@@ -68,20 +68,23 @@ static void pcap_handle(u_char *user, const struct pcap_pkthdr *h, const u_char
|
||||
|
||||
static int dumpfile_handle(const char *file, void *arg)
|
||||
{
|
||||
char resolved_path[256];
|
||||
char pcap_errbuf[PCAP_ERRBUF_SIZE];
|
||||
struct packet_io_dumpfile *handle = (struct packet_io_dumpfile *)arg;
|
||||
|
||||
PACKET_IO_LOG_STATE("dumpfile %s in-processing", file)
|
||||
realpath(file, resolved_path);
|
||||
PACKET_IO_LOG_STATE("dumpfile %s in-processing", resolved_path)
|
||||
|
||||
handle->pcap = pcap_open_offline(file, NULL);
|
||||
handle->pcap = pcap_open_offline(file, pcap_errbuf);
|
||||
if (handle->pcap == NULL)
|
||||
{
|
||||
PACKET_IO_LOG_ERROR("unable to open pcap file: %s", file);
|
||||
PACKET_IO_LOG_ERROR("unable to open pcap file: %s, %s", resolved_path, pcap_errbuf);
|
||||
return -1;
|
||||
}
|
||||
pcap_loop(handle->pcap, -1, pcap_handle, (u_char *)handle);
|
||||
pcap_close(handle->pcap);
|
||||
|
||||
PACKET_IO_LOG_STATE("dumpfile %s processed", file)
|
||||
PACKET_IO_LOG_STATE("dumpfile %s processed", resolved_path)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ add_library(session_manager
|
||||
)
|
||||
target_include_directories(session_manager PUBLIC ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_include_directories(session_manager PUBLIC ${CMAKE_SOURCE_DIR}/src/stellar)
|
||||
target_link_libraries(session_manager timeout id_generator duplicated_packet_filter evicted_session_filter log)
|
||||
target_link_libraries(session_manager timeout id_generator duplicated_packet_filter evicted_session_filter log tcp_reassembly)
|
||||
|
||||
add_subdirectory(test)
|
||||
@@ -236,6 +236,47 @@ enum session_dir session_get_cur_dir(const struct session *sess)
|
||||
return sess->cur_dir;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* session tcp reassembly
|
||||
******************************************************************************/
|
||||
|
||||
const char *session_peek_tcp_payload(struct session *sess, uint32_t *len)
|
||||
{
|
||||
if (sess->type != SESSION_TYPE_TCP)
|
||||
{
|
||||
*len = 0;
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sess->cur_dir == SESSION_DIR_C2S)
|
||||
{
|
||||
return tcp_reassembly_peek(sess->c2s_reassembly, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tcp_reassembly_peek(sess->s2c_reassembly, len);
|
||||
}
|
||||
}
|
||||
|
||||
void session_consume_tcp_payload(struct session *sess, uint32_t len)
|
||||
{
|
||||
if (sess->type != SESSION_TYPE_TCP)
|
||||
{
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sess->cur_dir == SESSION_DIR_C2S)
|
||||
{
|
||||
tcp_reassembly_consume(sess->c2s_reassembly, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
tcp_reassembly_consume(sess->s2c_reassembly, len);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* session ex data
|
||||
******************************************************************************/
|
||||
@@ -327,7 +368,7 @@ void session_free_ex_data(struct session *sess, uint8_t idx)
|
||||
sess->ex_data[idx] = NULL;
|
||||
}
|
||||
|
||||
void session_clean(struct session *sess)
|
||||
void session_free_all_ex_data(struct session *sess)
|
||||
{
|
||||
if (sess)
|
||||
{
|
||||
@@ -335,18 +376,6 @@ void session_clean(struct session *sess)
|
||||
{
|
||||
session_free_ex_data(sess, i);
|
||||
}
|
||||
|
||||
if (sess->c2s_1st_pkt)
|
||||
{
|
||||
packet_free(sess->c2s_1st_pkt);
|
||||
sess->c2s_1st_pkt = NULL;
|
||||
}
|
||||
|
||||
if (sess->s2c_1st_pkt)
|
||||
{
|
||||
packet_free(sess->s2c_1st_pkt);
|
||||
sess->s2c_1st_pkt = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,13 @@ const struct packet *session_get0_cur_pkt(const struct session *sess);
|
||||
void session_set_cur_dir(struct session *sess, enum session_dir dir);
|
||||
enum session_dir session_get_cur_dir(const struct session *sess);
|
||||
|
||||
/******************************************************************************
|
||||
* session tcp reassembly
|
||||
******************************************************************************/
|
||||
|
||||
const char *session_peek_tcp_payload(struct session *sess, uint32_t *len);
|
||||
void session_consume_tcp_payload(struct session *sess, uint32_t len);
|
||||
|
||||
/******************************************************************************
|
||||
* session ex data
|
||||
******************************************************************************/
|
||||
@@ -150,7 +157,7 @@ void *session_get0_ex_data(const struct session *sess, uint8_t idx);
|
||||
* if user want to free ex_data, should use session_free_ex_data.
|
||||
*/
|
||||
void session_free_ex_data(struct session *sess, uint8_t idx);
|
||||
void session_clean(struct session *sess);
|
||||
void session_free_all_ex_data(struct session *sess);
|
||||
|
||||
/******************************************************************************
|
||||
* session expire
|
||||
|
||||
@@ -32,6 +32,8 @@ struct session_manager
|
||||
|
||||
#define EVICTE_SESSION_BURST (RX_BURST_MAX)
|
||||
|
||||
struct tcp_reassembly_options tcp_reassembly_opts = {0};
|
||||
|
||||
/******************************************************************************
|
||||
* Options
|
||||
******************************************************************************/
|
||||
@@ -150,6 +152,20 @@ static int check_options(struct session_manager_options *opts)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// TCP reassembly opts
|
||||
if (opts->tcp_reassembly_enable != 0 && opts->tcp_reassembly_enable != 1)
|
||||
{
|
||||
SESSION_LOG_ERROR("invalid tcp reassembly enable, support range: 0-1");
|
||||
return -1;
|
||||
}
|
||||
if (opts->tcp_reassembly_enable)
|
||||
{
|
||||
if (opts->tcp_reassembly_max_timeout < 1 || opts->tcp_reassembly_max_timeout > 60000)
|
||||
{
|
||||
SESSION_LOG_ERROR("invalid tcp reassembly max timeout, support range: 1-60,000");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -500,16 +516,31 @@ static struct session *session_manager_new_tcp_session(struct session_manager *m
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
mgr->stat.tcp_sess.nr_sess_used++;
|
||||
session_init(sess);
|
||||
session_set_id(sess, id_generator_alloc());
|
||||
sess->c2s_reassembly = tcp_reassembly_new(&tcp_reassembly_opts);
|
||||
sess->s2c_reassembly = tcp_reassembly_new(&tcp_reassembly_opts);
|
||||
if (sess->c2s_reassembly == NULL || sess->s2c_reassembly == NULL)
|
||||
{
|
||||
assert(0);
|
||||
session_pool_push(mgr->sess_pool, sess);
|
||||
return NULL;
|
||||
}
|
||||
mgr->stat.tcp_sess.nr_sess_used++;
|
||||
|
||||
enum session_dir dir = tcp_hdr_get_ack_flag(hdr) ? SESSION_DIR_S2C : SESSION_DIR_C2S;
|
||||
enum session_state next_state = session_transition_run(SESSION_STATE_INIT, TCP_SYN);
|
||||
session_transition_log(sess, SESSION_STATE_INIT, next_state, TCP_SYN);
|
||||
session_update(sess, next_state, pkt, key, dir, now);
|
||||
session_transition_log(sess, SESSION_STATE_INIT, next_state, TCP_SYN);
|
||||
session_stat_inc(&mgr->stat.tcp_sess, next_state);
|
||||
|
||||
tcp_reassembly_init(dir == SESSION_DIR_C2S ? sess->c2s_reassembly : sess->s2c_reassembly, tcp_hdr_get_seq(hdr));
|
||||
if (tcp_layer->pld_len)
|
||||
{
|
||||
tcp_reassembly_insert(dir == SESSION_DIR_C2S ? sess->c2s_reassembly : sess->s2c_reassembly,
|
||||
tcp_hdr_get_seq(hdr), tcp_layer->pld_ptr, tcp_layer->pld_len, now);
|
||||
}
|
||||
|
||||
uint64_t timeout = tcp_hdr_get_ack_flag(hdr) ? opts->tcp_timeout_handshake : opts->tcp_timeout_init;
|
||||
timer_update(mgr->sess_timer, sess, now + timeout);
|
||||
session_table_add(mgr->tcp_sess_table, key, sess);
|
||||
@@ -542,8 +573,8 @@ static struct session *session_manager_new_udp_session(struct session_manager *m
|
||||
|
||||
enum session_dir dir = identify_direction_by_port(ntohs(key->src_port), ntohs(key->dst_port));
|
||||
enum session_state next_state = session_transition_run(SESSION_STATE_INIT, UDP_DATA);
|
||||
session_transition_log(sess, SESSION_STATE_INIT, next_state, UDP_DATA);
|
||||
session_update(sess, next_state, pkt, key, dir, now);
|
||||
session_transition_log(sess, SESSION_STATE_INIT, next_state, UDP_DATA);
|
||||
session_stat_inc(&mgr->stat.udp_sess, next_state);
|
||||
|
||||
timer_update(mgr->sess_timer, sess, now + opts->udp_timeout_data);
|
||||
@@ -564,10 +595,22 @@ static int session_manager_update_tcp_session(struct session_manager *mgr, struc
|
||||
inputs |= tcp_layer->pld_len ? TCP_DATA : NONE;
|
||||
enum session_state curr_state = session_get_state(sess);
|
||||
enum session_state next_state = session_transition_run(curr_state, inputs);
|
||||
session_transition_log(sess, curr_state, next_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);
|
||||
|
||||
if (tcp_hdr_get_syn_flag(hdr))
|
||||
{
|
||||
tcp_reassembly_init(dir == SESSION_DIR_C2S ? sess->c2s_reassembly : sess->s2c_reassembly, tcp_hdr_get_seq(hdr));
|
||||
}
|
||||
tcp_reassembly_expire(sess->c2s_reassembly, now);
|
||||
tcp_reassembly_expire(sess->s2c_reassembly, now);
|
||||
if (tcp_layer->pld_len)
|
||||
{
|
||||
tcp_reassembly_insert(dir == SESSION_DIR_C2S ? sess->c2s_reassembly : sess->s2c_reassembly,
|
||||
tcp_hdr_get_seq(hdr), tcp_layer->pld_ptr, tcp_layer->pld_len, now);
|
||||
}
|
||||
|
||||
// select next timeout
|
||||
uint64_t timeout = 0;
|
||||
switch (next_state)
|
||||
@@ -616,8 +659,8 @@ static int session_manager_update_udp_session(struct session_manager *mgr, struc
|
||||
enum session_dir dir = identify_direction_by_history(sess, key);
|
||||
enum session_state curr_state = session_get_state(sess);
|
||||
enum session_state next_state = session_transition_run(curr_state, UDP_DATA);
|
||||
session_transition_log(sess, curr_state, next_state, UDP_DATA);
|
||||
session_update(sess, next_state, pkt, key, dir, now);
|
||||
session_transition_log(sess, curr_state, next_state, UDP_DATA);
|
||||
session_stat_update(mgr, sess, curr_state, next_state);
|
||||
timer_update(mgr->sess_timer, sess, now + opts->udp_timeout_data);
|
||||
|
||||
@@ -653,6 +696,13 @@ struct session_manager *session_manager_new(struct session_manager_options *opts
|
||||
.timeout_sec = opts->evicted_session_filter_timeout,
|
||||
.error_rate = opts->evicted_session_filter_error_rate,
|
||||
};
|
||||
tcp_reassembly_opts = {
|
||||
.enable = opts->tcp_reassembly_enable,
|
||||
.max_timeout = opts->tcp_reassembly_max_timeout,
|
||||
.max_segments = opts->tcp_reassembly_max_segments,
|
||||
.max_bytes = opts->tcp_reassembly_max_bytes,
|
||||
};
|
||||
|
||||
mgr->sess_pool = session_pool_new(opts->max_tcp_session_num + opts->max_udp_session_num);
|
||||
mgr->tcp_sess_table = session_table_new();
|
||||
mgr->udp_sess_table = session_table_new();
|
||||
@@ -738,6 +788,8 @@ void session_manager_free_session(struct session_manager *mgr, struct session *s
|
||||
switch (session_get_type(sess))
|
||||
{
|
||||
case SESSION_TYPE_TCP:
|
||||
tcp_reassembly_free(sess->c2s_reassembly);
|
||||
tcp_reassembly_free(sess->s2c_reassembly);
|
||||
session_table_del(mgr->tcp_sess_table, session_get0_key(sess));
|
||||
session_stat_dec(&mgr->stat.tcp_sess, session_get_state(sess));
|
||||
mgr->stat.tcp_sess.nr_sess_used--;
|
||||
@@ -754,7 +806,9 @@ void session_manager_free_session(struct session_manager *mgr, struct session *s
|
||||
|
||||
session_set0_cur_pkt(sess, NULL);
|
||||
session_set_cur_dir(sess, SESSION_DIR_NONE);
|
||||
session_clean(sess);
|
||||
packet_free(sess->c2s_1st_pkt);
|
||||
packet_free(sess->s2c_1st_pkt);
|
||||
session_free_all_ex_data(sess);
|
||||
session_pool_push(mgr->sess_pool, sess);
|
||||
sess = NULL;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,12 @@ struct session_manager_options
|
||||
uint32_t evicted_session_filter_capacity;
|
||||
uint32_t evicted_session_filter_timeout; // ms, Range: 1-60,000
|
||||
double evicted_session_filter_error_rate;
|
||||
|
||||
// TCP reassembly
|
||||
uint8_t tcp_reassembly_enable;
|
||||
uint32_t tcp_reassembly_max_timeout; // ms, Range: 1-60,000
|
||||
uint32_t tcp_reassembly_max_segments; // 0: unlimited
|
||||
uint32_t tcp_reassembly_max_bytes; // 0: unlimited
|
||||
};
|
||||
|
||||
struct session_stat
|
||||
|
||||
@@ -13,8 +13,9 @@ extern "C"
|
||||
#include "timeout.h"
|
||||
#include "uthash.h"
|
||||
#include "session.h"
|
||||
#include "tcp_reassembly.h"
|
||||
|
||||
#define EX_DATA_MAX_COUNT 128
|
||||
#define EX_DATA_MAX_COUNT 16
|
||||
|
||||
struct session
|
||||
{
|
||||
@@ -50,6 +51,13 @@ struct session
|
||||
// session user data
|
||||
void *user_data;
|
||||
|
||||
/******************************
|
||||
* Session TCP Reassembly
|
||||
******************************/
|
||||
|
||||
struct tcp_reassembly *c2s_reassembly;
|
||||
struct tcp_reassembly *s2c_reassembly;
|
||||
|
||||
/******************************
|
||||
* Session Current Packet
|
||||
******************************/
|
||||
|
||||
@@ -90,6 +90,13 @@ target_link_libraries(gtest_overload_evict_udp_sess session_manager gtest)
|
||||
add_executable(gtest_session_transition gtest_session_transition.cpp)
|
||||
target_link_libraries(gtest_session_transition session_manager gtest)
|
||||
|
||||
###############################################################################
|
||||
# gtest tcp reassembly
|
||||
###############################################################################
|
||||
|
||||
add_executable(gtest_sess_mgr_tcp_reassembly gtest_sess_mgr_tcp_reassembly.cpp)
|
||||
target_link_libraries(gtest_sess_mgr_tcp_reassembly session_manager gtest)
|
||||
|
||||
###############################################################################
|
||||
# gtest
|
||||
###############################################################################
|
||||
@@ -121,3 +128,5 @@ gtest_discover_tests(gtest_overload_evict_tcp_sess)
|
||||
gtest_discover_tests(gtest_overload_evict_udp_sess)
|
||||
|
||||
gtest_discover_tests(gtest_session_transition)
|
||||
|
||||
gtest_discover_tests(gtest_sess_mgr_tcp_reassembly)
|
||||
@@ -37,6 +37,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
static void packet_set_ip_id(struct packet *pkt, uint16_t ip_id)
|
||||
|
||||
@@ -39,6 +39,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
static void packet_set_tcp_src_addr(struct packet *pkt, uint32_t addr)
|
||||
|
||||
@@ -39,6 +39,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
static void packet_set_tcp_src_addr(struct packet *pkt, uint32_t addr)
|
||||
|
||||
349
src/session/test/gtest_sess_mgr_tcp_reassembly.cpp
Normal file
349
src/session/test/gtest_sess_mgr_tcp_reassembly.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "session.h"
|
||||
#include "session_manager.h"
|
||||
|
||||
#include "ipv4_utils.h"
|
||||
#include "test_packets.h"
|
||||
|
||||
struct session_manager_options opts = {
|
||||
// max session number
|
||||
.max_tcp_session_num = 256,
|
||||
.max_udp_session_num = 256,
|
||||
|
||||
// session overload
|
||||
.tcp_overload_evict_old_sess = 1, // 1: evict old session, 0: bypass new session
|
||||
.udp_overload_evict_old_sess = 1, // 1: evict old session, 0: bypass new session
|
||||
|
||||
// tcp timeout
|
||||
.tcp_timeout_init = 1,
|
||||
.tcp_timeout_handshake = 2,
|
||||
.tcp_timeout_data = 3,
|
||||
.tcp_timeout_half_closed = 4,
|
||||
.tcp_timeout_time_wait = 5,
|
||||
.tcp_timeout_discard = 6,
|
||||
|
||||
// udp timeout
|
||||
.udp_timeout_data = 7,
|
||||
|
||||
// duplicate packet filter
|
||||
.duplicated_packet_filter_enable = 1,
|
||||
.duplicated_packet_filter_capacity = 1000,
|
||||
.duplicated_packet_filter_timeout = 10,
|
||||
.duplicated_packet_filter_error_rate = 0.0001,
|
||||
|
||||
// evicted session filter
|
||||
.evicted_session_filter_enable = 1,
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
static void hex_dump(const char *payload, uint32_t len)
|
||||
{
|
||||
printf("Payload Length: %d\n", len);
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
{
|
||||
if (i > 0 && i % 16 == 0)
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
printf("%02x ", (uint8_t)payload[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#if 1
|
||||
TEST(SESS_MGR_TCP_REASSEMBLY, OUT_OF_ORDER)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
const char *payload = NULL;
|
||||
struct packet pkt;
|
||||
struct session *sess = NULL;
|
||||
struct session_manager *mgr = NULL;
|
||||
|
||||
mgr = session_manager_new(&opts, 1);
|
||||
EXPECT_TRUE(mgr != NULL);
|
||||
|
||||
// C2S SYN Packet
|
||||
printf("\n=> Packet Parse: TCP C2S SYN packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_out_of_order_pkt1, sizeof(tcp_out_of_order_pkt1));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
EXPECT_TRUE(session_manager_lookup_session(mgr, &pkt) == NULL);
|
||||
// new session
|
||||
sess = session_manager_new_session(mgr, &pkt, 1);
|
||||
EXPECT_TRUE(sess);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload == NULL);
|
||||
EXPECT_TRUE(len == 0);
|
||||
|
||||
// C2S ACK Packet
|
||||
printf("\n=> Packet Parse: TCP C2S ACK packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_out_of_order_pkt2, sizeof(tcp_out_of_order_pkt2));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
sess = session_manager_lookup_session(mgr, &pkt);
|
||||
EXPECT_TRUE(sess);
|
||||
// update session
|
||||
EXPECT_TRUE(session_manager_update_session(mgr, sess, &pkt, 2) == 0);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload == NULL);
|
||||
EXPECT_TRUE(len == 0);
|
||||
|
||||
// C2S Data Packet 2222
|
||||
printf("\n=> Packet Parse: TCP C2S Data packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_out_of_order_pkt3, sizeof(tcp_out_of_order_pkt3));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
sess = session_manager_lookup_session(mgr, &pkt);
|
||||
EXPECT_TRUE(sess);
|
||||
// update session
|
||||
EXPECT_TRUE(session_manager_update_session(mgr, sess, &pkt, 3) == 0);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload == NULL);
|
||||
EXPECT_TRUE(len == 0);
|
||||
|
||||
// C2S Data Packet 3333
|
||||
printf("\n=> Packet Parse: TCP C2S Data packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_out_of_order_pkt4, sizeof(tcp_out_of_order_pkt4));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
sess = session_manager_lookup_session(mgr, &pkt);
|
||||
EXPECT_TRUE(sess);
|
||||
// update session
|
||||
EXPECT_TRUE(session_manager_update_session(mgr, sess, &pkt, 4) == 0);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload == NULL);
|
||||
EXPECT_TRUE(len == 0);
|
||||
|
||||
// C2S Data Packet 4444
|
||||
printf("\n=> Packet Parse: TCP C2S Data packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_out_of_order_pkt5, sizeof(tcp_out_of_order_pkt5));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
sess = session_manager_lookup_session(mgr, &pkt);
|
||||
EXPECT_TRUE(sess);
|
||||
// update session
|
||||
EXPECT_TRUE(session_manager_update_session(mgr, sess, &pkt, 5) == 0);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload == NULL);
|
||||
EXPECT_TRUE(len == 0);
|
||||
|
||||
// C2S Data Packet 5555
|
||||
printf("\n=> Packet Parse: TCP C2S Data packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_out_of_order_pkt6, sizeof(tcp_out_of_order_pkt6));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
sess = session_manager_lookup_session(mgr, &pkt);
|
||||
EXPECT_TRUE(sess);
|
||||
// update session
|
||||
EXPECT_TRUE(session_manager_update_session(mgr, sess, &pkt, 6) == 0);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload == NULL);
|
||||
EXPECT_TRUE(len == 0);
|
||||
|
||||
// C2S Data Packet 1111
|
||||
printf("\n=> Packet Parse: TCP C2S Data packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_out_of_order_pkt7, sizeof(tcp_out_of_order_pkt7));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
sess = session_manager_lookup_session(mgr, &pkt);
|
||||
EXPECT_TRUE(sess);
|
||||
// update session
|
||||
EXPECT_TRUE(session_manager_update_session(mgr, sess, &pkt, 7) == 0);
|
||||
|
||||
/*
|
||||
* 11111111111111111111111111111111111111111111111111111111111111
|
||||
* 22222222222222222222222222222222222222222222222222222222222222
|
||||
* 33333333333333333333333333333333333333333333333333333333333333
|
||||
* 44444444444444444444444444444444444444444444444444444444444444
|
||||
* 55555555555555555555555555555555555555555555555555555555555555
|
||||
*/
|
||||
|
||||
unsigned char payload1[] = {
|
||||
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
|
||||
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
|
||||
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x0a};
|
||||
unsigned char payload2[] = {
|
||||
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
|
||||
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
|
||||
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x0a};
|
||||
unsigned char payload3[] = {
|
||||
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x0a};
|
||||
unsigned char payload4[] = {
|
||||
0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
|
||||
0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
|
||||
0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x0a};
|
||||
unsigned char payload5[] = {
|
||||
0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
|
||||
0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
|
||||
0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x0a};
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload != NULL);
|
||||
EXPECT_TRUE(len == sizeof(payload1));
|
||||
EXPECT_TRUE(memcmp((void *)payload, payload1, sizeof(payload1)) == 0);
|
||||
hex_dump(payload, len);
|
||||
session_consume_tcp_payload(sess, len);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload != NULL);
|
||||
EXPECT_TRUE(len == sizeof(payload2));
|
||||
EXPECT_TRUE(memcmp((void *)payload, payload2, sizeof(payload2)) == 0);
|
||||
hex_dump(payload, len);
|
||||
session_consume_tcp_payload(sess, len);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload != NULL);
|
||||
EXPECT_TRUE(len == sizeof(payload3));
|
||||
EXPECT_TRUE(memcmp((void *)payload, payload3, sizeof(payload3)) == 0);
|
||||
hex_dump(payload, len);
|
||||
session_consume_tcp_payload(sess, len);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload != NULL);
|
||||
EXPECT_TRUE(len == sizeof(payload4));
|
||||
EXPECT_TRUE(memcmp((void *)payload, payload4, sizeof(payload4)) == 0);
|
||||
hex_dump(payload, len);
|
||||
session_consume_tcp_payload(sess, len);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload != NULL);
|
||||
EXPECT_TRUE(len == sizeof(payload5));
|
||||
EXPECT_TRUE(memcmp((void *)payload, payload5, sizeof(payload5)) == 0);
|
||||
hex_dump(payload, len);
|
||||
session_consume_tcp_payload(sess, len);
|
||||
|
||||
// expire session
|
||||
EXPECT_TRUE(session_manager_get_expired_session(mgr, 7 + opts.tcp_timeout_data) == NULL); // active -> closing
|
||||
sess = session_manager_get_expired_session(mgr, 7 + opts.tcp_timeout_data + opts.tcp_timeout_time_wait); // closing -> closed
|
||||
EXPECT_TRUE(sess);
|
||||
EXPECT_TRUE(session_get_state(sess) == SESSION_STATE_CLOSED);
|
||||
EXPECT_TRUE(session_get_closing_reason(sess) == CLOSING_BY_TIMEOUT);
|
||||
session_dump(sess);
|
||||
// free session
|
||||
session_manager_free_session(mgr, sess);
|
||||
|
||||
session_manager_free(mgr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
TEST(SESS_MGR_TCP_REASSEMBLY, SEQ_WRAPAROUND)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
const char *payload = NULL;
|
||||
struct packet pkt;
|
||||
struct session *sess = NULL;
|
||||
struct session_manager *mgr = NULL;
|
||||
|
||||
mgr = session_manager_new(&opts, 1);
|
||||
EXPECT_TRUE(mgr != NULL);
|
||||
|
||||
// C2S SYN Packet
|
||||
printf("\n=> Packet Parse: TCP C2S SYN packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_seq_wraparound_pkt1, sizeof(tcp_seq_wraparound_pkt1));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
EXPECT_TRUE(session_manager_lookup_session(mgr, &pkt) == NULL);
|
||||
// new session
|
||||
sess = session_manager_new_session(mgr, &pkt, 1);
|
||||
EXPECT_TRUE(sess);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload == NULL);
|
||||
EXPECT_TRUE(len == 0);
|
||||
|
||||
// C2S ACK Packet
|
||||
printf("\n=> Packet Parse: TCP C2S ACK packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_seq_wraparound_pkt2, sizeof(tcp_seq_wraparound_pkt2));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
sess = session_manager_lookup_session(mgr, &pkt);
|
||||
EXPECT_TRUE(sess);
|
||||
// update session
|
||||
EXPECT_TRUE(session_manager_update_session(mgr, sess, &pkt, 2) == 0);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload == NULL);
|
||||
EXPECT_TRUE(len == 0);
|
||||
|
||||
// C2S Data Packet
|
||||
printf("\n=> Packet Parse: TCP C2S Data packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_seq_wraparound_pkt3, sizeof(tcp_seq_wraparound_pkt3));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
sess = session_manager_lookup_session(mgr, &pkt);
|
||||
EXPECT_TRUE(sess);
|
||||
// update session
|
||||
EXPECT_TRUE(session_manager_update_session(mgr, sess, &pkt, 3) == 0);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload != NULL);
|
||||
EXPECT_TRUE(len == sizeof(tcp_seq_wraparound_pkt3_payload));
|
||||
EXPECT_TRUE(memcmp((void *)payload, tcp_seq_wraparound_pkt3_payload, sizeof(tcp_seq_wraparound_pkt3_payload)) == 0);
|
||||
hex_dump(payload, len);
|
||||
session_consume_tcp_payload(sess, len);
|
||||
|
||||
// C2S Data Packet
|
||||
printf("\n=> Packet Parse: TCP C2S Data packet\n");
|
||||
packet_parse(&pkt, (const char *)tcp_seq_wraparound_pkt4, sizeof(tcp_seq_wraparound_pkt4));
|
||||
printf("<= Packet Parse: done\n\n");
|
||||
|
||||
// lookup session
|
||||
sess = session_manager_lookup_session(mgr, &pkt);
|
||||
EXPECT_TRUE(sess);
|
||||
// update session
|
||||
EXPECT_TRUE(session_manager_update_session(mgr, sess, &pkt, 4) == 0);
|
||||
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
EXPECT_TRUE(payload != NULL);
|
||||
EXPECT_TRUE(len == sizeof(tcp_seq_wraparound_pkt4_payload));
|
||||
EXPECT_TRUE(memcmp((void *)payload, tcp_seq_wraparound_pkt4_payload, sizeof(tcp_seq_wraparound_pkt4_payload)) == 0);
|
||||
hex_dump(payload, len);
|
||||
session_consume_tcp_payload(sess, len);
|
||||
|
||||
// expire session
|
||||
EXPECT_TRUE(session_manager_get_expired_session(mgr, 4 + opts.tcp_timeout_data) == NULL); // active -> closing
|
||||
sess = session_manager_get_expired_session(mgr, 4 + opts.tcp_timeout_data + opts.tcp_timeout_time_wait); // closing -> closed
|
||||
EXPECT_TRUE(sess);
|
||||
EXPECT_TRUE(session_get_state(sess) == SESSION_STATE_CLOSED);
|
||||
EXPECT_TRUE(session_get_closing_reason(sess) == CLOSING_BY_TIMEOUT);
|
||||
session_dump(sess);
|
||||
// free session
|
||||
session_manager_free_session(mgr, sess);
|
||||
|
||||
session_manager_free(mgr);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -38,6 +38,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
static void build_active_tcp_session(struct session_manager *mgr, struct session *sess)
|
||||
|
||||
@@ -38,6 +38,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -37,6 +37,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
#if 1
|
||||
|
||||
@@ -37,6 +37,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -38,6 +38,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -37,6 +37,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
#if 1
|
||||
|
||||
@@ -37,6 +37,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -36,6 +36,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
#if 1
|
||||
|
||||
@@ -37,6 +37,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
#if 1
|
||||
|
||||
@@ -37,6 +37,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
#if 1
|
||||
|
||||
@@ -36,6 +36,12 @@ struct session_manager_options opts = {
|
||||
.evicted_session_filter_capacity = 1000,
|
||||
.evicted_session_filter_timeout = 10,
|
||||
.evicted_session_filter_error_rate = 0.0001,
|
||||
|
||||
// TCP Reassembly
|
||||
.tcp_reassembly_enable = 1,
|
||||
.tcp_reassembly_max_timeout = 60000,
|
||||
.tcp_reassembly_max_segments = 0,
|
||||
.tcp_reassembly_max_bytes = 0,
|
||||
};
|
||||
|
||||
#if 1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,20 @@ struct session_manager_options *sess_mgr_opts = &stellar_context.config.sess_mgr
|
||||
static const char *log_config_file = "./conf/log.toml";
|
||||
static const char *stellar_config_file = "./conf/stellar.toml";
|
||||
|
||||
// TODO
|
||||
static void hex_dump(const char *payload, uint32_t len)
|
||||
{
|
||||
printf("Payload Length: %d\n", len);
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
{
|
||||
if (i > 0 && i % 16 == 0)
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
printf("%02x ", (uint8_t)payload[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void *plugin_manager_new_ctx()
|
||||
{
|
||||
return NULL;
|
||||
@@ -74,8 +87,22 @@ void plugin_manager_dispatch(void *plugin_mgr, struct session *sess, const struc
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t len = 0;
|
||||
const char *payload = NULL;
|
||||
|
||||
printf("=> plugin dispatch session: %p\n", sess);
|
||||
session_dump(sess);
|
||||
|
||||
if (session_get_type(sess) == SESSION_TYPE_TCP)
|
||||
{
|
||||
payload = session_peek_tcp_payload(sess, &len);
|
||||
if (payload && len > 0)
|
||||
{
|
||||
hex_dump(payload, len);
|
||||
}
|
||||
session_consume_tcp_payload(sess, len);
|
||||
}
|
||||
|
||||
printf("<= plugin dispatch session\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ void tcp_reassembly_init(struct tcp_reassembly *assy, uint32_t syn_seq)
|
||||
}
|
||||
|
||||
assy->exp_seq = syn_seq + 1;
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p init expect seq %lu", assy, assy->exp_seq);
|
||||
}
|
||||
|
||||
void tcp_reassembly_expire(struct tcp_reassembly *assy, uint64_t now)
|
||||
@@ -189,7 +190,7 @@ void tcp_reassembly_expire(struct tcp_reassembly *assy, uint64_t now)
|
||||
};
|
||||
assy->stat.timeout_discard_segments++;
|
||||
assy->stat.timeout_discard_bytes += seg->len;
|
||||
TCP_REASSEMBLE_DEBUG("expire %p [%lu, %lu] (time: %lu, now: %lu)", seg, seg->offset, high, seg->time, now);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p expire segment %p [%lu, %lu] (time: %lu, now: %lu)", assy, seg, seg->offset, high, seg->time, now);
|
||||
|
||||
itree_remove(assy->itree, &expire);
|
||||
}
|
||||
@@ -214,7 +215,7 @@ void tcp_reassembly_insert(struct tcp_reassembly *assy, uint32_t offset, const c
|
||||
{
|
||||
assy->stat.overload_bypass_segments++;
|
||||
assy->stat.overload_bypass_bytes += len;
|
||||
TCP_REASSEMBLE_DEBUG("insert [%lu, %lu] failed, reach max packets %u", low, high, assy->opts.max_segments);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p insert [%lu, %lu] failed, reach max packets %u", assy, low, high, assy->opts.max_segments);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -222,7 +223,7 @@ void tcp_reassembly_insert(struct tcp_reassembly *assy, uint32_t offset, const c
|
||||
{
|
||||
assy->stat.overload_bypass_segments++;
|
||||
assy->stat.overload_bypass_bytes += len;
|
||||
TCP_REASSEMBLE_DEBUG("insert [%lu, %lu] failed, reach max bytes %u", low, high, assy->opts.max_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p insert [%lu, %lu] failed, reach max bytes %u", assy, low, high, assy->opts.max_bytes);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -230,7 +231,7 @@ void tcp_reassembly_insert(struct tcp_reassembly *assy, uint32_t offset, const c
|
||||
{
|
||||
assy->stat.retrans_bypass_segments++;
|
||||
assy->stat.retrans_bypass_bytes += len;
|
||||
TCP_REASSEMBLE_DEBUG("insert [%lu, %lu] failed, less the expect seq %lu", low, high, assy->exp_seq);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p insert [%lu, %lu] failed, less the expect seq %lu", assy, low, high, assy->exp_seq);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,7 +258,7 @@ void tcp_reassembly_insert(struct tcp_reassembly *assy, uint32_t offset, const c
|
||||
free(seg);
|
||||
return;
|
||||
}
|
||||
TCP_REASSEMBLE_DEBUG("insert %p [%lu, %lu]", seg, insert.low, insert.high);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p insert segment %p [%lu, %lu]", assy, seg, insert.low, insert.high);
|
||||
|
||||
segment_list_add(&assy->list, seg);
|
||||
|
||||
@@ -327,10 +328,10 @@ const char *tcp_reassembly_peek(struct tcp_reassembly *assy, uint32_t *len)
|
||||
{
|
||||
overlap = assy->exp_seq - seg->offset;
|
||||
*len = seg->len - overlap;
|
||||
TCP_REASSEMBLE_DEBUG("peek [%lu, +∞], found %p [%lu, %lu] (left overlap: %lu)", assy->exp_seq, seg, oldest->low, oldest->high, overlap);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p peek [%lu, +∞], found segment %p [%lu, %lu] (left overlap: %lu)", assy, assy->exp_seq, seg, oldest->low, oldest->high, overlap);
|
||||
return seg->payload + overlap;
|
||||
}
|
||||
TCP_REASSEMBLE_DEBUG("peek [%lu, +∞], found %p [%lu, %lu]", assy->exp_seq, seg, oldest->low, oldest->high);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p peek [%lu, +∞], found segment %p [%lu, %lu]", assy, assy->exp_seq, seg, oldest->low, oldest->high);
|
||||
|
||||
*len = seg->len;
|
||||
return seg->payload;
|
||||
@@ -357,15 +358,33 @@ void tcp_reassembly_consume(struct tcp_reassembly *assy, uint32_t len)
|
||||
ilisttrav_t *trav = NULL;
|
||||
struct segment *seg = NULL;
|
||||
|
||||
/*
|
||||
* https://www.ietf.org/rfc/rfc0793.txt
|
||||
*
|
||||
* This space ranges from 0 to 2**32 - 1.
|
||||
* Since the space is finite, all arithmetic dealing with sequence
|
||||
* numbers must be performed modulo 2**32. This unsigned arithmetic
|
||||
* preserves the relationship of sequence numbers as they cycle from
|
||||
* 2**32 - 1 to 0 again. There are some subtleties to computer modulo
|
||||
* arithmetic, so great care should be taken in programming the
|
||||
* comparison of such values. The symbol "=<" means "less than or equal"
|
||||
* (modulo 2**32).
|
||||
*
|
||||
* UINT32_MAX = 4294967295
|
||||
* 2^32 = 4294967296
|
||||
* 2^32 - 1 = 4294967295
|
||||
* seq range: [0, 4294967295]
|
||||
* seq range: [0, UINT32_MAX]
|
||||
*/
|
||||
old_exp_seq = assy->exp_seq;
|
||||
assy->exp_seq += len;
|
||||
if (assy->exp_seq > UINT32_MAX)
|
||||
{
|
||||
assy->exp_seq = assy->exp_seq % UINT32_MAX;
|
||||
assy->exp_seq = assy->exp_seq % 4294967296;
|
||||
}
|
||||
new_exp_seq = assy->exp_seq;
|
||||
|
||||
TCP_REASSEMBLE_DEBUG("consume [%lu, %lu], update expect seq %lu -> %lu", old_exp_seq, old_exp_seq + len - 1, old_exp_seq, new_exp_seq);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p consume [%lu, %lu], update expect seq %lu -> %lu", assy, old_exp_seq, old_exp_seq + len - 1, old_exp_seq, new_exp_seq);
|
||||
consume =
|
||||
{
|
||||
.low = old_exp_seq,
|
||||
@@ -397,7 +416,7 @@ void tcp_reassembly_consume(struct tcp_reassembly *assy, uint32_t len)
|
||||
seg = (struct segment *)del->data;
|
||||
assy->stat.remove_segments++;
|
||||
assy->stat.remove_bytes += seg->len;
|
||||
TCP_REASSEMBLE_DEBUG("consume [%lu, %lu], delete %p [%lu, %lu]", old_exp_seq, old_exp_seq + len - 1, seg, del->low, del->high);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p consume [%lu, %lu], delete segment %p [%lu, %lu]", assy, old_exp_seq, old_exp_seq + len - 1, seg, del->low, del->high);
|
||||
itree_remove(assy->itree, del);
|
||||
}
|
||||
}
|
||||
@@ -422,11 +441,11 @@ void tcp_reassembly_print_stat(struct tcp_reassembly *assy)
|
||||
return;
|
||||
}
|
||||
|
||||
TCP_REASSEMBLE_DEBUG("current : segments %lu, bytes %lu", assy->stat.curr_segments, assy->stat.curr_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("insert : segments %lu, bytes %lu", assy->stat.insert_segments, assy->stat.insert_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("remove : segments %lu, bytes %lu", assy->stat.remove_segments, assy->stat.remove_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("consume : segments %lu, bytes %lu", assy->stat.consume_segments, assy->stat.consume_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("retrans bypass : segments %lu, bytes %lu", assy->stat.retrans_bypass_segments, assy->stat.retrans_bypass_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("overload bypass : segments %lu, bytes %lu", assy->stat.overload_bypass_segments, assy->stat.overload_bypass_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("timeout discard : segments %lu, bytes %lu", assy->stat.timeout_discard_segments, assy->stat.timeout_discard_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p current : segments %lu, bytes %lu", assy, assy->stat.curr_segments, assy->stat.curr_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p insert : segments %lu, bytes %lu", assy, assy->stat.insert_segments, assy->stat.insert_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p remove : segments %lu, bytes %lu", assy, assy->stat.remove_segments, assy->stat.remove_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p consume : segments %lu, bytes %lu", assy, assy->stat.consume_segments, assy->stat.consume_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p retrans bypass : segments %lu, bytes %lu", assy, assy->stat.retrans_bypass_segments, assy->stat.retrans_bypass_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p overload bypass : segments %lu, bytes %lu", assy, assy->stat.overload_bypass_segments, assy->stat.overload_bypass_bytes);
|
||||
TCP_REASSEMBLE_DEBUG("reassembler %p timeout discard : segments %lu, bytes %lu", assy, assy->stat.timeout_discard_segments, assy->stat.timeout_discard_bytes);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ extern "C"
|
||||
|
||||
struct tcp_reassembly_options
|
||||
{
|
||||
bool enable;
|
||||
uint8_t enable;
|
||||
uint32_t max_timeout;
|
||||
uint32_t max_segments;
|
||||
uint32_t max_bytes;
|
||||
|
||||
@@ -29,40 +29,6 @@ static void tcp_reassembly_check_stat(struct tcp_reassembly *assy,
|
||||
EXPECT_TRUE(stat->timeout_discard_bytes == timeout_discard_bytes);
|
||||
}
|
||||
|
||||
#if 0
|
||||
const char *session_peek_tcp_payload(struct session *session, uint32_t *len)
|
||||
{
|
||||
struct tcp_reassembly *assy;
|
||||
struct session_dir *dir = session_get_cur_dir(session);
|
||||
|
||||
if (dir == SESSION_DIR_C2S)
|
||||
{
|
||||
assy = session_get_tcp_c2s_reassembly(session);
|
||||
}
|
||||
else
|
||||
{
|
||||
assy = session_get_tcp_s2c_reassembly(session);
|
||||
}
|
||||
return tcp_reassembly_peek(assy, len);
|
||||
}
|
||||
|
||||
void session_consume_tcp_payload(struct session *session, uint32_t len)
|
||||
{
|
||||
struct tcp_reassembly *assy;
|
||||
struct session_dir *dir = session_get_cur_dir(session);
|
||||
|
||||
if (dir == SESSION_DIR_C2S)
|
||||
{
|
||||
assy = session_get_tcp_c2s_reassembly(session);
|
||||
}
|
||||
else
|
||||
{
|
||||
assy = session_get_tcp_s2c_reassembly(session);
|
||||
}
|
||||
tcp_reassembly_consume(assy, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
TEST(TCP_REASSEMBLY, TEST)
|
||||
{
|
||||
@@ -286,8 +252,6 @@ TEST(TCP_REASSEMBLY, REPEAT2)
|
||||
* +---> 90 +---> 100 +---> 109
|
||||
*/
|
||||
|
||||
// C2S
|
||||
|
||||
tcp_reassembly_insert(assy, 90, (const char *)"0123456789", 10, 0);
|
||||
tcp_reassembly_check_stat(assy,
|
||||
1, 10, // curr_segments, curr_bytes
|
||||
@@ -476,6 +440,7 @@ TEST(TCP_REASSEMBLY, SEQ_WRAPAROUND)
|
||||
.max_segments = 16,
|
||||
.max_bytes = 1500};
|
||||
|
||||
// UINT32_MAX = 4294967295
|
||||
printf("UINT32_MAX = %u\n", UINT32_MAX);
|
||||
|
||||
assy = tcp_reassembly_new(&opts);
|
||||
@@ -502,9 +467,9 @@ TEST(TCP_REASSEMBLY, SEQ_WRAPAROUND)
|
||||
* | | | |A|B|C|D|E|F|G|H|I|J|
|
||||
* | | | +-+-+-+-+-+-+-+-+-+-+
|
||||
* | | | | | |
|
||||
* | | | | | +---> UINT32_MAX + 11
|
||||
* | | | | +---> UINT32_MAX + 5
|
||||
* | | | +---> UINT32_MAX + 2
|
||||
* | | | | | +---> 10
|
||||
* | | | | +---> 4
|
||||
* | | | +---> 1
|
||||
* | | +---> UINT32_MAX - 1
|
||||
* | +---> UINT32_MAX - 4
|
||||
* +---> UINT32_MAX - 10
|
||||
@@ -532,7 +497,7 @@ TEST(TCP_REASSEMBLY, SEQ_WRAPAROUND)
|
||||
0, 0, // retrans_bypass_segments, retrans_bypass_bytes
|
||||
0, 0, // overload_bypass_segments, overload_bypass_bytes
|
||||
0, 0); // timeout_discard_segments, timeout_discard_bytes
|
||||
tcp_reassembly_insert(assy, 2, (const char *)"ABCDEFGHIJ", 10, 0);
|
||||
tcp_reassembly_insert(assy, 1, (const char *)"ABCDEFGHIJ", 10, 0);
|
||||
tcp_reassembly_check_stat(assy,
|
||||
3, 30, // curr_segments, curr_bytes
|
||||
3, 30, // insert_segments, insert_bytes
|
||||
@@ -627,7 +592,6 @@ TEST(TCP_REASSEMBLY, MAX_TIMEOUT1)
|
||||
* +---> 90 +---> 100 +---> 109
|
||||
*/
|
||||
|
||||
// C2S
|
||||
tcp_reassembly_insert(assy, 90, (const char *)"0123456789", 10, 0);
|
||||
tcp_reassembly_check_stat(assy,
|
||||
1, 10, // curr_segments, curr_bytes
|
||||
@@ -828,7 +792,6 @@ TEST(TCP_REASSEMBLY, MAX_PACKETS)
|
||||
* +---> 90 +---> 100 +---> 110
|
||||
*/
|
||||
|
||||
// C2S
|
||||
tcp_reassembly_insert(assy, 90, (const char *)"0123456789", 10, 0);
|
||||
tcp_reassembly_check_stat(assy,
|
||||
1, 10, // curr_segments, curr_bytes
|
||||
@@ -917,7 +880,6 @@ TEST(TCP_REASSEMBLY, MAX_BYTES)
|
||||
* +---> 90 +---> 100 +---> 110
|
||||
*/
|
||||
|
||||
// C2S
|
||||
tcp_reassembly_insert(assy, 90, (const char *)"0123456789", 10, 0);
|
||||
tcp_reassembly_check_stat(assy,
|
||||
1, 10, // curr_segments, curr_bytes
|
||||
|
||||
Reference in New Issue
Block a user