aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2023-02-13 19:14:32 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2023-02-18 10:41:24 +0100
commite4225cf8a92d701b475a9baa4f25cd8da3455149 (patch)
tree3e48b3e3a2eb9d5fb76057fbbb81e488c8c9178c
parentmisdn driver: replace printf and fprintf by logging functions (diff)
downloadlibosmo-abis-e4225cf8a92d701b475a9baa4f25cd8da3455149.tar.xz
libosmo-abis-e4225cf8a92d701b475a9baa4f25cd8da3455149.zip
Rework mi_e1_line_update() and some of its sub routines
Close file descriptor and free lapd resources, if time slot type changes or if it is released. Also, reset local states. Change-Id: Iab0776fce6921661b39e9e53376cf01a80bcd42c
-rw-r--r--src/input/misdn.c81
1 files changed, 60 insertions, 21 deletions
diff --git a/src/input/misdn.c b/src/input/misdn.c
index c682392..8f04567 100644
--- a/src/input/misdn.c
+++ b/src/input/misdn.c
@@ -71,6 +71,7 @@
struct misdn_line {
int use_userspace_lapd;
int unconfirmed_ts[NUM_E1_TS];
+ enum e1inp_ts_type type_ts[NUM_E1_TS];
int dummy_dchannel;
int los, ais, rai;
};
@@ -761,12 +762,18 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
struct misdn_line *mline = line->driver_data;
int ts, ret;
- mline->dummy_dchannel = -1;
- if (mline->use_userspace_lapd) {
+ /* check if sign type is used */
+ for (ts = 1; ts < line->num_ts; ts++) {
+ unsigned int idx = ts - 1;
+ struct e1inp_ts *e1i_ts = &line->ts[idx];
+ if (e1i_ts->type == E1INP_TS_TYPE_SIGN)
+ break;
+ }
+ if (ts < line->num_ts && mline->use_userspace_lapd) {
/* Open dummy d-channel in order to use b-channels.
* Also it is required to define the mode.
*/
- if (mline->dummy_dchannel < 0) {
+ if (mline->dummy_dchannel <= 0) {
struct sockaddr_mISDN addr;
mline->dummy_dchannel = socket(PF_ISDN, SOCK_DGRAM,
@@ -788,50 +795,86 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
return -EIO;
}
}
+ } else {
+ /* close dummy d-channel */
+ if (mline->dummy_dchannel > 0) {
+ close(mline->dummy_dchannel);
+ mline->dummy_dchannel = -1;
+ }
}
+ LOGPIL(line, DLINP, LOGL_NOTICE, "Line update %d %d %d\n", line->num, line->port_nr, line->num_ts);
+
/* TS0 is CRC4, don't need any fd for it */
- for (ts = 1; ts < NUM_E1_TS; ts++) {
- unsigned int idx = ts-1;
+ for (ts = 1; ts < line->num_ts; ts++) {
+ unsigned int idx = ts - 1;
struct e1inp_ts *e1i_ts = &line->ts[idx];
struct osmo_fd *bfd = &e1i_ts->driver.misdn.fd;
struct sockaddr_mISDN addr;
+ /* no change in type */
+ if (mline->type_ts[idx] == e1i_ts->type)
+ continue;
+
+ LOGPIL(line, DLINP, LOGL_INFO, "Time slot %d changes from type %s to type %s\n", ts,
+ e1inp_tstype_name(mline->type_ts[idx]), e1inp_tstype_name(e1i_ts->type));
+
+ /* unregister FD if it was already registered */
+ if (bfd->list.next && bfd->list.next != LLIST_POISON1)
+ osmo_fd_unregister(bfd);
+
+ /* close/release LAPD instance, if any */
+ if (e1i_ts->lapd) {
+ lapd_instance_free(e1i_ts->lapd);
+ e1i_ts->lapd = NULL;
+ }
+
+ /* close old file descriptor */
+ if (bfd->fd) {
+ close(bfd->fd);
+ bfd->fd = 0;
+ }
+
+ /* clear 'unconfirmed' state */
+ mline->unconfirmed_ts[idx] = 0;
+
+ /* set new type */
+ mline->type_ts[idx] = e1i_ts->type;
+
switch (e1i_ts->type) {
case E1INP_TS_TYPE_NONE:
+ /* keep closed */
continue;
- break;
case E1INP_TS_TYPE_HDLC:
+ /* open hdlc socket */
/* TS 16 is the D-channel, so we use D-channel proto */
bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
(ts == 16) ? ISDN_P_NT_E1 : ISDN_P_B_HDLC);
- bfd->when = OSMO_FD_READ;
break;
case E1INP_TS_TYPE_SIGN:
+ /* open and allocate user space lapd, if required */
if (mline->use_userspace_lapd)
bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
ISDN_P_B_HDLC);
else
bfd->fd = socket(PF_ISDN, SOCK_DGRAM,
ISDN_P_LAPD_NT);
- bfd->when = OSMO_FD_READ;
break;
case E1INP_TS_TYPE_TRAU:
case E1INP_TS_TYPE_I460:
case E1INP_TS_TYPE_RAW:
+ /* open raw socket */
bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
- /* We never include the mISDN B-Channel FD into the
- * writeset, since it doesn't support poll() based
- * write flow control */
- bfd->when = OSMO_FD_READ;
break;
}
+ /* failed to open? */
if (bfd->fd < 0) {
LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "could not open socket: %s\n", strerror(errno));
return bfd->fd;
}
+ /* configure mISDN socket, also add user space lapd, if enabled */
memset(&addr, 0, sizeof(addr));
addr.family = AF_ISDN;
addr.dev = line->port_nr;
@@ -863,6 +906,7 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
break;
}
+ /* bind mISDN socket */
ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "could not bind l2 socket %s\n",
@@ -870,6 +914,7 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
return -EIO;
}
+ /* release L2 in case of kernel space lapd, activate b-channel in other cases */
if (e1i_ts->type == E1INP_TS_TYPE_SIGN) {
if (!mline->use_userspace_lapd) {
ret = ioctl(bfd->fd, IMCLEAR_L2, &release_l2);
@@ -880,17 +925,11 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
}
} else
activate_bchan(line, ts, 1);
- }
-
- /* FIXME: only activate B-Channels once we start to
- * use them to conserve CPU power */
- if (e1i_ts->type == E1INP_TS_TYPE_HDLC
- || e1i_ts->type == E1INP_TS_TYPE_RAW
- || e1i_ts->type == E1INP_TS_TYPE_TRAU)
+ } else
activate_bchan(line, ts, 1);
- osmo_fd_setup(bfd, bfd->fd, bfd->when, misdn_fd_cb, line, ts);
-
+ /* register file descriptor with read set enabled */
+ osmo_fd_setup(bfd, bfd->fd, OSMO_FD_READ, misdn_fd_cb, line, ts);
ret = osmo_fd_register(bfd);
if (ret < 0) {
LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "could not register FD: %s\n", strerror(ret));