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:
parent
5a1d72cfc6
commit
582aec803c
|
@ -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
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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));
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue