perf: 优化通过四元组查询流表的实现(查表前先根据端口预判是否需要翻转四元组)

This commit is contained in:
luwenpeng
2023-11-28 16:36:58 +08:00
parent 699be92862
commit 95abad41b5
4 changed files with 167 additions and 154 deletions

View File

@@ -9,47 +9,32 @@ extern "C"
#include <stdint.h>
#include <sys/types.h>
#include "uthash.h"
#include "tuple.h"
// Note: session_addr must be initialized by memset(0) before use !!!
typedef void fn_free_cb(void *args);
struct session_node
{
uint64_t session_id; /* first key */
struct four_tuple session_addr; /* second key */
void *value;
fn_free_cb *value_free_cb;
UT_hash_handle hh1; /* handle for first hash table */
UT_hash_handle hh2; /* handle for second hash table */
};
struct session_table;
struct session_table *session_table_create();
void session_table_destory(struct session_table *table);
void session_table_reset(struct session_table *table);
uint64_t session_table_count(struct session_table *table);
// session_addr : deep copy
// value : shallow copy (malloc by user, free by value_free_cb)
// addr : deep copy
// value : shallow copy (malloc by user, free by free_cb)
// Note : addr must be initialized by memset(0) before use !!!
// return 0 : suceess
// return -1 : key exists
int session_table_insert(struct session_table *table, uint64_t session_id, const struct four_tuple *session_addr, void *value, const fn_free_cb *value_free_cb);
int session_table_insert(struct session_table *table, uint64_t id, const struct four_tuple *addr, void *value, const fn_free_cb *free_cb);
// return 0 : success
// return -1 : key not exists
int session_table_delete_by_id(struct session_table *table, uint64_t session_id);
int session_table_delete_by_addr(struct session_table *table, const struct four_tuple *session_addr);
int session_table_delete_by_id(struct session_table *table, uint64_t id);
int session_table_delete_by_addr(struct session_table *table, const struct four_tuple *addr);
// return NULL : key not exists
// return UnNULL : success
struct session_node *session_table_search_by_id(struct session_table *table, uint64_t session_id);
struct session_node *session_table_search_by_addr(struct session_table *table, const struct four_tuple *session_addr);
// return NULL : key not exists
// return value : success
void *session_table_search_by_id(struct session_table *table, uint64_t id);
void *session_table_search_by_addr(struct session_table *table, const struct four_tuple *addr);
#ifdef __cpluscplus
}

View File

@@ -3,20 +3,32 @@
#include "session_table.h"
#include "utils.h"
struct session_table
struct session_node
{
struct session_node *root_by_id;
struct session_node *root_by_addr;
uint64_t session_node_count;
uint64_t id; /* first key */
struct four_tuple addr; /* second key */
void *value;
fn_free_cb *free_cb;
UT_hash_handle hh1; /* handle for first hash table */
UT_hash_handle hh2; /* handle for second hash table */
};
// Note: session_addr must be initialized by memset(0) before use !!!
struct session_table
{
struct session_node *root_id;
struct session_node *root_addr;
uint64_t count;
};
static struct session_node *search_node_by_addr(struct session_table *table, const struct four_tuple *addr);
struct session_table *session_table_create()
{
struct session_table *table = (struct session_table *)calloc(1, sizeof(struct session_table));
assert(table);
table->session_node_count = 0;
table->count = 0;
return table;
}
@@ -25,21 +37,7 @@ void session_table_destory(struct session_table *table)
{
if (table)
{
struct session_node *temp = NULL;
struct session_node *node = NULL;
HASH_ITER(hh1, table->root_by_id, node, temp)
{
HASH_DELETE(hh1, table->root_by_id, node);
HASH_DELETE(hh2, table->root_by_addr, node);
if (node->value_free_cb && node->value)
{
node->value_free_cb(node->value);
}
free(node);
node = NULL;
}
session_table_reset(table);
free(table);
table = NULL;
@@ -52,20 +50,20 @@ void session_table_reset(struct session_table *table)
{
struct session_node *temp = NULL;
struct session_node *node = NULL;
HASH_ITER(hh1, table->root_by_id, node, temp)
HASH_ITER(hh1, table->root_id, node, temp)
{
HASH_DELETE(hh1, table->root_by_id, node);
HASH_DELETE(hh2, table->root_by_addr, node);
HASH_DELETE(hh1, table->root_id, node);
HASH_DELETE(hh2, table->root_addr, node);
if (node->value_free_cb && node->value)
if (node->free_cb && node->value)
{
node->value_free_cb(node->value);
node->free_cb(node->value);
}
free(node);
node = NULL;
table->session_node_count--;
table->count--;
}
}
}
@@ -74,7 +72,7 @@ uint64_t session_table_count(struct session_table *table)
{
if (table)
{
return table->session_node_count;
return table->count;
}
else
{
@@ -82,117 +80,151 @@ uint64_t session_table_count(struct session_table *table)
}
}
// session_addr : deep copy
// value : shallow copy (malloc by user, free by value_free_cb)
int session_table_insert(struct session_table *table, uint64_t session_id, const struct four_tuple *session_addr, void *value, const fn_free_cb *value_free_cb)
// addr : deep copy
// value : shallow copy (malloc by user, free by free_cb)
// Note : addr must be initialized by memset(0) before use !!!
int session_table_insert(struct session_table *table, uint64_t id, const struct four_tuple *addr, void *value, const fn_free_cb *free_cb)
{
struct session_node *temp = NULL;
HASH_FIND(hh1, table->root_by_id, &session_id, sizeof(session_id), temp);
if (temp)
struct session_node *node = NULL;
HASH_FIND(hh1, table->root_id, &id, sizeof(id), node);
if (node)
{
return -1;
}
temp = (struct session_node *)calloc(1, sizeof(struct session_node));
assert(temp);
node = (struct session_node *)calloc(1, sizeof(struct session_node));
assert(node);
temp->session_id = session_id;
memcpy(&temp->session_addr, session_addr, sizeof(struct four_tuple));
temp->value = value;
temp->value_free_cb = value_free_cb;
node->id = id;
node->value = value;
node->free_cb = free_cb;
HASH_ADD(hh1, table->root_by_id, session_id, sizeof(temp->session_id), temp);
HASH_ADD(hh2, table->root_by_addr, session_addr, sizeof(temp->session_addr), temp);
if (addr->src_port < addr->dst_port)
{
memcpy(&node->addr, addr, sizeof(struct four_tuple));
}
else
{
four_tuple_reverse(addr, &node->addr);
}
table->session_node_count++;
HASH_ADD(hh1, table->root_id, id, sizeof(node->id), node);
HASH_ADD(hh2, table->root_addr, addr, sizeof(node->addr), node);
table->count++;
return 0;
}
int session_table_delete_by_id(struct session_table *table, uint64_t session_id)
int session_table_delete_by_id(struct session_table *table, uint64_t id)
{
struct session_node *temp = NULL;
HASH_FIND(hh1, table->root_by_id, &session_id, sizeof(session_id), temp);
if (!temp)
struct session_node *node = NULL;
HASH_FIND(hh1, table->root_id, &id, sizeof(id), node);
if (!node)
{
return -1;
}
HASH_DELETE(hh1, table->root_by_id, temp);
HASH_DELETE(hh2, table->root_by_addr, temp);
HASH_DELETE(hh1, table->root_id, node);
HASH_DELETE(hh2, table->root_addr, node);
if (temp->value_free_cb && temp->value)
if (node->free_cb && node->value)
{
temp->value_free_cb(temp->value);
temp->value = NULL;
node->free_cb(node->value);
node->value = NULL;
}
free(temp);
temp = NULL;
free(node);
node = NULL;
table->session_node_count--;
table->count--;
return 0;
}
int session_table_delete_by_addr(struct session_table *table, const struct four_tuple *session_addr)
int session_table_delete_by_addr(struct session_table *table, const struct four_tuple *addr)
{
struct session_node *temp = NULL;
HASH_FIND(hh2, table->root_by_addr, session_addr, sizeof(struct four_tuple), temp);
if (!temp)
struct session_node *node = search_node_by_addr(table, addr);
if (node == NULL)
{
struct four_tuple reverse_addr;
four_tuple_reverse(session_addr, &reverse_addr);
HASH_FIND(hh2, table->root_by_addr, &reverse_addr, sizeof(struct four_tuple), temp);
if (!temp)
{
return -1;
}
return -1;
}
HASH_DELETE(hh1, table->root_by_id, temp);
HASH_DELETE(hh2, table->root_by_addr, temp);
HASH_DELETE(hh1, table->root_id, node);
HASH_DELETE(hh2, table->root_addr, node);
if (temp->value_free_cb && temp->value)
if (node->free_cb && node->value)
{
temp->value_free_cb(temp->value);
temp->value = NULL;
node->free_cb(node->value);
node->value = NULL;
}
free(temp);
temp = NULL;
free(node);
node = NULL;
table->session_node_count--;
table->count--;
return 0;
}
struct session_node *session_table_search_by_id(struct session_table *table, uint64_t session_id)
void *session_table_search_by_id(struct session_table *table, uint64_t id)
{
struct session_node *temp = NULL;
HASH_FIND(hh1, table->root_by_id, &session_id, sizeof(session_id), temp);
if (!temp)
struct session_node *node = NULL;
HASH_FIND(hh1, table->root_id, &id, sizeof(id), node);
if (!node)
{
return NULL;
}
return temp;
return node->value;
}
struct session_node *session_table_search_by_addr(struct session_table *table, const struct four_tuple *session_addr)
void *session_table_search_by_addr(struct session_table *table, const struct four_tuple *addr)
{
struct session_node *temp = NULL;
HASH_FIND(hh2, table->root_by_addr, session_addr, sizeof(struct four_tuple), temp);
if (!temp)
struct session_node *node = search_node_by_addr(table, addr);
if (!node)
{
struct four_tuple reverse_addr;
four_tuple_reverse(session_addr, &reverse_addr);
HASH_FIND(hh2, table->root_by_addr, &reverse_addr, sizeof(struct four_tuple), temp);
if (!temp)
{
return NULL;
}
return NULL;
}
return temp;
return node->value;
}
static struct session_node *search_node_by_addr(struct session_table *table, const struct four_tuple *addr)
{
struct session_node *node = NULL;
const struct four_tuple *first = NULL;
const struct four_tuple *second = NULL;
struct four_tuple reverse_addr;
if (addr->src_port < addr->dst_port)
{
first = addr;
second = NULL;
}
else
{
four_tuple_reverse(addr, &reverse_addr);
first = &reverse_addr;
second = addr;
}
HASH_FIND(hh2, table->root_addr, first, sizeof(struct four_tuple), node);
if (node)
{
return node;
}
if (second == NULL)
{
four_tuple_reverse(addr, &reverse_addr);
second = &reverse_addr;
}
HASH_FIND(hh2, table->root_addr, second, sizeof(struct four_tuple), node);
if (node)
{
return node;
}
return NULL;
}

View File

@@ -50,15 +50,15 @@ TEST(STREAM_TABLE, SEARCH_BY_ID)
EXPECT_TRUE(session_table_count(table) == 2);
// TEST Search By Session ID
struct session_node *node = NULL;
node = session_table_search_by_id(table, 1);
EXPECT_TRUE(node != nullptr);
EXPECT_STREQ((const char *)node->value, "HELLO");
node = session_table_search_by_id(table, 2);
EXPECT_TRUE(node != nullptr);
EXPECT_STREQ((const char *)node->value, "WORLD");
node = session_table_search_by_id(table, 3);
EXPECT_TRUE(node == nullptr);
char *val = NULL;
val = (char *)session_table_search_by_id(table, 1);
EXPECT_TRUE(val != nullptr);
EXPECT_STREQ((const char *)val, "HELLO");
val = (char *)session_table_search_by_id(table, 2);
EXPECT_TRUE(val != nullptr);
EXPECT_STREQ((const char *)val, "WORLD");
val = (char *)session_table_search_by_id(table, 3);
EXPECT_TRUE(val == nullptr);
// TEST Destory
session_table_destory(table);
@@ -85,15 +85,15 @@ TEST(STREAM_TABLE, SEARCH_BY_ADDR)
EXPECT_TRUE(session_table_count(table) == 2);
// TEST Search By Session Addr
struct session_node *node = NULL;
node = session_table_search_by_addr(table, &addr1);
EXPECT_TRUE(node != nullptr);
EXPECT_STREQ((const char *)node->value, "HELLO");
node = session_table_search_by_addr(table, &addr2);
EXPECT_TRUE(node != nullptr);
EXPECT_STREQ((const char *)node->value, "WORLD");
node = session_table_search_by_addr(table, &addr3);
EXPECT_TRUE(node == nullptr);
char *val = NULL;
val = (char *)session_table_search_by_addr(table, &addr1);
EXPECT_TRUE(val != nullptr);
EXPECT_STREQ((const char *)val, "HELLO");
val = (char *)session_table_search_by_addr(table, &addr2);
EXPECT_TRUE(val != nullptr);
EXPECT_STREQ((const char *)val, "WORLD");
val = (char *)session_table_search_by_addr(table, &addr3);
EXPECT_TRUE(val == nullptr);
// TEST Destory
session_table_destory(table);
@@ -122,13 +122,13 @@ TEST(STREAM_TABLE, SEARCH_BY_REVERSE_ADDR)
EXPECT_TRUE(session_table_count(table) == 2);
// TEST Search By Session Reverse Addr
struct session_node *node = NULL;
node = session_table_search_by_addr(table, &addr1_reverse);
EXPECT_TRUE(node != nullptr);
EXPECT_STREQ((const char *)node->value, "HELLO");
node = session_table_search_by_addr(table, &addr2_reverse);
EXPECT_TRUE(node != nullptr);
EXPECT_STREQ((const char *)node->value, "WORLD");
char *val = NULL;
val = (char *)session_table_search_by_addr(table, &addr1_reverse);
EXPECT_TRUE(val != nullptr);
EXPECT_STREQ((const char *)val, "HELLO");
val = (char *)session_table_search_by_addr(table, &addr2_reverse);
EXPECT_TRUE(val != nullptr);
EXPECT_STREQ((const char *)val, "WORLD");
// TEST Destory
session_table_destory(table);