aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc
diff options
context:
space:
mode:
authorKirill Zakharenko <earwin@gmail.com>2020-05-01 18:49:56 +0300
committerKirill Zakharenko <earwin@gmail.com>2020-05-01 18:49:56 +0300
commitf51f0bcef9e4d66c5bf4a4563762cf3b38861c1c (patch)
treea83b9be3ac029e1e3d8fd78755d693eca2fa37d6 /src/osmo-bsc
parentd7a64773bbd0f8bc98a55311a6b44108ac3b74d5 (diff)
parent74632859941d51a4f645d844cbb58709a8473443 (diff)
Merge master into fairwaves/production
Diffstat (limited to 'src/osmo-bsc')
-rw-r--r--src/osmo-bsc/abis_nm.c97
-rw-r--r--src/osmo-bsc/abis_nm_vty.c2
-rw-r--r--src/osmo-bsc/abis_om2000.c41
-rw-r--r--src/osmo-bsc/bsc_vty.c207
-rw-r--r--src/osmo-bsc/gsm_data.c4
-rw-r--r--src/osmo-bsc/osmo_bsc_bssap.c26
-rw-r--r--src/osmo-bsc/osmo_bsc_main.c26
-rw-r--r--src/osmo-bsc/osmo_bsc_vty.c4
-rw-r--r--src/osmo-bsc/rest_octets.c9
-rw-r--r--src/osmo-bsc/system_information.c11
10 files changed, 328 insertions, 99 deletions
diff --git a/src/osmo-bsc/abis_nm.c b/src/osmo-bsc/abis_nm.c
index 7ca4e7983..32e9a8faf 100644
--- a/src/osmo-bsc/abis_nm.c
+++ b/src/osmo-bsc/abis_nm.c
@@ -353,37 +353,92 @@ static inline void handle_manufact_report(struct gsm_bts *bts, const uint8_t *p_
};
}
-static int rx_fail_evt_rep(struct msgb *mb, struct gsm_bts *bts)
+/* Parse into newly allocated struct abis_nm_fail_evt_rep, caller must free it. */
+struct nm_fail_rep_signal_data *abis_nm_fail_evt_rep_parse(struct msgb *mb, struct gsm_bts *bts)
{
struct abis_om_hdr *oh = msgb_l2(mb);
struct abis_om_fom_hdr *foh = msgb_l3(mb);
- struct e1inp_sign_link *sign_link = mb->dst;
- struct tlv_parsed tp;
- int rc = 0;
+ struct nm_fail_rep_signal_data *sd;
const uint8_t *p_val = NULL;
char *p_text = NULL;
const char *e_type = NULL, *severity = NULL;
- abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data,
- oh->length-sizeof(*foh));
+ sd = talloc_zero(tall_bsc_ctx, struct nm_fail_rep_signal_data);
+ OSMO_ASSERT(sd);
+
+ if (abis_nm_tlv_parse(&sd->tp, bts, foh->data, oh->length-sizeof(*foh)) < 0)
+ goto fail;
- if (TLVP_PRESENT(&tp, NM_ATT_ADD_TEXT)) {
- const uint8_t *val = TLVP_VAL(&tp, NM_ATT_ADD_TEXT);
- p_text = talloc_strndup(tall_bsc_ctx, (const char *) val,
- TLVP_LEN(&tp, NM_ATT_ADD_TEXT));
+ if (TLVP_PRESENT(&sd->tp, NM_ATT_ADD_TEXT)) {
+ const uint8_t *val = TLVP_VAL(&sd->tp, NM_ATT_ADD_TEXT);
+ p_text = talloc_strndup(sd, (const char *) val, TLVP_LEN(&sd->tp, NM_ATT_ADD_TEXT));
}
- if (TLVP_PRESENT(&tp, NM_ATT_EVENT_TYPE))
- e_type = abis_nm_event_type_name(*TLVP_VAL(&tp,
- NM_ATT_EVENT_TYPE));
+ if (TLVP_PRESENT(&sd->tp, NM_ATT_EVENT_TYPE))
+ e_type = abis_nm_event_type_name(*TLVP_VAL(&sd->tp, NM_ATT_EVENT_TYPE));
+
+ if (TLVP_PRESENT(&sd->tp, NM_ATT_SEVERITY))
+ severity = abis_nm_severity_name(*TLVP_VAL(&sd->tp, NM_ATT_SEVERITY));
+
+ if (TLVP_PRESENT(&sd->tp, NM_ATT_PROB_CAUSE))
+ p_val = TLVP_VAL(&sd->tp, NM_ATT_PROB_CAUSE);
+
+ sd->bts = bts;
+ sd->msg = mb;
+ if (e_type)
+ sd->parsed.event_type = e_type;
+ else
+ sd->parsed.event_type = talloc_strdup(sd, "<none>");
+ if (severity)
+ sd->parsed.severity = severity;
+ else
+ sd->parsed.severity = talloc_strdup(sd, "<none>");
+ if (p_text)
+ sd->parsed.additional_text = p_text;
+ else
+ sd->parsed.additional_text = talloc_strdup(sd, "<none>");
+ sd->parsed.probable_cause = p_val;
- if (TLVP_PRESENT(&tp, NM_ATT_SEVERITY))
- severity = abis_nm_severity_name(*TLVP_VAL(&tp,
- NM_ATT_SEVERITY));
+ return sd;
+fail:
+ talloc_free(sd);
+ return NULL;
+}
- if (TLVP_PRESENT(&tp, NM_ATT_PROB_CAUSE)) {
- p_val = TLVP_VAL(&tp, NM_ATT_PROB_CAUSE);
+static int rx_fail_evt_rep(struct msgb *mb, struct gsm_bts *bts)
+{
+ struct abis_om_fom_hdr *foh = msgb_l3(mb);
+ struct nm_fail_rep_signal_data *sd;
+ int rc = 0;
+ const uint8_t *p_val;
+ const char *e_type, *severity, *p_text;
+ struct bts_oml_fail_rep *entry;
+
+ /* Store copy in bts->oml_fail_rep */
+ entry = talloc_zero(bts, struct bts_oml_fail_rep);
+ OSMO_ASSERT(entry);
+ entry->time = time(NULL);
+ entry->mb = msgb_copy_c(entry, mb, "OML failure report");
+ llist_add(&entry->list, &bts->oml_fail_rep);
+
+ /* Limit list size */
+ if (llist_count(&bts->oml_fail_rep) > 50) {
+ struct bts_oml_fail_rep *old = llist_last_entry(&bts->oml_fail_rep, struct bts_oml_fail_rep, list);
+ llist_del(&old->list);
+ talloc_free(old);
+ }
+
+ sd = abis_nm_fail_evt_rep_parse(mb, bts);
+ if (!sd) {
+ LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: failed to parse Failure Event Report\n", bts->nr);
+ return -EINVAL;
+ }
+ e_type = sd->parsed.event_type;
+ severity = sd->parsed.severity;
+ p_text = sd->parsed.additional_text;
+ p_val = sd->parsed.probable_cause;
+ if (p_val) {
switch (p_val[0]) {
case NM_PCAUSE_T_MANUF:
handle_manufact_report(bts, p_val, e_type, severity,
@@ -398,9 +453,8 @@ static int rx_fail_evt_rep(struct msgb *mb, struct gsm_bts *bts)
rc = -EINVAL;
}
- if (p_text)
- talloc_free(p_text);
-
+ osmo_signal_dispatch(SS_NM, S_NM_FAIL_REP, sd);
+ talloc_free(sd);
return rc;
}
@@ -419,7 +473,6 @@ static int abis_nm_rcvmsg_report(struct msgb *mb, struct gsm_bts *bts)
break;
case NM_MT_FAILURE_EVENT_REP:
rx_fail_evt_rep(mb, bts);
- osmo_signal_dispatch(SS_NM, S_NM_FAIL_REP, mb);
break;
case NM_MT_TEST_REP:
DEBUGPFOH(DNM, foh, "Test Report\n");
diff --git a/src/osmo-bsc/abis_nm_vty.c b/src/osmo-bsc/abis_nm_vty.c
index b1c6d56d2..fe467fad1 100644
--- a/src/osmo-bsc/abis_nm_vty.c
+++ b/src/osmo-bsc/abis_nm_vty.c
@@ -165,7 +165,7 @@ DEFUN(oml_chg_adm_state, oml_chg_adm_state_cmd,
}
DEFUN(oml_opstart, oml_opstart_cmd,
- "opstart", "Send an OPSTART message to the object")
+ "opstart", "Send an OPSTART message to the object\n")
{
struct oml_node_state *oms = vty->index;
diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c
index 14c373b17..f8efa3990 100644
--- a/src/osmo-bsc/abis_om2000.c
+++ b/src/osmo-bsc/abis_om2000.c
@@ -202,6 +202,26 @@ enum abis_om2k_msgtype {
OM2K_MSGT_NEGOT_REQ_ACK = 0x0104,
OM2K_MSGT_NEGOT_REQ_NACK = 0x0105,
OM2K_MSGT_NEGOT_REQ = 0x0106,
+
+ OM2K_MSGT_BTS_INITIATED_REQ_ACK = 0x0108,
+ OM2K_MSGT_BTS_INITIATED_REQ_NACK = 0x0109,
+ OM2K_MSGT_BTS_INITIATED_REQ = 0x010a,
+
+ OM2K_MSGT_RADIO_CHAN_REL_CMD = 0x010c,
+ OM2K_MSGT_RADIO_CHAN_REL_COMPL = 0x010e,
+ OM2K_MSGT_RADIO_CHAN_REL_REJ = 0x010f,
+
+ OM2K_MSGT_FEATURE_CTRL_CMD = 0x0118,
+ OM2K_MSGT_FEATURE_CTRL_COMPL = 0x011a,
+ OM2K_MSGT_FEATURE_CTRL_REJ = 0x011b,
+
+ OM2K_MSGT_MCTR_CONFIG_REQ = 0x012c,
+ OM2K_MSGT_MCTR_CONFIG_REQ_ACK = 0x012e,
+ OM2K_MSGT_MCTR_CONFIG_REQ_REJ = 0x012f,
+
+ OM2K_MSGT_MCTR_CONFIG_RES_ACK = 0x0130,
+ OM2K_MSGT_MCTR_CONFIG_RES_NACK = 0x0131,
+ OM2K_MSGT_MCTR_CONFIG_RES = 0x0132,
};
enum abis_om2k_dei {
@@ -272,6 +292,13 @@ enum abis_om2k_dei {
OM2K_DEI_FS_OFFSET = 0x98,
OM2K_DEI_EXT_COND_MAP_2_EXT = 0x9c,
OM2K_DEI_TSS_MO_STATE = 0x9d,
+ OM2K_DEI_CONFIG_TYPE = 0x9e,
+ OM2K_DEI_JITTER_SIZE = 0x9f,
+ OM2K_DEI_PACKING_ALGO = 0xa0,
+ OM2K_DEI_TRXC_LIST = 0xa8,
+ OM2K_DEI_MAX_ALLOWED_POWER = 0xa9,
+ OM2K_DEI_MAX_ALLOWED_NUM_TRXCS = 0xaa,
+ OM2K_DEI_MCTR_FEAT_STATUS_BMAP = 0xab,
};
const struct tlv_definition om2k_att_tlvdef = {
@@ -521,6 +548,12 @@ static const struct value_string om2k_msgcode_vals[] = {
{ 0x0118, "Feature Control Command" },
{ 0x011a, "Feature Control Complete" },
{ 0x011b, "Feature Control Reject" },
+ { 0x012c, "MCTR Configuration Request" },
+ { 0x012e, "MCTR Configuration Request Accept" },
+ { 0x012f, "MCTR Configuration Request Reject" },
+ { 0x0130, "MCTR Configuration Result ACK" },
+ { 0x0131, "MCTR Configuration Result NACK" },
+ { 0x0132, "MCTR Configuration Result" },
{ 0, NULL }
};
@@ -653,6 +686,13 @@ static const struct value_string om2k_attr_vals[] = {
{ 0x9b, "Master TX Chain Delay" },
{ 0x9c, "External Condition Class 2 Extension" },
{ 0x9d, "TSs MO State" },
+ { 0x9e, "Configuration Type" },
+ { 0x9f, "Jitter Size" },
+ { 0xa0, "Packing Algorithm" },
+ { 0xa8, "TRXC List" },
+ { 0xa9, "Maximum Allowed Power" },
+ { 0xaa, "Maximum Allowed Number of TRXCs" },
+ { 0xab, "MCTR Feature Status Bitmap" },
{ 0, NULL }
};
@@ -663,6 +703,7 @@ const struct value_string om2k_mo_class_short_vals[] = {
{ 0x05, "IS" },
{ 0x06, "CON" },
{ 0x07, "DP" },
+ { 0x08, "MCTR" },
{ 0x0a, "CF" },
{ 0x0b, "TX" },
{ 0x0c, "RX" },
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 1195d6580..f8bcee9a7 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -536,7 +536,7 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
DEFUN(show_bts, show_bts_cmd, "show bts [<0-255>]",
SHOW_STR "Display information about a BTS\n"
- "BTS number")
+ "BTS number\n")
{
struct gsm_network *net = gsmnet_from_vty(vty);
int bts_nr;
@@ -559,6 +559,67 @@ DEFUN(show_bts, show_bts_cmd, "show bts [<0-255>]",
return CMD_SUCCESS;
}
+DEFUN(show_bts_fail_rep, show_bts_fail_rep_cmd, "show bts <0-255> fail-rep [reset]",
+ SHOW_STR "Display information about a BTS\n"
+ "BTS number\n" "OML failure reports\n"
+ "Clear the list of failure reports after showing them\n")
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+ struct bts_oml_fail_rep *entry;
+ struct gsm_bts *bts;
+ int bts_nr;
+
+ bts_nr = atoi(argv[0]);
+ if (bts_nr >= net->num_bts) {
+ vty_out(vty, "%% can't find BTS '%s'%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ bts = gsm_bts_num(net, bts_nr);
+ if (llist_empty(&bts->oml_fail_rep)) {
+ vty_out(vty, "No failure reports received.%s", VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ llist_for_each_entry(entry, &bts->oml_fail_rep, list) {
+ struct nm_fail_rep_signal_data *sd;
+ char timestamp[20]; /* format like 2020-03-23 14:24:00 */
+ enum abis_nm_pcause_type pcause;
+ enum abis_mm_event_causes cause;
+
+ strftime(timestamp, sizeof(timestamp), "%F %T", localtime(&entry->time));
+ sd = abis_nm_fail_evt_rep_parse(entry->mb, bts);
+ if (!sd) {
+ vty_out(vty, "[%s] (failed to parse report)%s", timestamp, VTY_NEWLINE);
+ continue;
+ }
+ pcause = sd->parsed.probable_cause[0];
+ cause = osmo_load16be(sd->parsed.probable_cause + 1);
+
+ vty_out(vty, "[%s] Type=%s, Severity=%s, ", timestamp, sd->parsed.event_type, sd->parsed.severity);
+ vty_out(vty, "Probable cause=%s: ", get_value_string(abis_nm_pcause_type_names, pcause));
+ if (pcause == NM_PCAUSE_T_MANUF)
+ vty_out(vty, "%s, ", get_value_string(abis_mm_event_cause_names, cause));
+ else
+ vty_out(vty, "%04X, ", cause);
+ vty_out(vty, "Additional text=%s%s", sd->parsed.additional_text, VTY_NEWLINE);
+
+ talloc_free(sd);
+ }
+
+ /* Optionally clear the list */
+ if (argc > 1) {
+ while (!llist_empty(&bts->oml_fail_rep)) {
+ struct bts_oml_fail_rep *old = llist_last_entry(&bts->oml_fail_rep, struct bts_oml_fail_rep,
+ list);
+ llist_del(&old->list);
+ talloc_free(old);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN(show_rejected_bts, show_rejected_bts_cmd, "show rejected-bts",
SHOW_STR "Display recently rejected BTS devices\n")
{
@@ -675,9 +736,6 @@ static void config_write_bts_gprs(struct vty *vty, struct gsm_bts *bts)
if (bts->gprs.mode == BTS_GPRS_NONE)
return;
- vty_out(vty, " gprs 11bit_rach_support_for_egprs %u%s",
- bts->gprs.supports_egprs_11bit_rach, VTY_NEWLINE);
-
vty_out(vty, " gprs routing area %u%s", bts->gprs.rac,
VTY_NEWLINE);
vty_out(vty, " gprs network-control-order nc%u%s",
@@ -711,6 +769,12 @@ static void config_write_bts_gprs(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, " gprs nsvc %u remote ip %s%s", i,
inet_ntoa(ia), VTY_NEWLINE);
}
+
+ /* EGPRS specific parameters */
+ if (bts->gprs.mode == BTS_GPRS_EGPRS) {
+ if (bts->gprs.egprs_pkt_chan_request)
+ vty_out(vty, " gprs egprs-packet-channel-request%s", VTY_NEWLINE);
+ }
}
/* Write the model data if there is one */
@@ -1062,8 +1126,6 @@ static int config_write_net(struct vty *vty)
ho_vty_write_net(vty, gsmnet);
- osmo_tdef_vty_write(vty, gsmnet->T_defs, " ");
-
if (!gsmnet->dyn_ts_allow_tch_f)
vty_out(vty, " dyn_ts_allow_tch_f 0%s", VTY_NEWLINE);
if (gsmnet->tz.override != 0) {
@@ -1094,6 +1156,9 @@ static int config_write_net(struct vty *vty)
meas_scenario, VTY_NEWLINE);
}
+ if (gsmnet->allow_unusable_timeslots)
+ vty_out(vty, " allow-unusable-timeslots%s", VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -2498,7 +2563,7 @@ DEFUN(cfg_bts_ccch_load_ind_thresh,
"ccch load-indication-threshold <0-100>",
CCCH_STR
"Percentage of CCCH load at which BTS sends RSL CCCH LOAD IND\n"
- "CCCH Load Threshold in percent (Default: 10)")
+ "CCCH Load Threshold in percent (Default: 10)\n")
{
struct gsm_bts *bts = vty->index;
bts->ccch_load_ind_thresh = atoi(argv[0]);
@@ -2513,7 +2578,7 @@ DEFUN(cfg_bts_rach_nm_b_thresh,
RACH_STR NM_STR
"Set the NM Busy Threshold\n"
"Set the NM Busy Threshold\n"
- "NM Busy Threshold in dB")
+ "NM Busy Threshold in dB\n")
{
struct gsm_bts *bts = vty->index;
bts->rach_b_thresh = atoi(argv[0]);
@@ -2617,7 +2682,7 @@ DEFUN(cfg_bts_ms_max_power, cfg_bts_ms_max_power_cmd,
"MS Options\n"
"Maximum transmit power of the MS\n"
"Maximum transmit power of the MS\n"
- "Maximum transmit power of the MS in dBm")
+ "Maximum transmit power of the MS in dBm\n")
{
struct gsm_bts *bts = vty->index;
@@ -2632,7 +2697,7 @@ DEFUN(cfg_bts_cell_resel_hyst, cfg_bts_cell_resel_hyst_cmd,
"cell reselection hysteresis <0-14>",
CELL_STR "Cell re-selection parameters\n"
"Cell Re-Selection Hysteresis in dB\n"
- "Cell Re-Selection Hysteresis in dB")
+ "Cell Re-Selection Hysteresis in dB\n")
{
struct gsm_bts *bts = vty->index;
@@ -2646,7 +2711,7 @@ DEFUN(cfg_bts_rxlev_acc_min, cfg_bts_rxlev_acc_min_cmd,
"Minimum RxLev needed for cell access\n"
"Minimum RxLev needed for cell access\n"
"Minimum RxLev needed for cell access\n"
- "Minimum RxLev needed for cell access (better than -110dBm)")
+ "Minimum RxLev needed for cell access (better than -110dBm)\n")
{
struct gsm_bts *bts = vty->index;
@@ -2687,7 +2752,7 @@ DEFUN(cfg_bts_temp_ofs, cfg_bts_temp_ofs_cmd,
"temporary offset <0-60>",
"Cell selection temporary negative offset\n"
"Cell selection temporary negative offset\n"
- "Cell selection temporary negative offset in dB")
+ "Cell selection temporary negative offset in dB\n")
{
struct gsm_bts *bts = vty->index;
@@ -2701,7 +2766,7 @@ DEFUN(cfg_bts_temp_ofs_inf, cfg_bts_temp_ofs_inf_cmd,
"temporary offset infinite",
"Cell selection temporary negative offset\n"
"Cell selection temporary negative offset\n"
- "Sets cell selection temporary negative offset to infinity")
+ "Sets cell selection temporary negative offset to infinity\n")
{
struct gsm_bts *bts = vty->index;
@@ -2731,7 +2796,7 @@ DEFUN(cfg_bts_penalty_time_rsvd, cfg_bts_penalty_time_rsvd_cmd,
"Cell selection penalty time\n"
"Set cell selection penalty time to reserved value 31, "
"(indicate that CELL_RESELECT_OFFSET is subtracted from C2 "
- "and TEMPORARY_OFFSET is ignored)")
+ "and TEMPORARY_OFFSET is ignored)\n")
{
struct gsm_bts *bts = vty->index;
@@ -2778,7 +2843,7 @@ DEFUN(cfg_bts_prs_bvci, cfg_bts_gprs_bvci_cmd,
GPRS_TEXT
"GPRS Cell Settings\n"
"GPRS BSSGP VC Identifier\n"
- "GPRS BSSGP VC Identifier")
+ "GPRS BSSGP VC Identifier\n")
{
/* ETSI TS 101 343: values 0 and 1 are reserved for signalling and PTM */
struct gsm_bts *bts = vty->index;
@@ -2797,7 +2862,7 @@ DEFUN(cfg_bts_gprs_nsei, cfg_bts_gprs_nsei_cmd,
"gprs nsei <0-65535>",
GPRS_TEXT
"GPRS NS Entity Identifier\n"
- "GPRS NS Entity Identifier")
+ "GPRS NS Entity Identifier\n")
{
struct gsm_bts *bts = vty->index;
@@ -2818,7 +2883,7 @@ DEFUN(cfg_bts_gprs_nsvci, cfg_bts_gprs_nsvci_cmd,
"gprs nsvc <0-1> nsvci <0-65535>",
GPRS_TEXT NSVC_TEXT
"NS Virtual Connection Identifier\n"
- "GPRS NS VC Identifier")
+ "GPRS NS VC Identifier\n")
{
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
@@ -3064,29 +3129,65 @@ DEFUN(cfg_bts_gprs_mode, cfg_bts_gprs_mode_cmd,
return CMD_SUCCESS;
}
-DEFUN(cfg_bts_gprs_11bit_rach_support_for_egprs,
+DEFUN_DEPRECATED(cfg_bts_gprs_11bit_rach_support_for_egprs,
cfg_bts_gprs_11bit_rach_support_for_egprs_cmd,
"gprs 11bit_rach_support_for_egprs (0|1)",
- GPRS_TEXT "11 bit RACH options\n"
- "Disable 11 bit RACH for EGPRS\n"
- "Enable 11 bit RACH for EGPRS")
+ GPRS_TEXT "EGPRS Packet Channel Request support\n"
+ "Disable EGPRS Packet Channel Request support\n"
+ "Enable EGPRS Packet Channel Request support\n")
{
struct gsm_bts *bts = vty->index;
- bts->gprs.supports_egprs_11bit_rach = atoi(argv[0]);
+ vty_out(vty, "%% 'gprs 11bit_rach_support_for_egprs' is now deprecated: "
+ "use '[no] gprs egprs-packet-channel-request' instead%s", VTY_NEWLINE);
+
+ bts->gprs.egprs_pkt_chan_request = (argv[0][0] == '1');
- if (bts->gprs.supports_egprs_11bit_rach > 1) {
- vty_out(vty, "Error in RACH type%s", VTY_NEWLINE);
+ if (bts->gprs.mode == BTS_GPRS_NONE && bts->gprs.egprs_pkt_chan_request) {
+ vty_out(vty, "%% (E)GPRS is not enabled (see 'gprs mode')%s", VTY_NEWLINE);
return CMD_WARNING;
}
- if ((bts->gprs.mode == BTS_GPRS_NONE) &&
- (bts->gprs.supports_egprs_11bit_rach == 1)) {
- vty_out(vty, "Error:gprs mode is none and 11bit rach is"
- " enabled%s", VTY_NEWLINE);
+ if (bts->gprs.mode != BTS_GPRS_EGPRS) {
+ vty_out(vty, "%% EGPRS Packet Channel Request support requires "
+ "EGPRS mode to be enabled (see 'gprs mode')%s", VTY_NEWLINE);
+ /* Do not return here, keep the old behaviour. */
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_gprs_egprs_pkt_chan_req,
+ cfg_bts_gprs_egprs_pkt_chan_req_cmd,
+ "gprs egprs-packet-channel-request",
+ GPRS_TEXT "EGPRS Packet Channel Request support")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (bts->gprs.mode != BTS_GPRS_EGPRS) {
+ vty_out(vty, "%% EGPRS Packet Channel Request support requires "
+ "EGPRS mode to be enabled (see 'gprs mode')%s", VTY_NEWLINE);
return CMD_WARNING;
}
+ bts->gprs.egprs_pkt_chan_request = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_no_gprs_egprs_pkt_chan_req,
+ cfg_bts_no_gprs_egprs_pkt_chan_req_cmd,
+ "no gprs egprs-packet-channel-request",
+ NO_STR GPRS_TEXT "EGPRS Packet Channel Request support")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (bts->gprs.mode != BTS_GPRS_EGPRS) {
+ vty_out(vty, "%% EGPRS Packet Channel Request support requires "
+ "EGPRS mode to be enabled (see 'gprs mode')%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ bts->gprs.egprs_pkt_chan_request = false;
return CMD_SUCCESS;
}
@@ -3719,7 +3820,7 @@ DEFUN(cfg_bts_no_depends_on, cfg_bts_no_depends_on_cmd,
#define AMR_TH_TEXT "AMR threshold between codecs\nMS side\nBTS side\n"
#define AMR_HY_TEXT "AMR hysteresis between codecs\nMS side\nBTS side\n"
-static void get_amr_from_arg(struct vty *vty, int argc, const char *argv[], int full)
+static int get_amr_from_arg(struct vty *vty, int argc, const char *argv[], int full)
{
struct gsm_bts *bts = vty->index;
struct amr_multirate_conf *mr = (full) ? &bts->mr_full: &bts->mr_half;
@@ -3735,12 +3836,12 @@ static void get_amr_from_arg(struct vty *vty, int argc, const char *argv[], int
if (mode_prev > mode) {
vty_out(vty, "Modes must be listed in order%s",
VTY_NEWLINE);
- return;
+ return -1;
}
if (mode_prev == mode) {
vty_out(vty, "Modes must be unique %s", VTY_NEWLINE);
- return;
+ return -2;
}
mode_prev = mode;
}
@@ -3765,6 +3866,7 @@ static void get_amr_from_arg(struct vty *vty, int argc, const char *argv[], int
mr->ms_mode[i].hysteresis = 0;
mr->bts_mode[i].hysteresis = 0;
}
+ return 0;
}
static void get_amr_th_from_arg(struct vty *vty, int argc, const char *argv[], int full)
@@ -3880,7 +3982,8 @@ DEFUN(cfg_bts_amr_fr_modes1, cfg_bts_amr_fr_modes1_cmd,
AMR_TEXT "Full Rate\n" AMR_MODE_TEXT
AMR_TCHF_HELP_STR)
{
- get_amr_from_arg(vty, 1, argv, 1);
+ if (get_amr_from_arg(vty, 1, argv, 1))
+ return CMD_WARNING;
return check_amr_config(vty);
}
@@ -3889,7 +3992,8 @@ DEFUN(cfg_bts_amr_fr_modes2, cfg_bts_amr_fr_modes2_cmd,
AMR_TEXT "Full Rate\n" AMR_MODE_TEXT
AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR)
{
- get_amr_from_arg(vty, 2, argv, 1);
+ if (get_amr_from_arg(vty, 2, argv, 1))
+ return CMD_WARNING;
return check_amr_config(vty);
}
@@ -3898,7 +4002,8 @@ DEFUN(cfg_bts_amr_fr_modes3, cfg_bts_amr_fr_modes3_cmd,
AMR_TEXT "Full Rate\n" AMR_MODE_TEXT
AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR)
{
- get_amr_from_arg(vty, 3, argv, 1);
+ if (get_amr_from_arg(vty, 3, argv, 1))
+ return CMD_WARNING;
return check_amr_config(vty);
}
@@ -3907,7 +4012,8 @@ DEFUN(cfg_bts_amr_fr_modes4, cfg_bts_amr_fr_modes4_cmd,
AMR_TEXT "Full Rate\n" AMR_MODE_TEXT
AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR)
{
- get_amr_from_arg(vty, 4, argv, 1);
+ if (get_amr_from_arg(vty, 4, argv, 1))
+ return CMD_WARNING;
return check_amr_config(vty);
}
@@ -3978,7 +4084,8 @@ DEFUN(cfg_bts_amr_hr_modes1, cfg_bts_amr_hr_modes1_cmd,
AMR_TEXT "Half Rate\n" AMR_MODE_TEXT
AMR_TCHH_HELP_STR)
{
- get_amr_from_arg(vty, 1, argv, 0);
+ if (get_amr_from_arg(vty, 1, argv, 0))
+ return CMD_WARNING;
return check_amr_config(vty);
}
@@ -3987,7 +4094,8 @@ DEFUN(cfg_bts_amr_hr_modes2, cfg_bts_amr_hr_modes2_cmd,
AMR_TEXT "Half Rate\n" AMR_MODE_TEXT
AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR)
{
- get_amr_from_arg(vty, 2, argv, 0);
+ if (get_amr_from_arg(vty, 2, argv, 0))
+ return CMD_WARNING;
return check_amr_config(vty);
}
@@ -3996,7 +4104,8 @@ DEFUN(cfg_bts_amr_hr_modes3, cfg_bts_amr_hr_modes3_cmd,
AMR_TEXT "Half Rate\n" AMR_MODE_TEXT
AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR)
{
- get_amr_from_arg(vty, 3, argv, 0);
+ if (get_amr_from_arg(vty, 3, argv, 0))
+ return CMD_WARNING;
return check_amr_config(vty);
}
@@ -4005,7 +4114,8 @@ DEFUN(cfg_bts_amr_hr_modes4, cfg_bts_amr_hr_modes4_cmd,
AMR_TEXT "Half Rate\n" AMR_MODE_TEXT
AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR)
{
- get_amr_from_arg(vty, 4, argv, 0);
+ if (get_amr_from_arg(vty, 4, argv, 0))
+ return CMD_WARNING;
return check_amr_config(vty);
}
@@ -4129,8 +4239,8 @@ DEFUN(cfg_bts_no_t3113_dynamic, cfg_bts_no_t3113_dynamic_cmd,
DEFUN(cfg_trx,
cfg_trx_cmd,
"trx <0-255>",
- TRX_TEXT
- "Select a TRX to configure")
+ TRX_TEXT
+ "Select a TRX to configure\n")
{
int trx_nr = atoi(argv[0]);
struct gsm_bts *bts = vty->index;
@@ -5202,6 +5312,17 @@ DEFUN(cfg_net_timer, cfg_net_timer_cmd,
return osmo_tdef_vty_set_cmd(vty, net->T_defs, argv);
}
+DEFUN(cfg_net_allow_unusable_timeslots, cfg_net_allow_unusable_timeslots_cmd,
+ "allow-unusable-timeslots",
+ "Don't refuse to start with mutually exclusive codec settings\n")
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+ net->allow_unusable_timeslots = true;
+ LOGP(DMSC, LOGL_ERROR, "Configuration contains 'allow-unusable-timeslots'. OsmoBSC will start up even if the"
+ " configuration has unusable codec settings!\n");
+ return CMD_SUCCESS;
+}
+
extern int bsc_vty_init_extra(void);
int bsc_vty_init(struct gsm_network *network)
@@ -5247,9 +5368,11 @@ int bsc_vty_init(struct gsm_network *network)
install_element(GSMNET_NODE, &cfg_net_meas_feed_dest_cmd);
install_element(GSMNET_NODE, &cfg_net_meas_feed_scenario_cmd);
install_element(GSMNET_NODE, &cfg_net_timer_cmd);
+ install_element(GSMNET_NODE, &cfg_net_allow_unusable_timeslots_cmd);
install_element_ve(&bsc_show_net_cmd);
install_element_ve(&show_bts_cmd);
+ install_element_ve(&show_bts_fail_rep_cmd);
install_element_ve(&show_rejected_bts_cmd);
install_element_ve(&show_trx_cmd);
install_element_ve(&show_trx_con_cmd);
@@ -5329,6 +5452,8 @@ int bsc_vty_init(struct gsm_network *network)
install_element(BTS_NODE, &cfg_bts_radio_link_timeout_inf_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_mode_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_11bit_rach_support_for_egprs_cmd);
+ install_element(BTS_NODE, &cfg_bts_no_gprs_egprs_pkt_chan_req_cmd);
+ install_element(BTS_NODE, &cfg_bts_gprs_egprs_pkt_chan_req_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_ns_timer_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_rac_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_net_ctrl_ord_cmd);
diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c
index 1f19b4ebc..02541c7f3 100644
--- a/src/osmo-bsc/gsm_data.c
+++ b/src/osmo-bsc/gsm_data.c
@@ -807,6 +807,9 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num)
memcpy(&bts->gprs.cell.rlc_cfg, &rlc_cfg_default,
sizeof(bts->gprs.cell.rlc_cfg));
+ /* 3GPP TS 08.18, chapter 5.4.1: 0 is reserved for signalling */
+ bts->gprs.cell.bvci = 2;
+
/* init statistics */
bts->bts_ctrs = rate_ctr_group_alloc(bts, &bts_ctrg_desc, bts->nr);
if (!bts->bts_ctrs) {
@@ -878,6 +881,7 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num)
INIT_LLIST_HEAD(&bts->abis_queue);
INIT_LLIST_HEAD(&bts->loc_list);
INIT_LLIST_HEAD(&bts->local_neighbors);
+ INIT_LLIST_HEAD(&bts->oml_fail_rep);
/* Enable all codecs by default. These get reset to a more fine grained selection IF a
* 'codec-support' config appears in the config file (see bsc_vty.c). */
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index 74faae1bc..1ba490faa 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -568,20 +568,24 @@ reject:
static void bssmap_handle_ass_req_lcls(struct gsm_subscriber_connection *conn,
const struct tlv_parsed *tp)
{
- const uint8_t *config, *control, *gcr, gcr_len = TLVP_LEN(tp, GSM0808_IE_GLOBAL_CALL_REF);
-
- if (gcr_len > sizeof(conn->lcls.global_call_ref))
- LOGPFSML(conn->fi, LOGL_ERROR, "Global Call Ref IE of %u bytes is too long\n",
- gcr_len);
- else {
- gcr = TLVP_VAL_MINLEN(tp, GSM0808_IE_GLOBAL_CALL_REF, 13);
- if (gcr) {
+ const uint8_t *config, *control, *gcr;
+ uint8_t gcr_len;
+
+ /* TS 48.008 sec 3.2.2.115 Global Call Reference */
+ if (TLVP_PRESENT(tp, GSM0808_IE_GLOBAL_CALL_REF)) {
+ gcr = TLVP_VAL(tp, GSM0808_IE_GLOBAL_CALL_REF);
+ gcr_len = TLVP_LEN(tp, GSM0808_IE_GLOBAL_CALL_REF);
+ if (gcr_len > sizeof(conn->lcls.global_call_ref)) {
+ LOGPFSML(conn->fi, LOGL_ERROR, "Global Call Ref IE of %u bytes is too long: %s\n",
+ gcr_len, osmo_hexdump_nospc(gcr, gcr_len));
+ } else if (gcr_len < 13) { /* FIXME: document this magic value 13 */
+ LOGPFSML(conn->fi, LOGL_ERROR, "Global Call Ref IE of %u bytes is too short: %s\n",
+ gcr_len, osmo_hexdump_nospc(gcr, gcr_len));
+ } else {
LOGPFSM(conn->fi, "Setting GCR to %s\n", osmo_hexdump_nospc(gcr, gcr_len));
memcpy(&conn->lcls.global_call_ref, gcr, gcr_len);
conn->lcls.global_call_ref_len = gcr_len;
- } else
- LOGPFSML(conn->fi, LOGL_ERROR, "Global Call Ref IE of %u bytes is too short\n",
- gcr_len);
+ }
}
config = TLVP_VAL_MINLEN(tp, GSM0808_IE_LCLS_CONFIG, 1);
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index 6b1427903..ad5a3a9da 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -713,7 +713,7 @@ static const struct log_info_cat osmo_bsc_categories[] = {
.name = "DNM",
.description = "A-bis Network Management / O&M (NM/OML)",
.color = "\033[1;36m",
- .enabled = 1, .loglevel = LOGL_INFO,
+ .enabled = 1, .loglevel = LOGL_NOTICE,
},
[DPAG] = {
.name = "DPAG",
@@ -748,11 +748,6 @@ static const struct log_info_cat osmo_bsc_categories[] = {
.description = "Reference Counting",
.enabled = 0, .loglevel = LOGL_NOTICE,
},
- [DNAT] = {
- .name = "DNAT",
- .description = "GSM 08.08 NAT/Multiplexer",
- .enabled = 1, .loglevel = LOGL_NOTICE,
- },
[DCTRL] = {
.name = "DCTRL",
.description = "Control interface",
@@ -761,12 +756,12 @@ static const struct log_info_cat osmo_bsc_categories[] = {
[DFILTER] = {
.name = "DFILTER",
.description = "BSC/NAT IMSI based filtering",
- .enabled = 1, .loglevel = LOGL_DEBUG,
+ .enabled = 1, .loglevel = LOGL_NOTICE,
},
[DPCU] = {
.name = "DPCU",
.description = "PCU Interface",
- .enabled = 1, .loglevel = LOGL_DEBUG,
+ .enabled = 1, .loglevel = LOGL_NOTICE,
},
[DLCLS] = {
.name = "DLCLS",
@@ -850,6 +845,7 @@ int main(int argc, char **argv)
ctrl_vty_init(tall_bsc_ctx);
logging_vty_add_deprecated_subsys(tall_bsc_ctx, "cc");
logging_vty_add_deprecated_subsys(tall_bsc_ctx, "mgcp");
+ logging_vty_add_deprecated_subsys(tall_bsc_ctx, "nat");
/* Initialize SS7 */
OSMO_ASSERT(osmo_ss7_init() == 0);
@@ -902,12 +898,20 @@ int main(int argc, char **argv)
}
rc = check_codec_pref(&bsc_gsmnet->bsc_data->mscs);
- if (rc < 0)
- LOGP(DMSC, LOGL_ERROR, "Configuration contains mutually exclusive codec settings -- check configuration!\n");
+ if (rc < 0) {
+ LOGP(DMSC, LOGL_ERROR, "Configuration contains mutually exclusive codec settings -- check"
+ " configuration!\n");
+ if (!bsc_gsmnet->allow_unusable_timeslots) {
+ LOGP(DMSC, LOGL_ERROR, "You should really fix that! However, you can prevent OsmoBSC from"
+ " stopping here by setting 'allow-unusable-timeslots' in the 'network'"
+ " section of the config.\n");
+ exit(1);
+ }
+ }
llist_for_each_entry(msc, &bsc_gsmnet->bsc_data->mscs, entry) {
if (osmo_bsc_msc_init(msc) != 0) {
- LOGP(DNAT, LOGL_ERROR, "Failed to start up. Exiting.\n");
+ LOGP(DMSC, LOGL_ERROR, "Failed to start up. Exiting.\n");
exit(1);
}
}
diff --git a/src/osmo-bsc/osmo_bsc_vty.c b/src/osmo-bsc/osmo_bsc_vty.c
index e656d7079..c372b48ff 100644
--- a/src/osmo-bsc/osmo_bsc_vty.c
+++ b/src/osmo-bsc/osmo_bsc_vty.c
@@ -539,7 +539,7 @@ DEFUN(cfg_msc_acc_lst_name,
cfg_msc_acc_lst_name_cmd,
"access-list-name NAME",
"Set the name of the access list to use.\n"
- "The name of the to be used access list.")
+ "The name of the to be used access list.\n")
{
struct bsc_msc_data *msc = bsc_msc_data(vty);
@@ -792,7 +792,7 @@ DEFUN(cfg_bsc_acc_lst_name,
cfg_bsc_acc_lst_name_cmd,
"access-list-name NAME",
"Set the name of the access list to use.\n"
- "The name of the to be used access list.")
+ "The name of the to be used access list.\n")
{
struct osmo_bsc_data *bsc = osmo_bsc_data(vty);
diff --git a/src/osmo-bsc/rest_octets.c b/src/osmo-bsc/rest_octets.c
index 1d2279bf9..2238b088d 100644
--- a/src/osmo-bsc/rest_octets.c
+++ b/src/osmo-bsc/rest_octets.c
@@ -822,13 +822,8 @@ static int append_gprs_cell_opt(struct bitvec *bv,
/* EGPRS supported in the cell */
bitvec_set_bit(bv, 1);
- /* 1bit EGPRS PACKET CHANNEL REQUEST */
- if (gco->supports_egprs_11bit_rach == 0) {
- bitvec_set_bit(bv,
- gco->ext_info.use_egprs_p_ch_req);
- } else {
- bitvec_set_bit(bv, 0);
- }
+ /* 1bit EGPRS PACKET CHANNEL REQUEST (inverted logic) */
+ bitvec_set_bit(bv, !gco->ext_info.use_egprs_p_ch_req);
/* 4bit BEP PERIOD */
bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
diff --git a/src/osmo-bsc/system_information.c b/src/osmo-bsc/system_information.c
index 6e5841966..d5be3f2d7 100644
--- a/src/osmo-bsc/system_information.c
+++ b/src/osmo-bsc/system_information.c
@@ -1151,11 +1151,10 @@ static struct gsm48_si13_info si13_default = {
.bs_cv_max = 15,
.ctrl_ack_type_use_block = true,
.ext_info_present = 0,
- .supports_egprs_11bit_rach = 0,
.ext_info = {
/* The values below are just guesses ! */
.egprs_supported = 0,
- .use_egprs_p_ch_req = 1,
+ .use_egprs_p_ch_req = 0,
.bep_period = 5,
.pfc_supported = 0,
.dtm_supported = 0,
@@ -1197,8 +1196,12 @@ static int generate_si13(enum osmo_sysinfo_type t, struct gsm_bts *bts)
/* Information about the other SIs */
si13_default.bcch_change_mark = bts->bcch_change_mark;
- si13_default.cell_opts.supports_egprs_11bit_rach =
- bts->gprs.supports_egprs_11bit_rach;
+
+ /* Whether EGPRS capable MSs shall use EGPRS PACKET CHANNEL REQUEST */
+ if (bts->gprs.egprs_pkt_chan_request)
+ si13_default.cell_opts.ext_info.use_egprs_p_ch_req = 1;
+ else
+ si13_default.cell_opts.ext_info.use_egprs_p_ch_req = 0;
ret = rest_octets_si13(si13->rest_octets, &si13_default);
if (ret < 0)