[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:
parent
fc65a393a6
commit
51eaba28a3
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue