Duplicated packet filter supports IPv4-Based TCP / UDP packet (IPv6 is not supported, because IPv6 does not have an IPid and cannot distinguish between retransmissions and duplicates)

This commit is contained in:
luwenpeng
2024-04-11 11:26:50 +08:00
parent 621a4cf292
commit cfbad63021
7 changed files with 77 additions and 54 deletions

View File

@@ -2,12 +2,13 @@
#include "dablooms.h"
#include "tcp_utils.h"
#include "udp_utils.h"
#include "ipv4_utils.h"
#include "duplicated_packet_filter.h"
struct duplicated_packet_key
{
// TCP
// TCP or UDP
uint32_t seq;
uint32_t ack;
uint16_t src_port; /* host order */
@@ -38,8 +39,8 @@ static inline int duplicated_packet_key_get(const struct packet *packet, struct
{
return -1;
}
const struct packet_layer *tcp_layer = packet_get_innermost_layer(packet, LAYER_TYPE_TCP);
if (tcp_layer == NULL)
const struct packet_layer *l4_layer = packet_get_innermost_layer(packet, LAYER_TYPE_L4);
if (l4_layer == NULL)
{
return -1;
}
@@ -51,12 +52,22 @@ static inline int duplicated_packet_key_get(const struct packet *packet, struct
key->src_addr = ipv4_hdr_get_src_addr(iphdr);
key->dst_addr = ipv4_hdr_get_dst_addr(iphdr);
const struct tcphdr *tcphdr = (const struct tcphdr *)tcp_layer->hdr_ptr;
key->seq = tcp_hdr_get_seq(tcphdr);
key->ack = tcp_hdr_get_ack(tcphdr);
key->src_port = tcp_hdr_get_src_port(tcphdr);
key->dst_port = tcp_hdr_get_dst_port(tcphdr);
key->l4_checksum = tcp_hdr_get_checksum(tcphdr);
if (l4_layer->type == LAYER_TYPE_TCP)
{
const struct tcphdr *tcphdr = (const struct tcphdr *)l4_layer->hdr_ptr;
key->seq = tcp_hdr_get_seq(tcphdr);
key->ack = tcp_hdr_get_ack(tcphdr);
key->src_port = tcp_hdr_get_src_port(tcphdr);
key->dst_port = tcp_hdr_get_dst_port(tcphdr);
key->l4_checksum = tcp_hdr_get_checksum(tcphdr);
}
else
{
const struct udphdr *udphdr = (const struct udphdr *)l4_layer->hdr_ptr;
key->src_port = udp_hdr_get_src_port(udphdr);
key->dst_port = udp_hdr_get_dst_port(udphdr);
key->l4_checksum = udp_hdr_get_checksum(udphdr);
}
return 0;
}

View File

@@ -6,7 +6,7 @@ extern "C"
{
#endif
// Duplicated Packet Filter for IPv4-Based TCP Packet
// Duplicated Packet Filter for IPv4 Packet
#include "log.h"
#include "packet_private.h"

View File

@@ -411,7 +411,7 @@ static int tcp_overload_bypass(struct session_manager *mgr, const struct tuple6
{
if (key->ip_proto == IPPROTO_TCP && mgr->stat.nr_tcp_sess_used >= mgr->opts.max_tcp_session_num)
{
mgr->stat.nr_tcp_pkts_bypass_no_space++;
mgr->stat.nr_tcp_pkts_nospace_bypass++;
return 1;
}
return 0;
@@ -420,7 +420,7 @@ static int udp_overload_bypass(struct session_manager *mgr, const struct tuple6
{
if (key->ip_proto == IPPROTO_UDP && mgr->stat.nr_udp_sess_used >= mgr->opts.max_udp_session_num)
{
mgr->stat.nr_udp_pkts_bypass_no_space++;
mgr->stat.nr_udp_pkts_nospace_bypass++;
return 1;
}
return 0;
@@ -429,7 +429,7 @@ static int evicted_session_bypass(struct session_manager *mgr, const struct tupl
{
if (mgr->opts.evicted_session_filter_enable && evicted_session_filter_lookup(mgr->evicte_sess_filter, key, now))
{
mgr->stat.nr_udp_pkts_bypass_hit_evc++;
mgr->stat.nr_udp_pkts_evctd_bypass++;
return 1;
}
@@ -450,7 +450,18 @@ static int duplicated_packet_bypass(struct session_manager *mgr, struct session
{
session_inc_stat(sess, dir, STAT_DUP_PKTS_BYPASS, 1);
session_inc_stat(sess, dir, STAT_DUP_BYTES_BYPASS, packet_get_len(pkt));
mgr->stat.nr_tcp_pkts_bypass_hit_dup++;
switch (session_get_type(sess))
{
case SESSION_TYPE_TCP:
mgr->stat.nr_tcp_pkts_duped_bypass++;
break;
case SESSION_TYPE_UDP:
mgr->stat.nr_udp_pkts_duped_bypass++;
break;
default:
assert(0);
break;
}
session_set_dup_traffic(sess);
return 1;
}
@@ -555,7 +566,7 @@ static struct session *session_manager_new_tcp_session(struct session_manager *m
uint8_t flags = tcp_hdr_get_flags(hdr);
if (!(flags & TH_SYN))
{
mgr->stat.nr_tcp_pkts_bypass_miss_sess++;
mgr->stat.nr_tcp_pkts_nosess_bypass++;
return NULL;
}
@@ -935,13 +946,13 @@ int session_manager_update_session(struct session_manager *mgr, struct session *
{
return -1;
}
if (duplicated_packet_bypass(mgr, sess, pkt, &key, now))
{
return -1;
}
switch (session_get_type(sess))
{
case SESSION_TYPE_TCP:
if (duplicated_packet_bypass(mgr, sess, pkt, &key, now))
{
return -1;
}
return session_manager_update_tcp_session(mgr, sess, pkt, &key, now);
case SESSION_TYPE_UDP:
return session_manager_update_udp_session(mgr, sess, pkt, &key, now);

View File

@@ -75,11 +75,12 @@ struct session_manager_stat
uint64_t nr_udp_sess_evicted; // sum
// Packet
uint64_t nr_udp_pkts_bypass_no_space; // sum
uint64_t nr_tcp_pkts_bypass_no_space; // sum
uint64_t nr_tcp_pkts_bypass_miss_sess; // sum
uint64_t nr_tcp_pkts_bypass_hit_dup; // sum
uint64_t nr_udp_pkts_bypass_hit_evc; // sum
uint64_t nr_udp_pkts_nospace_bypass; // sum
uint64_t nr_tcp_pkts_nospace_bypass; // sum
uint64_t nr_tcp_pkts_nosess_bypass; // sum
uint64_t nr_tcp_pkts_duped_bypass; // sum
uint64_t nr_udp_pkts_duped_bypass; // sum
uint64_t nr_udp_pkts_evctd_bypass; // sum
// TCP segments
uint64_t nr_tcp_seg_received; // sum

View File

@@ -77,7 +77,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SYN_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
// C2S SYN dup Packet
printf("\n=> Packet Parse: TCP C2S SYN dup packet\n");
@@ -92,7 +92,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SYN_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 1);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 1);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 1);
// C2S SYN retransmission Packet
printf("\n=> Packet Parse: TCP C2S SYN retransmission packet\n");
@@ -110,7 +110,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SYN_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 1);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 1);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 1);
session_manager_free(mgr);
}
@@ -140,7 +140,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SYNACK_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
// S2C SYNACK dup Packet
printf("\n=> Packet Parse: TCP S2C SYNACK dup packet\n");
@@ -155,7 +155,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SYNACK_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 1);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 1);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 1);
// S2C SYNACK retransmission Packet
printf("\n=> Packet Parse: TCP S2C SYNACK retransmission packet\n");
@@ -173,7 +173,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SYNACK_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 1);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 1);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 1);
session_manager_free(mgr);
}
@@ -204,7 +204,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SKIP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
// C2S SYN retransmission Packet
printf("\n=> Packet Parse: TCP C2S SYN retransmission packet\n");
@@ -221,7 +221,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SKIP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
// C2S SYN retransmission Packet
printf("\n=> Packet Parse: TCP C2S SYN retransmission packet\n");
@@ -238,7 +238,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SKIP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
// C2S SYN dup Packet
printf("\n=> Packet Parse: TCP C2S SYN dup packet\n");
@@ -253,7 +253,7 @@ TEST(TCP_DUPKT_FILTER_ENABLE, SKIP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
session_manager_free(mgr);
}
@@ -286,7 +286,7 @@ TEST(TCP_DUPKT_FILTER_DISABLE, SYN_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
// C2S SYN dup Packet
printf("\n=> Packet Parse: TCP C2S SYN dup packet\n");
@@ -301,7 +301,7 @@ TEST(TCP_DUPKT_FILTER_DISABLE, SYN_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
session_manager_free(mgr);
}
@@ -334,7 +334,7 @@ TEST(TCP_DUPKT_FILTER_DISABLE, SYNACK_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
// S2C SYNACK dup Packet
printf("\n=> Packet Parse: TCP S2C SYNACK dup packet\n");
@@ -349,7 +349,7 @@ TEST(TCP_DUPKT_FILTER_DISABLE, SYNACK_DUP)
EXPECT_TRUE(session_has_dup_traffic(sess) == 0);
stat = session_manager_get_stat(mgr);
EXPECT_TRUE(stat);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_hit_dup == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_duped_bypass == 0);
session_manager_free(mgr);
}

View File

@@ -86,8 +86,8 @@ TEST(TCP_OVERLOAD, EVICT_OLD_SESS)
EXPECT_TRUE(stat->nr_tcp_sess_closing == 0);
EXPECT_TRUE(stat->nr_tcp_sess_closed == RX_BURST_MAX); // have evicted, have't free
EXPECT_TRUE(stat->nr_tcp_sess_evicted == RX_BURST_MAX);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_no_space == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_miss_sess == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_nospace_bypass == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_nosess_bypass == 0);
session_manager_free(mgr);
}
@@ -127,8 +127,8 @@ TEST(TCP_OVERLOAD, EVICT_NEW_SESS)
EXPECT_TRUE(stat->nr_tcp_sess_closing == 0);
EXPECT_TRUE(stat->nr_tcp_sess_closed == 0);
EXPECT_TRUE(stat->nr_tcp_sess_evicted == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_no_space == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_miss_sess == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_nospace_bypass == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_nosess_bypass == 0);
// table full, evict new session
for (uint32_t i = 0; i < RX_BURST_MAX; i++)
@@ -147,8 +147,8 @@ TEST(TCP_OVERLOAD, EVICT_NEW_SESS)
EXPECT_TRUE(stat->nr_tcp_sess_closing == 0);
EXPECT_TRUE(stat->nr_tcp_sess_closed == 0);
EXPECT_TRUE(stat->nr_tcp_sess_evicted == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_no_space == RX_BURST_MAX);
EXPECT_TRUE(stat->nr_tcp_pkts_bypass_miss_sess == 0);
EXPECT_TRUE(stat->nr_tcp_pkts_nospace_bypass == RX_BURST_MAX);
EXPECT_TRUE(stat->nr_tcp_pkts_nosess_bypass == 0);
session_manager_free(mgr);
}

View File

@@ -87,8 +87,8 @@ TEST(UDP_OVERLOAD, EVICT_OLD_SESS)
EXPECT_TRUE(stat->nr_udp_sess_closing == 0);
EXPECT_TRUE(stat->nr_udp_sess_closed == RX_BURST_MAX); // have evicted, have't free
EXPECT_TRUE(stat->nr_udp_sess_evicted == RX_BURST_MAX);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_no_space == 0);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_hit_evc == 0);
EXPECT_TRUE(stat->nr_udp_pkts_nospace_bypass == 0);
EXPECT_TRUE(stat->nr_udp_pkts_evctd_bypass == 0);
// evicted session
while (1)
@@ -120,8 +120,8 @@ TEST(UDP_OVERLOAD, EVICT_OLD_SESS)
EXPECT_TRUE(stat->nr_udp_sess_closing == 0);
EXPECT_TRUE(stat->nr_udp_sess_closed == 0);
EXPECT_TRUE(stat->nr_udp_sess_evicted == RX_BURST_MAX);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_no_space == 0);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_hit_evc == RX_BURST_MAX);
EXPECT_TRUE(stat->nr_udp_pkts_nospace_bypass == 0);
EXPECT_TRUE(stat->nr_udp_pkts_evctd_bypass == RX_BURST_MAX);
// evicted session timeout
packet_set_ip_src_addr(&pkt, 0);
@@ -137,8 +137,8 @@ TEST(UDP_OVERLOAD, EVICT_OLD_SESS)
EXPECT_TRUE(stat->nr_udp_sess_closing == 0);
EXPECT_TRUE(stat->nr_udp_sess_closed == 1); // have evicted, have't free
EXPECT_TRUE(stat->nr_udp_sess_evicted == RX_BURST_MAX + 1);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_no_space == 0);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_hit_evc == RX_BURST_MAX);
EXPECT_TRUE(stat->nr_udp_pkts_nospace_bypass == 0);
EXPECT_TRUE(stat->nr_udp_pkts_evctd_bypass == RX_BURST_MAX);
session_manager_free(mgr);
}
@@ -178,8 +178,8 @@ TEST(UDP_OVERLOAD, EVICT_NEW_SESS)
EXPECT_TRUE(stat->nr_udp_sess_closing == 0);
EXPECT_TRUE(stat->nr_udp_sess_closed == 0);
EXPECT_TRUE(stat->nr_udp_sess_evicted == 0);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_no_space == 0);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_hit_evc == 0);
EXPECT_TRUE(stat->nr_udp_pkts_nospace_bypass == 0);
EXPECT_TRUE(stat->nr_udp_pkts_evctd_bypass == 0);
// evicted session
EXPECT_TRUE(session_manager_get_evicted_session(mgr) == NULL);
@@ -201,8 +201,8 @@ TEST(UDP_OVERLOAD, EVICT_NEW_SESS)
EXPECT_TRUE(stat->nr_udp_sess_closing == 0);
EXPECT_TRUE(stat->nr_udp_sess_closed == 0);
EXPECT_TRUE(stat->nr_udp_sess_evicted == 0);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_no_space == RX_BURST_MAX);
EXPECT_TRUE(stat->nr_udp_pkts_bypass_hit_evc == 0);
EXPECT_TRUE(stat->nr_udp_pkts_nospace_bypass == RX_BURST_MAX);
EXPECT_TRUE(stat->nr_udp_pkts_evctd_bypass == 0);
session_manager_free(mgr);
}