Add support for TCP port reuse (same tuple6 but different ISN) in session manager: evict old session and create new session

This commit is contained in:
luwenpeng
2024-05-16 19:13:36 +08:00
parent 1559f0a13e
commit 32ae4618ef
25 changed files with 176 additions and 119 deletions

View File

@@ -286,6 +286,10 @@ static void tcp_update(struct session_manager *mgr, struct session *sess, enum f
uint8_t flags = tcp_hdr_get_flags(hdr);
uint16_t len = tcp_layer->pld_len;
if ((flags & TH_SYN) && half->isn == 0)
{
half->isn = tcp_hdr_get_seq(hdr);
}
half->flags = flags;
half->history |= flags;
half->seq = tcp_hdr_get_seq(hdr);
@@ -586,7 +590,7 @@ static void session_update(struct session *sess, enum session_state next_state,
session_set_state(sess, next_state);
}
static void session_manager_evicte_session(struct session_manager *mgr, struct session *sess, uint64_t now)
static void session_manager_evicte_session(struct session_manager *mgr, struct session *sess, uint64_t now, int reason)
{
if (sess == NULL)
{
@@ -595,12 +599,19 @@ static void session_manager_evicte_session(struct session_manager *mgr, struct s
// when session add to evicted queue, session lifetime is over
enum session_state curr_state = session_get_state(sess);
enum session_state next_state = session_transition_run(curr_state, LRU_EVICT);
session_transition_log(sess, curr_state, next_state, LRU_EVICT);
enum session_state next_state = session_transition_run(curr_state, reason);
session_transition_log(sess, curr_state, next_state, reason);
session_set_state(sess, next_state);
if (!session_get_closing_reason(sess))
{
session_set_closing_reason(sess, CLOSING_BY_EVICTED);
if (reason == PORT_REUSE_EVICT)
{
session_set_closing_reason(sess, CLOSING_BY_PORT_REUSE_EVICTED);
}
if (reason == LRU_EVICT)
{
session_set_closing_reason(sess, CLOSING_BY_LRU_EVICTED);
}
}
session_timer_del(mgr->sess_timer, sess);
list_add_tail(&sess->evicte, &mgr->evicte_queue);
@@ -629,6 +640,37 @@ static void session_manager_evicte_session(struct session_manager *mgr, struct s
}
}
static struct session *session_manager_lookup_tcp_session(struct session_manager *mgr, const struct packet *pkt, const struct tuple6 *key, uint64_t now)
{
struct session *sess = session_table_find_tuple6(mgr->tcp_sess_table, key);
if (sess == NULL)
{
return NULL;
}
const struct packet_layer *tcp_layer = packet_get_innermost_layer(pkt, LAYER_TYPE_TCP);
const struct tcphdr *hdr = (const struct tcphdr *)tcp_layer->hdr_ptr;
uint8_t flags = tcp_hdr_get_flags(hdr);
if ((flags & TH_SYN) == 0)
{
return sess;
}
enum flow_direction dir = identify_direction_by_history(sess, key);
struct tcp_half *half = &sess->tcp_halfs[dir];
if (half->isn && half->isn != tcp_hdr_get_seq(hdr))
{
// TCP port reuse, evict old session
session_manager_evicte_session(mgr, sess, now, PORT_REUSE_EVICT);
return NULL;
}
else
{
// TCP SYN retransmission
return sess;
}
}
static struct session *session_manager_new_tcp_session(struct session_manager *mgr, const struct packet *pkt, const struct tuple6 *key, uint64_t now)
{
const struct packet_layer *tcp_layer = packet_get_innermost_layer(pkt, LAYER_TYPE_TCP);
@@ -644,7 +686,7 @@ static struct session *session_manager_new_tcp_session(struct session_manager *m
if (mgr->opts.tcp_overload_evict_old_sess && mgr->stat.curr_nr_tcp_sess_used >= mgr->opts.max_tcp_session_num - EVICTE_SESSION_BURST)
{
struct session *evic_sess = session_table_find_lru(mgr->tcp_sess_table);
session_manager_evicte_session(mgr, evic_sess, now);
session_manager_evicte_session(mgr, evic_sess, now, LRU_EVICT);
}
enum flow_direction dir = (flags & TH_ACK) ? FLOW_DIRECTION_S2C : FLOW_DIRECTION_C2S;
@@ -691,7 +733,7 @@ static struct session *session_manager_new_udp_session(struct session_manager *m
if (mgr->opts.udp_overload_evict_old_sess && mgr->stat.curr_nr_udp_sess_used >= mgr->opts.max_udp_session_num - EVICTE_SESSION_BURST)
{
struct session *evic_sess = session_table_find_lru(mgr->udp_sess_table);
session_manager_evicte_session(mgr, evic_sess, now);
session_manager_evicte_session(mgr, evic_sess, now, LRU_EVICT);
}
struct session *sess = session_pool_pop(mgr->sess_pool);
@@ -1006,7 +1048,7 @@ void session_manager_free_session(struct session_manager *mgr, struct session *s
}
}
struct session *session_manager_lookup_session(struct session_manager *mgr, const struct packet *pkt)
struct session *session_manager_lookup_session(struct session_manager *mgr, const struct packet *pkt, uint64_t now)
{
struct tuple6 key;
if (packet_get_innermost_tuple6(pkt, &key))
@@ -1018,7 +1060,7 @@ struct session *session_manager_lookup_session(struct session_manager *mgr, cons
case IPPROTO_UDP:
return session_table_find_tuple6(mgr->udp_sess_table, &key);
case IPPROTO_TCP:
return session_table_find_tuple6(mgr->tcp_sess_table, &key);
return session_manager_lookup_tcp_session(mgr, pkt, &key, now);
default:
return NULL;
}