Commit 0ea04a2b authored by Joanne Hugé's avatar Joanne Hugé

Clean up, bug fixes, add frame tracer and analyzer

parent 7b4b19a8
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <getopt.h>
#include <immintrin.h>
#include <inttypes.h>
#include <limits.h>
#include <linux/if_packet.h>
#include <math.h>
#include <netdb.h>
#include <netinet/ether.h>
#include <netinet/in.h>
#include <net/if.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
/* Note: src and dst must be 16 byte aligned */
static void float_to_int16(int16_t *dst, const float *src, int n, float mult)
{
const __m128 *p;
__m128i *q, a0, a1;
__m128 mult1;
mult1 = _mm_set1_ps(mult);
p = (const void *)src;
q = (void *)dst;
while (n >= 16) {
a0 = _mm_cvtps_epi32(p[0] * mult1);
a1 = _mm_cvtps_epi32(p[1] * mult1);
q[0] = _mm_packs_epi32(a0, a1);
a0 = _mm_cvtps_epi32(p[2] * mult1);
a1 = _mm_cvtps_epi32(p[3] * mult1);
q[1] = _mm_packs_epi32(a0, a1);
p += 4;
q += 2;
n -= 16;
}
if (n >= 8) {
a0 = _mm_cvtps_epi32(p[0] * mult1);
a1 = _mm_cvtps_epi32(p[1] * mult1);
q[0] = _mm_packs_epi32(a0, a1);
p += 2;
q += 1;
n -= 8;
}
if (n != 0) {
/* remaining samples (n <= 7) */
do {
a0 = _mm_cvtps_epi32(_mm_load_ss((float *)p) * mult);
*(int16_t *)q = _mm_cvtsi128_si32 (_mm_packs_epi32(a0, a0));
p = (__m128 *)((float *)p + 1);
q = (__m128i *)((int16_t *)q + 1);
n--;
} while (n != 0);
}
}
/* Note: src and dst must be 16 byte aligned */
static void int16_to_float(float *dst, const int16_t *src, int len, float mult)
{
__m128i a0, a1, a, b, sign;
__m128 mult1;
mult1 = _mm_set1_ps(mult);
while (len >= 8) {
a = *(__m128i *)&src[0];
#ifdef SSE4
a0 = _mm_cvtepi16_epi32(a);
#else
// Fix for CPU without SSE4.1
a0 = _mm_unpacklo_epi16(a, a);
a0 = _mm_srai_epi32(a0, 16);
#endif
b = _mm_srli_si128(a, 8);
#ifdef SSE4
a1 = _mm_cvtepi16_epi32(b);
#else
a1 = _mm_unpacklo_epi16(b, b);
a1 = _mm_srai_epi32(a1, 16);
#endif
*(__m128 *)&dst[0] = _mm_cvtepi32_ps(a0) * mult1;
*(__m128 *)&dst[4] = _mm_cvtepi32_ps(a1) * mult1;
dst += 8;
src += 8;
len -= 8;
}
/* remaining data */
while (len != 0) {
_mm_store_ss(&dst[0], _mm_cvtsi32_ss(_mm_setzero_ps(), src[0]) * mult1);
dst++;
src++;
len--;
}
}
/* Compr_bf1 */
static inline int max_int(int a, int b)
{
if (a > b)
return a;
else
return b;
}
static inline int min_int(int a, int b)
{
if (a < b)
return a;
else
return b;
}
static inline int clamp_int(int val, int min_val, int max_val)
{
if (val < min_val)
return min_val;
else if (val > max_val)
return max_val;
else
return val;
}
/* 1 <= n_bits <= 7 */
static void encode_put_bits(uint8_t *buf, int bit_offset, int n_bits, unsigned int val)
{
int shift, n;
shift = bit_offset & 7;
buf[bit_offset >> 3] |= val << shift;
n = 8 - shift;
if (n > 0)
buf[(bit_offset >> 3) + 1] |= val >> n;
}
/* 1 <= n_bits <= 7 */
static int decode_get_bits(const uint8_t *buf, int bit_offset, int n_bits)
{
int shift, n, v;
shift = bit_offset & 7;
n = 8 - shift;
v = buf[bit_offset >> 3];
if (n_bits > n)
v |= buf[(bit_offset >> 3) + 1] << 8;
return (v >> shift) & ((1 << n_bits) - 1);
}
#define BLOCK_LEN 8
#define CMULT_BITS 7
#define CMULT 181
/* CPRI frame format for 122.88 MHz with 4 channels using bit rate
option 7 (9.8304 Gb/s):
data byte offset
0 Channel 0. One BF1 block containing I0, Q0, I1, Q1, ..., I31, Q31.
60 Channel 1
120 Channel 2
180 Channel 3
*/
/* take 64 * 16 bit I or Q values as input and return 60 bytes into obuf.
When using a smaller sample bit width, the samples should be
appropriately scaled (e.g. multiplied by 2 for a bit width =
15). */
static void encode_bf1(uint8_t *obuf, const int16_t *samples)
{
int e, vmax, v, block_num, i, e1, m;
memset(obuf, 0, 4 + 7 * BLOCK_LEN);
/* the compressed data contains 8 blocks of 8 I or Q components. Each
block is compressed independently but the corresponding values
and output bits are interleaved. */
for(block_num = 0; block_num < 8; block_num++) {
vmax = 0;
for(i = 0; i < BLOCK_LEN; i++) {
vmax = max_int(vmax, abs(samples[i * 8 + block_num]));
}
vmax = min_int(vmax, (1 << 15) - 1);
/* 0 <= vmax <= 2^15-1 */
e = 8;
while (vmax < (1 << 14) && e > 0) {
vmax <<= 1;
e--;
}
if (e <= 1) {
e1 = e;
m = 1;
} else {
m = (vmax >= (CMULT << (14 - CMULT_BITS)));
e1 = e * 2 + m - 2;
}
encode_put_bits(obuf, block_num * 32, 4, e1); /* store the exponent */
for(i = 0; i < BLOCK_LEN; i++) {
v = samples[i * 8 + block_num];
v = v << (8 - e);
if (!m)
v = v * CMULT;
else
v = v << CMULT_BITS;
/* quantize on 7 bits using two's complement notation */
v = (v + (1 << (8 + CMULT_BITS))) >> (9 + CMULT_BITS);
v = clamp_int(v, -64, 63);
v = v & 0x7f;
if (i < 4)
encode_put_bits(obuf, block_num * 32 + 4 + i * 7, 7, v);
else
encode_put_bits(obuf, 8 * 32 + block_num * 28 + (i - 4) * 7, 7, v);
}
}
}
/* Take 60 bytes as input and return 64 values of sample_bit_width bits
(14 <= sample_bit_width <= 16) */
static void decode_bf1(int16_t *samples, const uint8_t *ibuf, int sample_bit_width)
{
int e, v, e1, m, shift, bias;
int block_num, i;
shift = (15 - sample_bit_width) + CMULT_BITS + 1;
bias = (1 << shift) >> 1;
for(block_num = 0; block_num < 8; block_num++) {
e1 = decode_get_bits(ibuf, block_num * 32, 4);
if (e1 <= 1) {
e = e1;
m = 1;
} else {
e1 += 2;
m = e1 & 1;
e = e1 >> 1;
}
for(i = 0; i < BLOCK_LEN; i++) {
if (i < 4)
v = decode_get_bits(ibuf, block_num * 32 + 4 + i * 7, 7);
else
v = decode_get_bits(ibuf, 8 * 32 + block_num * 28 + (i - 4) * 7, 7);
/* sign extend two's complement 7 bit value to 32 bits */
v = (int32_t)((uint32_t)v << (32 - 7)) >> (32 - 7);
/* multiply by the scale */
v = v << e;
if (!m)
v = v * CMULT;
else
v = v << (CMULT_BITS + 1);
/* shift and round */
v = (v + bias) >> shift;
samples[i * 8 + block_num] = v;
}
}
}
char in[256];
char out[256];
int main(int argc, char ** argv) {
int compress, tx;
int16_t int16_samples[64];
const float mult = 1. / 32767.;
if(argc != 2)
fprintf(stderr, "Wrong argument number");
compress = (argv[1][0] == 'c');
freopen(NULL, "rb", stdin);
fread(in, compress ? (64 * 4) : 60 , 1, stdin);
fclose(stdin);
if(compress) {
float_to_int16(int16_samples, (float *) in, 64, 32767);
encode_bf1(out, int16_samples);
} else {
decode_bf1(int16_samples, in, 16);
int16_to_float((float *) out, int16_samples, 64, mult);
}
freopen(NULL, "wb", stdout);
fwrite(out, compress ? 60 : (64 * 4), 1, stdout);
fclose(stdout);
return 0;
}
import subprocess
import struct
import random
def float_to_byte(float_list):
iq_samples_bytes = bytearray(64 * 4)
for i in range(64):
b = struct.pack('f', float_list[i])
for j in range(4):
iq_samples_bytes[i * 4 + j] = b[j]
return bytes(iq_samples_bytes)
def byte_to_float(b):
float_list = []
for i in range(64):
x = struct.unpack('f', b[4 * i:4 * (i+1)])[0]
float_list.append(x)
return float_list
def compress(b):
s = subprocess.run(
["./bf1", "c"],
input=b,
capture_output=True,
)
return s.stdout
def decompress(b):
s = subprocess.run(["./bf1", "d"],
input=b,
capture_output=True,
)
return s.stdout
iq_samples = [0.2 * (random.randint(1,1000) / 1000.0) for i in range(64)]
iq_samples2 = byte_to_float(decompress(compress(float_to_byte(iq_samples))))
d = []
for i in range(64):
d.append(abs(iq_samples[i]-iq_samples2[i]))
print("{}% accuracy".format(100 - 100 * max(d) / max(map(abs, iq_samples))))
/* DPDK */
#define BURST_SIZE 16
#define MEMPOOL_CACHE_SIZE 256
#define RTE_TEST_RX_DESC_DEFAULT 1024
#define RTE_TEST_TX_DESC_DEFAULT 1024
static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
struct rte_mempool *mbuf_pool;
struct rte_ether_addr s_addr;
struct rte_ether_addr d_addr;
int8_t tx_data[BURST_SIZE][TX_PACKET_SIZE];
static const struct rte_eth_conf port_conf_default = {
.rxmode = { .max_lro_pkt_size = RTE_ETHER_MAX_LEN }
};
static inline int port_init(int portid, struct rte_mempool *mbuf_pool) {
struct rte_eth_conf port_conf = port_conf_default;
const uint16_t rx_rings = 1, tx_rings = 1;
int retval;
uint16_t q;
retval = rte_eth_dev_configure(portid, rx_rings, tx_rings, &port_conf);
if (retval != 0)
return retval;
/* Allocate and set up 1 RX queue per Ethernet port. */
for (q = 0; q < rx_rings; q++) {
retval = rte_eth_rx_queue_setup(portid, q, nb_rxd,
rte_eth_dev_socket_id(portid), NULL, mbuf_pool);
if (retval < 0)
return retval;
}
/* Allocate and set up 1 TX queue per Ethernet port. */
for (q = 0; q < tx_rings; q++) {
retval = rte_eth_tx_queue_setup(portid, q, nb_txd,
rte_eth_dev_socket_id(portid), NULL);
if (retval < 0)
return retval;
}
/* Start the Ethernet port. */
retval = rte_eth_dev_start(portid);
if (retval < 0)
return retval;
return 0;
}
static void init_dpdk(int argc, char ** argv) {
unsigned int nb_mbufs;
int ret;
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "initlize fail!");
argc -= ret;
argv += ret;
nb_mbufs = RTE_MAX((nb_rxd + nb_txd + BURST_SIZE + MEMPOOL_CACHE_SIZE), 8192U);
mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", nb_mbufs,
MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
if (mbuf_pool == NULL)
rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
if (port_init(0, mbuf_pool) != 0)
rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", 0);
}
This diff is collapsed.
......@@ -39,14 +39,13 @@ rf_driver: {
dpdk_options: "-l 10,20 -b 0000:04:00.0 -b 0000:3b:00.0 -b 0000:3b:00.1 -b 0000:5e:00.0 ",
recv_affinity: 39,
send_affinity: 38,
prepare_affinity: 37,
decompress_affinity: 36,
encode_affinity: 37,
decode_affinity: 36,
statistic_affinity: 35,
ecpri_period: 800,
flow_id: 0,
trace_period: 10000000,
trace_file: "/root/ecpri-logs/rx.trace",
stats_file: "/root/ecpri-logs/ecpri.stats",
log_directory: "/root/ecpri-logs",
},
tx_gain: 90.0, /* TX gain (in dB) */
......
This diff is collapsed.
import subprocess
import struct
import random
import os
import hashlib
def _hash(x):
return hashlib.sha256(repr(x).encode()).hexdigest()[:8]
def print_hash(name, x):
print("{:<32}: {}".format(name, _hash(x)))
def parse_binary(b):
return ''.join(map(lambda x:format(int(x), '0>2x'), b))
def parse_frame(buf):
c = [0]
def b(c, n):
ret = buf[c[0]:c[0]+n]
c[0] += n
return ret
dst_mac = b(c, 6)
src_mac = b(c, 6)
ether_type = b(c, 2)
ecpri_common_header = b(c, 4)
pc_id = b(c, 2)
seq_id = b(c, 2)
iq_samples = b(c, 240)
avg = sum(map(lambda x:int(x), iq_samples))
s = '''
dst_mac, src_mac, ether_type: {}, {}, {}
ecpri_common_header: {}
pc_id, seq_id: {}, {}
IQ samples: {}'''.format(
parse_binary(dst_mac),
parse_binary(src_mac),
parse_binary(ether_type),
parse_binary(ecpri_common_header),
parse_binary(pc_id),
parse_binary(seq_id),
parse_binary(iq_samples))[1:]
return (avg == 0, s)
# Parse RX/TX frame
def read_trace(name, n):
log_directory = '/root/ecpri-logs'
file_name = '{}/{}'.format(log_directory, name)
n = min(n * 262, os.path.getsize(file_name))
f = open(file_name, "rb")
data = f.read(n)
f.close()
print(name + ", frame number = " + str(n / 262))
return data
def print_frame(data):
n = len(data)
frame_len = 262
for i in range(int(n / frame_len)):
empty, s = parse_frame(data[i * frame_len:(i+1) * frame_len])
if empty:
continue
print("Frame example:\n\n{}\n".format(s))
break
def analyze_tdd(data):
null_frames = 0
tdd_switch_list = []
prev_empty = False
prev_i = 0
n = len(data)
frame_len = 262
for i in range(int(n / frame_len)):
empty, s = parse_frame(data[i * frame_len:(i+1) * frame_len])
if i > 0 and empty != prev_empty:
tdd_switch_list.append(i-prev_i)
prev_i = i
null_frames += empty
prev_empty = empty
tdd_switch_list.append(i-prev_i)
print('Frame analyzed: ' + str(i))
total_frames = int(n / frame_len)
ratio = total_frames / null_frames if null_frames > 0 else 'inf'
print('TDD ratio: {}\n'.format(ratio))
print('TDD switch list: ' + ', '.join(map(str, tdd_switch_list)) + '\n')
def print_frame_list(data, start, end):
n = len(data)
frame_len = 262
end = int(n / frame_len) if end == -1 else end
end = min(int(n / frame_len), end)
for i in range(start, end):
empty, s = parse_frame(data[i * frame_len:(i+1) * frame_len])
print(s)
print('')
def print_iq_list(data, start, end, tx=False):
n = len(data)
frame_len = 64 * 4
end = int(n / frame_len) if end == -1 else end
end = min(int(n / frame_len), end)
for i in range(start * 4, end * 4, 4):
iq = data[i * frame_len:(i+1) * frame_len]
iq_packed = []
k = 0
h = _hash(iq)
prev_x = 2
for x in map(lambda x: int(x != 0), iq):
if x == prev_x:
iq_packed[-1][0] += 1
else:
iq_packed.append([1, str(x) * 2])
prev_x = x
print(h + " " + " ".join(map(lambda x: "{}*{}".format(*x), iq_packed)))
# Parse RX/TX frame
def read_trx_trace(name, n, channels):
log_directory = '/root/ecpri-logs'
file_name = '{}/{}'.format(log_directory, name)
n = min(n * (4 * channels * 64), os.path.getsize(file_name))
f = open(file_name, "rb")
data = f.read(n)
f.close()
print(name + ", frame number = " + str(n / (4 * channels * 64)))
return data
def analyze_trx_tdd(data, channels):
null_frames = 0
tdd_switch_list = []
prev_empty = False
prev_i = 0
n = len(data)
frame_len = channels * 4 * 64
max_iq_sample = 0
min_iq_sample = 0
avg_iq_sample = 0
for i in range(int(n / frame_len)):
iq_samples = data[i * frame_len:(i+1) * frame_len]
iq_samples = [struct.unpack('f', iq_samples[4*j:4*(j+1)])[0] for j in range(int(len(iq_samples) / 4))]
iq_samples_abs_avg = sum(map(abs, iq_samples))
max_iq_sample = max(max_iq_sample, max(iq_samples))
min_iq_sample = min(min_iq_sample, min(iq_samples))
avg_iq_sample += iq_samples_abs_avg
empty = iq_samples_abs_avg < 0.1
if i > 0 and empty != prev_empty:
tdd_switch_list.append(i-prev_i)
prev_i = i
null_frames += empty
prev_empty = empty
tdd_switch_list.append(i-prev_i)
avg_iq_sample /= (n / frame_len) * (64 * channels)
print('Max IQ sample: {}, Min IQ sample: {}'.format(max_iq_sample, min_iq_sample))
print('Avg IQ sample: {}'.format(avg_iq_sample))
print('Frame analyzed: ' + str(i))
total_frames = int(n / frame_len)
ratio = total_frames / null_frames if null_frames > 0 else 'inf'
print('TDD ratio: {}\n'.format(ratio))
print('TDD switch list: ' + ', '.join(map(str, tdd_switch_list)) + '\n')
BF1_PATH="../bf1/bf1"
def float_to_byte(float_list):
iq_samples_bytes = bytearray(64 * 4)
for i in range(64):
b = struct.pack('f', float_list[i])
for j in range(4):
iq_samples_bytes[i * 4 + j] = b[j]
return bytes(iq_samples_bytes)
def byte_to_float(b):
float_list = []
for i in range(64):
x = struct.unpack('f', b[4 * i:4 * (i+1)])[0]
float_list.append(x)
return float_list
def compress(data):
s = subprocess.run(
[BF1_PATH, "c"],
input=data,
capture_output=True,
)
return s.stdout
def decompress(data):
s = subprocess.run([BF1_PATH, "d"],
input=data,
capture_output=True,
)
return s.stdout
def open_all(n):
return (
read_trace('tx.trace', n),
read_trace('rx.trace', n),
read_trx_trace('trxw.trace', n, 4),
read_trx_trace('trxr.trace', n, 1),
)
def analyze_all_tdd(n=0, data=None):
if data:
tx_data, rx_data, trxw_data, trxr_data = data
print("TX")
analyze_tdd(tx_data)
print("RX")
analyze_tdd(rx_data)
print("TRXW")
analyze_trx_tdd(trxw_data, 4)
print("TRXR")
analyze_trx_tdd(trxr_data, 1)
else:
data = read_trace('rx.trace', n)
analyze_tdd(data)
data = read_trace('tx.trace', n)
analyze_tdd(data)
data = read_trx_trace('trxw.trace', n, 4)
analyze_trx_tdd(data, 4)
data = read_trx_trace('trxr.trace', n, 1)
analyze_trx_tdd(data, 1)
def check_tx_trxw(n=0, data=None):
if data:
tx_data, rx_data, trxw_data, trxr_data = data
else:
tx_data = read_trace('tx.trace', n)
trxw_data = read_trx_trace('trxw.trace', n, 4)
for i in range(int(min(len(tx_data) / 262, len(trxw_data) / (64 * 4 * 4)))):
for j in range(1):
k = i * 4 + j
tx_iq = tx_data[(i * 262 + 22 + j * 60):(i * 262 + 22 + (j+1) * 60)]
trxw_iq = trxw_data[(k * (64 * 4)):((k+1) * (64 * 4))]
tx_iq_d = decompress(tx_iq)
trxw_iq_d = compress(trxw_iq)
if (_hash(tx_iq) != _hash(trxw_iq_d)) or (_hash(trxw_iq) != _hash(tx_iq_d)):
print((i,j))
print_hash("TX", tx_iq)
print_hash("TRX compressed", trxw_iq_d)
print_hash("TRX", trxw_iq)
print_hash("TX decompressed", tx_iq_d)
def print_all(n=0, data=None):
if data:
tx_data, rx_data, trxw_data, trxr_data = data
print('TX_DATA')
print_frame_list(tx_data, 0, 10)
print('RX_DATA')
print_frame_list(rx_data, 0, 10)
print('TRXW_DATA')
print('TRXR_DATA')
print_iq_list(trxr_data, 0, 10)
data = open_all(100000)
#check_tx_trxw(data=data)
#print_all(data=data)
analyze_all_tdd(data=data)
export PTP_INSTALL="/root/linuxptp"
export INTERFACE="ens9f0"
export DPDK_INSTALL="/root/dpdk-21.11"
export LTEENB="/root/enb/lteenb"
export ENB_CONFIG="enb.cfg"
export LOG_DIRECTORY="/root/ecpri-logs"
export LD_LIBRARY_PATH="/root/ecpri-priv:/root/enb:$LD_LIBRARY_PATH"
export AMARISOFT_PATH="/root/.amarisoft"
export PTP_INSTALL="/root/linuxptp"
export INTERFACE="ens9f0"
export DPDK_INSTALL="/root/dpdk-stable-20.11.3"
export LTEENB="/root/enb/lteenb"
export ENB_CONFIG="enb-hfr.cfg"
export LOG_DIRECTORY="/home/hfr/ecpri-logs"
export LD_LIBRARY_PATH="/root/ecpri-priv:/root/enb:$LD_LIBRARY_PATH"
export AMARISOFT_PATH="/root/.amarisoft"
......@@ -2,16 +2,7 @@
DIR=$(dirname $(realpath $0))
#HFR
#DPDK_INSTALL=/root/dpdk-stable-20.11.3
#Tiogapass004
DPDK_INSTALL=/root/dpdk-21.11
cd $DPDK_INSTALL/usertools;
python3 dpdk-hugepages.py --setup 2G;
cd $DIR/..;
make;
cd test-eNB;
make all;
ln -sf /root/ecpri-priv/libtrx_ecpri_dpdk.so /root/enb/trx_ecpri.so
ln -sf /root/ecpri-priv/enb.cfg /root/enb/config/enb.cfg
cd $DIR/.. && make;
ln -sf $DIR/../libtrx_ecpri_dpdk.so $(dirname $LTEENB)/trx_ecpri.so
# Tiogapass004 test
#chrt -f 97 taskset -c 2 phc2sys -m -c ens9f1 -s CLOCK_REALTIME -O0 -f $HOME/linuxptp/configs/G.8275.1.cfg
#chrt -f 97 taskset -c 2 phc2sys -m -s ens9f1 -c CLOCK_REALTIME -O0 -f $HOME/linuxptp/configs/G.8275.1.cfg
# HFR Switch
chrt -f 97 taskset -c 39 phc2sys -m -c ens9f0 -s CLOCK_REALTIME -O0 -f $HOME/linuxptp/configs/G.8275.1.cfg
chrt -f 97 taskset -c 39 phc2sys -m -c $INTERFACE -s CLOCK_REALTIME -O0 -f $PTP_INSTALL/configs/G.8275.1.cfg
# Tiogapass003 test
#chrt -f 97 taskset -c 38 ptp4l -H -i ens9f1 -m -f $HOME/linuxptp/configs/G.8275.1.cfg
# HFR Switch
chrt -f 97 taskset -c 38 ptp4l -H -i ens9f0 -m -f $HOME/linuxptp/configs/G.8275.1.cfg
chrt -f 97 taskset -c 38 ptp4l -H -i $INTERFACE -m -f $PTP_INSTALL/configs/G.8275.1.cfg
#!/bin/bash
/root/stop-cpri.sh
DIR=$(dirname $(realpath $0))
$DIR/stop-cpri.sh
systemctl start lte
......@@ -2,23 +2,13 @@
DIR=$(dirname $(realpath $0))
#HFR
#LOGD=/home/hfr
#Tiogapass004
LOGD=/root/ecpri-logs
systemctl stop lte;
$DIR/stop-ecpri.sh;
cd $DIR/..;
#make clean;
make;
cd test-eNB;
make all;
export LD_LIBRARY_PATH="/root/ecpri-priv:/root/enb:$LD_LIBRARY_PATH"
export AMARISOFT_PATH="/root/.amarisoft"
cd $DIR/../test-eNB;
$DIR/../launch-ptp > $LOGD/ptp.log 2> $LOGD/ptp.error &
$DIR/../launch-phc2sys > $LOGD/phc2sys.log 2> $LOGD/phc2sys.error &
#./test-dpdk-ecpri > $LOGD/ecpri.log 2> $LOGD/ecpri.error &
~/enb/lteenb ~/enb/config/enb.cfg
#$DIR/launch-ptp > $LOG_DIRECTORY/ptp.log 2> $LOG_DIRECTORY/ptp.error &
#$DIR/launch-phc2sys > $LOG_DIRECTORY/phc2sys.log 2> $LOG_DIRECTORY/phc2sys.error &
$LTEENB $DIR/../enb-configs/$ENB_CONFIG
......@@ -38,12 +38,11 @@ typedef struct {
const char * rec_mac;
const char * rec_if;
const char * dpdk_options;
const char * trace_file;
const char * stats_file;
const char * log_directory;
int recv_affinity;
int send_affinity;
int prepare_affinity;
int decompress_affinity;
int encode_affinity;
int decode_affinity;
int statistic_affinity;
int ecpri_period;
int flow_id;
......@@ -109,7 +108,8 @@ static int64_t calcdiff_ns(struct timespec t1, struct timespec t2) {
}
TRXState s1;
float ** tx_samples;
float ** tx_samples_zeroes;
float ** tx_samples_ones;
float ** rx_samples;
void dummy_enb_init(TRXState *s1, TRXEcpriState *s);
......@@ -174,7 +174,7 @@ int main(int argc, char * argv[]) {
s->dpdk_options = "-l 10,20 -b 0000:04:00.0 -b 0000:3b:00.0 -b 0000:3b:00.1 -b 0000:5e:00.1 ";
#endif
#if 1
#if 0
// tiogapass-004 MT27710 port1
s->rec_mac = "b8:59:9f:07:86:43";
//s->re_mac = "04:09:a5:0f:9f:4c"; // Lille M6424 Switch
......@@ -192,18 +192,33 @@ int main(int argc, char * argv[]) {
s->dpdk_options = "-l 10,20 -b 0000:04:00.0 -b 0000:3b:00.1 -b 0000:5e:00.0 -b 0000:5e:00.1 ";
#endif
//s->recv_affinity = 39;
//s->send_affinity = 38;
//s->prepare_affinity = 37;
//s->decompress_affinity = 36;
//s->statistic_affinity = 35;
//s->ecpri_period = 800;
//s->flow_id = 0;
//s->sample_rate = 122880000;
//s->trace_file = "/root/ecpri-logs/rx.trace";
//s->stats_file = "/root/ecpri-logs/ecpri.stats";
//s->trace_period = 1000000;
// enb.cfg
s->rec_mac = "b8:59:9f:07:86:42";
s->re_mac = "04:09:a5:0f:9f:4a";
s->rec_if = "ens9f0";
s->dpdk_options = "-l 10,20 -b 0000:04:00.0 -b 0000:3b:00.0 -b 0000:3b:00.1 -b 0000:5e:00.1 ";
s->recv_affinity = 39;
s->send_affinity = 38;
s->prepare_affinity = 37;
s->decompress_affinity = 36;
s->encode_affinity = 37;
s->decode_affinity = 36;
s->statistic_affinity = 35;
s->ecpri_period = 800;
s->flow_id = 0;
s->sample_rate = 122880000;
s->trace_file = "/root/ecpri-logs/rx.trace";
s->stats_file = "/root/ecpri-logs/ecpri.stats";
s->trace_period = 1000000;
s->trace_period = 10000000;
s->log_directory = "/root/ecpri-logs";
log_info("TEST-DPDK-ECPRI", "Starting test...\n");
......@@ -217,17 +232,21 @@ int main(int argc, char * argv[]) {
static void enb(TRXState * s1, TRXEcpriState * s) {
struct timespec next;
trx_timestamp_t ptimestamp;
int64_t p = 1000000 * 100;
int64_t p = 100000 * 10;
int m = 1;
int64_t first_rx_ts;
clock_gettime(CLOCK_TAI, &next);
tx_samples = (float**) malloc(sizeof(float*) * 4);
tx_samples_zeroes = (float**) malloc(sizeof(float*) * 4);
tx_samples_ones = (float**) malloc(sizeof(float*) * 4);
rx_samples = (float**) malloc(sizeof(float*) * 4);
for(int i = 0; i < 4; i++) {
tx_samples[i] = (float*) malloc(sizeof(float) * 65536);
tx_samples_zeroes[i] = (float*) malloc(sizeof(float) * 65536);
tx_samples_ones[i] = (float*) malloc(sizeof(float) * 65536);
rx_samples[i] = (float*) malloc(sizeof(float) * 65536);
for(int j = 0; j < 65536; j++) {
tx_samples[i][j] = i * j;
tx_samples_zeroes[i][j] = 0.0f;
tx_samples_ones[i][j] = 1.0f;
}
}
......@@ -235,12 +254,12 @@ static void enb(TRXState * s1, TRXEcpriState * s) {
int64_t tx_timestamp = 256 * (INT64_C(3840000) * ((int64_t) p * i + p)) / (INT64_C(1000000000));
add_ns(&next, p);
//log_info("TEST-DPDK-ECPRI", "Reading 256 samples");
s1->trx_read_func2(s1, &ptimestamp, rx_samples, 256 * m, 0, NULL);
//log_info("TEST-DPDK-ECPRI", "Writing 256 samples, %" PRIi64, tx_timestamp);
s1->trx_write_func2(s1, tx_timestamp, tx_samples, 256 * m, 0, NULL);
s1->trx_write_func2(s1, tx_timestamp + 256 * m + 100, tx_samples, 256 * m, 0, NULL);
s1->trx_write_func2(s1, tx_timestamp + 2 * 256 * m + 110, tx_samples, 256 * m, 0, NULL);
s1->trx_read_func2(s1, &ptimestamp, rx_samples, 32, 0, NULL);
if(i == 0)
first_rx_ts = ptimestamp;
s1->trx_write_func2(s1, first_rx_ts + 2*i*32, tx_samples_zeroes, 32, 0, NULL);
s1->trx_read_func2(s1, &ptimestamp, rx_samples, 32, 0, NULL);
s1->trx_write_func2(s1, first_rx_ts + (2*i + 1)*32, tx_samples_ones, 32, 0, NULL);
clock_nanosleep(CLOCK_TAI, TIMER_ABSTIME, &next, NULL);
}
......
This diff is collapsed.
static void log_error(const char * section, const char * msg, ...) {
time_t t;
struct tm ts;
char line[256];
va_list arglist;
time(&t);
ts = *localtime(&t);
strftime(line, 80, "%m-%d %H:%M:%S", &ts);
sprintf(line + strlen(line), " ERROR [%s] ", section);
va_start(arglist, msg);
vsprintf(line + strlen(line), msg, arglist);
va_end(arglist);
puts(line);
exit(EXIT_FAILURE);
}
static volatile int64_t limit_counter = 0;
static inline void log_limit(const char * section, const char * msg, ...) {
time_t t;
struct tm ts;
char line[256];
va_list arglist;
if(limit_counter++ % 1000000)
return;
time(&t);
ts = *localtime(&t);
strftime(line, 80, "%m-%d %H:%M:%S", &ts);
sprintf(line + strlen(line), " DEBUG [%s] ", section);
va_start(arglist, msg);
vsprintf(line + strlen(line), msg, arglist);
va_end(arglist);
puts(line);
}
static void log_info(const char * section, const char * msg, ...) {
time_t t;
struct tm ts;
char line[256];
va_list arglist;
time(&t);
ts = *localtime(&t);
strftime(line, 80, "%m-%d %H:%M:%S", &ts);
sprintf(line + strlen(line), " INFO [%s] ", section);
va_start(arglist, msg);
vsprintf(line + strlen(line), msg, arglist);
va_end(arglist);
puts(line);
}
static void log_exit(const char * section, const char * msg, ...) {
time_t t;
struct tm ts;
char line[256];
va_list arglist;
time(&t);
ts = *localtime(&t);
strftime(line, 80, "%m-%d %H:%M:%S", &ts);
sprintf(line + strlen(line), " EXIT [%s] ", section);
va_start(arglist, msg);
vsprintf(line + strlen(line), msg, arglist);
va_end(arglist);
fprintf(stderr, "%s\n", line);
fflush(stdout);
fflush(stderr);
exit(EXIT_FAILURE);
}
#ifdef DEBUG
static void log_debug(const char * section, const char * msg, ...) {
time_t t;
struct tm ts;
char line[256];
va_list arglist;
time(&t);
ts = *localtime(&t);
strftime(line, 80, "%m-%d %H:%M:%S", &ts);
sprintf(line + strlen(line), " DEBUG [%s] ", section);
va_start(arglist, msg);
vsprintf(line + strlen(line), msg, arglist);
va_end(arglist);
puts(line);
}
#else
#define log_debug(...)
#endif
static int latency_target_fd = -1;
static int32_t latency_target_value = 0;
/* Latency trick
* if the file /dev/cpu_dma_latency exists,
* open it and write a zero into it. This will tell
* the power management system not to transition to
* a high cstate (in fact, the system acts like idle=poll)
* When the fd to /dev/cpu_dma_latency is closed, the behavior
* goes back to the system default.
*
* Documentation/power/pm_qos_interface.txt
*/
void set_latency_target(void) {
struct stat s;
int err;
errno = 0;
err = stat("/dev/cpu_dma_latency", &s);
if (err == -1) {
error(EXIT_FAILURE, errno, "WARN: stat /dev/cpu_dma_latency failed");
return;
}
errno = 0;
latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR);
if (latency_target_fd == -1) {
error(EXIT_FAILURE, errno, "WARN: open /dev/cpu_dma_latency");
return;
}
errno = 0;
err = write(latency_target_fd, &latency_target_value, 4);
if (err < 1) {
error(EXIT_FAILURE, errno, "# error setting cpu_dma_latency to %d!",
latency_target_value);
close(latency_target_fd);
return;
}
printf("# /dev/cpu_dma_latency set to %dus\n", latency_target_value);
}
// Timestamps utils
#define NSEC_PER_SEC INT64_C(1000000000)
static struct timespec int_to_ts(int64_t t) {
struct timespec ts;
ts.tv_sec = t / NSEC_PER_SEC;
ts.tv_nsec = t - (ts.tv_sec * NSEC_PER_SEC);
return ts;
}
static int64_t ts_to_int(struct timespec ts) {
return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
}
static void add_ns(struct timespec *t, int64_t ns) {
t->tv_nsec += ns;
while (t->tv_nsec >= ((int64_t)NSEC_PER_SEC)) {
t->tv_sec += 1;
t->tv_nsec -= NSEC_PER_SEC;
}
}
static int64_t calcdiff_ns(struct timespec t1, struct timespec t2) {
int64_t diff;
diff = NSEC_PER_SEC * ((int)t1.tv_sec - (int)t2.tv_sec);
diff += ((int)t1.tv_nsec - (int)t2.tv_nsec);
return diff;
}
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