Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upper Tester #30

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 46 additions & 65 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,81 +1,62 @@
language: cpp

sudo: false

compiler:
- gcc
- gcc

os:
- linux
- linux

cache:
apt: true
directories:
- $HOME/deps
- $HOME/deps

addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.8
- g++-4.8
- expect
- libssl-dev
- libxml2-dev
- libncurses5-dev
- flex
- bison
- xutils-dev
- ant
- xsltproc

install:
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- mkdir -p "$HOME/deps"
- |-
# Boost dependency
pushd "$HOME/deps"
export BOOST_ROOT="$PWD/boost_1_58_0"
if [ -d ${BOOST_ROOT} ]; then
echo "using Boost from Travis cache"
else
wget -nc 'https://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.bz2'
tar xjf boost_1_58_0.tar.bz2
pushd ${BOOST_ROOT}
./bootstrap.sh
./b2 --with-date_time --with-serialization --with-system --with-program_options
popd
fi
popd
- |-
# GeographicLib dependency
pushd "$HOME/deps"
GEOGRAPHICLIB_ROOT="$PWD/GeographicLib-1.37"
if [ -d ${GEOGRAPHICLIB_ROOT} ]; then
echo "using GeographicLib from Travis cache"
else
wget -nc 'https://sourceforge.net/projects/geographiclib/files/distrib/archive/GeographicLib-1.37.tar.gz'
tar xzf GeographicLib-1.37.tar.gz
pushd ${GEOGRAPHICLIB_ROOT}
./configure
make
popd
fi
export CMAKE_GEOGRAPHICLIB_FLAGS="-DGeographicLib_INCLUDE_DIR=${GEOGRAPHICLIB_ROOT}/include -DGeographicLib_LIBRARY_RELEASE=${GEOGRAPHICLIB_ROOT}/src/.libs/libGeographic.so"
popd
- |-
# Crypto++ dependency
pushd "$HOME/deps"
CRYPTOPP_ROOT="$PWD/cryptopp-5.6.2"
if [ -d ${CRYPTOPP_ROOT} ]; then
echo "using Crypto++ from Travis cache"
else
wget -nc 'https://sourceforge.net/projects/cryptopp/files/cryptopp/5.6.2/cryptopp562.zip'
unzip cryptopp562.zip -d ${CRYPTOPP_ROOT}
pushd ${CRYPTOPP_ROOT}
make dynamic install CXXFLAGS="-fPIC -DNDEBUG -march=native -pipe" PREFIX=./install
popd
fi
export CMAKE_CRYPTOPP_FLAGS="-DCryptoPP_INCLUDE_DIR=${CRYPTOPP_ROOT}/install/include -DCryptoPP_LIBRARY=${CRYPTOPP_ROOT}/install/lib/libcryptopp.so"
popd
- |-
# CMake 3.0+
pushd "$HOME/deps"
CMAKE_VERSION="3.1.3-Linux-x86_64"
wget -nc --no-check-certificate "https://cmake.org/files/v3.1/cmake-${CMAKE_VERSION}.tar.gz"
tar xzf cmake-${CMAKE_VERSION}.tar.gz
export PATH="$PWD/cmake-${CMAKE_VERSION}/bin:$PATH"
popd
- mkdir -p "$HOME/deps"

- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- export BOOST_ROOT="$HOME/deps/boost_1_58_0"
- export GEOGRAPHICLIB_ROOT="$HOME/deps/GeographicLib-1.37"
- export CMAKE_GEOGRAPHICLIB_FLAGS="-DGeographicLib_INCLUDE_DIR=${GEOGRAPHICLIB_ROOT}/include -DGeographicLib_LIBRARY_RELEASE=${GEOGRAPHICLIB_ROOT}/src/.libs/libGeographic.so"
- export CRYPTOPP_ROOT="$PWD/cryptopp-5.6.2"
- export CMAKE_CRYPTOPP_FLAGS="-DCryptoPP_INCLUDE_DIR=${CRYPTOPP_ROOT}/install/include -DCryptoPP_LIBRARY=${CRYPTOPP_ROOT}/install/lib/libcryptopp.so"
- export CMAKE_VERSION="3.1.3-Linux-x86_64"
- export TTCN3_DIR=$HOME/titan.core/Install
- export LD_LIBRARY_PATH=$HOME/titan.core/Install/lib:${LD_LIBRARY_PATH}
- export PATH="$HOME/deps/cmake-${CMAKE_VERSION}/bin:$HOME/titan.core/Install/bin:$PATH"

- travis/boost.sh
- travis/cmake.sh
- travis/cryptopp.sh
- travis/geographiclib.sh
- travis/titan.sh

script:
- mkdir -p "${HOME}/build"
- pushd "${HOME}/build"
- cmake -DBUILD_TESTS=ON ${CMAKE_GEOGRAPHICLIB_FLAGS} ${CMAKE_CRYPTOPP_FLAGS} ${TRAVIS_BUILD_DIR}
- cmake --build .
- ctest
- popd
- mkdir -p "${HOME}/build"
- pushd "${HOME}/build"
- cmake -DBUILD_TESTS=ON -DBUILD_UPPERTESTER=ON ${CMAKE_GEOGRAPHICLIB_FLAGS} ${CMAKE_CRYPTOPP_FLAGS} ${TRAVIS_BUILD_DIR}
- cmake --build .
- ctest
- popd
- pushd ${TRAVIS_BUILD_DIR}/tools/uppertester
- BUILD_DIR=$HOME/build ./run.sh
- popd
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ if(BUILD_CERTIFY)
add_subdirectory(tools/certify)
endif()

option(BUILD_UPPERTESTER "Build uppertester for TTCN-3 tests" OFF)
if(BUILD_UPPERTESTER)
add_subdirectory(tools/uppertester)
endif()

# interface library for convenience
get_property(_components GLOBAL PROPERTY VANETZA_COMPONENTS)
add_library(vanetza INTERFACE)
Expand Down
1 change: 0 additions & 1 deletion tools/socktap/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,3 @@ class Application : public vanetza::btp::IndicationInterface
};

#endif /* APPLICATION_HPP_PSIGPUTG */

1 change: 0 additions & 1 deletion tools/socktap/router_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,3 @@ void RouterContext::update_packet_flow(const geonet::LongPositionVector& lpv)
request_interface_->allow_packet_flow(true);
}
}

39 changes: 39 additions & 0 deletions tools/uppertester/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
if(NOT TARGET Boost::system)
message(STATUS "Skip build of uppertester because of missing Boost::system dependency")
return()
endif()

if(NOT TARGET Boost::program_options)
message(STATUS "Skip build of uppertester because of missing Boost::program_options dependency")
return()
endif()

find_package(Threads REQUIRED)

add_executable(uppertester
application.cpp
ethernet_device.cpp
main.cpp
passthrough.cpp
socket.cpp
time_trigger.cpp
uppertester.cpp

trigger/btp.cpp
trigger/btp_a.cpp
trigger/btp_b.cpp
trigger/common_change_position.cpp
trigger/common_change_pseudonym.cpp
trigger/common_ut_initialize.cpp
trigger/common_ut_result.cpp
trigger/gn.cpp
trigger/gn_geo_anycast.cpp
trigger/gn_geo_broadcast.cpp
trigger/gn_geo_unicast.cpp
trigger/gn_shb.cpp
trigger/gn_tsb.cpp
trigger/trigger.cpp
)

set_target_properties(uppertester PROPERTIES INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(uppertester Boost::program_options Boost::system Threads::Threads vanetza)
40 changes: 40 additions & 0 deletions tools/uppertester/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# UpperTester

This directory contains an upper tester implementation for ETSI's TTCN-3 test suite. A TTCN-3 compiler is required to execute these tests.

## Running

A script is provided that works on Ubuntu, which does the following steps automatically.
You're encouraged to read through the script and the following instructions.
If you use the script, you have to setup TITAN manually, everything else is covered by the script.

```bash
# With $PWD being the current directory
./run.sh
```

This guide will provide instructions how to run these tests manually using the open source TTCN-3 compiler [TITAN](https://github.com/eclipse/titan.core).

The TITAN TRI Mapper requires a network interface with a MAC address where it injects and captures packets. The easiest way to have a local virtual interface is to create two `peer` virtual interfaces.

```
sudo ip link add veth0 type veth peer name veth1
sudo ip link set dev veth0 up
sudo ip link set dev veth1 up
```

This will create the two interface `veth0` and `veth1` that are connected. If a packet is sent on `veth0` it will be available at `veth1` and the other way around.

The MAC address can be queried using `sudo ip link` and looking for the correct interface.

You need to setup TITAN as instructed in their documentation.

We make use of a [fork of the official test suite](https://github.com/elnrnag/ITSG5_TS_Titanized_TA), as the official test suite isn't compatible with TITAN (yet). Please clone the linked repository and install it as instructed in its README. You might need to add `jnetpcap` to your Java installation.

Switch to the `titan_tri_mapper` directory of the clone and copy `jnetpcap.jar` there. Adjust the `taproperties.cfg` to contain the correct MAC address for the virtual interface. Use the MAC address of the `veth1@veth0` interface. Then launch `sudo java -Djava.library.path=/path/to/jnetpcap -jar TitanTriMapper.jar -l info` where `/path/to/jnetpcap` is the path to the directory containing `libjnetpcap.so`.

Next, launch the upper tester using `bin/uppertester -i veth0` from the build directory of Vanetza.

Last, start the test suite by running `ttcn3_start ./ITS_Exec cfg.cfg ItsBtp_TestControl`. You might want to append ` | grep -v TRI_encode | grep -v TRI_decode` to suppress the verbose encoding and decoding output.

You might need to `up` and `down` one network interface after each test run to repeat the tests, because the TITAN TRI Mapper only seems to capture the frames, but not consume them. You can do so using `sudo ip link set dev veth0 down && sudo ip link set dev veth0 up`.
56 changes: 56 additions & 0 deletions tools/uppertester/application.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "application.hpp"
#include <vanetza/btp/header.hpp>
#include <vanetza/btp/header_conversion.hpp>
#include <cassert>

using namespace vanetza;

Application::DataConfirm Application::request(const btp::DataRequestA& request, DownPacketPtr packet)
{
DataConfirm confirm(DataConfirm::ResultCode::REJECTED_UNSPECIFIED);

if (router && packet) {
btp::HeaderA btp_header;
btp_header.destination_port = request.destination_port;
btp_header.source_port = request.source_port;
packet->layer(OsiLayer::Transport) = btp_header;

switch (request.gn.transport_type) {
case geonet::TransportType::SHB: {
geonet::ShbDataRequest shb(router->get_mib());
copy_request_parameters(request, shb);
confirm = router->request(shb, std::move(packet)); }
break;
default:
// TODO remaining transport types are not implemented
break;
}
}

return confirm;
}

Application::DataConfirm Application::request(const btp::DataRequestB& request, DownPacketPtr packet)
{
DataConfirm confirm(DataConfirm::ResultCode::REJECTED_UNSPECIFIED);

if (router && packet) {
btp::HeaderB btp_header;
btp_header.destination_port = request.destination_port;
btp_header.destination_port_info = request.destination_port_info;
packet->layer(OsiLayer::Transport) = btp_header;

switch (request.gn.transport_type) {
case geonet::TransportType::SHB: {
geonet::ShbDataRequest shb(router->get_mib());
copy_request_parameters(request, shb);
confirm = router->request(shb, std::move(packet)); }
break;
default:
// TODO remaining transport types are not implemented
break;
}
}

return confirm;
}
32 changes: 32 additions & 0 deletions tools/uppertester/application.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef UPPERTESTER_APPLICATION_HPP
#define UPPERTESTER_APPLICATION_HPP

#include <vanetza/btp/data_interface.hpp>
#include <vanetza/btp/data_request.hpp>
#include <vanetza/btp/port_dispatcher.hpp>
#include <vanetza/geonet/data_confirm.hpp>
#include <vanetza/geonet/router.hpp>

class Application : public vanetza::btp::PortDispatcher::PromiscuousHook
{
public:
using DataConfirm = vanetza::geonet::DataConfirm;
using DataIndication = vanetza::btp::DataIndication;
using DataRequest = vanetza::btp::DataRequestGeoNetParams;
using DownPacketPtr = vanetza::geonet::Router::DownPacketPtr;
using PortType = vanetza::btp::port_type;
using UpPacketPtr = vanetza::geonet::Router::UpPacketPtr;

Application() = default;
Application(const Application&) = delete;
Application& operator=(const Application&) = delete;
virtual ~Application() = default;

DataConfirm request(const vanetza::btp::DataRequestA& request, DownPacketPtr packet);
DataConfirm request(const vanetza::btp::DataRequestB& request, DownPacketPtr packet);

protected:
vanetza::geonet::Router* router;
};

#endif /* UPPERTESTER_APPLICATION_HPP */
56 changes: 56 additions & 0 deletions tools/uppertester/ethernet_device.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "ethernet_device.hpp"
#include <algorithm>
#include <cstring>
#include <system_error>
#include <linux/if_packet.h>
#include <net/if.h>
#include <sys/ioctl.h>

static void initialize(ifreq& request, const char* interface_name)
{
std::memset(&request, 0, sizeof(ifreq));
std::strncpy(request.ifr_name, interface_name, IF_NAMESIZE);
request.ifr_name[IF_NAMESIZE - 1] = '\0';
}

EthernetDevice::EthernetDevice(const char* devname) :
local_socket_(::socket(AF_LOCAL, SOCK_DGRAM, 0)),
interface_name_(devname)
{
if (!local_socket_) {
throw std::system_error(errno, std::system_category());
}
}

EthernetDevice::~EthernetDevice()
{
if (local_socket_ >= 0)
::close(local_socket_);
}

EthernetDevice::protocol::endpoint EthernetDevice::endpoint(int family) const
{
sockaddr_ll socket_address = {0};
socket_address.sll_family = family;
socket_address.sll_ifindex = index();
return protocol::endpoint(&socket_address, sizeof(sockaddr_ll));
}

int EthernetDevice::index() const
{
ifreq data;
initialize(data, interface_name_.c_str());
::ioctl(local_socket_, SIOCGIFINDEX, &data);
return data.ifr_ifindex;
}

vanetza::MacAddress EthernetDevice::address() const
{
ifreq data;
initialize(data, interface_name_.c_str());
::ioctl(local_socket_, SIOCGIFHWADDR, &data);

vanetza::MacAddress addr;
std::copy_n(data.ifr_hwaddr.sa_data, addr.octets.size(), addr.octets.data());
return addr;
}
Loading