the code creates a sink to read all traced packets and drop it. but this works only if we send to a local address and if there is not another sink (like if we trace both UE and gNB in the same machine). this sink's purpose is only to prevent to get automatic packets back from the kernel saying "no listener". So, instead of killing the trace when we can't create the sink (as done previously), we now just let the trace in operation.
626 lines
20 KiB
C
626 lines
20 KiB
C
/* mac_lte_logger.c
|
|
*
|
|
* Example code for sending MAC LTE frames over UDP
|
|
* Written by Martin Mathieson, with input from Kiran Kumar
|
|
* This header file may also be distributed under
|
|
* the terms of the BSD Licence as follows:
|
|
*
|
|
* Copyright (C) 2009 Martin Mathieson. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE
|
|
*/
|
|
|
|
/*! \file probe.c
|
|
* \brief
|
|
* \author navid nikaein
|
|
* \date 2010-2012
|
|
* \version 1.0
|
|
* \company Eurecom
|
|
* \email: navid.nikaein@eurecom.fr
|
|
*/
|
|
/** @defgroup _oai System definitions
|
|
There is different modules:
|
|
- OAI Address
|
|
- OAI Components
|
|
|
|
numbering:
|
|
-# OAI Address
|
|
-# OAI Components
|
|
|
|
The following diagram is based on graphviz (http://www.graphviz.org/), you need to install the package to view the diagram.
|
|
*
|
|
* \dot
|
|
* digraph group_frame {
|
|
* node [shape=rect, fontname=Helvetica, fontsize=8,style=filled,fillcolor=lightgrey];
|
|
* a [ label = " Trace_pdu"];
|
|
* b [ label = " dispatcher"];
|
|
* c [ label = " send_ul_mac_pdu"];
|
|
* D [ label = " send_Dl_mac_pdu"];
|
|
* E [ label = " SendFrame"];
|
|
* F[ label = " _Send_Ra_Mac_Pdu"];
|
|
* a->b;
|
|
* b->c;
|
|
* b->d;
|
|
* label="Architecture"
|
|
*
|
|
* }
|
|
* \enddot
|
|
\section _doxy Doxygen Help
|
|
You can use the provided Doxyfile as the configuration file or alternatively run "doxygen -g Doxyfile" to generat the file.
|
|
You need at least to set the some variables in the Doxyfile including "PROJECT_NAME","PROJECT_NUMBER","INPUT","IMAGE_PATH".
|
|
Doxygen help and commands can be found at http://www.stack.nl/~dimitri/doxygen/commands.html#cmdprotocol
|
|
|
|
\section _arch Architecture
|
|
|
|
\subsection _mac MAC
|
|
thisis the mac
|
|
\subsection _rlc RLC
|
|
this is the rlc
|
|
\subsection _impl Implementation
|
|
what about the implementation
|
|
|
|
|
|
*@{*/
|
|
|
|
#include <pthread.h>
|
|
#include <stdint.h>
|
|
#include <sys/time.h>
|
|
#include "common/config/config_userapi.h"
|
|
#include "opt.h"
|
|
#include "common/utils/system.h"
|
|
|
|
int opt_enabled=0;
|
|
|
|
//static unsigned char g_PDUBuffer[1600];
|
|
//static unsigned int g_PDUOffset;
|
|
|
|
FILE *file_fd = NULL;
|
|
const pcap_hdr_t file_header = {
|
|
0xa1b2c3d4, /* magic number */
|
|
2,
|
|
4, /* version number is 2.4 */
|
|
0, /* timezone */
|
|
0, /* sigfigs - apparently all tools do this */
|
|
65535, /* snaplen - this should be long enough */
|
|
DLT_IPV4
|
|
// MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */
|
|
};
|
|
|
|
trace_mode_t opt_type = OPT_NONE;
|
|
static char *in_type=NULL;
|
|
static char *in_path=NULL;
|
|
static char *in_ip=NULL;
|
|
static unsigned int subframesSinceCaptureStart;
|
|
|
|
static int g_socksd = -1;/* UDP socket used for sending frames */
|
|
static struct sockaddr_in g_serv_addr;
|
|
|
|
typedef struct {
|
|
pthread_t thread;
|
|
int sd;
|
|
struct sockaddr_in address;
|
|
} opt_listener_t;
|
|
|
|
opt_listener_t opt_listener;
|
|
|
|
unsigned short checksum(unsigned short *ptr, int length) {
|
|
int sum = 0;
|
|
u_short answer = 0;
|
|
unsigned short *w = ptr;
|
|
int nleft = length;
|
|
|
|
while(nleft > 1) {
|
|
sum += *w++;
|
|
nleft -= 2;
|
|
}
|
|
|
|
sum = (sum >> 16) + (sum & 0xFFFF);
|
|
sum += (sum >> 16);
|
|
answer = ~sum;
|
|
return(answer);
|
|
}
|
|
|
|
/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */
|
|
static int PCAP_WritePDU(const uint8_t *PDU,
|
|
unsigned int length) {
|
|
pcaprec_hdr_t packet_header;
|
|
// IPv4 header
|
|
typedef struct ip_hdr {
|
|
unsigned char ip_verlen; // 4-bit IPv4 version 4-bit header length (in 32-bit words)
|
|
unsigned char ip_tos; // IP type of service
|
|
unsigned short ip_totallength; // Total length
|
|
unsigned short ip_id; // Unique identifier
|
|
unsigned short ip_offset; // Fragment offset field
|
|
unsigned char ip_ttl; // Time to live
|
|
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
|
|
unsigned short ip_checksum; // IP checksum
|
|
unsigned int ip_srcaddr; // Source address
|
|
unsigned int ip_destaddr; // Source address
|
|
} IPV4_HDR;
|
|
// Define the UDP header
|
|
typedef struct udp_hdr {
|
|
unsigned short src_portno; // Source port no.
|
|
unsigned short dst_portno; // Dest. port no.
|
|
unsigned short udp_length; // Udp packet length
|
|
unsigned short udp_checksum; // Udp checksum (optional)
|
|
} UDP_HDR;
|
|
IPV4_HDR IPheader= {0};
|
|
IPheader.ip_verlen = (4 << 4) | (sizeof(IPV4_HDR) / sizeof(uint32_t));
|
|
IPheader.ip_totallength = htons(sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length);
|
|
IPheader.ip_ttl = 8; // Time-to-live is eight
|
|
IPheader.ip_protocol = IPPROTO_UDP;
|
|
IPheader.ip_srcaddr = inet_addr(in_ip);
|
|
IPheader.ip_destaddr = inet_addr(in_ip);
|
|
IPheader.ip_checksum = checksum((unsigned short *)&IPheader, sizeof(IPV4_HDR));
|
|
// Initialize the UDP header
|
|
UDP_HDR UDPheader;
|
|
UDPheader.src_portno = htons( PACKET_MAC_LTE_DEFAULT_UDP_PORT);
|
|
UDPheader.dst_portno = htons( PACKET_MAC_LTE_DEFAULT_UDP_PORT);
|
|
UDPheader.udp_length = htons(sizeof(UDP_HDR) + length);
|
|
UDPheader.udp_checksum = 0;
|
|
/****************************************************************/
|
|
/* PCAP Header */
|
|
/* TODO: Timestamp might want to be relative to a more sensible
|
|
base time... */
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
packet_header.ts_sec = tv.tv_sec;
|
|
packet_header.ts_usec = tv.tv_usec;
|
|
packet_header.incl_len =sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length;
|
|
packet_header.orig_len =sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length;
|
|
/***************************************************************/
|
|
/* Now write everything to the file */
|
|
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, file_fd);
|
|
fwrite(&IPheader, sizeof(IPV4_HDR), 1, file_fd);
|
|
fwrite(&UDPheader, sizeof(UDP_HDR), 1, file_fd);
|
|
fwrite(PDU, 1, length, file_fd);
|
|
fflush(file_fd);
|
|
return length;
|
|
}
|
|
|
|
static void *opt_listener_thread(void *arg) {
|
|
ssize_t ret;
|
|
struct sockaddr_in from_address;
|
|
socklen_t socklen = sizeof(from_address);
|
|
memset(&from_address, 0, sizeof(from_address));
|
|
|
|
while(1) {
|
|
/* Simply drop packets */
|
|
ret = recvfrom(opt_listener.sd, NULL, 0, 0, (struct sockaddr *)&from_address,
|
|
&socklen);
|
|
|
|
if (ret == 0) {
|
|
LOG_D(OPT, "Remote host is no more connected, exiting thread\n");
|
|
pthread_exit(NULL);
|
|
} else if (ret < 0) {
|
|
/* Errors */
|
|
LOG_E(OPT, "An error occured during recvfrom: %s\n", strerror(errno));
|
|
pthread_exit(NULL);
|
|
} else {
|
|
/* Normal read -> discard PDU */
|
|
LOG_D(OPT, "Incoming data received from: %s:%u with length %zd\n",
|
|
inet_ntoa(opt_listener.address.sin_addr),
|
|
ntohs(opt_listener.address.sin_port), ret);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static
|
|
int opt_create_listener_socket(char *ip_address, uint16_t port) {
|
|
/* Create an UDP socket and listen on it.
|
|
* Silently discard PDU received.
|
|
*/
|
|
int sd = -1;
|
|
int ret = -1;
|
|
memset(&opt_listener, 0, sizeof(opt_listener_t));
|
|
sd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (sd < 0) {
|
|
LOG_E(OPT, "Failed to create listener socket: %s\n", strerror(errno));
|
|
sd = -1;
|
|
opt_type = OPT_NONE;
|
|
return -1;
|
|
}
|
|
|
|
opt_listener.sd = sd;
|
|
opt_listener.address.sin_family = AF_INET;
|
|
/* Listening only on provided IP address */
|
|
opt_listener.address.sin_addr.s_addr = inet_addr(ip_address);
|
|
opt_listener.address.sin_port = htons(port);
|
|
ret = bind(opt_listener.sd, (struct sockaddr *) &opt_listener.address, sizeof(opt_listener.address));
|
|
|
|
if (ret != 0) {
|
|
LOG_E(OPT, "Failed to bind socket to (%s:%u): %s\n",
|
|
inet_ntoa(opt_listener.address.sin_addr),
|
|
ntohs(opt_listener.address.sin_port), strerror(errno));
|
|
// we log anyway as planned because other OAI process may have created the sink
|
|
close(opt_listener.sd);
|
|
opt_listener.sd = -1;
|
|
return -1;
|
|
}
|
|
|
|
threadCreate(&opt_listener.thread, opt_listener_thread, NULL, "optListener", -1, OAI_PRIORITY_RT_LOW);
|
|
return 0;
|
|
}
|
|
|
|
//struct mac_lte_info * mac_info;
|
|
|
|
// #define WIRESHARK_DEV
|
|
/* if you want to define this, then you need to
|
|
* 1. checkout the wireshark dev at : svn co http://anonsvn.wireshark.org/wireshark/trunk wireshark
|
|
* 2. copy the local packet-mac-lte.h and packet-mac-lte.c into epan/dissectors/
|
|
* 3. install it, read INSTALL
|
|
* 4. run the wireshark and capture packets from lo interface, and filter out icmp packet (!icmp)
|
|
* 5. run ./oasim -a -P0 -n 30 | grep OPT
|
|
*/
|
|
/* Add framing header to MAC PDU and send. */
|
|
static void SendFrame(guint8 radioType, ws_trace_t *t)
|
|
{
|
|
unsigned char frameBuffer[16000];
|
|
unsigned int frameOffset;
|
|
ssize_t bytesSent;
|
|
frameOffset = 0;
|
|
uint16_t tmp16;
|
|
memcpy(frameBuffer+frameOffset, MAC_LTE_START_STRING,
|
|
strlen(MAC_LTE_START_STRING));
|
|
frameOffset += strlen(MAC_LTE_START_STRING);
|
|
/******************************************************************************/
|
|
/* Now write out fixed fields (the mandatory elements of struct mac_lte_info) */
|
|
frameBuffer[frameOffset++] = radioType;
|
|
frameBuffer[frameOffset++] = t->direction;
|
|
frameBuffer[frameOffset++] = t->rntiType;
|
|
/*************************************/
|
|
/* Now optional fields */
|
|
/* RNTI */
|
|
frameBuffer[frameOffset++] = MAC_LTE_RNTI_TAG;
|
|
tmp16 = htons(t->rnti);
|
|
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
|
frameOffset += 2;
|
|
/* UEId */
|
|
frameBuffer[frameOffset++] = MAC_LTE_UEID_TAG;
|
|
tmp16 = htons(t->ueid);
|
|
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
|
frameOffset += 2;
|
|
/* Subframe number */
|
|
frameBuffer[frameOffset++] = MAC_LTE_FRAME_SUBFRAME_TAG;
|
|
tmp16 =
|
|
htons((t->sysFrame << 4) + t->subframe); // frame counter : this will give an expert info as wireshark expects SF and not F
|
|
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
|
frameOffset += 2;
|
|
frameBuffer[frameOffset++] = MAC_LTE_CRC_STATUS_TAG;
|
|
frameBuffer[frameOffset++] = t->crcStatus;
|
|
#ifdef WIRESHARK_DEV
|
|
frameOffset += 2;
|
|
tmp16 = htons(sfnSf); // subframe
|
|
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
|
frameOffset += 2;
|
|
#endif
|
|
|
|
/***********************************************************/
|
|
/* For these optional fields, no need to encode if value is default */
|
|
if (t->isPredefinedData) {
|
|
frameBuffer[frameOffset++] = MAC_LTE_PREDEFINED_DATA_TAG;
|
|
frameBuffer[frameOffset++] = t->isPredefinedData;
|
|
}
|
|
|
|
if (t->retx != 0) {
|
|
frameBuffer[frameOffset++] = MAC_LTE_RETX_TAG;
|
|
frameBuffer[frameOffset++] = t->retx;
|
|
}
|
|
|
|
//#ifdef WIRESHARK_DEV
|
|
|
|
/* Relating to out-of-band events */
|
|
/* N.B. dissector will only look to these fields if length is 0... */
|
|
if (t->pdu_buffer_size == 0) {
|
|
switch (t->oob_event) {
|
|
case ltemac_send_preamble :
|
|
LOG_D(OPT,
|
|
"ltemac_send_preamble event %02x."
|
|
//"%02x."
|
|
"%02x.%02x\n",
|
|
MAC_LTE_SEND_PREAMBLE_TAG,
|
|
// ltemac_send_preamble,
|
|
t->rnti,
|
|
t->oob_event_value);
|
|
//frameBuffer[frameOffset++]=0;
|
|
//frameBuffer[frameOffset++]=0;
|
|
//frameBuffer[frameOffset++]=0;
|
|
frameBuffer[frameOffset++] = MAC_LTE_SEND_PREAMBLE_TAG;
|
|
//frameBuffer[frameOffset++]=ltemac_send_preamble;
|
|
frameBuffer[frameOffset++] = t->rnti; // is the preamble
|
|
frameBuffer[frameOffset++] = t->oob_event_value;
|
|
break;
|
|
|
|
case ltemac_send_sr:
|
|
frameBuffer[frameOffset++]=MAC_LTE_SR_TAG ;
|
|
frameOffset+=2;
|
|
frameBuffer[frameOffset++] = t->rnti;
|
|
frameOffset++;
|
|
frameBuffer[frameOffset++] = t->oob_event_value;
|
|
frameOffset++;
|
|
break;
|
|
|
|
case ltemac_sr_failure:
|
|
default:
|
|
LOG_W(OPT,"not implemeneted yet\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
//#endif
|
|
/***************************************/
|
|
/* Now write the MAC PDU */
|
|
frameBuffer[frameOffset++] = MAC_LTE_PAYLOAD_TAG;
|
|
|
|
/* Append actual PDU */
|
|
//memcpy(frameBuffer+frameOffset, g_PDUBuffer, g_PDUOffset);
|
|
//frameOffset += g_PDUOffset;
|
|
if (t->pdu_buffer != NULL) {
|
|
const int sz = min(t->pdu_buffer_size, sizeof(frameBuffer) - frameOffset);
|
|
memcpy(frameBuffer + frameOffset, t->pdu_buffer, sz);
|
|
if (t->pdu_buffer_size != sz)
|
|
LOG_W(OPT, "pdu is huge : %d\n", t->pdu_buffer_size);
|
|
frameOffset += sz;
|
|
}
|
|
|
|
if ( opt_type == OPT_WIRESHARK )
|
|
/* Send out the data over the UDP socket */
|
|
bytesSent = sendto(g_socksd, frameBuffer, frameOffset, 0,
|
|
(const struct sockaddr *)&g_serv_addr, sizeof(g_serv_addr));
|
|
else
|
|
bytesSent = PCAP_WritePDU(frameBuffer, frameOffset);
|
|
|
|
if (bytesSent != frameOffset) {
|
|
LOG_W(OPT, "trace_pdu expected %d bytes, got %ld (errno=%d)\n",
|
|
frameOffset, bytesSent, errno);
|
|
//exit(1);
|
|
}
|
|
}
|
|
|
|
static void SendFrameNR(guint8 radioType, ws_trace_t *t)
|
|
{
|
|
unsigned char frameBuffer[32000];
|
|
unsigned int frameOffset;
|
|
ssize_t bytesSent;
|
|
frameOffset = 0;
|
|
uint16_t tmp16;
|
|
memcpy(frameBuffer+frameOffset, MAC_NR_START_STRING,
|
|
strlen(MAC_NR_START_STRING));
|
|
frameOffset += strlen(MAC_NR_START_STRING);
|
|
/******************************************************************************/
|
|
/* Now write out fixed fields (the mandatory elements of struct mac_lte_info) */
|
|
frameBuffer[frameOffset++] = radioType;
|
|
frameBuffer[frameOffset++] = t->direction;
|
|
frameBuffer[frameOffset++] = t->rntiType;
|
|
/*************************************/
|
|
/* Now optional fields */
|
|
/* RNTI */
|
|
frameBuffer[frameOffset++] = MAC_NR_RNTI_TAG;
|
|
tmp16 = htons(t->rnti);
|
|
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
|
frameOffset += 2;
|
|
/* UEId */
|
|
frameBuffer[frameOffset++] = MAC_NR_UEID_TAG;
|
|
tmp16 = htons(t->ueid);
|
|
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
|
frameOffset += 2;
|
|
/* HARQid */
|
|
frameBuffer[frameOffset++] = MAC_NR_HARQID;
|
|
frameBuffer[frameOffset++] = t->harq_pid;
|
|
/* Subframe number */
|
|
frameBuffer[frameOffset++] = MAC_NR_FRAME_SLOT_TAG;
|
|
tmp16 = htons(t->sysFrame); // frame counter : this will give an expert info as wireshark expects SF and not F
|
|
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
|
frameOffset += 2;
|
|
tmp16 = htons(t->subframe); // frame counter : this will give an expert info as wireshark expects SF and not F
|
|
memcpy(frameBuffer+frameOffset, &tmp16, 2);
|
|
frameOffset += 2;
|
|
if (t->direction == 0) { // ulink
|
|
frameBuffer[frameOffset++] = MAC_NR_PHR_TYPE2_OTHERCELL_TAG;
|
|
frameBuffer[frameOffset++] = 0;
|
|
}
|
|
|
|
/***************************************/
|
|
/* Now write the MAC PDU */
|
|
frameBuffer[frameOffset++] = MAC_NR_PAYLOAD_TAG;
|
|
|
|
/* Append actual PDU */
|
|
//memcpy(frameBuffer+frameOffset, g_PDUBuffer, g_PDUOffset);
|
|
//frameOffset += g_PDUOffset;
|
|
if (t->pdu_buffer != NULL) {
|
|
const int sz = min(t->pdu_buffer_size, sizeof(frameBuffer) - frameOffset);
|
|
memcpy(frameBuffer + frameOffset, t->pdu_buffer, sz);
|
|
if (sz != t->pdu_buffer_size)
|
|
LOG_W(OPT, "large pdu: %d\n", t->pdu_buffer_size);
|
|
frameOffset += sz;
|
|
}
|
|
|
|
if ( opt_type == OPT_WIRESHARK )
|
|
/* Send out the data over the UDP socket */
|
|
bytesSent = sendto(g_socksd, frameBuffer, frameOffset, 0,
|
|
(const struct sockaddr *)&g_serv_addr, sizeof(g_serv_addr));
|
|
else
|
|
bytesSent = PCAP_WritePDU(frameBuffer, frameOffset);
|
|
|
|
if (bytesSent != frameOffset) {
|
|
LOG_W(OPT, "trace_pdu expected %d bytes, got %ld (errno=%d)\n",
|
|
frameOffset, bytesSent, errno);
|
|
//exit(1);
|
|
}
|
|
}
|
|
|
|
#include <common/ran_context.h>
|
|
extern RAN_CONTEXT_t RC;
|
|
#include <openair1/PHY/phy_extern_ue.h>
|
|
/* Remote serveraddress (where Wireshark is running) */
|
|
|
|
void trace_pdu_implementation(ws_trace_t *t)
|
|
{
|
|
int radioType = FDD_RADIO;
|
|
LOG_D(OPT,
|
|
"sending packet to wireshark: direction=%s, size: %d, ueid: %d, rnti: %x, frame/sf: %d.%d\n",
|
|
t->direction ? "DL" : "UL",
|
|
t->pdu_buffer_size,
|
|
t->ueid,
|
|
t->rnti,
|
|
t->sysFrame,
|
|
t->subframe);
|
|
|
|
if (t->nr) {
|
|
radioType = TDD_RADIO;
|
|
} else {
|
|
if (RC.eNB && RC.eNB[0][0] != NULL)
|
|
radioType = RC.eNB[0][0]->frame_parms.frame_type == FDD ? FDD_RADIO : TDD_RADIO;
|
|
else if (PHY_vars_UE_g && PHY_vars_UE_g[0][0] != NULL)
|
|
radioType = PHY_vars_UE_g[0][0]->frame_parms.frame_type == FDD ? FDD_RADIO : TDD_RADIO;
|
|
else {
|
|
LOG_E(OPT, "not a 4G eNB neither a 4G UE!!! \n");
|
|
}
|
|
}
|
|
|
|
switch (opt_type) {
|
|
case OPT_WIRESHARK:
|
|
if (g_socksd == -1)
|
|
return;
|
|
|
|
break;
|
|
|
|
case OPT_PCAP:
|
|
if (file_fd == NULL)
|
|
return;
|
|
|
|
break;
|
|
|
|
case OPT_TSHARK:
|
|
default:
|
|
return;
|
|
break;
|
|
}
|
|
|
|
if (t->nr)
|
|
SendFrameNR(radioType, t);
|
|
else
|
|
SendFrame(radioType, t);
|
|
}
|
|
|
|
/*---------------------------------------------------*/
|
|
int init_opt(void) {
|
|
paramdef_t opt_params[] = OPT_PARAMS_DESC ;
|
|
checkedparam_t opt_checkParams[] = OPTPARAMS_CHECK_DESC;
|
|
int sz=sizeofArray(opt_params);
|
|
AssertFatal(sz == sizeofArray(opt_checkParams), "Error in arrays size (%d!=%lu)\n", sz, sizeofArray(opt_checkParams));
|
|
config_set_checkfunctions(opt_params, opt_checkParams, sz);
|
|
config_get(config_get_if(), opt_params, sz, OPT_CONFIGPREFIX);
|
|
subframesSinceCaptureStart = 0;
|
|
int tmptype = config_get_processedint(config_get_if(), &(opt_params[OPTTYPE_IDX]));
|
|
|
|
if (tmptype == OPT_NONE) {
|
|
opt_enabled=0;
|
|
LOG_I(OPT,"OPT disabled\n");
|
|
return 0;
|
|
} else if (tmptype == OPT_PCAP && strlen(in_path) > 0) {
|
|
opt_type = OPT_PCAP;
|
|
opt_enabled=1;
|
|
} else if (tmptype == OPT_WIRESHARK && strlen(in_ip) > 0) {
|
|
opt_enabled=1;
|
|
opt_type = OPT_WIRESHARK;
|
|
} else {
|
|
LOG_E(OPT,"Invalid OPT configuration\n");
|
|
config_printhelp(opt_params, sizeofArray(opt_params), OPT_CONFIGPREFIX);
|
|
}
|
|
|
|
// trace_mode
|
|
switch (opt_type) {
|
|
case OPT_WIRESHARK:
|
|
LOG_I(OPT,"mode Wireshark: ip %s port %d\n", in_ip, PACKET_MAC_LTE_DEFAULT_UDP_PORT);
|
|
/* Create local server socket only if using localhost address */
|
|
if (strncmp(in_ip, "127.0.0.1", 4) == 0) {
|
|
opt_create_listener_socket(in_ip, PACKET_MAC_LTE_DEFAULT_UDP_PORT);
|
|
}
|
|
|
|
g_socksd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (g_socksd == -1) {
|
|
LOG_E(OPT, "Error trying to create socket (errno=%d)\n", errno);
|
|
LOG_E(OPT, "CREATING SOCKET FAILED\n");
|
|
return (-1);
|
|
}
|
|
|
|
/* Get remote IP address from the function argument */
|
|
g_serv_addr.sin_family = AF_INET;
|
|
g_serv_addr.sin_port = htons(PACKET_MAC_LTE_DEFAULT_UDP_PORT);
|
|
g_serv_addr.sin_addr.s_addr = inet_addr(in_ip);
|
|
break;
|
|
|
|
case OPT_PCAP:
|
|
LOG_I(OPT,"mode PCAB : path is %s \n",in_path);
|
|
file_fd = fopen(in_path, "w");
|
|
|
|
if (file_fd == NULL) {
|
|
LOG_D(OPT, "Failed to open file \"%s\" for writing\n", in_path);
|
|
return (-1);
|
|
}
|
|
|
|
/* Write the file header */
|
|
fwrite(&file_header, sizeof(pcap_hdr_t), 1, file_fd);
|
|
break;
|
|
|
|
case OPT_TSHARK:
|
|
LOG_W(OPT, "Tshark is currently not supported\n");
|
|
opt_type = OPT_NONE;
|
|
break;
|
|
|
|
default:
|
|
opt_type = OPT_NONE;
|
|
LOG_E(OPT,"Unsupported or unknown mode %d \n", opt_type);
|
|
break;
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
void terminate_opt(void) {
|
|
/* Close local socket */
|
|
// free(mac_info);
|
|
if (opt_type != OPT_NONE) {
|
|
pthread_cancel(opt_listener.thread);
|
|
}
|
|
|
|
switch (opt_type) {
|
|
case OPT_WIRESHARK:
|
|
close(g_socksd);
|
|
g_socksd = -1;
|
|
break;
|
|
|
|
case OPT_PCAP:
|
|
fclose (file_fd);
|
|
file_fd = NULL;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
/** @}*/
|