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 ;)
This commit is contained in:
parent
3633a6daf9
commit
ad38464728
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -25,8 +25,10 @@
|
|||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/select.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
#include <openbsc/abis_nm.h>
|
||||
|
||||
|
@ -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) {
|
||||
|
|
64
src/misdn.c
64
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue