mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-04-19 01:03:15 +00:00
Replacing GNURadio udp packet source with custom libpcap-based ethernet packet source
This commit is contained in:
parent
0ef3b56e22
commit
bde6bd6cee
@ -1455,6 +1455,34 @@ if(ENABLE_GPROF)
|
||||
endif(ENABLE_GPROF)
|
||||
|
||||
|
||||
# - Try to find libpcap include dirs and libraries
|
||||
#
|
||||
# Usage of this module as follows:
|
||||
#
|
||||
# find_package(PCAP)
|
||||
#
|
||||
# Variables used by this module, they can change the default behaviour and need
|
||||
# to be set before calling find_package:
|
||||
#
|
||||
# PCAP_ROOT_DIR Set this variable to the root installation of
|
||||
# libpcap if the module has problems finding the
|
||||
# proper installation path.
|
||||
#
|
||||
# Variables defined by this module:
|
||||
#
|
||||
# PCAP_FOUND System has libpcap, include and library dirs found
|
||||
# PCAP_INCLUDE_DIR The libpcap include directories.
|
||||
# PCAP_LIBRARY The libpcap library (possibly includes a thread
|
||||
# library e.g. required by pf_ring's libpcap)
|
||||
# HAVE_PF_RING If a found version of libpcap supports PF_RING
|
||||
find_package(PCAP)
|
||||
if(NOT PCAP_FOUND)
|
||||
message(FATAL_ERROR "PCAP required to compile dbfcttc")
|
||||
endif()
|
||||
get_filename_component(PCAP_LIBRARY_DIRS ${PCAP_LIBRARY} DIRECTORY CACHE)
|
||||
|
||||
|
||||
|
||||
|
||||
########################################################################
|
||||
# Set compiler flags
|
||||
|
122
cmake/Modules/FindPCAP.cmake
Normal file
122
cmake/Modules/FindPCAP.cmake
Normal file
@ -0,0 +1,122 @@
|
||||
|
||||
###################################################################
|
||||
#
|
||||
# Copyright (c) 2006 Frederic Heem, <frederic.heem@telsey.it>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * 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.
|
||||
#
|
||||
# * Neither the name of the Telsey nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE
|
||||
# COPYRIGHT OWNER 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.
|
||||
#
|
||||
###################################################################
|
||||
# - Find pcap
|
||||
# Find the PCAP includes and library
|
||||
# http://www.tcpdump.org/
|
||||
#
|
||||
# The environment variable PCAPDIR allows to specficy where to find
|
||||
# libpcap in non standard location.
|
||||
#
|
||||
# PCAP_INCLUDE_DIRS - where to find pcap.h, etc.
|
||||
# PCAP_LIBRARIES - List of libraries when using pcap.
|
||||
# PCAP_FOUND - True if pcap found.
|
||||
|
||||
|
||||
IF(EXISTS $ENV{PCAPDIR})
|
||||
FIND_PATH(PCAP_INCLUDE_DIR
|
||||
NAMES
|
||||
pcap/pcap.h
|
||||
pcap.h
|
||||
PATHS
|
||||
$ENV{PCAPDIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
FIND_LIBRARY(PCAP_LIBRARY
|
||||
NAMES
|
||||
pcap
|
||||
PATHS
|
||||
$ENV{PCAPDIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
|
||||
ELSE(EXISTS $ENV{PCAPDIR})
|
||||
FIND_PATH(PCAP_INCLUDE_DIR
|
||||
NAMES
|
||||
pcap/pcap.h
|
||||
pcap.h
|
||||
)
|
||||
|
||||
FIND_LIBRARY(PCAP_LIBRARY
|
||||
NAMES
|
||||
pcap
|
||||
)
|
||||
|
||||
ENDIF(EXISTS $ENV{PCAPDIR})
|
||||
|
||||
SET(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR})
|
||||
SET(PCAP_LIBRARIES ${PCAP_LIBRARY})
|
||||
|
||||
IF(PCAP_INCLUDE_DIRS)
|
||||
MESSAGE(STATUS "Pcap include dirs set to ${PCAP_INCLUDE_DIRS}")
|
||||
ELSE(PCAP_INCLUDE_DIRS)
|
||||
MESSAGE(FATAL " Pcap include dirs cannot be found")
|
||||
ENDIF(PCAP_INCLUDE_DIRS)
|
||||
|
||||
IF(PCAP_LIBRARIES)
|
||||
MESSAGE(STATUS "Pcap library set to ${PCAP_LIBRARIES}")
|
||||
ELSE(PCAP_LIBRARIES)
|
||||
MESSAGE(FATAL "Pcap library cannot be found")
|
||||
ENDIF(PCAP_LIBRARIES)
|
||||
|
||||
#Functions
|
||||
INCLUDE(CheckFunctionExists)
|
||||
SET(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS})
|
||||
SET(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARIES})
|
||||
CHECK_FUNCTION_EXISTS("pcap_breakloop" HAVE_PCAP_BREAKLOOP)
|
||||
CHECK_FUNCTION_EXISTS("pcap_datalink_name_to_val" HAVE_PCAP_DATALINK_NAME_TO_VAL)
|
||||
CHECK_FUNCTION_EXISTS("pcap_datalink_val_to_name" HAVE_PCAP_DATALINK_VAL_TO_NAME)
|
||||
CHECK_FUNCTION_EXISTS("pcap_findalldevs" HAVE_PCAP_FINDALLDEVS)
|
||||
CHECK_FUNCTION_EXISTS("pcap_freecode" HAVE_PCAP_FREECODE)
|
||||
CHECK_FUNCTION_EXISTS("pcap_get_selectable_fd" HAVE_PCAP_GET_SELECTABLE_FD)
|
||||
CHECK_FUNCTION_EXISTS("pcap_lib_version" HAVE_PCAP_LIB_VERSION)
|
||||
CHECK_FUNCTION_EXISTS("pcap_list_datalinks" HAVE_PCAP_LIST_DATALINKS)
|
||||
CHECK_FUNCTION_EXISTS("pcap_open_dead" HAVE_PCAP_OPEN_DEAD)
|
||||
CHECK_FUNCTION_EXISTS("pcap_set_datalink" HAVE_PCAP_SET_DATALINK)
|
||||
|
||||
|
||||
#Is pcap found ?
|
||||
IF(PCAP_INCLUDE_DIRS AND PCAP_LIBRARIES)
|
||||
SET( PCAP_FOUND "YES" )
|
||||
ENDIF(PCAP_INCLUDE_DIRS AND PCAP_LIBRARIES)
|
||||
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
PCAP_LIBRARIES
|
||||
PCAP_INCLUDE_DIRS
|
||||
)
|
@ -14,9 +14,10 @@ SignalSource.implementation=UDP_Signal_Source
|
||||
;SignalSource.implementation=File_Signal_Source
|
||||
SignalSource.filename=/home/javier/gnss/gnss-simulator/build/signal_out.bin ; <- PUT YOUR FILE HERE
|
||||
SignalSource.item_type=gr_complex
|
||||
SignalSource.address=0.0.0.0
|
||||
SignalSource.origin_address=0.0.0.0
|
||||
SignalSource.capture_device=eth0
|
||||
SignalSource.port=1234
|
||||
SignalSource.payload_bytes=1024
|
||||
SignalSource.payload_bytes=1472
|
||||
SignalSource.sample_type=cbyte
|
||||
SignalSource.RF_channels=1
|
||||
SignalSource.select_single_channel=0
|
||||
@ -32,7 +33,7 @@ SignalConditioner.implementation=Pass_Through
|
||||
;SignalConditioner1.implementation=Pass_Through
|
||||
|
||||
;######### CHANNELS GLOBAL CONFIG ############
|
||||
Channels_1C.count=8
|
||||
Channels_1C.count=1
|
||||
Channels.in_acquisition=1
|
||||
|
||||
;# CHANNEL CONNECTION
|
||||
@ -49,7 +50,7 @@ Acquisition_1C.threshold=60
|
||||
Acquisition_1C.use_CFAR_algorithm=false
|
||||
Acquisition_1C.blocking=false
|
||||
Acquisition_1C.doppler_max=5000
|
||||
Acquisition_1C.doppler_step=250
|
||||
Acquisition_1C.doppler_step=500
|
||||
Acquisition_1C.dump=false
|
||||
Acquisition_1C.dump_filename=./acq_dump.dat
|
||||
|
||||
@ -57,7 +58,7 @@ Acquisition_1C.dump_filename=./acq_dump.dat
|
||||
;######### TRACKING GLOBAL CONFIG ############
|
||||
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
|
||||
Tracking_1C.item_type=gr_complex
|
||||
Tracking_1C.dump=true
|
||||
Tracking_1C.dump=false
|
||||
Tracking_1C.dump_filename=./tracking_ch_
|
||||
Tracking_1C.pll_bw_hz=35.0;
|
||||
Tracking_1C.dll_bw_hz=2.0;
|
||||
|
@ -54,8 +54,14 @@ UDPSignalSource::UDPSignalSource(ConfigurationInterface* configuration,
|
||||
default_dump_file);
|
||||
|
||||
// network PARAMETERS
|
||||
std::string default_capture_device = "eth0";
|
||||
std::string default_address = "127.0.0.1";
|
||||
int default_port = 1234;
|
||||
std::string address = configuration->property(role + ".origin_address", default_address);
|
||||
std::string capture_device = configuration->property(role + ".capture_device", default_capture_device);
|
||||
int port = configuration->property(role + ".port", default_port);
|
||||
int payload_bytes = configuration->property(role + ".payload_bytes", 1024);
|
||||
|
||||
|
||||
RF_channels_ = configuration->property(role + ".RF_channels", 1);
|
||||
select_single_channel_ = configuration->property(role + ".select_single_channel", 0);
|
||||
@ -64,19 +70,15 @@ UDPSignalSource::UDPSignalSource(ConfigurationInterface* configuration,
|
||||
|
||||
std::string default_sample_type = "cbyte";
|
||||
std::string sample_type = configuration->property(role + ".sample_type", default_sample_type);
|
||||
|
||||
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
||||
std::string address = configuration->property(role + ".address", default_address);
|
||||
int port = configuration->property(role + ".port", default_port);
|
||||
int payload_bytes = configuration->property(role + ".payload_bytes", 1024);
|
||||
|
||||
if (sample_type.compare("cbyte")==0)
|
||||
{
|
||||
udp_gnss_rx_source_ = make_udp_gnss_rx_source(sizeof(char), address, port, payload_bytes, true);
|
||||
udp_gnss_rx_source_ = raw_ip_packet_source::make(capture_device, address, port, payload_bytes);
|
||||
demux_=gr::blocks::deinterleave::make(sizeof(char),1);
|
||||
}else{
|
||||
std::cout<<"WARNING: Requested UDP sample type unsuported, setting sample type to cbyte\n";
|
||||
udp_gnss_rx_source_ = make_udp_gnss_rx_source(sizeof(char), address, port, payload_bytes, true);
|
||||
udp_gnss_rx_source_ = raw_ip_packet_source::make(capture_device, address, port, payload_bytes);
|
||||
demux_=gr::blocks::deinterleave::make(sizeof(char),1);
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
#define GNSS_SDR_UDP_SIGNAL_SOURCE_H
|
||||
|
||||
#include "gnss_block_interface.h"
|
||||
#include "udp_gnss_rx_source.h"
|
||||
#include "raw_ip_packet_source.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <gnuradio/msg_queue.h>
|
||||
#include <gnuradio/blocks/char_to_float.h>
|
||||
@ -103,7 +103,7 @@ private:
|
||||
std::vector<boost::shared_ptr<gr::block>> float_to_complex_;
|
||||
std::vector<boost::shared_ptr<gr::block>> null_sinks_;
|
||||
|
||||
udp_gnss_rx_source_sptr udp_gnss_rx_source_;
|
||||
raw_ip_packet_source::sptr udp_gnss_rx_source_;
|
||||
gr::blocks::deinterleave::sptr demux_;
|
||||
std::vector<boost::shared_ptr<gr::block>> file_sink_;
|
||||
boost::shared_ptr<gr::msg_queue> queue_;
|
||||
|
@ -25,7 +25,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
|
||||
unpack_2bit_samples.cc
|
||||
unpack_spir_gss6450_samples.cc
|
||||
labsat23_source.cc
|
||||
udp_gnss_rx_source.cc
|
||||
raw_ip_packet_source.cc
|
||||
)
|
||||
|
||||
include_directories(
|
||||
@ -41,5 +41,10 @@ file(GLOB SIGNAL_SOURCE_GR_BLOCKS_HEADERS "*.h")
|
||||
list(SORT SIGNAL_SOURCE_GR_BLOCKS_HEADERS)
|
||||
add_library(signal_source_gr_blocks ${SIGNAL_SOURCE_GR_BLOCKS_SOURCES} ${SIGNAL_SOURCE_GR_BLOCKS_HEADERS})
|
||||
source_group(Headers FILES ${SIGNAL_SOURCE_GR_BLOCKS_HEADERS})
|
||||
target_link_libraries(signal_source_gr_blocks signal_source_lib ${GNURADIO_RUNTIME_LIBRARIES} ${Boost_LIBRARIES})
|
||||
target_link_libraries(signal_source_gr_blocks
|
||||
signal_source_lib
|
||||
${GNURADIO_RUNTIME_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${PCAP_LIBRARIES}
|
||||
)
|
||||
add_dependencies(signal_source_gr_blocks glog-${glog_RELEASE})
|
||||
|
@ -0,0 +1,289 @@
|
||||
/*!
|
||||
* \file raw_ip_packet_source.cc
|
||||
*
|
||||
* \brief Receives ip frames containing samples in UDP frame encapsulation
|
||||
* using a high performance packet capture library (libpcap)
|
||||
* \author Javier Arribas jarribas (at) cttc.es
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include "raw_ip_packet_source.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define FIFO_SIZE 1000000
|
||||
|
||||
|
||||
/* 4 bytes IP address */
|
||||
typedef struct gr_ip_address{
|
||||
u_char byte1;
|
||||
u_char byte2;
|
||||
u_char byte3;
|
||||
u_char byte4;
|
||||
}gr_ip_address;
|
||||
|
||||
/* IPv4 header */
|
||||
typedef struct gr_ip_header{
|
||||
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
|
||||
u_char tos; // Type of service
|
||||
u_short tlen; // Total length
|
||||
u_short identification; // Identification
|
||||
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
|
||||
u_char ttl; // Time to live
|
||||
u_char proto; // Protocol
|
||||
u_short crc; // Header checksum
|
||||
gr_ip_address saddr; // Source address
|
||||
gr_ip_address daddr; // Destination address
|
||||
u_int op_pad; // Option + Padding
|
||||
}gr_ip_header;
|
||||
|
||||
/* UDP header*/
|
||||
typedef struct gr_udp_header{
|
||||
u_short sport; // Source port
|
||||
u_short dport; // Destination port
|
||||
u_short len; // Datagram length
|
||||
u_short crc; // Checksum
|
||||
}gr_udp_header;
|
||||
|
||||
raw_ip_packet_source::sptr
|
||||
raw_ip_packet_source::make(std::string src_device, std::string origin_address, int udp_port, int udp_packet_size)
|
||||
{
|
||||
return gnuradio::get_initial_sptr
|
||||
(new raw_ip_packet_source(src_device, origin_address, udp_port, udp_packet_size));
|
||||
}
|
||||
|
||||
/*
|
||||
* The private constructor
|
||||
*/
|
||||
raw_ip_packet_source::raw_ip_packet_source(std::string src_device, std::string origin_address, int udp_port, int udp_packet_size)
|
||||
: gr::sync_block("raw_ip_packet_source",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 1, sizeof(char)))
|
||||
{
|
||||
|
||||
// constructor code here
|
||||
std::cout<<"Start Ethernet packet capture\n";
|
||||
|
||||
d_src_device=src_device;
|
||||
d_udp_port=udp_port;
|
||||
d_udp_payload_size=udp_packet_size;
|
||||
d_fifo_full=false;
|
||||
d_last_frame_counter=0;
|
||||
d_num_rx_errors=0;
|
||||
|
||||
//allocate signal samples buffer
|
||||
fifo_buff=new char[FIFO_SIZE];
|
||||
fifo_read_ptr=0;
|
||||
fifo_write_ptr=0;
|
||||
fifo_items=0;
|
||||
|
||||
//open the ethernet device
|
||||
if (open()==true)
|
||||
{
|
||||
// start pcap capture thread
|
||||
d_pcap_thread=new boost::thread(boost::bind(&raw_ip_packet_source::my_pcap_loop_thread,this,descr));
|
||||
}else{
|
||||
exit(1); //ethernet error!
|
||||
}
|
||||
}
|
||||
|
||||
bool raw_ip_packet_source::open()
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
|
||||
/* open device for reading */
|
||||
descr = pcap_open_live(d_src_device.c_str(),1500,1,1000,errbuf);
|
||||
if(descr == NULL)
|
||||
{
|
||||
std::cout<<"Error openning Ethernet device "<<d_src_device<<std::endl;
|
||||
printf("Fatal Error in pcap_open_live(): %s\n",errbuf);
|
||||
return false;
|
||||
}
|
||||
//bind UDP port to avoid automatic reply with ICMP port ureacheable packets from kernel
|
||||
d_sock_raw = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP);
|
||||
if(d_sock_raw == -1)
|
||||
{
|
||||
std::cout<<"Error openning UDP socket"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// zero out the structure
|
||||
memset((char *) &si_me, 0, sizeof(si_me));
|
||||
|
||||
si_me.sin_family = AF_INET;
|
||||
si_me.sin_port = htons(d_udp_port);
|
||||
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
//bind socket to port
|
||||
if( bind(d_sock_raw , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
|
||||
{
|
||||
std::cout<<"Error openning UDP socket"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Our virtual destructor.
|
||||
*/
|
||||
raw_ip_packet_source::~raw_ip_packet_source()
|
||||
{
|
||||
if(descr != NULL)
|
||||
{
|
||||
pcap_breakloop(descr);
|
||||
d_pcap_thread->join();
|
||||
pcap_close(descr);
|
||||
}
|
||||
|
||||
delete fifo_buff;
|
||||
std::cout<<"Stop Ethernet packet capture\n";
|
||||
|
||||
}
|
||||
|
||||
void raw_ip_packet_source::static_pcap_callback(u_char *args, const struct pcap_pkthdr* pkthdr,
|
||||
const u_char* packet)
|
||||
{
|
||||
raw_ip_packet_source *bridge=(raw_ip_packet_source*) args;
|
||||
bridge->pcap_callback(args, pkthdr, packet);
|
||||
}
|
||||
|
||||
void raw_ip_packet_source::pcap_callback(u_char *args, const struct pcap_pkthdr* pkthdr,
|
||||
const u_char* packet)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
|
||||
|
||||
gr_ip_header *ih;
|
||||
gr_udp_header *uh;
|
||||
|
||||
// eth frame parameters
|
||||
// **** UDP RAW PACKET DECODER ****
|
||||
if ((packet[12]==0x08) & (packet[13]==0x00)) //IP FRAME
|
||||
{
|
||||
|
||||
/* retireve the position of the ip header */
|
||||
ih = (gr_ip_header *) (packet +
|
||||
14); //length of ethernet header
|
||||
|
||||
/* retireve the position of the udp header */
|
||||
u_int ip_len;
|
||||
ip_len = (ih->ver_ihl & 0xf) * 4;
|
||||
uh = (gr_udp_header *) ((u_char*)ih + ip_len);
|
||||
|
||||
/* convert from network byte order to host byte order */
|
||||
u_short sport,dport;
|
||||
dport = ntohs( uh->dport );
|
||||
sport = ntohs( uh->sport );
|
||||
if (dport==d_udp_port)
|
||||
{
|
||||
// print ip addresses and udp ports
|
||||
// printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
|
||||
// ih->saddr.byte1,
|
||||
// ih->saddr.byte2,
|
||||
// ih->saddr.byte3,
|
||||
// ih->saddr.byte4,
|
||||
// sport,
|
||||
// ih->daddr.byte1,
|
||||
// ih->daddr.byte2,
|
||||
// ih->daddr.byte3,
|
||||
// ih->daddr.byte4,
|
||||
// dport);
|
||||
// std::cout<<"d_udp_port:"<<d_udp_port<<std::endl;
|
||||
//snapshots reading..
|
||||
u_char* udp_payload=((u_char*)uh+sizeof(gr_udp_header));
|
||||
if (fifo_items<=(FIFO_SIZE-d_udp_payload_size))
|
||||
{
|
||||
int aligned_write_items=FIFO_SIZE-fifo_write_ptr;
|
||||
if (aligned_write_items>=d_udp_payload_size)
|
||||
{
|
||||
//write all in a single memcpy
|
||||
memcpy(&fifo_buff[fifo_write_ptr],&udp_payload[0],d_udp_payload_size); //size in bytes
|
||||
fifo_write_ptr+=d_udp_payload_size;
|
||||
if (fifo_write_ptr==FIFO_SIZE) fifo_write_ptr=0;
|
||||
fifo_items+=d_udp_payload_size;
|
||||
}else{
|
||||
//two step wrap write
|
||||
memcpy(&fifo_buff[fifo_write_ptr],&udp_payload[0],aligned_write_items); //size in bytes
|
||||
fifo_write_ptr=d_udp_payload_size-aligned_write_items;
|
||||
memcpy(&fifo_buff[0],&udp_payload[aligned_write_items],fifo_write_ptr); //size in bytes
|
||||
fifo_items+=d_udp_payload_size;
|
||||
}
|
||||
}else{
|
||||
std::cout<<"Ou"<<std::flush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void raw_ip_packet_source::my_pcap_loop_thread(pcap_t *pcap_handle)
|
||||
|
||||
{
|
||||
|
||||
pcap_loop(pcap_handle, -1, raw_ip_packet_source::static_pcap_callback, (u_char *)this);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
raw_ip_packet_source::work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
|
||||
// send samples to next GNU Radio block
|
||||
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
|
||||
int num_samples_readed;
|
||||
|
||||
if (noutput_items<fifo_items)
|
||||
{
|
||||
num_samples_readed=noutput_items;//read all
|
||||
}else{
|
||||
num_samples_readed=fifo_items;//read what we have
|
||||
}
|
||||
|
||||
int aligned_read_items=FIFO_SIZE-fifo_read_ptr;
|
||||
if (aligned_read_items>=num_samples_readed)
|
||||
{
|
||||
//read all in a single memcpy
|
||||
memcpy(&((char*)output_items[0])[0],&fifo_buff[fifo_read_ptr],num_samples_readed);
|
||||
fifo_read_ptr=fifo_read_ptr+num_samples_readed; //increase the fifo pointer
|
||||
if (fifo_read_ptr==FIFO_SIZE) fifo_read_ptr=0;
|
||||
}else{
|
||||
//two step wrap read
|
||||
memcpy(&((char*)output_items[0])[0],&fifo_buff[fifo_read_ptr],aligned_read_items);
|
||||
fifo_read_ptr=num_samples_readed-aligned_read_items;//increase the fifo pointer considering the rollover
|
||||
memcpy(&((char*)output_items[0])[aligned_read_items],&fifo_buff[0],fifo_read_ptr);
|
||||
}
|
||||
|
||||
fifo_items=fifo_items-num_samples_readed;
|
||||
|
||||
// Tell runtime system how many output items we produced.
|
||||
//std::cout<<"fifo_items:"<<fifo_items<<"n:"<<num_samples_readed<<".";
|
||||
return num_samples_readed;
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*!
|
||||
* \file raw_ip_packet_source.h
|
||||
*
|
||||
* \brief Receives ip frames containing samples in UDP frame encapsulation
|
||||
* using a high performance packet capture library (libpcap)
|
||||
* \author Javier Arribas jarribas (at) cttc.es
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef INCLUDED_RAW_IP_PACKET_SOURCE_H
|
||||
#define INCLUDED_RAW_IP_PACKET_SOURCE_H
|
||||
|
||||
#include <gnuradio/sync_block.h>
|
||||
#include <boost/thread.hpp>
|
||||
#include <pcap.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
class raw_ip_packet_source : virtual public gr::sync_block
|
||||
{
|
||||
private:
|
||||
boost::mutex d_mutex;
|
||||
|
||||
pcap_t* descr; //ethernet pcap device descriptor
|
||||
int fifo_pipe[2];
|
||||
|
||||
char *fifo_buff;
|
||||
|
||||
int fifo_read_ptr;
|
||||
int fifo_write_ptr;
|
||||
int fifo_items;
|
||||
int d_sock_raw;
|
||||
int d_udp_port;
|
||||
struct sockaddr_in si_me;
|
||||
std::string d_src_device;
|
||||
std::string d_origin_address;
|
||||
int d_udp_payload_size;
|
||||
bool d_fifo_full;
|
||||
|
||||
int d_last_frame_counter;
|
||||
int d_num_rx_errors;
|
||||
|
||||
|
||||
boost::thread *d_pcap_thread;
|
||||
/*!
|
||||
* \brief
|
||||
* Opens the ethernet device using libpcap raw capture mode
|
||||
* If any of these fail, the fuction retuns the error and exits.
|
||||
*/
|
||||
bool open();
|
||||
|
||||
void my_pcap_loop_thread(pcap_t *pcap_handle);
|
||||
|
||||
void pcap_callback(u_char *args, const struct pcap_pkthdr* pkthdr, const u_char* packet);
|
||||
|
||||
static void static_pcap_callback(u_char *args, const struct pcap_pkthdr* pkthdr, const u_char* packet);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
typedef boost::shared_ptr<raw_ip_packet_source> sptr;
|
||||
static sptr make(std::string src_device, std::string origin_address, int udp_port, int udp_packet_size);
|
||||
raw_ip_packet_source(std::string src_device, std::string origin_address, int udp_port, int udp_packet_size);
|
||||
~raw_ip_packet_source();
|
||||
|
||||
// Where all the action really happens
|
||||
int work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_RAW_IP_PACKET_SOURCE_H */
|
||||
|
@ -1,215 +0,0 @@
|
||||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007-2010,2013 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "udp_gnss_rx_source.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <gnuradio/math.h>
|
||||
#include <gnuradio/prefs.h>
|
||||
#include <stdexcept>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
const int udp_gnss_rx_source::BUF_SIZE_PAYLOADS =
|
||||
gr::prefs::singleton()->get_long("udp_blocks", "buf_size_payloads", 50);
|
||||
|
||||
udp_gnss_rx_source_sptr
|
||||
make_udp_gnss_rx_source(size_t itemsize,
|
||||
const std::string &ipaddr, int port,
|
||||
int payload_size, bool eof)
|
||||
{
|
||||
return gnuradio::get_initial_sptr
|
||||
(new udp_gnss_rx_source(itemsize, ipaddr, port,
|
||||
payload_size, eof));
|
||||
}
|
||||
|
||||
udp_gnss_rx_source::udp_gnss_rx_source(size_t itemsize,
|
||||
const std::string &host, int port,
|
||||
int payload_size, bool eof)
|
||||
: sync_block("udp_gnss_rx_source",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 1, itemsize)),
|
||||
d_itemsize(itemsize), d_payload_size(payload_size),
|
||||
d_eof(eof), d_connected(false), d_residual(0), d_sent(0), d_offset(0)
|
||||
{
|
||||
// Give us some more room to play.
|
||||
d_rxbuf = new char[4*d_payload_size];
|
||||
d_residbuf = new char[BUF_SIZE_PAYLOADS*d_payload_size];
|
||||
|
||||
connect(host, port);
|
||||
}
|
||||
|
||||
udp_gnss_rx_source::~udp_gnss_rx_source()
|
||||
{
|
||||
if(d_connected)
|
||||
disconnect();
|
||||
|
||||
delete [] d_rxbuf;
|
||||
delete [] d_residbuf;
|
||||
}
|
||||
|
||||
void
|
||||
udp_gnss_rx_source::connect(const std::string &host, int port)
|
||||
{
|
||||
if(d_connected)
|
||||
disconnect();
|
||||
|
||||
d_host = host;
|
||||
d_port = static_cast<unsigned short>(port);
|
||||
|
||||
std::string s_port;
|
||||
s_port = (boost::format("%d")%d_port).str();
|
||||
|
||||
if(host.size() > 0) {
|
||||
boost::asio::ip::udp::resolver resolver(d_io_service);
|
||||
boost::asio::ip::udp::resolver::query query(d_host, s_port,
|
||||
boost::asio::ip::resolver_query_base::passive);
|
||||
d_endpoint = *resolver.resolve(query);
|
||||
|
||||
d_socket = new boost::asio::ip::udp::socket(d_io_service);
|
||||
d_socket->open(d_endpoint.protocol());
|
||||
|
||||
boost::asio::socket_base::reuse_address roption(true);
|
||||
d_socket->set_option(roption);
|
||||
|
||||
d_socket->bind(d_endpoint);
|
||||
|
||||
start_receive();
|
||||
d_udp_thread = gr::thread::thread(boost::bind(&udp_gnss_rx_source::run_io_service, this));
|
||||
d_connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
udp_gnss_rx_source::disconnect()
|
||||
{
|
||||
gr::thread::scoped_lock lock(d_setlock);
|
||||
|
||||
if(!d_connected)
|
||||
return;
|
||||
|
||||
d_io_service.reset();
|
||||
d_io_service.stop();
|
||||
d_udp_thread.join();
|
||||
|
||||
d_socket->close();
|
||||
delete d_socket;
|
||||
|
||||
d_connected = false;
|
||||
}
|
||||
|
||||
// Return port number of d_socket
|
||||
int
|
||||
udp_gnss_rx_source::get_port(void)
|
||||
{
|
||||
//return d_endpoint.port();
|
||||
return d_socket->local_endpoint().port();
|
||||
}
|
||||
|
||||
void
|
||||
udp_gnss_rx_source::start_receive()
|
||||
{
|
||||
d_socket->async_receive_from(boost::asio::buffer((void*)d_rxbuf, d_payload_size), d_endpoint_rcvd,
|
||||
boost::bind(&udp_gnss_rx_source::handle_read, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void
|
||||
udp_gnss_rx_source::handle_read(const boost::system::error_code& error,
|
||||
size_t bytes_transferred)
|
||||
{
|
||||
if(!error) {
|
||||
{
|
||||
boost::lock_guard<gr::thread::mutex> lock(d_udp_mutex);
|
||||
if(d_eof && (bytes_transferred == 0)) {
|
||||
// If we are using EOF notification, test for it and don't
|
||||
// add anything to the output.
|
||||
d_residual = WORK_DONE;
|
||||
d_cond_wait.notify_one();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// Make sure we never go beyond the boundary of the
|
||||
// residual buffer. This will just drop the last bit of
|
||||
// data in the buffer if we've run out of room.
|
||||
if((int)(d_residual + bytes_transferred) >= (BUF_SIZE_PAYLOADS*d_payload_size)) {
|
||||
GR_LOG_WARN(d_logger, "Too much data; dropping packet.");
|
||||
}
|
||||
else {
|
||||
// otherwise, copy received data into local buffer for
|
||||
// copying later.
|
||||
memcpy(d_residbuf+d_residual, d_rxbuf, bytes_transferred);
|
||||
d_residual += bytes_transferred;
|
||||
}
|
||||
}
|
||||
d_cond_wait.notify_one();
|
||||
}
|
||||
}
|
||||
start_receive();
|
||||
}
|
||||
|
||||
int
|
||||
udp_gnss_rx_source::work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
gr::thread::scoped_lock l(d_setlock);
|
||||
|
||||
char *out = (char*)output_items[0];
|
||||
|
||||
// Use async receive_from to get data from UDP buffer and wait
|
||||
// on a conditional signal before proceeding. We use this
|
||||
// because the conditional wait is interruptable while a
|
||||
// synchronous receive_from is not.
|
||||
boost::unique_lock<boost::mutex> lock(d_udp_mutex);
|
||||
|
||||
//use timed_wait to avoid permanent blocking in the work function
|
||||
d_cond_wait.timed_wait(lock, boost::posix_time::milliseconds(10));
|
||||
|
||||
if (d_residual < 0) {
|
||||
return d_residual;
|
||||
}
|
||||
|
||||
int bytes_left_in_buffer = (int)(d_residual - d_sent);
|
||||
int bytes_to_send = std::min<int>(d_itemsize * noutput_items, bytes_left_in_buffer);
|
||||
|
||||
// Copy the received data in the residual buffer to the output stream
|
||||
memcpy(out, d_residbuf+d_sent, bytes_to_send);
|
||||
int nitems = bytes_to_send/d_itemsize;
|
||||
|
||||
// Keep track of where we are if we don't have enough output
|
||||
// space to send all the data in the residbuf.
|
||||
if (bytes_to_send == bytes_left_in_buffer) {
|
||||
d_residual = 0;
|
||||
d_sent = 0;
|
||||
}
|
||||
else {
|
||||
d_sent += bytes_to_send;
|
||||
}
|
||||
|
||||
return nitems;
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007-2010,2013 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_GR_UDP_GNSS_RX_SOURCE_IMPL_H
|
||||
#define INCLUDED_GR_UDP_GNSS_RX_SOURCE_IMPL_H
|
||||
|
||||
#include <gnuradio/blocks/udp_source.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <gnuradio/thread/thread.h>
|
||||
|
||||
class udp_gnss_rx_source;
|
||||
|
||||
typedef boost::shared_ptr<udp_gnss_rx_source> udp_gnss_rx_source_sptr;
|
||||
|
||||
udp_gnss_rx_source_sptr make_udp_gnss_rx_source(size_t itemsize,
|
||||
const std::string &ipaddr, int port,
|
||||
int payload_size, bool eof);
|
||||
|
||||
|
||||
|
||||
class udp_gnss_rx_source : public gr::blocks::udp_source
|
||||
{
|
||||
private:
|
||||
size_t d_itemsize;
|
||||
int d_payload_size; // maximum transmission unit (packet length)
|
||||
bool d_eof; // look for an EOF signal
|
||||
bool d_connected; // are we connected?
|
||||
char *d_rxbuf; // get UDP buffer items
|
||||
char *d_residbuf; // hold buffer between calls
|
||||
ssize_t d_residual; // hold information about number of bytes stored in residbuf
|
||||
ssize_t d_sent; // track how much of d_residbuf we've outputted
|
||||
size_t d_offset; // point to residbuf location offset
|
||||
|
||||
static const int BUF_SIZE_PAYLOADS; //!< The d_residbuf size in multiples of d_payload_size
|
||||
|
||||
std::string d_host;
|
||||
unsigned short d_port;
|
||||
|
||||
boost::asio::ip::udp::socket *d_socket;
|
||||
boost::asio::ip::udp::endpoint d_endpoint;
|
||||
boost::asio::ip::udp::endpoint d_endpoint_rcvd;
|
||||
boost::asio::io_service d_io_service;
|
||||
|
||||
gr::thread::condition_variable d_cond_wait;
|
||||
gr::thread::mutex d_udp_mutex;
|
||||
gr::thread::thread d_udp_thread;
|
||||
|
||||
void start_receive();
|
||||
void handle_read(const boost::system::error_code& error,
|
||||
size_t bytes_transferred);
|
||||
void run_io_service() { d_io_service.run(); }
|
||||
|
||||
public:
|
||||
udp_gnss_rx_source(size_t itemsize,
|
||||
const std::string &host, int port,
|
||||
int payload_size, bool eof);
|
||||
~udp_gnss_rx_source();
|
||||
|
||||
void connect(const std::string &host, int port);
|
||||
void disconnect();
|
||||
|
||||
int payload_size() { return d_payload_size; }
|
||||
int get_port();
|
||||
|
||||
int work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
};
|
||||
|
||||
|
||||
#endif /* INCLUDED_GR_UDP_GNSS_RX_SOURCE_H */
|
Loading…
x
Reference in New Issue
Block a user