diff --git a/deps/interval_tree/interval.cpp b/deps/interval_tree/interval.cpp index bdcebaa..4fc7ddf 100644 --- a/deps/interval_tree/interval.cpp +++ b/deps/interval_tree/interval.cpp @@ -67,5 +67,5 @@ int interval_overlap(const interval_t *i1, const interval_t *i2) int interval_equal(const interval_t *i1, const interval_t *i2) { - return i1->low == i2->low && i1->high == i2->high; + return i1->low == i2->low && i1->high == i2->high && i1->data == i2->data; } diff --git a/deps/interval_tree/test/gtest_interval_tree.cpp b/deps/interval_tree/test/gtest_interval_tree.cpp index 70c26ca..7fe0fbc 100644 --- a/deps/interval_tree/test/gtest_interval_tree.cpp +++ b/deps/interval_tree/test/gtest_interval_tree.cpp @@ -4,15 +4,11 @@ void *my_dup(void *p) { - return p ? strdup((const char *)p) : NULL; + return p; } void my_rel(void *p) { - if (p) - { - free(p); - } } // find overlap @@ -23,6 +19,7 @@ TEST(INTERVAL_TREE, FIND) interval_t *result; interval_t query; interval_t segment; + void *data = (void *)"Hello"; // new tree = itree_new(my_dup, my_rel); @@ -33,7 +30,7 @@ TEST(INTERVAL_TREE, FIND) segment = { .low = 5, .high = 9, - .data = (void *)"Hello", + .data = data, }; EXPECT_TRUE(itree_insert(tree, &segment) == 1); EXPECT_TRUE(itree_size(tree) == 1); @@ -118,6 +115,7 @@ TEST(INTERVAL_TREE, DELETE) itree_t *tree; interval_t query; interval_t segment; + void *data = (void *)"Hello"; // new tree = itree_new(my_dup, my_rel); @@ -128,7 +126,7 @@ TEST(INTERVAL_TREE, DELETE) segment = { .low = 5, .high = 9, - .data = (void *)"Hello", + .data = data, }; EXPECT_TRUE(itree_insert(tree, &segment) == 1); EXPECT_TRUE(itree_size(tree) == 1); @@ -145,6 +143,7 @@ TEST(INTERVAL_TREE, DELETE) query = { .low = 9, .high = 9, + .data = data, }; EXPECT_TRUE(itree_remove(tree, &query) == 0); EXPECT_TRUE(itree_size(tree) == 1); @@ -153,6 +152,7 @@ TEST(INTERVAL_TREE, DELETE) query = { .low = 1, .high = 20, + .data = data, }; EXPECT_TRUE(itree_remove(tree, &query) == 0); EXPECT_TRUE(itree_size(tree) == 1); @@ -161,6 +161,7 @@ TEST(INTERVAL_TREE, DELETE) query = { .low = 5, .high = 9, + .data = data, }; EXPECT_TRUE(itree_remove(tree, &query) == 1); EXPECT_TRUE(itree_size(tree) == 0); @@ -175,6 +176,8 @@ TEST(INTERVAL_TREE, REPEAT1) itree_t *tree; interval_t segment; interval_t query; + void *data1 = (void *)"Hello"; + void *data2 = (void *)"World"; // new tree = itree_new(my_dup, my_rel); @@ -185,7 +188,7 @@ TEST(INTERVAL_TREE, REPEAT1) segment = { .low = 5, .high = 9, - .data = (void *)"Hello", + .data = data1, }; EXPECT_TRUE(itree_insert(tree, &segment) == 1); EXPECT_TRUE(itree_size(tree) == 1); @@ -194,7 +197,7 @@ TEST(INTERVAL_TREE, REPEAT1) segment = { .low = 5, .high = 9, - .data = (void *)"World", + .data = data2, }; EXPECT_TRUE(itree_insert(tree, &segment) == 1); EXPECT_TRUE(itree_size(tree) == 2); @@ -203,9 +206,15 @@ TEST(INTERVAL_TREE, REPEAT1) query = { .low = 5, .high = 9, + .data = data1, }; EXPECT_TRUE(itree_remove(tree, &query) == 1); EXPECT_TRUE(itree_size(tree) == 1); + query = { + .low = 5, + .high = 9, + .data = data2, + }; EXPECT_TRUE(itree_remove(tree, &query) == 1); EXPECT_TRUE(itree_size(tree) == 0); diff --git a/src/ip_reassembly/ip_reassembly.cpp b/src/ip_reassembly/ip_reassembly.cpp index 6352951..2213546 100644 --- a/src/ip_reassembly/ip_reassembly.cpp +++ b/src/ip_reassembly/ip_reassembly.cpp @@ -14,7 +14,7 @@ #define IPV6_KEYLEN 4 #define PRIME_VALUE 0xeaad8405 #define IP_FRAG_HASH_FNUM 2 -#define IP_FRAG_TBL_POS(assembler, sig) ((assembler)->table + ((sig) & (assembler)->entry_mask)) +#define IP_FRAG_TBL_POS(assy, sig) ((assy)->table + ((sig) & (assy)->entry_mask)) #define KEY_TO_STR(key, str_str, dst_str) \ do \ @@ -136,16 +136,16 @@ struct ip_reassembly * utils ******************************************************************************/ -#define ip_reassembly_stat_inc(assembler, filed, key) \ - { \ - if ((key)->src_dst_len == IPV4_KEYLEN) \ - { \ - (assembler)->stat.ip4_flow_##filed++; \ - } \ - else \ - { \ - (assembler)->stat.ip6_flow_##filed++; \ - } \ +#define ip_reassembly_stat_inc(assy, filed, key) \ + { \ + if ((key)->src_dst_len == IPV4_KEYLEN) \ + { \ + (assy)->stat.ip4_flow_##filed++; \ + } \ + else \ + { \ + (assy)->stat.ip6_flow_##filed++; \ + } \ } static inline void *memdup(const void *src, size_t len) @@ -402,7 +402,7 @@ static inline int ip_flow_is_ready(struct ip_flow *flow) // return 0 : success // return -1 : failed -static inline int ip_flow_update(struct ip_reassembly *assembler, +static inline int ip_flow_update(struct ip_reassembly *assy, struct ip_flow *flow, const struct packet *pkt, char *frag_data, uint16_t frag_len, uint16_t frag_offset, bool more_frags) { @@ -424,7 +424,7 @@ static inline int ip_flow_update(struct ip_reassembly *assembler, if (flow->frags[IP_FIRST_FRAG_IDX].data != NULL) { IP_REASSEMBLE_DEBUG1("duplicate first fragment bypass", &flow->key); - ip_reassembly_stat_inc(assembler, bypass_dup_fist_frag, &flow->key); + ip_reassembly_stat_inc(assy, bypass_dup_fist_frag, &flow->key); return 0; } idx = IP_FIRST_FRAG_IDX; @@ -435,7 +435,7 @@ static inline int ip_flow_update(struct ip_reassembly *assembler, if (flow->frags[IP_LAST_FRAG_IDX].data != NULL) { IP_REASSEMBLE_DEBUG1("duplicate last fragment bypass", &flow->key); - ip_reassembly_stat_inc(assembler, bypass_dup_last_frag, &flow->key); + ip_reassembly_stat_inc(assy, bypass_dup_last_frag, &flow->key); return 0; } idx = IP_LAST_FRAG_IDX; @@ -446,7 +446,7 @@ static inline int ip_flow_update(struct ip_reassembly *assembler, if (flow->next_fill_idx >= IP_MAX_FRAG_NUM) { IP_REASSEMBLE_ERROR1("max number of fragment exceeded", &flow->key); - ip_reassembly_stat_inc(assembler, fail_many_frag, &flow->key); + ip_reassembly_stat_inc(assy, fail_many_frag, &flow->key); return -1; } idx = flow->next_fill_idx; @@ -464,26 +464,26 @@ static inline int ip_flow_update(struct ip_reassembly *assembler, * ip reassemble manager add/del/reuse/find/update flow ******************************************************************************/ -static inline void ip_reassembly_add_flow(struct ip_reassembly *assembler, struct ip_flow *flow) +static inline void ip_reassembly_add_flow(struct ip_reassembly *assy, struct ip_flow *flow) { - ip_reassembly_stat_inc(assembler, add, &flow->key); - TAILQ_INSERT_TAIL(&assembler->lru, flow, lru); - assembler->entry_used++; + ip_reassembly_stat_inc(assy, add, &flow->key); + TAILQ_INSERT_TAIL(&assy->lru, flow, lru); + assy->entry_used++; } -static inline void ip_reassembly_del_flow(struct ip_reassembly *assembler, struct ip_flow *flow) +static inline void ip_reassembly_del_flow(struct ip_reassembly *assy, struct ip_flow *flow) { - ip_reassembly_stat_inc(assembler, del, &flow->key); - TAILQ_REMOVE(&assembler->lru, flow, lru); - assembler->entry_used--; + ip_reassembly_stat_inc(assy, del, &flow->key); + TAILQ_REMOVE(&assy->lru, flow, lru); + assy->entry_used--; } -static inline void ip_reassembly_reuse_flow(struct ip_reassembly *assembler, struct ip_flow *flow, const struct ip_flow_key *key, uint64_t now) +static inline void ip_reassembly_reuse_flow(struct ip_reassembly *assy, struct ip_flow *flow, const struct ip_flow_key *key, uint64_t now) { - ip_reassembly_del_flow(assembler, flow); + ip_reassembly_del_flow(assy, flow); ip_flow_free(flow); ip_flow_init(flow, key, now); - ip_reassembly_add_flow(assembler, flow); + ip_reassembly_add_flow(assy, flow); } /* @@ -491,13 +491,13 @@ static inline void ip_reassembly_reuse_flow(struct ip_reassembly *assembler, str * free : the first empty entry in the bucket * expired: the first timed-out entry in the bucket */ -static struct ip_flow *ip_reassembly_find_flow(struct ip_reassembly *assembler, const struct ip_flow_key *key, struct ip_flow **free, struct ip_flow **expired, uint64_t now) +static struct ip_flow *ip_reassembly_find_flow(struct ip_reassembly *assy, const struct ip_flow_key *key, struct ip_flow **free, struct ip_flow **expired, uint64_t now) { - ip_reassembly_stat_inc(assembler, find, key); + ip_reassembly_stat_inc(assy, find, key); - if (assembler->last != NULL && ip_flow_key_cmp(key, &assembler->last->key) == 0) + if (assy->last != NULL && ip_flow_key_cmp(key, &assy->last->key) == 0) { - return assembler->last; + return assy->last; } uint32_t sig1 = 0; @@ -512,14 +512,14 @@ static struct ip_flow *ip_reassembly_find_flow(struct ip_reassembly *assembler, } // get the bucket by hash - struct ip_flow *p1 = IP_FRAG_TBL_POS(assembler, sig1); - struct ip_flow *p2 = IP_FRAG_TBL_POS(assembler, sig2); + struct ip_flow *p1 = IP_FRAG_TBL_POS(assy, sig1); + struct ip_flow *p2 = IP_FRAG_TBL_POS(assy, sig2); // search in the bucket struct ip_flow *old = NULL; struct ip_flow *empty = NULL; - uint64_t timeout = assembler->timeout; - uint32_t assoc = assembler->bucket_entries; + uint64_t timeout = assy->timeout; + uint32_t assoc = assy->bucket_entries; for (uint32_t i = 0; i != assoc; i++) { if (ip_flow_key_cmp(key, &p1[i].key) == 0) @@ -558,22 +558,22 @@ static struct ip_flow *ip_reassembly_find_flow(struct ip_reassembly *assembler, return NULL; } -static struct ip_flow *ip_reassembly_update_flow(struct ip_reassembly *assembler, const struct ip_flow_key *key, uint64_t now) +static struct ip_flow *ip_reassembly_update_flow(struct ip_reassembly *assy, const struct ip_flow_key *key, uint64_t now) { struct ip_flow *flow = NULL; struct ip_flow *free = NULL; struct ip_flow *expired = NULL; - flow = ip_reassembly_find_flow(assembler, key, &free, &expired, now); + flow = ip_reassembly_find_flow(assy, key, &free, &expired, now); if (flow == NULL) { if (expired) { IP_REASSEMBLE_DEBUG1("add ip flow success: reuse expired entry", key); - ip_reassembly_reuse_flow(assembler, expired, key, now); - ip_reassembly_stat_inc(assembler, timeout, key); + ip_reassembly_reuse_flow(assy, expired, key, now); + ip_reassembly_stat_inc(assy, timeout, key); - assembler->last = expired; + assy->last = expired; return expired; } @@ -581,27 +581,27 @@ static struct ip_flow *ip_reassembly_update_flow(struct ip_reassembly *assembler { IP_REASSEMBLE_DEBUG1("add ip flow success: use free entry", key); ip_flow_init(free, key, now); - ip_reassembly_add_flow(assembler, free); + ip_reassembly_add_flow(assy, free); - assembler->last = free; + assy->last = free; return free; } // no space IP_REASSEMBLE_ERROR1("add ip flow failed: bucket full", key); - ip_reassembly_stat_inc(assembler, fail_no_space, key); + ip_reassembly_stat_inc(assy, fail_no_space, key); return NULL; } else { // expired - if (assembler->timeout + flow->create_time <= now) + if (assy->timeout + flow->create_time <= now) { IP_REASSEMBLE_DEBUG1("add ip flow success: reuse expired entry", key); - ip_reassembly_reuse_flow(assembler, flow, key, now); - ip_reassembly_stat_inc(assembler, timeout, key); + ip_reassembly_reuse_flow(assy, flow, key, now); + ip_reassembly_stat_inc(assy, timeout, key); - assembler->last = flow; + assy->last = flow; return flow; } // not expired @@ -609,7 +609,7 @@ static struct ip_flow *ip_reassembly_update_flow(struct ip_reassembly *assembler { IP_REASSEMBLE_DEBUG1("find ip flow success: not expire", key); - assembler->last = flow; + assy->last = flow; return flow; } } @@ -619,7 +619,7 @@ static struct ip_flow *ip_reassembly_update_flow(struct ip_reassembly *assembler * frag reassemble ******************************************************************************/ -static struct packet *ip_frag_reassemble(struct ip_reassembly *assembler, struct ip_flow *flow) +static struct packet *ip_frag_reassemble(struct ip_reassembly *assy, struct ip_flow *flow) { struct ip_frag_pkt *first = &flow->frags[IP_FIRST_FRAG_IDX]; struct ip_frag_pkt *last = &flow->frags[IP_LAST_FRAG_IDX]; @@ -735,12 +735,12 @@ static struct packet *ip_frag_reassemble(struct ip_reassembly *assembler, struct return pkt; error_out_invalid_length: - ip_reassembly_stat_inc(assembler, fail_invalid_length, &flow->key); + ip_reassembly_stat_inc(assy, fail_invalid_length, &flow->key); packet_free(pkt); return NULL; error_out_overlap: - ip_reassembly_stat_inc(assembler, fail_overlap, &flow->key); + ip_reassembly_stat_inc(assy, fail_overlap, &flow->key); packet_free(pkt); return NULL; } @@ -756,84 +756,84 @@ struct ip_reassembly *ip_reassembly_new(const struct ip_reassembly_options *opts return NULL; } - struct ip_reassembly *assembler = (struct ip_reassembly *)calloc(1, sizeof(struct ip_reassembly)); - if (assembler == NULL) + 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; } - assembler->enable = opts->enable; - assembler->timeout = opts->timeout; - assembler->bucket_entries = opts->bucket_entries; - assembler->bucket_num = opts->bucket_num; + assy->enable = opts->enable; + assy->timeout = opts->timeout; + assy->bucket_entries = opts->bucket_entries; + assy->bucket_num = opts->bucket_num; - if (!assembler->enable) + if (!assy->enable) { - return assembler; + return assy; } - uint64_t entry_total = align32pow2(assembler->bucket_num) * assembler->bucket_entries * IP_FRAG_HASH_FNUM; + uint64_t entry_total = align32pow2(assy->bucket_num) * assy->bucket_entries * IP_FRAG_HASH_FNUM; if (entry_total > UINT32_MAX) { IP_REASSEMBLE_ERROR("bucket_num * bucket_entries is too large"); - free(assembler); + free(assy); return NULL; } - assembler->entry_total = (uint32_t)entry_total; - assembler->entry_mask = (assembler->entry_total - 1) & ~(assembler->bucket_entries - 1); - assembler->table = (struct ip_flow *)calloc(assembler->entry_total, sizeof(struct ip_flow)); - if (assembler->table == NULL) + assy->entry_total = (uint32_t)entry_total; + assy->entry_mask = (assy->entry_total - 1) & ~(assy->bucket_entries - 1); + assy->table = (struct ip_flow *)calloc(assy->entry_total, sizeof(struct ip_flow)); + if (assy->table == NULL) { IP_REASSEMBLE_ERROR("unable to allocate memory"); - free(assembler); + free(assy); return NULL; } - TAILQ_INIT(&(assembler->lru)); + TAILQ_INIT(&(assy->lru)); - return assembler; + return assy; } -void ip_reassembly_free(struct ip_reassembly *assembler) +void ip_reassembly_free(struct ip_reassembly *assy) { - if (assembler) + if (assy) { - if (assembler->table) + if (assy->table) { - for (uint32_t i = 0; i < assembler->entry_total; i++) + for (uint32_t i = 0; i < assy->entry_total; i++) { - ip_flow_free(assembler->table + i); + ip_flow_free(assy->table + i); } - free(assembler->table); - assembler->table = NULL; + free(assy->table); + assy->table = NULL; } - free(assembler); - assembler = NULL; + free(assy); + assy = NULL; } } -void ip_reassembly_expire(struct ip_reassembly *assembler, uint64_t now) +void ip_reassembly_expire(struct ip_reassembly *assy, uint64_t now) { struct ip_flow *flow = NULL; - uint64_t timeout = assembler->timeout; + uint64_t timeout = assy->timeout; - TAILQ_FOREACH(flow, &assembler->lru, lru) + TAILQ_FOREACH(flow, &assy->lru, lru) if (timeout + flow->create_time <= now) { IP_REASSEMBLE_DEBUG1("expire ip flow: discarding old fragmented packets", &flow->key); - ip_reassembly_del_flow(assembler, flow); - ip_reassembly_stat_inc(assembler, timeout, &flow->key); + ip_reassembly_del_flow(assy, flow); + ip_reassembly_stat_inc(assy, timeout, &flow->key); ip_flow_free(flow); } } -struct ip_reassembly_stat *ip_reassembly_get_stat(struct ip_reassembly *assembler) +struct ip_reassembly_stat *ip_reassembly_get_stat(struct ip_reassembly *assy) { - if (assembler) + if (assy) { - return &(assembler->stat); + return &(assy->stat); } else { @@ -846,12 +846,12 @@ struct ip_reassembly_stat *ip_reassembly_get_stat(struct ip_reassembly *assemble * The returned packet should be freed by calling the packet_free() function */ -struct packet *ip_reassembly_packet(struct ip_reassembly *assembler, const struct packet *pkt, uint64_t now) +struct packet *ip_reassembly_packet(struct ip_reassembly *assy, const struct packet *pkt, uint64_t now) { struct packet *pkt1; struct packet *pkt2; - if (!assembler->enable) + if (!assy->enable) { return NULL; } @@ -864,10 +864,10 @@ struct packet *ip_reassembly_packet(struct ip_reassembly *assembler, const struc if (layer->type == LAYER_TYPE_IPV4) { - pkt1 = ipv4_reassembly_packet(assembler, pkt, now); + pkt1 = ipv4_reassembly_packet(assy, pkt, now); if (pkt1 && pkt1->frag_layer) { - pkt2 = ip_reassembly_packet(assembler, pkt1, now); + pkt2 = ip_reassembly_packet(assy, pkt1, now); packet_free(pkt1); return pkt2; } @@ -876,10 +876,10 @@ struct packet *ip_reassembly_packet(struct ip_reassembly *assembler, const struc } else if (layer->type == LAYER_TYPE_IPV6) { - pkt1 = ipv6_reassembly_packet(assembler, pkt, now); + pkt1 = ipv6_reassembly_packet(assy, pkt, now); if (pkt1 && pkt1->frag_layer) { - pkt2 = ip_reassembly_packet(assembler, pkt1, now); + pkt2 = ip_reassembly_packet(assy, pkt1, now); packet_free(pkt1); return pkt2; } @@ -892,7 +892,7 @@ struct packet *ip_reassembly_packet(struct ip_reassembly *assembler, const struc } } -struct packet *ipv4_reassembly_packet(struct ip_reassembly *assembler, const struct packet *pkt, uint64_t now) +struct packet *ipv4_reassembly_packet(struct ip_reassembly *assy, const struct packet *pkt, uint64_t now) { const struct layer *layer = pkt->frag_layer; const struct ip *hdr = (const struct ip *)layer->hdr_ptr; @@ -911,7 +911,7 @@ struct packet *ipv4_reassembly_packet(struct ip_reassembly *assembler, const str key.ip_id = ipv4_hdr_get_ipid(hdr); key.proto = ipv4_hdr_get_proto(hdr); - struct ip_flow *flow = ip_reassembly_update_flow(assembler, &key, now); + struct ip_flow *flow = ip_reassembly_update_flow(assy, &key, now); if (flow == NULL) { return NULL; @@ -920,9 +920,9 @@ struct packet *ipv4_reassembly_packet(struct ip_reassembly *assembler, const str char *frag_data = (char *)layer->pld_ptr; bool more_frags = ipv4_hdr_get_mf_flag(hdr); uint16_t frag_offset = ipv4_hdr_get_frag_offset(hdr); - if (ip_flow_update(assembler, flow, pkt, frag_data, frag_len, frag_offset, more_frags) != 0) + if (ip_flow_update(assy, flow, pkt, frag_data, frag_len, frag_offset, more_frags) != 0) { - ip_reassembly_del_flow(assembler, flow); + ip_reassembly_del_flow(assy, flow); ip_flow_free(flow); return NULL; } @@ -932,8 +932,8 @@ struct packet *ipv4_reassembly_packet(struct ip_reassembly *assembler, const str return NULL; } - struct packet *new_pkt = ip_frag_reassemble(assembler, flow); - ip_reassembly_del_flow(assembler, flow); + struct packet *new_pkt = ip_frag_reassemble(assy, flow); + ip_reassembly_del_flow(assy, flow); ip_flow_free(flow); return new_pkt; @@ -978,7 +978,7 @@ struct packet *ipv4_reassembly_packet(struct ip_reassembly *assembler, const str * +-----------------+-----------------+--------+--------+-//-+--------+ */ -struct packet *ipv6_reassembly_packet(struct ip_reassembly *assembler, const struct packet *pkt, uint64_t now) +struct packet *ipv6_reassembly_packet(struct ip_reassembly *assy, const struct packet *pkt, uint64_t now) { const struct layer *layer = pkt->frag_layer; const struct ip6_hdr *hdr = (const struct ip6_hdr *)layer->hdr_ptr; @@ -1003,7 +1003,7 @@ struct packet *ipv6_reassembly_packet(struct ip_reassembly *assembler, const str key.ip_id = ipv6_frag_get_ident(frag_hdr); key.proto = 0; // only first fragment has the upper layer protocol - struct ip_flow *flow = ip_reassembly_update_flow(assembler, &key, now); + struct ip_flow *flow = ip_reassembly_update_flow(assy, &key, now); if (flow == NULL) { return NULL; @@ -1011,9 +1011,9 @@ struct packet *ipv6_reassembly_packet(struct ip_reassembly *assembler, const str bool more_frags = ipv6_frag_get_more(frag_hdr); uint16_t frag_offset = ipv6_frag_get_offset(frag_hdr); - if (ip_flow_update(assembler, flow, pkt, frag_data, frag_len, frag_offset, more_frags) != 0) + if (ip_flow_update(assy, flow, pkt, frag_data, frag_len, frag_offset, more_frags) != 0) { - ip_reassembly_del_flow(assembler, flow); + ip_reassembly_del_flow(assy, flow); ip_flow_free(flow); return NULL; } @@ -1023,8 +1023,8 @@ struct packet *ipv6_reassembly_packet(struct ip_reassembly *assembler, const str return NULL; } - struct packet *new_pkt = ip_frag_reassemble(assembler, flow); - ip_reassembly_del_flow(assembler, flow); + struct packet *new_pkt = ip_frag_reassemble(assy, flow); + ip_reassembly_del_flow(assy, flow); ip_flow_free(flow); return new_pkt; diff --git a/src/ip_reassembly/ip_reassembly.h b/src/ip_reassembly/ip_reassembly.h index 96775c9..a0e8d87 100644 --- a/src/ip_reassembly/ip_reassembly.h +++ b/src/ip_reassembly/ip_reassembly.h @@ -51,17 +51,17 @@ struct ip_reassembly_stat }; struct ip_reassembly *ip_reassembly_new(const struct ip_reassembly_options *opts); -void ip_reassembly_free(struct ip_reassembly *assembler); -void ip_reassembly_expire(struct ip_reassembly *assembler, uint64_t now); -struct ip_reassembly_stat *ip_reassembly_get_stat(struct ip_reassembly *assembler); +void ip_reassembly_free(struct ip_reassembly *assy); +void ip_reassembly_expire(struct ip_reassembly *assy, uint64_t now); +struct ip_reassembly_stat *ip_reassembly_get_stat(struct ip_reassembly *assy); /* * Returns the reassembled packet, or NULL if the packet is not reassembled * The returned packet should be freed by calling the packet_free() function */ -struct packet *ip_reassembly_packet(struct ip_reassembly *assembler, const struct packet *pkt, uint64_t now); -struct packet *ipv4_reassembly_packet(struct ip_reassembly *assembler, const struct packet *pkt, uint64_t now); -struct packet *ipv6_reassembly_packet(struct ip_reassembly *assembler, const struct packet *pkt, uint64_t now); +struct packet *ip_reassembly_packet(struct ip_reassembly *assy, const struct packet *pkt, uint64_t now); +struct packet *ipv4_reassembly_packet(struct ip_reassembly *assy, const struct packet *pkt, uint64_t now); +struct packet *ipv6_reassembly_packet(struct ip_reassembly *assy, const struct packet *pkt, uint64_t now); #ifdef __cpluscplus } diff --git a/src/ip_reassembly/test/gtest_ipv4_reassembly.cpp b/src/ip_reassembly/test/gtest_ipv4_reassembly.cpp index e42cf8c..8a942d6 100644 --- a/src/ip_reassembly/test/gtest_ipv4_reassembly.cpp +++ b/src/ip_reassembly/test/gtest_ipv4_reassembly.cpp @@ -197,7 +197,7 @@ TEST(IPV4_REASSEMBLE, PADDING_ORDER) struct packet pkt; struct packet *new_pkt; const struct layer *layer; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -205,10 +205,10 @@ TEST(IPV4_REASSEMBLE, PADDING_ORDER) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -216,10 +216,10 @@ TEST(IPV4_REASSEMBLE, PADDING_ORDER) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 1, 1, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -227,10 +227,10 @@ TEST(IPV4_REASSEMBLE, PADDING_ORDER) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 2, 1, 1, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -280,7 +280,7 @@ TEST(IPV4_REASSEMBLE, PADDING_ORDER) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -290,7 +290,7 @@ TEST(IPV4_REASSEMBLE, PADDING_UNORDER) struct packet pkt; struct packet *new_pkt; const struct layer *layer; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -298,10 +298,10 @@ TEST(IPV4_REASSEMBLE, PADDING_UNORDER) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -309,10 +309,10 @@ TEST(IPV4_REASSEMBLE, PADDING_UNORDER) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 1, 1, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -320,10 +320,10 @@ TEST(IPV4_REASSEMBLE, PADDING_UNORDER) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 2, 1, 1, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -373,7 +373,7 @@ TEST(IPV4_REASSEMBLE, PADDING_UNORDER) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -382,7 +382,7 @@ TEST(IPV4_REASSEMBLE, EXPIRE) { struct packet pkt; struct packet *new_pkt; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -390,10 +390,10 @@ TEST(IPV4_REASSEMBLE, EXPIRE) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -401,10 +401,10 @@ TEST(IPV4_REASSEMBLE, EXPIRE) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 1, 1, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -412,10 +412,10 @@ TEST(IPV4_REASSEMBLE, EXPIRE) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 2); + new_pkt = ip_reassembly_packet(assy, &pkt, 2); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 2, 2, 1, 1, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -424,7 +424,7 @@ TEST(IPV4_REASSEMBLE, EXPIRE) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -434,7 +434,7 @@ TEST(IPV4_REASSEMBLE, DUP_FIRST_FRAG) struct packet pkt; struct packet *new_pkt; const struct layer *layer; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -442,10 +442,10 @@ TEST(IPV4_REASSEMBLE, DUP_FIRST_FRAG) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -453,10 +453,10 @@ TEST(IPV4_REASSEMBLE, DUP_FIRST_FRAG) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 1, 1, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -464,10 +464,10 @@ TEST(IPV4_REASSEMBLE, DUP_FIRST_FRAG) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 2, 1, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 1, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -475,10 +475,10 @@ TEST(IPV4_REASSEMBLE, DUP_FIRST_FRAG) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 3, 1, 1, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 1, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -528,7 +528,7 @@ TEST(IPV4_REASSEMBLE, DUP_FIRST_FRAG) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -538,7 +538,7 @@ TEST(IPV4_REASSEMBLE, DUP_LAST_FRAG) struct packet pkt; struct packet *new_pkt; const struct layer *layer; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -546,10 +546,10 @@ TEST(IPV4_REASSEMBLE, DUP_LAST_FRAG) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -557,10 +557,10 @@ TEST(IPV4_REASSEMBLE, DUP_LAST_FRAG) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 1, 1, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -568,10 +568,10 @@ TEST(IPV4_REASSEMBLE, DUP_LAST_FRAG) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 2, 1, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 1, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -579,10 +579,10 @@ TEST(IPV4_REASSEMBLE, DUP_LAST_FRAG) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 3, 1, 1, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 1, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -632,7 +632,7 @@ TEST(IPV4_REASSEMBLE, DUP_LAST_FRAG) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -641,7 +641,7 @@ TEST(IPV4_REASSEMBLE, FULL) { struct packet pkt; struct packet *new_pkt; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -649,10 +649,10 @@ TEST(IPV4_REASSEMBLE, FULL) .bucket_num = 1, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -664,10 +664,10 @@ TEST(IPV4_REASSEMBLE, FULL) // flow1 packet_set_ipv4_src_addr(&pkt, 1); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 1, 1, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -675,10 +675,10 @@ TEST(IPV4_REASSEMBLE, FULL) // flow2 packet_set_ipv4_src_addr(&pkt, 2); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 2, 2, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -686,10 +686,10 @@ TEST(IPV4_REASSEMBLE, FULL) // flow3 packet_set_ipv4_src_addr(&pkt, 3); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 3, 2, 0, 0, // ip4: find, add, del, timeout 1, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -698,7 +698,7 @@ TEST(IPV4_REASSEMBLE, FULL) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif diff --git a/src/ip_reassembly/test/gtest_ipv6_reassembly.cpp b/src/ip_reassembly/test/gtest_ipv6_reassembly.cpp index a106a38..b137cf4 100644 --- a/src/ip_reassembly/test/gtest_ipv6_reassembly.cpp +++ b/src/ip_reassembly/test/gtest_ipv6_reassembly.cpp @@ -608,7 +608,7 @@ TEST(IPV6_REASSEMBLE, NORMAL) struct packet pkt; struct packet *new_pkt; const struct layer *layer; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -616,10 +616,10 @@ TEST(IPV6_REASSEMBLE, NORMAL) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -627,10 +627,10 @@ TEST(IPV6_REASSEMBLE, NORMAL) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 1, 1, 0, 0, // ip6: find, add, del, timeout @@ -638,10 +638,10 @@ TEST(IPV6_REASSEMBLE, NORMAL) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 2, 1, 0, 0, // ip6: find, add, del, timeout @@ -649,10 +649,10 @@ TEST(IPV6_REASSEMBLE, NORMAL) // frag3 packet_parse(&pkt, (const char *)frag3, sizeof(frag3)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 3, 1, 0, 0, // ip6: find, add, del, timeout @@ -660,10 +660,10 @@ TEST(IPV6_REASSEMBLE, NORMAL) // frag4 packet_parse(&pkt, (const char *)frag4, sizeof(frag4)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 4, 1, 1, 0, // ip6: find, add, del, timeout @@ -707,7 +707,7 @@ TEST(IPV6_REASSEMBLE, NORMAL) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -716,7 +716,7 @@ TEST(IPV6_REASSEMBLE, EXPIRE) { struct packet pkt; struct packet *new_pkt; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -724,10 +724,10 @@ TEST(IPV6_REASSEMBLE, EXPIRE) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -735,10 +735,10 @@ TEST(IPV6_REASSEMBLE, EXPIRE) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 1, 1, 0, 0, // ip6: find, add, del, timeout @@ -746,10 +746,10 @@ TEST(IPV6_REASSEMBLE, EXPIRE) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 2); + new_pkt = ip_reassembly_packet(assy, &pkt, 2); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 2, 2, 1, 1, // ip6: find, add, del, timeout @@ -758,7 +758,7 @@ TEST(IPV6_REASSEMBLE, EXPIRE) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -768,7 +768,7 @@ TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG) struct packet pkt; struct packet *new_pkt; const struct layer *layer; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -776,10 +776,10 @@ TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -787,10 +787,10 @@ TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 1, 1, 0, 0, // ip6: find, add, del, timeout @@ -798,10 +798,10 @@ TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 2, 1, 0, 0, // ip6: find, add, del, timeout @@ -809,10 +809,10 @@ TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 3, 1, 0, 0, // ip6: find, add, del, timeout @@ -820,10 +820,10 @@ TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG) // frag3 packet_parse(&pkt, (const char *)frag3, sizeof(frag3)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 4, 1, 0, 0, // ip6: find, add, del, timeout @@ -831,10 +831,10 @@ TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG) // frag4 packet_parse(&pkt, (const char *)frag4, sizeof(frag4)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 5, 1, 1, 0, // ip6: find, add, del, timeout @@ -878,7 +878,7 @@ TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -888,7 +888,7 @@ TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG) struct packet pkt; struct packet *new_pkt; const struct layer *layer; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -896,10 +896,10 @@ TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -907,10 +907,10 @@ TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG) // frag4 packet_parse(&pkt, (const char *)frag4, sizeof(frag4)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 1, 1, 0, 0, // ip6: find, add, del, timeout @@ -918,10 +918,10 @@ TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG) // frag4 packet_parse(&pkt, (const char *)frag4, sizeof(frag4)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 2, 1, 0, 0, // ip6: find, add, del, timeout @@ -929,10 +929,10 @@ TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG) // frag3 packet_parse(&pkt, (const char *)frag3, sizeof(frag3)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 3, 1, 0, 0, // ip6: find, add, del, timeout @@ -940,10 +940,10 @@ TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 4, 1, 0, 0, // ip6: find, add, del, timeout @@ -951,10 +951,10 @@ TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 5, 1, 1, 0, // ip6: find, add, del, timeout @@ -998,7 +998,7 @@ TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -1008,7 +1008,7 @@ TEST(IPV6_REASSEMBLE, FULL) struct packet pkt; struct packet *new_pkt; struct in6_addr src_addr; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -1016,10 +1016,10 @@ TEST(IPV6_REASSEMBLE, FULL) .bucket_num = 1, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -1032,10 +1032,10 @@ TEST(IPV6_REASSEMBLE, FULL) // flow1 memset(&src_addr, 1, sizeof(src_addr)); packet_set_ipv6_src_addr(&pkt, src_addr); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 1, 1, 0, 0, // ip6: find, add, del, timeout @@ -1044,10 +1044,10 @@ TEST(IPV6_REASSEMBLE, FULL) // flow2 memset(&src_addr, 2, sizeof(src_addr)); packet_set_ipv6_src_addr(&pkt, src_addr); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 2, 2, 0, 0, // ip6: find, add, del, timeout @@ -1056,10 +1056,10 @@ TEST(IPV6_REASSEMBLE, FULL) // flow3 memset(&src_addr, 3, sizeof(src_addr)); packet_set_ipv6_src_addr(&pkt, src_addr); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 3, 2, 0, 0, // ip6: find, add, del, timeout @@ -1068,7 +1068,7 @@ TEST(IPV6_REASSEMBLE, FULL) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif @@ -1077,7 +1077,7 @@ TEST(IPV6_REASSEMBLE, OVERLAP) { struct packet pkt; struct packet *new_pkt; - struct ip_reassembly *assembler; + struct ip_reassembly *assy; struct ip_reassembly_options opts = { .enable = true, .timeout = 1, @@ -1085,10 +1085,10 @@ TEST(IPV6_REASSEMBLE, OVERLAP) .bucket_num = 8, }; - assembler = ip_reassembly_new(&opts); - EXPECT_TRUE(assembler != NULL); + assy = ip_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 0, 0, 0, 0, // ip6: find, add, del, timeout @@ -1096,10 +1096,10 @@ TEST(IPV6_REASSEMBLE, OVERLAP) // frag1 packet_parse(&pkt, (const char *)frag1, sizeof(frag1)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 1, 1, 0, 0, // ip6: find, add, del, timeout @@ -1107,10 +1107,10 @@ TEST(IPV6_REASSEMBLE, OVERLAP) // frag2 packet_parse(&pkt, (const char *)frag2, sizeof(frag2)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 2, 1, 0, 0, // ip6: find, add, del, timeout @@ -1121,10 +1121,10 @@ TEST(IPV6_REASSEMBLE, OVERLAP) memcpy(dup_frag, frag3, sizeof(frag3)); packet_parse(&pkt, (const char *)dup_frag, sizeof(dup_frag)); packet_set_ipv6_frag_offset(&pkt, 2048); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 3, 1, 0, 0, // ip6: find, add, del, timeout @@ -1132,10 +1132,10 @@ TEST(IPV6_REASSEMBLE, OVERLAP) // frag4 packet_parse(&pkt, (const char *)frag4, sizeof(frag4)); - new_pkt = ip_reassembly_packet(assembler, &pkt, 1); + new_pkt = ip_reassembly_packet(assy, &pkt, 1); EXPECT_TRUE(new_pkt == NULL); - check_stat(ip_reassembly_get_stat(assembler), + check_stat(ip_reassembly_get_stat(assy), 0, 0, 0, 0, // ip4: find, add, del, timeout 0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag 4, 1, 1, 0, // ip6: find, add, del, timeout @@ -1144,7 +1144,7 @@ TEST(IPV6_REASSEMBLE, OVERLAP) // free packet packet_free(new_pkt); - ip_reassembly_free(assembler); + ip_reassembly_free(assy); } #endif diff --git a/src/tcp_reassembly/tcp_reassembly.cpp b/src/tcp_reassembly/tcp_reassembly.cpp index 45f10e8..0106945 100644 --- a/src/tcp_reassembly/tcp_reassembly.cpp +++ b/src/tcp_reassembly/tcp_reassembly.cpp @@ -6,287 +6,339 @@ #include "tcp_reassembly.h" #include "itree.h" -struct tcp_reassembly -{ - // config - bool enable; - uint32_t max_timeout; - uint32_t max_packets; - uint32_t max_bytes; - - // stat - struct tcp_reassembly_stat stat; - - // runtime - struct itree *c2s_itree; - struct itree *s2c_itree; - uint64_t c2s_exp_seq; - uint64_t s2c_exp_seq; - - // used for timeout - struct segment *head; // del segment from head - struct segment *tail; // add segment to tail -}; - struct segment { - struct tcp_reassembly *assembler; - struct itree *itree; + struct tcp_reassembly *assy; struct segment *next; struct segment *prev; + uint64_t id; uint64_t time; uint32_t offset; uint32_t len; char *payload; // Flexible array member }; -void *segment_dup(void *p) +struct segment_list +{ + struct segment *head; // del segment from head + struct segment *tail; // add segment to tail +}; + +struct tcp_reassembly +{ + struct tcp_reassembly_options opts; + struct tcp_reassembly_stat stat; + struct segment_list list; + + struct itree *itree; + uint64_t exp_seq; +}; + +/* + * The next routines deal with comparing 32 bit unsigned ints + * and worry about wraparound (automatic with unsigned arithmetic). + */ + +static inline bool before(uint32_t seq1, uint32_t seq2) +{ + return (int32_t)(seq1 - seq2) < 0; +} + +static inline void segment_list_add(struct segment_list *list, struct segment *seg) +{ + if (list->head == NULL) + { + list->head = seg; + } + else + { + list->tail->next = seg; + seg->prev = list->tail; + } + list->tail = seg; +} + +static inline void segment_list_del(struct segment_list *list, struct segment *seg) +{ + if (list->head == seg) + { + list->head = seg->next; + } + if (list->tail == seg) + { + list->tail = seg->prev; + } + if (seg->prev) + { + seg->prev->next = seg->next; + } + if (seg->next) + { + seg->next->prev = seg->prev; + } +} + +static inline struct segment *segment_list_get_oldest(struct segment_list *list) +{ + return list->head; +} + +static inline struct segment *segment_new(uint32_t len) +{ + return (struct segment *)calloc(1, sizeof(struct segment) + len); +} + +static inline void *segment_dup(void *p) { return p; } -void segment_rel(void *p) +static inline void segment_free(void *p) { - struct segment *seg = (struct segment *)p; - if (seg) - { - struct tcp_reassembly *assembler = seg->assembler; - // delete from list - if (assembler->head == seg) - { - assembler->head = seg->next; - } - if (assembler->tail == seg) - { - assembler->tail = seg->prev; - } - if (seg->prev) - { - seg->prev->next = seg->next; - } - if (seg->next) - { - seg->next->prev = seg->prev; - } + struct segment *seg = NULL; + struct tcp_reassembly *assy = NULL; - assembler->stat.bytes -= seg->len; - assembler->stat.packets--; + if (p) + { + seg = (struct segment *)p; + assy = seg->assy; + segment_list_del(&assy->list, seg); + + assy->stat.curr_bytes -= seg->len; + assy->stat.curr_segments--; free(seg); } } -struct tcp_reassembly *tcp_reassembly_new(bool enable, uint32_t max_timeout, uint32_t max_packets, uint32_t max_bytes) +struct tcp_reassembly *tcp_reassembly_new(struct tcp_reassembly_options *opts) { - struct tcp_reassembly *assembler = (struct tcp_reassembly *)calloc(1, sizeof(struct tcp_reassembly)); - if (assembler == NULL) + struct tcp_reassembly *assy = NULL; + + assy = (struct tcp_reassembly *)calloc(1, sizeof(struct tcp_reassembly)); + if (assy == NULL) { return NULL; } - assembler->enable = enable; - assembler->max_timeout = max_timeout; - assembler->max_packets = max_packets; - assembler->max_bytes = max_bytes; - if (!assembler->enable) + memcpy(&assy->opts, opts, sizeof(struct tcp_reassembly_options)); + if (!assy->opts.enable) { - return assembler; + return assy; } - assembler->c2s_itree = itree_new(segment_dup, segment_rel); - assembler->s2c_itree = itree_new(segment_dup, segment_rel); - if (assembler->c2s_itree == NULL || assembler->s2c_itree == NULL) + assy->itree = itree_new(segment_dup, segment_free); + if (assy->itree == NULL) { goto error_out; } - return assembler; + return assy; error_out: - tcp_reassembly_free(assembler); + tcp_reassembly_free(assy); return NULL; } -void tcp_reassembly_init(struct tcp_reassembly *assembler, uint32_t c2s_init_seq, uint32_t s2c_init_seq) +void tcp_reassembly_free(struct tcp_reassembly *assy) { - if (!assembler->enable) + if (assy) + { + if (assy->itree) + { + itree_delete(assy->itree); + } + free(assy); + } +} + +void tcp_reassembly_init(struct tcp_reassembly *assy, uint32_t syn_seq) +{ + if (!assy->opts.enable) { return; } - if (c2s_init_seq) - { - assembler->c2s_exp_seq = c2s_init_seq + 1; - } - - if (s2c_init_seq) - { - assembler->s2c_exp_seq = s2c_init_seq + 1; - } + assy->exp_seq = syn_seq + 1; } -void tcp_reassembly_free(struct tcp_reassembly *assembler) +void tcp_reassembly_expire(struct tcp_reassembly *assy, uint64_t now) { - if (assembler) - { - if (assembler->c2s_itree) - { - itree_delete(assembler->c2s_itree); - } - if (assembler->s2c_itree) - { - itree_delete(assembler->s2c_itree); - } - free(assembler); - } -} - -void tcp_reassembly_expire(struct tcp_reassembly *assembler, uint64_t now) -{ - if (!assembler->enable) + if (!assy->opts.enable) { return; } - struct tcp_reassembly_stat *stat = &assembler->stat; - while (assembler->head) + uint64_t high; + interval_t expire; + struct segment *seg = NULL; + + while ((seg = segment_list_get_oldest(&assy->list)) != NULL) { - struct segment *seg = assembler->head; - if (now - seg->time < assembler->max_timeout) + if (seg->time + assy->opts.max_timeout > now) { break; } - stat->tcp_segement_timout++; - - struct itree *itree = seg->itree; - interval_t interval = { + high = (uint64_t)seg->offset + (uint64_t)seg->len - 1; + expire = { .low = seg->offset, - .high = seg->offset + seg->len - 1, + .high = high, + .data = seg, }; - itree_remove(itree, &interval); + 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); + + itree_remove(assy->itree, &expire); } } -void tcp_reassembly_update(struct tcp_reassembly *assembler, int direction, uint32_t offset, const char *payload, uint32_t len, uint64_t now) +void tcp_reassembly_insert(struct tcp_reassembly *assy, uint32_t offset, const char *payload, uint32_t len, uint64_t now) { - if (!assembler->enable) + if (!assy->opts.enable) { return; } - struct itree *itree = (direction == 0x01) ? assembler->c2s_itree : assembler->s2c_itree; - uint64_t exp_seq = (direction == 0x01) ? assembler->c2s_exp_seq : assembler->s2c_exp_seq; + uint64_t low = (uint64_t)offset; + uint64_t high = (uint64_t)offset + (uint64_t)len - 1; // from uint32_t to uint64_t, so no overflow + struct segment *seg = NULL; + interval_t insert; - if (len == 0 || offset + len < exp_seq) + assy->stat.insert_segments++; + assy->stat.insert_bytes += len; + + if (assy->opts.max_segments > 0 && assy->stat.curr_segments >= assy->opts.max_segments) { + 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); return; } - if (assembler->max_packets > 0 && assembler->stat.packets >= assembler->max_packets) + if (assy->opts.max_bytes > 0 && assy->stat.curr_bytes >= assy->opts.max_bytes) { + 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); return; } - if (assembler->max_bytes > 0 && assembler->stat.bytes >= assembler->max_bytes) + if (len == 0 || before(offset + len, assy->exp_seq)) { + 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); return; } - struct segment *seg = (struct segment *)calloc(1, sizeof(struct segment) + len); + seg = segment_new(len); if (seg == NULL) { return; } - seg->itree = itree; - seg->assembler = assembler; + seg->assy = assy; + seg->id = assy->stat.insert_segments; seg->time = now; seg->offset = offset; seg->len = len; seg->payload = (char *)seg + sizeof(struct segment); memcpy(seg->payload, payload, len); - - interval_t interval = { - .low = seg->offset, - .high = seg->offset + seg->len - 1, + insert = { + .low = low, + .high = high, .data = seg, }; - if (itree_insert(itree, &interval) == 0) + if (itree_insert(assy->itree, &insert) == 0) { free(seg); return; } - TCP_REASSEMBLE_DEBUG("%s insert [%lu, %lu], segment {ptr: %p, offset: %lu, len: %lu}", - (direction == 0x01) ? "C2S" : "S2C", - seg->offset, seg->offset + seg->len - 1, - seg, seg->offset, seg->len); + TCP_REASSEMBLE_DEBUG("insert %p [%lu, %lu]", seg, insert.low, insert.high); - if (assembler->head == NULL) - { - assembler->head = seg; - } - else - { - assembler->tail->next = seg; - seg->prev = assembler->tail; - } - assembler->tail = seg; + segment_list_add(&assy->list, seg); - assembler->stat.packets++; - assembler->stat.bytes += len; - - tcp_reassembly_expire(assembler, now); + assy->stat.curr_segments++; + assy->stat.curr_bytes += seg->len; } -const char *tcp_reassembly_peek(struct tcp_reassembly *assembler, int direction, uint32_t *len) +const char *tcp_reassembly_peek(struct tcp_reassembly *assy, uint32_t *len) { *len = 0; - if (!assembler->enable) + if (!assy->opts.enable) { return NULL; } - struct itree *itree = (direction == 0x01) ? assembler->c2s_itree : assembler->s2c_itree; - uint64_t exp_seq = (direction == 0x01) ? assembler->c2s_exp_seq : assembler->s2c_exp_seq; + int count = 0; + interval_t peek; + uint64_t overlap = 0; + uint64_t min_id = UINT64_MAX; + struct segment *seg = NULL; + ilist_t *list = NULL; + ilisttrav_t *trav = NULL; + interval_t *query = NULL; + interval_t *oldest = NULL; - interval_t interval = { - .low = exp_seq, - .high = exp_seq, + peek = { + .low = assy->exp_seq, + .high = assy->exp_seq, }; - interval_t *result = itree_find(itree, &interval); - if (result == NULL) + + list = itree_findall(assy->itree, &peek); + if (list == NULL) { - TCP_REASSEMBLE_DEBUG("%s peek [%lu, +∞]: not found", (direction == 0x01) ? "C2S" : "S2C", exp_seq); return NULL; } - struct segment *seg = (struct segment *)result->data; - assert(seg != NULL); - // check overlap - if (seg->offset < exp_seq) + count = ilist_size(list); + trav = ilisttrav_new(list); + for (int i = 0; i < count; i++) { - TCP_REASSEMBLE_DEBUG("%s peek [%lu, +∞], found [%lu, %lu], segment {ptr: %p, offset: %lu, len: %lu, left trim: %lu}", - (direction == 0x01) ? "C2S" : "S2C", exp_seq, - seg->offset, seg->offset + seg->len - 1, - seg, seg->offset, seg->len, exp_seq - seg->offset); - *len = seg->len - (exp_seq - seg->offset); - return seg->payload + (exp_seq - seg->offset); + if (i == 0) + { + query = (interval_t *)ilisttrav_first(trav); + } + else + { + query = (interval_t *)ilisttrav_next(trav); + } + seg = (struct segment *)query->data; + if (seg->id < min_id) + { + min_id = seg->id; + oldest = query; + } } - TCP_REASSEMBLE_DEBUG("%s peek [%lu, +∞], found [%lu, %lu], segment {ptr: %p, offset: %lu, len: %lu}", - (direction == 0x01) ? "C2S" : "S2C", exp_seq, - seg->offset, seg->offset + seg->len - 1, - seg, seg->offset, seg->len); + ilisttrav_delete(trav); + ilist_delete(list); + + if (oldest == NULL) + { + return NULL; + } + + seg = (struct segment *)oldest->data; + if (seg->offset < assy->exp_seq) + { + 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); + return seg->payload + overlap; + } + TCP_REASSEMBLE_DEBUG("peek [%lu, +∞], found %p [%lu, %lu]", assy->exp_seq, seg, oldest->low, oldest->high); *len = seg->len; return seg->payload; } -void tcp_reassembly_consume(struct tcp_reassembly *assembler, int direction, uint32_t len) +void tcp_reassembly_consume(struct tcp_reassembly *assy, uint32_t len) { - if (!assembler->enable) + if (!assy->opts.enable) { return; } @@ -296,55 +348,85 @@ void tcp_reassembly_consume(struct tcp_reassembly *assembler, int direction, uin return; } - struct itree *itree = (direction == 0x01) ? assembler->c2s_itree : assembler->s2c_itree; - uint64_t *exp_seq = (direction == 0x01) ? &assembler->c2s_exp_seq : &assembler->s2c_exp_seq; - uint64_t old_exp_seq = *exp_seq; + int count; + uint64_t old_exp_seq; + uint64_t new_exp_seq; + interval_t consume; + ilist_t *list = NULL; + interval_t *del = NULL; + ilisttrav_t *trav = NULL; + struct segment *seg = NULL; - *exp_seq += len; - uint64_t new_exp_seq = *exp_seq; + old_exp_seq = assy->exp_seq; + assy->exp_seq += len; + if (assy->exp_seq > UINT32_MAX) + { + assy->exp_seq = assy->exp_seq % UINT32_MAX; + } + new_exp_seq = assy->exp_seq; - TCP_REASSEMBLE_DEBUG("%s consume [%lu, %lu], update expect seq %lu -> %lu", - (direction == 0x01) ? "C2S" : "S2C", - old_exp_seq, new_exp_seq - 1, old_exp_seq, new_exp_seq); - - interval_t interval = { - .low = 0, - .high = *exp_seq, - }; - - ilist_t *list = itree_findall(itree, &interval); + 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); + consume = + { + .low = old_exp_seq, + .high = old_exp_seq + len - 1, + }; + list = itree_findall(assy->itree, &consume); if (list == NULL) { return; } - interval_t *result; - int count = ilist_size(list); - ilisttrav_t *trav = ilisttrav_new(list); + assy->stat.consume_segments++; + assy->stat.consume_bytes += len; + + count = ilist_size(list); + trav = ilisttrav_new(list); for (int i = 0; i < count; i++) { if (i == 0) { - result = (interval_t *)ilisttrav_first(trav); + del = (interval_t *)ilisttrav_first(trav); } else { - result = (interval_t *)ilisttrav_next(trav); + del = (interval_t *)ilisttrav_next(trav); } - if (result && result->high < *exp_seq) + if (del && before(del->high, new_exp_seq)) { - struct segment *seg = (struct segment *)result->data; - TCP_REASSEMBLE_DEBUG("%s consume [%lu, %lu], delete [%lu, %lu], segment {ptr: %p, offset: %lu, len: %lu}", - (direction == 0x01) ? "C2S" : "S2C", old_exp_seq, new_exp_seq - 1, - result->low, result->high, seg, seg->offset, seg->len); - itree_remove(itree, result); + 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); + itree_remove(assy->itree, del); } } ilisttrav_delete(trav); ilist_delete(list); } -struct tcp_reassembly_stat *tcp_reassembly_get_stat(struct tcp_reassembly *assembler) +struct tcp_reassembly_stat *tcp_reassembly_get_stat(struct tcp_reassembly *assy) { - return NULL; -} \ No newline at end of file + if (!assy->opts.enable) + { + return NULL; + } + + return &assy->stat; +} + +void tcp_reassembly_print_stat(struct tcp_reassembly *assy) +{ + if (!assy->opts.enable) + { + 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); +} diff --git a/src/tcp_reassembly/tcp_reassembly.h b/src/tcp_reassembly/tcp_reassembly.h index cb55173..bdccf5b 100644 --- a/src/tcp_reassembly/tcp_reassembly.h +++ b/src/tcp_reassembly/tcp_reassembly.h @@ -13,30 +13,55 @@ extern "C" #define TCP_REASSEMBLE_DEBUG(format, ...) LOG_DEBUG("tcp_reassembly", format, ##__VA_ARGS__) #define TCP_REASSEMBLE_ERROR(format, ...) LOG_ERROR("tcp_reassembly", format, ##__VA_ARGS__) -struct tcp_reassembly_stat -{ - uint64_t packets; // current packets - uint64_t bytes; // current bytes - - uint64_t tcp_segement_timout; // total tcp segment timeout -}; - /* * If retransmission or overlap occurs, the old data packet may have been consumed by the upper-layer plug-in, * so the old data packet takes priority and the new data packet will be bypassed. */ -struct tcp_reassembly *tcp_reassembly_new(bool enable, uint32_t max_timeout, uint32_t max_packets, uint32_t max_bytes); -void tcp_reassembly_init(struct tcp_reassembly *assembler, uint32_t c2s_init_seq, uint32_t s2c_init_seq); -void tcp_reassembly_free(struct tcp_reassembly *assembler); -void tcp_reassembly_expire(struct tcp_reassembly *assembler, uint64_t now); +struct tcp_reassembly_options +{ + bool enable; + uint32_t max_timeout; + uint32_t max_segments; + uint32_t max_bytes; +}; -// direction: 1 C2S; 2: S2C -void tcp_reassembly_update(struct tcp_reassembly *assembler, int direction, uint32_t offset, const char *payload, uint32_t len, uint64_t now); -const char *tcp_reassembly_peek(struct tcp_reassembly *assembler, int direction, uint32_t *len); -void tcp_reassembly_consume(struct tcp_reassembly *assembler, int direction, uint32_t len); +struct tcp_reassembly_stat +{ + uint64_t curr_segments; + uint64_t curr_bytes; -struct tcp_reassembly_stat *tcp_reassembly_get_stat(struct tcp_reassembly *assembler); + uint64_t insert_segments; + uint64_t insert_bytes; + + uint64_t remove_segments; + uint64_t remove_bytes; + + uint64_t consume_segments; + uint64_t consume_bytes; + + uint64_t retrans_bypass_segments; + uint64_t retrans_bypass_bytes; + + uint64_t overload_bypass_segments; + uint64_t overload_bypass_bytes; + + uint64_t timeout_discard_segments; + uint64_t timeout_discard_bytes; +}; + +struct tcp_reassembly *tcp_reassembly_new(struct tcp_reassembly_options *opts); +void tcp_reassembly_free(struct tcp_reassembly *assy); + +void tcp_reassembly_init(struct tcp_reassembly *assy, uint32_t syn_seq); +void tcp_reassembly_expire(struct tcp_reassembly *assy, uint64_t now); + +void tcp_reassembly_insert(struct tcp_reassembly *assy, uint32_t seq, const char *payload, uint32_t len, uint64_t now); +const char *tcp_reassembly_peek(struct tcp_reassembly *assy, uint32_t *len); +void tcp_reassembly_consume(struct tcp_reassembly *assy, uint32_t len); + +struct tcp_reassembly_stat *tcp_reassembly_get_stat(struct tcp_reassembly *assy); +void tcp_reassembly_print_stat(struct tcp_reassembly *assy); #ifdef __cpluscplus } diff --git a/src/tcp_reassembly/test/gtest_tcp_reassembly.cpp b/src/tcp_reassembly/test/gtest_tcp_reassembly.cpp index 9c1ed43..64dfc62 100644 --- a/src/tcp_reassembly/test/gtest_tcp_reassembly.cpp +++ b/src/tcp_reassembly/test/gtest_tcp_reassembly.cpp @@ -2,34 +2,92 @@ #include "tcp_reassembly.h" +static void tcp_reassembly_check_stat(struct tcp_reassembly *assy, + uint64_t curr_segments, uint64_t curr_bytes, + uint64_t insert_segments, uint64_t insert_bytes, + uint64_t remove_segments, uint64_t remove_bytes, + uint64_t consume_segments, uint64_t consume_bytes, + uint64_t retrans_bypass_segments, uint64_t retrans_bypass_bytes, + uint64_t overload_bypass_segments, uint64_t overload_bypass_bytes, + uint64_t timeout_discard_segments, uint64_t timeout_discard_bytes) +{ + struct tcp_reassembly_stat *stat = tcp_reassembly_get_stat(assy); + EXPECT_TRUE(stat != NULL); + EXPECT_TRUE(stat->curr_segments == curr_segments); + EXPECT_TRUE(stat->curr_bytes == curr_bytes); + EXPECT_TRUE(stat->insert_segments == insert_segments); + EXPECT_TRUE(stat->insert_bytes == insert_bytes); + EXPECT_TRUE(stat->remove_segments == remove_segments); + EXPECT_TRUE(stat->remove_bytes == remove_bytes); + EXPECT_TRUE(stat->consume_segments == consume_segments); + EXPECT_TRUE(stat->consume_bytes == consume_bytes); + EXPECT_TRUE(stat->retrans_bypass_segments == retrans_bypass_segments); + EXPECT_TRUE(stat->retrans_bypass_bytes == retrans_bypass_bytes); + EXPECT_TRUE(stat->overload_bypass_segments == overload_bypass_segments); + EXPECT_TRUE(stat->overload_bypass_bytes == overload_bypass_bytes); + EXPECT_TRUE(stat->timeout_discard_segments == timeout_discard_segments); + 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); - struct tcp_reassembly *assembler = session_get_tcp_reassembly(session); - return tcp_reassembly_peek(assembler, dir, len); + + 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); - struct tcp_reassembly *assembler = session_get_tcp_reassembly(session); - tcp_reassembly_consume(assembler, dir, len); + + 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_C2S) +TEST(TCP_REASSEMBLY, TEST) { uint32_t len; - int dir = 1; const char *ptr; - struct tcp_reassembly *assembler; + struct tcp_reassembly *assy; + struct tcp_reassembly_options opts = + { + .enable = true, + .max_timeout = 10, + .max_segments = 16, + .max_bytes = 1500}; - assembler = tcp_reassembly_new(1, 10, 16, 1500); - EXPECT_TRUE(assembler != NULL); + assy = tcp_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 0, 0, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_init(assembler, 99, 199); + tcp_reassembly_init(assy, 99); /* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -39,82 +97,71 @@ TEST(TCP_REASSEMBLY, TEST_C2S) * +---> 90 +---> 100 +---> 110 */ - // C2S - tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); - tcp_reassembly_update(assembler, dir, 100, (const char *)"abcdefghij", 10, 0); - tcp_reassembly_update(assembler, dir, 110, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_insert(assy, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 1, 10, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 2, 20, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 110, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_check_stat(assy, + 3, 30, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr != NULL); EXPECT_TRUE(len == 10); EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr != NULL); EXPECT_TRUE(len == 10); EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); - tcp_reassembly_consume(assembler, dir, len); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 1, 10, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr != NULL); EXPECT_TRUE(len == 10); EXPECT_TRUE(memcmp(ptr, "ABCDEFGHIJ", len) == 0); - tcp_reassembly_consume(assembler, dir, len); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 2, 20, // remove_segments, remove_bytes + 2, 20, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr == NULL); - tcp_reassembly_free(assembler); -} -#endif - -#if 1 -TEST(TCP_REASSEMBLY, TEST_S2C) -{ - uint32_t len; - int dir = 2; - const char *ptr; - struct tcp_reassembly *assembler; - - assembler = tcp_reassembly_new(1, 10, 16, 1500); - EXPECT_TRUE(assembler != NULL); - - tcp_reassembly_init(assembler, 199, 99); - - /* - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|A|B|C|D|E|F|G|H|I|J| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | - * +---> 90 +---> 100 +---> 110 - */ - - // C2S - tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); - tcp_reassembly_update(assembler, dir, 100, (const char *)"abcdefghij", 10, 0); - tcp_reassembly_update(assembler, dir, 110, (const char *)"ABCDEFGHIJ", 10, 0); - - ptr = tcp_reassembly_peek(assembler, dir, &len); - EXPECT_TRUE(ptr != NULL); - EXPECT_TRUE(len == 10); - EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); - - ptr = tcp_reassembly_peek(assembler, dir, &len); - EXPECT_TRUE(ptr != NULL); - EXPECT_TRUE(len == 10); - EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); - tcp_reassembly_consume(assembler, dir, len); - - ptr = tcp_reassembly_peek(assembler, dir, &len); - EXPECT_TRUE(ptr != NULL); - EXPECT_TRUE(len == 10); - EXPECT_TRUE(memcmp(ptr, "ABCDEFGHIJ", len) == 0); - tcp_reassembly_consume(assembler, dir, len); - - ptr = tcp_reassembly_peek(assembler, dir, &len); - EXPECT_TRUE(ptr == NULL); - - tcp_reassembly_free(assembler); + tcp_reassembly_free(assy); } #endif @@ -122,14 +169,27 @@ TEST(TCP_REASSEMBLY, TEST_S2C) TEST(TCP_REASSEMBLY, REPEAT1) { uint32_t len; - int dir = 1; const char *ptr; - struct tcp_reassembly *assembler; + struct tcp_reassembly *assy; + struct tcp_reassembly_options opts = + { + .enable = true, + .max_timeout = 10, + .max_segments = 16, + .max_bytes = 1500}; - assembler = tcp_reassembly_new(1, 10, 16, 1500); - EXPECT_TRUE(assembler != NULL); + assy = tcp_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 0, 0, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_init(assembler, 99, 199); + tcp_reassembly_init(assy, 99); /* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -141,21 +201,52 @@ TEST(TCP_REASSEMBLY, REPEAT1) * +---> 90 +---> 100 +---> 109 */ - // C2S - tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); - tcp_reassembly_update(assembler, dir, 100, (const char *)"abcdefghij", 10, 0); - tcp_reassembly_update(assembler, dir, 100, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_insert(assy, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 1, 10, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 2, 20, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_check_stat(assy, + 3, 30, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr != NULL); EXPECT_TRUE(len == 10); EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); - tcp_reassembly_consume(assembler, dir, len); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 2, 20, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr == NULL); - tcp_reassembly_free(assembler); + tcp_reassembly_free(assy); } #endif @@ -163,14 +254,27 @@ TEST(TCP_REASSEMBLY, REPEAT1) TEST(TCP_REASSEMBLY, REPEAT2) { uint32_t len; - int dir = 1; const char *ptr; - struct tcp_reassembly *assembler; + struct tcp_reassembly *assy; + struct tcp_reassembly_options opts = + { + .enable = true, + .max_timeout = 10, + .max_segments = 16, + .max_bytes = 1500}; - assembler = tcp_reassembly_new(1, 10, 16, 1500); - EXPECT_TRUE(assembler != NULL); + assy = tcp_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 0, 0, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_init(assembler, 99, 199); + tcp_reassembly_init(assy, 99); /* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -184,20 +288,52 @@ TEST(TCP_REASSEMBLY, REPEAT2) // C2S - tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); - tcp_reassembly_update(assembler, dir, 100, (const char *)"ABCDEFGHIJ", 10, 0); - tcp_reassembly_update(assembler, dir, 100, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_insert(assy, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 1, 10, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 2, 20, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_check_stat(assy, + 3, 30, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr != NULL); EXPECT_TRUE(len == 10); EXPECT_TRUE(memcmp(ptr, "ABCDEFGHIJ", len) == 0); - tcp_reassembly_consume(assembler, dir, len); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 2, 20, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr == NULL); - tcp_reassembly_free(assembler); + tcp_reassembly_free(assy); } #endif @@ -205,14 +341,27 @@ TEST(TCP_REASSEMBLY, REPEAT2) TEST(TCP_REASSEMBLY, OVERLAP) { uint32_t len; - int dir = 1; const char *ptr; - struct tcp_reassembly *assembler; + struct tcp_reassembly *assy; + struct tcp_reassembly_options opts = + { + .enable = true, + .max_timeout = 10, + .max_segments = 16, + .max_bytes = 1500}; - assembler = tcp_reassembly_new(1, 10, 16, 1500); - EXPECT_TRUE(assembler != NULL); + assy = tcp_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 0, 0, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_init(assembler, 89, 199); + tcp_reassembly_init(assy, 89); /* * +-+-+-+-+-+-+-+-+-+-+ @@ -237,61 +386,589 @@ TEST(TCP_REASSEMBLY, OVERLAP) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - // C2S - tcp_reassembly_update(assembler, dir, 90, (const char *)"0123456789", 10, 0); - tcp_reassembly_update(assembler, dir, 96, (const char *)"abcdefghij", 10, 0); - tcp_reassembly_update(assembler, dir, 102, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_insert(assy, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 1, 10, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 96, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 2, 20, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 102, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_check_stat(assy, + 3, 30, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr != NULL); EXPECT_TRUE(len == 10); EXPECT_TRUE(memcmp(ptr, "0123456789", len) == 0); - tcp_reassembly_consume(assembler, dir, len); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 1, 10, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr != NULL); EXPECT_TRUE(len == 6); EXPECT_TRUE(memcmp(ptr, "efghij", len) == 0); - tcp_reassembly_consume(assembler, dir, len); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 2, 20, // remove_segments, remove_bytes + 2, 16, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr != NULL); EXPECT_TRUE(len == 6); EXPECT_TRUE(memcmp(ptr, "EFGHIJ", len) == 0); - tcp_reassembly_consume(assembler, dir, len); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 3, 30, // remove_segments, remove_bytes + 3, 22, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes - ptr = tcp_reassembly_peek(assembler, dir, &len); + ptr = tcp_reassembly_peek(assy, &len); EXPECT_TRUE(ptr == NULL); - tcp_reassembly_free(assembler); -} -#endif - -#if 1 -TEST(TCP_REASSEMBLY, MAX_TIMEOUT) -{ - // TODO -} -#endif - -#if 1 -TEST(TCP_REASSEMBLY, MAX_PACKETS) -{ - // TODO -} -#endif - -#if 1 -TEST(TCP_REASSEMBLY, MAX_BYTES) -{ - // TODO + tcp_reassembly_free(assy); } #endif #if 1 TEST(TCP_REASSEMBLY, SEQ_WRAPAROUND) { - // TODO + uint32_t len; + const char *ptr; + struct tcp_reassembly *assy; + struct tcp_reassembly_options opts = + { + .enable = true, + .max_timeout = 10, + .max_segments = 16, + .max_bytes = 1500}; + + printf("UINT32_MAX = %u\n", UINT32_MAX); + + assy = tcp_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 0, 0, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_init(assy, UINT32_MAX - 11); + + /* + * +-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9| + * +-+-+-+-+-+-+-+-+-+-+ + * | +-+-+-+-+-+-+-+-+-+-+ + * | |a|b|c|d|e|f|g|h|i|j| + * | +-+-+-+-+-+-+-+-+-+-+ + * | | | +-+-+-+-+-+-+-+-+-+-+ + * | | | |A|B|C|D|E|F|G|H|I|J| + * | | | +-+-+-+-+-+-+-+-+-+-+ + * | | | | | | + * | | | | | +---> UINT32_MAX + 11 + * | | | | +---> UINT32_MAX + 5 + * | | | +---> UINT32_MAX + 2 + * | | +---> UINT32_MAX - 1 + * | +---> UINT32_MAX - 4 + * +---> UINT32_MAX - 10 + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|e|f|g|h|i|j|E|F|G|H|I|J| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + tcp_reassembly_insert(assy, UINT32_MAX - 10, (const char *)"0123456789", 10, 0); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 1, 10, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, UINT32_MAX - 4, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 2, 20, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_check_stat(assy, + 3, 30, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "0123456789", len) == 0); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 1, 10, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 6); + EXPECT_TRUE(memcmp(ptr, "efghij", len) == 0); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 2, 20, // remove_segments, remove_bytes + 2, 16, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 6); + EXPECT_TRUE(memcmp(ptr, "EFGHIJ", len) == 0); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 3, 30, // remove_segments, remove_bytes + 3, 22, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr == NULL); + + tcp_reassembly_free(assy); +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, MAX_TIMEOUT1) +{ + uint32_t len; + const char *ptr; + struct tcp_reassembly *assy; + struct tcp_reassembly_options opts = + { + .enable = true, + .max_timeout = 10, + .max_segments = 16, + .max_bytes = 1500}; + + assy = tcp_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 0, 0, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_init(assy, 99); + + /* + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | |A|B|C|D|E|F|G|H|I|J| + * | +-+-+-+-+-+-+-+-+-+-+ + * | | | + * +---> 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 + 1, 10, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"abcdefghij", 10, 1); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 2, 20, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"ABCDEFGHIJ", 10, 2); + tcp_reassembly_check_stat(assy, + 3, 30, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_expire(assy, 11); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 2, 20); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "ABCDEFGHIJ", len) == 0); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 1, 10, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 2, 20); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr == NULL); + + tcp_reassembly_free(assy); +} +#endif + +#if 1 +// expire after consume +TEST(TCP_REASSEMBLY, MAX_TIMEOUT2) +{ + uint32_t len; + const char *ptr; + struct tcp_reassembly *assy; + struct tcp_reassembly_options opts = + { + .enable = true, + .max_timeout = 10, + .max_segments = 16, + .max_bytes = 1500}; + + assy = tcp_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 0, 0, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_init(assy, 89); + + /* + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | |A|B|C|D|E|F|G|H|I|J| + * | +-+-+-+-+-+-+-+-+-+-+ + * | | | + * +---> 90 +---> 100 +---> 109 + */ + + tcp_reassembly_insert(assy, 90, (const char *)"0123456789", 10, 0); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 1, 10, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"abcdefghij", 10, 1); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 2, 20, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"ABCDEFGHIJ", 10, 2); + tcp_reassembly_check_stat(assy, + 3, 30, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "0123456789", len) == 0); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 1, 10, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 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_expire(assy, 11); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 1, 10, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 1, 10); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "ABCDEFGHIJ", len) == 0); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 2, 20, // remove_segments, remove_bytes + 2, 20, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 0, 0, // overload_bypass_segments, overload_bypass_bytes + 1, 10); // timeout_discard_segments, timeout_discard_bytes + + tcp_reassembly_free(assy); +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, MAX_PACKETS) +{ + uint32_t len; + const char *ptr; + struct tcp_reassembly *assy; + struct tcp_reassembly_options opts = + { + .enable = true, + .max_timeout = 10, + .max_segments = 2, + .max_bytes = 1500}; + + assy = tcp_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 0, 0, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_init(assy, 99); + + /* + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|A|B|C|D|E|F|G|H|I|J| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | + * +---> 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 + 1, 10, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 2, 20, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 110, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 1, 10, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 1, 10, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 1, 10, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr == NULL); + + tcp_reassembly_free(assy); +} +#endif + +#if 1 +TEST(TCP_REASSEMBLY, MAX_BYTES) +{ + uint32_t len; + const char *ptr; + struct tcp_reassembly *assy; + struct tcp_reassembly_options opts = + { + .enable = true, + .max_timeout = 10, + .max_segments = 16, + .max_bytes = 20}; + + assy = tcp_reassembly_new(&opts); + EXPECT_TRUE(assy != NULL); + tcp_reassembly_check_stat(assy, + 0, 0, // curr_segments, curr_bytes + 0, 0, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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_init(assy, 99); + + /* + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|A|B|C|D|E|F|G|H|I|J| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | + * +---> 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 + 1, 10, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 100, (const char *)"abcdefghij", 10, 0); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 2, 20, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 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, 110, (const char *)"ABCDEFGHIJ", 10, 0); + tcp_reassembly_check_stat(assy, + 2, 20, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 0, 0, // remove_segments, remove_bytes + 0, 0, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 1, 10, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr != NULL); + EXPECT_TRUE(len == 10); + EXPECT_TRUE(memcmp(ptr, "abcdefghij", len) == 0); + tcp_reassembly_consume(assy, len); + tcp_reassembly_check_stat(assy, + 1, 10, // curr_segments, curr_bytes + 3, 30, // insert_segments, insert_bytes + 1, 10, // remove_segments, remove_bytes + 1, 10, // consume_segments, consume_bytes + 0, 0, // retrans_bypass_segments, retrans_bypass_bytes + 1, 10, // overload_bypass_segments, overload_bypass_bytes + 0, 0); // timeout_discard_segments, timeout_discard_bytes + + ptr = tcp_reassembly_peek(assy, &len); + EXPECT_TRUE(ptr == NULL); + + tcp_reassembly_free(assy); } #endif