mirror of https://github.com/PentHertz/srsLTE.git
add simple RLC PCAP writer
This commit is contained in:
parent
7993385742
commit
e7c74fa0f7
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#define MAC_LTE_DLT 147
|
#define MAC_LTE_DLT 147
|
||||||
#define NAS_LTE_DLT 148
|
#define NAS_LTE_DLT 148
|
||||||
|
#define RLC_LTE_DLT 149 // UDP needs to be selected as protocol
|
||||||
|
|
||||||
|
|
||||||
/* This structure gets written to the start of the file */
|
/* This structure gets written to the start of the file */
|
||||||
|
@ -104,6 +105,67 @@ typedef struct NAS_Context_Info_s {
|
||||||
} NAS_Context_Info_t;
|
} NAS_Context_Info_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* RLC-LTE disector */
|
||||||
|
|
||||||
|
/* rlcMode */
|
||||||
|
#define RLC_TM_MODE 1
|
||||||
|
#define RLC_UM_MODE 2
|
||||||
|
#define RLC_AM_MODE 4
|
||||||
|
#define RLC_PREDEF 8
|
||||||
|
|
||||||
|
/* priority ? */
|
||||||
|
|
||||||
|
/* channelType */
|
||||||
|
#define CHANNEL_TYPE_CCCH 1
|
||||||
|
#define CHANNEL_TYPE_BCCH_BCH 2
|
||||||
|
#define CHANNEL_TYPE_PCCH 3
|
||||||
|
#define CHANNEL_TYPE_SRB 4
|
||||||
|
#define CHANNEL_TYPE_DRB 5
|
||||||
|
#define CHANNEL_TYPE_BCCH_DL_SCH 6
|
||||||
|
#define CHANNEL_TYPE_MCCH 7
|
||||||
|
#define CHANNEL_TYPE_MTCH 8
|
||||||
|
|
||||||
|
/* sequenceNumberLength */
|
||||||
|
#define UM_SN_LENGTH_5_BITS 5
|
||||||
|
#define UM_SN_LENGTH_10_BITS 10
|
||||||
|
#define AM_SN_LENGTH_10_BITS 10
|
||||||
|
#define AM_SN_LENGTH_16_BITS 16
|
||||||
|
|
||||||
|
/* Narrow band mode */
|
||||||
|
typedef enum {
|
||||||
|
rlc_no_nb_mode = 0,
|
||||||
|
rlc_nb_mode = 1
|
||||||
|
} rlc_lte_nb_mode;
|
||||||
|
|
||||||
|
/* Context information for every RLC PDU that will be logged */
|
||||||
|
typedef struct {
|
||||||
|
unsigned char rlcMode;
|
||||||
|
unsigned char direction;
|
||||||
|
unsigned char priority;
|
||||||
|
unsigned char sequenceNumberLength;
|
||||||
|
unsigned short ueid;
|
||||||
|
unsigned short channelType;
|
||||||
|
unsigned short channelId; /* for SRB: 1=SRB1, 2=SRB2, 3=SRB1bis; for DRB: DRB ID */
|
||||||
|
unsigned short pduLength;
|
||||||
|
bool extendedLiField;
|
||||||
|
rlc_lte_nb_mode nbMode;
|
||||||
|
} RLC_Context_Info_t;
|
||||||
|
|
||||||
|
|
||||||
|
// See Wireshark's packet-rlc-lte.h for details
|
||||||
|
#define RLC_LTE_START_STRING "rlc-lte"
|
||||||
|
#define RLC_LTE_SN_LENGTH_TAG 0x02
|
||||||
|
#define RLC_LTE_DIRECTION_TAG 0x03
|
||||||
|
#define RLC_LTE_PRIORITY_TAG 0x04
|
||||||
|
#define RLC_LTE_UEID_TAG 0x05
|
||||||
|
#define RLC_LTE_CHANNEL_TYPE_TAG 0x06
|
||||||
|
#define RLC_LTE_CHANNEL_ID_TAG 0x07
|
||||||
|
#define RLC_LTE_EXT_LI_FIELD_TAG 0x08
|
||||||
|
#define RLC_LTE_NB_MODE_TAG 0x09
|
||||||
|
#define RLC_LTE_PAYLOAD_TAG 0x01
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* API functions for opening/closing LTE PCAP files *
|
* API functions for opening/closing LTE PCAP files *
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
@ -247,4 +309,92 @@ inline int LTE_PCAP_NAS_WritePDU(FILE *fd, NAS_Context_Info_t *context,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* API functions for writing RLC-LTE PCAP files *
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/* Write an individual RLC PDU (PCAP packet header + UDP header + rlc-context + rlc-pdu) */
|
||||||
|
inline int LTE_PCAP_RLC_WritePDU(FILE *fd, RLC_Context_Info_t *context,
|
||||||
|
const unsigned char *PDU, unsigned int length)
|
||||||
|
{
|
||||||
|
pcaprec_hdr_t packet_header;
|
||||||
|
char context_header[256];
|
||||||
|
int offset = 0;
|
||||||
|
uint16_t tmp16;
|
||||||
|
|
||||||
|
/* Can't write if file wasn't successfully opened */
|
||||||
|
if (fd == NULL) {
|
||||||
|
printf("Error: Can't write to empty file handle\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************/
|
||||||
|
|
||||||
|
// Add dummy UDP header, start with src and dest port
|
||||||
|
context_header[offset++] = 0xde;
|
||||||
|
context_header[offset++] = 0xad;
|
||||||
|
context_header[offset++] = 0xbe;
|
||||||
|
context_header[offset++] = 0xef;
|
||||||
|
// length
|
||||||
|
tmp16 = length + 12;
|
||||||
|
memcpy(context_header+offset, &tmp16, 2);
|
||||||
|
offset += 2;
|
||||||
|
// dummy CRC
|
||||||
|
context_header[offset++] = 0xde;
|
||||||
|
context_header[offset++] = 0xad;
|
||||||
|
|
||||||
|
// Start magic string
|
||||||
|
memcpy(&context_header[offset], RLC_LTE_START_STRING, strlen(RLC_LTE_START_STRING));
|
||||||
|
offset += strlen(RLC_LTE_START_STRING);
|
||||||
|
|
||||||
|
// Fixed field RLC mode
|
||||||
|
context_header[offset++] = context->rlcMode;
|
||||||
|
|
||||||
|
// Conditional fields
|
||||||
|
if (context->rlcMode == RLC_UM_MODE) {
|
||||||
|
context_header[offset++] = RLC_LTE_SN_LENGTH_TAG;
|
||||||
|
context_header[offset++] = context->sequenceNumberLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional fields
|
||||||
|
context_header[offset++] = RLC_LTE_DIRECTION_TAG;
|
||||||
|
context_header[offset++] = context->direction;
|
||||||
|
|
||||||
|
context_header[offset++] = RLC_LTE_PRIORITY_TAG;
|
||||||
|
context_header[offset++] = context->priority;
|
||||||
|
|
||||||
|
context_header[offset++] = RLC_LTE_UEID_TAG;
|
||||||
|
tmp16 = htons(context->ueid);
|
||||||
|
memcpy(context_header+offset, &tmp16, 2);
|
||||||
|
offset += 2;
|
||||||
|
|
||||||
|
context_header[offset++] = RLC_LTE_CHANNEL_TYPE_TAG;
|
||||||
|
tmp16 = htons(context->channelType);
|
||||||
|
memcpy(context_header+offset, &tmp16, 2);
|
||||||
|
offset += 2;
|
||||||
|
|
||||||
|
context_header[offset++] = RLC_LTE_CHANNEL_ID_TAG;
|
||||||
|
tmp16 = htons(context->channelId);
|
||||||
|
memcpy(context_header+offset, &tmp16, 2);
|
||||||
|
offset += 2;
|
||||||
|
|
||||||
|
// Now the actual PDU
|
||||||
|
context_header[offset++] = RLC_LTE_PAYLOAD_TAG;
|
||||||
|
|
||||||
|
// PCAP header
|
||||||
|
struct timeval t;
|
||||||
|
gettimeofday(&t, NULL);
|
||||||
|
packet_header.ts_sec = t.tv_sec;
|
||||||
|
packet_header.ts_usec = t.tv_usec;
|
||||||
|
packet_header.incl_len = offset + length;
|
||||||
|
packet_header.orig_len = offset + length;
|
||||||
|
|
||||||
|
// Write everything to file
|
||||||
|
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, fd);
|
||||||
|
fwrite(context_header, 1, offset, fd);
|
||||||
|
fwrite(PDU, 1, length, fd);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* UEPCAP_H */
|
#endif /* UEPCAP_H */
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2015 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the srsUE library.
|
||||||
|
*
|
||||||
|
* srsUE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsUE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RLCPCAP_H
|
||||||
|
#define RLCPCAP_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "srslte/common/pcap.h"
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
class rlc_pcap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
rlc_pcap() {enable_write=false; ue_id=0; pcap_file = NULL; };
|
||||||
|
void enable(bool en);
|
||||||
|
void open(const char *filename, uint32_t ue_id = 0);
|
||||||
|
void close();
|
||||||
|
|
||||||
|
void set_ue_id(uint16_t ue_id);
|
||||||
|
|
||||||
|
void write_dl_am_ccch(uint8_t* pdu, uint32_t pdu_len_bytes);
|
||||||
|
void write_ul_am_ccch(uint8_t* pdu, uint32_t pdu_len_bytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool enable_write;
|
||||||
|
FILE *pcap_file;
|
||||||
|
uint32_t ue_id;
|
||||||
|
void pack_and_write(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint8_t mode,
|
||||||
|
uint8_t direction,
|
||||||
|
uint8_t priority,
|
||||||
|
uint8_t seqnumberlength,
|
||||||
|
uint16_t ueid,
|
||||||
|
uint16_t channel_type,
|
||||||
|
uint16_t channel_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // RLCPCAP_H
|
|
@ -0,0 +1,90 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2015 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* This file is part of the srsUE library.
|
||||||
|
*
|
||||||
|
* srsUE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsUE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "srslte/srslte.h"
|
||||||
|
#include "srslte/common/pcap.h"
|
||||||
|
#include "srslte/common/rlc_pcap.h"
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
void rlc_pcap::enable(bool en)
|
||||||
|
{
|
||||||
|
enable_write = true;
|
||||||
|
}
|
||||||
|
void rlc_pcap::open(const char* filename, uint32_t ue_id)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Opening RLC PCAP with DLT=%d\n", RLC_LTE_DLT);
|
||||||
|
pcap_file = LTE_PCAP_Open(RLC_LTE_DLT, filename);
|
||||||
|
this->ue_id = ue_id;
|
||||||
|
enable_write = true;
|
||||||
|
}
|
||||||
|
void rlc_pcap::close()
|
||||||
|
{
|
||||||
|
fprintf(stdout, "Saving RLC PCAP file\n");
|
||||||
|
LTE_PCAP_Close(pcap_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rlc_pcap::set_ue_id(uint16_t ue_id) {
|
||||||
|
this->ue_id = ue_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rlc_pcap::pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint8_t mode, uint8_t direction, uint8_t priority, uint8_t seqnumberlength, uint16_t ueid, uint16_t channel_type, uint16_t channel_id)
|
||||||
|
{
|
||||||
|
if (enable_write) {
|
||||||
|
RLC_Context_Info_t context;
|
||||||
|
context.rlcMode = mode;
|
||||||
|
context.direction = direction;
|
||||||
|
context.priority = priority;
|
||||||
|
context.sequenceNumberLength = seqnumberlength;
|
||||||
|
context.ueid = ueid;
|
||||||
|
context.channelType = channel_type;
|
||||||
|
context.channelId = channel_id;
|
||||||
|
context.pduLength = pdu_len_bytes;
|
||||||
|
if (pdu) {
|
||||||
|
LTE_PCAP_RLC_WritePDU(pcap_file, &context, pdu, pdu_len_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rlc_pcap::write_dl_am_ccch(uint8_t* pdu, uint32_t pdu_len_bytes)
|
||||||
|
{
|
||||||
|
uint8_t priority = 0;
|
||||||
|
uint8_t seqnumberlength = 0; // normal length of 10bit
|
||||||
|
uint8_t channel_id = 0;
|
||||||
|
pack_and_write(pdu, pdu_len_bytes, RLC_AM_MODE, DIRECTION_DOWNLINK, priority, seqnumberlength, ue_id, CHANNEL_TYPE_CCCH, channel_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rlc_pcap::write_ul_am_ccch(uint8_t* pdu, uint32_t pdu_len_bytes)
|
||||||
|
{
|
||||||
|
uint8_t priority = 0;
|
||||||
|
uint8_t seqnumberlength = 0; // normal length of 10bit
|
||||||
|
uint8_t channel_id = 0;
|
||||||
|
pack_and_write(pdu, pdu_len_bytes, RLC_AM_MODE, DIRECTION_UPLINK, priority, seqnumberlength, ue_id, CHANNEL_TYPE_CCCH, channel_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue