net/nat: Add auto reclaim logic for NAT entries.

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
Zhe Weng 2022-12-21 20:34:39 +08:00 committed by Xiang Xiao
parent 879c337e30
commit a9da1fff28
3 changed files with 75 additions and 5 deletions

View File

@ -53,3 +53,17 @@ config NET_NAT_ICMP_EXPIRE_SEC
Note: The default value 60 is suggested by RFC5508, Section 3.2,
Page 8.
config NET_NAT_ENTRY_RECLAIM_SEC
int "The time to auto reclaim all expired entries"
default 3600
depends on NET_NAT
---help---
The time to auto reclaim all expired entries. A value of zero will
disable auto reclaiming.
Note: Expired entries will be automatically reclaimed when matching
inbound/outbound entries, so this config does not have significant
impact when NAT is normally used, but very useful when the hashtable
is big and there are only a few connections using NAT (which will
only trigger reclaiming on a few chains in hashtable).

View File

@ -352,6 +352,54 @@ static void ipv4_nat_entry_delete(FAR struct ipv4_nat_entry *entry)
kmm_free(entry);
}
/****************************************************************************
* Name: ipv4_nat_reclaim_entry
*
* Description:
* Try reclaim all expired NAT entries.
* Only works after every CONFIG_NET_NAT_ENTRY_RECLAIM_SEC (low frequency).
*
* Although expired entries will be automatically reclaimed when matching
* inbound/outbound entries, there might be some situations that entries
* will be kept in memory, e.g. big hashtable with only a few connections.
*
* Assumptions:
* NAT is initialized.
*
****************************************************************************/
#if CONFIG_NET_NAT_ENTRY_RECLAIM_SEC > 0
static void ipv4_nat_reclaim_entry(int32_t current_time)
{
static int32_t next_reclaim_time = CONFIG_NET_NAT_ENTRY_RECLAIM_SEC;
if (next_reclaim_time - current_time <= 0)
{
FAR hash_node_t *p;
FAR hash_node_t *tmp;
int count = 0;
int i;
ninfo("INFO: Reclaiming all expired NAT entries.\n");
hashtable_for_every_safe(g_table_inbound, p, tmp, i)
{
FAR struct ipv4_nat_entry *entry =
container_of(p, struct ipv4_nat_entry, hash_inbound);
if (entry->expire_time - current_time <= 0)
{
ipv4_nat_entry_delete(entry);
count++;
}
}
ninfo("INFO: %d expired NAT entries reclaimed.\n", count);
next_reclaim_time = current_time + CONFIG_NET_NAT_ENTRY_RECLAIM_SEC;
}
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -378,7 +426,11 @@ ipv4_nat_inbound_entry_find(uint8_t protocol, uint16_t external_port,
{
FAR hash_node_t *p;
FAR hash_node_t *tmp;
uint32_t current_time = TICK2SEC(clock_systime_ticks());
int32_t current_time = TICK2SEC(clock_systime_ticks());
#if CONFIG_NET_NAT_ENTRY_RECLAIM_SEC > 0
ipv4_nat_reclaim_entry(current_time);
#endif
hashtable_for_every_possible_safe(g_table_inbound, p, tmp,
ipv4_nat_inbound_key(external_port, protocol))
@ -388,7 +440,7 @@ ipv4_nat_inbound_entry_find(uint8_t protocol, uint16_t external_port,
/* Remove expired entries. */
if (entry->expire_time < current_time)
if (entry->expire_time - current_time <= 0)
{
ipv4_nat_entry_delete(entry);
continue;
@ -437,7 +489,11 @@ ipv4_nat_outbound_entry_find(FAR struct net_driver_s *dev, uint8_t protocol,
{
FAR hash_node_t *p;
FAR hash_node_t *tmp;
uint32_t current_time = TICK2SEC(clock_systime_ticks());
int32_t current_time = TICK2SEC(clock_systime_ticks());
#if CONFIG_NET_NAT_ENTRY_RECLAIM_SEC > 0
ipv4_nat_reclaim_entry(current_time);
#endif
hashtable_for_every_possible_safe(g_table_outbound, p, tmp,
ipv4_nat_outbound_key(local_ip, local_port, protocol))
@ -447,7 +503,7 @@ ipv4_nat_outbound_entry_find(FAR struct net_driver_s *dev, uint8_t protocol,
/* Remove expired entries. */
if (entry->expire_time < current_time)
if (entry->expire_time - current_time <= 0)
{
ipv4_nat_entry_delete(entry);
continue;

View File

@ -63,7 +63,7 @@ struct ipv4_nat_entry
uint16_t external_port; /* The external port of local (private) host. */
uint8_t protocol; /* L4 protocol (TCP, UDP etc). */
uint32_t expire_time; /* The expiration time of this entry. */
int32_t expire_time; /* The expiration time of this entry. */
};
/* NAT IP/Port manipulate type, to indicate whether to manipulate source or