<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-e1d/+/16735">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

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

<div style="display:none"> Gerrit-Project: osmo-e1d </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ib25d266e61e0d70919cc4e65d5b1bf0bc9ec7d00 </div>
<div style="display:none"> Gerrit-Change-Number: 16735 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>