feature: packet IO support IP reassembly

This commit is contained in:
luwenpeng
2024-10-23 10:01:20 +08:00
parent a7b79a0e22
commit fd3cc20554
54 changed files with 3474 additions and 4271 deletions

View File

@@ -1,4 +1,49 @@
#include "gtest_utils.h"
#include <gtest/gtest.h>
#include "packet_parser.h"
#include "packet_helper.h"
#include "packet_internal.h"
#include "ip_reassembly.h"
static inline void packet_overwrite_v4_saddr(struct packet *pkt, uint32_t saddr)
{
const struct layer_private *ipv4_layer = packet_get_innermost_layer(pkt, LAYER_PROTO_IPV4);
EXPECT_TRUE(ipv4_layer);
struct ip *hdr = (struct ip *)ipv4_layer->hdr_ptr;
ip4_hdr_set_src_addr(hdr, saddr);
}
static inline void stat_cmp(struct ip_reassembly_stat *curr, struct ip_reassembly_stat *expect)
{
EXPECT_TRUE(curr != NULL);
EXPECT_TRUE(expect != NULL);
EXPECT_TRUE(curr->ip4_defrags_expected == expect->ip4_defrags_expected);
EXPECT_TRUE(curr->ip4_defrags_succeed == expect->ip4_defrags_succeed);
EXPECT_TRUE(curr->ip4_defrags_failed == expect->ip4_defrags_failed);
EXPECT_TRUE(curr->ip4_frags == expect->ip4_frags);
EXPECT_TRUE(curr->ip4_frags_freed == expect->ip4_frags_freed);
EXPECT_TRUE(curr->ip4_frags_buffered == expect->ip4_frags_buffered);
EXPECT_TRUE(curr->ip4_frags_no_buffer == expect->ip4_frags_no_buffer);
EXPECT_TRUE(curr->ip4_frags_timeout == expect->ip4_frags_timeout);
EXPECT_TRUE(curr->ip4_frags_invalid_length == expect->ip4_frags_invalid_length);
EXPECT_TRUE(curr->ip4_frags_overlap == expect->ip4_frags_overlap);
EXPECT_TRUE(curr->ip4_frags_too_many == expect->ip4_frags_too_many);
EXPECT_TRUE(curr->ip6_defrags_expected == expect->ip6_defrags_expected);
EXPECT_TRUE(curr->ip6_defrags_succeed == expect->ip6_defrags_succeed);
EXPECT_TRUE(curr->ip6_defrags_failed == expect->ip6_defrags_failed);
EXPECT_TRUE(curr->ip6_frags == expect->ip6_frags);
EXPECT_TRUE(curr->ip6_frags_freed == expect->ip6_frags_freed);
EXPECT_TRUE(curr->ip6_frags_buffered == expect->ip6_frags_buffered);
EXPECT_TRUE(curr->ip6_frags_no_buffer == expect->ip6_frags_no_buffer);
EXPECT_TRUE(curr->ip6_frags_timeout == expect->ip6_frags_timeout);
EXPECT_TRUE(curr->ip6_frags_invalid_length == expect->ip6_frags_invalid_length);
EXPECT_TRUE(curr->ip6_frags_overlap == expect->ip6_frags_overlap);
EXPECT_TRUE(curr->ip6_frags_too_many == expect->ip6_frags_too_many);
}
/*
* Frame 4: 60 bytes on wire (480 bits), 60 bytes captured (480 bits)
@@ -194,60 +239,58 @@ unsigned char expect[] = {
#if 1
TEST(IPV4_REASSEMBLE, PADDING_ORDER)
{
struct packet pkt;
struct packet *new_pkt;
struct packet frag_pkt1 = {};
struct packet frag_pkt2 = {};
struct packet *frag_pkt = NULL;
struct packet *defrag_pkt = NULL;
const struct layer_private *layer;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 1024, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
stat_cmp(curr_stat, &expect_stat);
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
1, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt1, (const char *)frag1, sizeof(frag1));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
1, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt);
check_stat(ip_reassembly_stat(assy),
1, 1, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 2, 2, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt2, (const char *)frag2, sizeof(frag2));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt2, 1);
EXPECT_TRUE(defrag_pkt);
expect_stat = {
1, 1, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
2, 2, 2, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// check packet
packet_print(new_pkt);
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
EXPECT_TRUE(defrag_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
EXPECT_TRUE(defrag_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(defrag_pkt->data_ptr, expect, defrag_pkt->data_len) == 0);
// check IPv4
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_IPV4);
layer = packet_get_innermost_layer(defrag_pkt, LAYER_PROTO_IPV4);
EXPECT_TRUE(layer);
struct ip *hdr = (struct ip *)layer->hdr_ptr;
EXPECT_TRUE(ip4_hdr_get_version(hdr) == 4);
@@ -266,7 +309,7 @@ TEST(IPV4_REASSEMBLE, PADDING_ORDER)
EXPECT_TRUE(ip4_hdr_get_opt_data(hdr) == NULL);
// check TCP
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_TCP);
layer = packet_get_innermost_layer(defrag_pkt, LAYER_PROTO_TCP);
EXPECT_TRUE(layer);
struct tcphdr *tcp_hdr = (struct tcphdr *)layer->hdr_ptr;
EXPECT_TRUE(tcp_hdr_get_src_port(tcp_hdr) == 62629);
@@ -282,69 +325,89 @@ TEST(IPV4_REASSEMBLE, PADDING_ORDER)
EXPECT_TRUE(tcp_hdr_get_opt_data(tcp_hdr) == NULL);
// free packet
packet_free(new_pkt);
EXPECT_TRUE(packet_is_defraged(defrag_pkt));
ip_reassembly_free(assy);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt);
packet_free(frag_pkt);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt);
packet_free(frag_pkt);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt == NULL);
packet_free(defrag_pkt);
EXPECT_TRUE(ip_reassembly_clean(ip_reass, 2) == NULL);
expect_stat = {
1, 1, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
2, 2, 2, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
ip_reassembly_free(ip_reass);
}
#endif
#if 1
TEST(IPV4_REASSEMBLE, PADDING_UNORDER)
{
struct packet pkt;
struct packet *new_pkt;
struct packet frag_pkt1 = {};
struct packet frag_pkt2 = {};
struct packet *frag_pkt = NULL;
struct packet *defrag_pkt = NULL;
const struct layer_private *layer;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 1024, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
stat_cmp(curr_stat, &expect_stat);
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
1, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt2, (const char *)frag2, sizeof(frag2));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt2, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
1, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt);
check_stat(ip_reassembly_stat(assy),
1, 1, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 2, 2, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt1, (const char *)frag1, sizeof(frag1));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt);
expect_stat = {
1, 1, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
2, 2, 2, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// check packet
packet_print(new_pkt);
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
EXPECT_TRUE(defrag_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
EXPECT_TRUE(defrag_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(defrag_pkt->data_ptr, expect, defrag_pkt->data_len) == 0);
// check IPv4
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_IPV4);
layer = packet_get_innermost_layer(defrag_pkt, LAYER_PROTO_IPV4);
EXPECT_TRUE(layer);
struct ip *hdr = (struct ip *)layer->hdr_ptr;
EXPECT_TRUE(ip4_hdr_get_version(hdr) == 4);
@@ -363,7 +426,7 @@ TEST(IPV4_REASSEMBLE, PADDING_UNORDER)
EXPECT_TRUE(ip4_hdr_get_opt_data(hdr) == NULL);
// check TCP
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_TCP);
layer = packet_get_innermost_layer(defrag_pkt, LAYER_PROTO_TCP);
EXPECT_TRUE(layer);
struct tcphdr *tcp_hdr = (struct tcphdr *)layer->hdr_ptr;
EXPECT_TRUE(tcp_hdr_get_src_port(tcp_hdr) == 62629);
@@ -379,358 +442,308 @@ TEST(IPV4_REASSEMBLE, PADDING_UNORDER)
EXPECT_TRUE(tcp_hdr_get_opt_data(tcp_hdr) == NULL);
// free packet
packet_free(new_pkt);
EXPECT_TRUE(packet_is_defraged(defrag_pkt));
ip_reassembly_free(assy);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt);
packet_free(frag_pkt);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt);
packet_free(frag_pkt);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt == NULL);
packet_free(defrag_pkt);
EXPECT_TRUE(ip_reassembly_clean(ip_reass, 2) == NULL);
expect_stat = {
1, 1, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
2, 2, 2, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
ip_reassembly_free(ip_reass);
}
#endif
#if 1
TEST(IPV4_REASSEMBLE, EXPIRE)
{
struct packet pkt;
struct packet *new_pkt;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct packet frag_pkt1 = {};
struct packet *defrag_pkt = NULL;
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 1024, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
stat_cmp(curr_stat, &expect_stat);
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
packet_parse(&frag_pkt1, (const char *)frag1, sizeof(frag1));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
1, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
check_stat(ip_reassembly_stat(assy),
1, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
struct packet *pkt = NULL;
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
expect_stat = {
1, 0, 1, // ip4: defrags_expected, defrags_succeed, defrags_failed
1, 1, 1, 0, 1, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 2);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
2, 0, 1, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 1, 2, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// free packet
packet_free(new_pkt);
ip_reassembly_free(assy);
ip_reassembly_free(ip_reass);
}
#endif
#if 1
TEST(IPV4_REASSEMBLE, DUP_FIRST_FRAG)
{
struct packet pkt;
struct packet *new_pkt;
const struct layer_private *layer;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct packet frag_pkt1 = {};
struct packet frag_pkt2 = {};
struct packet *defrag_pkt = NULL;
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 1024, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
stat_cmp(curr_stat, &expect_stat);
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
1, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt1, (const char *)frag1, sizeof(frag1));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
1, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
packet_parse(&frag_pkt2, (const char *)frag1, sizeof(frag1));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt2, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
1, 0, 1, // ip4: defrags_expected, defrags_succeed, defrags_failed
2, 1, 1, 0, 0, 0, 1, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
check_stat(ip_reassembly_stat(assy),
1, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 0, 1, 0, 1, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
struct packet *pkt = NULL;
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt == NULL);
expect_stat = {
1, 0, 1, // ip4: defrags_expected, defrags_succeed, defrags_failed
2, 1, 1, 0, 0, 0, 1, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt);
check_stat(ip_reassembly_stat(assy),
1, 1, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
3, 2, 2, 0, 1, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// check packet
packet_print(new_pkt);
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
// check IPv4
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_IPV4);
EXPECT_TRUE(layer);
struct ip *hdr = (struct ip *)layer->hdr_ptr;
EXPECT_TRUE(ip4_hdr_get_version(hdr) == 4);
EXPECT_TRUE(ip4_hdr_get_hdr_len(hdr) == 20 /* IPv4 */);
EXPECT_TRUE(ip4_hdr_get_tos(hdr) == 0);
EXPECT_TRUE(ip4_hdr_get_total_len(hdr) == 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
EXPECT_TRUE(ip4_hdr_get_ipid(hdr) == 0xffff);
EXPECT_TRUE(ip4_hdr_get_flags(hdr) == 0x0);
EXPECT_TRUE(ip4_hdr_get_frag_offset(hdr) == 0);
EXPECT_TRUE(ip4_hdr_get_ttl(hdr) == 127);
EXPECT_TRUE(ip4_hdr_get_proto(hdr) == 6);
EXPECT_TRUE(ip4_hdr_get_checksum(hdr) == 0x6d73); // NOTE this is correct checksum
EXPECT_TRUE(ip4_hdr_get_src_addr(hdr) == 0xc0a82467);
EXPECT_TRUE(ip4_hdr_get_dst_addr(hdr) == 0xc0a82889);
EXPECT_TRUE(ip4_hdr_get_opt_len(hdr) == 0);
EXPECT_TRUE(ip4_hdr_get_opt_data(hdr) == NULL);
// check TCP
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_TCP);
EXPECT_TRUE(layer);
struct tcphdr *tcp_hdr = (struct tcphdr *)layer->hdr_ptr;
EXPECT_TRUE(tcp_hdr_get_src_port(tcp_hdr) == 62629);
EXPECT_TRUE(tcp_hdr_get_dst_port(tcp_hdr) == 9999);
EXPECT_TRUE(tcp_hdr_get_seq(tcp_hdr) == 2433164423);
EXPECT_TRUE(tcp_hdr_get_ack(tcp_hdr) == 64297191);
EXPECT_TRUE(tcp_hdr_get_hdr_len(tcp_hdr) == 20);
EXPECT_TRUE(tcp_hdr_get_flags(tcp_hdr) == 0x018);
EXPECT_TRUE(tcp_hdr_get_window(tcp_hdr) == 65280);
EXPECT_TRUE(tcp_hdr_get_checksum(tcp_hdr) == 0x5e92);
EXPECT_TRUE(tcp_hdr_get_urg_ptr(tcp_hdr) == 0);
EXPECT_TRUE(tcp_hdr_get_opt_len(tcp_hdr) == 0);
EXPECT_TRUE(tcp_hdr_get_opt_data(tcp_hdr) == NULL);
// free packet
packet_free(new_pkt);
ip_reassembly_free(assy);
ip_reassembly_free(ip_reass);
}
#endif
#if 1
TEST(IPV4_REASSEMBLE, DUP_LAST_FRAG)
{
struct packet pkt;
struct packet *new_pkt;
const struct layer_private *layer;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct packet frag_pkt1 = {};
struct packet frag_pkt2 = {};
struct packet *defrag_pkt = NULL;
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 1024, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
stat_cmp(curr_stat, &expect_stat);
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
1, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt1, (const char *)frag2, sizeof(frag2));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
1, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
packet_parse(&frag_pkt2, (const char *)frag2, sizeof(frag2));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt2, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
1, 0, 1, // ip4: defrags_expected, defrags_succeed, defrags_failed
2, 1, 1, 0, 0, 0, 1, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
check_stat(ip_reassembly_stat(assy),
1, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 0, 1, 0, 0, 1, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
struct packet *pkt = NULL;
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt == NULL);
expect_stat = {
1, 0, 1, // ip4: defrags_expected, defrags_succeed, defrags_failed
2, 1, 1, 0, 0, 0, 1, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt);
check_stat(ip_reassembly_stat(assy),
1, 1, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
3, 2, 2, 0, 0, 1, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// check packet
packet_print(new_pkt);
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
// check IPv4
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_IPV4);
EXPECT_TRUE(layer);
struct ip *hdr = (struct ip *)layer->hdr_ptr;
EXPECT_TRUE(ip4_hdr_get_version(hdr) == 4);
EXPECT_TRUE(ip4_hdr_get_hdr_len(hdr) == 20 /* IPv4 */);
EXPECT_TRUE(ip4_hdr_get_tos(hdr) == 0);
EXPECT_TRUE(ip4_hdr_get_total_len(hdr) == 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
EXPECT_TRUE(ip4_hdr_get_ipid(hdr) == 0xffff);
EXPECT_TRUE(ip4_hdr_get_flags(hdr) == 0x0);
EXPECT_TRUE(ip4_hdr_get_frag_offset(hdr) == 0);
EXPECT_TRUE(ip4_hdr_get_ttl(hdr) == 127);
EXPECT_TRUE(ip4_hdr_get_proto(hdr) == 6);
EXPECT_TRUE(ip4_hdr_get_checksum(hdr) == 0x6d73); // NOTE this is correct checksum
EXPECT_TRUE(ip4_hdr_get_src_addr(hdr) == 0xc0a82467);
EXPECT_TRUE(ip4_hdr_get_dst_addr(hdr) == 0xc0a82889);
EXPECT_TRUE(ip4_hdr_get_opt_len(hdr) == 0);
EXPECT_TRUE(ip4_hdr_get_opt_data(hdr) == NULL);
// check TCP
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_TCP);
EXPECT_TRUE(layer);
struct tcphdr *tcp_hdr = (struct tcphdr *)layer->hdr_ptr;
EXPECT_TRUE(tcp_hdr_get_src_port(tcp_hdr) == 62629);
EXPECT_TRUE(tcp_hdr_get_dst_port(tcp_hdr) == 9999);
EXPECT_TRUE(tcp_hdr_get_seq(tcp_hdr) == 2433164423);
EXPECT_TRUE(tcp_hdr_get_ack(tcp_hdr) == 64297191);
EXPECT_TRUE(tcp_hdr_get_hdr_len(tcp_hdr) == 20);
EXPECT_TRUE(tcp_hdr_get_flags(tcp_hdr) == 0x018);
EXPECT_TRUE(tcp_hdr_get_window(tcp_hdr) == 65280);
EXPECT_TRUE(tcp_hdr_get_checksum(tcp_hdr) == 0x5e92);
EXPECT_TRUE(tcp_hdr_get_urg_ptr(tcp_hdr) == 0);
EXPECT_TRUE(tcp_hdr_get_opt_len(tcp_hdr) == 0);
EXPECT_TRUE(tcp_hdr_get_opt_data(tcp_hdr) == NULL);
// free packet
packet_free(new_pkt);
ip_reassembly_free(assy);
ip_reassembly_free(ip_reass);
}
#endif
#if 1
TEST(IPV4_REASSEMBLE, FULL)
{
struct packet pkt;
struct packet *new_pkt;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 1,
.bucket_num = 1,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct packet frag_pkt1 = {};
struct packet frag_pkt2 = {};
struct packet frag_pkt3 = {};
struct packet *defrag_pkt = NULL;
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 2, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
char dup1[sizeof(frag1)] = {0};
char dup2[sizeof(frag1)] = {0};
char dup3[sizeof(frag1)] = {0};
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
char dup_frag[sizeof(frag1)] = {0};
memcpy(dup_frag, frag1, sizeof(frag1));
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)dup_frag, sizeof(dup_frag));
memcpy(dup1, frag1, sizeof(frag1));
memcpy(dup2, frag1, sizeof(frag1));
memcpy(dup3, frag1, sizeof(frag1));
// flow1
packet_set_ipv4_src_addr(&pkt, 1);
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
1, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt1, (const char *)dup1, sizeof(dup1));
packet_overwrite_v4_saddr(&frag_pkt1, 1);
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
1, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// flow2
packet_set_ipv4_src_addr(&pkt, 2);
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
2, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 0, 2, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt2, (const char *)dup2, sizeof(dup2));
packet_overwrite_v4_saddr(&frag_pkt2, 2);
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt2, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
2, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
2, 0, 2, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// flow3
packet_set_ipv4_src_addr(&pkt, 3);
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
packet_parse(&frag_pkt3, (const char *)dup3, sizeof(dup3));
packet_overwrite_v4_saddr(&frag_pkt3, 3);
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt3, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
2, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
3, 0, 2, 1, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
check_stat(ip_reassembly_stat(assy),
2, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
3, 0, 2, 1, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
struct packet *pkt = NULL;
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt == NULL);
expect_stat = {
2, 0, 2, // ip4: defrags_expected, defrags_succeed, defrags_failed
3, 2, 2, 1, 2, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// free packet
packet_free(new_pkt);
ip_reassembly_free(assy);
}
#endif
#if 1
TEST(IPV4_REASSEMBLE, OVERLAP)
{
// TEST ON IPv6
ip_reassembly_free(ip_reass);
}
#endif