Dynamically open and close b-channels depending on the usage

This commit is contained in:
Andreas Eversberg 2023-02-12 15:19:08 +01:00
parent a4483db3af
commit ebfab5792d
6 changed files with 70 additions and 23 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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]);
}
}
}

View File

@ -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 {

View File

@ -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",