Compare commits

...

7 Commits

Author SHA1 Message Date
Holger Hans Peter Freyther
84df56d577 Increase version.. 2010-04-11 19:41:32 +02:00
Holger Hans Peter Freyther
4e23d5f87f [bsc_init] When the RSL/OML connection drops, free all lchan
Free all allocated channels on the TRX that failed, go through
lchan_free to signal higher layers and then force a reset of
the channel. Make the TRX and TS unusable by setting the operational
set to 0 (not really defined).
2010-04-11 19:34:43 +02:00
Holger Hans Peter Freyther
4346424987 [ipa] Fix the reporting of link down...
Now bsc_init.c is able to handle the link down messages.
2010-04-11 18:54:58 +02:00
Holger Hans Peter Freyther
520656e004 [ipa] Handle losing the RSL/OML connection..
This is addressing multiple issues regarding the loss of the
OML/RSL link to the BTS.

1.) When we lose the OML link, close down all RSL connections
on all TRXs (only tested with one TRX) and free the e1inp_line
allocated for the OML connection.
2.) When we lose the RSL link on any TRX and we know to which
lines this connection belongs, we will close down the OML connection
as we have a problem to just reactivate the RSL link.
3.) When we lose the RSL link on any TRX and we do not know
where it belongs to we will free the bfd we have allocated in the
rsl listen/accept method and we properly close the socket (i could
not test this one properly).
4.) When we already have a bts->oml_link we will throw it away
and use the new link.
2010-04-11 18:49:03 +02:00
Holger Hans Peter Freyther
9dac231fe4 e1_input: Stop the timer when deleting the signalling link on the TS
Stop the tx_timer when deleting the link on top of that ts. Otherwise
bad things might happen. E.g. when scheduling a write on OML and then
the OML link vanishes...

This is a slight layering violation as there could be more than
one signalling link on the timeslow (at least in theory) so the
queue and the timer should move to the e1inp_sign_link.
2010-04-11 17:18:02 +02:00
Holger Hans Peter Freyther
2bb518a3bd [e1_input] When destroying a link clear all pending messages 2010-04-11 14:13:10 +02:00
Holger Hans Peter Freyther
476940f747 [vty] First set of fixes for the oml/rsl con dropping
The code had wrong documentation in the VTY, it crashed
when OML or RSL was not up yet. These issues are fixed
right now.
2010-04-11 12:46:45 +02:00
8 changed files with 184 additions and 35 deletions

View File

@@ -1,7 +1,7 @@
dnl Process this file with autoconf to produce a configure script
AC_INIT
AM_INIT_AUTOMAKE(openbsc, 0.3.95onwaves)
AM_INIT_AUTOMAKE(openbsc, 0.3.96onwaves)
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])

View File

@@ -67,6 +67,7 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type);
/* Free a logical channel (SDCCH, TCH, ...) */
void lchan_free(struct gsm_lchan *lchan);
void lchan_reset(struct gsm_lchan *lchan);
/* internal.. do not use */
int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason);

View File

@@ -53,6 +53,8 @@ int ipaccess_send_id_req(int fd);
int ipaccess_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len);
int ipaccess_drop_oml(struct gsm_bts *bts);
int ipaccess_drop_rsl(struct gsm_bts_trx *trx);
/*
* Firmware specific header

View File

@@ -31,6 +31,7 @@
#include <openbsc/system_information.h>
#include <openbsc/paging.h>
#include <openbsc/signal.h>
#include <openbsc/chan_alloc.h>
#include <osmocore/talloc.h>
/* global pointer to the gsm network data structure */
@@ -901,6 +902,8 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
{
int ts_no, lchan_no;
switch (event) {
case EVT_E1_TEI_UP:
switch (type) {
@@ -915,8 +918,30 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
}
break;
case EVT_E1_TEI_DN:
LOGP(DMI, LOGL_NOTICE, "Lost some E1 TEI link\n");
/* FIXME: deal with TEI or L1 link loss */
LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", type, trx);
/*
* free all allocated channels. change the nm_state so the
* trx and trx_ts becomes unusable and chan_alloc.c can not
* allocate from it.
*/
for (ts_no = 0; ts_no < ARRAY_SIZE(trx->ts); ++ts_no) {
struct gsm_bts_trx_ts *ts = &trx->ts[ts_no];
for (lchan_no = 0; lchan_no < ARRAY_SIZE(ts->lchan); ++lchan_no) {
if (ts->lchan[lchan_no].state != GSM_LCHAN_NONE)
lchan_free(&ts->lchan[lchan_no]);
lchan_reset(&ts->lchan[lchan_no]);
}
ts->nm_state.operational = 0;
ts->nm_state.availability = 0;
}
trx->nm_state.operational = 0;
trx->nm_state.availability = 0;
trx->bb_transc.nm_state.operational = 0;
trx->bb_transc.nm_state.availability = 0;
break;
default:
break;

View File

@@ -322,6 +322,21 @@ void lchan_free(struct gsm_lchan *lchan)
* channel using it */
}
/*
* There was an error with the TRX and we need to forget
* any state so that a lchan can be allocated again after
* the trx is fully usable.
*/
void lchan_reset(struct gsm_lchan *lchan)
{
bsc_del_timer(&lchan->T3101);
bsc_del_timer(&lchan->T3111);
bsc_del_timer(&lchan->error_timer);
lchan->type = GSM_LCHAN_NONE;
lchan->state = LCHAN_S_NONE;
}
static int _lchan_release_next_sapi(struct gsm_lchan *lchan)
{
int sapi;

View File

@@ -420,7 +420,17 @@ e1inp_sign_link_create(struct e1inp_ts *ts, enum e1inp_sign_type type,
void e1inp_sign_link_destroy(struct e1inp_sign_link *link)
{
struct msgb *msg;
llist_del(&link->list);
while (!llist_empty(&link->tx_list)) {
msg = msgb_dequeue(&link->tx_list);
msgb_free(msg);
}
if (link->ts->type == E1INP_TS_TYPE_SIGN)
bsc_del_timer(&link->ts->sign.tx_timer);
talloc_free(link);
}

View File

@@ -1,6 +1,8 @@
/* OpenBSC Abis input driver for ip.access */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by Holger Hans Peter Freyther
* (C) 2010 by On-Waves
*
* All Rights Reserved
*
@@ -234,6 +236,8 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
}
DEBUGP(DINP, "Identified BTS %u/%u/%u\n", site_id, bts_id, trx_id);
if (bfd->priv_nr == PRIV_OML) {
/* drop any old oml connection */
ipaccess_drop_oml(bts);
bts->oml_link = e1inp_sign_link_create(&line->ts[PRIV_OML - 1],
E1INP_SIGN_OML, bts->c0,
bts->oml_tei, 0);
@@ -241,7 +245,18 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
struct e1inp_ts *e1i_ts;
struct bsc_fd *newbfd;
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, trx_id);
/* drop any old rsl connection */
ipaccess_drop_rsl(trx);
if (!bts->oml_link) {
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
talloc_free(bfd);
return 0;
}
bfd->data = line = bts->oml_link->ts->line;
e1i_ts = &line->ts[PRIV_RSL + trx_id - 1];
newbfd = &e1i_ts->driver.ipaccess.fd;
@@ -251,19 +266,13 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
E1INP_SIGN_RSL, trx,
trx->rsl_tei, 0);
if (newbfd->fd >= 0) {
LOGP(DINP, LOGL_ERROR, "BTS is still registered. Closing old connection.\n");
bsc_unregister_fd(newbfd);
close(newbfd->fd);
newbfd->fd = -1;
}
/* get rid of our old temporary bfd */
memcpy(newbfd, bfd, sizeof(*newbfd));
newbfd->priv_nr = PRIV_RSL + trx_id;
bsc_unregister_fd(bfd);
bsc_register_fd(newbfd);
bfd->fd = -1;
talloc_free(bfd);
bsc_register_fd(newbfd);
}
break;
}
@@ -328,6 +337,103 @@ struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
return msg;
}
int ipaccess_drop_oml(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx;
struct e1inp_ts *ts;
struct e1inp_line *line;
struct bsc_fd *bfd;
if (!bts || !bts->oml_link)
return -1;
/* send OML down */
ts = bts->oml_link->ts;
line = ts->line;
e1inp_event(ts, EVT_E1_TEI_DN, bts->oml_link->tei, bts->oml_link->sapi);
bfd = &ts->driver.ipaccess.fd;
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
/* clean up OML and RSL */
e1inp_sign_link_destroy(bts->oml_link);
bts->oml_link = NULL;
bts->ip_access.flags = 0;
/* drop all RSL connections too */
llist_for_each_entry(trx, &bts->trx_list, list)
ipaccess_drop_rsl(trx);
/* kill the E1 line now... as we have no one left to use it */
talloc_free(line);
return -1;
}
static int ipaccess_drop(struct e1inp_ts *ts, struct bsc_fd *bfd)
{
struct e1inp_sign_link *link;
int bts_nr;
if (!ts) {
/*
* If we don't have a TS this means that this is a RSL
* connection but we are not past the authentication
* handling yet. So we can safely delete this bfd and
* wait for a reconnect.
*/
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
talloc_free(bfd);
return -1;
}
/* attempt to find a signalling link */
if (ts->type == E1INP_TS_TYPE_SIGN) {
llist_for_each_entry(link, &ts->sign.sign_links, list) {
bts_nr = link->trx->bts->bts_nr;
/* we have issues just reconnecting RLS so we drop OML */
ipaccess_drop_oml(link->trx->bts);
return bts_nr;
}
}
/* error case */
LOGP(DINP, LOGL_ERROR, "Failed to find a signalling link for ts: %p\n", ts);
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
return -1;
}
int ipaccess_drop_rsl(struct gsm_bts_trx *trx)
{
struct bsc_fd *bfd;
struct e1inp_ts *ts;
if (!trx || !trx->rsl_link)
return -1;
/* send RSL down */
ts = trx->rsl_link->ts;
e1inp_event(ts, EVT_E1_TEI_DN, trx->rsl_link->tei, trx->rsl_link->sapi);
/* close the socket */
bfd = &ts->driver.ipaccess.fd;
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
/* destroy */
e1inp_sign_link_destroy(trx->rsl_link);
trx->rsl_link = NULL;
return -1;
}
static int handle_ts1_read(struct bsc_fd *bfd)
{
struct e1inp_line *line = bfd->data;
@@ -341,18 +447,12 @@ static int handle_ts1_read(struct bsc_fd *bfd)
msg = ipaccess_read_msg(bfd, &error);
if (!msg) {
if (error == 0) {
link = e1inp_lookup_sign_link(e1i_ts, IPAC_PROTO_OML, 0);
if (link) {
link->trx->bts->ip_access.flags = 0;
int ret = ipaccess_drop(e1i_ts, bfd);
if (ret >= 0)
LOGP(DINP, LOGL_NOTICE, "BTS %u disappeared, dead socket\n",
link->trx->bts->nr);
} else
ret);
else
LOGP(DINP, LOGL_NOTICE, "unknown BTS disappeared, dead socket\n");
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_RSL);
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_OML);
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
}
return error;
}
@@ -362,13 +462,8 @@ static int handle_ts1_read(struct bsc_fd *bfd)
hh = (struct ipaccess_head *) msg->data;
if (hh->proto == IPAC_PROTO_IPACCESS) {
ret = ipaccess_rcvmsg(line, msg, bfd);
if (ret < 0) {
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_RSL);
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_OML);
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
}
if (ret < 0)
ipaccess_drop(e1i_ts, bfd);
msgb_free(msg);
return ret;
}

View File

@@ -39,6 +39,7 @@
#include <osmocore/talloc.h>
#include <openbsc/telnet_interface.h>
#include <openbsc/vty.h>
#include <openbsc/ipaccess.h>
static struct gsm_network *gsmnet;
@@ -957,8 +958,8 @@ DEFUN(show_stats,
DEFUN(drop_bts,
drop_bts_cmd,
"drop bts connection [nr] (oml|rsl)",
SHOW_STR "Debug/Simulation command to drop ipaccess BTS\n")
"drop bts connection <0-65535> (oml|rsl)",
"Debug/Simulation command to drop ipaccess BTS\n")
{
struct gsm_bts_trx *trx;
struct gsm_bts *bts;
@@ -984,12 +985,12 @@ DEFUN(drop_bts,
/* close all connections */
if (strcmp(argv[1], "oml") == 0) {
close(bts->oml_link->ts->driver.ipaccess.fd.fd);
} else if (strcmp(argv[1], "rsl") == 0) {
if (strcmp(argv[1], "oml") == 0)
ipaccess_drop_oml(bts);
else if (strcmp(argv[1], "rsl") == 0) {
/* close all rsl connections */
llist_for_each_entry(trx, &bts->trx_list, list) {
close(trx->rsl_link->ts->driver.ipaccess.fd.fd);
ipaccess_drop_rsl(trx);
}
} else {
vty_out(vty, "Argument must be 'oml# or 'rsl'.%s", VTY_NEWLINE);