From ebfab5792dadfda3089bcf9f673f0a34725aafff Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 12 Feb 2023 15:19:08 +0100 Subject: [PATCH] Dynamically open and close b-channels depending on the usage --- src/layer1.c | 52 +++++++++++++++++++++++++++++++++++++---- src/layer1.h | 2 ++ src/v5le_vty.c | 8 +++---- src/v5x_data.c | 4 ++-- src/v5x_internal.h | 2 +- src/v5x_le_management.c | 25 ++++++++++---------- 6 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/layer1.c b/src/layer1.c index 921d1ba..050691f 100644 --- a/src/layer1.c +++ b/src/layer1.c @@ -261,11 +261,11 @@ static void raw_rx_cb(struct e1inp_ts *ts, struct msgb *msg) osmo_revbytebits_buf(msg->data, msg->len); /* if assigned and active, send B-channel data to socket interface */ - if (v5up->ts[0] && v5up->ts[0]->nr == ts->num && v5up->ts_activated[0]) { + if (v5up->ts[0] && v5up->ts[0]->nr == ts->num && v5up->ts[0]->b_activated) { echo_rx(&v5up->ep[0], msg->data, msg->len); ph_socket_tx_msg(&v5up->ph_socket, 1, PH_PRIM_DATA_IND, msg->data, msg->len); } - if (v5up->ts[1] && v5up->ts[1]->nr == ts->num && v5up->ts_activated[1]) { + if (v5up->ts[1] && v5up->ts[1]->nr == ts->num && v5up->ts[1]->b_activated) { echo_rx(&v5up->ep[1], msg->data, msg->len); ph_socket_tx_msg(&v5up->ph_socket, 2, PH_PRIM_DATA_IND, msg->data, msg->len); } @@ -355,6 +355,50 @@ int ph_data_req_dl_prot(struct msgb *msg, void *cbdata) return e1inp_ts_send_hdlc(ts, msg); } +int ph_activate_req(struct v5x_timeslot *ts) +{ + struct e1inp_line *e1_line; + struct e1inp_ts *e1_ts; + int rc; + + if (ts->b_activated) + return 0; + + e1_line = e1_line_from_link(ts->link); + if (!e1_line) + return -EINVAL; + e1_ts = &e1_line->ts[ts->nr - 1]; + + e1inp_ts_config_raw(e1_ts, e1_line, raw_rx_cb); + rc = e1inp_line_update(e1_line); + + ts->b_activated = 1; + + return rc; +} + +int ph_deactivate_req(struct v5x_timeslot *ts) +{ + struct e1inp_line *e1_line; + struct e1inp_ts *e1_ts; + int rc; + + if (!ts->b_activated) + return 0; + + e1_line = e1_line_from_link(ts->link); + if (!e1_line) + return -EINVAL; + e1_ts = &e1_line->ts[ts->nr - 1]; + + e1_ts->type = E1INP_TS_TYPE_NONE; + rc = e1inp_line_update(e1_line); + + ts->b_activated = 0; + + return rc; +} + /* send raw (B-channel) data to E1 interface */ static int ph_data_req_raw(struct v5x_link *v5l, struct msgb *msg, int ts_nr) { @@ -414,7 +458,7 @@ void ph_socket_rx_cb(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, i struct msgb *msg = msgb_alloc_headroom(length + 32, 32, "V5 EF MSG"); memcpy(msgb_put(msg, length), data, length); lapv5ef_tx(v5up, msg); - } else if ((channel == 1 || channel == 2) && v5up->ts[channel - 1]) { + } else if ((channel == 1 || channel == 2) && v5up->ts[channel - 1] && v5up->ts[channel - 1]->b_activated) { echo_tx(&v5up->ep[channel - 1], data, length); struct msgb *msg = msgb_alloc_headroom(length + 32, 32, "B MSG"); memcpy(msgb_put(msg, length), data, length); @@ -471,7 +515,7 @@ int e1_init(void) //e1inp_sign_link_create(e1_ts, E1INP_SIGN_NONE, NULL, 115/*TEI*/, 0/*SAPI*/); e1inp_ts_config_hdlc(e1_ts, e1_line, hdlc_rx_cb); } else - e1inp_ts_config_raw(e1_ts, e1_line, raw_rx_cb); + e1_ts->type = E1INP_TS_TYPE_NONE; } e1inp_line_update(e1_line); diff --git a/src/layer1.h b/src/layer1.h index 8829c71..c7b6517 100644 --- a/src/layer1.h +++ b/src/layer1.h @@ -11,6 +11,8 @@ enum l1_signal_prim { }; int v5x_l1_signal_snd(struct v5x_link *v5l, enum l1_signal_prim prim); +int ph_activate_req(struct v5x_timeslot *ts); +int ph_deactivate_req(struct v5x_timeslot *ts); int ph_data_req_hdlc(struct msgb *msg, struct v5x_interface *v5if); int ph_data_req_dl_cc(struct msgb *msg, void *cbdata); int ph_data_req_dl_prot(struct msgb *msg, void *cbdata); diff --git a/src/v5le_vty.c b/src/v5le_vty.c index d2a9ad5..a92db5f 100644 --- a/src/v5le_vty.c +++ b/src/v5le_vty.c @@ -654,9 +654,9 @@ DEFUN(cfg_echo, cfg_echo_cmd, struct v5x_user_port *v5up = vty->index; v5up->echo_configured = 1; - if (v5up->ts_activated[0]) + if (v5up->ts[0] && v5up->ts[0]->b_activated) v5x_echo_reset(&v5up->ep[0], v5up->echo_configured); - if (v5up->ts_activated[1]) + if (v5up->ts[1] && v5up->ts[1]->b_activated) v5x_echo_reset(&v5up->ep[1], v5up->echo_configured); return CMD_SUCCESS; } @@ -668,9 +668,9 @@ DEFUN(cfg_no_echo, cfg_no_echo_cmd, struct v5x_user_port *v5up = vty->index; v5up->echo_configured = 0; - if (v5up->ts_activated[0]) + if (v5up->ts[0] && v5up->ts[0]->b_activated) v5x_echo_reset(&v5up->ep[0], v5up->echo_configured); - if (v5up->ts_activated[1]) + if (v5up->ts[1] && v5up->ts[1]->b_activated) v5x_echo_reset(&v5up->ep[1], v5up->echo_configured); return CMD_SUCCESS; } diff --git a/src/v5x_data.c b/src/v5x_data.c index 037cc49..4a973af 100644 --- a/src/v5x_data.c +++ b/src/v5x_data.c @@ -166,11 +166,11 @@ int v5x_link_destroy(struct v5x_link *v5l) if ((v5up = v5l->ts[i].v5up)) { if (v5up->ts[0] == &v5l->ts[i]) { v5up->ts[0] = NULL; - v5up->ts_activated[0] = 0; + ph_deactivate_req(&v5l->ts[i]); } if (v5up->ts[1] == &v5l->ts[i]) { v5up->ts[1] = NULL; - v5up->ts_activated[1] = 0; + ph_deactivate_req(&v5l->ts[i]); } } } diff --git a/src/v5x_internal.h b/src/v5x_internal.h index 5daa492..719fb14 100644 --- a/src/v5x_internal.h +++ b/src/v5x_internal.h @@ -172,6 +172,7 @@ struct v5x_timeslot { struct v5x_link *link; /* back-pointer */ struct v5x_user_port *v5up; /* user port that this TS is assigned to */ bool b_channel; /* channel can be used as b-channel */ + bool b_activated; /* activated (b-channel) at libosmo-abis */ }; /* one physical E1 interface used within a V5.2 interface */ @@ -281,7 +282,6 @@ struct v5x_user_port { struct v5x_ctrl_proto *ctrl; /* port control protocol instance */ struct osmo_fsm_inst *port_fi; /* port FSM */ struct v5x_timeslot *ts[2]; /* two time slots */ - uint8_t ts_activated[2]; /* set if data stream is active */ struct { } isdn; struct { diff --git a/src/v5x_le_management.c b/src/v5x_le_management.c index 08c8bbe..af6d032 100644 --- a/src/v5x_le_management.c +++ b/src/v5x_le_management.c @@ -38,6 +38,7 @@ #include "v52_le_bcc_fsm.h" #include "v52_le_pp_fsm.h" #include "v5x_le_management.h" +#include "layer1.h" #include "logging.h" void v5x_le_mgmt_init(void) @@ -438,11 +439,11 @@ static void flush_link(struct v5x_link *v5l) if ((v5up = v5l->ts[t].v5up)) { if (v5up->ts[0] == &v5l->ts[t]) { v5up->ts[0] = NULL; - v5up->ts_activated[0] = 0; + ph_deactivate_req(&v5l->ts[t]); } if (v5up->ts[1] == &v5l->ts[t]) { v5up->ts[1] = NULL; - v5up->ts_activated[1] = 0; + ph_deactivate_req(&v5l->ts[t]); } v5l->ts[t].v5up = NULL; } @@ -564,18 +565,18 @@ void v5x_le_channel_assign(struct v5x_user_port *v5up, int channel) "%d.\n", (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5l->id); return; } - if (v5up->ts_activated[channel - 1]) + if (v5up->ts[channel - 1]->b_activated) return; LOGP(DV5MGMT, LOGL_DEBUG, "Activating channel %d for %s port %d at TS %d of link %d.\n", channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, v5up->ts[channel - 1]->nr, v5up->ts[channel - 1]->link->id); - v5up->ts_activated[channel - 1] = 1; + ph_activate_req(v5up->ts[channel - 1]); return; } /* channel already assigned, just activate it, if not already */ if (v5up->ts[channel - 1]) { - v5up->ts_activated[channel - 1] = 1; + ph_activate_req(v5up->ts[channel - 1]); return; } @@ -620,27 +621,27 @@ void v5x_le_channel_unassign(struct v5x_user_port *v5up, int channel) /* the channels are pre-assigned with V5.1, so only activation state is set */ if (v5if->dialect == V5X_DIALECT_V51) { - if (!v5up->ts_activated[channel - 1]) - return; if (!v5up->ts[channel - 1]) { LOGP(DV5MGMT, LOGL_ERROR, "Cannot deactivate channel, because no TS is assigned for %s port " "%d.\n", (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr); return; } + if (!v5up->ts[channel - 1]->b_activated) + return; LOGP(DV5MGMT, LOGL_DEBUG, "Deactivating channel %d for %s port %d at TS %d of link %d.\n", channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, v5up->ts[channel - 1]->nr, v5up->ts[channel - 1]->link->id); - v5up->ts_activated[channel - 1] = 0; + ph_deactivate_req(v5up->ts[channel - 1]); return; } - /* deactivate */ - v5up->ts_activated[channel - 1] = 0; - /* if not assigned */ if (!v5up->ts[channel - 1]) return; + /* deactivate */ + ph_deactivate_req(v5up->ts[channel - 1]); + /* unassign or abort ongoing BCC allocation */ v52_le_bcc_mdu_snd(v5if, v5up->nr, v5up->type == V5X_USER_TYPE_ISDN, v5up->ts[channel - 1]->link->id, v5up->ts[channel - 1]->nr, 1, channel, NULL, 0, MDU_BCC_deallocation_req); @@ -679,7 +680,7 @@ int v52_le_bcc_mdu_rcv(struct v5x_interface *v5if, uint8_t link_id, uint8_t ts, case MDU_BCC_allocation_conf: LOGP(DV5MGMT, LOGL_INFO, "Assigned channel %d for %s port %d at TS %d of link %d.\n", channel, (v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr, ts, link_id); - v5up->ts_activated[channel - 1] = 1; + ph_activate_req(v5up->ts[channel - 1]); break; case MDU_BCC_deallocation_conf: LOGP(DV5MGMT, LOGL_INFO, "Unassigned channel %d for %s port %d at TS %d of link %d.\n",