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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user