* add abis_nm_software_load_status() to header file

* new abis_nm_bs11_bsc_disconnect() function to disconnect BSC/BTS link
* add support for 'forced load' of BS-11 software to abis_nm.c and bs11_config
* remove lots of debug output
* print progress during software load
This commit is contained in:
Harald Welte 2009-02-01 22:15:49 +00:00
parent c12d52bae4
commit 3ffd1376b7
3 changed files with 87 additions and 31 deletions

View File

@ -461,7 +461,9 @@ int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *msg);
int abis_nm_event_reports(struct gsm_bts *bts, int on); int abis_nm_event_reports(struct gsm_bts *bts, int on);
int abis_nm_reset_resource(struct gsm_bts *bts); int abis_nm_reset_resource(struct gsm_bts *bts);
int abis_nm_software_load(struct gsm_bts *bts, const char *fname, int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
u_int8_t win_size, gsm_cbfn *cbfn, void *cb_data); u_int8_t win_size, int forced,
gsm_cbfn *cbfn, void *cb_data);
int abis_nm_software_load_status(struct gsm_bts *bts);
int abis_nm_software_activate(struct gsm_bts *bts, const char *fname, int abis_nm_software_activate(struct gsm_bts *bts, const char *fname,
gsm_cbfn *cbfn, void *cb_data); gsm_cbfn *cbfn, void *cb_data);
@ -480,7 +482,8 @@ int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on);
int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password); int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password);
int abis_nm_bs11_get_state(struct gsm_bts *bts); int abis_nm_bs11_get_state(struct gsm_bts *bts);
int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname, int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
u_int8_t win_size, gsm_cbfn *cbfn); u_int8_t win_size, int forced, gsm_cbfn *cbfn);
int abis_nm_bs11_set_ext_time(struct gsm_bts *bts); int abis_nm_bs11_set_ext_time(struct gsm_bts *bts);
int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect);
#endif /* _NM_H */ #endif /* _NM_H */

View File

@ -296,6 +296,7 @@ struct abis_nm_sw {
struct gsm_bts *bts; struct gsm_bts *bts;
gsm_cbfn *cbfn; gsm_cbfn *cbfn;
void *cb_data; void *cb_data;
int forced;
/* this will become part of the SW LOAD INITIATE */ /* this will become part of the SW LOAD INITIATE */
u_int8_t obj_class; u_int8_t obj_class;
@ -518,7 +519,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
struct abis_nm_sw *sw = &g_sw; struct abis_nm_sw *sw = &g_sw;
enum sw_state old_state = sw->state; enum sw_state old_state = sw->state;
DEBUGP(DNM, "state %u, NM MT 0x%02x\n", sw->state, foh->msg_type); //DEBUGP(DNM, "state %u, NM MT 0x%02x\n", sw->state, foh->msg_type);
switch (sw->state) { switch (sw->state) {
case SW_STATE_WAIT_INITACK: case SW_STATE_WAIT_INITACK:
@ -533,18 +534,33 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
sw->state = SW_STATE_WAIT_SEGACK; sw->state = SW_STATE_WAIT_SEGACK;
break; break;
case NM_MT_LOAD_INIT_NACK: case NM_MT_LOAD_INIT_NACK:
DEBUGP(DNM, "Software Load Init NACK\n"); if (sw->forced) {
if (sw->cbfn) DEBUGP(DNM, "FORCED: Ignoring Software Load "
sw->cbfn(GSM_HOOK_NM_SWLOAD, "Init NACK\n");
NM_MT_LOAD_INIT_NACK, mb, if (sw->cbfn)
sw->cb_data, NULL); sw->cbfn(GSM_HOOK_NM_SWLOAD,
sw->state = SW_STATE_ERROR; NM_MT_LOAD_INIT_ACK, mb,
sw->cb_data, NULL);
rc = sw_fill_window(sw);
sw->state = SW_STATE_WAIT_SEGACK;
} else {
DEBUGP(DNM, "Software Load Init NACK\n");
if (sw->cbfn)
sw->cbfn(GSM_HOOK_NM_SWLOAD,
NM_MT_LOAD_INIT_NACK, mb,
sw->cb_data, NULL);
sw->state = SW_STATE_ERROR;
}
break; break;
} }
break; break;
case SW_STATE_WAIT_SEGACK: case SW_STATE_WAIT_SEGACK:
switch (foh->msg_type) { switch (foh->msg_type) {
case NM_MT_LOAD_SEG_ACK: case NM_MT_LOAD_SEG_ACK:
if (sw->cbfn)
sw->cbfn(GSM_HOOK_NM_SWLOAD,
NM_MT_LOAD_SEG_ACK, mb,
sw->cb_data, NULL);
sw->seg_in_window = 0; sw->seg_in_window = 0;
if (!sw->last_seg) { if (!sw->last_seg) {
/* fill window with more segments */ /* fill window with more segments */
@ -614,7 +630,8 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
/* Load the specified software into the BTS */ /* Load the specified software into the BTS */
int abis_nm_software_load(struct gsm_bts *bts, const char *fname, int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
u_int8_t win_size, gsm_cbfn *cbfn, void *cb_data) u_int8_t win_size, int forced,
gsm_cbfn *cbfn, void *cb_data)
{ {
struct abis_nm_sw *sw = &g_sw; struct abis_nm_sw *sw = &g_sw;
int rc; int rc;
@ -634,6 +651,7 @@ int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
sw->state = SW_STATE_WAIT_INITACK; sw->state = SW_STATE_WAIT_INITACK;
sw->cbfn = cbfn; sw->cbfn = cbfn;
sw->cb_data = cb_data; sw->cb_data = cb_data;
sw->forced = forced;
rc = sw_open_file(sw, fname); rc = sw_open_file(sw, fname);
if (rc < 0) { if (rc < 0) {
@ -835,8 +853,17 @@ int abis_nm_event_reports(struct gsm_bts *bts, int on)
return __simple_cmd(bts, NM_MT_REST_EVENT_REP); return __simple_cmd(bts, NM_MT_REST_EVENT_REP);
} }
/* Siemens (or BS-11) specific commands */ /* Siemens (or BS-11) specific commands */
int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect)
{
if (reconnect == 0)
return __simple_cmd(bts, NM_MT_BS11_DISCONNECT);
else
return __simple_cmd(bts, NM_MT_BS11_RECONNECT);
}
struct bs11_date_time { struct bs11_date_time {
u_int16_t year; u_int16_t year;
u_int8_t month; u_int8_t month;
@ -1022,6 +1049,7 @@ struct abis_nm_bs11_sw {
struct gsm_bts *bts; struct gsm_bts *bts;
char swl_fname[PATH_MAX]; char swl_fname[PATH_MAX];
u_int8_t win_size; u_int8_t win_size;
int forced;
struct llist_head file_list; struct llist_head file_list;
gsm_cbfn *user_cb; /* specified by the user */ gsm_cbfn *user_cb; /* specified by the user */
}; };
@ -1070,7 +1098,7 @@ static int bs11_read_swl_file(struct abis_nm_bs11_sw *bs11_sw)
if (strlen(linebuf) < 4) if (strlen(linebuf) < 4)
continue; continue;
printf("linebuf='%s'\n", linebuf);
rc = sscanf(linebuf+4, "%12s:%80s\r\n", file_id, file_version); rc = sscanf(linebuf+4, "%12s:%80s\r\n", file_id, file_version);
if (rc < 0) { if (rc < 0) {
perror("ERR parsing SWL file"); perror("ERR parsing SWL file");
@ -1092,7 +1120,6 @@ static int bs11_read_swl_file(struct abis_nm_bs11_sw *bs11_sw)
strncat(fle->fname, dirname(dir), sizeof(fle->fname) - 1); strncat(fle->fname, dirname(dir), sizeof(fle->fname) - 1);
strcat(fle->fname, "/"); strcat(fle->fname, "/");
strncat(fle->fname, file_id, sizeof(fle->fname) - 1 -strlen(fle->fname)); strncat(fle->fname, file_id, sizeof(fle->fname) - 1 -strlen(fle->fname));
printf("fname='%s'\n", fle->fname);
llist_add_tail(&fle->list, &bs11_sw->file_list); llist_add_tail(&fle->list, &bs11_sw->file_list);
} }
@ -1110,8 +1137,6 @@ static int bs11_swload_cbfn(unsigned int hook, unsigned int event,
struct file_list_entry *fle; struct file_list_entry *fle;
int rc = 0; int rc = 0;
printf("bs11_swload_cbfn(%u, %u, %p, %p, %p)\n", hook, event, msg, data, param);
switch (event) { switch (event) {
case NM_MT_LOAD_END_ACK: case NM_MT_LOAD_END_ACK:
fle = fl_dequeue(&bs11_sw->file_list); fle = fl_dequeue(&bs11_sw->file_list);
@ -1119,6 +1144,7 @@ static int bs11_swload_cbfn(unsigned int hook, unsigned int event,
/* start download the next file of our file list */ /* start download the next file of our file list */
rc = abis_nm_software_load(bs11_sw->bts, fle->fname, rc = abis_nm_software_load(bs11_sw->bts, fle->fname,
bs11_sw->win_size, bs11_sw->win_size,
bs11_sw->forced,
&bs11_swload_cbfn, bs11_sw); &bs11_swload_cbfn, bs11_sw);
free(fle); free(fle);
} else { } else {
@ -1129,6 +1155,7 @@ static int bs11_swload_cbfn(unsigned int hook, unsigned int event,
bs11_sw); bs11_sw);
} }
break; break;
case NM_MT_LOAD_SEG_ACK:
case NM_MT_LOAD_END_NACK: case NM_MT_LOAD_END_NACK:
case NM_MT_LOAD_INIT_ACK: case NM_MT_LOAD_INIT_ACK:
case NM_MT_LOAD_INIT_NACK: case NM_MT_LOAD_INIT_NACK:
@ -1147,7 +1174,7 @@ static int bs11_swload_cbfn(unsigned int hook, unsigned int event,
* files that are part of a software release. We need to upload first * files that are part of a software release. We need to upload first
* the list file, and then each file that is listed in the list file */ * the list file, and then each file that is listed in the list file */
int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname, int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
u_int8_t win_size, gsm_cbfn *cbfn) u_int8_t win_size, int forced, gsm_cbfn *cbfn)
{ {
struct abis_nm_bs11_sw *bs11_sw = g_bs11_sw; struct abis_nm_bs11_sw *bs11_sw = g_bs11_sw;
struct file_list_entry *fle; struct file_list_entry *fle;
@ -1157,6 +1184,7 @@ int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
bs11_sw->bts = bts; bs11_sw->bts = bts;
bs11_sw->win_size = win_size; bs11_sw->win_size = win_size;
bs11_sw->user_cb = cbfn; bs11_sw->user_cb = cbfn;
bs11_sw->forced = forced;
strncpy(bs11_sw->swl_fname, fname, sizeof(bs11_sw->swl_fname)); strncpy(bs11_sw->swl_fname, fname, sizeof(bs11_sw->swl_fname));
rc = bs11_read_swl_file(bs11_sw); rc = bs11_read_swl_file(bs11_sw);
@ -1169,7 +1197,7 @@ int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
return -EINVAL; return -EINVAL;
/* start download the next file of our file list */ /* start download the next file of our file list */
rc = abis_nm_software_load(bts, fle->fname, win_size, rc = abis_nm_software_load(bts, fle->fname, win_size, forced,
bs11_swload_cbfn, bs11_sw); bs11_swload_cbfn, bs11_sw);
free(fle); free(fle);
return rc; return rc;

View File

@ -92,9 +92,8 @@ static int create_trx1_objects(struct gsm_bts *bts)
} }
/* create all objects for an initial configuration */ /* create all objects for an initial configuration */
static int create_objects(struct gsm_bts *bts, int trx1) static int create_objects(struct gsm_bts *bts)
{ {
//abis_nm_bs11_factory_logon(bts, 1);
abis_nm_bs11_create_object(bts, BS11_OBJ_LI, 0, sizeof(obj_li_attr), abis_nm_bs11_create_object(bts, BS11_OBJ_LI, 0, sizeof(obj_li_attr),
obj_li_attr); obj_li_attr);
abis_nm_bs11_create_object(bts, BS11_OBJ_GPSU, 0, 0, NULL); abis_nm_bs11_create_object(bts, BS11_OBJ_GPSU, 0, 0, NULL);
@ -113,7 +112,6 @@ static int create_objects(struct gsm_bts *bts, int trx1)
abis_nm_bs11_set_oml_tei(bts, TEI_OML); abis_nm_bs11_set_oml_tei(bts, TEI_OML);
abis_nm_bs11_set_trx_power(&bts->trx[0], BS11_TRX_POWER_GSM_30mW); abis_nm_bs11_set_trx_power(&bts->trx[0], BS11_TRX_POWER_GSM_30mW);
//abis_nm_bs11_factory_logon(bts, 0);
return 0; return 0;
} }
@ -124,6 +122,8 @@ static char *fname_software = "HS011106.SWL";
static int delay_ms = 0; static int delay_ms = 0;
static int have_trx1 = 0; static int have_trx1 = 0;
static int win_size = 8; static int win_size = 8;
static int param_disconnect = 0;
static int param_forced = 0;
static struct gsm_bts *g_bts; static struct gsm_bts *g_bts;
static int file_is_readable(const char *fname) static int file_is_readable(const char *fname)
@ -141,6 +141,9 @@ static int file_is_readable(const char *fname)
return 0; return 0;
} }
static int percent;
static int percent_old;
/* callback function passed to the ABIS OML code */ /* callback function passed to the ABIS OML code */
static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg, static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg,
void *data, void *param) void *data, void *param)
@ -173,6 +176,12 @@ static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg,
case NM_MT_ACTIVATE_SW_ACK: case NM_MT_ACTIVATE_SW_ACK:
bs11cfg_state = STATE_NONE; bs11cfg_state = STATE_NONE;
break;
case NM_MT_LOAD_SEG_ACK:
percent = abis_nm_software_load_status(g_bts);
if (percent > percent_old)
printf("Software Download Progress: %d%%\n", percent);
percent_old = percent;
break; break;
} }
return 0; return 0;
@ -278,8 +287,8 @@ static int handle_state_resp(enum abis_bs11_phase state)
* a safety load from a regular software */ * a safety load from a regular software */
if (file_is_readable(fname_safety)) if (file_is_readable(fname_safety))
rc = abis_nm_software_load(g_bts, fname_safety, rc = abis_nm_software_load(g_bts, fname_safety,
win_size, swload_cbfn, win_size, param_forced,
g_bts); swload_cbfn, g_bts);
else else
fprintf(stderr, "No valid Safety Load file \"%s\"\n", fprintf(stderr, "No valid Safety Load file \"%s\"\n",
fname_safety); fname_safety);
@ -287,17 +296,20 @@ static int handle_state_resp(enum abis_bs11_phase state)
case BS11_STATE_WAIT_MIN_CFG: case BS11_STATE_WAIT_MIN_CFG:
case BS11_STATE_WAIT_MIN_CFG_2: case BS11_STATE_WAIT_MIN_CFG_2:
bs11cfg_state = STATE_SWLOAD; bs11cfg_state = STATE_SWLOAD;
rc = create_objects(g_bts, have_trx1); rc = create_objects(g_bts);
break; break;
case BS11_STATE_MAINTENANCE: case BS11_STATE_MAINTENANCE:
bs11cfg_state = STATE_SWLOAD; if (bs11cfg_state != STATE_SWLOAD) {
/* send software (FIXME: over A-bis?) */ bs11cfg_state = STATE_SWLOAD;
if (file_is_readable(fname_software)) /* send software (FIXME: over A-bis?) */
rc = abis_nm_bs11_load_swl(g_bts, fname_software, if (file_is_readable(fname_software))
win_size, swload_cbfn); rc = abis_nm_bs11_load_swl(g_bts, fname_software,
else win_size, param_forced,
fprintf(stderr, "No valid Software file \"%s\"\n", swload_cbfn);
fname_software); else
fprintf(stderr, "No valid Software file \"%s\"\n",
fname_software);
}
break; break;
case BS11_STATE_NORMAL: case BS11_STATE_NORMAL:
if (have_trx1) if (have_trx1)
@ -389,7 +401,9 @@ static void print_help(void)
printf("\t-s --software <file>\t\tSpecify Software file\n"); printf("\t-s --software <file>\t\tSpecify Software file\n");
printf("\t-S --safety <file>\t\tSpecify Safety Load file\n"); printf("\t-S --safety <file>\t\tSpecify Safety Load file\n");
printf("\t-d --delay <file>\t\tSpecify delay\n"); printf("\t-d --delay <file>\t\tSpecify delay\n");
printf("\t-D --disconnect\t\t\tDisconnect BTS from BSC\n");
printf("\t-w --win-size <num>\t\tSpecify Window Size\n"); printf("\t-w --win-size <num>\t\tSpecify Window Size\n");
printf("\t-f --forced\t\t\tForce Software Load\n");
} }
static void handle_options(int argc, char **argv) static void handle_options(int argc, char **argv)
@ -405,10 +419,12 @@ static void handle_options(int argc, char **argv)
{ "software", 1, 0, 's' }, { "software", 1, 0, 's' },
{ "safety", 1, 0, 'S' }, { "safety", 1, 0, 'S' },
{ "delay", 1, 0, 'd' }, { "delay", 1, 0, 'd' },
{ "disconnect", 0, 0, 'D' },
{ "win-size", 1, 0, 'w' }, { "win-size", 1, 0, 'w' },
{ "forced", 0, 0, 'f' },
}; };
c = getopt_long(argc, argv, "hp:s:S:td:w:", c = getopt_long(argc, argv, "hp:s:S:td:Dw:f",
long_options, &option_index); long_options, &option_index);
if (c == -1) if (c == -1)
@ -436,6 +452,12 @@ static void handle_options(int argc, char **argv)
case 'w': case 'w':
win_size = atoi(optarg); win_size = atoi(optarg);
break; break;
case 'D':
param_disconnect = 1;
break;
case 'f':
param_forced = 1;
break;
default: default:
break; break;
} }
@ -474,6 +496,9 @@ int main(int argc, char **argv)
abis_nm_bs11_factory_logon(g_bts, 1); abis_nm_bs11_factory_logon(g_bts, 1);
//abis_nm_bs11_get_serno(g_bts); //abis_nm_bs11_get_serno(g_bts);
if (param_disconnect)
abis_nm_bs11_bsc_disconnect(g_bts, 0);
while (1) { while (1) {
bsc_select_main(); bsc_select_main();
} }