aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2023-02-14 13:54:24 +0100
committerPhilipp Maier <pmaier@sysmocom.de>2023-02-21 11:00:54 +0100
commit896cb2207a017f411a0375e6a7508fcb195dcdb0 (patch)
treeecfde8ef2d5075286fdda30b64220c73581a4e4b
parent3dacef93ca00e3880285c8b4006cbffe5a563530 (diff)
e1_input: cleanup TS resources when timeslot type is changed
There may be situations where we want to change the timeslot type by calling a different e1inp_ts_config_xyz function at some later point. In those cases we must ensure that no dynamically allocated resources remain in the type dependend union of struct e1inp_ts. Depends: libosmocore.git I0454ffe5809f21504c1e263a781c06596d452d4b Related: OS#5198 Change-Id: Icf84816460b8ceba43601594bcf504306606f4ed
-rw-r--r--src/e1_input.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/e1_input.c b/src/e1_input.c
index be98138..e3ac67e 100644
--- a/src/e1_input.c
+++ b/src/e1_input.c
@@ -361,6 +361,56 @@ int e1inp_ts_send_hdlc(struct e1inp_ts *ts, struct msgb *msg)
return 0;
}
+/* Depending on its typ a timeslot may hold resources which must be cleaned up
+ * or reset before the type of the timeslot type may be changed. */
+static int cleanup_e1inp_ts(struct e1inp_ts *e1i_ts)
+{
+ int rc;
+
+ switch (e1i_ts->type) {
+ case E1INP_TS_TYPE_SIGN:
+ /* The caller is responsible for removing all signalling links
+ * first. */
+ if (!llist_empty(&e1i_ts->sign.sign_links)) {
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR,
+ "timeslot still holds active signalling links -- cannot modify timeslot!\n");
+ return -EINVAL;
+ }
+ return 0;
+ case E1INP_TS_TYPE_TRAU:
+ /* Call the initialization functions once more. This will
+ * deactivate all subchannels so that the related callbacks
+ * are no longer called */
+ subchan_mux_init(&e1i_ts->trau.mux);
+ subch_demux_init(&e1i_ts->trau.demux);
+ return 0;
+ case E1INP_TS_TYPE_RAW:
+ msgb_queue_free(&e1i_ts->raw.tx_queue);
+ return 0;
+ case E1INP_TS_TYPE_HDLC:
+ msgb_queue_free(&e1i_ts->hdlc.tx_queue);
+ return 0;
+ case E1INP_TS_TYPE_I460:
+ /* The caller is responsible for removing all I.460 subchannels
+ * first. */
+ rc = osmo_i460_subchan_count(&e1i_ts->i460.i460_ts);
+ if (rc != 0) {
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR,
+ "timeslot still holds active I.460 subchannels -- cannot modify timeslot!\n");
+ return -EINVAL;
+ }
+ return 0;
+ case E1INP_TS_TYPE_NONE:
+ return 0;
+ default:
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "unsupported E1 TS type %u\n",
+ e1i_ts->type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/* Timeslot */
int e1inp_ts_config_trau(struct e1inp_ts *ts, struct e1inp_line *line,
int (*trau_rcv_cb)(struct subch_demux *dmx, int ch,
@@ -369,6 +419,8 @@ int e1inp_ts_config_trau(struct e1inp_ts *ts, struct e1inp_line *line,
if (ts->type == E1INP_TS_TYPE_TRAU && ts->line && line)
return 0;
+ cleanup_e1inp_ts(ts);
+
ts->type = E1INP_TS_TYPE_TRAU;
ts->line = line;
@@ -384,6 +436,8 @@ int e1inp_ts_config_i460(struct e1inp_ts *ts, struct e1inp_line *line)
if (ts->type == E1INP_TS_TYPE_I460 && ts->line && line)
return 0;
+ cleanup_e1inp_ts(ts);
+
ts->type = E1INP_TS_TYPE_I460;
ts->line = line;
osmo_i460_ts_init(&ts->i460.i460_ts);
@@ -403,6 +457,8 @@ int e1inp_ts_config_sign(struct e1inp_ts *ts, struct e1inp_line *line)
if (ts->type == E1INP_TS_TYPE_SIGN && ts->line && line)
return 0;
+ cleanup_e1inp_ts(ts);
+
ts->type = E1INP_TS_TYPE_SIGN;
ts->line = line;
@@ -421,6 +477,8 @@ int e1inp_ts_config_raw(struct e1inp_ts *ts, struct e1inp_line *line,
if (ts->type == E1INP_TS_TYPE_RAW && ts->line && line)
return 0;
+ cleanup_e1inp_ts(ts);
+
ts->type = E1INP_TS_TYPE_RAW;
ts->line = line;
ts->raw.recv_cb = raw_recv_cb;
@@ -436,6 +494,8 @@ int e1inp_ts_config_hdlc(struct e1inp_ts *ts, struct e1inp_line *line,
if (ts->type == E1INP_TS_TYPE_HDLC && ts->line && line)
return 0;
+ cleanup_e1inp_ts(ts);
+
ts->type = E1INP_TS_TYPE_HDLC;
ts->line = line;
ts->hdlc.recv_cb = hdlc_recv_cb;
@@ -449,6 +509,8 @@ int e1inp_ts_config_none(struct e1inp_ts *ts, struct e1inp_line *line)
if (ts->type == E1INP_TS_TYPE_NONE && ts->line && line)
return 0;
+ cleanup_e1inp_ts(ts);
+
ts->type = E1INP_TS_TYPE_NONE;
ts->line = line;