[gsm-tvoid] new gsmtap header, raw burst pcap support

* split burst decoding context out of GS_ctx and have one for each TS
* add PCAP output for GSMTAP_TYPE_UM_BURST (142 bit burst per packet)
This commit is contained in:
Harald Welte 2008-11-29 13:48:12 +05:30
parent fc65a393a6
commit 51eaba28a3
5 changed files with 110 additions and 39 deletions

View File

@ -17,6 +17,28 @@
static void out_gsmdecode(char type, int arfcn, int ts, int fn, char *data, int len);
/* encode a decoded burst (1 bit per byte) into 8-bit-per-byte */
static void burst_octify(unsigned char *dest,
const unsigned char *data, int length)
{
int bitpos = 0;
while (bitpos < USEFUL_BITS) {
unsigned char tbyte;
int i;
tbyte = 0;
for (i = 0; (i < 8) && (bitpos < length); i++) {
tbyte <<= 1;
tbyte |= data[bitpos++];
}
if (i < 8)
tbyte <<= 8 - i;
*dest++ = tbyte;
}
}
#if 0
static void
diff_decode(char *dst, char *src, int len)
@ -58,9 +80,14 @@ GS_new(GS_CTX *ctx)
if (ctx->pcap_fd < 0)
fprintf(stderr, "cannot open PCAP file: %s\n", strerror(errno));
ctx->burst_pcap_fd = open_pcap_file("tvoid-burst.pcap");
if (ctx->burst_pcap_fd < 0)
fprintf(stderr, "cannot open burst PCAP file: %s\n", strerror(errno));
return 0;
}
#define BURST_BYTES ((USEFUL_BITS/8)+1)
/*
* 142 bit
*/
@ -72,7 +99,17 @@ GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src)
int ret;
unsigned char *data;
int len;
struct gs_ts_ctx *ts_ctx = &ctx->ts_ctx[ts];
unsigned char octified[BURST_BYTES];
memset(ctx->msg, 0, sizeof(ctx->msg));
/* write burst to burst PCAP file */
burst_octify(octified, src, USEFUL_BITS);
write_pcap_packet(ctx->burst_pcap_fd, 0 /* arfcn */, ts, ctx->fn,
1, type, octified, BURST_BYTES);
#if 0
if (ts != 0) {
/* non-0 timeslots should end up in PCAP */
data = decode_cch(ctx, ctx->burst, &len);
@ -81,51 +118,56 @@ GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src)
write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn, data, len);
return;
}
#endif
if (type == SCH)
{
ret = decode_sch(src, &fn, &bsic);
if (ret != 0)
if (ts == 0) {
if (type == SCH) {
ret = decode_sch(src, &fn, &bsic);
if (ret != 0)
return 0;
if ((ctx->bsic > 0) && (bsic != ctx->bsic))
fprintf(stderr, "WARN: BSIC changed.\n");
//DEBUGF("FN %d, BSIC %d\n", fn, bsic);
ctx->fn = fn;
ctx->bsic = bsic;
/* Reset message concatenator */
ts_ctx->burst_count = 0;
return 0;
if ((ctx->bsic > 0) && (bsic != ctx->bsic))
fprintf(stderr, "WARN: BSIC changed.\n");
//DEBUGF("FN %d, BSIC %d\n", fn, bsic);
ctx->fn = fn;
ctx->bsic = bsic;
/* Reset message concatenator */
ctx->burst_count = 0;
return 0;
}
/* If we did not get Frame Number yet then return */
if (ctx->fn < 0)
return 0;
ctx->fn++;
}
/* If we did not get Frame Number yet then return */
if (ctx->fn < 0)
return 0;
ctx->fn++;
if (type == NORMAL)
{
if (type == NORMAL) {
/* Interested in these frame numbers (cch)
* 2-5, 12-15, 22-25, 23-35, 42-45
* 6-9, 16-19, 26-29, 36-39, 46-49
*/
/* Copy content data into new array */
//DEBUGF("burst count %d\n", ctx->burst_count);
memcpy(ctx->burst + (116 * ctx->burst_count), src, 58);
memcpy(ctx->burst + (116 * ctx->burst_count) + 58, src + 58 + 26, 58);
ctx->burst_count++;
memcpy(ts_ctx->burst + (116 * ts_ctx->burst_count), src, 58);
memcpy(ts_ctx->burst + (116 * ts_ctx->burst_count) + 58, src + 58 + 26, 58);
ts_ctx->burst_count++;
/* Return if not enough bursts for a full gsm message */
if (ctx->burst_count < 4)
if (ts_ctx->burst_count < 4)
return 0;
ctx->burst_count = 0;
data = decode_cch(ctx, ctx->burst, &len);
if (data == NULL)
ts_ctx->burst_count = 0;
data = decode_cch(ctx, ts_ctx->burst, &len);
if (data == NULL) {
DEBUGF("cannot decode fnr=0x%08x ts=%d\n", ctx->fn, ts);
return -1;
}
//DEBUGF("OK TS %d, len %d\n", ts, len);
out_gsmdecode(0, 0, ts, ctx->fn - 4, data, len);
write_interface(ctx->tun_fd, data+1, len-1, ctx->ether_addr);
write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn, data, len);
write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn,
0, NORMAL, data, len);
#if 0
if (ctx->fn % 51 != 0) && ( (((ctx->fn % 51 + 5) % 10 == 0) || (((ctx->fn % 51) + 1) % 10 ==0) ) )
ready = 1;

View File

@ -9,22 +9,28 @@ extern "C" {
#include <linux/if_ether.h>
#include "interleave.h"
struct gs_ts_ctx {
/* FIXME: later do this per each ts per each arfcn */
unsigned char burst[4 * 58 * 2];
int burst_count;
};
typedef struct
{
int flags;
int fn;
int bsic;
char msg[23]; /* last decoded message */
INTERLEAVE_CTX interleave_ctx;
/* FIXME: later do this per each ts per each arfcn */
unsigned char burst[4 * 58 * 2];
int burst_count;
struct gs_ts_ctx ts_ctx[8];
int tun_fd;
unsigned char ether_addr[ETH_ALEN];
int pcap_fd;
int burst_pcap_fd;
} GS_CTX;
int GS_new(GS_CTX *ctx);

View File

@ -5,10 +5,21 @@
#include <sys/types.h>
#define GSMTAP_VERSION 0x02
#define GSMTAP_VERSION 0x01
#define GSMTAP_TYPE_UM 0x01
#define GSMTAP_TYPE_ABIS 0x02
#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */
#define GSMTAP_BURST_UNKNOWN 0x00
#define GSMTAP_BURST_FCCH 0x01
#define GSMTAP_BURST_PARTIAL_SCH 0x02
#define GSMTAP_BURST_SCH 0x03
#define GSMTAP_BURST_CTS_SCH 0x04
#define GSMTAP_BURST_COMPACT_SCH 0x05
#define GSMTAP_BURST_NORMAL 0x06
#define GSMTAP_BURST_DUMMY 0x07
#define GSMTAP_BURST_ACCESS 0x08
struct gsmtap_hdr {
u_int8_t version; /* version, set to 0x01 currently */
@ -17,10 +28,14 @@ struct gsmtap_hdr {
u_int8_t timeslot; /* timeslot (0..7 on Um) */
u_int16_t arfcn; /* ARFCN (frequency) */
u_int8_t noise_db;
u_int8_t signal_db;
u_int8_t noise_db; /* noise figure in dB */
u_int8_t signal_db; /* signal level in dB */
u_int32_t frame_number;
u_int32_t frame_number; /* GSM Frame Number (FN) */
u_int8_t burst_type; /* Type of burst, see above */
u_int8_t antenna_nr; /* Antenna Number */
u_int16_t res; /* reserved for future use (RFU) */
} __attribute__((packed));
#endif /* _GSMTAP_H */

View File

@ -67,7 +67,8 @@ int open_pcap_file(char *fname)
}
int write_pcap_packet(int fd, int arfcn, int ts, int fn,
char *data, unsigned int len)
int burst, int burst_type,
const unsigned char *data, unsigned int len)
{
unsigned char buf[8192];
struct pcap_sf_pkthdr *ph;
@ -75,7 +76,8 @@ int write_pcap_packet(int fd, int arfcn, int ts, int fn,
struct timeval tv;
int rc;
printf("writing pcap packet fd=%d len=%d\n", fd, len);
if (fd < 0)
return -EINVAL;
ph = (struct pcap_sf_pkthdr *) &buf[0];
gh = (struct gsmtap_hdr *) &buf[sizeof(struct pcap_sf_pkthdr)];
@ -88,18 +90,22 @@ int write_pcap_packet(int fd, int arfcn, int ts, int fn,
gh->version = GSMTAP_VERSION;
gh->hdr_len = sizeof(struct gsmtap_hdr)>>2;
gh->type = GSMTAP_TYPE_UM;
if (burst)
gh->type = GSMTAP_TYPE_UM_BURST;
else
gh->type = GSMTAP_TYPE_UM;
gh->timeslot = ts;
gh->arfcn = htons(arfcn);
/* we don't support signal/noise yet */
gh->noise_db = gh->signal_db = 0;
gh->frame_number = htonl(fn);
gh->burst_type = burst_type & 0xff;
memcpy(buf + sizeof(*ph) + sizeof(*gh), data, len);
rc = write(fd, buf, sizeof(*ph) + sizeof(*gh) + len);
fsync(fd);
//fsync(fd);
return rc;
}

View File

@ -2,6 +2,8 @@
#define _PCAP_IF_H
extern int open_pcap_file(char *fname);
int write_pcap_packet(int fd, int arfcn, int ts, int fn, char *data, unsigned int len);
int write_pcap_packet(int fd, int arfcn, int ts, int fn,
int burst, int burst_type,
const unsigned char *data, unsigned int len);
#endif