Commit ee6f7bc8 authored by Yann Garcia's avatar Yann Garcia
Browse files

Adding Gtpv2 support; Enhance scripts

parent c39f3b96
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -344,6 +344,25 @@ $ ../run_all.bash

- The log files are located in ../logs/AtsNGAP folder for this example. You can edit them using any editor or using the Eclipse TITAN log plugins

# Visualizing test execution logs

A merged execution log can be converted into a PlantUML sequence diagram (SVG) and browsed in a web page. See [plantuml/README.md](plantuml/README.md) for full details; in short:

```sh
$ export ATS=AtsNGAP # The Abstract Test Suite whose log you want to visualize
$ ./scripts/generate_png.sh
```

This produces one `plantuml/<test_case_name>.svg` per test case found in the ATS's log (e.g. `plantuml/TC_CSE_SUB_NTF_002.svg`), rather than a single ATS-wide diagram. To browse the generated diagrams with working hyperlinks to the exchanged TTCN-3 messages, run the bundled web server:

```sh
$ cd plantuml/webserver
$ pip install -r requirements.txt
$ python3 app.py
```

Then open `http://localhost:5000/` in a browser (see [plantuml/README.md](plantuml/README.md) for the `--host`/`--port` options and notes on working over a remote SSH connection).

# Limitations

The following limitations apply:
+126 −0
Original line number Diff line number Diff line
/*!
 * \file      Gtpv2Port.cc
 * \brief     CC file for Gtpv2Port.
 * \author    ETSI TTF T059
 * \copyright ETSI Copyright Notification
 *            No part may be reproduced except as authorized by written permission.
 *            The copyright and the foregoing restriction extend to reproduction in all media.
 *            All rights reserved.
 * \version   0.1
 */

#include "loggers.hh"

#include "LibGtpv2_Interface.hh"
#include "LibGtpv2_TypesAndValues.hh"
#include "gtpv2_layer_factory.hh"
#include "layer.hh"
#include "params.hh"

namespace LibGtpv2__TypesAndValues {
  class Gtpv2Message;
}
namespace LibGtpv2__Interface {

  Gtpv2Port::Gtpv2Port(const char *par_port_name): Gtpv2Port_BASE(par_port_name), _cfg_params(), _layer_params(), _layer(nullptr), _time_key("Gtpv2Port::") {
    // Nothing to do
  } // End of constructor

  Gtpv2Port::~Gtpv2Port() {
    loggers::get_instance().log(">>> Gtpv2Port::~Gtpv2Port");

    if (_layer != nullptr) {
      delete _layer;
    }
  } // End of destructor

  void Gtpv2Port::set_parameter(const char * parameter_name, const char * parameter_value)
  {
    loggers::get_instance().log("Gtpv2Port::set_parameter: %s=%s", parameter_name, parameter_value);
    _cfg_params.insert(std::pair<std::string, std::string>(std::string(parameter_name), std::string(parameter_value)));
  }

  void Gtpv2Port::Handle_Fd_Event_Error(int /*fd*/)
  {

  }

  void Gtpv2Port::Handle_Fd_Event_Writable(int /*fd*/)
  {

  }

  void Gtpv2Port::Handle_Fd_Event_Readable(int /*fd*/)
  {

  }

  void Gtpv2Port::user_map(const char * system_port)
  {
    loggers::get_instance().log(">>> Gtpv2Port::user_map: %s", system_port);
    // Build layer stack
    params::iterator it = _cfg_params.find(std::string("params"));
    if (it != _cfg_params.end()) {
      loggers::get_instance().log("Gtpv2Port::user_map: %s", it->second.c_str());
      // Setup parameters
      params::convert(_layer_params, it->second); // TODO This _layer_params seems to be useless
      // Create layer
      _layer = layer_stack_builder::get_instance()->create_layer_stack(it->second.c_str());

      if (static_cast<gtpv2_layer*>(_layer) == nullptr) {
        loggers::get_instance().error("Gtpv2Port::user_map: Invalid stack configuration - NOT GTPV2: %s", it->second.c_str());
      }
      static_cast<gtpv2_layer*>(_layer)->add_upper_port(this);
    } else {
      loggers::get_instance().error("Gtpv2Port::user_map: No layers defined in configuration file");
    }
  } // End of user_map method

  void Gtpv2Port::user_unmap(const char * system_port)
  {
    loggers::get_instance().log(">>> Gtpv2Port:user_unmap: %s", system_port);

    // Reset layers
    if (_layer != nullptr) {
      delete _layer;
      _layer = nullptr;
    }
  } // End of user_unmap method

  void Gtpv2Port::user_start()
  {
    loggers::get_instance().log(">>> Gtpv2Port::user_start");

  } // End of user_start method

  void Gtpv2Port::user_stop()
  {
    loggers::get_instance().log(">>> Gtpv2Port::user_stop");

  } // End of user_stop method

  void Gtpv2Port::outgoing_send(const LibGtpv2__TypesAndValues::Gtpv2Message& send_par)
  {
    loggers::get_instance().log_msg(">>> Gtpv2Port::outgoing_send: payload=", send_par);

    float duration;
    loggers::get_instance().set_start_time(_time_key);
    params params;
        static_cast<gtpv2_layer*>(_layer)->sendMsg(send_par, params);
    loggers::get_instance().set_stop_time(_time_key, duration);
  }

  void Gtpv2Port::receiveMsg (const  LibGtpv2__TypesAndValues::Gtpv2Message& p_ind, const params& p_params) {
    loggers::get_instance().log_msg(">>> Gtpv2Port::receive_msg: ", p_ind);
    float duration;
    loggers::get_instance().set_start_time(_time_key);
    // Sanity check
    if (!p_ind.is_bound()) {
      return;
    }

    incoming_message(p_ind);
    loggers::get_instance().set_stop_time(_time_key, duration);
  }

} // End of namespace LibGtpv2__Interface
+54 −0
Original line number Diff line number Diff line
/*!
 * \file      Gtpv2Port.hh
 * \brief     Header file for Gtpv2Port.
 * \author    ETSI TTF T059
 * \copyright ETSI Copyright Notification
 *            No part may be reproduced except as authorized by written permission.
 *            The copyright and the foregoing restriction extend to reproduction in all media.
 *            All rights reserved.
 * \version   0.1
 */

#pragma once

#include "LibGtpv2_Interface.hh"
#include "LibGtpv2_TypesAndValues.hh"

#include "layer.hh"
#include "params.hh"

namespace LibGtpv2__TypesAndValues {
  class Gtpv2Message;
}
namespace LibGtpv2__Interface {

  class  Gtpv2Port : public Gtpv2Port_BASE {
    params _cfg_params;
    params _layer_params;
    layer* _layer;
    std::string _time_key;
  public:
     Gtpv2Port(const char *par_port_name);
    ~ Gtpv2Port();

    void set_parameter(const char *parameter_name, const char *parameter_value);
    void receiveMsg (const LibGtpv2__TypesAndValues::Gtpv2Message& p_ind, const params& p_params);

  private:
    void Handle_Fd_Event_Error(int fd);
    void Handle_Fd_Event_Writable(int fd);
    void Handle_Fd_Event_Readable(int fd);

  protected:
    const char *port_name;
    void user_map(const char *system_port);
    void user_unmap(const char *system_port);

    void user_start();
    void user_stop();

  protected:
    void outgoing_send(const LibGtpv2__TypesAndValues::Gtpv2Message& send_par);
  }; // End of class  Gtpv2Port

} // End of namespace LibGtpv2__Interface
+2 −0
Original line number Diff line number Diff line
sources := Gtpv2Port.cc
includes := .
+48 −0
Original line number Diff line number Diff line
#include "gtpv2_codec.hh"

#include "LibGtpv2_TypesAndValues.hh"

#include "loggers.hh"

int gtpv2_codec::encode(const LibGtpv2__TypesAndValues::Gtpv2Message& p_msg, OCTETSTRING& p_data) {
  loggers::get_instance().log_msg(">>> gtpv2_codec::encode: ", p_msg);

  gtpv2_header hdr;
  hdr.version         = 2;
  hdr.piggybacked     = static_cast<bool>(p_msg.header().piggybacked());
  hdr.teid_present    = static_cast<bool>(p_msg.header().teidPresent());
  hdr.message_type    = static_cast<uint8_t>(static_cast<int>(p_msg.header().messageType()));
  hdr.sequence        = static_cast<uint32_t>(static_cast<int>(p_msg.header().sequenceNumber()));
  if (hdr.teid_present) {
    const INTEGER& teid = static_cast<const INTEGER&>(*p_msg.header().teid().get_opt_value());
    hdr.teid = static_cast<uint32_t>(static_cast<int>(teid));
  } else {
    hdr.teid = 0;
  }
  //hdr.teid            = static_cast<uint32_t>(hdr.teid_present ? static_cast<uint32_t>(static_cast<int>(p_msg.header().teid())) : 0);
  hdr.message_length  = static_cast<uint16_t>((hdr.header_length() - 4) + p_msg.ies().lengthof());

  TTCN_Buffer buffer;
  gtpv2_encode_header(hdr, buffer);
  buffer.put_os(p_msg.ies());

  p_data = OCTETSTRING(buffer.get_read_len(), buffer.get_data());
  return 0;
}

int gtpv2_codec::decode(const gtpv2_header& p_hdr, const OCTETSTRING& p_ies, LibGtpv2__TypesAndValues::Gtpv2Message& p_msg) {
  loggers::get_instance().log_msg(">>> gtpv2_codec::decode: ", p_ies);

  p_msg.header().piggybacked()    = p_hdr.piggybacked;
  p_msg.header().teidPresent()    = p_hdr.teid_present;
  p_msg.header().messageType()    = static_cast<int>(p_hdr.message_type);
  p_msg.header().sequenceNumber() = static_cast<int>(p_hdr.sequence);
  if (p_hdr.teid_present) {
    p_msg.header().teid() = static_cast<int>(p_hdr.teid);
  } else {
    p_msg.header().teid().set_to_omit();
  }
  p_msg.ies() = p_ies;

  return 0;
}
Loading