Change in osmo-e1d[master]: Add virtual pair of E1 interfaces

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
Tue Jun 30 20:15:01 UTC 2020


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

Change subject: Add virtual pair of E1 interfaces
......................................................................

Add virtual pair of E1 interfaces

The idea is to generate a pair of virtual E1 interfaces (each with
identical number of lines), where each line A:n is connected to line B:n
of the pair and vice-versa.

This allows to test E1 using applications back to back against each
other, without any physical E1 circuits in between.

Change-Id: If42c959556b17d543762546eb45dd69d25f715f2
---
M src/Makefile.am
M src/ctl.c
M src/e1d.h
M src/intf_line.c
A src/vpair.c
M src/vty.c
6 files changed, 232 insertions(+), 9 deletions(-)

Approvals:
  Jenkins Builder: Verified
  tnt: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved



diff --git a/src/Makefile.am b/src/Makefile.am
index aa796f2..e811f0a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,6 +35,7 @@
 	log.c \
 	osmo-e1d.c \
 	usb.c \
+	vpair.c \
 	vty.c \
 	$(NULL)
 
diff --git a/src/ctl.c b/src/ctl.c
index b29e990..0fb42de 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -52,8 +52,8 @@
 	return NULL;
 }
 
-static struct e1_line *
-_e1d_find_line(struct e1_intf *intf, uint8_t id)
+struct e1_line *
+e1_intf_find_line(struct e1_intf *intf, uint8_t id)
 {
 	struct e1_line *line;
 
@@ -185,7 +185,7 @@
 		return 0;
 
 	if (hdr->line != E1DP_INVALID) {
-		line = _e1d_find_line(intf, hdr->line);
+		line = e1_intf_find_line(intf, hdr->line);
 		n = line ? 1 : 0;
 	} else{
 		n = llist_count(&intf->lines);
@@ -226,7 +226,7 @@
 	if (!intf)
 		return 0;
 
-	line = _e1d_find_line(intf, hdr->line);
+	line = e1_intf_find_line(intf, hdr->line);
 	if (!line)
 		return 0;
 
@@ -272,7 +272,7 @@
 	if (!intf)
 		return 0;
 
-	line = _e1d_find_line(intf, hdr->line);
+	line = e1_intf_find_line(intf, hdr->line);
 	if (!line)
 		return 0;
 
diff --git a/src/e1d.h b/src/e1d.h
index 7803b2e..64e8f45 100644
--- a/src/e1d.h
+++ b/src/e1d.h
@@ -67,6 +67,7 @@
 
 enum e1_driver {
 	E1_DRIVER_USB,
+	E1_DRIVER_VPAIR,
 };
 
 extern const struct value_string e1_driver_names[];
@@ -97,6 +98,10 @@
 void
 e1_intf_destroy(struct e1_intf *intf);
 
+
+struct e1_line *
+e1_intf_find_line(struct e1_intf *intf, uint8_t id);
+
 struct e1_line *
 e1_line_new(struct e1_intf *intf, void *drv_data);
 
@@ -115,3 +120,5 @@
 void
 e1d_vty_init(struct e1_daemon *e1d);
 
+int
+e1d_vpair_create(struct e1_daemon *e1d, unsigned int num_lines);
diff --git a/src/intf_line.c b/src/intf_line.c
index afe477d..ce30b4f 100644
--- a/src/intf_line.c
+++ b/src/intf_line.c
@@ -36,6 +36,7 @@
 
 const struct value_string e1_driver_names[] = {
 	{ E1_DRIVER_USB, "usb" },
+	{ E1_DRIVER_VPAIR, "vpair" },
 	{ 0, NULL }
 };
 
diff --git a/src/vpair.c b/src/vpair.c
new file mode 100644
index 0000000..12452fe
--- /dev/null
+++ b/src/vpair.c
@@ -0,0 +1,196 @@
+/* Virtual E1 interface pair: Two virtual interfaces with N lines each,
+ * where data written to A can be read from B and vice-versa.
+ *
+ * (C) 2020 by Harald Welte <laforge at osmocom.org>
+ *
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * 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 <osmocom/core/utils.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/logging.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include "e1d.h"
+#include "log.h"
+
+/* number of bits in each frame */
+#define BITS_PER_FRAME		(32*8)
+/* overall bit-rate of E1 line in bits per second */
+#define BITRATE			2048000
+/* number of frames per second (8000) */
+#define FRAME_RATE		(BITRATE / BITS_PER_FRAME)
+/* duration of one frame in nanoseconds (125000) */
+#define FRAME_DURATION_NS	(1000000000UL / FRAME_RATE)
+
+/* number of E1 frames (32bytes) to handle for each timer interval */
+#define FRAMES_PER_TIMER	10
+
+struct ve1_intf_data {
+	/* pointer to other side of the interface pair */
+	struct e1_intf *peer;
+	struct osmo_fd timerfd;
+};
+
+struct ve1_line_data {
+	/* pointer to other side of the interface pair */
+	struct e1_line *peer;
+};
+
+static struct e1_intf *
+vintf_create(struct e1_daemon *e1d, unsigned int num_lines)
+{
+	struct e1_intf *intf;
+	struct ve1_intf_data *intf_data;
+	unsigned int i;
+
+	intf_data = talloc_zero(e1d->ctx, struct ve1_intf_data);
+
+	intf = e1_intf_new(e1d, intf_data);
+	intf->drv = E1_DRIVER_VPAIR;
+
+	for (i = 0; i < num_lines; i++) {
+		struct ve1_line_data *line_data;
+
+		line_data = talloc_zero(e1d->ctx, struct ve1_line_data);
+		e1_line_new(intf, line_data);
+	}
+
+	return intf;
+}
+
+static void
+vintf_destroy(struct e1_intf *intf)
+{
+	OSMO_ASSERT(intf->drv == E1_DRIVER_VPAIR);
+	e1_intf_destroy(intf);
+	talloc_free(intf->drv_data);
+}
+
+static int
+ve1_timerfd_cb(struct osmo_fd *ofd, unsigned int what)
+{
+	struct e1_intf *intf = ofd->data;
+	struct e1_line *line, *peer;
+	uint64_t expire_count;
+	unsigned int frames_expired;
+	int rc;
+
+	if (!(what & OSMO_FD_READ))
+		return 0;
+
+	rc = read(ofd->fd, (void *) &expire_count, sizeof(expire_count));
+	if (rc < 0 && errno == EAGAIN)
+		return 0;
+	OSMO_ASSERT(rc == sizeof(expire_count));
+
+	if (expire_count > 1) {
+		LOGP(DE1D, LOGL_NOTICE, "vpair timer expire_count=%" PRIu64
+			": We missed %" PRIu64 " timers\n", expire_count, expire_count-1);
+	}
+
+	OSMO_ASSERT(expire_count < UINT_MAX/FRAMES_PER_TIMER);
+	frames_expired = expire_count * FRAMES_PER_TIMER;
+
+	llist_for_each_entry(line, &intf->lines, list) {
+		uint8_t buf[32*frames_expired];
+		struct ve1_line_data *ldata = line->drv_data;
+
+		peer = ldata->peer;
+
+		/* generate data on current line */
+		rc = e1_line_mux_out(line, buf, frames_expired);
+		OSMO_ASSERT(rc >= 0);
+		/* write data to peer */
+		rc = e1_line_demux_in(peer, buf, rc);
+		OSMO_ASSERT(rc >= 0);
+
+		/* generate data on peer line */
+		rc = e1_line_mux_out(peer, buf, frames_expired);
+		OSMO_ASSERT(rc >= 0);
+		/* write data to current line */
+		rc = e1_line_demux_in(line, buf, rc);
+		OSMO_ASSERT(rc >= 0);
+	}
+
+	return 0;
+}
+
+int
+e1d_vpair_create(struct e1_daemon *e1d, unsigned int num_lines)
+{
+	struct e1_intf *a, *b;
+	struct e1_line *al, *bl;
+	struct ve1_intf_data *adata, *bdata;
+	int rc = -1;
+
+	/* create both interfaces, each with identical line count */
+	a = vintf_create(e1d, num_lines);
+	if (!a)
+		goto err;
+	adata = a->drv_data;
+
+	b = vintf_create(e1d, num_lines);
+	if (!b)
+		goto err_free_a;
+	bdata = b->drv_data;
+
+	/* point the interfaces at each other */
+	adata->peer = b;
+	bdata->peer = a;
+
+	/* point the lines at each other */
+	llist_for_each_entry(al, &a->lines, list) {
+		struct ve1_line_data *aldata, *bldata;
+		bl = e1_intf_find_line(b, al->id);
+		OSMO_ASSERT(bl);
+		aldata = al->drv_data;
+		bldata = bl->drv_data;
+
+		aldata->peer = bl;
+		bldata->peer = al;
+	}
+
+	/* schedule timer only for 'a' side; handles both directions */
+	struct timespec interval = {
+		.tv_sec = 0,
+		.tv_nsec = FRAME_DURATION_NS*FRAMES_PER_TIMER,
+	};
+	adata->timerfd.fd = -1;
+	rc = osmo_timerfd_setup(&adata->timerfd, ve1_timerfd_cb, a);
+	if (rc < 0)
+		goto err_free_b;
+	rc = osmo_timerfd_schedule(&adata->timerfd, NULL, &interval);
+	if (rc < 0)
+		goto err_free_b;
+
+	return 0;
+
+err_free_b:
+	vintf_destroy(b);
+err_free_a:
+	vintf_destroy(a);
+err:
+	return rc;
+}
diff --git a/src/vty.c b/src/vty.c
index 88b6257..57a21bf 100644
--- a/src/vty.c
+++ b/src/vty.c
@@ -3,16 +3,16 @@
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
+ * 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 Affero General Public License for more details.
+ * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU Affero General Public License
+ * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
@@ -131,9 +131,27 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_vpair, cfg_vpair_cmd, "virtual-e1-pair <1-255>",
+	"Create a virtual E1 interface pair\n"
+	"Number of E1 lines in virtual E1 interface pair\n")
+{
+	int num_lines = atoi(argv[0]);
+	int rc;
+
+	rc = e1d_vpair_create(vty_e1d, num_lines);
+	if (rc < 0) {
+		vty_out(vty, "%% Error creating virtual-e1-pair: %d%s", rc, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	return CMD_SUCCESS;
+}
+
 void e1d_vty_init(struct e1_daemon *e1d)
 {
 	vty_e1d = e1d;
 	install_element_ve(&show_intf_cmd);
 	install_element_ve(&show_line_cmd);
+
+	install_element(CONFIG_NODE, &cfg_vpair_cmd);
 }

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

Gerrit-Project: osmo-e1d
Gerrit-Branch: master
Gerrit-Change-Id: If42c959556b17d543762546eb45dd69d25f715f2
Gerrit-Change-Number: 19047
Gerrit-PatchSet: 5
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-Assignee: tnt <tnt at 246tNt.com>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: tnt <tnt at 246tNt.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200630/4f7c3fb0/attachment.htm>


More information about the gerrit-log mailing list