From ad38464728cf1503258288ee9d64600c8adf38ba Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 26 Dec 2008 10:20:07 +0000 Subject: [PATCH] this is the first version that actually talks to the BTS * initialize OML and RSL based on TEI establish (ACTIVATE_IND) events * fix abis_nm_raw_msg() to not overwrite the OML header with payload * fix debug print statements * fix msgb_dequeue: actually dequeue it from the list ;) --- include/openbsc/debug.h | 6 ++-- include/openbsc/gsm_data.h | 10 +++++- include/openbsc/msgb.h | 8 ++--- src/abis_nm.c | 16 +++++++--- src/abis_rsl.c | 4 +-- src/bsc_hack.c | 44 ++++++++++++++++++++------ src/misdn.c | 64 +++++++++++++++++++++++++++++--------- src/msgb.c | 3 +- 8 files changed, 115 insertions(+), 40 deletions(-) diff --git a/include/openbsc/debug.h b/include/openbsc/debug.h index 41953a362..02ae699c4 100644 --- a/include/openbsc/debug.h +++ b/include/openbsc/debug.h @@ -12,9 +12,11 @@ #define DMI 0x1000 #ifdef DEBUG -#define DEBUGP(ss, args...) debugp(ss, __FILE__, __LINE__, ## args) +#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, fmt, ## args) #else -#define DEBUGP(xss, args, ...) +#define DEBUGP(xss, fmt, args...) #endif +void debugp(int subsys, char *file, int line, const char *format, ...); + #endif /* _DEBUG_H */ diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h index 8bb219a11..75de2e72f 100644 --- a/include/openbsc/gsm_data.h +++ b/include/openbsc/gsm_data.h @@ -126,5 +126,13 @@ struct gsm_call { /* the 'local' subscriber */ struct gsm_subscriber *subscr; }; - + +enum gsm_e1_event { + EVT_E1_NONE, + EVT_E1_OML_UP, + EVT_E1_RSL_UP, + EVT_E1_OML_DN, + EVT_E1_RSL_DN, +}; + #endif diff --git a/include/openbsc/msgb.h b/include/openbsc/msgb.h index 13631e7bc..cfb912135 100644 --- a/include/openbsc/msgb.h +++ b/include/openbsc/msgb.h @@ -34,8 +34,8 @@ struct msgb { struct gsm_bts_trx *trx; struct gsm_lchan *lchan; - u_int8_t l2_off; - u_int8_t l3_off; + unsigned char *l2h; + unsigned char *l3h; u_int16_t data_len; u_int16_t len; @@ -51,8 +51,8 @@ extern void msgb_free(struct msgb *m); extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg); extern struct msgb *msgb_dequeue(struct llist_head *queue); -#define msgb_l2(m) ((void *)(m->data + m->l2_off)) -#define msgb_l3(m) ((void *)(m->data + m->l3_off)) +#define msgb_l2(m) ((void *)(m->l2h)) +#define msgb_l3(m) ((void *)(m->l3h)) static inline unsigned int msgb_headlen(const struct msgb *msgb) { diff --git a/src/abis_nm.c b/src/abis_nm.c index bf442fa43..e1a641b53 100644 --- a/src/abis_nm.c +++ b/src/abis_nm.c @@ -138,7 +138,7 @@ static struct msgb *nm_msgb_alloc(void) /* Send a OML NM Message from BSC to BTS */ int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg) { - /* FIXME */ + return _abis_nm_sendmsg(msg); } /* Receive a OML NM Message from BTS */ @@ -149,10 +149,12 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) /* check for unsolicited message */ if (is_report(mt)) { - nmh->cfg->report_cb(mb, foh); + DEBUGP(DNM, "reporting NM MT 0x%02x\n", mt); + //nmh->cfg->report_cb(mb, foh); return 0; } +#if 0 /* check if last message is to be acked */ if (is_ack_nack(nmh->last_msgtype)) { if (mt == MT_ACK(nmh->last_msgtype)) { @@ -169,6 +171,9 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) return -EINVAL; } } +#endif + + return 0; } /* High-Level API */ @@ -198,7 +203,7 @@ int abis_nm_rcvmsg(struct msgb *msg) if (oh->length + sizeof(*oh) < l2_len) fprintf(stderr, "ABIS OML message with extra trailer?!?\n"); - msg->l3_off = ((unsigned char *)oh + sizeof(*oh)) - msg->head; + msg->l3h = (unsigned char *)oh + sizeof(*oh); switch (oh->mdisc) { case ABIS_OM_MDISC_FOM: @@ -213,6 +218,7 @@ int abis_nm_rcvmsg(struct msgb *msg) return -EINVAL; } + msgb_free(msg); return rc; } @@ -389,7 +395,7 @@ int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *rawmsg) oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(*oh)); fill_om_hdr(oh, len); data = msgb_put(msg, len); - memcpy(msg->data, rawmsg, len); + memcpy(data, rawmsg, len); return abis_nm_sendmsg(bts, msg); } @@ -420,7 +426,7 @@ int abis_nm_reset_resource(struct gsm_bts *bts) return __simple_cmd(bts, 0x74); } -int abis_nm_db_transaction(struct gsm_bts *bts, int begin) +int abis_nm_db_transmission(struct gsm_bts *bts, int begin) { if (begin) return __simple_cmd(bts, 0xA3); diff --git a/src/abis_rsl.c b/src/abis_rsl.c index ad90dea90..257b118b2 100644 --- a/src/abis_rsl.c +++ b/src/abis_rsl.c @@ -618,13 +618,13 @@ static int abis_rsl_rx_rll(struct msgb *msg) case RSL_MT_DATA_IND: DEBUGP(DRLL, "DATA INDICATION\n"); /* FIXME: Verify L3 info element */ - msg->l3_off = &rllh->data[2] - msg->data; + msg->l3h = &rllh->data[2]; rc = gsm0408_rcvmsg(msg); break; case RSL_MT_EST_IND: DEBUGP(DRLL, "ESTABLISH INDICATION\n"); /* FIXME: Verify L3 info element */ - msg->l3_off = &rllh->data[2] - msg->data; + msg->l3h = &rllh->data[2]; rc = gsm0408_rcvmsg(msg); break; case RSL_MT_ERROR_IND: diff --git a/src/bsc_hack.c b/src/bsc_hack.c index 253826af0..b0d726573 100644 --- a/src/bsc_hack.c +++ b/src/bsc_hack.c @@ -25,8 +25,10 @@ #include #include #include +#include #include +#include #include #include @@ -242,6 +244,8 @@ static void bootstrap_om(struct gsm_bts *bts) { struct gsm_bts_trx *trx = &bts->trx[0]; + fprintf(stdout, "bootstrapping OML\n"); + /* stop sending event reports */ abis_nm_event_reports(bts, 0); @@ -510,6 +514,8 @@ static int set_system_infos(struct gsm_bts *bts) } rsl_sacch_filling(bts, RSL_SYSTEM_INFO_5, si5, sizeof(si5)); rsl_sacch_filling(bts, RSL_SYSTEM_INFO_6, si6, sizeof(si6)); + + return 0; } static void activate_traffic_channels(struct gsm_bts_trx *trx) @@ -521,28 +527,47 @@ static void activate_traffic_channels(struct gsm_bts_trx *trx) rsl_chan_activate_tch_f(&trx->ts[i]); } -static void bootstrap_bts(struct gsm_bts *bts) +static void bootstrap_rsl(struct gsm_bts *bts) { - bootstrap_om(bts); - + fprintf(stdout, "bootstrapping RSL\n"); set_system_infos(bts); /* FIXME: defer this until the channels are used */ activate_traffic_channels(&bts->trx[0]); } -static void bootstrap_network() +static void mi_cb(int event, struct gsm_bts *bts) +{ + switch (event) { + case EVT_E1_OML_UP: + bootstrap_om(bts); + break; + case EVT_E1_RSL_UP: + bootstrap_rsl(bts); + break; + default: + /* FIXME: deal with TEI or L1 link loss */ + break; + } +} + +static int bootstrap_network(void) { struct gsm_bts *bts; /* initialize our data structures */ gsmnet = gsm_network_init(1, 1, 1); + if (!gsmnet) + return -ENOMEM; + bts = &gsmnet->bts[0]; bts->location_area_code = 1; bts->trx[0].arfcn = HARDCODED_ARFCN; - /* initialize the BTS */ - bootstrap_bts(&gsmnet->bts[0]); + if (mi_setup(bts, 0, mi_cb) < 0) + return -EIO; + + return 0; } void debugp(int subsys, char *file, int line, const char *format, ...) @@ -558,16 +583,15 @@ void debugp(int subsys, char *file, int line, const char *format, ...) timestr = ctime(&tm); timestr[strlen(timestr)-1] = '\0'; fprintf(outfd, "%s <%4.4x> %s:%d ", timestr, subsys, file, line); - vsprintf(outfd, format, ap); + vfprintf(outfd, format, ap); + va_end(ap); + fflush(outfd); } int main(int argc, char **argv) { - if (mi_setup() < 0) - exit(1); - bootstrap_network(); while (1) { diff --git a/src/misdn.c b/src/misdn.c index 8f9aed8b1..10a92d137 100644 --- a/src/misdn.c +++ b/src/misdn.c @@ -57,6 +57,7 @@ struct mi_e1_handle { struct llist_head rsl_tx_list; struct llist_head oml_tx_list; + void (*cb)(int event, struct gsm_bts *bts); struct bsc_fd fd[NUM_E1_TS]; }; @@ -65,7 +66,7 @@ static struct mi_e1_handle *global_e1h; #define SAPI_L2ML 0 #define SAPI_OML 62 -#define SAPI_RSL 63 +#define SAPI_RSL 0 /* 63 ? */ #define TEI_L2ML 127 #define TEI_OML 25 @@ -149,17 +150,32 @@ static int handle_ts1_read(struct bsc_fd *bfd) DEBUGP(DMI, "got DL_ESTABLISH_CNF\n"); break; case DL_RELEASE_IND: - DEBUGP(DMI, "got DL_RELEASE_IND\n"); + DEBUGP(DMI, "got DL_RELEASE_IND: E1 Layer 1 disappeared?\n"); break; case MPH_ACTIVATE_IND: DEBUGP(DMI, "got MPH_ACTIVATE_IND\n"); + if (l2addr.tei == TEI_OML && l2addr.sapi == SAPI_OML) + e1h->cb(EVT_E1_OML_UP, e1h->bts); + else if (l2addr.tei == TEI_RSL && l2addr.sapi == SAPI_RSL) + e1h->cb(EVT_E1_RSL_UP, e1h->bts); break; case MPH_DEACTIVATE_IND: - DEBUGP(DMI, "got MPH_DEACTIVATE_IND\n"); + DEBUGP(DMI, "got MPH_DEACTIVATE_IND: TEI link closed?\n"); + if (l2addr.tei == TEI_OML && l2addr.sapi == SAPI_OML) + e1h->cb(EVT_E1_OML_DN, e1h->bts); + else if (l2addr.tei == TEI_RSL && l2addr.sapi == SAPI_RSL) + e1h->cb(EVT_E1_RSL_DN, e1h->bts); + break; break; case DL_DATA_IND: DEBUGP(DMI, "got DL_DATA_IND\n"); - msg->l2_off = MISDN_HEADER_LEN; + + /* FIXME: this stinks */ + msg->trx = e1h->bts->c0; + + msg->l2h = msg->data + MISDN_HEADER_LEN; + + fprintf(stdout, "RX: "); hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN); switch (l2addr.tei) { case TEI_OML: @@ -185,31 +201,44 @@ static int handle_ts1_write(struct bsc_fd *bfd) struct mi_e1_handle *e1h = bfd->data; struct msgb *msg; struct mISDNhead *hh; - int ret, no_rsl = 0; + int ret, no_oml = 0; - msg = msgb_dequeue(&e1h->rsl_tx_list); + msg = msgb_dequeue(&e1h->oml_tx_list); if (!msg) - no_rsl = 1; + no_oml = 1; else { + u_int8_t *l2_data = msg->data; + /* prepend the mISDNhead */ hh = (struct mISDNhead *) msgb_push(msg, sizeof(*hh)); hh->prim = DL_DATA_REQ; + fprintf(stdout, "OML TX: "); + hexdump(l2_data, msg->len - MISDN_HEADER_LEN); + ret = sendto(bfd->fd, msg->data, msg->len, 0, (struct sockaddr *)&e1h->l2addr, sizeof(e1h->l2addr)); msgb_free(msg); usleep(100000); + /* we always dequeue all OML messages */ + return ret; } + msg = msgb_dequeue(&e1h->rsl_tx_list); if (!msg) { - if (no_rsl) + if (no_oml) bfd->when &= ~BSC_FD_WRITE; } else { + u_int8_t *l2_data = msg->data; + /* prepend the mISDNhead */ hh = (struct mISDNhead *) msgb_push(msg, sizeof(*hh)); hh->prim = DL_DATA_REQ; + fprintf(stdout, "RSL TX: "); + hexdump(l2_data, msg->len - MISDN_HEADER_LEN); + ret = sendto(bfd->fd, msg->data, msg->len, 0, (struct sockaddr *)&e1h->omladdr, sizeof(e1h->omladdr)); @@ -258,16 +287,18 @@ int abis_rsl_sendmsg(struct msgb *msg) { struct mi_e1_handle *e1h = global_e1h; + msg->l2h = msg->data; msgb_enqueue(&e1h->rsl_tx_list, msg); e1h->fd[0].when |= BSC_FD_WRITE; return 0; } -int abis_nm_sendmsg(struct msgb *msg) +int _abis_nm_sendmsg(struct msgb *msg) { struct mi_e1_handle *e1h = global_e1h; + msg->l2h = msg->data; msgb_enqueue(&e1h->oml_tx_list, msg); e1h->fd[0].when |= BSC_FD_WRITE; @@ -292,13 +323,14 @@ static int mi_e1_setup(struct mi_e1_handle *e1h) close(sk); return -ENODEV; } - DEBUGP(DMI,"%d device%s found\n", cnt, (cnt==1)?"":"s"); -#if 0 - devinfo.id = di->cardnr; + //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; ret = ioctl(sk, IMGETDEVINFO, &devinfo); if (ret < 0) { fprintf(stdout, "error getting info for device %d: %s\n", - di->cardnr, strerror(errno)); + e1h->cardnr, strerror(errno)); return -ENODEV; } fprintf(stdout, " id: %d\n", devinfo.id); @@ -320,7 +352,7 @@ static int mi_e1_setup(struct mi_e1_handle *e1h) bfd->cb = misdn_fd_cb; if (ts == 1) { - bfd->fd = socket(PF_ISDN, SOCK_RAW, ISDN_P_LAPD_NT); + bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_NT); bfd->when = BSC_FD_READ; } else bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW); @@ -360,7 +392,8 @@ static int mi_e1_setup(struct mi_e1_handle *e1h) return 0; } -int mi_setup(struct gsm_bts *bts, int cardnr) +int mi_setup(struct gsm_bts *bts, int cardnr, + void (cb)(int event, struct gsm_bts *bts)) { struct mi_e1_handle *e1h; @@ -369,6 +402,7 @@ int mi_setup(struct gsm_bts *bts, int cardnr) e1h->cardnr = cardnr; e1h->bts = bts; + e1h->cb = cb; INIT_LLIST_HEAD(&e1h->oml_tx_list); INIT_LLIST_HEAD(&e1h->rsl_tx_list); diff --git a/src/msgb.c b/src/msgb.c index f5330c38b..249fed9b6 100644 --- a/src/msgb.c +++ b/src/msgb.c @@ -62,6 +62,7 @@ struct msgb *msgb_dequeue(struct llist_head *queue) return NULL; lh = queue->next; - + llist_del(lh); + return llist_entry(lh, struct msgb, list); }