mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 04:53:24 +00:00
Compare commits
7 Commits
on-waves/0
...
on-waves/0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84df56d577 | ||
|
|
4e23d5f87f | ||
|
|
4346424987 | ||
|
|
520656e004 | ||
|
|
9dac231fe4 | ||
|
|
2bb518a3bd | ||
|
|
476940f747 |
@@ -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])])
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user