diff --git a/openbsc/include/openbsc/e1_input.h b/openbsc/include/openbsc/e1_input.h index 132672364..1e8da56fe 100644 --- a/openbsc/include/openbsc/e1_input.h +++ b/openbsc/include/openbsc/e1_input.h @@ -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); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 663c8698b..8af07816f 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -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; diff --git a/openbsc/include/openbsc/talloc.h b/openbsc/include/openbsc/talloc.h index a4b33c3ed..f7f7643b8 100644 --- a/openbsc/include/openbsc/talloc.h +++ b/openbsc/include/openbsc/talloc.h @@ -29,6 +29,8 @@ #include #include +#define HAVE_VA_COPY + /* this is only needed for compatibility with the old talloc */ typedef void TALLOC_CTX; diff --git a/openbsc/include/vty/command.h b/openbsc/include/vty/command.h index 1be05aa8e..21fb6a1af 100644 --- a/openbsc/include/vty/command.h +++ b/openbsc/include/vty/command.h @@ -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 diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c index 9e0a26096..0759f2626 100644 --- a/openbsc/src/bsc_hack.c +++ b/openbsc/src/bsc_hack.c @@ -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; diff --git a/openbsc/src/e1_config.c b/openbsc/src/e1_config.c index 898780374..e7431327b 100644 --- a/openbsc/src/e1_config.c +++ b/openbsc/src/e1_config.c @@ -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) diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c index 7531755c2..4bc15e5f7 100644 --- a/openbsc/src/e1_input.c +++ b/openbsc/src/e1_input.c @@ -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) diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index 370c41097..edf1b3d05 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -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: diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c index cee53cc13..05786dab4 100644 --- a/openbsc/src/input/ipaccess.c +++ b/openbsc/src/input/ipaccess.c @@ -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) diff --git a/openbsc/src/input/misdn.c b/openbsc/src/input/misdn.c index 2ec74b8ea..bd655d12e 100644 --- a/openbsc/src/input/misdn.c +++ b/openbsc/src/input/misdn.c @@ -49,12 +49,6 @@ #include #include -/* 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) diff --git a/openbsc/src/vty/command.c b/openbsc/src/vty/command.c index 16e0dfb36..f03dcbb4e 100644 --- a/openbsc/src/vty/command.c +++ b/openbsc/src/vty/command.c @@ -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; diff --git a/openbsc/src/vty/vty.c b/openbsc/src/vty/vty.c index 5472fa05a..b403a7b2c 100644 --- a/openbsc/src/vty/vty.c +++ b/openbsc/src/vty/vty.c @@ -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) diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 45b2c7469..b4aa9f4f5 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -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);