Merge remote-tracking branch 'origin/refactor-rfsim-fds' into integration_2024_w43 (!2994)
Refactor file descriptor handling in rfsimulator - add hashtable iterator to hashtable.c - use hashtable for file descriptor to buffer_t mapping in rfsimulator This enables the use of file descriptors above 250. The linux file descriptors can reach the value of FD_SETSIZE which could be e.g. 1024. This is not an issue in most cases but if the UE or gNB process opens a lot of file descriptors for other purposes we might see rfsimulator file descriptors reach > 250 and cause a segfault. Also added tests for new hashtable functions.
This commit is contained in:
@@ -16,3 +16,6 @@ add_subdirectory(threadPool)
|
|||||||
add_library(utils utils.c system.c time_meas.c time_stat.c tun_if.c)
|
add_library(utils utils.c system.c time_meas.c time_stat.c tun_if.c)
|
||||||
target_include_directories(utils PUBLIC .)
|
target_include_directories(utils PUBLIC .)
|
||||||
target_link_libraries(utils PRIVATE ${T_LIB})
|
target_link_libraries(utils PRIVATE ${T_LIB})
|
||||||
|
if (ENABLE_TESTS)
|
||||||
|
add_subdirectory(hashtable/tests)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -305,3 +305,24 @@ hashtable_rc_t hashtable_get(const hash_table_t *const hashtblP, const hash_key_
|
|||||||
*dataP = NULL;
|
*dataP = NULL;
|
||||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hash_table_iterator_s hashtable_get_iterator(const hash_table_t *const hashtbl)
|
||||||
|
{
|
||||||
|
return (hash_table_iterator_s){.index = 0, .node = hashtbl->nodes[0], .hashtbl = hashtbl};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hashtable_iterator_getnext(hash_table_iterator_s *iterator, void **dataP)
|
||||||
|
{
|
||||||
|
// Iterate over table indexes
|
||||||
|
while (iterator->node == NULL) {
|
||||||
|
iterator->index++;
|
||||||
|
if (iterator->index >= iterator->hashtbl->size) {
|
||||||
|
*dataP = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iterator->node = iterator->hashtbl->nodes[iterator->index];
|
||||||
|
}
|
||||||
|
*dataP = iterator->node->data;
|
||||||
|
iterator->node = iterator->node->next;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include<stdlib.h>
|
#include<stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef size_t hash_size_t;
|
typedef size_t hash_size_t;
|
||||||
typedef uint64_t hash_key_t;
|
typedef uint64_t hash_key_t;
|
||||||
@@ -54,6 +55,12 @@ typedef struct hash_table_s {
|
|||||||
void (*freefunc)(void *);
|
void (*freefunc)(void *);
|
||||||
} hash_table_t;
|
} hash_table_t;
|
||||||
|
|
||||||
|
typedef struct hash_table_iterator_s {
|
||||||
|
int index;
|
||||||
|
hash_node_t* node;
|
||||||
|
const hash_table_t* const hashtbl;
|
||||||
|
} hash_table_iterator_s;
|
||||||
|
|
||||||
char *hashtable_rc_code2string(hashtable_rc_t rcP);
|
char *hashtable_rc_code2string(hashtable_rc_t rcP);
|
||||||
void hash_free_int_func(void *memoryP);
|
void hash_free_int_func(void *memoryP);
|
||||||
hash_table_t *hashtable_create (const hash_size_t size, hash_size_t (*hashfunc)(const hash_key_t ), void (*freefunc)(void *));
|
hash_table_t *hashtable_create (const hash_size_t size, hash_size_t (*hashfunc)(const hash_key_t ), void (*freefunc)(void *));
|
||||||
@@ -63,8 +70,8 @@ hashtable_rc_t hashtable_dump_content (const hash_table_t *const hashtblP, char
|
|||||||
hashtable_rc_t hashtable_insert (hash_table_t *const hashtbl, const hash_key_t key, void *data);
|
hashtable_rc_t hashtable_insert (hash_table_t *const hashtbl, const hash_key_t key, void *data);
|
||||||
hashtable_rc_t hashtable_remove (hash_table_t *const hashtbl, const hash_key_t key);
|
hashtable_rc_t hashtable_remove (hash_table_t *const hashtbl, const hash_key_t key);
|
||||||
hashtable_rc_t hashtable_get (const hash_table_t *const hashtbl, const hash_key_t key, void **dataP);
|
hashtable_rc_t hashtable_get (const hash_table_t *const hashtbl, const hash_key_t key, void **dataP);
|
||||||
|
hash_table_iterator_s hashtable_get_iterator(const hash_table_t *const hashtbl);
|
||||||
|
bool hashtable_iterator_getnext(hash_table_iterator_s* iterator, void **dataP);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
add_executable(test_hashtable test_hashtable.cpp)
|
||||||
|
add_dependencies(tests test_hashtable)
|
||||||
|
target_link_libraries(test_hashtable PRIVATE HASHTABLE GTest::gtest)
|
||||||
|
add_test(NAME test_hashtable
|
||||||
|
COMMAND ./test_hashtable)
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
extern "C" {
|
||||||
|
#include "hashtable.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(hashtable, test_insert_remove) {
|
||||||
|
hash_table_t* table = hashtable_create(250, NULL, NULL);
|
||||||
|
int* a = (int*)calloc(1, sizeof(*a));
|
||||||
|
EXPECT_EQ(hashtable_insert(table, 1, a), HASH_TABLE_OK);
|
||||||
|
EXPECT_EQ(hashtable_remove(table, 1), HASH_TABLE_OK);
|
||||||
|
EXPECT_EQ(hashtable_destroy(&table), HASH_TABLE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(hashtable, test_insert_iterate_remove) {
|
||||||
|
hash_table_t* table = hashtable_create(250, NULL, NULL);
|
||||||
|
int* a = (int*)calloc(1, sizeof(*a));
|
||||||
|
EXPECT_EQ(hashtable_insert(table, 1, a), HASH_TABLE_OK);
|
||||||
|
auto iterator = hashtable_get_iterator(table);
|
||||||
|
void* ptr;
|
||||||
|
int num_items = 0;
|
||||||
|
while(hashtable_iterator_getnext(&iterator, &ptr)) {
|
||||||
|
num_items++;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(num_items, 1);
|
||||||
|
EXPECT_EQ(hashtable_remove(table, 1), HASH_TABLE_OK);
|
||||||
|
num_items = 0;
|
||||||
|
|
||||||
|
auto iterator2 = hashtable_get_iterator(table);
|
||||||
|
while(hashtable_iterator_getnext(&iterator2, &ptr)) {
|
||||||
|
num_items++;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(num_items, 0);
|
||||||
|
EXPECT_EQ(hashtable_destroy(&table), HASH_TABLE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(hashtable, test_insert_three_iterate_remove) {
|
||||||
|
hash_table_t* table = hashtable_create(250, NULL, NULL);
|
||||||
|
int* a1 = (int*)calloc(1, sizeof(*a1));
|
||||||
|
int* a2 = (int*)calloc(1, sizeof(*a2));
|
||||||
|
int* a3 = (int*)calloc(1, sizeof(*a3));
|
||||||
|
EXPECT_EQ(hashtable_insert(table, 1, a1), HASH_TABLE_OK);
|
||||||
|
EXPECT_EQ(hashtable_insert(table, 2, a2), HASH_TABLE_OK);
|
||||||
|
EXPECT_EQ(hashtable_insert(table, 3, a3), HASH_TABLE_OK);
|
||||||
|
auto iterator = hashtable_get_iterator(table);
|
||||||
|
void* ptr;
|
||||||
|
int num_items = 0;
|
||||||
|
while(hashtable_iterator_getnext(&iterator, &ptr)) {
|
||||||
|
num_items++;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(num_items, 3);
|
||||||
|
EXPECT_EQ(hashtable_remove(table, 1), HASH_TABLE_OK);
|
||||||
|
num_items = 0;
|
||||||
|
|
||||||
|
auto iterator2 = hashtable_get_iterator(table);
|
||||||
|
while(hashtable_iterator_getnext(&iterator2, &ptr)) {
|
||||||
|
num_items++;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(num_items, 2);
|
||||||
|
EXPECT_EQ(hashtable_destroy(&table), HASH_TABLE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(hashtable, test_insert_empty_insert_interate) {
|
||||||
|
hash_table_t* table = hashtable_create(250, NULL, NULL);
|
||||||
|
int* a = (int*)calloc(1, sizeof(*a));
|
||||||
|
EXPECT_EQ(hashtable_insert(table, 1, a), HASH_TABLE_OK);
|
||||||
|
EXPECT_EQ(hashtable_remove(table, 1), HASH_TABLE_OK);
|
||||||
|
|
||||||
|
int* a2 = (int*)calloc(1, sizeof(*a2));
|
||||||
|
EXPECT_EQ(hashtable_insert(table, 1, a2), HASH_TABLE_OK);
|
||||||
|
auto iterator3 = hashtable_get_iterator(table);
|
||||||
|
int num_items = 0;
|
||||||
|
void* ptr;
|
||||||
|
while(hashtable_iterator_getnext(&iterator3, &ptr)) {
|
||||||
|
num_items++;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(num_items, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(hashtable_destroy(&table), HASH_TABLE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ add_library(rfsimulator MODULE
|
|||||||
apply_channelmod.c
|
apply_channelmod.c
|
||||||
../../openair1/PHY/TOOLS/signal_energy.c
|
../../openair1/PHY/TOOLS/signal_energy.c
|
||||||
)
|
)
|
||||||
target_link_libraries(rfsimulator PRIVATE SIMU)
|
target_link_libraries(rfsimulator PRIVATE SIMU HASHTABLE)
|
||||||
set_target_properties(rfsimulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
set_target_properties(rfsimulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
add_executable(replay_node stored_node.c)
|
add_executable(replay_node stored_node.c)
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
#define CHANNELMOD_DYNAMICLOAD
|
#define CHANNELMOD_DYNAMICLOAD
|
||||||
#include <openair1/SIMULATION/TOOLS/sim.h>
|
#include <openair1/SIMULATION/TOOLS/sim.h>
|
||||||
#include "rfsimulator.h"
|
#include "rfsimulator.h"
|
||||||
|
#include "hashtable.h"
|
||||||
|
|
||||||
#define PORT 4043 //default TCP port for this simulator
|
#define PORT 4043 //default TCP port for this simulator
|
||||||
//
|
//
|
||||||
@@ -82,6 +83,8 @@
|
|||||||
// Until a convenient management is implemented, the MAX_FD_RFSIMU is used everywhere (instead of
|
// Until a convenient management is implemented, the MAX_FD_RFSIMU is used everywhere (instead of
|
||||||
// FD_SETSIE) and reduced to 125. This should allow for around 20 simultaeous UEs.
|
// FD_SETSIE) and reduced to 125. This should allow for around 20 simultaeous UEs.
|
||||||
//
|
//
|
||||||
|
// An indirection level via hashtable was added to allow the software to use FDs above MAX_FD_RFSIMU.
|
||||||
|
//
|
||||||
// #define MAX_FD_RFSIMU FD_SETSIZE
|
// #define MAX_FD_RFSIMU FD_SETSIZE
|
||||||
#define MAX_FD_RFSIMU 250
|
#define MAX_FD_RFSIMU 250
|
||||||
#define SEND_BUFF_SIZE 100000000 // Socket buffer size
|
#define SEND_BUFF_SIZE 100000000 // Socket buffer size
|
||||||
@@ -162,6 +165,9 @@ typedef struct {
|
|||||||
uint16_t port;
|
uint16_t port;
|
||||||
int saveIQfile;
|
int saveIQfile;
|
||||||
buffer_t buf[MAX_FD_RFSIMU];
|
buffer_t buf[MAX_FD_RFSIMU];
|
||||||
|
int next_buf;
|
||||||
|
// Hashtable used as an indirection level between file descriptor and the buf array
|
||||||
|
hash_table_t *fd_to_buf_map;
|
||||||
int rx_num_channels;
|
int rx_num_channels;
|
||||||
int tx_num_channels;
|
int tx_num_channels;
|
||||||
double sample_rate;
|
double sample_rate;
|
||||||
@@ -178,11 +184,38 @@ typedef struct {
|
|||||||
double prop_delay_ms;
|
double prop_delay_ms;
|
||||||
} rfsimulator_state_t;
|
} rfsimulator_state_t;
|
||||||
|
|
||||||
|
|
||||||
|
static buffer_t *get_buff_from_socket(rfsimulator_state_t *simulator_state, int socket)
|
||||||
|
{
|
||||||
|
uint64_t buffer_index;
|
||||||
|
if (hashtable_get(simulator_state->fd_to_buf_map, socket, (void **)&buffer_index) == HASH_TABLE_OK) {
|
||||||
|
return &simulator_state->buf[buffer_index];
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_buff_to_socket_mapping(rfsimulator_state_t *simulator_state, int socket, uint64_t buff_index)
|
||||||
|
{
|
||||||
|
hashtable_rc_t rc = hashtable_insert(simulator_state->fd_to_buf_map, socket, (void *)buff_index);
|
||||||
|
AssertFatal(rc == HASH_TABLE_OK,
|
||||||
|
"%s sock = %d\n",
|
||||||
|
rc == HASH_TABLE_INSERT_OVERWRITTEN_DATA ? "Duplicate entry in hashtable" : "Hashtable is not allocated",
|
||||||
|
socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_buff_to_socket_mapping(rfsimulator_state_t *simulator_state, int socket)
|
||||||
|
{
|
||||||
|
// Failure is fine here
|
||||||
|
hashtable_remove(simulator_state->fd_to_buf_map, socket);
|
||||||
|
}
|
||||||
|
|
||||||
static int allocCirBuf(rfsimulator_state_t *bridge, int sock)
|
static int allocCirBuf(rfsimulator_state_t *bridge, int sock)
|
||||||
{
|
{
|
||||||
/* TODO: cleanup code so that this AssertFatal becomes useless */
|
/* TODO: cleanup code so that this AssertFatal becomes useless */
|
||||||
AssertFatal(sock >= 0 && sock < sizeofArray(bridge->buf), "socket %d is not in range\n", sock);
|
AssertFatal(sock >= 0 && sock < sizeofArray(bridge->buf), "socket %d is not in range\n", sock);
|
||||||
buffer_t *ptr=&bridge->buf[sock];
|
uint64_t buff_index = bridge->next_buf++ % MAX_FD_RFSIMU;
|
||||||
|
buffer_t *ptr=&bridge->buf[buff_index];
|
||||||
ptr->circularBuf = calloc(1, sampleToByte(CirSize, 1));
|
ptr->circularBuf = calloc(1, sampleToByte(CirSize, 1));
|
||||||
if (ptr->circularBuf == NULL) {
|
if (ptr->circularBuf == NULL) {
|
||||||
LOG_E(HW, "malloc(%lu) failed\n", sampleToByte(CirSize, 1));
|
LOG_E(HW, "malloc(%lu) failed\n", sampleToByte(CirSize, 1));
|
||||||
@@ -235,6 +268,7 @@ static int allocCirBuf(rfsimulator_state_t *bridge, int sock)
|
|||||||
random_channel(ptr->channel_model,false);
|
random_channel(ptr->channel_model,false);
|
||||||
LOG_I(HW, "Random channel %s in rfsimulator activated\n", modelname);
|
LOG_I(HW, "Random channel %s in rfsimulator activated\n", modelname);
|
||||||
}
|
}
|
||||||
|
add_buff_to_socket_mapping(bridge, sock, buff_index);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,17 +277,23 @@ static void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
|
|||||||
LOG_E(HW, "epoll_ctl(EPOLL_CTL_DEL) failed\n");
|
LOG_E(HW, "epoll_ctl(EPOLL_CTL_DEL) failed\n");
|
||||||
}
|
}
|
||||||
close(sock);
|
close(sock);
|
||||||
free(bridge->buf[sock].circularBuf);
|
buffer_t* buf = get_buff_from_socket(bridge, sock);
|
||||||
// Fixme: no free_channel_desc_scm(bridge->buf[sock].channel_model) implemented
|
if (buf) {
|
||||||
// a lot of mem leaks
|
free(buf->circularBuf);
|
||||||
//free(bridge->buf[sock].channel_model);
|
// Fixme: no free_channel_desc_scm(bridge->buf[sock].channel_model) implemented
|
||||||
memset(&bridge->buf[sock], 0, sizeof(buffer_t));
|
// a lot of mem leaks
|
||||||
bridge->buf[sock].conn_sock=-1;
|
//free(bridge->buf[sock].channel_model);
|
||||||
nb_ue--;
|
memset(buf, 0, sizeof(buffer_t));
|
||||||
|
buf->conn_sock=-1;
|
||||||
|
remove_buff_to_socket_mapping(bridge, sock);
|
||||||
|
nb_ue--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void socketError(rfsimulator_state_t *bridge, int sock) {
|
static void socketError(rfsimulator_state_t *bridge, int sock) {
|
||||||
if (bridge->buf[sock].conn_sock!=-1) {
|
buffer_t* buf = get_buff_from_socket(bridge, sock);
|
||||||
|
if (!buf) return;
|
||||||
|
if (buf->conn_sock != -1) {
|
||||||
LOG_W(HW, "Lost socket\n");
|
LOG_W(HW, "Lost socket\n");
|
||||||
removeCirBuf(bridge, sock);
|
removeCirBuf(bridge, sock);
|
||||||
|
|
||||||
@@ -789,7 +829,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
|
|||||||
|
|
||||||
rfsimulator_write_internal(t, t->lastWroteTS > 1 ? t->lastWroteTS - 1 : 0, samplesVoid, 1, t->tx_num_channels, 1, false);
|
rfsimulator_write_internal(t, t->lastWroteTS > 1 ? t->lastWroteTS - 1 : 0, samplesVoid, 1, t->tx_num_channels, 1, false);
|
||||||
|
|
||||||
buffer_t *b = &t->buf[conn_sock];
|
buffer_t *b = get_buff_from_socket(t, conn_sock);
|
||||||
if (b->channel_model)
|
if (b->channel_model)
|
||||||
b->channel_model->start_TS = t->lastWroteTS;
|
b->channel_model->start_TS = t->lastWroteTS;
|
||||||
} else {
|
} else {
|
||||||
@@ -798,8 +838,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_t *b=&t->buf[fd];
|
buffer_t *b = get_buff_from_socket(t, fd);
|
||||||
|
if (!b) continue;
|
||||||
if ( b->circularBuf == NULL ) {
|
if ( b->circularBuf == NULL ) {
|
||||||
LOG_E(HW, "Received data on not connected socket %d\n", events[nbEv].data.fd);
|
LOG_E(HW, "Received data on not connected socket %d\n", events[nbEv].data.fd);
|
||||||
continue;
|
continue;
|
||||||
@@ -1044,6 +1084,7 @@ static void rfsimulator_end(openair0_device *device) {
|
|||||||
removeCirBuf(s, b->conn_sock);
|
removeCirBuf(s, b->conn_sock);
|
||||||
}
|
}
|
||||||
close(s->epollfd);
|
close(s->epollfd);
|
||||||
|
hashtable_destroy(&s->fd_to_buf_map);
|
||||||
}
|
}
|
||||||
static int rfsimulator_stop(openair0_device *device) {
|
static int rfsimulator_stop(openair0_device *device) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1059,6 +1100,12 @@ static int rfsimulator_set_gains(openair0_device *device, openair0_config_t *ope
|
|||||||
static int rfsimulator_write_init(openair0_device *device) {
|
static int rfsimulator_write_init(openair0_device *device) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void do_not_free_integer(void *integer)
|
||||||
|
{
|
||||||
|
(void)integer;
|
||||||
|
}
|
||||||
|
|
||||||
__attribute__((__visibility__("default")))
|
__attribute__((__visibility__("default")))
|
||||||
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||||
// to change the log level, use this on command line
|
// to change the log level, use this on command line
|
||||||
@@ -1104,6 +1151,8 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
|||||||
|
|
||||||
for (int i = 0; i < MAX_FD_RFSIMU; i++)
|
for (int i = 0; i < MAX_FD_RFSIMU; i++)
|
||||||
rfsimulator->buf[i].conn_sock=-1;
|
rfsimulator->buf[i].conn_sock=-1;
|
||||||
|
rfsimulator->next_buf = 0;
|
||||||
|
rfsimulator->fd_to_buf_map = hashtable_create(MAX_FD_RFSIMU, NULL, do_not_free_integer);
|
||||||
|
|
||||||
AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1, "epoll_create1() failed, errno(%d)", errno);
|
AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1, "epoll_create1() failed, errno(%d)", errno);
|
||||||
// we need to call randominit() for telnet server (use gaussdouble=>uniformrand)
|
// we need to call randominit() for telnet server (use gaussdouble=>uniformrand)
|
||||||
|
|||||||
Reference in New Issue
Block a user