Change in osmo-e1d[master]: contrib: add e1-prbs-test

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Mon Jan 6 17:27:06 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-e1d/+/16735 )

Change subject: contrib: add e1-prbs-test
......................................................................

contrib: add e1-prbs-test

e1-prbs-test is a small utility that can be used to do PRBS testing
on E1/T1 lines using DAHDI cards.  A transmiter and receiver are
exchanging timeslot-specific PRBS sequences.

Change-Id: Ib25d266e61e0d70919cc4e65d5b1bf0bc9ec7d00
---
A contrib/e1-prbs-test/Makefile
A contrib/e1-prbs-test/README
A contrib/e1-prbs-test/internal.h
A contrib/e1-prbs-test/main.c
A contrib/e1-prbs-test/prbs.c
A contrib/e1-prbs-test/rx.c
A contrib/e1-prbs-test/tx.c
A contrib/e1-prbs-test/utils.c
8 files changed, 727 insertions(+), 0 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved



diff --git a/contrib/e1-prbs-test/Makefile b/contrib/e1-prbs-test/Makefile
new file mode 100644
index 0000000..726befc
--- /dev/null
+++ b/contrib/e1-prbs-test/Makefile
@@ -0,0 +1,16 @@
+LIBOSMO_CFLAGS:=$(shell pkg-config --cflags libosmocore)
+LIBOSMO_LIBS:=$(shell pkg-config --libs libosmocore)
+
+CFLAGS=-O2 -g -Wall -Werror $(LIBOSMO_CFLAGS)
+LIBS=$(LIBOSMO_LIBS)
+
+all: e1-prbs-test
+
+e1-prbs-test: main.o rx.o tx.o prbs.o utils.o
+	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+%.o: %.c
+	$(CC) $(CFLAGS) -o $@ -c $^
+
+clean:
+	@rm -f e1-prbs-test e1-prbs-test *.o
diff --git a/contrib/e1-prbs-test/README b/contrib/e1-prbs-test/README
new file mode 100644
index 0000000..903cc39
--- /dev/null
+++ b/contrib/e1-prbs-test/README
@@ -0,0 +1,36 @@
+e1-prbs-test - Utility to test for bit errors on E1 lines using DAHDI
+======================================================================
+
+e1-prbs-test can be used to test for bit errors in E1 transmission
+lines. It consists of a sender and a receiver, which should be used
+on either end of the E1 line.
+
+Transmitter and receiver can be on the same machine, or on different
+machines.
+
+The code currently works directly on DAHDI, so only DAHDI-supported E1
+cards are supported at this point.
+
+The test works by sending timeslot-specific PRBS sequences of 512 bit
+(64byte) length on the transmit side, and by correlating to those PRBS
+sequences on the receiver side.
+
+The use is relatively simple:
+
+For the A-side, assuming you would want to use DAHDI span 1:
+  e1-prbs-test /dev/dahdi/chan/001
+
+For the B-side, assuming you would want to use DAHDI span 2:
+  e1-prbs-test /dev/dahdi/chan/002
+
+The test will run indefinitely.
+
+If you'd like to get an interim report, send a SIGHUP to
+e1-prbs-test.
+
+If you'd like to stop, simply press Ctrl+C.
+There is a two-stage shut-down process.  When you press Ctrl+C for
+the first time, the report is printed, but transmission continues. At
+the second Ctrl+C, the process terminates.   You must press Ctrl+C for
+the first time on both A and B side, before pressing it the second time
+on the A-side in order to get correct results.
diff --git a/contrib/e1-prbs-test/internal.h b/contrib/e1-prbs-test/internal.h
new file mode 100644
index 0000000..681648a
--- /dev/null
+++ b/contrib/e1-prbs-test/internal.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/prbs.h>
+#include <osmocom/core/select.h>
+
+#define MAX_NR_TS	31
+#define PRBS_LEN	2048
+
+/* prbs.c */
+
+struct timeslot_state;
+struct prbs_precomp {
+	uint8_t bytes[PRBS_LEN/8];
+};
+
+void prbs_for_ts_nr(struct osmo_prbs *prbs, uint8_t ts_nr);
+
+void prbs_precomp(struct prbs_precomp *out, const struct osmo_prbs *prbs);
+void ts_init_prbs_tx(struct timeslot_state *ts, unsigned int prbs_offs_tx);
+void ts_init_prbs_rx(struct timeslot_state *ts, unsigned int prbs_offs_rx);
+
+/* utils.c */
+uint8_t bits_set_in_byte(uint8_t byte);
+void cfg_dahdi_buffer(int fd);
+void set_realtime(int rt_prio);
+
+
+struct timeslot_state_tx {
+	struct osmo_prbs prbs;			/* PRBS definition */
+	struct prbs_precomp prbs_pc;		/* pre-computed PRBS bytes */
+	unsigned int prbs_pc_idx;		/* next to-be-transmitted byte offset in prbs_pc */
+};
+
+struct timeslot_state_rx {
+	struct osmo_prbs prbs;			/* PRBS definition */
+	struct prbs_precomp prbs_pc[8];		/* bit-shifted pre-computed PRBS sequences */
+	struct {
+		bool has_sync;			/* do we have a PRBS sync? */
+		struct timespec ts_sync;	/* time at which sync was established */
+		unsigned int prbs_pc_num;	/* index to prbs_pc[] array */
+		unsigned int prbs_pc_offset;	/* offset of next byte into prbs_pc[pc_num].bytes[] */
+
+		unsigned int num_bit_err;	/* bit errors since last sync */
+		unsigned int num_sync_loss;	/* number of sync losses since start */
+	} sync_state;
+};
+
+
+struct timeslot_state {
+	struct osmo_fd ofd;
+	struct timeslot_state_tx tx;
+	struct timeslot_state_rx rx;
+};
+
+struct test_state {
+	struct timeslot_state ts[MAX_NR_TS];
+	unsigned int next_unused_ts;
+};
+
+/* rx.c */
+void process_rx(struct timeslot_state_rx *tsr, unsigned int ts_nr, const uint8_t *data, unsigned int len);
+
+/* tx.c */
+void process_tx(struct timeslot_state *ts, int len);
diff --git a/contrib/e1-prbs-test/main.c b/contrib/e1-prbs-test/main.c
new file mode 100644
index 0000000..4fe0e84
--- /dev/null
+++ b/contrib/e1-prbs-test/main.c
@@ -0,0 +1,208 @@
+/* (C) 2019 by Harald Welte <laforge at gnumonks.org>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <dahdi/user.h>
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/bits.h>
+#include <osmocom/core/prbs.h>
+
+#include "internal.h"
+
+static struct test_state g_tst;
+static int g_prbs_offs_rx;
+static int g_prbs_offs_tx;
+
+static int e1_fd_cb(struct osmo_fd *ofd, unsigned int what)
+{
+	struct timeslot_state *ts = ofd->data;
+	uint8_t buf[4096];
+	int rc, len;
+
+	OSMO_ASSERT(what & OSMO_FD_READ);
+
+	/* read whatever data */
+	rc = read(ofd->fd, buf, sizeof(buf));
+	if (rc < 0) {
+		fprintf(stderr, "E1TS(%d) read: %d (%s)\n", ofd->priv_nr, rc, strerror(errno));
+		return rc;
+	}
+	len = rc;
+	process_rx(&ts->rx, ofd->priv_nr, buf, len);
+
+	/* generate as many bytes as were read */
+	process_tx(ts, len);
+
+	return 0;
+}
+
+static int open_slots(struct test_state *tst, const char *basedir)
+{
+	DIR *dir = opendir(basedir);
+	struct dirent *ent;
+	int rc, num_slots = 0;
+
+	if (!dir)
+		return -ENOENT;
+
+	while ((ent = readdir(dir))) {
+		struct timeslot_state *ts;
+		switch (ent->d_type) {
+		case DT_CHR:
+		case DT_FIFO:
+		case DT_SOCK:
+			break;
+		default:
+			printf("%s: skipping\n", ent->d_name);
+			continue;
+		}
+
+		rc = openat(dirfd(dir), ent->d_name, O_RDWR);
+		if (rc < 0) {
+			fprintf(stderr, "Error opening %s: %d (%s)\n", ent->d_name, rc, strerror(errno));
+			return -1;
+		}
+		ts = &tst->ts[tst->next_unused_ts++];
+
+		/* open the respective file descriptor */
+		osmo_fd_setup(&ts->ofd, rc, BSC_FD_READ, e1_fd_cb, ts, atoi(ent->d_name));
+		osmo_fd_register(&ts->ofd);
+		printf("E1TS(%02u) opened\n", ts->ofd.priv_nr);
+
+		ts_init_prbs_tx(ts, g_prbs_offs_tx);
+		ts_init_prbs_rx(ts, g_prbs_offs_rx);
+
+		/* start to put something into the transmit queue, before we get read-triggered
+		 * later on */
+		process_tx(ts, 1024);
+
+		cfg_dahdi_buffer(ts->ofd.fd);
+		struct dahdi_bufferinfo bi;
+		rc = ioctl(ts->ofd.fd, DAHDI_GET_BUFINFO, &bi);
+		OSMO_ASSERT(rc == 0);
+		printf("tx_pol=%d, rx_pol=%d, num=%d, size=%d, nread=%d, nwrite=%d\n",
+			bi.txbufpolicy, bi.rxbufpolicy, bi.numbufs, bi.bufsize, bi.readbufs, bi.writebufs); 
+		num_slots++;
+	}
+	closedir(dir);
+	return num_slots;
+}
+
+static void print_report(void)
+{
+	struct timespec ts_now;
+	int i;
+
+	clock_gettime(CLOCK_MONOTONIC, &ts_now);
+
+	for (i = 0; i < ARRAY_SIZE(g_tst.ts); i++) {
+		const struct timeslot_state *ts = &g_tst.ts[i];
+		printf("E1TS(%02u) STATS: sync_losses=%u, bit_errs=%u in %lu seconds\n",
+			ts->ofd.priv_nr, ts->rx.sync_state.num_sync_loss, ts->rx.sync_state.num_bit_err,
+			ts_now.tv_sec - ts->rx.sync_state.ts_sync.tv_sec);
+	}
+}
+
+static int g_ctrlc_count = 0;
+
+static void sig_handler(int signal)
+{
+	switch (signal) {
+	case SIGINT:
+		g_ctrlc_count++;
+		if (g_ctrlc_count == 1) {
+			print_report();
+			printf("\nPlease stop remote end before pressing Ctrl+C another time\n");
+		}
+		if (g_ctrlc_count > 1)
+			exit(0);
+		break;
+	case SIGHUP:
+		print_report();
+		break;
+	}
+}
+
+static void handle_options(int argc, char **argv)
+{
+	while (1) {
+		int c;
+		static const struct option long_opts[] = {
+			{ "rx-prbs-offset", 1, 0, 'r' },
+			{ "tx-prbs-offset", 1, 0, 't' },
+			{ 0, 0, 0, 0 }
+		};
+		c = getopt_long(argc, argv, "r:t:", long_opts, NULL);
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'r':
+			g_prbs_offs_rx = atoi(optarg);
+			break;
+		case 't':
+			g_prbs_offs_tx = atoi(optarg);
+			break;
+		default:
+			exit(1);
+		}
+	}
+}
+
+int main(int argc, char **argv)
+{
+	char *basedir;
+	int rc;
+
+	handle_options(argc, argv);
+
+	if (argc <= optind) {
+		fprintf(stderr, "You must specify the base-path of your DAHDI span "
+			"like /dev/dahdi/chan/001\n");
+		exit(1);
+	}
+	basedir = argv[optind];
+
+	set_realtime(10);
+	rc = open_slots(&g_tst, basedir);
+	printf("==> opened a total of %d slots\n", rc);
+
+	signal(SIGINT, sig_handler);
+	signal(SIGHUP, sig_handler);
+	while (1) {
+		osmo_select_main(0);
+	}
+}
diff --git a/contrib/e1-prbs-test/prbs.c b/contrib/e1-prbs-test/prbs.c
new file mode 100644
index 0000000..ed8a80a
--- /dev/null
+++ b/contrib/e1-prbs-test/prbs.c
@@ -0,0 +1,183 @@
+/* (C) 2019 by Harald Welte <laforge at gnumonks.org>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/prbs.h>
+
+#include "internal.h"
+
+/* according to https://users.ece.cmu.edu/~koopman/lfsr/index.html all below
+ * coefficients should render maximal length LFSRs of 11bit (2048) length */
+static const uint32_t prbs11_coeff[] = {
+	0x402,
+	0x40B,
+	0x415,
+	0x416,
+	0x423,
+	0x431,
+	0x432,
+	0x438,
+	0x43D,
+	0x446,
+	0x44A,
+	0x44F,
+	0x454,
+	0x458,
+	0x467,
+	0x468,
+	0x470,
+	0x473,
+	0x475,
+	0x47A,
+	0x486,
+	0x489,
+	0x492,
+	0x494,
+	0x49D,
+	0x49E,
+	0x4A2,
+	0x4A4,
+	0x4A8,
+	0x4AD,
+	0x4B9,
+	0x4BA,
+	0x4BF,
+	0x4C1,
+	0x4C7,
+	0x4D5,
+	0x4D6,
+	0x4DC,
+	0x4E3,
+	0x4EC,
+	0x4F2,
+	0x4FB,
+	0x500,
+	0x503,
+	0x509,
+	0x50A,
+	0x514,
+	0x524,
+	0x530,
+	0x536,
+	0x53C,
+	0x53F,
+	0x542,
+	0x548,
+	0x54E,
+	0x553,
+	0x555,
+	0x559,
+	0x55A,
+	0x56A,
+	0x56F,
+	0x574,
+	0x577,
+	0x578,
+	0x57D,
+	0x581,
+	0x584,
+	0x588,
+	0x599,
+	0x59F,
+	0x5A0,
+	0x5A5,
+	0x5AC,
+	0x5AF,
+	0x5B2,
+	0x5B7,
+	0x5BE,
+	0x5C3,
+	0x5C5,
+	0x5C9,
+	0x5CA,
+	0x5D7,
+	0x5DB,
+	0x5DE,
+	0x5E4,
+	0x5ED,
+	0x5EE,
+	0x5F3,
+	0x5F6,
+	0x605,
+	0x606,
+	0x60C,
+	0x60F,
+	0x62B,
+	0x630,
+	0x635,
+	0x639,
+	0x642,
+	0x644,
+	0x64B
+};
+
+/* build the PRBS description for a given timeslot number */
+void prbs_for_ts_nr(struct osmo_prbs *prbs, uint8_t ts_nr)
+{
+
+	OSMO_ASSERT(ts_nr < ARRAY_SIZE(prbs11_coeff));
+	prbs->name = "custom";
+	prbs->len = 11;
+	prbs->coeff = prbs11_coeff[ts_nr];
+}
+
+/* compute one full sequence of the given PRBS */
+void prbs_precomp(struct prbs_precomp *out, const struct osmo_prbs *prbs)
+{
+	struct osmo_prbs_state prbs_s;
+	int i;
+
+	osmo_prbs_state_init(&prbs_s, prbs);
+	for (i = 0; i < sizeof(out->bytes); i++) {
+		ubit_t ubit[8];
+		osmo_prbs_get_ubits(ubit, sizeof(ubit), &prbs_s);
+		osmo_ubit2pbit(&out->bytes[i], ubit, sizeof(ubit));
+	}
+}
+
+void ts_init_prbs_tx(struct timeslot_state *ts, unsigned int prbs_offs_tx)
+{
+	unsigned int prbs_nr = prbs_offs_tx + ts->ofd.priv_nr;
+	/* initialize the transmit-side PRNG for this slot */
+	printf("Selecting PRBS11 #%02u for Tx of TS%02u\n", prbs_nr, ts->ofd.priv_nr);
+	prbs_for_ts_nr(&ts->tx.prbs, prbs_nr);
+	prbs_precomp(&ts->tx.prbs_pc, &ts->tx.prbs);
+}
+
+void ts_init_prbs_rx(struct timeslot_state *ts, unsigned int prbs_offs_rx)
+{
+	unsigned int prbs_nr = prbs_offs_rx + ts->ofd.priv_nr;
+	/* initialize the receive-side PRNG for this slot */
+	ubit_t ubit[PRBS_LEN*2];
+	printf("Selecting PRBS11 #%02u for Rx of TS%02u\n", prbs_nr, ts->ofd.priv_nr);
+	prbs_for_ts_nr(&ts->rx.prbs, prbs_nr);
+	prbs_precomp(&ts->rx.prbs_pc[0], &ts->rx.prbs);
+	osmo_pbit2ubit(ubit, ts->rx.prbs_pc[0].bytes, PRBS_LEN);
+	/* copy buffer twice back-to-back */
+	memcpy(ubit+PRBS_LEN, ubit, PRBS_LEN);
+
+	/* pre-compute bit-shifted versions */
+	for (int i = 1; i < ARRAY_SIZE(ts->rx.prbs_pc); i++) {
+		osmo_ubit2pbit_ext(ts->rx.prbs_pc[i].bytes, 0, ubit, i, PRBS_LEN, 0);
+		//printf("%d: %s\n", i, osmo_hexdump_nospc(ts->prbs_pc[i].bytes, sizeof(ts->prbs_pc[i].bytes)));
+	}
+}
diff --git a/contrib/e1-prbs-test/rx.c b/contrib/e1-prbs-test/rx.c
new file mode 100644
index 0000000..bb6967d
--- /dev/null
+++ b/contrib/e1-prbs-test/rx.c
@@ -0,0 +1,106 @@
+/* (C) 2019 by Harald Welte <laforge at gnumonks.org>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/utils.h>
+
+#include "internal.h"
+
+static uint8_t next_prbs_pc_byte(struct timeslot_state_rx *tsr)
+{
+	const struct prbs_precomp *pc = &tsr->prbs_pc[tsr->sync_state.prbs_pc_num];
+	uint8_t ret = pc->bytes[tsr->sync_state.prbs_pc_offset];
+	tsr->sync_state.prbs_pc_offset = (tsr->sync_state.prbs_pc_offset + 1) % sizeof(pc->bytes);
+	return ret;
+}
+
+/* compare if received buffer matches PRBS; count number of different bits */
+static unsigned int compare_buf(struct timeslot_state_rx *tsr, const uint8_t *data, unsigned int len)
+{
+	unsigned int i, num_wrong_bits = 0;
+
+	for (i = 0; i < len; i++) {
+		uint8_t bt = next_prbs_pc_byte(tsr);
+		if (data[i] != bt) {
+			uint8_t x = data[i] ^ bt;
+			num_wrong_bits += bits_set_in_byte(x);
+		}
+	}
+	return num_wrong_bits;
+}
+
+/* process incoming received data; try to correlate with prbs sequence */
+void process_rx(struct timeslot_state_rx *tsr, unsigned int ts_nr, const uint8_t *data, unsigned int len)
+{
+	if (!tsr->sync_state.has_sync) {
+		unsigned int pc_num;
+		/* we haven't synced yet and must attempt to sync to the pattern.  We will try
+		 * to match each pattern */
+		for (pc_num = 0; pc_num < ARRAY_SIZE(tsr->prbs_pc); pc_num++) {
+			const struct prbs_precomp *pc = &tsr->prbs_pc[pc_num];
+			uint8_t *found;
+			long int offset;
+
+			OSMO_ASSERT(len > sizeof(pc->bytes));
+			found = memmem(data, len, pc->bytes, sizeof(pc->bytes));
+			if (!found)
+				continue;
+
+			offset = (found - data);
+			printf("E1TS(%02u) FOUND SYNC (pc_num=%u, offset=%li)\n", ts_nr,
+				pc_num, offset);
+			clock_gettime(CLOCK_MONOTONIC, &tsr->sync_state.ts_sync);
+			tsr->sync_state.has_sync = true;
+			tsr->sync_state.prbs_pc_num = pc_num;
+			tsr->sync_state.prbs_pc_offset = (sizeof(pc->bytes) - offset) % sizeof(pc->bytes);
+			tsr->sync_state.num_bit_err = 0;
+			/* FIXME: compare the remainder of the buffer */
+			return;
+		}
+	}
+	if (tsr->sync_state.has_sync) {
+		unsigned int num_wrong_bits;
+		/* we already have sync */
+		num_wrong_bits = compare_buf(tsr, data, len);
+		if (num_wrong_bits >= len*8/4) { /* more than 25% of wrong bits */
+			struct timespec ts_now;
+			clock_gettime(CLOCK_MONOTONIC, &ts_now);
+			printf("E1TS(%02u) LOST SYNC after %u of %u wrong bits in one buffer; "
+				"until now, total bit errors %u in %lu seconds\n", ts_nr,
+				num_wrong_bits, len*8, tsr->sync_state.num_bit_err,
+				ts_now.tv_sec - tsr->sync_state.ts_sync.tv_sec);
+			tsr->sync_state.has_sync = false;
+			tsr->sync_state.num_sync_loss++;
+		}
+		tsr->sync_state.num_bit_err += num_wrong_bits;
+	}
+}
diff --git a/contrib/e1-prbs-test/tx.c b/contrib/e1-prbs-test/tx.c
new file mode 100644
index 0000000..6d775d7
--- /dev/null
+++ b/contrib/e1-prbs-test/tx.c
@@ -0,0 +1,47 @@
+/* (C) 2019 by Harald Welte <laforge at gnumonks.org>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/utils.h>
+
+#include "internal.h"
+
+void process_tx(struct timeslot_state *ts, int len)
+{
+	uint8_t buf[4096];
+	int i, rc;
+
+	for (i = 0; i < len; i++) {
+		buf[i] = ts->tx.prbs_pc.bytes[ts->tx.prbs_pc_idx];
+		ts->tx.prbs_pc_idx = (ts->tx.prbs_pc_idx + 1) % sizeof(ts->tx.prbs_pc);
+	}
+	rc = write(ts->ofd.fd, buf, len);
+	if (rc != len)
+		fprintf(stderr, "E1TS(%02u) write: %d bytes less than %d\n", ts->ofd.priv_nr, rc, len);
+}
diff --git a/contrib/e1-prbs-test/utils.c b/contrib/e1-prbs-test/utils.c
new file mode 100644
index 0000000..5610e80
--- /dev/null
+++ b/contrib/e1-prbs-test/utils.c
@@ -0,0 +1,66 @@
+/* (C) 2019 by Harald Welte <laforge at gnumonks.org>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <sched.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <dahdi/user.h>
+
+#include <osmocom/core/utils.h>
+
+/* we could generate a lookup table at start ... */
+uint8_t bits_set_in_byte(uint8_t byte)
+{
+	uint8_t ret = 0;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		if (byte & (1 << i))
+			ret += 1;
+	}
+	return ret;
+}
+
+void cfg_dahdi_buffer(int fd)
+{
+	struct dahdi_bufferinfo bi = {
+		.txbufpolicy = DAHDI_POLICY_WHEN_FULL, /* default is immediate */
+		.rxbufpolicy = DAHDI_POLICY_WHEN_FULL, /* default is immediate */
+		.numbufs = 8, /* default is 2 */
+		.bufsize = 1024, /* default is 1024 */
+		.readbufs = -1,
+		.writebufs = -1,
+	};
+	OSMO_ASSERT(ioctl(fd, DAHDI_SET_BUFINFO, &bi) == 0);
+}
+
+void set_realtime(int rt_prio)
+{
+	struct sched_param param;
+	int rc;
+
+	memset(&param, 0, sizeof(param));
+	param.sched_priority = rt_prio;
+	rc = sched_setscheduler(getpid(), SCHED_RR, &param);
+	OSMO_ASSERT(rc == 0);
+}

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-e1d/+/16735
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-e1d
Gerrit-Branch: master
Gerrit-Change-Id: Ib25d266e61e0d70919cc4e65d5b1bf0bc9ec7d00
Gerrit-Change-Number: 16735
Gerrit-PatchSet: 3
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200106/a146fc52/attachment.htm>


More information about the gerrit-log mailing list