layer23: GSMTAP update (gsmtap for uplink, DCCH and ACCH)

* use GSMTAP for uplink frames (generated by layer23; sent to L1)
* only use GSMTAP if the user specifies the '-i dstip' arguments
* properly encode the GSMTAP channel type
* requires GSMTAP protocol version 0x02 (see next commit for wireshark patch)
This commit is contained in:
Harald Welte 2010-03-04 15:41:11 +01:00
parent 5a1d72cfc6
commit 582aec803c
6 changed files with 105 additions and 36 deletions

View File

@ -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

View File

@ -0,0 +1,15 @@
#ifndef _GSMTAP_UTIL_H
#define _GSMTAP_UTIL_H
#include <stdint.h>
/* 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 */

View File

@ -22,9 +22,11 @@
#include <osmocom/osmocom_data.h>
#include <osmocom/debug.h>
#include <osmocom/gsmtap_util.h>
#include <osmocore/protocol/gsm_04_08.h>
#include <osmocore/gsmtap.h>
#include <osmocore/msgb.h>
#include <osmocore/rsl.h>
#include <arpa/inet.h>
#include <sys/socket.h>
@ -36,17 +38,56 @@
#include <string.h>
#include <errno.h>
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);

View File

@ -1,13 +0,0 @@
#ifndef GSMTAP_ROUTINES_H
#define GSMTAP_ROUTINES_H
#include <stdint.h>
#include <netinet/in.h>
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

View File

@ -32,13 +32,13 @@
#include <osmocore/tlv.h>
#include <osmocore/protocol/gsm_04_08.h>
#include <osmocore/protocol/gsm_08_58.h>
#include <osmocore/rsl.h>
#include <osmocom/l1ctl.h>
#include <osmocom/osmocom_data.h>
#include <osmocom/lapdm.h>
#include <osmocom/debug.h>
#include "gsmtap_util.h"
#include <osmocom/gsmtap_util.h>
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));

View File

@ -24,6 +24,7 @@
#include <osmocom/osmocom_data.h>
#include <osmocom/l1ctl.h>
#include <osmocom/lapdm.h>
#include <osmocom/gsmtap_util.h>
#include <osmocom/debug.h>
#include <osmocore/msgb.h>
@ -42,13 +43,13 @@
#include <errno.h>
#include <fcntl.h>
#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) {