Commit 6d51052e authored by Raymond Knopp's avatar Raymond Knopp

Merge branch 'enhancement-10-harmony' of...

Merge branch 'enhancement-10-harmony' of https://gitlab.eurecom.fr/oai/openairinterface5g into enhancement-10-harmony
parents 4302afee 1f274a7b
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
import time import time
import serial import serial
import os import os
from socket import AF_INET
from pyroute2 import IPRoute from pyroute2 import IPRoute
import sys import sys
import re import re
...@@ -62,7 +63,7 @@ def find_open_port(): ...@@ -62,7 +63,7 @@ def find_open_port():
while True: while True:
if os.path.exists(serial_port) == True: if os.path.exists(serial_port) == True:
return serial_port return serial_port
for port in range(2,100): for port in range(0,100):
serial_port_tmp = '/dev/ttyUSB'+str(port) serial_port_tmp = '/dev/ttyUSB'+str(port)
if os.path.exists(serial_port_tmp) == True: if os.path.exists(serial_port_tmp) == True:
print 'New Serial Port : ' + serial_port_tmp print 'New Serial Port : ' + serial_port_tmp
...@@ -97,11 +98,12 @@ signal.signal(signal.SIGINT, signal_handler) ...@@ -97,11 +98,12 @@ signal.signal(signal.SIGINT, signal_handler)
#ser.isOpen() #ser.isOpen()
class pppThread (threading.Thread): class pppThread (threading.Thread):
def __init__(self, threadID, name, counter): def __init__(self, threadID, name, counter,port):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.threadID = threadID self.threadID = threadID
self.name = name self.name = name
self.counter = counter self.counter = counter
self.port=port
def run(self): def run(self):
print "Starting " + self.name print "Starting " + self.name
#Here we keep running pppd thread in indefinite loop as this script terminates sometimes #Here we keep running pppd thread in indefinite loop as this script terminates sometimes
...@@ -111,6 +113,10 @@ class pppThread (threading.Thread): ...@@ -111,6 +113,10 @@ class pppThread (threading.Thread):
print "Starting wvdial now..." print "Starting wvdial now..."
print 'exit_flag = ' + str(exit_flag) print 'exit_flag = ' + str(exit_flag)
send_command('AT+CGATT=1','OK', 300) send_command('AT+CGATT=1','OK', 300)
#Now we do search and replace on wvdial config file
cmd="sed -i \"s%Modem = .*%Modem = " + self.port + "%g\" " + bandrich_ppd_config
os.system(cmd)
os.system('wvdial -C ' + bandrich_ppd_config + '' ) os.system('wvdial -C ' + bandrich_ppd_config + '' )
if exit_flag == 1: if exit_flag == 1:
print "Exit flag set to true. Exiting pppThread now" print "Exit flag set to true. Exiting pppThread now"
...@@ -146,6 +152,7 @@ def send_command (cmd, response, timeout): ...@@ -146,6 +152,7 @@ def send_command (cmd, response, timeout):
def start_ue () : def start_ue () :
#print 'Enter your commands below.\r\nInsert "exit" to leave the application.' #print 'Enter your commands below.\r\nInsert "exit" to leave the application.'
global serial_port
timeout=60 #timeout in seconds timeout=60 #timeout in seconds
send_command('AT', 'OK' , timeout) send_command('AT', 'OK' , timeout)
send_command('AT+CFUN=1' , 'OK' , timeout) send_command('AT+CFUN=1' , 'OK' , timeout)
...@@ -153,23 +160,33 @@ def start_ue () : ...@@ -153,23 +160,33 @@ def start_ue () :
send_command('AT+CGATT=1','OK', 300) send_command('AT+CGATT=1','OK', 300)
#os.system('wvdial -C ' + bandrich_ppd_config + ' &' ) #os.system('wvdial -C ' + bandrich_ppd_config + ' &' )
thread_ppp = pppThread(1, "ppp_thread", 1) thread_ppp = pppThread(1, "ppp_thread", 1,port=serial_port)
thread_ppp.start() thread_ppp.start()
iface='ppp0' #iface='ppp0'
while 1: while 1:
time.sleep ( 2) time.sleep ( 2)
iface=''
#Now we check if ppp0 interface is up and running #Now we check if ppp0 interface is up and running
try: try:
if exit_flag == 1: if exit_flag == 1:
break break
cmd="ifconfig -a | sed 's/[ \t].*//;/^$/d' | grep ppp"
status, out = commands.getstatusoutput(cmd)
iface=out
ip = IPRoute() ip = IPRoute()
idx = ip.link_lookup(ifname=iface)[0] idx = ip.link_lookup(ifname=iface)[0]
os.system ('route add ' + gw + ' ppp0') print "iface = " + iface
print " Setting route now..."
#os.system("status=1; while [ \"$status\" -ne \"0\" ]; do route add -host " + gw + ' ' + iface + " ; status=$? ;sleep 1; echo \"status = $status\" ; sleep 2; done ")
os.system ('route add -host ' + gw + ' ' + iface + ' 2> /dev/null')
#ip.route('add', dst=gw, oif=iface)
os.system('sleep 5') os.system('sleep 5')
os.system ('ping ' + gw) #print "Starting ping now..."
break os.system ('ping -c 1 ' + gw)
#break
except Exception, e: except Exception, e:
error = ' Interface ' + iface + 'does not exist...' error = ' Interface ' + iface + 'does not exist...'
error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e)
...@@ -206,6 +223,7 @@ def reset_ue(): ...@@ -206,6 +223,7 @@ def reset_ue():
os.system(cmd + " ; sleep 15" ) os.system(cmd + " ; sleep 15" )
cmd = "sudo sh -c \"echo 1 > " + usb_dir + "/authorized\"" cmd = "sudo sh -c \"echo 1 > " + usb_dir + "/authorized\""
os.system(cmd + " ; sleep 30" ) os.system(cmd + " ; sleep 30" )
find_open_port()
stop_ue() stop_ue()
i=1 i=1
...@@ -213,14 +231,17 @@ gw='192.172.0.1' ...@@ -213,14 +231,17 @@ gw='192.172.0.1'
while i < len(sys.argv): while i < len(sys.argv):
arg=sys.argv[i] arg=sys.argv[i]
if arg == '--start-ue' : if arg == '--start-ue' :
print "Turning on UE..."
find_open_port() find_open_port()
print 'Using Serial port : ' + serial_port print 'Using Serial port : ' + serial_port
start_ue() start_ue()
elif arg == '--stop-ue' : elif arg == '--stop-ue' :
print "Turning off UE..."
find_open_port() find_open_port()
print 'Using Serial port : ' + serial_port print 'Using Serial port : ' + serial_port
stop_ue() stop_ue()
elif arg == '--reset-ue' : elif arg == '--reset-ue' :
print "Resetting UE..."
find_open_port() find_open_port()
reset_ue() reset_ue()
elif arg == '-gw' : elif arg == '-gw' :
......
#!/usr/bin/python
#******************************************************************************
# OpenAirInterface
# Copyright(c) 1999 - 2014 Eurecom
# OpenAirInterface is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# OpenAirInterface is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with OpenAirInterface.The full GNU General Public License is
# included in this distribution in the file called "COPYING". If not,
# see <http://www.gnu.org/licenses/>.
# Contact Information
# OpenAirInterface Admin: openair_admin@eurecom.fr
# OpenAirInterface Tech : openair_tech@eurecom.fr
# OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
# Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
# *******************************************************************************/
# \author Navid Nikaein, Rohit Gupta
import time
import serial
import os
from pyroute2 import IPRoute
import sys
import re
import threading
import signal
import traceback
import os
import commands
# configure the serial connections (the parameters differs on the device you are connecting to)
#First we find an open port to work with
serial_port=''
openair_dir = os.environ.get('OPENAIR_DIR')
if openair_dir == None:
print "Error getting OPENAIR_DIR environment variable"
sys.exit(1)
sys.path.append(os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/'))
from lib_autotest import *
#Stop the USB BUS of USRPB210
def stop_usrpb210():
stringIdBandrich='National Instruments Corp.'
status, out = commands.getstatusoutput('lsusb | grep -i \'' + stringIdBandrich + '\'')
if (out == '') :
print "USRP B210 not found. Exiting now..."
sys.exit()
p=re.compile('Bus\s*(\w+)\s*Device\s*(\w+):\s*ID\s*(\w+):(\w+)')
res=p.findall(out)
BusId=res[0][0]
DeviceId=res[0][1]
VendorId=res[0][2]
ProductId=res[0][3]
usb_dir= find_usb_path(VendorId, ProductId)
print "USRP B210 found in..." + usb_dir
cmd = "sudo sh -c \"echo 0 > " + usb_dir + "/authorized\""
os.system(cmd)
#Start the USB bus of USRP B210
def start_usrpb210():
stringIdBandrich='National Instruments Corp.'
status, out = commands.getstatusoutput('lsusb | grep -i \'' + stringIdBandrich + '\'')
if (out == '') :
print "USRP B210 not found. Exiting now..."
sys.exit()
p=re.compile('Bus\s*(\w+)\s*Device\s*(\w+):\s*ID\s*(\w+):(\w+)')
res=p.findall(out)
BusId=res[0][0]
DeviceId=res[0][1]
VendorId=res[0][2]
ProductId=res[0][3]
usb_dir= find_usb_path(VendorId, ProductId)
print "USRP B210 found in..." + usb_dir
cmd = "sudo sh -c \"echo 1 > " + usb_dir + "/authorized\""
os.system(cmd)
i=1
while i < len(sys.argv):
arg=sys.argv[i]
if arg == '--start-usrpb210' :
start_usrpb210()
elif arg == '--stop-usrpb210' :
stop_usrpb210()
elif arg == '-h' :
print "--stop-usrpb210: Stop the USRP B210. It cannot be found in uhd_find_devices"
print "--start-usrpb210: Start the USRP B210. It can now be found in uhd_find_devices"
else :
print " Script called with wrong arguments, arg = " + arg
sys.exit()
i = i +1
...@@ -58,6 +58,7 @@ CFLAGS_PROCESSOR_USER="" ...@@ -58,6 +58,7 @@ CFLAGS_PROCESSOR_USER=""
RUN_GROUP=0 RUN_GROUP=0
TEST_CASE_GROUP="" TEST_CASE_GROUP=""
BUILD_DOXYGEN=0 BUILD_DOXYGEN=0
T_TRACER="False"
trap handle_ctrl_c INT trap handle_ctrl_c INT
function print_help() { function print_help() {
...@@ -128,6 +129,8 @@ Options ...@@ -128,6 +129,8 @@ Options
Enable deadline scheduler of Linux kernel (>=3.14.x). Enable deadline scheduler of Linux kernel (>=3.14.x).
--disable-cpu-affinity --disable-cpu-affinity
Disables CPU Affinity between UHD/TX/RX Threads (Valid only when deadline scheduler is disabled). By defaulT, CPU Affinity is enabled when not using deadline scheduler. It is enabled only with >2 CPUs. For eNB, CPU_0-> Device library (UHD), CPU_1->TX Threads, CPU_2...CPU_MAX->Rx Threads. For UE, CPU_0->Device Library(UHD), CPU_1..CPU_MAX -> All the UE threads Disables CPU Affinity between UHD/TX/RX Threads (Valid only when deadline scheduler is disabled). By defaulT, CPU Affinity is enabled when not using deadline scheduler. It is enabled only with >2 CPUs. For eNB, CPU_0-> Device library (UHD), CPU_1->TX Threads, CPU_2...CPU_MAX->Rx Threads. For UE, CPU_0->Device Library(UHD), CPU_1..CPU_MAX -> All the UE threads
--T-tracer
Enables the T tracer.
Usage (first build): Usage (first build):
oaisim (eNB + UE): ./build_oai -I -g --oaisim -x --install-system-files oaisim (eNB + UE): ./build_oai -I -g --oaisim -x --install-system-files
Eurecom EXMIMO + COTS UE : ./build_oai -I -g --eNB -x --install-system-files Eurecom EXMIMO + COTS UE : ./build_oai -I -g --eNB -x --install-system-files
...@@ -270,6 +273,10 @@ function main() { ...@@ -270,6 +273,10 @@ function main() {
CPU_AFFINITY_FLAG_USER="False" CPU_AFFINITY_FLAG_USER="False"
echo_info "Disabling CPU Affinity (only valid when not using deadline scheduler)" echo_info "Disabling CPU Affinity (only valid when not using deadline scheduler)"
shift 1;; shift 1;;
--T-tracer)
T_TRACER="True"
echo_info "Enabling the T tracer"
shift 1;;
-h | --help) -h | --help)
print_help print_help
exit 1;; exit 1;;
...@@ -434,6 +441,7 @@ function main() { ...@@ -434,6 +441,7 @@ function main() {
echo "set(PACKAGE_NAME \"${lte_exec}\")" >> $cmake_file echo "set(PACKAGE_NAME \"${lte_exec}\")" >> $cmake_file
echo "set (DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )" >>$cmake_file echo "set (DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )" >>$cmake_file
echo "set (CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )" >>$cmake_file echo "set (CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )" >>$cmake_file
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
cd $DIR/$lte_build_dir/build cd $DIR/$lte_build_dir/build
cmake .. cmake ..
...@@ -567,6 +575,7 @@ function main() { ...@@ -567,6 +575,7 @@ function main() {
echo "set ( PRINT_STATS $PRINT_STATS )" >> $cmake_file echo "set ( PRINT_STATS $PRINT_STATS )" >> $cmake_file
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
[ "$CLEAN" = "1" ] && rm -rf $DIR/$oaisim_build_dir/build [ "$CLEAN" = "1" ] && rm -rf $DIR/$oaisim_build_dir/build
mkdir -p $DIR/$oaisim_build_dir/build mkdir -p $DIR/$oaisim_build_dir/build
...@@ -632,6 +641,7 @@ function main() { ...@@ -632,6 +641,7 @@ function main() {
echo "set(XFORMS $XFORMS )" >> $cmake_file echo "set(XFORMS $XFORMS )" >> $cmake_file
echo "set(RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file echo "set(RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set(ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set(ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
#[ "$CLEAN" = "1" ] && rm -rf $DIR/oaisim_mme_build_oai/build #[ "$CLEAN" = "1" ] && rm -rf $DIR/oaisim_mme_build_oai/build
#mkdir -p $DIR/oaisim_mme_build_oai/build #mkdir -p $DIR/oaisim_mme_build_oai/build
...@@ -662,6 +672,7 @@ function main() { ...@@ -662,6 +672,7 @@ function main() {
echo 'set(PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file echo 'set(PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file
echo "set (DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )" >>$cmake_file echo "set (DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )" >>$cmake_file
echo "set (CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )" >>$cmake_file echo "set (CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )" >>$cmake_file
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
cd $DIR/$rrh_build_dir/build cd $DIR/$rrh_build_dir/build
cmake .. cmake ..
......
...@@ -226,7 +226,25 @@ check_install_additional_tools (){ ...@@ -226,7 +226,25 @@ check_install_additional_tools (){
valgrind \ valgrind \
vlan \ vlan \
ctags \ ctags \
ntpdate ntpdate \
iperf3 \
android-tools-adb
$SUDO pip install paramiko
$SUDO pip install pyroute2
$SUDO rm -fr /opt/ssh
$SUDO git clone https://gist.github.com/2190472.git /opt/ssh
log_netiface=$OPENAIR_DIR/cmake_targets/log/netiface_install_log.txt
echo_info "Installing Netinterfaces package. The logfile for installation is in $log_netiface"
(
$SUDO rm -fr /tmp/netifaces-0.10.4.tar.gz /tmp/netifaces
wget -P /tmp https://pypi.python.org/packages/18/fa/dd13d4910aea339c0bb87d2b3838d8fd923c11869b1f6e741dbd0ff3bc00/netifaces-0.10.4.tar.gz
tar -xzvf /tmp/netifaces-0.10.4.tar.gz -C /tmp
cd /tmp/netifaces-0.10.4
$SUDO python setup.py install
cd -
) >& $log_netiface
} }
check_install_oai_software() { check_install_oai_software() {
...@@ -293,8 +311,7 @@ check_install_oai_software() { ...@@ -293,8 +311,7 @@ check_install_oai_software() {
python-numpy \ python-numpy \
sshpass \ sshpass \
libxslt1-dev \ libxslt1-dev \
android-tools-adb \ android-tools-adb
iperf3
$SUDO update-alternatives --set liblapack.so /usr/lib/atlas-base/atlas/liblapack.so $SUDO update-alternatives --set liblapack.so /usr/lib/atlas-base/atlas/liblapack.so
...@@ -303,11 +320,7 @@ check_install_oai_software() { ...@@ -303,11 +320,7 @@ check_install_oai_software() {
install_nettle_from_source install_nettle_from_source
install_gnutls_from_source install_gnutls_from_source
$SUDO pip install paramiko
$SUDO pip install pyroute2
install_asn1c_from_source install_asn1c_from_source
$SUDO rm -fr /opt/ssh
$SUDO git clone https://gist.github.com/2190472.git /opt/ssh
} }
install_asn1c_from_source(){ install_asn1c_from_source(){
...@@ -315,14 +328,12 @@ install_asn1c_from_source(){ ...@@ -315,14 +328,12 @@ install_asn1c_from_source(){
echo_info "\nInstalling ASN1. The log file for ASN1 installation is here: $asn1_install_log " echo_info "\nInstalling ASN1. The log file for ASN1 installation is here: $asn1_install_log "
( (
$SUDO rm -rf /tmp/asn1c-r1516 $SUDO rm -rf /tmp/asn1c-r1516
mkdir -p /tmp/asn1c-r1516 svn co https://github.com/vlm/asn1c/trunk /tmp/asn1c-r1516 -r 1516
cd /tmp/asn1c-r1516 cd /tmp/asn1c-r1516
rm -rf /tmp/asn1c-r1516/* patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch.p0
svn co https://github.com/vlm/asn1c/trunk /tmp/asn1c-r1516 -r 1516 > /tmp/log_compile_asn1c patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_2.p0
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch.p0 >> /tmp/log_compile_asn1c patch -p0 < $OPENAIR_DIR/openair2/RRC/LITE/MESSAGES/asn1c/asn1cpatch.p0
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_2.p0 >> /tmp/log_compile_asn1c patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_3.p0
patch -p0 < $OPENAIR_DIR/openair2/RRC/LITE/MESSAGES/asn1c/asn1cpatch.p0 >> /tmp/log_compile_asn1c
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_3.p0 >> /tmp/log_compile_asn1c
./configure ./configure
make -j`nproc` make -j`nproc`
$SUDO make install $SUDO make install
......
CC=gcc
CFLAGS=-Wall -g
GENIDS=genids
GENIDS_OBJS=genids.o
all : $(GENIDS) T_messages.txt.h T_IDs.h
$(GENIDS): $(GENIDS_OBJS)
$(CC) $(CFLAGS) -o $(GENIDS) $(GENIDS_OBJS)
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
T_messages.txt.h: T_messages.txt
xxd -i T_messages.txt > T_messages.txt.h
T_IDs.h: $(GENIDS) T_messages.txt
./$(GENIDS) T_messages.txt T_IDs.h
clean:
rm -f *.o $(GENIDS) core T_IDs.h T_messages.txt.h
cd tracer && make clean
#include "T.h"
#include "T_messages.txt.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#define QUIT(x) do { \
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;
static int T_socket;
/* T_cache
* - the T macro picks up the head of freelist and marks it busy
* - the T sender thread periodically wakes up and sends what's to be sent
*/
volatile int _T_freelist_head;
volatile int *T_freelist_head = &_T_freelist_head;
T_cache_t *T_cache;
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("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 */
}
}
static void *T_receive_thread(void *_)
{
while (1) get_message(T_socket);
return NULL;
}
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); }
}
/* defined in local_tracer.c */
void T_local_tracer_main(int remote_port, int wait_for_tracer,
int local_socket);
/* 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)
{
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 socket_pair[2];
int s;
int T_shm_fd;
unsigned char *buf;
int len;
int child1, child2;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair))
{ perror("socketpair"); abort(); }
/* child1 runs the local tracer and child2 runs the tracee */
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]);
exit(0);
}
close(socket_pair[0]);
child2 = fork(); if (child2 == -1) abort();
if (child2 != 0) {
close(socket_pair[1]);
monitor_and_kill(child1, child2);
}
s = socket_pair[1];
/* wait for first message - initial list of active T events */
get_message(s);
T_socket = s;
/* setup shared memory */
T_shm_fd = shm_open(T_SHM_FILENAME, O_RDWR /*| O_SYNC*/, 0666);
shm_unlink(T_SHM_FILENAME);
if (T_shm_fd == -1) { perror(T_SHM_FILENAME); abort(); }
T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
PROT_READ | PROT_WRITE, MAP_SHARED, T_shm_fd, 0);
if (T_cache == NULL)
{ perror(T_SHM_FILENAME); abort(); }
close(T_shm_fd);
new_thread(T_receive_thread, NULL);
/* trace T_message.txt
* Send several messages -1 with content followed by message -2.
* We can't use the T macro directly, events -1 and -2 are special.
*/
buf = T_messages_txt;
len = T_messages_txt_len;
while (len) {
int send_size = len;
if (send_size > T_PAYLOAD_MAXSIZE - sizeof(int))
send_size = T_PAYLOAD_MAXSIZE - sizeof(int);
do {
T_LOCAL_DATA
T_HEADER(T_ID(-1));
T_PUT_buffer(1, ((T_buffer){addr:(buf), length:(len)}));
T_COMMIT();
} while (0);
buf += send_size;
len -= send_size;
}
do {
T_LOCAL_DATA
T_HEADER(T_ID(-2));
T_COMMIT();
} while (0);
}
This diff is collapsed.
#ifndef _T_defs_H_
#define _T_defs_H_
/* comment (and recompile everything) to not send time in events */
#define T_SEND_TIME
/* maximum number of arguments for the T macro */
#define T_MAX_ARGS 16
/* maximum size of a message - increase if needed */
#define T_BUFFER_MAX (1024*64)
/* size of the local cache for messages (must be pow(2,something)) */
#define T_CACHE_SIZE (8192 * 2)
/* maximum number of bytes a message can contain */
#ifdef T_SEND_TIME
# define T_PAYLOAD_MAXSIZE (T_BUFFER_MAX-sizeof(int)-sizeof(struct timespec))
#else
# define T_PAYLOAD_MAXSIZE (T_BUFFER_MAX-sizeof(int))
#endif
typedef struct {
volatile int busy;
char buffer[T_BUFFER_MAX];
int length;
} T_cache_t;
#define T_SHM_FILENAME "/T_shm_segment"
/* number of VCD functions (to be kept up to date! see in T_messages.txt) */
#define VCD_NUM_FUNCTIONS 146
/* number of VCD variables (to be kept up to date! see in T_messages.txt) */
#define VCD_NUM_VARIABLES 99
/* first VCD function (to be kept up to date! see in T_messages.txt) */
#define VCD_FIRST_FUNCTION ((uintptr_t)T_VCD_FUNCTION_RT_SLEEP)
/* first VCD variable (to be kept up to date! see in T_messages.txt) */
#define VCD_FIRST_VARIABLE ((uintptr_t)T_VCD_VARIABLE_FRAME_NUMBER_TX_ENB)
#endif /* _T_defs_H_ */
This diff is collapsed.
#ifndef _TRACER_DEFS_H_
#define _TRACER_DEFS_H_
/* types of plots */
#define PLOT_VS_TIME 0
#define PLOT_IQ_POINTS 1
#define PLOT_MINMAX 2
void new_thread(void *(*f)(void *), void *data);
/* ... is { int count; int type; char *color; } for 'nplots' plots */
void *make_plot(int width, int height, char *title, int nplots, ...);
void plot_set(void *plot, float *data, int len, int pos, int pp);
void iq_plot_set(void *plot, short *data, int len, int pos, int pp);
void iq_plot_set_sized(void *_plot, short *data, int len, int pp);
void iq_plot_add_iq_point_loop(void *_plot, short i, short q, int pp);
void iq_plot_add_energy_point_loop(void *_plot, int e, int pp);
/* returns an opaque pointer - truly a 'database *', see t_data.c */
void *parse_database(char *filename);
void dump_database(void *database);
void list_ids(void *database);
void list_groups(void *database);
void on_off(void *d, char *item, int *a, int onoff);
void *forwarder(char *ip, int port);
void forward(void *forwarder, char *buf, int size);
void forward_start_client(void *forwarder, int socket);
#endif /* _TRACER_DEFS_H_ */
#include <stdio.h>
void print(int n)
{
int i;
printf("#define T%d(t", n);
for(i=0; i<(n-1)/2; i++) printf(",t%d,x%d", i, i);
printf(") \\\n");
printf(" do { \\\n");
printf(" if (T_ACTIVE(t)) { \\\n");
printf(" T_LOCAL_DATA \\\n");
printf(" T_HEADER(t); \\\n");
for(i=0; i<(n-1)/2; i++) printf(" T_PUT_##t%d(%d, x%d); \\\n", i, i+2, i);
printf(" T_COMMIT(); \\\n");
printf(" } \\\n");
printf(" } while (0)\n");
printf("\n");
}
int main(void)
{
int i;
for (i = 11; i <= 33; i+=2) print(i);
return 0;
}
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char **unique_ids;
int unique_ids_size;
int unique_ids_maxsize;
int cmp(const void *p1, const void *p2)
{
return strcmp(*(char * const *)p1, *(char * const *)p2);
}
/* return 1 if s was not already known, 0 if it was */
int new_unique_id(char *s)
{
if (unique_ids_size)
if (bsearch(&s, unique_ids, unique_ids_size, sizeof(char *), cmp) != NULL) {
printf("FATAL: ID %s is not unique\n", s);
return 0;
}
if (unique_ids_size == unique_ids_maxsize) {
unique_ids_maxsize += 256;
unique_ids = realloc(unique_ids, unique_ids_maxsize * sizeof(char *));
if (unique_ids == NULL) { printf("out of memory\n"); abort(); }
}
unique_ids[unique_ids_size] = strdup(s);
if (unique_ids[unique_ids_size] == NULL)
{ printf("out of memory\n"); abort(); }
unique_ids_size++;
qsort(unique_ids, unique_ids_size, sizeof(char *), cmp);
return 1;
}
char *bufname;
int bufname_size;
int bufname_maxsize;
void putname(int c)
{
if (bufname_size == bufname_maxsize) {
bufname_maxsize += 256;
bufname = realloc(bufname, bufname_maxsize);
if (bufname == NULL) { printf("memory allocation error\n"); exit(1); }
}
bufname[bufname_size] = c;
bufname_size++;
}
char *bufvalue;
int bufvalue_size;
int bufvalue_maxsize;
void putvalue(int c)
{
if (bufvalue_size == bufvalue_maxsize) {
bufvalue_maxsize += 256;
bufvalue = realloc(bufvalue, bufvalue_maxsize);
if (bufvalue == NULL) { printf("memory allocation error\n"); exit(1); }
}
bufvalue[bufvalue_size] = c;
bufvalue_size++;
}
void smash_spaces(FILE *f)
{
int c;
while (1) {
c = fgetc(f);
if (isspace(c)) continue;
if (c == ' ') continue;
if (c == '\t') continue;
if (c == '\n') continue;
if (c == 10 || c == 13) continue;
if (c == '#') {
while (1) {
c = fgetc(f);
if (c == '\n' || c == EOF) break;
}
continue;
}
break;
}
if (c != EOF) ungetc(c, f);
}
void get_line(FILE *f, char **name, char **value)
{
int c;
bufname_size = 0;
bufvalue_size = 0;
*name = NULL;
*value = NULL;
smash_spaces(f);
c = fgetc(f);
while (!(c == '=' || isspace(c) || c == EOF)) { putname(c); c = fgetc(f); }
if (c == EOF) return;
putname(0);
while (!(c == EOF || c == '=')) c = fgetc(f);
if (c == EOF) return;
smash_spaces(f);
c = fgetc(f);
while (!(c == 10 || c == 13 || c == EOF)) { putvalue(c); c = fgetc(f); }
putvalue(0);
if (bufname_size <= 1) return;
if (bufvalue_size <= 1) return;
*name = bufname;
*value = bufvalue;
}
int main(int n, char **v)
{
FILE *in;
FILE *out;
char *name;
char *value;
char *in_name;
char *out_name;
if (n != 3) { printf("gimme <source> <dest>\n"); exit(1); }
n = 0;
in_name = v[1];
out_name = v[2];
in = fopen(in_name, "r"); if (in == NULL) { perror(in_name); exit(1); }
out = fopen(out_name, "w"); if (out == NULL) { perror(out_name); exit(1); }
fprintf(out, "/* generated file, do not edit by hand */\n\n");
while (1) {
get_line(in, &name, &value);
if (name == NULL) break;
printf("name '%s' value '%s'\n", name, value);
if (isspace(value[strlen(value)-1])) {
printf("bad value '%s' (no space at the end please!)\n", value);
unlink(out_name);
exit(1);
}
if (!strcmp(name, "ID")) {
if (!new_unique_id(value)) { unlink(out_name); exit(1); }
fprintf(out, "#define T_%s T_ID(%d)\n", value, n);
n++;
}
}
fprintf(out, "#define T_NUMBER_OF_IDS %d\n", n);
fclose(in);
fclose(out);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <inttypes.h>
#include <signal.h>
#include "T_defs.h"
#include "T_IDs.h"
static T_cache_t *T_cache;
static int T_busylist_head;
typedef struct databuf {
char *d;
int l;
struct databuf *next;
} databuf;
typedef struct {
int socket_local;
volatile int socket_remote;
int remote_port;
pthread_mutex_t lock;
pthread_cond_t cond;
databuf * volatile head, *tail;
uint64_t memusage;
uint64_t last_warning_memusage;
} forward_data;
/****************************************************************************/
/* utility functions */
/****************************************************************************/
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); }
}
static int get_connection(char *addr, int port)
{
struct sockaddr_in a;
socklen_t alen;
int s, t;
printf("waiting for connection on %s:%d\n", addr, port);
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) { perror("socket"); exit(1); }
t = 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); }
alen = sizeof(a);
t = accept(s, (struct sockaddr *)&a, &alen);
if (t == -1) { perror("accept"); exit(1); }
close(s);
printf("connected\n");
return t;
}
/****************************************************************************/
/* forward functions */
/****************************************************************************/
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("forward error\n");
close(f->socket_remote);
f->socket_remote = -1;
break;
}
size -= l;
b += l;
}
free(buf);
goto wait;
}
static void *forward_remote_messages(void *_f)
{
#define PUT(x) do { \
if (bufsize == bufmaxsize) { \
bufmaxsize += 4096; \
buf = realloc(buf, bufmaxsize); \
if (buf == NULL) abort(); \
} \
buf[bufsize] = x; \
bufsize++; \
} while (0)
#define PUT_BUF(x, l) do { \
char *zz = (char *)(x); \
int len = l; \
while (len) { PUT(*zz); zz++; len--; } \
} while (0)
forward_data *f = _f;
int from;
int to;
int l, len;
char *b;
char *buf = NULL;
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;
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 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;
}
}
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);
goto again;
return NULL;
}
static void *forwarder(int port, int s)
{
forward_data *f;
f = malloc(sizeof(*f)); 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("waiting for remote tracer on port %d\n", port);
f->remote_port = port;
f->socket_remote = get_connection("0.0.0.0", port);
new_thread(data_sender, f);
new_thread(forward_remote_messages, f);
return f;
}
static void forward(void *_forwarder, char *buf, int size)
{
forward_data *f = _forwarder;
int32_t ssize = size;
databuf *new;
new = malloc(sizeof(*new)); if (new == NULL) abort();
if (pthread_mutex_lock(&f->lock)) 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;
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("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) {
f->last_warning_memusage = (f->memusage/100000000) * 100000000;
}
if (pthread_cond_signal(&f->cond)) abort();
if (pthread_mutex_unlock(&f->lock)) abort();
}
/****************************************************************************/
/* local functions */
/****************************************************************************/
static void wait_message(void)
{
while (T_cache[T_busylist_head].busy == 0) usleep(1000);
}
static void init_shm(void)
{
int i;
int s = shm_open(T_SHM_FILENAME, O_RDWR | O_CREAT /*| O_SYNC*/, 0666);
if (s == -1) { perror(T_SHM_FILENAME); abort(); }
if (ftruncate(s, T_CACHE_SIZE * sizeof(T_cache_t)))
{ perror(T_SHM_FILENAME); abort(); }
T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
PROT_READ | PROT_WRITE, MAP_SHARED, s, 0);
if (T_cache == NULL)
{ perror(T_SHM_FILENAME); abort(); }
close(s);
/* 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;
}
void T_local_tracer_main(int remote_port, int wait_for_tracer,
int local_socket)
{
int s;
int port = remote_port;
int dont_wait = wait_for_tracer ? 0 : 1;
void *f;
/* write on a socket fails if the other end is closed and we get SIGPIPE */
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
init_shm();
s = local_socket;
if (dont_wait) {
char t = 2;
if (write(s, &t, 1) != 1) abort();
}
f = forwarder(port, s);
/* read messages */
while (1) {
wait_message();
__sync_synchronize();
forward(f, T_cache[T_busylist_head].buffer,
T_cache[T_busylist_head].length);
T_cache[T_busylist_head].busy = 0;
T_busylist_head++;
T_busylist_head &= T_CACHE_SIZE - 1;
}
}
#include "defs.h"
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <math.h>
#include <unistd.h>
#include <sys/select.h>
#include <stdarg.h>
typedef struct {
float *buf;
short *iqbuf;
int count;
int type;
volatile int iq_count; /* for ULSCH IQ data */
int iq_insert_pos;
GC g;
} data;
typedef struct {
Display *d;
Window w;
Pixmap px;
GC bg;
int width;
int height;
pthread_mutex_t lock;
float zoom;
int timer_pipe[2];
data *p; /* list of plots */
int nplots;
} plot;
static void *timer_thread(void *_p)
{
plot *p = _p;
char c;
while (1) {
/* more or less 10Hz */
usleep(100*1000);
c = 1;
if (write(p->timer_pipe[1], &c, 1) != 1) abort();
}
return NULL;
}
static void *plot_thread(void *_p)
{
float v;
float *s;
int i, j;
plot *p = _p;
int redraw = 0;
int replot = 0;
fd_set rset;
int xfd = ConnectionNumber(p->d);
int maxfd = xfd > p->timer_pipe[0] ? xfd : p->timer_pipe[0];
int pp;
while (1) {
while (XPending(p->d)) {
XEvent e;
XNextEvent(p->d, &e);
switch (e.type) {
case ButtonPress:
/* button 4: zoom out */
if (e.xbutton.button == 4) { p->zoom = p->zoom * 1.25; replot = 1; }
/* button 5: zoom in */
if (e.xbutton.button == 5) { p->zoom = p->zoom * 0.8; replot = 1; }
printf("zoom: %f\n", p->zoom);
break;
case Expose: redraw = 1; break;
}
}
if (replot == 1) {
replot = 0;
redraw = 1;
if (pthread_mutex_lock(&p->lock)) abort();
XFillRectangle(p->d, p->px, p->bg, 0, 0, p->width, p->height);
for (pp = 0; pp < p->nplots; pp++) {
if (p->p[pp].type == PLOT_MINMAX) {
s = p->p[pp].buf;
for (i = 0; i < 512; i++) {
int min = *s;
int max = *s;
for (j = 0; j < p->p[pp].count/512; j++, s++) {
if (*s < min) min = *s;
if (*s > max) max = *s;
}
XDrawLine(p->d, p->px, p->p[pp].g, i, 100-min, i, 100-max);
}
} else if (p->p[pp].type == PLOT_VS_TIME) {
for (i = 0; i < p->p[pp].count; i++)
p->p[pp].buf[i] =
10*log10(1.0+(float)(p->p[pp].iqbuf[2*i]*p->p[pp].iqbuf[2*i]+
p->p[pp].iqbuf[2*i+1]*p->p[pp].iqbuf[2*i+1]));
s = p->p[pp].buf;
for (i = 0; i < 512; i++) {
v = 0;
for (j = 0; j < p->p[pp].count/512; j++, s++) v += *s;
v /= p->p[pp].count/512;
XDrawLine(p->d, p->px, p->p[pp].g, i, 100, i, 100-v);
}
} else if (p->p[pp].type == PLOT_IQ_POINTS) {
XPoint pts[p->p[pp].iq_count];
int count = p->p[pp].iq_count;
for (i = 0; i < count; i++) {
pts[i].x = p->p[pp].iqbuf[2*i]*p->zoom/20+50;
pts[i].y = -p->p[pp].iqbuf[2*i+1]*p->zoom/20+50;
}
XDrawPoints(p->d, p->px, p->p[pp].g, pts, count, CoordModeOrigin);
}
}
if (pthread_mutex_unlock(&p->lock)) abort();
}
if (redraw) {
redraw = 0;
XCopyArea(p->d, p->px, p->w, DefaultGC(p->d, DefaultScreen(p->d)),
0, 0, p->width, p->height, 0, 0);
}
XFlush(p->d);
FD_ZERO(&rset);
FD_SET(p->timer_pipe[0], &rset);
FD_SET(xfd, &rset);
if (select(maxfd+1, &rset, NULL, NULL, NULL) == -1) abort();
if (FD_ISSET(p->timer_pipe[0], &rset)) {
char b[512];
if (read(p->timer_pipe[0], b, 512) <= 0) abort();
replot = 1;
}
}
return NULL;
}
void *make_plot(int width, int height, char *title, int nplots, ...)
{
plot *p;
Display *d;
Window w;
Pixmap pm;
int i;
va_list ap;
XGCValues gcv;
p = malloc(sizeof(*p)); if (p == NULL) abort();
d = XOpenDisplay(0); if (d == NULL) abort();
w = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, width, height,
0, WhitePixel(d, DefaultScreen(d)), WhitePixel(d, DefaultScreen(d)));
XSelectInput(d, w, ExposureMask | ButtonPressMask);
XMapWindow(d, w);
{
XSetWindowAttributes att;
att.backing_store = Always;
XChangeWindowAttributes(d, w, CWBackingStore, &att);
}
XStoreName(d, w, title);
p->bg = XCreateGC(d, w, 0, NULL);
XCopyGC(d, DefaultGC(d, DefaultScreen(d)), -1L, p->bg);
gcv.foreground = WhitePixel(d, DefaultScreen(d));
XChangeGC(d, p->bg, GCForeground, &gcv);
pm = XCreatePixmap(d, w, width, height, DefaultDepth(d, DefaultScreen(d)));
p->width = width;
p->height = height;
p->p = malloc(nplots * sizeof(data)); if (p->p == NULL) abort();
va_start(ap, nplots);
for (i = 0; i < nplots; i++) {
int count;
int type;
char *color;
XColor rcol, scol;
count = va_arg(ap, int);
type = va_arg(ap, int);
color = va_arg(ap, char *);
p->p[i].g = XCreateGC(d, w, 0, NULL);
XCopyGC(d, DefaultGC(d, DefaultScreen(d)), -1L, p->p[i].g);
if (XAllocNamedColor(d, DefaultColormap(d, DefaultScreen(d)),
color, &scol, &rcol)) {
gcv.foreground = scol.pixel;
XChangeGC(d, p->p[i].g, GCForeground, &gcv);
} else {
printf("could not allocate color '%s'\n", color);
abort();
}
if (type == PLOT_VS_TIME) {
p->p[i].buf = malloc(sizeof(float) * count);
if (p->p[i].buf == NULL) abort();
p->p[i].iqbuf = malloc(sizeof(short) * count * 2);
if(p->p[i].iqbuf==NULL)abort();
} else if (type == PLOT_MINMAX) {
p->p[i].buf = malloc(sizeof(float) * count);
if (p->p[i].buf == NULL) abort();
p->p[i].iqbuf = NULL;
} else {
p->p[i].buf = NULL;
p->p[i].iqbuf = malloc(sizeof(short) * count * 2);
if(p->p[i].iqbuf==NULL)abort();
}
p->p[i].count = count;
p->p[i].type = type;
p->p[i].iq_count = 0;
p->p[i].iq_insert_pos = 0;
}
va_end(ap);
p->d = d;
p->w = w;
p->px = pm;
p->zoom = 1;
p->nplots = nplots;
pthread_mutex_init(&p->lock, NULL);
if (pipe(p->timer_pipe)) abort();
new_thread(plot_thread, p);
new_thread(timer_thread, p);
return p;
}
void plot_set(void *_plot, float *data, int len, int pos, int pp)
{
plot *p = _plot;
if (pthread_mutex_lock(&p->lock)) abort();
memcpy(p->p[pp].buf + pos, data, len * sizeof(float));
if (pthread_mutex_unlock(&p->lock)) abort();
}
void iq_plot_set(void *_plot, short *data, int count, int pos, int pp)
{
plot *p = _plot;
if (pthread_mutex_lock(&p->lock)) abort();
memcpy(p->p[pp].iqbuf + pos * 2, data, count * 2 * sizeof(short));
if (pthread_mutex_unlock(&p->lock)) abort();
}
void iq_plot_set_sized(void *_plot, short *data, int count, int pp)
{
plot *p = _plot;
if (pthread_mutex_lock(&p->lock)) abort();
memcpy(p->p[pp].iqbuf, data, count * 2 * sizeof(short));
p->p[pp].iq_count = count;
if (pthread_mutex_unlock(&p->lock)) abort();
}
void iq_plot_add_iq_point_loop(void *_plot, short i, short q, int pp)
{
plot *p = _plot;
if (pthread_mutex_lock(&p->lock)) abort();
p->p[pp].iqbuf[p->p[pp].iq_insert_pos*2] = i;
p->p[pp].iqbuf[p->p[pp].iq_insert_pos*2+1] = q;
if (p->p[pp].iq_count != p->p[pp].count) p->p[pp].iq_count++;
p->p[pp].iq_insert_pos++;
if (p->p[pp].iq_insert_pos == p->p[pp].count) p->p[pp].iq_insert_pos = 0;
if (pthread_mutex_unlock(&p->lock)) abort();
}
void iq_plot_add_energy_point_loop(void *_plot, int e, int pp)
{
plot *p = _plot;
if (pthread_mutex_lock(&p->lock)) abort();
p->p[pp].buf[p->p[pp].iq_insert_pos] = e;
if (p->p[pp].iq_count != p->p[pp].count) p->p[pp].iq_count++;
p->p[pp].iq_insert_pos++;
if (p->p[pp].iq_insert_pos == p->p[pp].count) p->p[pp].iq_insert_pos = 0;
if (pthread_mutex_unlock(&p->lock)) abort();
}
CC=gcc
CFLAGS=-Wall -g -pthread -DT_TRACER -I.
PROG=tracee
OBJS=tracee.o ../T.o
$(PROG): $(OBJS)
$(CC) $(CFLAGS) -o $(PROG) $(OBJS) -lrt
tracee.o: tracee.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f *.o $(PROG) core
this is a very basic tracee, used to debug the tracer
#include "../T.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int frame = 0;
T_connect_to_tracer("127.0.0.1", 2020);
while (1) {
getchar();
T(T_ENB_PHY_PUCCH_1AB_IQ, T_INT(0), T_INT(0), T_INT(frame), T_INT(0), T_INT(0), T_INT(0));
frame++;
}
return 0;
}
CC=gcc
CFLAGS=-Wall -g -pthread -DT_TRACER -I.
#CFLAGS += -O3 -ffast-math -fomit-frame-pointer
LIBS=-lX11 -lm -lpng -lXft
all: textlog enb vcd
textlog: utils.o textlog.o database.o event.o handler.o config.o \
event_selector.o view/view.a gui/gui.a logger/logger.a \
filter/filter.a
$(CC) $(CFLAGS) -o textlog $^ $(LIBS)
enb: utils.o enb.o database.o event.o handler.o config.o \
event_selector.o view/view.a gui/gui.a logger/logger.a \
filter/filter.a
$(CC) $(CFLAGS) -o enb $^ $(LIBS)
vcd: utils.o vcd.o database.o event.o handler.o config.o \
event_selector.o view/view.a gui/gui.a logger/logger.a \
filter/filter.a
$(CC) $(CFLAGS) -o vcd $^ $(LIBS)
.PHONY: all gui/gui.a view/view.a logger/logger.a filter/filter.a
gui/gui.a:
cd gui && make
view/view.a:
cd view && make
logger/logger.a:
cd logger && make
filter/filter.a:
cd filter && make
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f *.o core tracer_remote textlog enb vcd
cd gui && make clean
cd view && make clean
cd logger && make clean
cd filter && make clean
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *local;
static int local_size;
static char *remote;
static int remote_size;
static char *PUT(char *to, int tosize, char c)
{
if ((tosize & 4095) == 0) {
to = realloc(to, tosize + 4096); if (to == NULL) abort();
}
to[tosize] = c;
return to;
}
void clear_remote_config(void)
{
free(remote);
remote = NULL;
remote_size = 0;
}
void append_received_config_chunk(char *buf, int length)
{
int buflen = *(int *)buf;
if (buflen != length - sizeof(int)) {
printf("ERROR: bad trace -1, should not happen...\n");
abort();
}
buf += sizeof(int);
while (buflen) {
remote = PUT(remote, remote_size, *buf);
remote_size++;
buf++;
buflen--;
}
}
void load_config_file(char *filename)
{
int c;
FILE *f = fopen(filename, "r");
if (f == NULL) { perror(filename); abort(); }
while (1) {
c = fgetc(f); if (c == EOF) break;
local = PUT(local, local_size, c);
local_size++;
}
fclose(f);
}
void verify_config(void)
{
if (local_size != remote_size || memcmp(local, remote, local_size) != 0) {
printf("ERROR: local and remote T_messages.txt not identical\n");
abort();
}
}
#ifndef _CONFIG_H_
#define _CONFIG_H_
void clear_remote_config(void);
void append_received_config_chunk(char *buf, int length);
void load_config_file(char *filename);
void verify_config(void);
#endif /* _CONFIG_H_ */
This diff is collapsed.
#ifndef _DATABASE_H_
#define _DATABASE_H_
/* returns an opaque pointer - truly a 'database *', see database.c */
void *parse_database(char *filename);
void dump_database(void *database);
void list_ids(void *database);
void list_groups(void *database);
void on_off(void *d, char *item, int *a, int onoff);
char *event_name_from_id(void *database, int id);
int event_id_from_name(void *database, char *name);
int number_of_ids(void *database);
int database_get_ids(void *database, char ***ids);
int database_get_groups(void *database, char ***groups);
int database_pos_to_id(void *database, int pos);
void database_get_generic_description(void *database, int id,
char **name, char **desc);
/****************************************************************************/
/* get format of an event */
/****************************************************************************/
typedef struct {
char **type;
char **name;
int count;
} database_event_format;
database_event_format get_format(void *database, int event_id);
#endif /* _DATABASE_H_ */
#ifndef _TRACER_DEFS_H_
#define _TRACER_DEFS_H_
/* types of plots */
#define PLOT_VS_TIME 0
#define PLOT_IQ_POINTS 1
#define PLOT_MINMAX 2
void new_thread(void *(*f)(void *), void *data);
/* ... is { int count; int type; char *color; } for 'nplots' plots */
void *make_plot(int width, int height, char *title, int nplots, ...);
void plot_set(void *plot, float *data, int len, int pos, int pp);
void iq_plot_set(void *plot, short *data, int len, int pos, int pp);
void iq_plot_set_sized(void *_plot, short *data, int len, int pp);
void iq_plot_add_iq_point_loop(void *_plot, short i, short q, int pp);
void iq_plot_add_energy_point_loop(void *_plot, int e, int pp);
/* T gui functions */
void t_gui_start(void);
void t_gui_set_input_signal(int eNB, int frame, int subframe, int antenna,
int size, void *buf);
#endif /* _TRACER_DEFS_H_ */
This diff is collapsed.
#include "event.h"
#include "database.h"
#include "utils.h"
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
event get_event(int socket, char *event_buffer, void *database)
{
#ifdef T_SEND_TIME
struct timespec t;
#endif
int type;
int32_t length;
/* Events type -1 and -2 are special: the tracee sends its version
* of T_messages.txt using those events.
* We have to check that the local version of T_messages.txt is identical
* to the one the tracee uses. We don't report those events to the
* application.
*/
again:
if (fullread(socket, &length, 4) == -1) goto read_error;
#ifdef T_SEND_TIME
if (fullread(socket, &t, sizeof(struct timespec)) == -1) goto read_error;
length -= sizeof(struct timespec);
#endif
if (fullread(socket, &type, sizeof(int)) == -1) goto read_error;
length -= sizeof(int);
if (fullread(socket, event_buffer, length) == -1) goto read_error;
if (type == -1) append_received_config_chunk(event_buffer, length);
if (type == -2) verify_config();
if (type == -1 || type == -2) goto again;
#ifdef T_SEND_TIME
return new_event(t, type, length, event_buffer, database);
#else
return new_event(type, length, event_buffer, database);
#endif
read_error:
return (event){type: -1};
}
#ifdef T_SEND_TIME
event new_event(struct timespec sending_time, int type,
int length, char *buffer, void *database)
#else
event new_event(int type, int length, char *buffer, void *database)
#endif
{
database_event_format f;
event e;
int i;
int offset;
#ifdef T_SEND_TIME
e.sending_time = sending_time;
#endif
e.type = type;
e.buffer = buffer;
f = get_format(database, type);
e.ecount = f.count;
offset = 0;
/* setup offsets */
/* TODO: speedup (no strcmp, string event to include length at head) */
for (i = 0; i < f.count; i++) {
//e.e[i].offset = offset;
if (!strcmp(f.type[i], "int")) {
e.e[i].type = EVENT_INT;
e.e[i].i = *(int *)(&buffer[offset]);
offset += 4;
} else if (!strcmp(f.type[i], "ulong")) {
e.e[i].type = EVENT_ULONG;
e.e[i].ul = *(unsigned long *)(&buffer[offset]);
offset += sizeof(unsigned long);
} else if (!strcmp(f.type[i], "string")) {
e.e[i].type = EVENT_STRING;
e.e[i].s = &buffer[offset];
while (buffer[offset]) offset++;
offset++;
} else if (!strcmp(f.type[i], "buffer")) {
int len;
e.e[i].type = EVENT_BUFFER;
len = *(int *)(&buffer[offset]);
e.e[i].bsize = len;
e.e[i].b = &buffer[offset+sizeof(int)];
offset += len+sizeof(int);
} else {
printf("unhandled type '%s'\n", f.type[i]);
abort();
}
}
if (e.ecount==0) { printf("FORMAT not set in event %d\n", type); abort(); }
return e;
}
#ifndef _EVENT_H_
#define _EVENT_H_
#include "../T_defs.h"
#ifdef T_SEND_TIME
#include <time.h>
#endif
enum event_arg_type {
EVENT_INT,
EVENT_ULONG,
EVENT_STRING,
EVENT_BUFFER
};
typedef struct {
enum event_arg_type type;
//int offset;
union {
int i;
unsigned long ul;
char *s;
struct {
int bsize;
void *b;
};
};
} event_arg;
typedef struct {
#ifdef T_SEND_TIME
struct timespec sending_time;
#endif
int type;
char *buffer;
event_arg e[T_MAX_ARGS];
int ecount;
} event;
event get_event(int s, char *v, void *d);
#ifdef T_SEND_TIME
event new_event(struct timespec sending_time, int type,
int length, char *buffer, void *database);
#else
event new_event(int type, int length, char *buffer, void *database);
#endif
#endif /* _EVENT_H_ */
This diff is collapsed.
#ifndef _EVENT_SELECTOR_H_
#define _EVENT_SELECTOR_H_
#include "gui/gui.h"
typedef void event_selector;
event_selector *setup_event_selector(gui *g, void *database, int *is_on,
void (*change_callback)(void *), void *change_callback_data);
#endif /* _EVENT_SELECTOR_H_ */
CC=gcc
CFLAGS=-Wall -g -pthread -I..
OBJS=filter.o
filter.a: $(OBJS)
ar cr filter.a $(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
clean:
rm -f *.a *.o
#include "filter.h"
#include "event.h"
#include "database.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct filter {
union {
struct { struct filter *a, *b; } op2;
int v;
struct { int event_type; int arg_index; } evarg;
} v;
int (*eval)(struct filter *this, event e);
};
/****************************************************************************/
/* evaluation functions */
/****************************************************************************/
int eval_and(struct filter *f, event e)
{
if (f->v.op2.a->eval(f->v.op2.a, e) == 0) return 0;
return f->v.op2.b->eval(f->v.op2.b, e);
}
int eval_eq(struct filter *f, event e)
{
int a = f->v.op2.a->eval(f->v.op2.a, e);
int b = f->v.op2.b->eval(f->v.op2.b, e);
return a == b;
}
int eval_int(struct filter *f, event e)
{
return f->v.v;
}
int eval_evarg(struct filter *f, event e)
{
if (e.type != f->v.evarg.event_type) {
printf("%s:%d:%s: bad event type\n", __FILE__, __LINE__, __FUNCTION__);
abort();
}
if (e.e[f->v.evarg.arg_index].type != EVENT_INT) {
printf("%s:%d:%s: bad event argtype; has to be 'int'\n",
__FILE__, __LINE__, __FUNCTION__);
abort();
}
return e.e[f->v.evarg.arg_index].i;
}
/****************************************************************************/
/* filter construction functions */
/****************************************************************************/
filter *filter_and(filter *a, filter *b)
{
struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort();
ret->eval = eval_and;
ret->v.op2.a = a;
ret->v.op2.b = b;
return ret;
}
filter *filter_eq(filter *a, filter *b)
{
struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort();
ret->eval = eval_eq;
ret->v.op2.a = a;
ret->v.op2.b = b;
return ret;
}
filter *filter_int(int v)
{
struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort();
ret->eval = eval_int;
ret->v.v = v;
return ret;
}
filter *filter_evarg(void *database, char *event_name, char *varname)
{
struct filter *ret;
int event_id;
database_event_format f;
int i;
ret = calloc(1, sizeof(struct filter)); if (ret == NULL) abort();
event_id = event_id_from_name(database, event_name);
f = get_format(database, event_id);
ret->eval = eval_evarg;
ret->v.evarg.event_type = event_id;
ret->v.evarg.arg_index = -1;
for (i = 0; i < f.count; i++) {
if (strcmp(f.name[i], varname) != 0) continue;
ret->v.evarg.arg_index = i;
break;
}
if (ret->v.evarg.arg_index == -1) {
printf("%s:%d:%s: event '%s' has no argument '%s'\n",
__FILE__, __LINE__, __FUNCTION__, event_name, varname);
abort();
}
return ret;
}
/****************************************************************************/
/* eval function */
/****************************************************************************/
int filter_eval(filter *_f, event e)
{
struct filter *f = _f;
return f->eval(f, e);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
CC=gcc
CFLAGS=-Wall -g -pthread -I..
OBJS=logger.o textlog.o framelog.o ttilog.o timelog.o ticklog.o
logger.a: $(OBJS)
ar cr logger.a $(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
clean:
rm -f *.a *.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment