[PATCH] libosmo-abis[master]: Add HDLC timeslot mode

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:44 UTC 2016


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

Add HDLC timeslot mode

This is useful for protocols that use HDLC framing for signalling on E1
timeslots, but which don't use LAPD inside (our E1INP_TS_TYPE_SIGN).

Examples are particularly a MTP2/MTP3 SS7 stack, like it is used on the
A interfaces or on the core network interfaces of classic
circuit-switched networks.

Change-Id: I2d75801df4d7cbb8dad325f4d6689841f0196fa6
---
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, 110 insertions(+), 2 deletions(-)


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

diff --git a/include/osmocom/abis/e1_input.h b/include/osmocom/abis/e1_input.h
index 7568f19..c99b133 100644
--- a/include/osmocom/abis/e1_input.h
+++ b/include/osmocom/abis/e1_input.h
@@ -65,9 +65,10 @@
 	E1INP_TS_TYPE_SIGN,
 	E1INP_TS_TYPE_TRAU,
 	E1INP_TS_TYPE_RAW,
+	E1INP_TS_TYPE_HDLC,
 };
 const char *e1inp_tstype_name(enum e1inp_ts_type tp);
-const struct value_string e1inp_ts_type_names[5];
+const struct value_string e1inp_ts_type_names[6];
 
 /* A timeslot in the E1 interface */
 struct e1inp_ts {
@@ -101,6 +102,12 @@
 			/* queue of pending to-be-transmitted msgbs */
 			struct llist_head tx_queue;
 		} raw;
+		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;
+		} hdlc;
 	};
 	union {
 		struct {
@@ -252,6 +259,11 @@
 			void (*raw_recv_cb)(struct e1inp_ts *ts,
 					    struct msgb *msg));
 
+/* configure and initialize one timeslot dedicated to HDLC frames */
+int e1inp_ts_config_hdlc(struct e1inp_ts *ts, struct e1inp_line *line,
+			 void (*hdlc_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 75ae36e..970bdb9 100644
--- a/src/e1_input.c
+++ b/src/e1_input.c
@@ -213,11 +213,12 @@
 	return get_value_string(e1inp_sign_type_names, tp);
 }
 
-const struct value_string e1inp_ts_type_names[5] = {
+const struct value_string e1inp_ts_type_names[6] = {
 	{ E1INP_TS_TYPE_NONE,	"None" },
 	{ E1INP_TS_TYPE_SIGN,	"Signalling" },
 	{ E1INP_TS_TYPE_TRAU,	"TRAU" },
 	{ E1INP_TS_TYPE_RAW,	"RAW" },
+	{ E1INP_TS_TYPE_HDLC,	"HDLC" },
 	{ 0, NULL }
 };
 
@@ -311,6 +312,21 @@
 	ts->line = line;
 	ts->raw.recv_cb = raw_recv_cb;
 	INIT_LLIST_HEAD(&ts->raw.tx_queue);
+
+	return 0;
+}
+
+int e1inp_ts_config_hdlc(struct e1inp_ts *ts, struct e1inp_line *line,
+			 void (*hdlc_recv_cb)(struct e1inp_ts *ts,
+					      struct msgb *msg))
+{
+	if (ts->type == E1INP_TS_TYPE_HDLC && ts->line && line)
+		return 0;
+
+	ts->type = E1INP_TS_TYPE_HDLC;
+	ts->line = line;
+	ts->hdlc.recv_cb = hdlc_recv_cb;
+	INIT_LLIST_HEAD(&ts->hdlc.tx_queue);
 
 	return 0;
 }
@@ -550,6 +566,9 @@
 	case E1INP_TS_TYPE_RAW:
 		ts->raw.recv_cb(ts, msg);
 		break;
+	case E1INP_TS_TYPE_HDLC:
+		ts->hdlc.recv_cb(ts, msg);
+		break;
 	default:
 		ret = -EINVAL;
 		LOGP(DLMI, LOGL_ERROR, "unknown TS type %u\n", ts->type);
@@ -677,6 +696,10 @@
 		/* Get msgb from tx_queue */
 		msg = msgb_dequeue(&e1i_ts->raw.tx_queue);
 		break;
+	case E1INP_TS_TYPE_HDLC:
+		/* Get msgb from tx_queue */
+		msg = msgb_dequeue(&e1i_ts->hdlc.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 db00f5f..0945daa 100644
--- a/src/input/dahdi.c
+++ b/src/input/dahdi.c
@@ -259,6 +259,51 @@
 	return 0;
 }
 
+static void handle_hdlc_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;
+
+	ret = write(bfd->fd, msg->data, msg->len + 2);
+	msgb_free(msg);
+	if (ret == -1)
+		handle_dahdi_exception(e1i_ts);
+	else if (ret < 0)
+		LOGP(DLMI, LOGL_NOTICE, "%s write failed %d\n", __func__, ret);
+}
+
+static int handle_hdlc_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(TS1_ALLOC_SIZE, "DAHDI HDLC Rx");
+	int ret;
+
+	if (!msg)
+		return -ENOMEM;
+
+	ret = read(bfd->fd, msg->data, TS1_ALLOC_SIZE - 16);
+	if (ret == -1)
+		handle_dahdi_exception(e1i_ts);
+	else if (ret < 0) {
+		perror("read ");
+	}
+	msgb_put(msg, ret - 2);
+	if (ret <= 3) {
+		perror("read ");
+	}
+
+	return e1inp_rx_ts(e1i_ts, msg, 0, 0);
+}
 
 static int invertbits = 1;
 
@@ -451,6 +496,14 @@
 		if (what & BSC_FD_WRITE)
 			rc = handle_ts1_write(bfd);
 		break;
+	case E1INP_TS_TYPE_HDLC:
+		if (what & BSC_FD_EXCEPT)
+			handle_dahdi_exception(e1i_ts);
+		if (what & BSC_FD_READ)
+			rc = handle_hdlc_read(bfd);
+		if (what & BSC_FD_WRITE)
+			handle_hdlc_write(bfd);
+		break;
 	case E1INP_TS_TYPE_TRAU:
 		if (what & BSC_FD_EXCEPT)
 			handle_dahdi_exception(e1i_ts);
@@ -620,6 +673,20 @@
 					dahdi_write_msg, bfd, e1inp_dlsap_up,
 					e1i_ts, &lapd_profile_abis);
 			break;
+		case E1INP_TS_TYPE_HDLC:
+			if (!bfd->fd)
+				bfd->fd = open(openstr, O_RDWR | O_NONBLOCK);
+			if (bfd->fd == -1) {
+				LOGP(DLINP, LOGL_ERROR,
+					"%s could not open %s %s\n",
+					__func__, openstr, strerror(errno));
+				return -EIO;
+			}
+			bfd->when = BSC_FD_READ | BSC_FD_EXCEPT;
+			ret = dahdi_set_bufinfo(bfd->fd, 1);
+			if (ret < 0)
+				return ret;
+			break;
 		case E1INP_TS_TYPE_TRAU:
 		case E1INP_TS_TYPE_RAW:
 			/* close/release LAPD instance, if any */
diff --git a/src/input/misdn.c b/src/input/misdn.c
index 391cd18..f72b496 100644
--- a/src/input/misdn.c
+++ b/src/input/misdn.c
@@ -607,6 +607,11 @@
 		case E1INP_TS_TYPE_NONE:
 			continue;
 			break;
+		case E1INP_TS_TYPE_HDLC:
+			bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
+				ISDN_P_B_HDLC);
+			bfd->when = BSC_FD_READ;
+			break;
 		case E1INP_TS_TYPE_SIGN:
 			if (mline->use_userspace_lapd)
 				bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
@@ -650,6 +655,7 @@
 				addr.tei = GROUP_TEI;
 			}
 			break;
+		case E1INP_TS_TYPE_HDLC:
 		case E1INP_TS_TYPE_TRAU:
 			addr.channel = ts;
 			break;

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I2d75801df4d7cbb8dad325f4d6689841f0196fa6
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