[PATCH] libosmo-abis[master]: Implement new 'raw' input type for E1 timeslots

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

Harald Welte gerrit-no-reply at lists.osmocom.org
Mon Oct 17 20:16:43 UTC 2016


Review at  https://gerrit.osmocom.org/1101

Implement new 'raw' input type for E1 timeslots

In the past, the A-bis E1 input system only unederstood LAPD signalling
time-slots and trau-slots with 16kBps sub-slots.  This adds the notion
of a 'raw' transparent 64kBps slot, without any furthe de-multiplexing
nor any HLDC inside.

Change-Id: I0c25c2688eddd0c55c15b280a8c6e8a49629516b
---
M include/osmocom/abis/e1_input.h
M src/e1_input.c
M src/input/dahdi.c
M src/input/misdn.c
4 files changed, 214 insertions(+), 3 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/01/1101/1

diff --git a/include/osmocom/abis/e1_input.h b/include/osmocom/abis/e1_input.h
index 8ef33d5..7568f19 100644
--- a/include/osmocom/abis/e1_input.h
+++ b/include/osmocom/abis/e1_input.h
@@ -64,6 +64,7 @@
 	E1INP_TS_TYPE_NONE,
 	E1INP_TS_TYPE_SIGN,
 	E1INP_TS_TYPE_TRAU,
+	E1INP_TS_TYPE_RAW,
 };
 const char *e1inp_tstype_name(enum e1inp_ts_type tp);
 const struct value_string e1inp_ts_type_names[5];
@@ -94,6 +95,12 @@
 			/* subchannel muxer for frames to E1 */
 			struct subch_mux mux;
 		} trau;
+		struct {
+			/* call-back for every received frame */
+			void (*recv_cb)(struct e1inp_ts *ts, struct msgb *msg);
+			/* queue of pending to-be-transmitted msgbs */
+			struct llist_head tx_queue;
+		} raw;
 	};
 	union {
 		struct {
@@ -203,9 +210,6 @@
 /* fine a previously registered driver */
 struct e1inp_driver *e1inp_driver_find(const char *name);
 
-/* register a line with the E1 core */
-int e1inp_line_register(struct e1inp_line *line);
-
 /* get a line by its ID */
 struct e1inp_line *e1inp_line_find(uint8_t e1_nr);
 
@@ -243,6 +247,11 @@
                          int (*trau_rcv_cb)(struct subch_demux *dmx, int ch,
 					uint8_t *data, int len, void *_priv));
 
+/* configure and initialize one timeslot dedicated to RAW frames */
+int e1inp_ts_config_raw(struct e1inp_ts *ts, struct e1inp_line *line,
+			void (*raw_recv_cb)(struct e1inp_ts *ts,
+					    struct msgb *msg));
+
 /* Receive a packet from the E1 driver */
 int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
 		uint8_t tei, uint8_t sapi);
diff --git a/src/e1_input.c b/src/e1_input.c
index df990d5..75ae36e 100644
--- a/src/e1_input.c
+++ b/src/e1_input.c
@@ -217,6 +217,7 @@
 	{ E1INP_TS_TYPE_NONE,	"None" },
 	{ E1INP_TS_TYPE_SIGN,	"Signalling" },
 	{ E1INP_TS_TYPE_TRAU,	"TRAU" },
+	{ E1INP_TS_TYPE_RAW,	"RAW" },
 	{ 0, NULL }
 };
 
@@ -296,6 +297,21 @@
 	else
 		ts->sign.delay = 100000;
 	INIT_LLIST_HEAD(&ts->sign.sign_links);
+	return 0;
+}
+
+int e1inp_ts_config_raw(struct e1inp_ts *ts, struct e1inp_line *line,
+			void (*raw_recv_cb)(struct e1inp_ts *ts,
+					    struct msgb *msg))
+{
+	if (ts->type == E1INP_TS_TYPE_RAW && ts->line && line)
+		return 0;
+
+	ts->type = E1INP_TS_TYPE_RAW;
+	ts->line = line;
+	ts->raw.recv_cb = raw_recv_cb;
+	INIT_LLIST_HEAD(&ts->raw.tx_queue);
+
 	return 0;
 }
 
@@ -531,6 +547,9 @@
 		ret = subch_demux_in(&ts->trau.demux, msg->l2h, msgb_l2len(msg));
 		msgb_free(msg);
 		break;
+	case E1INP_TS_TYPE_RAW:
+		ts->raw.recv_cb(ts, msg);
+		break;
 	default:
 		ret = -EINVAL;
 		LOGP(DLMI, LOGL_ERROR, "unknown TS type %u\n", ts->type);
@@ -654,6 +673,10 @@
 		}
 		msgb_put(msg, 40);
 		break;
+	case E1INP_TS_TYPE_RAW:
+		/* Get msgb from tx_queue */
+		msg = msgb_dequeue(&e1i_ts->raw.tx_queue);
+		break;
 	default:
 		LOGP(DLMI, LOGL_ERROR, "unsupported E1 TS type %u\n", e1i_ts->type);
 		return NULL;
diff --git a/src/input/dahdi.c b/src/input/dahdi.c
index ab06908..db00f5f 100644
--- a/src/input/dahdi.c
+++ b/src/input/dahdi.c
@@ -360,6 +360,79 @@
 	return ret;
 }
 
+/* write to a raw channel TS */
+static int handle_ts_raw_write(struct osmo_fd *bfd)
+{
+	struct e1inp_line *line = bfd->data;
+	unsigned int ts_nr = bfd->priv_nr;
+	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+	struct msgb *msg;
+	int ret;
+
+	/* get the next msg for this timeslot */
+	msg = e1inp_tx_ts(e1i_ts, NULL);
+	if (!msg)
+		return 0;
+
+	if (msg->len != D_BCHAN_TX_GRAN) {
+		/* This might lead to a transmit underrun, as we call tx
+		 * from the rx path, as there's no select/poll on dahdi
+		 * */
+		LOGP(DLINP, LOGL_NOTICE, "unexpected msg->len = %u, "
+		     "expected %u\n", msg->len, D_BCHAN_TX_GRAN);
+	}
+
+	DEBUGP(DLMIB, "RAW CHAN TX: %s\n",
+		osmo_hexdump(msg->data, msg->len));
+
+	if (0/*invertbits*/) {
+		flip_buf_bits(msg->data, msg->len);
+	}
+
+	ret = write(bfd->fd, msg->data, msg->len);
+	if (ret < msg->len)
+		LOGP(DLINP, LOGL_DEBUG, "send returns %d instead of %d\n",
+			ret, msg->len);
+	msgb_free(msg);
+
+	return ret;
+}
+
+static int handle_ts_raw_read(struct osmo_fd *bfd)
+{
+	struct e1inp_line *line = bfd->data;
+	unsigned int ts_nr = bfd->priv_nr;
+	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+	struct msgb *msg = msgb_alloc(D_TSX_ALLOC_SIZE, "DAHDI Raw TS");
+	int ret;
+
+	if (!msg)
+		return -ENOMEM;
+
+	ret = read(bfd->fd, msg->data, D_TSX_ALLOC_SIZE);
+	if (ret < 0 || ret != D_TSX_ALLOC_SIZE) {
+		LOGP(DLINP, LOGL_DEBUG, "read error  %d %s\n",
+			ret, strerror(errno));
+		return ret;
+	}
+
+	if (0/*invertbits*/) {
+		flip_buf_bits(msg->data, ret);
+	}
+
+	msgb_put(msg, ret);
+
+	msg->l2h = msg->data;
+	DEBUGP(DLMIB, "RAW CHAN RX: %s\n",
+		osmo_hexdump(msgb_l2(msg), ret));
+	ret = e1inp_rx_ts(e1i_ts, msg, 0, 0);
+	/* physical layer indicates that data has been sent,
+	 * we thus can send some more data */
+	ret = handle_ts_raw_write(bfd);
+
+	return ret;
+}
+
 /* callback from select.c in case one of the fd's can be read/written */
 static int dahdi_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
@@ -385,6 +458,17 @@
 			rc = handle_tsX_read(bfd);
 		if (what & BSC_FD_WRITE)
 			rc = handle_tsX_write(bfd);
+		/* We never include the DAHDI B-Channel FD into the
+		 * writeset, since it doesn't support poll() based
+		 * write flow control */
+		break;
+	case E1INP_TS_TYPE_RAW:
+		if (what & BSC_FD_EXCEPT)
+			handle_dahdi_exception(e1i_ts);
+		if (what & BSC_FD_READ)
+			rc = handle_ts_raw_read(bfd);
+		if (what & BSC_FD_WRITE)
+			rc = handle_ts_raw_write(bfd);
 		/* We never include the DAHDI B-Channel FD into the
 		 * writeset, since it doesn't support poll() based
 		 * write flow control */
@@ -537,6 +621,7 @@
 					e1i_ts, &lapd_profile_abis);
 			break;
 		case E1INP_TS_TYPE_TRAU:
+		case E1INP_TS_TYPE_RAW:
 			/* close/release LAPD instance, if any */
 			if (e1i_ts->lapd) {
 				lapd_instance_free(e1i_ts->lapd);
diff --git a/src/input/misdn.c b/src/input/misdn.c
index 330e3b3..391cd18 100644
--- a/src/input/misdn.c
+++ b/src/input/misdn.c
@@ -391,6 +391,92 @@
 	return ret;
 }
 
+/* write to a raw channel TS */
+static int handle_ts_raw_write(struct osmo_fd *bfd, unsigned int len)
+{
+	struct e1inp_line *line = bfd->data;
+	unsigned int ts_nr = bfd->priv_nr;
+	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+	struct msgb *msg;
+	struct mISDNhead *hh;
+	int ret;
+
+	/* get the next msg for this timeslot */
+	msg = e1inp_tx_ts(e1i_ts, NULL);
+	if (!msg)
+		return 0;
+
+	if (msg->len != len) {
+		/* This might lead to a transmit underrun, as we call tx
+		 * from the rx path, as there's no select/poll on dahdi
+		 * */
+		LOGP(DLINP, LOGL_NOTICE, "unexpected msg->len = %u, "
+		     "expected %u\n", msg->len, len);
+	}
+
+	DEBUGP(DLMIB, "RAW CHAN TX: %s\n",
+		osmo_hexdump(msg->data, msg->len));
+
+	hh = (struct mISDNhead *) msgb_push(msg, sizeof(*hh));
+	hh->prim = PH_DATA_REQ;
+	hh->id = 0;
+
+	ret = write(bfd->fd, msg->data, msg->len);
+	if (ret < msg->len)
+		LOGP(DLINP, LOGL_DEBUG, "send returns %d instead of %d\n",
+			ret, msg->len);
+	msgb_free(msg);
+
+	return ret;
+}
+
+static int handle_ts_raw_read(struct osmo_fd *bfd)
+{
+	struct e1inp_line *line = bfd->data;
+	unsigned int ts_nr = bfd->priv_nr;
+	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+	struct msgb *msg = msgb_alloc(TSX_ALLOC_SIZE, "mISDN Tx RAW");
+	struct mISDNhead *hh;
+	int ret;
+
+	if (!msg)
+		return -ENOMEM;
+
+	hh = (struct mISDNhead *) msg->data;
+
+	ret = recv(bfd->fd, msg->data, TSX_ALLOC_SIZE, 0);
+	if (ret < 0) {
+		fprintf(stderr, "recvfrom error  %s\n", strerror(errno));
+		return ret;
+	}
+
+	msgb_put(msg, ret);
+
+	if (hh->prim != PH_CONTROL_IND)
+		DEBUGP(DLMIB, "<= RAW CHAN len = %d, prim(0x%x) id(0x%x): %s\n",
+			ret, hh->prim, hh->id,
+			get_value_string(prim_names, hh->prim));
+
+	switch (hh->prim) {
+	case PH_DATA_IND:
+		msg->l2h = msg->data + MISDN_HEADER_LEN;
+		DEBUGP(DLMIB, "RAW CHAN RX: %s\n",
+			osmo_hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
+		/* the number of bytes received indicates that data to send */
+		handle_ts_raw_write(bfd, msgb_l2len(msg));
+		return e1inp_rx_ts(e1i_ts, msg, 0, 0);
+	case PH_ACTIVATE_IND:
+	case PH_DATA_CNF:
+		break;
+	default:
+		break;
+	}
+	/* FIXME: why do we free signalling msgs in the caller, and trau not? */
+	msgb_free(msg);
+
+	return ret;
+}
+
 /* callback from select.c in case one of the fd's can be read/written */
 static int misdn_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
@@ -413,6 +499,13 @@
 		/* We never include the mISDN B-Channel FD into the
 		 * writeset, since it doesn't support poll() based
 		 * write flow control */		
+		break;
+	case E1INP_TS_TYPE_RAW:
+		if (what & BSC_FD_READ)
+			rc = handle_ts_raw_read(bfd);
+		/* We never include the mISDN B-Channel FD into the
+		 * writeset, since it doesn't support poll() based
+		 * write flow control */
 		break;
 	default:
 		fprintf(stderr, "unknown E1 TS type %u\n", e1i_ts->type);
@@ -524,6 +617,7 @@
 			bfd->when = BSC_FD_READ;
 			break;
 		case E1INP_TS_TYPE_TRAU:
+		case E1INP_TS_TYPE_RAW:
 			bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
 			/* We never include the mISDN B-Channel FD into the
 	 		* writeset, since it doesn't support poll() based

-- 
To view, visit https://gerrit.osmocom.org/1101
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0c25c2688eddd0c55c15b280a8c6e8a49629516b
Gerrit-PatchSet: 1
Gerrit-Project: libosmo-abis
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>



More information about the gerrit-log mailing list