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.orglaforge 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>