Merge remote-tracking branch 'origin/develop' into ru_rau_enhancement_L1_renaming

Conflicts:
	cmake_targets/build_oai
	cmake_targets/oaisim_build_oai/CMakeLists.template
	cmake_targets/oaisim_mme_build_oai/CMakeLists.template
	cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
	openair1/PHY/LTE_ESTIMATION/lte_sync_time.c
	openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
	openair1/PHY/LTE_TRANSPORT/dci_tools.c
	openair1/PHY/LTE_TRANSPORT/if4_tools.c
	openair1/PHY/LTE_TRANSPORT/prach.c
	openair1/PHY/LTE_TRANSPORT/pucch.c
	openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c
	openair1/PHY/impl_defs_lte.h
	openair1/SCHED/fapi_l1.c
	openair1/SCHED/phy_procedures_lte_eNb.c
	openair1/SIMULATION/LTE_PHY/dlsim.c
	openair2/ENB_APP/enb_config.c
	openair2/ENB_APP/enb_paramdef.h
	openair2/LAYER2/MAC/eNB_scheduler_RA.c
	openair2/LAYER2/MAC/eNB_scheduler_primitives.c
	targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c
	targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
	targets/RT/USER/lte-enb.c
	targets/RT/USER/lte-ru.c
	targets/RT/USER/lte-softmodem.c
	targets/RT/USER/lte-softmodem.h
This commit is contained in:
Raymond Knopp
2019-04-14 20:34:03 +02:00
712 changed files with 88321 additions and 52611 deletions
+97 -67
View File
@@ -12,15 +12,17 @@
#include "common/config/config_userapi.h"
#define QUIT(x) do { \
printf("T tracer: QUIT: %s\n", x); \
exit(1); \
} while (0)
printf("T tracer: QUIT: %s\n", x); \
exit(1); \
} while (0)
/* array used to activate/disactivate a log */
static int T_IDs[T_NUMBER_OF_IDS];
int *T_active = T_IDs;
int T_stdout = 1;
static int T_socket;
/* T_cache
@@ -32,125 +34,159 @@ volatile int *T_freelist_head = &_T_freelist_head;
T_cache_t *T_cache;
#if BASIC_SIMULATOR
/* global variables used by T_GET_SLOT, see in T.h */
volatile uint64_t T_next_id;
volatile uint64_t T_active_id;
/* global variables used by T_GET_SLOT, see in T.h */
volatile uint64_t T_next_id;
volatile uint64_t T_active_id;
#endif
static void get_message(int s)
{
static void get_message(int s) {
char t;
int l;
int id;
int is_on;
if (read(s, &t, 1) != 1) QUIT("get_message fails");
printf("T tracer: got mess %d\n", t);
printf("T tracer: got mess %d\n", t);
switch (t) {
case 0:
/* toggle all those IDs */
/* optimze? (too much syscalls) */
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
while (l) {
if (read(s, &id, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
T_IDs[id] = 1 - T_IDs[id];
l--;
}
break;
case 1:
/* set IDs as given */
/* optimize? */
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
id = 0;
while (l) {
if (read(s, &is_on, sizeof(int)) != sizeof(int))
QUIT("get_message fails");
T_IDs[id] = is_on;
id++;
l--;
}
break;
case 2: break; /* do nothing, this message is to wait for local tracer */
case 0:
/* toggle all those IDs */
/* optimze? (too much syscalls) */
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
while (l) {
if (read(s, &id, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
T_IDs[id] = 1 - T_IDs[id];
l--;
}
break;
case 1:
/* set IDs as given */
/* optimize? */
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
id = 0;
while (l) {
if (read(s, &is_on, sizeof(int)) != sizeof(int))
QUIT("get_message fails");
T_IDs[id] = is_on;
id++;
l--;
}
break;
case 2:
break; /* do nothing, this message is to wait for local tracer */
}
}
static void *T_receive_thread(void *_)
{
static void *T_receive_thread(void *_) {
while (1) get_message(T_socket);
return NULL;
}
static void new_thread(void *(*f)(void *), void *data)
{
static void new_thread(void *(*f)(void *), void *data) {
pthread_t t;
pthread_attr_t att;
if (pthread_attr_init(&att))
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
if (pthread_create(&t, &att, f, data))
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
if (pthread_attr_destroy(&att))
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
if (pthread_attr_init(&att)) {
fprintf(stderr, "pthread_attr_init err\n");
exit(1);
}
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
fprintf(stderr, "pthread_attr_setdetachstate err\n");
exit(1);
}
if (pthread_create(&t, &att, f, data)) {
fprintf(stderr, "pthread_create err\n");
exit(1);
}
if (pthread_attr_destroy(&att)) {
fprintf(stderr, "pthread_attr_destroy err\n");
exit(1);
}
}
/* defined in local_tracer.c */
void T_local_tracer_main(int remote_port, int wait_for_tracer,
int local_socket, void *shm_array);
int local_socket, void *shm_array);
/* We monitor the tracee and the local tracer processes.
* When one dies we forcefully kill the other.
*/
#include <sys/types.h>
#include <sys/wait.h>
static void monitor_and_kill(int child1, int child2)
{
static void monitor_and_kill(int child1, int child2) {
int child;
int status;
child = wait(&status);
if (child == -1) perror("wait");
kill(child1, SIGKILL);
kill(child2, SIGKILL);
exit(0);
}
void T_init(int remote_port, int wait_for_tracer, int dont_fork)
{
void T_init(int remote_port, int wait_for_tracer, int dont_fork) {
int socket_pair[2];
int s;
int child1, child2;
int i;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair))
{ perror("socketpair"); abort(); }
if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair)) {
perror("socketpair");
abort();
}
/* setup shared memory */
T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (T_cache == MAP_FAILED)
{ perror("mmap"); abort(); }
if (T_cache == MAP_FAILED) {
perror("mmap");
abort();
}
/* let's garbage the memory to catch some potential problems
* (think multiprocessor sync issues, barriers, etc.)
*/
memset(T_cache, 0x55, T_CACHE_SIZE * sizeof(T_cache_t));
for (i = 0; i < T_CACHE_SIZE; i++) T_cache[i].busy = 0;
/* child1 runs the local tracer and child2 (or main) runs the tracee */
child1 = fork();
if (child1 == -1) abort();
child1 = fork(); if (child1 == -1) abort();
if (child1 == 0) {
close(socket_pair[1]);
T_local_tracer_main(remote_port, wait_for_tracer, socket_pair[0],
T_cache);
exit(0);
}
close(socket_pair[0]);
if (dont_fork == 0) {
child2 = fork(); if (child2 == -1) abort();
child2 = fork();
if (child2 == -1) abort();
if (child2 != 0) {
close(socket_pair[1]);
munmap(T_cache, T_CACHE_SIZE * sizeof(T_cache_t));
@@ -161,27 +197,21 @@ void T_init(int remote_port, int wait_for_tracer, int dont_fork)
s = socket_pair[1];
/* wait for first message - initial list of active T events */
get_message(s);
T_socket = s;
new_thread(T_receive_thread, NULL);
}
void T_Config_Init(void)
{
int T_port; /* by default we wait for the tracer */
int T_nowait; /* default port to listen to to wait for the tracer */
int T_dont_fork; /* default is to fork, see 'T_init' to understand */
void T_Config_Init(void) {
int T_port=TTRACER_DEFAULT_PORTNUM; /* by default we wait for the tracer */
int T_nowait=0; /* default port to listen to to wait for the tracer */
int T_dont_fork=0; /* default is to fork, see 'T_init' to understand */
paramdef_t ttraceparams[] = CMDLINE_TTRACEPARAMS_DESC;
/* for a cleaner config file, TTracer params should be defined in a
* specific section...
*/
config_get(ttraceparams,
sizeof(ttraceparams) / sizeof(paramdef_t),
TTRACER_CONFIG_PREFIX);
/* compatibility: look for TTracer command line options in root section */
config_process_cmdline(ttraceparams,
sizeof(ttraceparams) / sizeof(paramdef_t),
+41 -40
View File
@@ -8,7 +8,7 @@
#include "T_defs.h"
#ifdef T_SEND_TIME
#include <time.h>
#include <time.h>
#endif
/* T message IDs */
@@ -76,13 +76,13 @@
T_BUFFER_MAX - T_LOCAL_size, T_PUT_printf_deref x); \
if (T_PUT_len < 0) { \
printf("%s:%d:%s: you can't read this, or can you?", \
__FILE__, __LINE__, __FUNCTION__); \
__FILE__, __LINE__, __FUNCTION__); \
abort(); \
} \
if (T_PUT_len >= T_BUFFER_MAX - T_LOCAL_size) { \
printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \
", consider increasing T_BUFFER_MAX (%d)\n", \
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
", consider increasing T_BUFFER_MAX (%d)\n", \
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
abort(); \
} \
T_LOCAL_size += T_PUT_len + 1; \
@@ -97,9 +97,9 @@ struct T_header;
/* T macro tricks */
extern int T_stdout;
#define TN(...) TN_N(__VA_ARGS__,33,32,31,30,29,28,27,26,25,24,23,22,21,\
20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__)
20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__)
#define TN_N(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17,\
n18,n19,n20,n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32,n,...) T##n
n18,n19,n20,n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32,n,...) T##n
#define T(...) do { if (T_stdout == 0) TN(__VA_ARGS__); } while (0)
/* type used to send arbitrary buffer data */
@@ -119,30 +119,30 @@ extern int *T_active;
*/
#if BASIC_SIMULATOR
# define T_GET_SLOT \
do { \
extern volatile uint64_t T_next_id; \
extern volatile uint64_t T_active_id; \
uint64_t id; \
/* get a ticket */ \
id = __sync_fetch_and_add(&T_next_id, 1); \
/* wait for our turn */ \
while (id != __sync_fetch_and_add(&T_active_id, 0)) /* busy wait */; \
/* this is our turn, try to acquire the slot until it's free */ \
do { \
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01); \
if (T_LOCAL_busy & 0x01) usleep(100); \
} while (T_LOCAL_busy & 0x01); \
/* check that there are still some tickets */ \
if (__sync_fetch_and_add(&T_active_id, 0) == 0xffffffffffffffff) { \
printf("T: reached the end of times, bye...\n"); \
abort(); \
} \
/* free our ticket, which signals the next waiter that it's its turn */ \
(void)__sync_fetch_and_add(&T_active_id, 1); \
} while (0)
do { \
extern volatile uint64_t T_next_id; \
extern volatile uint64_t T_active_id; \
uint64_t id; \
/* get a ticket */ \
id = __sync_fetch_and_add(&T_next_id, 1); \
/* wait for our turn */ \
while (id != __sync_fetch_and_add(&T_active_id, 0)) /* busy wait */; \
/* this is our turn, try to acquire the slot until it's free */ \
do { \
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01); \
if (T_LOCAL_busy & 0x01) usleep(100); \
} while (T_LOCAL_busy & 0x01); \
/* check that there are still some tickets */ \
if (__sync_fetch_and_add(&T_active_id, 0) == 0xffffffffffffffff) { \
printf("T: reached the end of times, bye...\n"); \
abort(); \
} \
/* free our ticket, which signals the next waiter that it's its turn */ \
(void)__sync_fetch_and_add(&T_active_id, 1); \
} while (0)
#else
# define T_GET_SLOT \
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01);
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01);
#endif
/* used at header of Tn, allocates buffer */
@@ -172,8 +172,8 @@ extern int *T_active;
#define T_CHECK_SIZE(len, argnum) \
if (T_LOCAL_size + (len) > T_BUFFER_MAX) { \
printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \
", consider increasing T_BUFFER_MAX (%d)\n", \
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
", consider increasing T_BUFFER_MAX (%d)\n", \
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
abort(); \
}
@@ -598,20 +598,21 @@ extern int *T_active;
#define TTRACER_CONFIG_PREFIX "TTracer"
/*------------------------------------------------------------------------------------------------------------------------------------------*/
/* configuration parameters for TTRACE utility */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*------------------------------------------------------------------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
/* configuration parameters for TTRACE utility */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
#define TTRACER_DEFAULT_PORTNUM 2021
#define CMDLINE_TTRACEPARAMS_DESC { \
{"T_port", CONFIG_HLP_TPORT, 0, iptr:&T_port, defintval:2021, TYPE_INT, 0}, \
{"T_nowait", CONFIG_HLP_NOTWAIT, PARAMFLAG_BOOL, iptr:&T_nowait, defintval:0, TYPE_INT, 0}, \
{"T_dont_fork", CONFIG_HLP_TNOFORK, PARAMFLAG_BOOL, iptr:&T_dont_fork, defintval:0, TYPE_INT, 0}, \
{"T_stdout", CONFIG_HLP_STDOUT, PARAMFLAG_BOOL, iptr:&T_stdout, defintval:1, TYPE_INT, 0}, \
}
{"T_port", CONFIG_HLP_TPORT, 0, iptr:&T_port, defintval:TTRACER_DEFAULT_PORTNUM, TYPE_INT, 0},\
{"T_nowait", CONFIG_HLP_NOTWAIT, PARAMFLAG_BOOL, iptr:&T_nowait, defintval:0, TYPE_INT, 0},\
{"T_dont_fork", CONFIG_HLP_TNOFORK, PARAMFLAG_BOOL, iptr:&T_dont_fork, defintval:0, TYPE_INT, 0},\
{"T_stdout", CONFIG_HLP_STDOUT, PARAMFLAG_BOOL, iptr:&T_stdout, defintval:1, TYPE_INT, 0},\
}
/* log on stdout */
/* log on stdout */
void T_init(int remote_port, int wait_for_tracer, int dont_fork);
void T_Config_Init(void);
#else /* T_TRACER */
+94 -17
View File
@@ -629,7 +629,7 @@ ID = LEGACY_OCM_DEBUG
FORMAT = string,log
ID = LEGACY_OCM_TRACE
DESC = OCM legacy logs - trace level
GROUP = ALL:LEGACY_OCM:LEGACY_GROUP_TRACE:LEGACY
OGROUP = ALL:LEGACY_OCM:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
ID = LEGACY_OIP_INFO
@@ -800,6 +800,47 @@ ID = LEGACY_SIM_TRACE
GROUP = ALL:LEGACY_SIM:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_VNF_INFO
DESC = NFAPI_VNF legacy logs - info level
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_INFO:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_VNF_ERROR
DESC = NFAPI_VNF legacy logs - error level
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_ERROR:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_VNF_WARNING
DESC = NFAPI_VNF legacy logs - warning level
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_WARNING:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_VNF_DEBUG
DESC = NFAPI_VNF legacy logs - debug level
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_DEBUG:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_VNF_TRACE
DESC = NFAPI_VNF legacy logs - trace level
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_PNF_INFO
DESC = NFAPI_PNF legacy logs - info level
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_INFO:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_PNF_ERROR
DESC = NFAPI_PNF legacy logs - error level
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_ERROR:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_PNF_WARNING
DESC = NFAPI_PNF legacy logs - warning level
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_WARNING:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_PNF_DEBUG
DESC = NFAPI_PNF legacy logs - debug level
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_DEBUG:LEGACY
FORMAT = string,log
ID = LEGACY_NFAPI_PNF_TRACE
DESC = NFAPI_PNF legacy logs - trace level
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
# this is a bad hack but I won't fix (function util_print_hex_octets
# in openairinterface5g/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.c
# does funky things with the LOG_x macros but we work on the C pre-processor
@@ -845,26 +886,62 @@ ID = LEGACY_componentP_TRACE
GROUP = ALL:LEGACY_componentP:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
#needed?
ID = LEGACY_CLI_INFO
DESC = CLI legacy logs - info level
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_INFO:LEGACY
ID = LEGACY_PROTO_AGENT_DEBUG
DESC = PROTO AGENT DEBUG LEVEL
GROUP = ALL:LEGACY_PROTO:LEGACY_GROUP_DEBUG:LEGACY
FORMAT = string,log
ID = LEGACY_CLI_ERROR
DESC = CLI legacy logs - error level
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_ERROR:LEGACY
ID = LEGACY_PROTO_AGENT_INFO
DESC = PROTO AGENT INFO LEVEL
GROUP = ALL:LEGACY_PROTO:LEGACY_GROUP_INFO:LEGACY
FORMAT = string,log
ID = LEGACY_CLI_WARNING
DESC = CLI legacy logs - warning level
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_WARNING:LEGACY
ID = LEGACY_PROTO_AGENT_WARNING
DESC = PROTO AGENT WARNING LEVEL
GROUP = ALL:LEGACY_PROTO:LEGACY_GROUP_WARNING:LEGACY
FORMAT = string,log
ID = LEGACY_CLI_DEBUG
DESC = CLI legacy logs - debug level
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_DEBUG:LEGACY
ID = LEGACY_PROTO_AGENT_ERROR
DESC = PROTO AGENT ERROR LEVEL
GROUP = ALL:LEGACY_PROTO:LEGACY_GROUP_ERROR:LEGACY
FORMAT = string,log
ID = LEGACY_CLI_TRACE
DESC = CLI legacy logs - trace level
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_TRACE:LEGACY
ID = LEGACY_F1U_DEBUG
DESC = F1U DEBUG LEVEL
GROUP = ALL:LEGACY_F1U:LEGACY_GROUP_DEBUG:LEGACY
FORMAT = string,log
ID = LEGACY_F1U_INFO
DESC = F1U INFO LEVEL
GROUP = ALL:LEGACY_F1U:LEGACY_GROUP_INFO:LEGACY
FORMAT = string,log
ID = LEGACY_F1U_ERROR
DESC = F1U ERROR LEVEL
GROUP = ALL:LEGACY_F1U:LEGACY_GROUP_ERROR:LEGACY
FORMAT = string,log
ID = LEGACY_F1AP_TRACE
DESC = F1AP TRACE LEVEL
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
ID = LEGACY_F1AP_DEBUG
DESC = F1AP DEBUG LEVEL
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_DEBUG:LEGACY
FORMAT = string,log
ID = LEGACY_F1AP_INFO
DESC = F1AP INFO LEVEL
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_INFO:LEGACY
FORMAT = string,log
ID = LEGACY_F1AP_WARNING
DESC = F1AP WARNING LEVEL
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_WARNING:LEGACY
FORMAT = string,log
ID = LEGACY_F1AP_ERROR
DESC = F1AP ERROR LEVEL
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_ERROR:LEGACY
FORMAT = string,log
#################
+154 -94
View File
@@ -31,7 +31,7 @@ typedef struct {
int remote_port;
pthread_mutex_t lock;
pthread_cond_t cond;
databuf * volatile head, *tail;
databuf *volatile head, *tail;
uint64_t memusage;
uint64_t last_warning_memusage;
} forward_data;
@@ -40,80 +40,115 @@ typedef struct {
/* utility functions */
/****************************************************************************/
static void new_thread(void *(*f)(void *), void *data)
{
static void new_thread(void *(*f)(void *), void *data) {
pthread_t t;
pthread_attr_t att;
if (pthread_attr_init(&att))
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
if (pthread_attr_setstacksize(&att, 10000000))
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
if (pthread_create(&t, &att, f, data))
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
if (pthread_attr_destroy(&att))
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
if (pthread_attr_init(&att)) {
fprintf(stderr, "pthread_attr_init err\n");
exit(1);
}
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
fprintf(stderr, "pthread_attr_setdetachstate err\n");
exit(1);
}
if (pthread_attr_setstacksize(&att, 10000000)) {
fprintf(stderr, "pthread_attr_setstacksize err\n");
exit(1);
}
if (pthread_create(&t, &att, f, data)) {
fprintf(stderr, "pthread_create err\n");
exit(1);
}
if (pthread_attr_destroy(&att)) {
fprintf(stderr, "pthread_attr_destroy err\n");
exit(1);
}
}
static int get_connection(char *addr, int port)
{
static int get_connection(char *addr, int port) {
struct sockaddr_in a;
socklen_t alen;
int s, t;
printf("T tracer: waiting for connection on %s:%d\n", addr, port);
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) { perror("socket"); exit(1); }
if (s == -1) {
perror("socket");
exit(1);
}
t = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int)))
{ perror("setsockopt"); exit(1); }
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int))) {
perror("setsockopt");
exit(1);
}
a.sin_family = AF_INET;
a.sin_port = htons(port);
a.sin_addr.s_addr = inet_addr(addr);
if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); }
if (listen(s, 5)) { perror("bind"); exit(1); }
if (bind(s, (struct sockaddr *)&a, sizeof(a))) {
perror("bind");
exit(1);
}
if (listen(s, 5)) {
perror("bind");
exit(1);
}
alen = sizeof(a);
t = accept(s, (struct sockaddr *)&a, &alen);
if (t == -1) { perror("accept"); exit(1); }
if (t == -1) {
perror("accept");
exit(1);
}
close(s);
printf("T tracer: connected\n");
return t;
}
static void forward(void *_forwarder, char *buf, int size);
void send_T_messages_txt(void *forwarder)
{
void send_T_messages_txt(void *forwarder) {
char buf[T_BUFFER_MAX];
char *T_LOCAL_buf = buf;
int T_LOCAL_size;
unsigned char *src;
int src_len;
/* trace T_message.txt
* Send several messages -1 with content followed by message -2.
*/
src = T_messages_txt;
src_len = T_messages_txt_len;
while (src_len) {
int send_size = src_len;
if (send_size > T_PAYLOAD_MAXSIZE - sizeof(int))
send_size = T_PAYLOAD_MAXSIZE - sizeof(int);
/* TODO: be careful, we use internal T stuff, to rewrite? */
T_LOCAL_size = 0;
T_HEADER(T_ID(-1));
T_PUT_buffer(1, ((T_buffer){addr:(src), length:(send_size)}));
T_PUT_buffer(1, ((T_buffer) {
addr:
(src), length:
(send_size)
}));
forward(forwarder, buf, T_LOCAL_size);
src += send_size;
src_len -= send_size;
}
T_LOCAL_size = 0;
T_HEADER(T_ID(-2));
forward(forwarder, buf, T_LOCAL_size);
@@ -123,49 +158,54 @@ void send_T_messages_txt(void *forwarder)
/* forward functions */
/****************************************************************************/
static void *data_sender(void *_f)
{
static void *data_sender(void *_f) {
forward_data *f = _f;
databuf *cur;
char *buf, *b;
int size;
wait:
if (pthread_mutex_lock(&f->lock)) abort();
while (f->head == NULL)
if (pthread_cond_wait(&f->cond, &f->lock)) abort();
cur = f->head;
buf = cur->d;
size = cur->l;
f->head = cur->next;
f->memusage -= size;
if (f->head == NULL) f->tail = NULL;
if (pthread_mutex_unlock(&f->lock)) abort();
free(cur);
goto process;
process:
b = buf;
if (f->socket_remote != -1)
while (size) {
int l = write(f->socket_remote, b, size);
if (l <= 0) {
printf("T tracer: forward error\n");
close(f->socket_remote);
f->socket_remote = -1;
break;
while (size) {
int l = write(f->socket_remote, b, size);
if (l <= 0) {
printf("T tracer: forward error\n");
close(f->socket_remote);
f->socket_remote = -1;
break;
}
size -= l;
b += l;
}
size -= l;
b += l;
}
free(buf);
goto wait;
}
static void *forward_remote_messages(void *_f)
{
static void *forward_remote_messages(void *_f) {
#define PUT(x) do { \
if (bufsize == bufmaxsize) { \
bufmaxsize += 4096; \
@@ -180,7 +220,6 @@ static void *forward_remote_messages(void *_f)
int len = l; \
while (len) { PUT(*zz); zz++; len--; } \
} while (0)
forward_data *f = _f;
int from;
int to;
@@ -190,43 +229,53 @@ static void *forward_remote_messages(void *_f)
int bufsize = 0;
int bufmaxsize = 0;
char t;
again:
while (1) {
from = f->socket_remote;
to = f->socket_local;
bufsize = 0;
/* let's read and process messages */
len = read(from, &t, 1); if (len <= 0) goto dead;
len = read(from, &t, 1);
if (len <= 0) goto dead;
PUT(t);
switch (t) {
case 0:
case 1:
/* message 0 and 1: get a length and then 'length' numbers */
if (read(from, &len, sizeof(int)) != sizeof(int)) goto dead;
PUT_BUF(&len, 4);
while (len) {
if (read(from, &l, sizeof(int)) != sizeof(int)) goto dead;
PUT_BUF(&l, 4);
len--;
}
break;
case 0:
case 1:
case 2: break;
default:
printf("%s:%d:%s: unhandled message type %d\n",
__FILE__, __LINE__, __FUNCTION__, t);
abort();
/* message 0 and 1: get a length and then 'length' numbers */
if (read(from, &len, sizeof(int)) != sizeof(int)) goto dead;
PUT_BUF(&len, 4);
while (len) {
if (read(from, &l, sizeof(int)) != sizeof(int)) goto dead;
PUT_BUF(&l, 4);
len--;
}
break;
case 2:
break;
default:
printf("%s:%d:%s: unhandled message type %d\n",
__FILE__, __LINE__, __FUNCTION__, t);
abort();
}
b = buf;
while (bufsize) {
l = write(to, b, bufsize);
if (l <= 0) abort();
bufsize -= l;
b += l;
}
@@ -236,71 +285,80 @@ dead:
/* socket died, let's stop all traces and wait for another tracer */
/* TODO: be careful with those write, they might write less than wanted */
buf[0] = 1;
if (write(to, buf, 1) != 1) abort();
len = T_NUMBER_OF_IDS;
if (write(to, &len, sizeof(int)) != sizeof(int)) abort();
l = 0;
while (len) {
if (write(to, &l, sizeof(int)) != sizeof(int)) abort();
len--;
};
close(f->socket_remote);
f->socket_remote = get_connection("0.0.0.0", f->remote_port);
send_T_messages_txt(f);
goto again;
return NULL;
}
static void *forwarder(int port, int s)
{
static void *forwarder(int port, int s) {
forward_data *f;
f = malloc(sizeof(*f));
f = malloc(sizeof(*f)); if (f == NULL) abort();
if (f == NULL) abort();
pthread_mutex_init(&f->lock, NULL);
pthread_cond_init(&f->cond, NULL);
f->socket_local = s;
f->head = f->tail = NULL;
f->memusage = 0;
f->last_warning_memusage = 0;
printf("T tracer: waiting for remote tracer on port %d\n", port);
f->remote_port = port;
f->socket_remote = get_connection("0.0.0.0", port);
send_T_messages_txt(f);
new_thread(data_sender, f);
new_thread(forward_remote_messages, f);
return f;
}
static void forward(void *_forwarder, char *buf, int size)
{
static void forward(void *_forwarder, char *buf, int size) {
forward_data *f = _forwarder;
int32_t ssize = size;
databuf *new;
new = malloc(sizeof(*new));
new = malloc(sizeof(*new)); if (new == NULL) abort();
if (new == NULL) abort();
if (pthread_mutex_lock(&f->lock)) abort();
new->d = malloc(size + 4); if (new->d == NULL) abort();
new->d = malloc(size + 4);
if (new->d == NULL) abort();
/* put the size of the message at the head */
memcpy(new->d, &ssize, 4);
memcpy(new->d+4, buf, size);
new->l = size+4;
new->next = NULL;
if (f->head == NULL) f->head = new;
if (f->tail != NULL) f->tail->next = new;
f->tail = new;
if (f->head == NULL) f->head = new;
if (f->tail != NULL) f->tail->next = new;
f->tail = new;
#if BASIC_SIMULATOR
/* When runnng the basic simulator, the tracer may be too slow.
* Let's not take too much memory in the tracee and
* wait if there is too much data to send. 200MB is
@@ -308,26 +366,30 @@ static void forward(void *_forwarder, char *buf, int size)
*/
while (f->memusage > 200 * 1024 * 1024) {
if (pthread_cond_signal(&f->cond)) abort();
if (pthread_mutex_unlock(&f->lock)) abort();
usleep(1000);
if (pthread_mutex_lock(&f->lock)) abort();
}
#endif /* BASIC_SIMULATOR */
#endif /* BASIC_SIMULATOR */
f->memusage += size+4;
/* warn every 100MB */
if (f->memusage > f->last_warning_memusage &&
f->memusage - f->last_warning_memusage > 100000000) {
f->last_warning_memusage += 100000000;
printf("T tracer: WARNING: memory usage is over %"PRIu64"MB\n",
f->last_warning_memusage / 1000000);
} else
if (f->memusage < f->last_warning_memusage &&
f->last_warning_memusage - f->memusage > 100000000) {
} else if (f->memusage < f->last_warning_memusage &&
f->last_warning_memusage - f->memusage > 100000000) {
f->last_warning_memusage = (f->memusage/100000000) * 100000000;
}
if (pthread_cond_signal(&f->cond)) abort();
if (pthread_mutex_unlock(&f->lock)) abort();
}
@@ -335,14 +397,12 @@ static void forward(void *_forwarder, char *buf, int size)
/* local functions */
/****************************************************************************/
static void wait_message(void)
{
static void wait_message(void) {
while ((T_local_cache[T_busylist_head].busy & 0x02) == 0) usleep(1000);
}
void T_local_tracer_main(int remote_port, int wait_for_tracer,
int local_socket, void *shm_array)
{
int local_socket, void *shm_array) {
int s;
int port = remote_port;
int dont_wait = wait_for_tracer ? 0 : 1;
@@ -350,16 +410,16 @@ void T_local_tracer_main(int remote_port, int wait_for_tracer,
/* write on a socket fails if the other end is closed and we get SIGPIPE */
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
printf("local tracer received SIGPIPE\n");
abort();
printf("local tracer received SIGPIPE\n");
abort();
}
T_local_cache = shm_array;
s = local_socket;
if (dont_wait) {
char t = 2;
if (write(s, &t, 1) != 1) abort();
}
+16 -23
View File
@@ -5,62 +5,56 @@
#include <string.h>
unsigned long register_notifier(gui *_g, char *notification, widget *w,
notifier handler, void *private)
{
notifier handler, void *private) {
struct gui *g = _g;
unsigned long ret;
glock(g);
if (g->next_notifier_id == 2UL * 1024 * 1024 * 1024)
ERR("%s:%d: report a bug\n", __FILE__, __LINE__);
g->notifiers = realloc(g->notifiers,
(g->notifiers_count+1) * sizeof(struct notifier));
(g->notifiers_count+1) * sizeof(struct notifier));
if (g->notifiers == NULL) abort();
ret = g->next_notifier_id;
g->notifiers[g->notifiers_count].handler = handler;
g->notifiers[g->notifiers_count].id = g->next_notifier_id;
g->next_notifier_id++;
g->notifiers[g->notifiers_count].notification = strdup(notification);
if (g->notifiers[g->notifiers_count].notification == NULL) abort();
g->notifiers[g->notifiers_count].w = w;
g->notifiers[g->notifiers_count].private = private;
/* initialize done to 1 so as not to call the handler if it's created
* by the call of another one that is in progress
*/
g->notifiers[g->notifiers_count].done = 1;
g->notifiers_count++;
gunlock(g);
return ret;
}
void unregister_notifier(gui *_g, unsigned long notifier_id)
{
void unregister_notifier(gui *_g, unsigned long notifier_id) {
struct gui *g = _g;
int i;
glock(g);
for (i = 0; i < g->notifiers_count; i++)
if (g->notifiers[i].id == notifier_id) break;
if (i == g->notifiers_count)
ERR("%s:%d: notifier_id %ld not found\n", __FILE__,__LINE__,notifier_id);
ERR("%s:%d: notifier_id %lu not found\n", __FILE__,__LINE__,notifier_id);
free(g->notifiers[i].notification);
memmove(g->notifiers + i, g->notifiers + i + 1,
(g->notifiers_count-1 - i) * sizeof(struct notifier));
(g->notifiers_count-1 - i) * sizeof(struct notifier));
g->notifiers_count--;
g->notifiers = realloc(g->notifiers,
g->notifiers_count * sizeof(struct notifier));
g->notifiers_count * sizeof(struct notifier));
if (g->notifiers == NULL) abort();
gunlock(g);
@@ -68,19 +62,19 @@ void unregister_notifier(gui *_g, unsigned long notifier_id)
/* called with lock ON */
void gui_notify(struct gui *g, char *notification, widget *w,
void *notification_data)
{
void *notification_data) {
void *private;
notifier handler;
int i;
/* this function is not re-entrant, for the moment keep as is
* and if the need is there, we'll make a new thread to handle
* notifications (or something)
* for now let's crash in case of recursive call
*/
static int inside = 0;
if (inside) ERR("%s:%d: BUG! contact the authors\n", __FILE__, __LINE__);
inside = 1;
/* clear all handlers */
@@ -91,26 +85,25 @@ void gui_notify(struct gui *g, char *notification, widget *w,
* need to be careful here
*/
loop:
for (i = 0; i < g->notifiers_count; i++) {
if (g->notifiers[i].done == 1 ||
g->notifiers[i].w != w ||
strcmp(g->notifiers[i].notification, notification) != 0)
continue;
break;
}
if (i == g->notifiers_count) goto done;
g->notifiers[i].done = 1;
handler = g->notifiers[i].handler;
private = g->notifiers[i].private;
gunlock(g);
handler(private, g, notification, w, notification_data);
glock(g);
goto loop;
done:
inside = 0;
}
+4 -1
View File
@@ -3,7 +3,7 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I. -I..
LIBS=-lX11 -lm -lpng -lXft
all: dump_nack_signal time_meas timeplot
all: dump_nack_signal time_meas timeplot multi-rru-clean
dump_nack_signal: ../utils.o ../database.o ../config.o ../event.o \
dump_nack_signal.o
@@ -16,6 +16,9 @@ time_meas: ../utils.o ../database.o ../config.o ../event.o \
timplot: timeplot.o
$(CC) $(CFLAGS) -o timeplot $^ $(LIBS)
multi-rru-clean: ../utils.o ../database.o ../event.o ../config.o multi-rru-clean.o
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
.PHONY: all
%.o: %.c
+68 -32
View File
@@ -7,21 +7,19 @@
#include "config.h"
#include "../T_defs.h"
void usage(void)
{
void usage(void) {
printf(
"options:\n"
" -d <database file> this option is mandatory\n"
" -ip <host> connect to given IP address (default %s)\n"
" -p <port> connect to given port (default %d)\n",
DEFAULT_REMOTE_IP,
DEFAULT_REMOTE_PORT
"options:\n"
" -d <database file> this option is mandatory\n"
" -ip <host> connect to given IP address (default %s)\n"
" -p <port> connect to given port (default %d)\n",
DEFAULT_REMOTE_IP,
DEFAULT_REMOTE_PORT
);
exit(1);
}
int main(int n, char **v)
{
int main(int n, char **v) {
char *database_filename = NULL;
void *database;
char *ip = DEFAULT_REMOTE_IP;
@@ -36,11 +34,28 @@ int main(int n, char **v)
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
if (!strcmp(v[i], "-d"))
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
if (!strcmp(v[i], "-p"))
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
if (!strcmp(v[i], "-d")) {
if (i > n-2) usage();
database_filename = v[++i];
continue;
}
if (!strcmp(v[i], "-ip")) {
if (i > n-2) usage();
ip = v[++i];
continue;
}
if (!strcmp(v[i], "-p")) {
if (i > n-2) usage();
port = atoi(v[++i]);
continue;
}
usage();
}
@@ -50,71 +65,92 @@ int main(int n, char **v)
}
database = parse_database(database_filename);
load_config_file(database_filename);
number_of_events = number_of_ids(database);
is_on = calloc(number_of_events, sizeof(int));
if (is_on == NULL) abort();
on_off(database, "ENB_PHY_INPUT_SIGNAL", is_on, 1);
on_off(database, "ENB_PHY_ULSCH_UE_NACK", is_on, 1);
on_off(database, "ENB_PHY_ULSCH_UE_ACK", is_on, 1);
ev_input = event_id_from_name(database, "ENB_PHY_INPUT_SIGNAL");
ev_nack = event_id_from_name(database, "ENB_PHY_ULSCH_UE_NACK");
ev_ack = event_id_from_name(database, "ENB_PHY_ULSCH_UE_ACK");
socket = connect_to(ip, port);
t = 1;
if (socket_send(socket, &t, 1) == -1 ||
socket_send(socket, &number_of_events, sizeof(int)) == -1 ||
socket_send(socket, is_on, number_of_events * sizeof(int)) == -1)
abort();
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
char dump[10][T_BUFFER_MAX];
event dump_ev[10];
FILE *z = fopen("/tmp/dd", "w"); if (z == NULL) abort();
FILE *z = fopen("/tmp/dd", "w");
if (z == NULL) abort();
while (1) {
char *v;
event e;
e = get_event(socket, &ebuf, database);
v = ebuf.obuf;
if (e.type == -1) break;
if (e.type == ev_input) {
int sf = e.e[2].i;
if (ebuf.osize > T_BUFFER_MAX)
{ printf("event size too big\n"); exit(1); }
if (ebuf.osize > T_BUFFER_MAX) {
printf("event size too big\n");
exit(1);
}
memcpy(dump[sf], ebuf.obuf, ebuf.osize);
dump_ev[sf] = e;
printf("input %d/%d\n", e.e[1].i, sf);
if (fwrite(dump_ev[sf].e[4].b, dump_ev[sf].e[4].bsize, 1, z) != 1) abort();
fflush(z);
if (fwrite(dump_ev[sf].e[4].b, dump_ev[sf].e[4].bsize, 1, z) != 1) abort();
fflush(z);
}
if (e.type == ev_nack) {
int sf = e.e[2].i;
printf("nack %d/%d\n", e.e[1].i, sf);
FILE *f = fopen("/tmp/dump.raw", "w"); if (f == NULL) abort();
FILE *f = fopen("/tmp/dump.raw", "w");
if (f == NULL) abort();
if (fwrite(dump[sf] + ((char *)dump_ev[sf].e[4].b - v),
dump_ev[sf].e[4].bsize, 1, f) != 1) abort();
dump_ev[sf].e[4].bsize, 1, f) != 1) abort();
if (fclose(f)) abort();
printf("dumped... press enter (delta %d)\n", (int)((char *)dump_ev[sf].e[4].b - v));
// getchar();
// getchar();
}
if (e.type == ev_ack) {
int sf = e.e[2].i;
printf("ack %d/%d\n", e.e[1].i, sf);
FILE *f = fopen("/tmp/dump.raw", "w"); if (f == NULL) abort();
FILE *f = fopen("/tmp/dump.raw", "w");
if (f == NULL) abort();
if (fwrite(dump[sf] + ((char *)dump_ev[sf].e[4].b - v),
dump_ev[sf].e[4].bsize, 1, f) != 1) abort();
dump_ev[sf].e[4].bsize, 1, f) != 1) abort();
if (fclose(f)) abort();
printf("dumped... press enter (delta %d)\n", (int)((char *)dump_ev[sf].e[4].b - v));
// getchar();
// getchar();
}
}
if (z)
fclose(z);
return 0;
}
@@ -0,0 +1,230 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "database.h"
#include "utils.h"
#include "event.h"
#include "../T_defs.h"
void usage(void)
{
printf(
"usage: <number of tags> <input record file> <output curated record file>\n"
"options:\n"
" -d <database file> this option is mandatory\n"
);
exit(1);
}
#define ERR printf("ERROR: read file %s failed\n", input_filename)
typedef struct {
OBUF b;
struct timespec t;
int filled;
int error;
} cache_t;
void clear_cache(int n, cache_t *c)
{
int i;
for (i = 0; i < n; i++) {
c[i].filled = 0;
c[i].error = 0;
c[i].b.osize = 0;
}
}
void store_in_cache(cache_t *c, int pos, OBUF *b)
{
int i;
for (i = 0; i < b->osize; i++)
PUTC(&c[pos].b, b->obuf[i]);
}
int get_field(database_event_format *f, char *field, char *type)
{
int i;
for (i = 0; i < f->count; i++)
if (!strcmp(f->name[i], field)) {
if (strcmp(f->type[i], type)) break;
return i;
}
printf("bad field %s, check that it exists and has type '%s'\n",field,type);
exit(1);
}
void process_cache(FILE *out, cache_t *c, int n, int frame, int subframe)
{
int i;
struct tm *t;
for (i = 0; i < n; i++)
if (c[i].filled == 0 || c[i].error == 1)
goto error;
for (i = 0; i < n; i++)
fwrite(c[i].b.obuf, c[i].b.osize, 1, out);
clear_cache(n, c);
return;
error:
printf("ERROR: incorrect data at frame %d subframe %d", frame, subframe);
for (i = 0; i < n; i++) if (c[i].filled) {
t = localtime(&c[i].t.tv_sec);
printf(" [tag %d time %2.2d:%2.2d:%2.2d.%9.9ld]", i,
t->tm_hour, t->tm_min, t->tm_sec, c[i].t.tv_nsec);
}
printf("\n");
clear_cache(n, c);
}
int main(int n, char **v)
{
char *database_filename = NULL;
void *database;
int channel_estimate_id;
int number_of_tags = -1;
char *input_filename = NULL;
char *output_filename = NULL;
int i;
FILE *in;
FILE *out;
database_event_format f;
int frame_arg;
int subframe_arg;
int tag_arg;
cache_t *cache;
int cur_frame = -1;
int cur_subframe = -1;
int frame;
int subframe;
int tag;
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
if (!strcmp(v[i], "-d")) { if (i > n-2) usage();
database_filename = v[++i]; continue; }
if (number_of_tags == -1) { number_of_tags = atoi(v[i]);
if (number_of_tags <= 0) {usage();} continue; }
if (input_filename == NULL) { input_filename = v[i]; continue; }
if (output_filename == NULL) { output_filename = v[i]; continue; }
usage();
}
if (database_filename == NULL) {
printf("ERROR: provide a database file (-d)\n");
exit(1);
}
if (output_filename == NULL || input_filename == NULL || number_of_tags == -1)
usage();
database = parse_database(database_filename);
channel_estimate_id = event_id_from_name(database, "CALIBRATION_CHANNEL_ESTIMATES");
f = get_format(database, channel_estimate_id);
frame_arg = get_field(&f, "frame", "int");
subframe_arg = get_field(&f, "subframe", "int");
tag_arg = get_field(&f, "tag", "int");
in = fopen(input_filename, "r");
if (in == NULL) { perror(input_filename); abort(); }
out = fopen(output_filename, "w");
if (out == NULL) { perror(output_filename); abort(); }
cache = calloc(number_of_tags, sizeof(cache_t));
if (cache == NULL) { perror("malloc"); exit(1); }
clear_cache(number_of_tags, cache);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
while (1) {
int type;
int32_t length;
char *v;
int vpos = 0;
struct timespec t;
char *buf;
/* read event from file */
if (fread(&length, 4, 1, in) != 1) break;
if (ebuf.omaxsize < length) {
ebuf.omaxsize = (length + 65535) & ~65535;
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
}
v = ebuf.obuf;
memcpy(v+vpos, &length, 4);
vpos += 4;
#ifdef T_SEND_TIME
if (length < sizeof(struct timespec)) { ERR; break; }
if (fread(&t, sizeof(struct timespec), 1, in) != 1) { ERR; break; }
memcpy(v+vpos, &t, sizeof(struct timespec));
vpos += sizeof(struct timespec);
length -= sizeof(struct timespec);
#endif
if (length < sizeof(int)) { ERR; break; }
if (fread(&type, sizeof(int), 1, in) != 1) { ERR; break; }
memcpy(v+vpos, &type, sizeof(int));
vpos += sizeof(int);
length -= sizeof(int);
if (length) if (fread(v+vpos, length, 1, in) != 1) { ERR; break; }
buf = v + vpos;
vpos += length;
ebuf.osize = vpos;
if (type != channel_estimate_id) continue;
event e;
#ifdef T_SEND_TIME
e = new_event(t, type, length, buf, database);
#else
e = new_event(type, length, buf, database);
#endif
frame = e.e[frame_arg].i;
subframe = e.e[subframe_arg].i;
tag = e.e[tag_arg].i;
if (tag < 0 || tag >= number_of_tags) {
struct tm *tt;
tt = localtime(&t.tv_sec);
printf("ERROR: invalid tag (%d), skipping event for frame %d subframe %d (time %2.2d:%2.2d:%2.2d.%9.9ld)\n",
tag, frame, subframe,
tt->tm_hour, tt->tm_min, tt->tm_sec, t.tv_nsec);
continue;
}
if (cur_frame != frame || cur_subframe != subframe)
if (cur_frame != -1)
process_cache(out, cache, number_of_tags, cur_frame, cur_subframe);
cur_frame = frame;
cur_subframe = subframe;
if (cache[tag].filled) {
struct tm *tt;
tt = localtime(&t.tv_sec);
printf("ERROR: tag %d present twice at frame %d subframe %d (time %2.2d:%2.2d:%2.2d.%9.9ld)\n",
tag, frame, subframe,
tt->tm_hour, tt->tm_min, tt->tm_sec, t.tv_nsec);
cache[tag].error = 1;
continue;
}
store_in_cache(cache, tag, &ebuf);
cache[tag].filled = 1;
cache[tag].t = t;
}
if (fclose(in)) perror(input_filename);
if (fclose(out)) perror(output_filename);
free(cache);
return 0;
}
+149 -83
View File
@@ -58,14 +58,11 @@ typedef struct {
} ev_data;
void trace(ev_data *d, int direction, int rnti_type, int rnti,
int frame, int subframe, void *buf, int bufsize, int preamble)
{
int frame, int subframe, void *buf, int bufsize, int preamble) {
ssize_t ret;
int fsf;
int i;
d->buf.osize = 0;
PUTS(&d->buf, MAC_LTE_START_STRING);
PUTC(&d->buf, FDD_RADIO);
PUTC(&d->buf, direction);
@@ -92,16 +89,17 @@ void trace(ev_data *d, int direction, int rnti_type, int rnti,
}
PUTC(&d->buf, MAC_LTE_PAYLOAD_TAG);
for (i = 0; i < bufsize; i++)
PUTC(&d->buf, ((char*)buf)[i]);
PUTC(&d->buf, ((char *)buf)[i]);
ret = sendto(d->socket, d->buf.obuf, d->buf.osize, 0,
(struct sockaddr *)&d->to, sizeof(struct sockaddr_in));
(struct sockaddr *)&d->to, sizeof(struct sockaddr_in));
if (ret != d->buf.osize) abort();
}
void ul(void *_d, event e)
{
void ul(void *_d, event e) {
ev_data *d = _d;
trace(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i,
e.e[d->ul_frame].i, e.e[d->ul_subframe].i,
@@ -109,13 +107,14 @@ void ul(void *_d, event e)
NO_PREAMBLE);
}
void dl(void *_d, event e)
{
void dl(void *_d, event e) {
ev_data *d = _d;
if (e.e[d->dl_rnti].i == 0xffff) {
if (d->no_sib) return;
if (d->max_sib && d->cur_sib == d->max_sib) return;
d->cur_sib++;
}
@@ -126,22 +125,21 @@ void dl(void *_d, event e)
NO_PREAMBLE);
}
void mib(void *_d, event e)
{
void mib(void *_d, event e) {
ev_data *d = _d;
if (d->no_mib) return;
if (d->max_mib && d->cur_mib == d->max_mib) return;
d->cur_mib++;
if (d->max_mib && d->cur_mib == d->max_mib) return;
d->cur_mib++;
trace(d, DIRECTION_DOWNLINK, NO_RNTI, 0,
e.e[d->mib_frame].i, e.e[d->mib_subframe].i,
e.e[d->mib_data].b, e.e[d->mib_data].bsize,
NO_PREAMBLE);
}
void preamble(void *_d, event e)
{
void preamble(void *_d, event e) {
ev_data *d = _d;
trace(d, DIRECTION_UPLINK, NO_RNTI, 0,
e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i,
@@ -149,8 +147,7 @@ void preamble(void *_d, event e)
e.e[d->preamble_preamble].i);
}
void rar(void *_d, event e)
{
void rar(void *_d, event e) {
ev_data *d = _d;
trace(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i,
e.e[d->rar_frame].i, e.e[d->rar_subframe].i,
@@ -159,114 +156,118 @@ void rar(void *_d, event e)
}
void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
int preamble_id, int rar_id)
{
int preamble_id, int rar_id) {
database_event_format f;
int i;
d->ul_rnti = -1;
d->ul_frame = -1;
d->ul_subframe = -1;
d->ul_data = -1;
d->dl_rnti = -1;
d->dl_frame = -1;
d->dl_subframe = -1;
d->dl_data = -1;
d->mib_frame = -1;
d->mib_subframe = -1;
d->mib_data = -1;
d->preamble_frame = -1;
d->preamble_subframe = -1;
d->preamble_preamble = -1;
d->rar_rnti = -1;
d->rar_frame = -1;
d->rar_subframe = -1;
d->rar_data = -1;
#define G(var_name, var_type, var) \
if (!strcmp(f.name[i], var_name)) { \
if (strcmp(f.type[i], var_type)) goto error; \
var = i; \
continue; \
}
/* ul: rnti, frame, subframe, data */
f = get_format(database, ul_id);
for (i = 0; i < f.count; i++) {
G("rnti", "int", d->ul_rnti);
G("frame", "int", d->ul_frame);
G("subframe", "int", d->ul_subframe);
G("data", "buffer", d->ul_data);
}
if (d->ul_rnti == -1 || d->ul_frame == -1 || d->ul_subframe == -1 ||
d->ul_data == -1) goto error;
/* dl: rnti, frame, subframe, data */
f = get_format(database, dl_id);
for (i = 0; i < f.count; i++) {
G("rnti", "int", d->dl_rnti);
G("frame", "int", d->dl_frame);
G("subframe", "int", d->dl_subframe);
G("data", "buffer", d->dl_data);
}
if (d->dl_rnti == -1 || d->dl_frame == -1 || d->dl_subframe == -1 ||
d->dl_data == -1) goto error;
/* MIB: frame, subframe, data */
f = get_format(database, mib_id);
for (i = 0; i < f.count; i++) {
G("frame", "int", d->mib_frame);
G("subframe", "int", d->mib_subframe);
G("data", "buffer", d->mib_data);
}
if (d->mib_frame == -1 || d->mib_subframe == -1 || d->mib_data == -1)
goto error;
/* preamble: frame, subframe, preamble */
f = get_format(database, preamble_id);
for (i = 0; i < f.count; i++) {
G("frame", "int", d->preamble_frame);
G("subframe", "int", d->preamble_subframe);
G("preamble", "int", d->preamble_preamble);
}
if (d->preamble_frame == -1 || d->preamble_subframe == -1 ||
d->preamble_preamble == -1) goto error;
/* rar: rnti, frame, subframe, data */
f = get_format(database, rar_id);
for (i = 0; i < f.count; i++) {
G("rnti", "int", d->rar_rnti);
G("frame", "int", d->rar_frame);
G("subframe", "int", d->rar_subframe);
G("data", "buffer", d->rar_data);
}
if (d->rar_rnti == -1 || d->rar_frame == -1 || d->rar_subframe == -1 ||
d->rar_data == -1) goto error;
#undef G
return;
error:
printf("bad T_messages.txt\n");
abort();
}
void *receiver(void *_d)
{
void *receiver(void *_d) {
ev_data *d = _d;
int s;
char buf[100000];
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1) { perror("socket"); abort(); }
if (bind(s, (struct sockaddr *)&d->to, sizeof(struct sockaddr_in)) == -1)
{ perror("bind"); abort(); }
if (s == -1) {
perror("socket");
abort();
}
if (bind(s, (struct sockaddr *)&d->to, sizeof(struct sockaddr_in)) == -1) {
perror("bind");
abort();
}
while (1) {
if (recv(s, buf, 100000, 0) <= 0) abort();
@@ -275,33 +276,31 @@ void *receiver(void *_d)
return 0;
}
void usage(void)
{
void usage(void) {
printf(
"options:\n"
" -d <database file> this option is mandatory\n"
" -i <dump file> read events from this dump file\n"
" -ip <IP address> send packets to this IP address (default %s)\n"
" -p <port> send packets to this port (default %d)\n"
" -no-mib do not report MIB\n"
" -no-sib do not report SIBs\n"
" -max-mib <n> report at maximum n MIB\n"
" -max-sib <n> report at maximum n SIBs\n"
" -live run live\n"
" -live-ip <IP address> tracee's IP address (default %p)\n"
" -live-port <por> tracee's port (default %d)\n"
"-i and -live are mutually exclusive options. One of them must be provided\n"
"but not both.\n",
DEFAULT_IP,
DEFAULT_PORT,
DEFAULT_LIVE_IP,
DEFAULT_LIVE_PORT
"options:\n"
" -d <database file> this option is mandatory\n"
" -i <dump file> read events from this dump file\n"
" -ip <IP address> send packets to this IP address (default %s)\n"
" -p <port> send packets to this port (default %d)\n"
" -no-mib do not report MIB\n"
" -no-sib do not report SIBs\n"
" -max-mib <n> report at maximum n MIB\n"
" -max-sib <n> report at maximum n SIBs\n"
" -live run live\n"
" -live-ip <IP address> tracee's IP address (default %s)\n"
" -live-port <port> tracee's port (default %d)\n"
"-i and -live are mutually exclusive options. One of them must be provided\n"
"but not both.\n",
DEFAULT_IP,
DEFAULT_PORT,
DEFAULT_LIVE_IP,
DEFAULT_LIVE_PORT
);
exit(1);
}
int main(int n, char **v)
{
int main(int n, char **v) {
char *database_filename = NULL;
char *input_filename = NULL;
void *database;
@@ -315,28 +314,82 @@ int main(int n, char **v)
char *live_ip = DEFAULT_LIVE_IP;
int live_port = DEFAULT_LIVE_PORT;
int live = 0;
memset(&d, 0, sizeof(ev_data));
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
if (!strcmp(v[i], "-d"))
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
if (!strcmp(v[i], "-i"))
{ if (i > n-2) usage(); input_filename = v[++i]; continue; }
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
if (!strcmp(v[i], "-p")) {if(i>n-2)usage(); port=atoi(v[++i]); continue; }
if (!strcmp(v[i], "-no-mib")) { d.no_mib = 1; continue; }
if (!strcmp(v[i], "-no-sib")) { d.no_sib = 1; continue; }
if (!strcmp(v[i], "-max-mib"))
{ if (i > n-2) usage(); d.max_mib = atoi(v[++i]); continue; }
if (!strcmp(v[i], "-max-sib"))
{ if (i > n-2) usage(); d.max_sib = atoi(v[++i]); continue; }
if (!strcmp(v[i], "-live")) { live = 1; continue; }
if (!strcmp(v[i], "-live-ip"))
{ if (i > n-2) usage(); live_ip = v[++i]; continue; }
if (!strcmp(v[i], "-live-port"))
{ if (i > n-2) usage(); live_port = atoi(v[++i]); continue; }
if (!strcmp(v[i], "-d")) {
if (i > n-2) usage();
database_filename = v[++i];
continue;
}
if (!strcmp(v[i], "-i")) {
if (i > n-2) usage();
input_filename = v[++i];
continue;
}
if (!strcmp(v[i], "-ip")) {
if (i > n-2) usage();
ip = v[++i];
continue;
}
if (!strcmp(v[i], "-p")) {
if(i>n-2)usage();
port=atoi(v[++i]);
continue;
}
if (!strcmp(v[i], "-no-mib")) {
d.no_mib = 1;
continue;
}
if (!strcmp(v[i], "-no-sib")) {
d.no_sib = 1;
continue;
}
if (!strcmp(v[i], "-max-mib")) {
if (i > n-2) usage();
d.max_mib = atoi(v[++i]);
continue;
}
if (!strcmp(v[i], "-max-sib")) {
if (i > n-2) usage();
d.max_sib = atoi(v[++i]);
continue;
}
if (!strcmp(v[i], "-live")) {
live = 1;
continue;
}
if (!strcmp(v[i], "-live-ip")) {
if (i > n-2) usage();
live_ip = v[++i];
continue;
}
if (!strcmp(v[i], "-live-port")) {
if (i > n-2) usage();
live_port = atoi(v[++i]);
continue;
}
usage();
}
@@ -357,25 +410,34 @@ int main(int n, char **v)
if (live == 0) {
in = open(input_filename, O_RDONLY);
if (in == -1) { perror(input_filename); return 1; }
if (in == -1) {
perror(input_filename);
return 1;
}
} else
in = connect_to(live_ip, live_port);
database = parse_database(database_filename);
load_config_file(database_filename);
h = new_handler(database);
if (live) {
char mt = 1;
int number_of_events = number_of_ids(database);
int *is_on = calloc(number_of_events, sizeof(int));
if (is_on == NULL) { printf("ERROR: out of memory\n"); exit(1); }
if (is_on == NULL) {
printf("ERROR: out of memory\n");
exit(1);
}
on_off(database, "ENB_MAC_UE_UL_PDU_WITH_DATA", is_on, 1);
on_off(database, "ENB_MAC_UE_DL_PDU_WITH_DATA", is_on, 1);
on_off(database, "ENB_PHY_MIB", is_on, 1);
on_off(database, "ENB_PHY_INITIATE_RA_PROCEDURE", is_on, 1);
on_off(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA", is_on, 1);
/* activate selected traces */
if (socket_send(in, &mt, 1) == -1 ||
socket_send(in, &number_of_events, sizeof(int)) == -1 ||
@@ -383,6 +445,7 @@ int main(int n, char **v)
printf("ERROR: socket_send failed\n");
exit(1);
}
free(is_on);
}
@@ -392,31 +455,34 @@ int main(int n, char **v)
preamble_id = event_id_from_name(database, "ENB_PHY_INITIATE_RA_PROCEDURE");
rar_id = event_id_from_name(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA");
setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id);
register_handler_function(h, ul_id, ul, &d);
register_handler_function(h, dl_id, dl, &d);
register_handler_function(h, mib_id, mib, &d);
register_handler_function(h, preamble_id, preamble, &d);
register_handler_function(h, rar_id, rar, &d);
d.socket = socket(AF_INET, SOCK_DGRAM, 0);
if (d.socket == -1) { perror("socket"); exit(1); }
if (d.socket == -1) {
perror("socket");
exit(1);
}
d.to.sin_family = AF_INET;
d.to.sin_port = htons(port);
d.to.sin_addr.s_addr = inet_addr(ip);
new_thread(receiver, &d);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
/* read messages */
while (1) {
event e;
e = get_event(in, &ebuf, database);
if (e.type == -1) break;
if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id ||
e.type == preamble_id || e.type == rar_id)) continue;
handle_event(h, e);
}
+3
View File
@@ -195,5 +195,8 @@ int main(int n, char **v)
handle_event(h, e);
}
free(on_off_name);
free(on_off_action);
return 0;
}
+100 -67
View File
@@ -9,27 +9,38 @@
#include <arpa/inet.h>
#include <math.h>
void new_thread(void *(*f)(void *), void *data)
{
void new_thread(void *(*f)(void *), void *data) {
pthread_t t;
pthread_attr_t att;
if (pthread_attr_init(&att))
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
if (pthread_attr_setstacksize(&att, 10000000))
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
if (pthread_create(&t, &att, f, data))
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
if (pthread_attr_destroy(&att))
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
if (pthread_attr_init(&att)) {
fprintf(stderr, "pthread_attr_init err\n");
exit(1);
}
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
fprintf(stderr, "pthread_attr_setdetachstate err\n");
exit(1);
}
if (pthread_attr_setstacksize(&att, 10000000)) {
fprintf(stderr, "pthread_attr_setstacksize err\n");
exit(1);
}
if (pthread_create(&t, &att, f, data)) {
fprintf(stderr, "pthread_create err\n");
exit(1);
}
if (pthread_attr_destroy(&att)) {
fprintf(stderr, "pthread_attr_destroy err\n");
exit(1);
}
}
void sleepms(int ms)
{
void sleepms(int ms) {
struct timespec t;
t.tv_sec = ms / 1000;
t.tv_nsec = (ms % 1000) * 1000000L;
@@ -37,12 +48,15 @@ void sleepms(int ms)
if (nanosleep(&t, NULL)) abort();
}
void bps(char *out, float v, char *suffix)
{
void bps(char *out, float v, char *suffix) {
static char *bps_unit[4] = { "", "k", "M", "G" };
int flog;
if (v < 1000) flog = 0; else flog = floor(floor(log10(v)) / 3);
if (v < 1000) flog = 0;
else flog = floor(floor(log10(v)) / 3);
if (flog > 3) flog = 3;
v /= pow(10, flog*3);
sprintf(out, "%g%s%s", round(v*100)/100, bps_unit[flog], suffix);
}
@@ -51,25 +65,31 @@ void bps(char *out, float v, char *suffix)
/* list */
/****************************************************************************/
list *list_remove_head(list *l)
{
list *list_remove_head(list *l) {
list *ret;
if (l == NULL) return NULL;
ret = l->next;
if (ret != NULL) ret->last = l->last;
free(l);
return ret;
}
list *list_append(list *l, void *data)
{
list *list_append(list *l, void *data) {
list *new = calloc(1, sizeof(list));
if (new == NULL) abort();
new->data = data;
if (l == NULL) {
new->last = new;
return new;
}
l->last->next = new;
l->last = new;
return l;
@@ -79,88 +99,107 @@ list *list_append(list *l, void *data)
/* socket */
/****************************************************************************/
int create_listen_socket(char *addr, int port)
{
int create_listen_socket(char *addr, int port) {
struct sockaddr_in a;
int s;
int v;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) { perror("socket"); exit(1); }
if (s == -1) {
perror("socket");
exit(1);
}
v = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(int)))
{ perror("setsockopt"); exit(1); }
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(int))) {
perror("setsockopt");
exit(1);
}
a.sin_family = AF_INET;
a.sin_port = htons(port);
a.sin_addr.s_addr = inet_addr(addr);
if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); }
if (listen(s, 5)) { perror("listen"); exit(1); }
if (bind(s, (struct sockaddr *)&a, sizeof(a))) {
perror("bind");
exit(1);
}
if (listen(s, 5)) {
perror("listen");
exit(1);
}
return s;
}
int socket_accept(int s)
{
int socket_accept(int s) {
struct sockaddr_in a;
socklen_t alen;
alen = sizeof(a);
return accept(s, (struct sockaddr *)&a, &alen);
}
int socket_send(int socket, void *buffer, int size)
{
int socket_send(int socket, void *buffer, int size) {
char *x = buffer;
int ret;
while (size) {
ret = write(socket, x, size);
if (ret <= 0) return -1;
size -= ret;
x += ret;
}
return 0;
}
int get_connection(char *addr, int port)
{
int get_connection(char *addr, int port) {
int s, t;
printf("waiting for connection on %s:%d\n", addr, port);
s = create_listen_socket(addr, port);
t = socket_accept(s);
if (t == -1) { perror("accept"); exit(1); }
if (t == -1) {
perror("accept");
exit(1);
}
close(s);
printf("connected\n");
return t;
}
int fullread(int fd, void *_buf, int count)
{
int fullread(int fd, void *_buf, int count) {
char *buf = _buf;
int ret = 0;
int l;
while (count) {
l = read(fd, buf, count);
if (l <= 0) return -1;
count -= l;
buf += l;
ret += l;
}
return ret;
}
int try_connect_to(char *addr, int port)
{
int try_connect_to(char *addr, int port) {
int s;
struct sockaddr_in a;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) { perror("socket"); exit(1); }
if (s == -1) {
perror("socket");
exit(1);
}
a.sin_family = AF_INET;
a.sin_port = htons(port);
@@ -175,14 +214,12 @@ int try_connect_to(char *addr, int port)
return s;
}
int connect_to(char *addr, int port)
{
int connect_to(char *addr, int port) {
int s;
printf("connecting to %s:%d\n", addr, port);
again:
s = try_connect_to(addr, port);
if (s == -1) {
printf("trying again in 1s\n");
sleep(1);
@@ -196,50 +233,46 @@ again:
/* buffer */
/****************************************************************************/
void PUTC(OBUF *o, char c)
{
void PUTC(OBUF *o, char c) {
if (o->osize == o->omaxsize) {
o->omaxsize += 512;
o->obuf = realloc(o->obuf, o->omaxsize);
if (o->obuf == NULL) abort();
}
o->obuf[o->osize] = c;
o->osize++;
}
void PUTS(OBUF *o, char *s)
{
void PUTS(OBUF *o, char *s) {
while (*s) PUTC(o, *s++);
}
static int clean(char c)
{
static int clean(char c) {
if (!isprint(c)) c = ' ';
return c;
}
void PUTS_CLEAN(OBUF *o, char *s)
{
void PUTS_CLEAN(OBUF *o, char *s) {
while (*s) PUTC(o, clean(*s++));
}
void PUTI(OBUF *o, int i)
{
void PUTI(OBUF *o, int i) {
char s[64];
sprintf(s, "%d", i);
PUTS(o, s);
}
void PUTX2(OBUF *o, int i)
{
void PUTX2(OBUF *o, int i) {
char s[64];
sprintf(s, "%2.2x", i);
PUTS(o, s);
}
void PUTUL(OBUF *o, unsigned long l)
{
void PUTUL(OBUF *o, unsigned long l) {
char s[128];
sprintf(s, "%ld", l);
sprintf(s, "%lu", l);
PUTS(o, s);
}