diff --git a/src/host/layer23/include/osmocom/Makefile.am b/src/host/layer23/include/osmocom/Makefile.am index 6014195c5..69b8d7ea4 100644 --- a/src/host/layer23/include/osmocom/Makefile.am +++ b/src/host/layer23/include/osmocom/Makefile.am @@ -1,3 +1,3 @@ # headers from OpenBSC noinst_HEADERS = debug.h -noinst_HEADERS += l1ctl.h osmocom_data.h lapdm.h rslms.h layer3.h +noinst_HEADERS += l1ctl.h osmocom_data.h lapdm.h rslms.h layer3.h gsmtap_util.h diff --git a/src/host/layer23/include/osmocom/gsmtap_util.h b/src/host/layer23/include/osmocom/gsmtap_util.h new file mode 100644 index 000000000..e9dc383aa --- /dev/null +++ b/src/host/layer23/include/osmocom/gsmtap_util.h @@ -0,0 +1,15 @@ +#ifndef _GSMTAP_UTIL_H +#define _GSMTAP_UTIL_H + +#include + +/* convert RSL channel number to GSMTAP channel type */ +uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t rsl_link_id); + +/* receive a message from L1/L2 and put it in GSMTAP */ +int gsmtap_sendmsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, uint8_t ss, + uint32_t fn, const uint8_t *data, unsigned int len); + +int gsmtap_init(uint32_t dst_ip); + +#endif /* _GSMTAP_UTIL_H */ diff --git a/src/host/layer23/src/gsmtap_util.c b/src/host/layer23/src/gsmtap_util.c index 0254c188e..3bbc39ce4 100644 --- a/src/host/layer23/src/gsmtap_util.c +++ b/src/host/layer23/src/gsmtap_util.c @@ -22,9 +22,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -36,17 +38,56 @@ #include #include -static struct bsc_fd gsmtap_bfd; +static struct bsc_fd gsmtap_bfd = { .fd = -1 }; static LLIST_HEAD(gsmtap_txqueue); +uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t link_id) +{ + uint8_t ret = GSMTAP_CHANNEL_UNKNOWN; + + switch (rsl_chantype) { + case RSL_CHAN_Bm_ACCHs: + ret = GSMTAP_CHANNEL_TCH_F; + break; + case RSL_CHAN_Lm_ACCHs: + ret = GSMTAP_CHANNEL_TCH_H; + break; + case RSL_CHAN_SDCCH4_ACCH: + ret = GSMTAP_CHANNEL_SDCCH4; + break; + case RSL_CHAN_SDCCH8_ACCH: + ret = GSMTAP_CHANNEL_SDCCH8; + break; + case RSL_CHAN_BCCH: + ret = GSMTAP_CHANNEL_BCCH; + break; + case RSL_CHAN_RACH: + ret = GSMTAP_CHANNEL_RACH; + break; + case RSL_CHAN_PCH_AGCH: + /* it could also be AGCH... */ + ret = GSMTAP_CHANNEL_PCH; + break; + } + + if (link_id & 0x40) + ret |= GSMTAP_CHANNEL_ACCH; + + return ret; +} + /* receive a message from L1/L2 and put it in GSMTAP */ -int gsmtap_sendmsg(uint8_t ts, uint16_t arfcn, uint32_t fn, - const uint8_t *data, unsigned int len) +int gsmtap_sendmsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, uint8_t ss, + uint32_t fn, const uint8_t *data, unsigned int len) { struct msgb *msg; struct gsmtap_hdr *gh; uint8_t *dst; + /* gsmtap was never initialized, so don't try to send anything */ + if (gsmtap_bfd.fd == -1) + return 0; + msg = msgb_alloc(sizeof(*gh) + len, "gsmtap_tx"); if (!msg) return -ENOMEM; @@ -57,11 +98,12 @@ int gsmtap_sendmsg(uint8_t ts, uint16_t arfcn, uint32_t fn, gh->hdr_len = sizeof(*gh)/4; gh->type = GSMTAP_TYPE_UM; gh->timeslot = ts; + gh->sub_slot = ss; gh->arfcn = htons(arfcn); - gh->noise_db = 0; - gh->signal_db = 0; + gh->snr_db = 0; + gh->signal_dbm = 0; gh->frame_number = htonl(fn); - gh->burst_type = GSMTAP_BURST_NORMAL; + gh->sub_type = chan_type; gh->antenna_nr = 0; dst = msgb_put(msg, len); @@ -104,14 +146,14 @@ static int gsmtap_fd_cb(struct bsc_fd *fd, unsigned int flags) return 0; } -int gsmtap_init(void) +int gsmtap_init(uint32_t dst_ip) { int rc; struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(GSMTAP_UDP_PORT); - inet_aton("127.0.0.1", &sin.sin_addr); + sin.sin_addr.s_addr = htonl(dst_ip); /* FIXME: create socket */ rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); diff --git a/src/host/layer23/src/gsmtap_util.h b/src/host/layer23/src/gsmtap_util.h deleted file mode 100644 index 3599c33de..000000000 --- a/src/host/layer23/src/gsmtap_util.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef GSMTAP_ROUTINES_H -#define GSMTAP_ROUTINES_H - -#include -#include - -int gsmtap_init(void); - -/* receive a message from L1/L2 and put it in GSMTAP */ -int gsmtap_sendmsg(uint8_t ts, uint16_t arfcn, uint32_t fn, - const uint8_t *data, unsigned int len); - -#endif diff --git a/src/host/layer23/src/l1ctl.c b/src/host/layer23/src/l1ctl.c index b8c636ab3..c3f1b397d 100644 --- a/src/host/layer23/src/l1ctl.c +++ b/src/host/layer23/src/l1ctl.c @@ -32,13 +32,13 @@ #include #include #include +#include #include #include #include #include - -#include "gsmtap_util.h" +#include static struct msgb *osmo_l1_alloc(uint8_t msg_type) { @@ -116,6 +116,8 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg) struct l1ctl_info_dl *dl, dl_cpy; struct l1ctl_data_ind *ccch; struct lapdm_entity *le; + uint8_t chan_type, chan_ts, chan_ss; + uint8_t gsmtap_chan_type; if (msgb_l3len(msg) < sizeof(*ccch)) { fprintf(stderr, "MSG too short Data Ind: %u\n", msgb_l3len(msg)); @@ -124,13 +126,16 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg) dl = (struct l1ctl_info_dl *) msg->l1h; ccch = (struct l1ctl_data_ind *) msg->l2h; + + rsl_dec_chan_nr(dl->chan_nr, &chan_type, &chan_ss, &chan_ts); printf("%s (%.4u/%.2u/%.2u) %s\n", chan_nr2string(dl->chan_nr), dl->time.t1, dl->time.t2, dl->time.t3, hexdump(ccch->data, sizeof(ccch->data))); /* send CCCH data via GSMTAP */ - gsmtap_sendmsg(dl->chan_nr & 0x07, dl->band_arfcn, dl->time.fn, ccch->data, - sizeof(ccch->data)); + gsmtap_chan_type = chantype_rsl2gsmtap(chan_type, dl->link_id); + gsmtap_sendmsg(dl->band_arfcn, chan_ts, gsmtap_chan_type, chan_ss, + dl->time.fn, ccch->data, sizeof(ccch->data)); /* determine LAPDm entity based on SACCH or not */ if (dl->link_id & 0x40) @@ -155,6 +160,8 @@ int tx_ph_data_req(struct osmocom_ms *ms, struct msgb *msg, uint8_t chan_nr, uint8_t link_id) { struct l1ctl_info_ul *l1i_ul; + uint8_t chan_type, chan_ts, chan_ss; + uint8_t gsmtap_chan_type; printf("tx_ph_data_req(%s)\n", hexdump(msg->l2h, msgb_l2len(msg))); @@ -165,6 +172,12 @@ int tx_ph_data_req(struct osmocom_ms *ms, struct msgb *msg, } else if (msgb_l2len(msg) < 23) printf("L1 message length < 23 (%u) doesn't seem right!\n", msgb_l2len(msg)); + /* send copy via GSMTAP */ + rsl_dec_chan_nr(chan_nr, &chan_type, &chan_ss, &chan_ts); + gsmtap_chan_type = chantype_rsl2gsmtap(chan_type, link_id); + gsmtap_sendmsg(0|0x4000, chan_ts, gsmtap_chan_type, chan_ss, + 0, msg->l2h, msgb_l2len(msg)); + /* prepend uplink info header */ printf("sizeof(struct l1ctl_info_ul)=%lu\n", sizeof(*l1i_ul)); msg->l1h = msgb_push(msg, sizeof(*l1i_ul)); diff --git a/src/host/layer23/src/main.c b/src/host/layer23/src/main.c index 453fe6d7d..3afc8afe0 100644 --- a/src/host/layer23/src/main.c +++ b/src/host/layer23/src/main.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -42,13 +43,13 @@ #include #include -#include "gsmtap_util.h" #define GSM_L2_LENGTH 256 static void *l2_ctx = NULL; static char *socket_path = "/tmp/osmocom_l2"; static struct osmocom_ms *ms = NULL; +static uint32_t gsmtap_ip = 0; static int layer2_read(struct bsc_fd *fd, unsigned int flags) { @@ -124,23 +125,26 @@ static void print_usage() static void print_help() { printf(" Some help...\n"); - printf(" -h --help this text\n"); - printf(" -s --socket /tmp/osmocom_l2. Path to the unix domain socket\n"); - printf(" -a --arfcn NR. The ARFCN to be used for layer2.\n"); + printf(" -h --help this text\n"); + printf(" -s --socket /tmp/osmocom_l2. Path to the unix domain socket\n"); + printf(" -a --arfcn NR The ARFCN to be used for layer2.\n"); + printf(" -i --gsmtap-ip The destination IP used for GSMTAP.\n"); } static void handle_options(int argc, char **argv) { + struct sockaddr_in gsmtap; while (1) { int option_index = 0, c; static struct option long_options[] = { {"help", 0, 0, 'h'}, {"socket", 1, 0, 's'}, {"arfcn", 1, 0, 'a'}, + {"gsmtap-ip", 1, 0, 'i'}, {0, 0, 0, 0}, }; - c = getopt_long(argc, argv, "hs:a:", + c = getopt_long(argc, argv, "hs:a:i:", long_options, &option_index); if (c == -1) break; @@ -157,6 +161,13 @@ static void handle_options(int argc, char **argv) case 'a': ms->arfcn = atoi(optarg); break; + case 'i': + if (!inet_aton(optarg, &gsmtap.sin_addr)) { + perror("inet_aton"); + exit(2); + } + gsmtap_ip = gsmtap.sin_addr.s_addr; + break; default: break; } @@ -167,7 +178,6 @@ int main(int argc, char **argv) { int rc; struct sockaddr_un local; - struct sockaddr_in gsmtap; l2_ctx = talloc_named_const(NULL, 1, "layer2 context"); @@ -210,10 +220,12 @@ int main(int argc, char **argv) exit(1); } - rc = gsmtap_init(); - if (rc < 0) { - fprintf(stderr, "Failed during gsmtap_init()\n"); - exit(1); + if (gsmtap_ip) { + rc = gsmtap_init(gsmtap_ip); + if (rc < 0) { + fprintf(stderr, "Failed during gsmtap_init()\n"); + exit(1); + } } while (1) {