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 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 */
|
||||
|
@ -104,6 +105,67 @@ typedef struct NAS_Context_Info_s {
|
|||
} 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 *
|
||||
**************************************************************************/
|
||||
|
@ -247,4 +309,92 @@ inline int LTE_PCAP_NAS_WritePDU(FILE *fd, NAS_Context_Info_t *context,
|
|||
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 */
|
||||
|
|
|
@ -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