diff options
author | Philipp Maier <pmaier@sysmocom.de> | 2023-02-14 13:54:24 +0100 |
---|---|---|
committer | Philipp Maier <pmaier@sysmocom.de> | 2023-02-21 11:00:54 +0100 |
commit | 896cb2207a017f411a0375e6a7508fcb195dcdb0 (patch) | |
tree | ecfde8ef2d5075286fdda30b64220c73581a4e4b | |
parent | 3dacef93ca00e3880285c8b4006cbffe5a563530 (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.c | 62 |
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; |