gsm: Update and enhance the GSM Tap functionality
* switch to the new format * add uplink frame dump as well * fill more fields than before (not fully complete yet tough) Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
parent
b6b3f6ace1
commit
e6d5057d5d
|
@ -659,6 +659,10 @@ void XCCHL1Decoder::handleGoodFrame()
|
|||
OBJLOG(DEEPDEBUG) <<"XCCHL1Decoder d[]=" << mD;
|
||||
|
||||
if (mUpstream) {
|
||||
// Send all bits to GSMTAP
|
||||
gWriteGSMTAP(ARFCN(),TN(),mReadTime.FN(),
|
||||
typeAndOffset(),mMapping.repeatLength()>51,true,
|
||||
mD);
|
||||
// Build an L2 frame and pass it up.
|
||||
const BitVector L2Part(mD.tail(headerOffset()));
|
||||
OBJLOG(DEEPDEBUG) <<"XCCHL1Decoder L2=" << L2Part;
|
||||
|
@ -810,14 +814,18 @@ void XCCHL1Encoder::sendFrame(const L2Frame& frame)
|
|||
// GSM 05.03 4.1.1.
|
||||
//assert(mD.size()==headerOffset()+frame.size());
|
||||
frame.copyToSegment(mU,headerOffset());
|
||||
|
||||
// Send to GSMTAP (must send mU = real bits !)
|
||||
gWriteGSMTAP(ARFCN(),TN(),mNextWriteTime.FN(),
|
||||
typeAndOffset(),mMapping.repeatLength()>51,false,mU);
|
||||
|
||||
// Encode data into bursts
|
||||
OBJLOG(DEEPDEBUG) << "XCCHL1Encoder d[]=" << mD;
|
||||
mD.LSB8MSB();
|
||||
OBJLOG(DEEPDEBUG) << "XCCHL1Encoder d[]=" << mD;
|
||||
encode(); // Encode u[] to c[], GSM 05.03 4.1.2 and 4.1.3.
|
||||
interleave(); // Interleave c[] to i[][], GSM 05.03 4.1.4.
|
||||
transmit(); // Send the bursts to the radio, GSM 05.03 4.1.5.
|
||||
// FIXME: is this FN OK, or do we need to back it up by 4?
|
||||
gWriteGSMTAP(ARFCN(),mTN,mPrevWriteTime.FN(),frame);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,21 +30,107 @@
|
|||
|
||||
UDPSocket GSMTAPSocket;
|
||||
|
||||
void gWriteGSMTAP(unsigned ARFCN, unsigned TS, unsigned FN, const GSM::L2Frame& frame)
|
||||
void gWriteGSMTAP(unsigned ARFCN, unsigned TS, unsigned FN,
|
||||
GSM::TypeAndOffset to, bool is_saach, bool ul_dln,
|
||||
const BitVector& frame)
|
||||
{
|
||||
char buffer[MAX_UDP_LENGTH];
|
||||
int ofs = 0;
|
||||
|
||||
// Check if GSMTap is enabled
|
||||
if (!gConfig.defines("GSMTAP.TargetIP")) return;
|
||||
|
||||
// Port configuration
|
||||
unsigned port = GSMTAP_UDP_PORT; // default port for GSM-TAP
|
||||
if (gConfig.defines("GSMTAP.TargetPort"))
|
||||
port = gConfig.getNum("GSMTAP.TargetPort");
|
||||
|
||||
// Write a GSMTAP packet to the configured destination.
|
||||
// Set socket destination
|
||||
GSMTAPSocket.destination(port,gConfig.getStr("GSMTAP.TargetIP"));
|
||||
char buffer[MAX_UDP_LENGTH];
|
||||
gsmtap_hdr header(ARFCN,TS,FN);
|
||||
memcpy(buffer,&header,sizeof(header));
|
||||
frame.pack((unsigned char*)buffer+sizeof(header));
|
||||
GSMTAPSocket.write(buffer, sizeof(header) + frame.size()/8);
|
||||
|
||||
// Decode TypeAndOffset
|
||||
uint8_t stype, scn;
|
||||
|
||||
switch (to) {
|
||||
case GSM::TDMA_BEACON_BCCH:
|
||||
stype = GSMTAP_CHANNEL_BCCH;
|
||||
scn = 0;
|
||||
break;
|
||||
|
||||
case GSM::TDMA_BEACON_CCCH:
|
||||
stype = GSMTAP_CHANNEL_CCCH;
|
||||
scn = 0;
|
||||
break;
|
||||
|
||||
case GSM::SDCCH_4_0:
|
||||
case GSM::SDCCH_4_1:
|
||||
case GSM::SDCCH_4_2:
|
||||
case GSM::SDCCH_4_3:
|
||||
stype = GSMTAP_CHANNEL_SDCCH4;
|
||||
scn = to - GSM::SDCCH_4_0;
|
||||
break;
|
||||
|
||||
case GSM::SDCCH_8_0:
|
||||
case GSM::SDCCH_8_1:
|
||||
case GSM::SDCCH_8_2:
|
||||
case GSM::SDCCH_8_3:
|
||||
case GSM::SDCCH_8_4:
|
||||
case GSM::SDCCH_8_5:
|
||||
case GSM::SDCCH_8_6:
|
||||
case GSM::SDCCH_8_7:
|
||||
stype = GSMTAP_CHANNEL_SDCCH8;
|
||||
scn = to - GSM::SDCCH_8_0;
|
||||
break;
|
||||
|
||||
case GSM::TCHF_0:
|
||||
stype = GSMTAP_CHANNEL_TCH_F;
|
||||
scn = 0;
|
||||
break;
|
||||
|
||||
case GSM::TCHH_0:
|
||||
case GSM::TCHH_1:
|
||||
stype = GSMTAP_CHANNEL_TCH_H;
|
||||
scn = to - GSM::TCHH_0;
|
||||
break;
|
||||
|
||||
default:
|
||||
stype = GSMTAP_CHANNEL_UNKNOWN;
|
||||
scn = 0;
|
||||
}
|
||||
|
||||
if (is_saach)
|
||||
stype |= GSMTAP_CHANNEL_ACCH;
|
||||
|
||||
// Flags in ARFCN
|
||||
if (gConfig.getNum("GSM.Band") == 1900)
|
||||
ARFCN |= GSMTAP_ARFCN_F_PCS;
|
||||
|
||||
if (ul_dln)
|
||||
ARFCN |= GSMTAP_ARFCN_F_UPLINK;
|
||||
|
||||
// Build header
|
||||
struct gsmtap_hdr *header = (struct gsmtap_hdr *)buffer;
|
||||
header->version = GSMTAP_VERSION;
|
||||
header->hdr_len = sizeof(struct gsmtap_hdr) >> 2;
|
||||
header->type = GSMTAP_TYPE_UM;
|
||||
header->timeslot = TS;
|
||||
header->arfcn = htons(ARFCN);
|
||||
header->signal_dbm = 0; /* FIXME */
|
||||
header->snr_db = 0; /* FIXME */
|
||||
header->frame_number = htonl(FN);
|
||||
header->sub_type = stype;
|
||||
header->antenna_nr = 0;
|
||||
header->sub_slot = scn;
|
||||
header->res = 0;
|
||||
|
||||
ofs += sizeof(*header);
|
||||
|
||||
// Add frame data
|
||||
frame.pack((unsigned char*)&buffer[ofs]);
|
||||
ofs += (frame.size() + 7) >> 3;
|
||||
|
||||
// Write the GSMTAP packet
|
||||
GSMTAPSocket.write(buffer, ofs);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,10 +28,13 @@
|
|||
#define GSMTAPDUMP_H
|
||||
|
||||
#include "gsmtap.h"
|
||||
#include "GSMCommon.h"
|
||||
#include "GSMTransfer.h"
|
||||
|
||||
|
||||
void gWriteGSMTAP(unsigned ARFCN, unsigned TS, unsigned FN, const GSM::L2Frame& frame);
|
||||
void gWriteGSMTAP(unsigned ARFCN, unsigned TS, unsigned FN,
|
||||
GSM::TypeAndOffset to, bool is_sacch, bool ul_dln,
|
||||
const BitVector& frame);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
#ifndef _GSMTAP_H
|
||||
#define _GSMTAP_H
|
||||
|
||||
/* gsmtap header, pseudo-header in front of the actua GSM payload*/
|
||||
/* gsmtap header, pseudo-header in front of the actua GSM payload */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef __linux__
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
/* GSMTAP is a generic header format for GSM protocol captures,
|
||||
* it uses the IANA-assigned UDP port number 4729 and carries
|
||||
* payload in various formats of GSM interfaces such as Um MAC
|
||||
* blocks or Um bursts.
|
||||
*
|
||||
* Example programs generating GSMTAP data are airprobe
|
||||
* (http://airprobe.org/) or OsmocomBB (http://bb.osmocom.org/)
|
||||
*/
|
||||
|
||||
#define GSMTAP_VERSION 0x01
|
||||
#include <stdint.h>
|
||||
|
||||
#define GSMTAP_VERSION 0x02
|
||||
|
||||
#define GSMTAP_TYPE_UM 0x01 /* A Layer 2 MAC block (23 bytes) */
|
||||
#define GSMTAP_TYPE_ABIS 0x02
|
||||
|
@ -25,38 +31,41 @@
|
|||
#define GSMTAP_BURST_ACCESS 0x08
|
||||
#define GSMTAP_BURST_NONE 0x09
|
||||
|
||||
#define GSMTAP_CHANNEL_UNKNOWN 0x00
|
||||
#define GSMTAP_CHANNEL_BCCH 0x01
|
||||
#define GSMTAP_CHANNEL_CCCH 0x02
|
||||
#define GSMTAP_CHANNEL_RACH 0x03
|
||||
#define GSMTAP_CHANNEL_AGCH 0x04
|
||||
#define GSMTAP_CHANNEL_PCH 0x05
|
||||
#define GSMTAP_CHANNEL_SDCCH 0x06
|
||||
#define GSMTAP_CHANNEL_SDCCH4 0x07
|
||||
#define GSMTAP_CHANNEL_SDCCH8 0x08
|
||||
#define GSMTAP_CHANNEL_TCH_F 0x09
|
||||
#define GSMTAP_CHANNEL_TCH_H 0x0a
|
||||
#define GSMTAP_CHANNEL_ACCH 0x80
|
||||
|
||||
#define GSMTAP_ARFCN_F_PCS 0x8000
|
||||
#define GSMTAP_ARFCN_F_UPLINK 0x4000
|
||||
#define GSMTAP_ARFCN_MASK 0x3fff
|
||||
|
||||
#define GSMTAP_UDP_PORT 4729 /* officially registered with IANA */
|
||||
|
||||
struct gsmtap_hdr {
|
||||
u_int8_t version; /* version, set to 0x01 currently */
|
||||
u_int8_t hdr_len; /* length in number of 32bit words */
|
||||
u_int8_t type; /* see GSMTAP_TYPE_* */
|
||||
u_int8_t timeslot; /* timeslot (0..7 on Um) */
|
||||
uint8_t version; /* version, set to GSMTAP_VERSION */
|
||||
uint8_t hdr_len; /* length in number of 32bit words */
|
||||
uint8_t type; /* see GSMTAP_TYPE_* */
|
||||
uint8_t timeslot; /* timeslot (0..7 on Um) */
|
||||
|
||||
u_int16_t arfcn; /* ARFCN (frequency).
|
||||
* highest bit 1 == uplink */
|
||||
u_int8_t noise_db; /* noise figure in dB */
|
||||
u_int8_t signal_db; /* signal level in dB */
|
||||
uint16_t arfcn; /* ARFCN (frequency) */
|
||||
int8_t signal_dbm; /* signal level in dBm */
|
||||
int8_t snr_db; /* signal/noise ratio in dB */
|
||||
|
||||
u_int32_t frame_number; /* GSM Frame Number (FN) */
|
||||
uint32_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) */
|
||||
|
||||
gsmtap_hdr(unsigned ARFCN, unsigned TS, unsigned FN)
|
||||
{
|
||||
version = GSMTAP_VERSION;
|
||||
type = GSMTAP_TYPE_UM;
|
||||
burst_type = GSMTAP_BURST_NONE;
|
||||
antenna_nr = 0;
|
||||
noise_db = 0;
|
||||
signal_db = 0;
|
||||
|
||||
timeslot = TS;
|
||||
arfcn = htons(ARFCN);
|
||||
frame_number = htonl(FN);
|
||||
}
|
||||
uint8_t sub_type; /* Type of burst/channel, see above */
|
||||
uint8_t antenna_nr; /* Antenna Number */
|
||||
uint8_t sub_slot; /* sub-slot within timeslot */
|
||||
uint8_t res; /* reserved for future use (RFU) */
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
|
@ -70,12 +79,11 @@ struct pcap_timeval {
|
|||
int32_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
};
|
||||
|
||||
|
||||
struct pcap_sf_pkthdr {
|
||||
struct pcap_timeval ts; /* time stamp */
|
||||
u_int32_t caplen; /* lenght of portion present */
|
||||
u_int32_t len; /* length of this packet */
|
||||
uint32_t caplen; /* lenght of portion present */
|
||||
uint32_t len; /* length of this packet */
|
||||
};
|
||||
|
||||
|
||||
#endif /* _GSMTAP_H */
|
||||
|
|
Reference in New Issue