diff --git a/conf/stellar.toml b/conf/stellar.toml index ef9cb0c..360e6fe 100644 --- a/conf/stellar.toml +++ b/conf/stellar.toml @@ -15,10 +15,13 @@ cpu_mask = [5, 6, 7, 8, 9, 10, 11, 12] [ip_reassembly] enable = 1 -timeout = 10000 # range: [1, 60000] (ms) bucket_entries = 32 # range: [1, 4294967295] (must be power of 2) bucket_num = 1024 # range: [1, 4294967295] +ip_frag_timeout_ms = 10000 # range: [1, 60000] (ms) +ip_frag_expire_polling_interval_ms = 0 # range: [0, 60000] (ms) +ip_frag_expire_polling_limit = 1024 # range: [1, 1024] + [session_manager] # max session number max_tcp_session_num = 50000 @@ -62,10 +65,6 @@ tcp_reassembly_max_timeout_ms = 10000 # range: [1, 60000] (ms) tcp_reassembly_max_segments = 256 # range: [2, 4096] [schedule] -# Note: free_expired_ip_frag_interval determines the precision of ip_reassembly timeout -free_expired_ip_frag_interval = 50 # range: [1, 60000] (ms) -free_expired_ip_frag_batch = 1000 # range: [1, 60000] - merge_stat_interval = 500 # range: [1, 60000] (ms) output_stat_interval = 2000 # range: [1, 60000] (ms) diff --git a/infra/core/stellar_config.c b/infra/core/stellar_config.c index 47bded2..d1511fe 100644 --- a/infra/core/stellar_config.c +++ b/infra/core/stellar_config.c @@ -168,55 +168,6 @@ error_out: return ret; } -// return 0: success -// retuun -1: failed -static int parse_ip_reassembly_section(toml_table_t *root, struct ip_reassembly_options *opts) -{ - const char *ptr; - toml_table_t *table; - - table = toml_table_in(root, "ip_reassembly"); - if (table == NULL) - { - CONFIG_LOG_ERROR("config file missing ip_reassembly section"); - return -1; - } - - ptr = toml_raw_in(table, "enable"); - if (ptr == NULL) - { - CONFIG_LOG_ERROR("config file missing ip_reassembly->enable"); - return -1; - } - opts->enable = atoi(ptr); - - ptr = toml_raw_in(table, "timeout"); - if (ptr == NULL) - { - CONFIG_LOG_ERROR("config file missing ip_reassembly->timeout"); - return -1; - } - opts->timeout = atoi(ptr); - - ptr = toml_raw_in(table, "bucket_entries"); - if (ptr == NULL) - { - CONFIG_LOG_ERROR("config file missing ip_reassembly->bucket_entries"); - return -1; - } - opts->bucket_entries = atoi(ptr); - - ptr = toml_raw_in(table, "bucket_num"); - if (ptr == NULL) - { - CONFIG_LOG_ERROR("config file missing ip_reassembly->bucket_num"); - return -1; - } - opts->bucket_num = atoi(ptr); - - return 0; -} - // return 0: success // retuun -1: failed static int parse_schedule_options(toml_table_t *root, struct schedule_options *opts) @@ -231,32 +182,6 @@ static int parse_schedule_options(toml_table_t *root, struct schedule_options *o return -1; } - ptr = toml_raw_in(table, "free_expired_ip_frag_interval"); - if (ptr == NULL) - { - CONFIG_LOG_ERROR("config file missing schedule->free_expired_ip_frag_interval"); - return -1; - } - opts->free_expired_ip_frag_interval = atoll(ptr); - if (opts->free_expired_ip_frag_interval < 1 || opts->free_expired_ip_frag_interval > 60000) - { - CONFIG_LOG_ERROR("config file invalid schedule->free_expired_ip_frag_interval %ld, range [1, 60000]", opts->free_expired_ip_frag_interval); - return -1; - } - - ptr = toml_raw_in(table, "free_expired_ip_frag_batch"); - if (ptr == NULL) - { - CONFIG_LOG_ERROR("config file missing schedule->free_expired_ip_frag_batch"); - return -1; - } - opts->free_expired_ip_frag_batch = atoll(ptr); - if (opts->free_expired_ip_frag_batch < 1 || opts->free_expired_ip_frag_batch > 60000) - { - CONFIG_LOG_ERROR("config file invalid schedule->free_expired_ip_frag_batch %ld, range [1, 60000]", opts->free_expired_ip_frag_batch); - return -1; - } - ptr = toml_raw_in(table, "merge_stat_interval"); if (ptr == NULL) { @@ -332,11 +257,6 @@ int stellar_config_load(struct stellar_config *config, const char *file) goto error_out; } - if (parse_ip_reassembly_section(table, &config->ip_reass_opts) != 0) - { - goto error_out; - } - if (parse_schedule_options(table, &config->sched_opts) != 0) { goto error_out; @@ -367,7 +287,6 @@ void stellar_config_print(const struct stellar_config *config) const struct packet_io_options *pkt_io_opts = &config->pkt_io_opts; const struct snowflake_options *snowflake_opts = &config->snowflake_opts; - const struct ip_reassembly_options *ip_reass_opts = &config->ip_reass_opts; // snowflake config CONFIG_LOG_DEBUG("snowflake->snowflake_base : %d", snowflake_opts->snowflake_base); @@ -390,15 +309,7 @@ void stellar_config_print(const struct stellar_config *config) CONFIG_LOG_DEBUG("packet_io->cpu_mask[%3d] : %d", i, pkt_io_opts->cpu_mask[i]); } - // ip reassemble config - CONFIG_LOG_DEBUG("ip_reassembly->enable : %d", ip_reass_opts->enable); - CONFIG_LOG_DEBUG("ip_reassembly->timeout : %d", ip_reass_opts->timeout); - CONFIG_LOG_DEBUG("ip_reassembly->bucket_entries : %d", ip_reass_opts->bucket_entries); - CONFIG_LOG_DEBUG("ip_reassembly->bucket_num : %d", ip_reass_opts->bucket_num); - // schedule config - CONFIG_LOG_DEBUG("schedule->free_expired_ip_frag_interval : %ld", config->sched_opts.free_expired_ip_frag_interval); - CONFIG_LOG_DEBUG("schedule->free_expired_ip_frag_batch : %ld", config->sched_opts.free_expired_ip_frag_batch); CONFIG_LOG_DEBUG("schedule->merge_stat_interval : %ld", config->sched_opts.merge_stat_interval); CONFIG_LOG_DEBUG("schedule->output_stat_interval : %ld", config->sched_opts.output_stat_interval); CONFIG_LOG_DEBUG("schedule->packet_io_yield_interval : %ld", config->sched_opts.packet_io_yield_interval); diff --git a/infra/core/stellar_config.h b/infra/core/stellar_config.h index c91cd46..1e5f01e 100644 --- a/infra/core/stellar_config.h +++ b/infra/core/stellar_config.h @@ -6,14 +6,9 @@ extern "C" #endif #include "packet_io.h" -#include "ip_reassembly.h" struct schedule_options { - // Note: free_expired_ip_frag_interval determines the precision of ip_reassembly timeout - uint64_t free_expired_ip_frag_interval; // range: [1, 60000] (ms) - uint64_t free_expired_ip_frag_batch; // range: [1, 60000] - uint64_t merge_stat_interval; // range: [1, 60000] (ms) uint64_t output_stat_interval; // range: [1, 60000] (ms) @@ -30,7 +25,6 @@ struct stellar_config { struct packet_io_options pkt_io_opts; struct snowflake_options snowflake_opts; - struct ip_reassembly_options ip_reass_opts; struct schedule_options sched_opts; }; diff --git a/infra/core/stellar_core.c b/infra/core/stellar_core.c index e43abc4..83e9531 100644 --- a/infra/core/stellar_core.c +++ b/infra/core/stellar_core.c @@ -42,10 +42,9 @@ struct stellar_thread pthread_t tid; uint16_t idx; uint64_t is_runing; - uint64_t last_free_expired_ip_frag_timestamp; uint64_t last_merge_thread_stat_timestamp; struct snowflake *snowflake; - struct ip_reassembly *ip_mgr; + struct ip_reassembly *ip_reass; struct session_manager *sess_mgr; struct stellar *st; }; @@ -60,6 +59,7 @@ struct stellar_runtime struct plugin_manager_schema *plug_mgr; struct stellar_thread threads[MAX_THREAD_NUM]; struct session_manager_config *sess_mgr_cfg; + struct ip_reassembly_config *ip_reass_cfg; }; struct stellar @@ -130,7 +130,7 @@ static void *worker_thread(void *arg) struct packet packets[RX_BURST_MAX]; struct session *sess = NULL; struct stellar_thread *thread = (struct stellar_thread *)arg; - struct ip_reassembly *ip_reass = thread->ip_mgr; + struct ip_reassembly *ip_reass = thread->ip_reass; struct session_manager *sess_mgr = thread->sess_mgr; struct session_manager_stat *sess_stat = session_manager_stat(sess_mgr); struct stellar *st = thread->st; @@ -144,8 +144,6 @@ static void *worker_thread(void *arg) .session_mgr = session_manager_stat(sess_mgr), }; - uint64_t free_expired_ip_frag_interval = config->sched_opts.free_expired_ip_frag_interval; - uint64_t free_expired_ip_frag_batch = config->sched_opts.free_expired_ip_frag_batch; uint64_t merge_stat_interval = config->sched_opts.merge_stat_interval; uint64_t packet_io_yield_interval = config->sched_opts.packet_io_yield_interval; uint16_t thr_idx = thread->idx; @@ -290,6 +288,7 @@ static void *worker_thread(void *arg) idle_tasks: clean_session(sess_mgr, now_ms); + ip_reassembly_expire(ip_reass, now_ms); plugin_manager_on_polling(plug_mgr); // per merge_stat_interval merge thread stat @@ -299,13 +298,6 @@ static void *worker_thread(void *arg) thread->last_merge_thread_stat_timestamp = now_ms; } - // per free_expired_ip_frag_interval MAX free_expired_ip_frag_batch ip fragments are released - if (now_ms - thread->last_free_expired_ip_frag_timestamp >= free_expired_ip_frag_interval) - { - ip_reassembly_expire(ip_reass, free_expired_ip_frag_batch, now_ms); - thread->last_free_expired_ip_frag_timestamp = now_ms; - } - if (nr_pkt_received == 0) { packet_io_yield(packet_io, thr_idx, packet_io_yield_interval); @@ -359,7 +351,6 @@ static int stellar_thread_init(struct stellar *st) thread->idx = i; thread->is_runing = 0; - thread->last_free_expired_ip_frag_timestamp = now_ms; thread->last_merge_thread_stat_timestamp = now_ms; thread->snowflake = snowflake_new(i, config->snowflake_opts.snowflake_base, config->snowflake_opts.snowflake_offset); @@ -368,6 +359,7 @@ static int stellar_thread_init(struct stellar *st) CORE_LOG_ERROR("unable to create snowflake id generator"); return -1; } + thread->sess_mgr = session_manager_new(runtime->sess_mgr_cfg, now_ms); if (thread->sess_mgr == NULL) { @@ -375,8 +367,9 @@ static int stellar_thread_init(struct stellar *st) return -1; } session_manager_set_session_id_generator(thread->sess_mgr, stellar_generate_session_id); - thread->ip_mgr = ip_reassembly_new(&config->ip_reass_opts); - if (thread->ip_mgr == NULL) + + thread->ip_reass = ip_reassembly_new(runtime->ip_reass_cfg, now_ms); + if (thread->ip_reass == NULL) { CORE_LOG_ERROR("unable to create ip reassemble manager"); return -1; @@ -398,7 +391,7 @@ static void stellar_thread_clean(struct stellar *st) struct stellar_thread *thread = &runtime->threads[i]; if (ATOMIC_READ(&thread->is_runing) == 0) { - ip_reassembly_free(thread->ip_mgr); + ip_reassembly_free(thread->ip_reass); session_manager_free(thread->sess_mgr); snowflake_free(thread->snowflake); } @@ -490,8 +483,15 @@ struct stellar *stellar_new(const char *stellar_cfg_file, const char *plugin_cfg CORE_LOG_ERROR("unable to create session manager config"); goto error_out; } - session_manager_config_print(runtime->sess_mgr_cfg); + runtime->ip_reass_cfg = ip_reassembly_config_new(st->stellar_cfg_file); + if (runtime->ip_reass_cfg == NULL) + { + CORE_LOG_ERROR("unable to create ip reassembly config"); + goto error_out; + } + session_manager_config_print(runtime->sess_mgr_cfg); + ip_reassembly_config_print(runtime->ip_reass_cfg); if (stellar_config_load(config, st->stellar_cfg_file) != 0) { CORE_LOG_ERROR("unable to load config file"); @@ -587,6 +587,7 @@ void stellar_free(struct stellar *st) packet_io_free(runtime->packet_io); plugin_manager_exit(runtime->plug_mgr); stellar_stat_free(runtime->stat); + ip_reassembly_config_free(runtime->ip_reass_cfg); session_manager_config_free(runtime->sess_mgr_cfg); CORE_LOG_FATAL("stellar exit\n"); log_free(runtime->logger); diff --git a/infra/ip_reassembly/ip_reassembly.c b/infra/ip_reassembly/ip_reassembly.c index c6eb492..bfa228b 100644 --- a/infra/ip_reassembly/ip_reassembly.c +++ b/infra/ip_reassembly/ip_reassembly.c @@ -1,8 +1,10 @@ +#include #include #include #include #include +#include "toml.h" #include "checksum.h" #include "crc32_hash.h" #include "log_private.h" @@ -13,6 +15,7 @@ #define IP_REASSEMBLE_DEBUG(format, ...) STELLAR_LOG_DEBUG(__thread_local_logger, "ip_reassembly", format, ##__VA_ARGS__) #define IP_REASSEMBLE_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "ip_reassembly", format, ##__VA_ARGS__) +#define IP_REASSEMBLE_INFO(format, ...) STELLAR_LOG_INFO(__thread_local_logger, "ip_reassembly", format, ##__VA_ARGS__) #define IPV4_KEYLEN 1 #define IPV6_KEYLEN 4 @@ -112,15 +115,13 @@ struct ip_frag_pkt struct ip_reassembly { - // options - bool enable; - uint32_t timeout; - uint32_t bucket_entries; + struct ip_reassembly_config cfg; // runtime uint32_t entry_used; uint32_t entry_total; uint32_t entry_mask; + uint64_t last_clean_expired_frag_ts; // stats struct ip_reassembly_stat stat; @@ -190,38 +191,6 @@ static inline int is_power_of_2(uint32_t n) return n && !(n & (n - 1)); } -static int check_options(const struct ip_reassembly_options *opts) -{ - if (opts == NULL) - { - IP_REASSEMBLE_DEBUG("invalid options"); - return -1; - } - - if (opts->enable) - { - if (opts->timeout < 1 || opts->timeout > 60000) - { - IP_REASSEMBLE_DEBUG("invalid timeout: %u, supported range: [1, 60000]", opts->timeout); - return -1; - } - - if (opts->bucket_entries < 1 || is_power_of_2(opts->bucket_entries) == 0) - { - IP_REASSEMBLE_DEBUG("invalid bucket_entries: %u, must be power of 2", opts->bucket_entries); - return -1; - } - - if (opts->bucket_num == 0) - { - IP_REASSEMBLE_DEBUG("invalid bucket_num: %u, supported range: [1, 4294967295]", opts->bucket_num); - return -1; - } - } - - return 0; -} - /****************************************************************************** * ip frag key ******************************************************************************/ @@ -517,9 +486,9 @@ static struct ip_frag_pkt *ip_reassembly_find_frag_pkt(struct ip_reassembly *ass // search in the bucket struct ip_frag_pkt *old = NULL; struct ip_frag_pkt *empty = NULL; - uint64_t timeout = assy->timeout; - uint32_t assoc = assy->bucket_entries; - for (uint32_t i = 0; i != assoc; i++) + uint64_t timeout = assy->cfg.ip_frag_timeout_ms; + uint32_t entries = assy->cfg.bucket_entries; + for (uint32_t i = 0; i != entries; i++) { if (ip_frag_key_cmp(key, &p1[i].key) == 0) { @@ -594,7 +563,7 @@ static struct ip_frag_pkt *ip_reassembly_update_frag_pkt(struct ip_reassembly *a else { // expired - if (assy->timeout + frag_pkt->create_time <= now) + if (assy->cfg.ip_frag_timeout_ms + frag_pkt->create_time <= now) { IP_REASSEMBLE_DEBUG1("add ip frag pkt success: reuse expired entry", key); IP_REASSEMBLY_STAT_INC(&assy->stat, defrags_failed_timeout, key); @@ -757,29 +726,144 @@ error_out_overlap: * Public API ******************************************************************************/ -struct ip_reassembly *ip_reassembly_new(const struct ip_reassembly_options *opts) +#define PARSE_AND_CHECK_NUM(table, key, val, min, max) \ + do \ + { \ + const char *ptr = toml_raw_in(table, (key)); \ + if (ptr == NULL) \ + { \ + IP_REASSEMBLE_ERROR("config file missing ip_reassembly.%s", (key)); \ + goto error_out; \ + } \ + (val) = atoll(ptr); \ + if ((val) < (min) || (val) > (max)) \ + { \ + IP_REASSEMBLE_ERROR("invalid ip_reassembly.%s: %lu, supported range: [%lu, %lu]", (key), (val), (min), (max)); \ + goto error_out; \ + } \ + } while (0) + +int ip_reassembly_config_load(struct ip_reassembly_config *cfg, const char *toml_file) { - if (check_options(opts) == -1) + int ret = -1; + char errbuf[200]; + FILE *fp = NULL; + toml_table_t *root = NULL; + toml_table_t *table = NULL; + uint64_t zero = 0; // make compiler happy + + fp = fopen(toml_file, "r"); + if (fp == NULL) + { + IP_REASSEMBLE_ERROR("config file %s open failed, %s", toml_file, strerror(errno)); + goto error_out; + } + + root = toml_parse_file(fp, errbuf, sizeof(errbuf)); + if (root == NULL) + { + IP_REASSEMBLE_ERROR("config file %s parse failed, %s", toml_file, errbuf); + goto error_out; + } + + table = toml_table_in(root, "ip_reassembly"); + if (table == NULL) + { + IP_REASSEMBLE_ERROR("config file %s missing ip_reassembly", toml_file); + goto error_out; + } + + PARSE_AND_CHECK_NUM(table, "enable", cfg->enable, zero, 1); + + if (cfg->enable) + { + PARSE_AND_CHECK_NUM(table, "bucket_entries", cfg->bucket_entries, 1, 4294967295); + PARSE_AND_CHECK_NUM(table, "bucket_num", cfg->bucket_num, 1, 4294967295); + PARSE_AND_CHECK_NUM(table, "ip_frag_timeout_ms", cfg->ip_frag_timeout_ms, 1, 60000); + PARSE_AND_CHECK_NUM(table, "ip_frag_expire_polling_interval_ms", cfg->ip_frag_expire_polling_interval_ms, zero, 60000); + PARSE_AND_CHECK_NUM(table, "ip_frag_expire_polling_limit", cfg->ip_frag_expire_polling_limit, 1, 1024); + + if (is_power_of_2(cfg->bucket_entries) == 0) + { + IP_REASSEMBLE_ERROR("invalid ip_reassembly.bucket_entries: %lu, must be power of 2", cfg->bucket_entries); + goto error_out; + } + } + + ret = 0; +error_out: + if (root) + { + toml_free(root); + } + if (fp) + { + fclose(fp); + } + + return ret; +} + +struct ip_reassembly_config *ip_reassembly_config_new(const char *toml_file) +{ + if (toml_file == NULL) { return NULL; } + struct ip_reassembly_config *cfg = (struct ip_reassembly_config *)calloc(1, sizeof(struct ip_reassembly_config)); + if (cfg == NULL) + { + return NULL; + } + + if (ip_reassembly_config_load(cfg, toml_file) == -1) + { + ip_reassembly_config_free(cfg); + return NULL; + } + + return cfg; +} + +void ip_reassembly_config_free(struct ip_reassembly_config *cfg) +{ + if (cfg) + { + free(cfg); + cfg = NULL; + } +} + +void ip_reassembly_config_print(const struct ip_reassembly_config *cfg) +{ + if (cfg) + { + IP_REASSEMBLE_INFO("ip_reassembly.enable : %u", cfg->enable); + IP_REASSEMBLE_INFO("ip_reassembly.bucket_entries : %u", cfg->bucket_entries); + IP_REASSEMBLE_INFO("ip_reassembly.bucket_num : %u", cfg->bucket_num); + IP_REASSEMBLE_INFO("ip_reassembly.ip_frag_timeout_ms : %lu", cfg->ip_frag_timeout_ms); + IP_REASSEMBLE_INFO("ip_reassembly.ip_frag_expire_polling_interval_ms : %lu", cfg->ip_frag_expire_polling_interval_ms); + IP_REASSEMBLE_INFO("ip_reassembly.ip_frag_expire_polling_limit : %lu", cfg->ip_frag_expire_polling_limit); + } +} + +struct ip_reassembly *ip_reassembly_new(const struct ip_reassembly_config *cfg, uint64_t now_ms) +{ struct ip_reassembly *assy = (struct ip_reassembly *)calloc(1, sizeof(struct ip_reassembly)); if (assy == NULL) { IP_REASSEMBLE_ERROR("unable to allocate memory"); return NULL; } - assy->enable = opts->enable; - assy->timeout = opts->timeout; - assy->bucket_entries = opts->bucket_entries; + memcpy(&assy->cfg, cfg, sizeof(struct ip_reassembly_config)); - if (!assy->enable) + if (!assy->cfg.enable) { return assy; } - uint64_t entry_total = align32pow2(opts->bucket_num) * assy->bucket_entries * IP_FRAG_HASH_FNUM; + uint64_t entry_total = align32pow2(assy->cfg.bucket_num) * assy->cfg.bucket_entries * IP_FRAG_HASH_FNUM; if (entry_total > UINT32_MAX) { IP_REASSEMBLE_ERROR("bucket_num * bucket_entries is too large"); @@ -787,8 +871,9 @@ struct ip_reassembly *ip_reassembly_new(const struct ip_reassembly_options *opts return NULL; } + assy->last_clean_expired_frag_ts = now_ms; assy->entry_total = (uint32_t)entry_total; - assy->entry_mask = (assy->entry_total - 1) & ~(assy->bucket_entries - 1); + assy->entry_mask = (assy->entry_total - 1) & ~(assy->cfg.bucket_entries - 1); assy->table = (struct ip_frag_pkt *)calloc(assy->entry_total, sizeof(struct ip_frag_pkt)); if (assy->table == NULL) { @@ -821,11 +906,20 @@ void ip_reassembly_free(struct ip_reassembly *assy) } } -void ip_reassembly_expire(struct ip_reassembly *assy, uint64_t max_free, uint64_t now) +void ip_reassembly_expire(struct ip_reassembly *assy, uint64_t now) { - uint64_t count = 0; + if (now - assy->last_clean_expired_frag_ts >= assy->cfg.ip_frag_expire_polling_interval_ms) + { + assy->last_clean_expired_frag_ts = now; + } + else + { + return; + } + + uint64_t cleaned_frags = 0; struct ip_frag_pkt *frag_pkt = NULL; - uint64_t timeout = assy->timeout; + uint64_t timeout = assy->cfg.ip_frag_timeout_ms; TAILQ_FOREACH(frag_pkt, &assy->lru, lru) { if (timeout + frag_pkt->create_time <= now) @@ -833,9 +927,9 @@ void ip_reassembly_expire(struct ip_reassembly *assy, uint64_t max_free, uint64_ IP_REASSEMBLE_DEBUG1("expire ip frag pkt: discarding old fragmented packets", &frag_pkt->key); IP_REASSEMBLY_STAT_INC(&assy->stat, defrags_failed_timeout, &frag_pkt->key); ip_reassembly_del_frag_pkt(assy, frag_pkt); - count++; + cleaned_frags++; - if (count >= max_free) + if (cleaned_frags >= assy->cfg.ip_frag_expire_polling_limit) { break; } @@ -869,7 +963,7 @@ struct packet *ip_reassembly_packet(struct ip_reassembly *assy, const struct pac struct packet *pkt1; struct packet *pkt2; - if (!assy->enable) + if (!assy->cfg.enable) { return NULL; } diff --git a/infra/ip_reassembly/ip_reassembly.h b/infra/ip_reassembly/ip_reassembly.h index 456e09b..269b320 100644 --- a/infra/ip_reassembly/ip_reassembly.h +++ b/infra/ip_reassembly/ip_reassembly.h @@ -5,12 +5,15 @@ extern "C" { #endif -struct ip_reassembly_options +struct ip_reassembly_config { uint8_t enable; - uint32_t timeout; // range: [1, 60000] uint32_t bucket_entries; // range: [1, 4294967295] (must be power of 2) uint32_t bucket_num; // range: [1, 4294967295] + + uint64_t ip_frag_timeout_ms; // range: [1, 60000] (ms) + uint64_t ip_frag_expire_polling_interval_ms; // range: [0, 60000] (ms) + uint64_t ip_frag_expire_polling_limit; // range: [1, 1024] }; struct __attribute__((aligned(64))) ip_reassembly_stat @@ -46,9 +49,13 @@ struct __attribute__((aligned(64))) ip_reassembly_stat uint64_t ip6_frags_bypass_dup_last_frag; }; -struct ip_reassembly *ip_reassembly_new(const struct ip_reassembly_options *opts); +struct ip_reassembly_config *ip_reassembly_config_new(const char *toml_file); +void ip_reassembly_config_free(struct ip_reassembly_config *cfg); +void ip_reassembly_config_print(const struct ip_reassembly_config *cfg); + +struct ip_reassembly *ip_reassembly_new(const struct ip_reassembly_config *cfg, uint64_t now); void ip_reassembly_free(struct ip_reassembly *assy); -void ip_reassembly_expire(struct ip_reassembly *assy, uint64_t max_free, uint64_t now); +void ip_reassembly_expire(struct ip_reassembly *assy, uint64_t now); struct ip_reassembly_stat *ip_reassembly_stat(struct ip_reassembly *assy); /* diff --git a/infra/ip_reassembly/test/gtest_ipv4_reassembly.cpp b/infra/ip_reassembly/test/gtest_ipv4_reassembly.cpp index 5d96336..94a8254 100644 --- a/infra/ip_reassembly/test/gtest_ipv4_reassembly.cpp +++ b/infra/ip_reassembly/test/gtest_ipv4_reassembly.cpp @@ -198,14 +198,16 @@ TEST(IPV4_REASSEMBLE, PADDING_ORDER) struct packet *new_pkt; const struct layer_private *layer; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -293,14 +295,16 @@ TEST(IPV4_REASSEMBLE, PADDING_UNORDER) struct packet *new_pkt; const struct layer_private *layer; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -387,14 +391,16 @@ TEST(IPV4_REASSEMBLE, EXPIRE) struct packet pkt; struct packet *new_pkt; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -441,14 +447,16 @@ TEST(IPV4_REASSEMBLE, DUP_FIRST_FRAG) struct packet *new_pkt; const struct layer_private *layer; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -548,14 +556,16 @@ TEST(IPV4_REASSEMBLE, DUP_LAST_FRAG) struct packet *new_pkt; const struct layer_private *layer; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -654,14 +664,16 @@ TEST(IPV4_REASSEMBLE, FULL) struct packet pkt; struct packet *new_pkt; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 1, .bucket_num = 1, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), diff --git a/infra/ip_reassembly/test/gtest_ipv6_reassembly.cpp b/infra/ip_reassembly/test/gtest_ipv6_reassembly.cpp index f7eae08..ca177b2 100644 --- a/infra/ip_reassembly/test/gtest_ipv6_reassembly.cpp +++ b/infra/ip_reassembly/test/gtest_ipv6_reassembly.cpp @@ -609,14 +609,16 @@ TEST(IPV6_REASSEMBLE, NORMAL) struct packet *new_pkt; const struct layer_private *layer; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -721,14 +723,16 @@ TEST(IPV6_REASSEMBLE, EXPIRE) struct packet pkt; struct packet *new_pkt; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -775,14 +779,16 @@ TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG) struct packet *new_pkt; const struct layer_private *layer; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -900,14 +906,16 @@ TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG) struct packet *new_pkt; const struct layer_private *layer; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -1025,14 +1033,16 @@ TEST(IPV6_REASSEMBLE, FULL) struct packet *new_pkt; struct in6_addr src_addr; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 1, .bucket_num = 1, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), @@ -1095,14 +1105,16 @@ TEST(IPV6_REASSEMBLE, OVERLAP) struct packet pkt; struct packet *new_pkt; struct ip_reassembly *assy; - struct ip_reassembly_options opts = { + struct ip_reassembly_config cfg = { .enable = true, - .timeout = 1, .bucket_entries = 16, .bucket_num = 8, + .ip_frag_timeout_ms = 1, + .ip_frag_expire_polling_interval_ms = 0, + .ip_frag_expire_polling_limit = 1024, }; - assy = ip_reassembly_new(&opts); + assy = ip_reassembly_new(&cfg, 0); EXPECT_TRUE(assy != NULL); check_stat(ip_reassembly_stat(assy), diff --git a/test/decoders/http/test_based_on_stellar/env/stellar.toml b/test/decoders/http/test_based_on_stellar/env/stellar.toml index da13527..210ce3d 100644 --- a/test/decoders/http/test_based_on_stellar/env/stellar.toml +++ b/test/decoders/http/test_based_on_stellar/env/stellar.toml @@ -15,9 +15,12 @@ cpu_mask = [5, 6, 7, 8, 9, 10, 11, 12] [ip_reassembly] enable = 1 -timeout = 10000 # range: [1, 60000] (ms) -bucket_entries = 256 # range: [1, 4294967295] (must be power of 2) -bucket_num = 4096 # range: [1, 4294967295] +bucket_entries = 32 # range: [1, 4294967295] (must be power of 2) +bucket_num = 1024 # range: [1, 4294967295] + +ip_frag_timeout_ms = 10000 # range: [1, 60000] (ms) +ip_frag_expire_polling_interval_ms = 0 # range: [0, 60000] (ms) +ip_frag_expire_polling_limit = 1024 # range: [1, 1024] [session_manager] # max session number @@ -62,10 +65,6 @@ tcp_reassembly_max_timeout_ms = 10000 # range: [1, 60000] (ms) tcp_reassembly_max_segments = 256 # range: [2, 4096] [schedule] -# Note: free_expired_ip_frag_interval determines the precision of ip_reassembly timeout -free_expired_ip_frag_interval = 50 # range: [1, 60000] (ms) -free_expired_ip_frag_batch = 100 # range: [1, 60000] - merge_stat_interval = 50 # range: [1, 60000] (ms) output_stat_interval = 10 # range: [1, 60000] (ms) diff --git a/test/packet_inject/conf/stellar.toml b/test/packet_inject/conf/stellar.toml index 3860757..d039d0d 100644 --- a/test/packet_inject/conf/stellar.toml +++ b/test/packet_inject/conf/stellar.toml @@ -15,9 +15,12 @@ cpu_mask = [5] [ip_reassembly] enable = 1 -timeout = 10000 # range: [1, 60000] (ms) -bucket_entries = 8 # range: [1, 4294967295] (must be power of 2) -bucket_num = 1024 # range: [1, 4294967295] +bucket_entries = 32 # range: [1, 4294967295] (must be power of 2) +bucket_num = 1024 # range: [1, 4294967295] + +ip_frag_timeout_ms = 10000 # range: [1, 60000] (ms) +ip_frag_expire_polling_interval_ms = 0 # range: [0, 60000] (ms) +ip_frag_expire_polling_limit = 1024 # range: [1, 1024] [session_manager] # max session number @@ -62,10 +65,6 @@ tcp_reassembly_max_timeout_ms = 10000 # range: [1, 60000] (ms) tcp_reassembly_max_segments = 128 # range: [2, 4096] [schedule] -# Note: free_expired_ip_frag_interval determines the precision of ip_reassembly timeout -free_expired_ip_frag_interval = 50 # range: [1, 60000] (ms) -free_expired_ip_frag_batch = 1000 # range: [1, 60000] - merge_stat_interval = 50 # range: [1, 60000] (ms) output_stat_interval = 2000 # range: [1, 60000] (ms)