mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-03 05:23:43 +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
|
dnl Process this file with autoconf to produce a configure script
|
||||||
AC_INIT
|
AC_INIT
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE(openbsc, 0.3.95onwaves)
|
AM_INIT_AUTOMAKE(openbsc, 0.3.96onwaves)
|
||||||
|
|
||||||
dnl kernel style compile messages
|
dnl kernel style compile messages
|
||||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
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, ...) */
|
/* Free a logical channel (SDCCH, TCH, ...) */
|
||||||
void lchan_free(struct gsm_lchan *lchan);
|
void lchan_free(struct gsm_lchan *lchan);
|
||||||
|
void lchan_reset(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
/* internal.. do not use */
|
/* internal.. do not use */
|
||||||
int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason);
|
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_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
|
* Firmware specific header
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include <openbsc/system_information.h>
|
#include <openbsc/system_information.h>
|
||||||
#include <openbsc/paging.h>
|
#include <openbsc/paging.h>
|
||||||
#include <openbsc/signal.h>
|
#include <openbsc/signal.h>
|
||||||
|
#include <openbsc/chan_alloc.h>
|
||||||
#include <osmocore/talloc.h>
|
#include <osmocore/talloc.h>
|
||||||
|
|
||||||
/* global pointer to the gsm network data structure */
|
/* 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)
|
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
|
||||||
{
|
{
|
||||||
|
int ts_no, lchan_no;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case EVT_E1_TEI_UP:
|
case EVT_E1_TEI_UP:
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -915,8 +918,30 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVT_E1_TEI_DN:
|
case EVT_E1_TEI_DN:
|
||||||
LOGP(DMI, LOGL_NOTICE, "Lost some E1 TEI link\n");
|
LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", type, trx);
|
||||||
/* FIXME: deal with TEI or L1 link loss */
|
|
||||||
|
/*
|
||||||
|
* 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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -322,6 +322,21 @@ void lchan_free(struct gsm_lchan *lchan)
|
|||||||
* channel using it */
|
* 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)
|
static int _lchan_release_next_sapi(struct gsm_lchan *lchan)
|
||||||
{
|
{
|
||||||
int sapi;
|
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)
|
void e1inp_sign_link_destroy(struct e1inp_sign_link *link)
|
||||||
{
|
{
|
||||||
|
struct msgb *msg;
|
||||||
|
|
||||||
llist_del(&link->list);
|
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);
|
talloc_free(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
/* OpenBSC Abis input driver for ip.access */
|
/* OpenBSC Abis input driver for ip.access */
|
||||||
|
|
||||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* (C) 2010 by Holger Hans Peter Freyther
|
||||||
|
* (C) 2010 by On-Waves
|
||||||
*
|
*
|
||||||
* All Rights Reserved
|
* 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);
|
DEBUGP(DINP, "Identified BTS %u/%u/%u\n", site_id, bts_id, trx_id);
|
||||||
if (bfd->priv_nr == PRIV_OML) {
|
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],
|
bts->oml_link = e1inp_sign_link_create(&line->ts[PRIV_OML - 1],
|
||||||
E1INP_SIGN_OML, bts->c0,
|
E1INP_SIGN_OML, bts->c0,
|
||||||
bts->oml_tei, 0);
|
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 e1inp_ts *e1i_ts;
|
||||||
struct bsc_fd *newbfd;
|
struct bsc_fd *newbfd;
|
||||||
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, trx_id);
|
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;
|
bfd->data = line = bts->oml_link->ts->line;
|
||||||
e1i_ts = &line->ts[PRIV_RSL + trx_id - 1];
|
e1i_ts = &line->ts[PRIV_RSL + trx_id - 1];
|
||||||
newbfd = &e1i_ts->driver.ipaccess.fd;
|
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,
|
E1INP_SIGN_RSL, trx,
|
||||||
trx->rsl_tei, 0);
|
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 */
|
/* get rid of our old temporary bfd */
|
||||||
memcpy(newbfd, bfd, sizeof(*newbfd));
|
memcpy(newbfd, bfd, sizeof(*newbfd));
|
||||||
newbfd->priv_nr = PRIV_RSL + trx_id;
|
newbfd->priv_nr = PRIV_RSL + trx_id;
|
||||||
bsc_unregister_fd(bfd);
|
bsc_unregister_fd(bfd);
|
||||||
bsc_register_fd(newbfd);
|
bfd->fd = -1;
|
||||||
talloc_free(bfd);
|
talloc_free(bfd);
|
||||||
|
bsc_register_fd(newbfd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -328,6 +337,103 @@ struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
|
|||||||
return msg;
|
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)
|
static int handle_ts1_read(struct bsc_fd *bfd)
|
||||||
{
|
{
|
||||||
struct e1inp_line *line = bfd->data;
|
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);
|
msg = ipaccess_read_msg(bfd, &error);
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
link = e1inp_lookup_sign_link(e1i_ts, IPAC_PROTO_OML, 0);
|
int ret = ipaccess_drop(e1i_ts, bfd);
|
||||||
if (link) {
|
if (ret >= 0)
|
||||||
link->trx->bts->ip_access.flags = 0;
|
|
||||||
LOGP(DINP, LOGL_NOTICE, "BTS %u disappeared, dead socket\n",
|
LOGP(DINP, LOGL_NOTICE, "BTS %u disappeared, dead socket\n",
|
||||||
link->trx->bts->nr);
|
ret);
|
||||||
} else
|
else
|
||||||
LOGP(DINP, LOGL_NOTICE, "unknown BTS disappeared, dead socket\n");
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -362,13 +462,8 @@ static int handle_ts1_read(struct bsc_fd *bfd)
|
|||||||
hh = (struct ipaccess_head *) msg->data;
|
hh = (struct ipaccess_head *) msg->data;
|
||||||
if (hh->proto == IPAC_PROTO_IPACCESS) {
|
if (hh->proto == IPAC_PROTO_IPACCESS) {
|
||||||
ret = ipaccess_rcvmsg(line, msg, bfd);
|
ret = ipaccess_rcvmsg(line, msg, bfd);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_RSL);
|
ipaccess_drop(e1i_ts, bfd);
|
||||||
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_OML);
|
|
||||||
bsc_unregister_fd(bfd);
|
|
||||||
close(bfd->fd);
|
|
||||||
bfd->fd = -1;
|
|
||||||
}
|
|
||||||
msgb_free(msg);
|
msgb_free(msg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include <osmocore/talloc.h>
|
#include <osmocore/talloc.h>
|
||||||
#include <openbsc/telnet_interface.h>
|
#include <openbsc/telnet_interface.h>
|
||||||
#include <openbsc/vty.h>
|
#include <openbsc/vty.h>
|
||||||
|
#include <openbsc/ipaccess.h>
|
||||||
|
|
||||||
static struct gsm_network *gsmnet;
|
static struct gsm_network *gsmnet;
|
||||||
|
|
||||||
@@ -957,8 +958,8 @@ DEFUN(show_stats,
|
|||||||
|
|
||||||
DEFUN(drop_bts,
|
DEFUN(drop_bts,
|
||||||
drop_bts_cmd,
|
drop_bts_cmd,
|
||||||
"drop bts connection [nr] (oml|rsl)",
|
"drop bts connection <0-65535> (oml|rsl)",
|
||||||
SHOW_STR "Debug/Simulation command to drop ipaccess BTS\n")
|
"Debug/Simulation command to drop ipaccess BTS\n")
|
||||||
{
|
{
|
||||||
struct gsm_bts_trx *trx;
|
struct gsm_bts_trx *trx;
|
||||||
struct gsm_bts *bts;
|
struct gsm_bts *bts;
|
||||||
@@ -984,12 +985,12 @@ DEFUN(drop_bts,
|
|||||||
|
|
||||||
|
|
||||||
/* close all connections */
|
/* close all connections */
|
||||||
if (strcmp(argv[1], "oml") == 0) {
|
if (strcmp(argv[1], "oml") == 0)
|
||||||
close(bts->oml_link->ts->driver.ipaccess.fd.fd);
|
ipaccess_drop_oml(bts);
|
||||||
} else if (strcmp(argv[1], "rsl") == 0) {
|
else if (strcmp(argv[1], "rsl") == 0) {
|
||||||
/* close all rsl connections */
|
/* close all rsl connections */
|
||||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||||
close(trx->rsl_link->ts->driver.ipaccess.fd.fd);
|
ipaccess_drop_rsl(trx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vty_out(vty, "Argument must be 'oml# or 'rsl'.%s", VTY_NEWLINE);
|
vty_out(vty, "Argument must be 'oml# or 'rsl'.%s", VTY_NEWLINE);
|
||||||
|
|||||||
Reference in New Issue
Block a user