the actual config file code (not just config files)

this was missing from commit a08a9acdb6
This commit is contained in:
Harald Welte 2009-08-08 16:12:58 +02:00
parent 3c5cb256c2
commit 42581829ec
13 changed files with 381 additions and 326 deletions

View File

@ -113,6 +113,9 @@ int e1inp_driver_register(struct e1inp_driver *drv);
/* register a line with the E1 core */
int e1inp_line_register(struct e1inp_line *line);
/* ensure a certain line exists, return pointer to it */
struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr);
/* find a sign_link for given TEI and SAPI in a TS */
struct e1inp_sign_link *
e1inp_lookup_sign_link(struct e1inp_ts *ts, u_int8_t tei,
@ -148,8 +151,12 @@ void e1_set_pcap_fd(int fd);
/* called by TRAU muxer to obtain the destination mux entity */
struct subch_mux *e1inp_get_mux(u_int8_t e1_nr, u_int8_t ts_nr);
/* e1_config.c */
int e1_config(struct gsm_bts *bts, int cardnr, int release_l2);
int e1_reconfig_ts(struct gsm_bts_trx_ts *ts);
int e1_reconfig_trx(struct gsm_bts_trx *trx);
int e1_reconfig_bts(struct gsm_bts *bts);
int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin);
int ipaccess_setup(struct gsm_network *gsmnet);

View File

@ -200,7 +200,10 @@ struct gsm_bts_trx {
/* number of this TRX in the BTS */
u_int8_t nr;
/* how do we talk RSL with this TRX? */
struct gsm_e1_subslot rsl_e1_link;
u_int8_t rsl_tei;
struct e1inp_sign_link *rsl_link;
struct gsm_nm_state nm_state;
struct tlv_parsed nm_attr;
struct {
@ -293,6 +296,8 @@ struct gsm_bts {
enum gsm_bts_type type;
enum gsm_band band;
/* how do we talk OML with this TRX? */
struct gsm_e1_subslot oml_e1_link;
u_int8_t oml_tei;
struct e1inp_sign_link *oml_link;
/* Abis network management O&M handle */
@ -404,7 +409,7 @@ struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
struct gsm_bts *start_bts);
char *gsm_band_name(enum gsm_band band);
enum gsm_band gsm_band_parse(int mhz);
enum gsm_band gsm_band_parse(const char *mhz);
extern void *tall_bsc_ctx;

View File

@ -29,6 +29,8 @@
#include <stdio.h>
#include <stdarg.h>
#define HAVE_VA_COPY
/* this is only needed for compatibility with the old talloc */
typedef void TALLOC_CTX;

View File

@ -61,12 +61,6 @@ struct host {
/* There are some command levels which called from command node. */
enum node_type {
GSMNET_NODE,
BTS_NODE,
TRX_NODE,
TS_NODE,
SUBSCR_NODE,
AUTH_NODE, /* Authentication mode of vty interface. */
VIEW_NODE, /* View node. Default mode of vty interface. */
AUTH_ENABLE_NODE, /* Authentication mode for change enable. */
@ -74,6 +68,7 @@ enum node_type {
CONFIG_NODE, /* Config node. Default mode of config file. */
SERVICE_NODE, /* Service node. */
DEBUG_NODE, /* Debug node. */
#if 0
AAA_NODE, /* AAA node. */
KEYCHAIN_NODE, /* Key-chain node. */
KEYCHAIN_KEY_NODE, /* Key-chain key node. */
@ -103,7 +98,14 @@ enum node_type {
SMUX_NODE, /* SNMP configuration node. */
DUMP_NODE, /* Packet dump node. */
FORWARDING_NODE, /* IP forwarding node. */
VTY_NODE /* Vty node. */
#endif
VTY_NODE, /* Vty node. */
GSMNET_NODE,
BTS_NODE,
TRX_NODE,
TS_NODE,
SUBSCR_NODE,
};
/* Node which has some commands and prompt string and configuration

View File

@ -55,27 +55,12 @@ static struct gsm_network *gsmnet;
/* MCC and MNC for the Location Area Identifier */
static int MCC = 1;
static int MNC = 1;
static int LAC = 1;
static int TSC = HARDCODED_TSC;
static int BSIC = HARDCODED_BSIC;
static int ARFCN = HARDCODED_ARFCN;
static int cardnr = 0;
static int release_l2 = 0;
static int bs11_has_trx1 = 0;
static int bs11_has_bts1 = 0;
static enum gsm_bts_type BTS_TYPE = GSM_BTS_TYPE_BS11;
static enum gsm_band BAND = GSM_BAND_900;
static const char *database_name = "hlr.sqlite3";
extern int ipacc_rtp_direct;
struct nano_bts_id {
struct llist_head entry;
int site_id;
int bts_id;
};
static LLIST_HEAD(nanobts_ids);
/* The following definitions are for OM and NM packets that we cannot yet
* generate by code but we just pass on */
@ -986,7 +971,8 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
{
fprintf(stdout, "bootstrapping RSL for BTS/TRX (%u/%u) "
"using MCC=%u MNC=%u BSIC=%u TSC=%u\n",
trx->bts->nr, trx->nr, MCC, MNC, BSIC, TSC);
trx->bts->nr, trx->nr, gsmnet->country_code,
gsmnet->network_code, trx->bts->bsic, trx->bts->tsc);
set_system_infos(trx);
}
@ -1016,9 +1002,25 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
static int bootstrap_bts(struct gsm_bts *bts)
{
bts->band = BAND;
bts->location_area_code = LAC;
bts->c0->arfcn = ARFCN;
switch (bts->type) {
case GSM_BTS_TYPE_NANOBTS_1800:
if (bts->c0->arfcn < 512 || bts->c0->arfcn > 885) {
fprintf(stderr, "GSM1800 channel must be between 512-885.\n");
return -EINVAL;
}
break;
case GSM_BTS_TYPE_BS11:
case GSM_BTS_TYPE_NANOBTS_900:
/* Assume we have a P-GSM900 here */
if (bts->c0->arfcn < 1 || bts->c0->arfcn > 124) {
fprintf(stderr, "GSM900 channel must be between 1-124.\n");
return -EINVAL;
}
break;
case GSM_BTS_TYPE_UNKNOWN:
fprintf(stderr, "Unknown BTS. Please specify\n");
return -EINVAL;
}
/* Control Channel Description */
memset(&bts->chan_desc, 0, sizeof(struct gsm48_control_channel_descr));
@ -1031,66 +1033,21 @@ static int bootstrap_bts(struct gsm_bts *bts)
paging_init(bts);
if (bts->type == GSM_BTS_TYPE_BS11) {
struct gsm_bts_trx *trx = bts->c0;
set_ts_e1link(&trx->ts[0], 0, 1, 0xff);
set_ts_e1link(&trx->ts[1], 0, 2, 1);
set_ts_e1link(&trx->ts[2], 0, 2, 2);
set_ts_e1link(&trx->ts[3], 0, 2, 3);
set_ts_e1link(&trx->ts[4], 0, 3, 0);
set_ts_e1link(&trx->ts[5], 0, 3, 1);
set_ts_e1link(&trx->ts[6], 0, 3, 2);
set_ts_e1link(&trx->ts[7], 0, 3, 3);
/* TRX 1 */
trx = gsm_bts_trx_num(bts, 1);
if (trx) {
trx = gsm_bts_trx_num(bts, 1);
set_ts_e1link(&trx->ts[0], 0, 4, 0);
set_ts_e1link(&trx->ts[1], 0, 4, 1);
set_ts_e1link(&trx->ts[2], 0, 4, 2);
set_ts_e1link(&trx->ts[3], 0, 4, 3);
set_ts_e1link(&trx->ts[4], 0, 5, 0);
set_ts_e1link(&trx->ts[5], 0, 5, 1);
set_ts_e1link(&trx->ts[6], 0, 5, 2);
set_ts_e1link(&trx->ts[7], 0, 5, 3);
}
}
return 0;
}
static int bootstrap_network(void)
{
struct gsm_bts *bts;
int rc;
switch(BTS_TYPE) {
case GSM_BTS_TYPE_NANOBTS_1800:
if (ARFCN < 512 || ARFCN > 885) {
fprintf(stderr, "GSM1800 channel must be between 512-885.\n");
return -EINVAL;
}
break;
case GSM_BTS_TYPE_BS11:
case GSM_BTS_TYPE_NANOBTS_900:
/* Assume we have a P-GSM900 here */
if (ARFCN < 1 || ARFCN > 124) {
fprintf(stderr, "GSM900 channel must be between 1-124.\n");
return -EINVAL;
}
break;
case GSM_BTS_TYPE_UNKNOWN:
fprintf(stderr, "Unknown BTS. Please use the --bts-type switch\n");
return -EINVAL;
}
/* initialize our data structures */
gsmnet = gsm_network_init(MCC, MNC, mncc_recv);
if (!gsmnet)
return -ENOMEM;
gsmnet->name_long = "OpenBSC";
gsmnet->name_short = "OpenBSC";
gsmnet->name_long = talloc_strdup(gsmnet, "OpenBSC");
gsmnet->name_short = talloc_strdup(gsmnet, "OpenBSC");
if (db_init(database_name)) {
printf("DB: Failed to init database. Please check the option settings.\n");
@ -1105,56 +1062,24 @@ static int bootstrap_network(void)
printf("DB: Database prepared.\n");
telnet_init(gsmnet, 4242);
rc = vty_read_config_file("openbsc.cfg");
if (rc < 0)
return rc;
register_signal_handler(SS_NM, nm_sig_cb, NULL);
/* E1 mISDN input setup */
if (BTS_TYPE == GSM_BTS_TYPE_BS11) {
struct gsm_bts *bts = gsm_bts_alloc(gsmnet, BTS_TYPE, TSC, BSIC);
if (bs11_has_trx1) {
struct gsm_bts_trx *trx1;
trx1 = gsm_bts_trx_alloc(bts);
trx1->arfcn = ARFCN + 2;
}
llist_for_each_entry(bts, &gsmnet->bts_list, list) {
bootstrap_bts(bts);
rc = e1_config(bts, cardnr, release_l2);
if (rc < 0) {
fprintf(stderr, "Error during E1 config of BTS 0\n");
return rc;
}
if (is_ipaccess_bts(bts))
rc = ipaccess_setup(bts);
else
rc = e1_reconfig_bts(bts);
if (bs11_has_bts1) {
bts = gsm_bts_alloc(gsmnet, BTS_TYPE, TSC, BSIC);
if (bs11_has_trx1) {
struct gsm_bts_trx *trx1;
trx1 = gsm_bts_trx_alloc(bts);
trx1->arfcn = ARFCN + 2;
}
bootstrap_bts(bts);
rc = e1_config(bts, cardnr+1, release_l2);
if (rc < 0)
fprintf(stderr, "Error during E1 config of BTS 1\n");
}
return rc;
} else {
struct nano_bts_id *bts_id;
struct gsm_bts *bts;
if (llist_empty(&nanobts_ids)) {
fprintf(stderr, "You need to specify -i DEVICE_1 -i DEVICE_2 for nanoBTS.\n");
return -EINVAL;
}
llist_for_each_entry(bts_id, &nanobts_ids, entry) {
bts = gsm_bts_alloc(gsmnet, BTS_TYPE, TSC, BSIC);
bootstrap_bts(bts);
bts->ip_access.site_id = bts_id->site_id;
bts->ip_access.bts_id = 0;
}
return ipaccess_setup(gsmnet);
if (rc < 0)
exit (1);
}
return 0;
}
static void create_pcap_file(char *file)
@ -1178,22 +1103,15 @@ static void print_usage()
static void print_help()
{
printf(" Some useful help...\n");
printf(" -h --help this text\n");
printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
printf(" -s --disable-color\n");
printf(" -n --network-code number(MNC) \n");
printf(" -c --country-code number (MCC) \n");
printf(" -L --location-area-code number (LAC) \n");
printf(" -f --arfcn number The frequency ARFCN\n");
printf(" -l --database db-name The database to use\n");
printf(" -a --authorize-everyone Allow everyone into the network.\n");
printf(" -r --reject-cause number The reject cause for LOCATION UPDATING REJECT.\n");
printf(" -p --pcap file The filename of the pcap file\n");
printf(" -t --bts-type type The BTS type (bs11, nanobts900, nanobts1800)\n");
printf(" -i --bts-id=NUMBER The known nanoBTS device numbers. Can be specified multiple times.\n");
printf(" -C --cardnr number For bs11 select E1 card number other than 0\n");
printf(" -R --release-l2 Releases mISDN layer 2 after exit, to unload driver.\n");
printf(" -2 --second-bs11 Configure + Use a second BS-11\n");
printf(" -h --help this text\n");
}
static void handle_options(int argc, char** argv)
@ -1204,29 +1122,18 @@ static void handle_options(int argc, char** argv)
{"help", 0, 0, 'h'},
{"debug", 1, 0, 'd'},
{"disable-color", 0, 0, 's'},
{"network-code", 1, 0, 'n'},
{"country-code", 1, 0, 'c'},
{"location-area-code", 1, 0, 'L'},
{"database", 1, 0, 'l'},
{"authorize-everyone", 0, 0, 'a'},
{"reject-cause", 1, 0, 'r'},
{"pcap", 1, 0, 'p'},
{"arfcn", 1, 0, 'f'},
{"bts-type", 1, 0, 't'},
{"cardnr", 1, 0, 'C'},
{"release-l2", 0, 0, 'R'},
{"timestamp", 0, 0, 'T'},
{"band", 0, 0, 'b'},
{"bts-id", 1, 0, 'i'},
{"tsc", 1, 0, 'S'},
{"bsic", 1, 0, 'B'},
{"rtp-proxy", 0, 0, 'P'},
{"trx1", 0, 0, '1'},
{"second-bs11", 0, 0, '2'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:C:RL:l:Tb:i:S:B:P12",
c = getopt_long(argc, argv, "hd:sl:ar:p:C:RTP",
long_options, &option_index);
if (c == -1)
break;
@ -1242,18 +1149,6 @@ static void handle_options(int argc, char** argv)
case 'd':
debug_parse_category_mask(optarg);
break;
case 'n':
MNC = atoi(optarg);
break;
case 'c':
MCC = atoi(optarg);
break;
case 'L':
LAC = atoi(optarg);
break;
case 'f':
ARFCN = atoi(optarg);
break;
case 'l':
database_name = strdup(optarg);
break;
@ -1278,35 +1173,9 @@ static void handle_options(int argc, char** argv)
case 'T':
debug_timestamp(1);
break;
case 'b':
BAND = gsm_band_parse(atoi(optarg));
break;
case 'i': {
struct nano_bts_id *bts_id = talloc_zero(tall_bsc_ctx, struct nano_bts_id);
if (!bts_id) {
fprintf(stderr, "Failed to allocate bts id\n");
exit(-1);
}
bts_id->site_id = atoi(optarg);
llist_add(&bts_id->entry, &nanobts_ids);
break;
case 'S':
TSC = atoi(optarg);
break;
case 'B':
BSIC = atoi(optarg);
break;
case 'P':
ipacc_rtp_direct = 0;
break;
case '1':
bs11_has_trx1 = 1;
break;
case '2':
bs11_has_bts1 = 1;
break;
}
default:
/* ignore */
break;

View File

@ -14,10 +14,106 @@
#define SAPI_OML 62
#define SAPI_RSL 0 /* 63 ? */
#define TEI_L2ML 127
#define TEI_OML 25
#define TEI_RSL 1
/* The e1_reconfig_*() functions below tale the configuration present in the
* bts/trx/ts data structures and ensure the E1 configuration reflects the
* timeslot/subslot/TEI configuration */
int e1_reconfig_ts(struct gsm_bts_trx_ts *ts)
{
struct gsm_e1_subslot *e1_link = &ts->e1_link;
struct e1inp_line *line;
struct e1inp_ts *e1_ts;
printf("e1_reconfig_ts(%u,%u,%u)\n", ts->trx->bts->nr, ts->trx->nr, ts->nr);
if (!e1_link->e1_ts)
return 0;
line = e1inp_line_get_create(e1_link->e1_nr);
if (!line)
return -ENOMEM;
switch (ts->pchan) {
case GSM_PCHAN_TCH_F:
case GSM_PCHAN_TCH_H:
e1_ts = &line->ts[e1_link->e1_ts-1];
e1inp_ts_config(e1_ts, line, E1INP_TS_TYPE_TRAU);
subch_demux_activate(&e1_ts->trau.demux, e1_link->e1_ts_ss);
break;
default:
break;
}
return 0;
}
int e1_reconfig_trx(struct gsm_bts_trx *trx)
{
struct gsm_e1_subslot *e1_link = &trx->rsl_e1_link;
struct e1inp_ts *sign_ts;
struct e1inp_line *line;
struct e1inp_sign_link *rsl_link;
int i;
if (!e1_link->e1_ts)
return -EINVAL;
/* RSL Link */
line = e1inp_line_get_create(e1_link->e1_nr);
if (!line)
return -ENOMEM;
sign_ts = &line->ts[e1_link->e1_ts-1];
e1inp_ts_config(sign_ts, line, E1INP_TS_TYPE_SIGN);
rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
trx, trx->rsl_tei, SAPI_RSL);
if (!rsl_link)
return -ENOMEM;
if (trx->rsl_link)
e1inp_sign_link_destroy(trx->rsl_link);
trx->rsl_link = rsl_link;
for (i = 0; i < TRX_NR_TS; i++)
e1_reconfig_ts(&trx->ts[i]);
return 0;
}
int e1_reconfig_bts(struct gsm_bts *bts)
{
struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
struct e1inp_ts *sign_ts;
struct e1inp_line *line;
struct e1inp_sign_link *oml_link;
struct gsm_bts_trx *trx;
int rc;
printf("e1_reconfig_bts(%u)\n", bts->nr);
if (!e1_link->e1_ts)
return -EINVAL;
/* OML link */
line = e1inp_line_get_create(e1_link->e1_nr);
if (!line)
return -ENOMEM;
sign_ts = &line->ts[e1_link->e1_ts-1];
e1inp_ts_config(sign_ts, line, E1INP_TS_TYPE_SIGN);
oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
bts->c0, bts->oml_tei, SAPI_OML);
if (!oml_link)
return -ENOMEM;
if (bts->oml_link)
e1inp_sign_link_destroy(bts->oml_link);
bts->oml_link = oml_link;
llist_for_each_entry(trx, &bts->trx_list, list)
e1_reconfig_trx(trx);
/* notify E1 input something has changed */
return e1inp_line_update(line);
}
#if 0
/* do some compiled-in configuration for our BTS/E1 setup */
int e1_config(struct gsm_bts *bts, int cardnr, int release_l2)
{
@ -102,6 +198,7 @@ int e1_config(struct gsm_bts *bts, int cardnr, int release_l2)
return mi_setup(cardnr, line, release_l2);
}
#endif
/* configure pseudo E1 line in ip.access style and connect to BTS */
int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin)

View File

@ -289,6 +289,9 @@ int _abis_nm_sendmsg(struct msgb *msg)
int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
enum e1inp_ts_type type)
{
if (ts->type == type && ts->line && line)
return 0;
ts->type = type;
ts->line = line;
@ -322,6 +325,29 @@ static struct e1inp_line *e1inp_line_get(u_int8_t e1_nr)
return NULL;
}
struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr)
{
struct e1inp_line *line;
int i;
line = e1inp_line_get(e1_nr);
if (line)
return line;
line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
if (!line)
return NULL;
line->num = e1_nr;
for (i = 0; i < NUM_E1_TS; i++) {
line->ts[i].num = i+1;
line->ts[i].line = line;
}
llist_add_tail(&line->list, &e1inp_line_list);
return line;
}
static struct e1inp_ts *e1inp_ts_get(u_int8_t e1_nr, u_int8_t ts_nr)
{
struct e1inp_line *e1i_line;
@ -386,6 +412,12 @@ e1inp_sign_link_create(struct e1inp_ts *ts, enum e1inp_sign_type type,
return link;
}
void e1inp_sign_link_destroy(struct e1inp_sign_link *link)
{
llist_del(&link->list);
talloc_free(link);
}
/* the E1 driver tells us he has received something on a TS */
int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
u_int8_t tei, u_int8_t sapi)
@ -399,7 +431,7 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
write_pcap_packet(PCAP_INPUT, sapi, tei, msg);
link = e1inp_lookup_sign_link(ts, tei, sapi);
if (!link) {
fprintf(stderr, "didn't find singalling link for "
fprintf(stderr, "didn't find signalling link for "
"tei %d, sapi %d\n", tei, sapi);
return -EINVAL;
}
@ -487,19 +519,9 @@ int e1inp_driver_register(struct e1inp_driver *drv)
return 0;
}
/* register a line with the E1 core */
int e1inp_line_register(struct e1inp_line *line)
int e1inp_line_update(struct e1inp_line *line)
{
int i;
for (i = 0; i < NUM_E1_TS; i++) {
line->ts[i].num = i+1;
line->ts[i].line = line;
}
llist_add_tail(&line->list, &e1inp_line_list);
return 0;
return mi_e1_line_update(line);
}
static __attribute__((constructor)) void on_dso_load_e1_inp(void)

View File

@ -23,6 +23,7 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <openbsc/gsm_data.h>
#include <openbsc/talloc.h>
@ -295,9 +296,15 @@ char *gsm_band_name(enum gsm_band band)
return "invalid";
}
enum gsm_band gsm_band_parse(int mhz)
enum gsm_band gsm_band_parse(const char* mhz)
{
switch (mhz) {
while (*mhz && !isdigit(*mhz))
mhz++;
if (*mhz == '\0')
return -EINVAL;
switch (atoi(mhz)) {
case 400:
return GSM_BAND_400;
case 850:

View File

@ -461,7 +461,7 @@ static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
ret = write(bfd->fd, id_req, sizeof(id_req));
return e1inp_line_register(line);
//return e1inp_line_register(line);
}
static int rsl_listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
@ -574,7 +574,7 @@ int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa)
line->driver = &ipaccess_driver;
return e1inp_line_register(line);
//return e1inp_line_register(line);
}
int ipaccess_setup(struct gsm_network *gsmnet)

View File

@ -49,12 +49,6 @@
#include <openbsc/e1_input.h>
#include <openbsc/talloc.h>
/* data structure for one E1 interface with A-bis */
struct mi_e1_handle {
/* The mISDN card number of the card we use */
int cardnr;
};
#define TS1_ALLOC_SIZE 300
struct prim_name {
@ -383,7 +377,6 @@ struct e1inp_driver misdn_driver = {
static int mi_e1_setup(struct e1inp_line *line, int release_l2)
{
struct mi_e1_handle *e1h = line->driver_data;
int ts, ret;
/* TS0 is CRC4, don't need any fd for it */
@ -422,7 +415,7 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
memset(&addr, 0, sizeof(addr));
addr.family = AF_ISDN;
addr.dev = e1h->cardnr;
addr.dev = line->num;
switch (e1i_ts->type) {
case E1INP_TS_TYPE_SIGN:
addr.channel = 0;
@ -471,20 +464,23 @@ static int mi_e1_setup(struct e1inp_line *line, int release_l2)
return 0;
}
int mi_setup(int cardnr, struct e1inp_line *line, int release_l2)
int mi_e1_line_update(struct e1inp_line *line)
{
struct mi_e1_handle *e1h;
int sk, ret, cnt;
struct mISDN_devinfo devinfo;
int sk, ret, cnt;
/* create the actual line instance */
e1h = talloc(tall_bsc_ctx, struct mi_e1_handle);
memset(e1h, 0, sizeof(*e1h));
if (!line->driver) {
/* this must be the first update */
line->driver = &misdn_driver;
} else {
/* this is a subsequent update */
/* FIXME: first close all sockets */
fprintf(stderr, "incremental line updates not supported yet\n");
return 0;
}
e1h->cardnr = cardnr;
line->driver = &misdn_driver;
line->driver_data = e1h;
if (line->driver != &misdn_driver)
return -EINVAL;
/* open the ISDN card device */
sk = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
@ -504,11 +500,11 @@ int mi_setup(int cardnr, struct e1inp_line *line, int release_l2)
//DEBUGP(DMI,"%d device%s found\n", cnt, (cnt==1)?"":"s");
printf("%d device%s found\n", cnt, (cnt==1)?"":"s");
#if 1
devinfo.id = e1h->cardnr;
devinfo.id = line->num;
ret = ioctl(sk, IMGETDEVINFO, &devinfo);
if (ret < 0) {
fprintf(stdout, "error getting info for device %d: %s\n",
e1h->cardnr, strerror(errno));
line->num, strerror(errno));
return -ENODEV;
}
fprintf(stdout, " id: %d\n", devinfo.id);
@ -524,11 +520,11 @@ int mi_setup(int cardnr, struct e1inp_line *line, int release_l2)
return -EINVAL;
}
ret = mi_e1_setup(line, release_l2);
ret = mi_e1_setup(line, 1);
if (ret)
return ret;
return e1inp_line_register(line);
return 0;
}
static __attribute__((constructor)) void on_dso_load_sms(void)

View File

@ -1909,27 +1909,49 @@ char **cmd_complete_command(vector vline, struct vty *vty, int *status)
/* return parent node */
/* MUST eventually converge on CONFIG_NODE */
enum node_type node_parent(enum node_type node)
enum node_type vty_go_parent(struct vty *vty)
{
enum node_type ret;
assert(vty->node > CONFIG_NODE);
assert(node > CONFIG_NODE);
switch (node) {
case BGP_VPNV4_NODE:
case BGP_IPV4_NODE:
case BGP_IPV4M_NODE:
case BGP_IPV6_NODE:
ret = BGP_NODE;
switch (vty->node) {
case GSMNET_NODE:
vty->node = CONFIG_NODE;
vty->index = NULL;
break;
case KEYCHAIN_KEY_NODE:
ret = KEYCHAIN_NODE;
case BTS_NODE:
vty->node = GSMNET_NODE;
{
/* set vty->index correctly ! */
struct gsm_bts *bts = vty->index;
vty->index = bts->network;
}
break;
case TRX_NODE:
vty->node = BTS_NODE;
{
/* set vty->index correctly ! */
struct gsm_bts_trx *trx = vty->index;
vty->index = trx->bts;
}
break;
case TS_NODE:
vty->node = TRX_NODE;
{
/* set vty->index correctly ! */
struct gsm_bts_trx_ts *ts = vty->index;
vty->index = ts->trx;
}
break;
case SUBSCR_NODE:
vty->node = VIEW_NODE;
subscr_put(vty->index);
vty->index = NULL;
break;
default:
ret = CONFIG_NODE;
vty->node = CONFIG_NODE;
}
return ret;
return vty->node;
}
/* Execute command by argument vline vector. */
@ -2052,9 +2074,11 @@ cmd_execute_command(vector vline, struct vty *vty, struct cmd_element **cmd,
int vtysh)
{
int ret, saved_ret, tried = 0;
enum node_type onode, try_node;
enum node_type onode;
void *oindex;
onode = try_node = vty->node;
onode = vty->node;
oindex = vty->index;
if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
vector shifted_vline;
@ -2085,8 +2109,7 @@ cmd_execute_command(vector vline, struct vty *vty, struct cmd_element **cmd,
/* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
while (ret != CMD_SUCCESS && ret != CMD_WARNING
&& vty->node > CONFIG_NODE) {
try_node = node_parent(try_node);
vty->node = try_node;
vty_go_parent(vty);
ret = cmd_execute_command_real(vline, vty, cmd);
tried = 1;
if (ret == CMD_SUCCESS || ret == CMD_WARNING) {
@ -2096,8 +2119,10 @@ cmd_execute_command(vector vline, struct vty *vty, struct cmd_element **cmd,
}
/* no command succeeded, reset the vty to the original node and
return the error for this node */
if (tried)
if (tried) {
vty->node = onode;
vty->index = oindex;
}
return saved_ret;
}
@ -2232,7 +2257,7 @@ int config_from_file(struct vty *vty, FILE * fp)
while (ret != CMD_SUCCESS && ret != CMD_WARNING
&& ret != CMD_ERR_NOTHING_TODO
&& vty->node != CONFIG_NODE) {
vty->node = node_parent(vty->node);
vty_go_parent(vty);
ret = cmd_execute_command_strict(vline, vty, NULL);
}
@ -2332,29 +2357,9 @@ DEFUN(config_exit,
vty->node = ENABLE_NODE;
vty_config_unlock(vty);
break;
case INTERFACE_NODE:
case ZEBRA_NODE:
case BGP_NODE:
case RIP_NODE:
case RIPNG_NODE:
case OSPF_NODE:
case OSPF6_NODE:
case ISIS_NODE:
case KEYCHAIN_NODE:
case MASC_NODE:
case RMAP_NODE:
case VTY_NODE:
vty->node = CONFIG_NODE;
break;
case BGP_VPNV4_NODE:
case BGP_IPV4_NODE:
case BGP_IPV4M_NODE:
case BGP_IPV6_NODE:
vty->node = BGP_NODE;
break;
case KEYCHAIN_KEY_NODE:
vty->node = KEYCHAIN_NODE;
break;
default:
break;
}
@ -2375,22 +2380,6 @@ ALIAS(config_exit,
/* Nothing to do. */
break;
case CONFIG_NODE:
case INTERFACE_NODE:
case ZEBRA_NODE:
case RIP_NODE:
case RIPNG_NODE:
case BGP_NODE:
case BGP_VPNV4_NODE:
case BGP_IPV4_NODE:
case BGP_IPV4M_NODE:
case BGP_IPV6_NODE:
case RMAP_NODE:
case OSPF_NODE:
case OSPF6_NODE:
case ISIS_NODE:
case KEYCHAIN_NODE:
case KEYCHAIN_KEY_NODE:
case MASC_NODE:
case VTY_NODE:
vty_config_unlock(vty);
vty->node = ENABLE_NODE;
@ -3350,8 +3339,7 @@ void cmd_init(int terminal)
/* Default host value settings. */
host.name = NULL;
//host.password = NULL;
host.password = "foo";
host.password = NULL;
host.enable = NULL;
host.logfile = NULL;
host.config = NULL;

View File

@ -743,22 +743,6 @@ static void vty_end_config(struct vty *vty)
/* Nothing to do. */
break;
case CONFIG_NODE:
case INTERFACE_NODE:
case ZEBRA_NODE:
case RIP_NODE:
case RIPNG_NODE:
case BGP_NODE:
case BGP_VPNV4_NODE:
case BGP_IPV4_NODE:
case BGP_IPV4M_NODE:
case BGP_IPV6_NODE:
case RMAP_NODE:
case OSPF_NODE:
case OSPF6_NODE:
case ISIS_NODE:
case KEYCHAIN_NODE:
case KEYCHAIN_KEY_NODE:
case MASC_NODE:
case VTY_NODE:
vty_config_unlock(vty);
vty->node = ENABLE_NODE;
@ -1125,18 +1109,6 @@ static void vty_stop_input(struct vty *vty)
/* Nothing to do. */
break;
case CONFIG_NODE:
case INTERFACE_NODE:
case ZEBRA_NODE:
case RIP_NODE:
case RIPNG_NODE:
case BGP_NODE:
case RMAP_NODE:
case OSPF_NODE:
case OSPF6_NODE:
case ISIS_NODE:
case KEYCHAIN_NODE:
case KEYCHAIN_KEY_NODE:
case MASC_NODE:
case VTY_NODE:
vty_config_unlock(vty);
vty->node = ENABLE_NODE;
@ -1393,7 +1365,7 @@ vty_read_file(FILE *confp)
fprintf(stderr, "Ambiguous command.\n");
break;
case CMD_ERR_NO_MATCH:
fprintf(stderr, "Ther is no such command.\n");
fprintf(stderr, "There is no such command.\n");
break;
}
fprintf(stderr, "Error occurred during reading below "
@ -1675,10 +1647,8 @@ void vty_init()
install_element(ENABLE_NODE, &show_history_cmd);
install_default(VTY_NODE);
#if 0
install_element(VTY_NODE, &vty_login_cmd);
install_element(VTY_NODE, &no_vty_login_cmd);
#endif
}
int vty_read_config_file(const char *file_name)

View File

@ -164,13 +164,41 @@ DEFUN(show_bts, show_bts_cmd, "show bts [number]",
return CMD_SUCCESS;
}
/* utility functions */
static void parse_e1_link(struct gsm_e1_subslot *e1_link, const char *line,
const char *ts, const char *ss)
{
e1_link->e1_nr = atoi(line);
e1_link->e1_ts = atoi(ts);
if (!strcmp(ss, "full"))
e1_link->e1_ts_ss = 255;
else
e1_link->e1_ts_ss = atoi(ss);
}
static void config_write_e1_link(struct vty *vty, struct gsm_e1_subslot *e1_link,
const char *prefix)
{
if (!e1_link->e1_ts)
return;
if (e1_link->e1_ts_ss == 255)
vty_out(vty, "%se1 line %u timeslot %u sub-slot full%s",
prefix, e1_link->e1_nr, e1_link->e1_ts, VTY_NEWLINE);
else
vty_out(vty, "%se1 line %u timeslot %u sub-slot %u%s",
prefix, e1_link->e1_nr, e1_link->e1_ts,
e1_link->e1_ts_ss, VTY_NEWLINE);
}
static void config_write_ts_single(struct vty *vty, struct gsm_bts_trx_ts *ts)
{
vty_out(vty, " ts %u%s", ts->nr, VTY_NEWLINE);
vty_out(vty, " phys_chan_config %s%s", gsm_pchan_name(ts->pchan),
VTY_NEWLINE);
vty_out(vty, " e1_subslot %u %u %u%s", ts->e1_link.e1_nr,
ts->e1_link.e1_ts, ts->e1_link.e1_ts_ss, VTY_NEWLINE);
vty_out(vty, " timeslot %u%s", ts->nr, VTY_NEWLINE);
if (ts->pchan != GSM_PCHAN_NONE)
vty_out(vty, " phys_chan_config %s%s",
gsm_pchan_name(ts->pchan), VTY_NEWLINE);
config_write_e1_link(vty, &ts->e1_link, " ");
}
static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
@ -180,6 +208,8 @@ static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
vty_out(vty, " arfcn %u%s", trx->arfcn, VTY_NEWLINE);
vty_out(vty, " max_power_red %u%s", trx->max_power_red, VTY_NEWLINE);
config_write_e1_link(vty, &trx->rsl_e1_link, " rsl ");
vty_out(vty, " rsl e1 tei %u%s", trx->rsl_tei, VTY_NEWLINE);
for (i = 0; i < TRX_NR_TS; i++)
config_write_ts_single(vty, &trx->ts[i]);
@ -199,6 +229,10 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
if (is_ipaccess_bts(bts))
vty_out(vty, " ip.access unit_id %u %u%s",
bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE);
else {
config_write_e1_link(vty, &bts->oml_e1_link, " oml ");
vty_out(vty, " oml e1 tei %u%s", bts->oml_tei, VTY_NEWLINE);
}
llist_for_each_entry(trx, &bts->trx_list, list)
config_write_trx_single(vty, trx);
@ -217,10 +251,10 @@ static int config_write_bts(struct vty *v)
static int config_write_net(struct vty *vty)
{
vty_out(vty, "network%s", VTY_NEWLINE);
vty_out(vty, " country code %u%s", gsmnet->country_code, VTY_NEWLINE);
vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE);
vty_out(vty, " short name '%s'%s", gsmnet->name_short, VTY_NEWLINE);
vty_out(vty, " long name '%s'%s", gsmnet->name_long, VTY_NEWLINE);
vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
return CMD_SUCCESS;
}
@ -230,9 +264,9 @@ static void trx_dump_vty(struct vty *vty, struct gsm_bts_trx *trx)
vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s",
trx->nr, trx->bts->nr, trx->arfcn, VTY_NEWLINE);
vty_out(vty, " RF Nominal Power: %d dBm, reduced by %u dB, "
"resulting BS power: %d dBm\n",
"resulting BS power: %d dBm%s",
trx->nominal_power, trx->max_power_red,
trx->nominal_power - trx->max_power_red);
trx->nominal_power - trx->max_power_red, VTY_NEWLINE);
vty_out(vty, " NM State: ");
net_dump_nmstate(vty, &trx->nm_state);
vty_out(vty, " Baseband Transceiver NM State: ");
@ -550,6 +584,8 @@ DEFUN(show_e1line,
static void e1ts_dump_vty(struct vty *vty, struct e1inp_ts *ts)
{
if (ts->type == E1INP_TS_TYPE_NONE)
return;
vty_out(vty, "E1 Timeslot %2u of Line %u is Type %s%s",
ts->num, ts->line->num, e1inp_tstype_name(ts->type),
VTY_NEWLINE);
@ -776,7 +812,7 @@ DEFUN(cfg_bts_band,
"Set the frequency band of this BTS\n")
{
struct gsm_bts *bts = vty->index;
int band = gsm_band_parse(atoi(argv[0]));
int band = gsm_band_parse(argv[0]);
if (band < 0) {
vty_out(vty, "%% BAND %d is not a valid GSM band%s",
@ -834,7 +870,7 @@ DEFUN(cfg_bts_bsic,
int bsic = atoi(argv[0]);
if (bsic < 0 || bsic > 0x3f) {
vty_out(vty, "%% TSC %d is not in the valid range (0-255)%s",
vty_out(vty, "%% BSIC %d is not in the valid range (0-255)%s",
bsic, VTY_NEWLINE);
return CMD_WARNING;
}
@ -875,6 +911,31 @@ DEFUN(cfg_bts_unit_id,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_oml_e1,
cfg_bts_oml_e1_cmd,
"oml e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
"E1 interface to be used for OML\n")
{
struct gsm_bts *bts = vty->index;
parse_e1_link(&bts->oml_e1_link, argv[0], argv[1], argv[2]);
return CMD_SUCCESS;
}
DEFUN(cfg_bts_oml_e1_tei,
cfg_bts_oml_e1_tei_cmd,
"oml e1 tei <0-63>",
"Set the TEI to be used for OML")
{
struct gsm_bts *bts = vty->index;
bts->oml_tei = atoi(argv[0]);
return CMD_SUCCESS;
}
/* per TRX configuration */
DEFUN(cfg_trx,
cfg_trx_cmd,
@ -951,10 +1012,35 @@ DEFUN(cfg_trx_max_power_red,
return CMD_SUCCESS;
}
DEFUN(cfg_trx_rsl_e1,
cfg_trx_rsl_e1_cmd,
"rsl e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
"E1 interface to be used for RSL\n")
{
struct gsm_bts_trx *trx = vty->index;
parse_e1_link(&trx->rsl_e1_link, argv[0], argv[1], argv[2]);
return CMD_SUCCESS;
}
DEFUN(cfg_trx_rsl_e1_tei,
cfg_trx_rsl_e1_tei_cmd,
"rsl e1 tei <0-63>",
"Set the TEI to be used for RSL")
{
struct gsm_bts_trx *trx = vty->index;
trx->rsl_tei = atoi(argv[0]);
return CMD_SUCCESS;
}
/* per TS configuration */
DEFUN(cfg_ts,
cfg_ts_cmd,
"timeslot TS_NR",
"timeslot <0-7>",
"Select a Timeslot to configure")
{
int ts_nr = atoi(argv[0]);
@ -994,14 +1080,12 @@ DEFUN(cfg_ts_pchan,
DEFUN(cfg_ts_e1_subslot,
cfg_ts_e1_subslot_cmd,
"e1_subslot E1_IF <1-31> <0-4>",
"e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
"E1 sub-slot connected to this on-air timeslot")
{
struct gsm_bts_trx_ts *ts = vty->index;
ts->e1_link.e1_nr = atoi(argv[0]);
ts->e1_link.e1_ts = atoi(argv[1]);
ts->e1_link.e1_ts_ss = atoi(argv[2]);
parse_e1_link(&ts->e1_link, argv[0], argv[1], argv[2]);
return CMD_SUCCESS;
}
@ -1158,6 +1242,7 @@ int bsc_vty_init(struct gsm_network *net)
install_element(CONFIG_NODE, &cfg_net_cmd);
install_node(&net_node, config_write_net);
install_default(GSMNET_NODE);
install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
@ -1169,13 +1254,18 @@ int bsc_vty_init(struct gsm_network *net)
install_element(BTS_NODE, &cfg_bts_band_cmd);
install_element(BTS_NODE, &cfg_bts_lac_cmd);
install_element(BTS_NODE, &cfg_bts_tsc_cmd);
install_element(BTS_NODE, &cfg_bts_bsic_cmd);
install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
install_element(BTS_NODE, &cfg_bts_oml_e1_cmd);
install_element(BTS_NODE, &cfg_bts_oml_e1_tei_cmd);
install_element(BTS_NODE, &cfg_trx_cmd);
install_node(&trx_node, dummy_config_write);
install_default(TRX_NODE);
install_element(TRX_NODE, &cfg_trx_arfcn_cmd);
install_element(TRX_NODE, &cfg_trx_max_power_red_cmd);
install_element(TRX_NODE, &cfg_trx_rsl_e1_cmd);
install_element(TRX_NODE, &cfg_trx_rsl_e1_tei_cmd);
install_element(TRX_NODE, &cfg_ts_cmd);
install_node(&ts_node, dummy_config_write);