version 0.0.1
This commit is contained in:
parent
24b5baf73b
commit
1c64f34ef4
2
catch.cpp
Normal file
2
catch.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
3
config.json
Normal file
3
config.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"number_of_worker_threads": "11"
|
||||
}
|
1
default_config.json
Normal file
1
default_config.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
56
include/Cli.hpp
Normal file
56
include/Cli.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
using Args = std::deque<std::string>;
|
||||
using Func = std::function<void(Args)>;
|
||||
using Command = std::tuple<std::string, std::string, Func>;
|
||||
|
||||
class Cli{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Cli object and adds "help, h" and "exit" to _commands.
|
||||
*/
|
||||
Cli();
|
||||
/**
|
||||
* @brief Adds a command to _commands.
|
||||
*
|
||||
* Example: add_to_commands_list("h", "Help", std::bind(&Cli::print_help, &cli, std::placeholders::_1));
|
||||
*
|
||||
* @param names string, list of names that execute the command
|
||||
* @param par string, description to be displayed when help command is executed
|
||||
* @param func function to be executed (for member functions see example above)
|
||||
*/
|
||||
void add_to_commands_list(std::string names, std::string desc, Func func);
|
||||
|
||||
/**
|
||||
* @brief Loops the iterate function. Stops when _exit is set to true.
|
||||
*/
|
||||
void run();
|
||||
/**
|
||||
* @brief Asks user for input and runs matching method from _commands.
|
||||
*/
|
||||
void iterate();
|
||||
|
||||
bool get_exit() { return _exit; }
|
||||
Command& get_command(int i) { return _commands[i]; }
|
||||
|
||||
// Functions for commands
|
||||
void default_help(Args args);
|
||||
void exit_program(Args args);
|
||||
void print_help(Args args);
|
||||
void syn(Args args);
|
||||
|
||||
private:
|
||||
bool _exit = false; ///< When set to true the run method will stop.
|
||||
std::vector<Command> _commands; ///< Set of commands that can be accessed in the cli.
|
||||
|
||||
void print(std::string str) { std::cout << " " << str << "\n"; }
|
||||
Func get_function(std::string input);
|
||||
};
|
107
include/Configurator.hpp
Normal file
107
include/Configurator.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "Definitions.hpp"
|
||||
#include "iostream"
|
||||
#include <fstream>
|
||||
#include <json.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
class Configurator{
|
||||
public:
|
||||
/**
|
||||
* @brief Checks if attribute exists in either the normal or the default config file
|
||||
*
|
||||
* @param att_name Name of attribute that is searched for
|
||||
* @return true when attribute was found
|
||||
* @return false when attribute wasn't found
|
||||
*/
|
||||
bool entry_exists(const std::string att_name);
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//------------------------------- Get-Methods ---------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Get value from config as string object
|
||||
*
|
||||
* @param att_name Name of attribute that is searched for
|
||||
* @param default_value When set to true the method searches in the default config (default: false)
|
||||
* @return std::string value
|
||||
*/
|
||||
std::string get_config_as_string(const std::string& att_name,
|
||||
bool default_value = false);
|
||||
/**
|
||||
* @brief Get value from config as unsigned integer
|
||||
*
|
||||
* @param att_name Name of attribute that is searched for
|
||||
* @param default_value When set to true the method searches in the default config (default: false)
|
||||
* @return std::string value
|
||||
*/
|
||||
unsigned int get_config_as_unsigned_int(const std::string& att_name,
|
||||
bool default_value = false);
|
||||
/**
|
||||
* @brief Get value from config as boolean
|
||||
*
|
||||
* @param att_name Name of attribute that is searched for
|
||||
* @param default_value When set to true the method searches in the default config (default: false)
|
||||
* @return std::string value
|
||||
*/
|
||||
bool get_config_as_bool(const std::string& att_name,
|
||||
bool default_value = false);
|
||||
/**
|
||||
* @brief Get value from config as float
|
||||
*
|
||||
* @param att_name Name of attribute that is searched for
|
||||
* @param default_value When set to true the method searches in the default config (default: false)
|
||||
* @return std::string value
|
||||
*/
|
||||
float get_config_as_float(const std::string& att_name,
|
||||
bool default_value = false);
|
||||
/**
|
||||
* @brief Get value from config as double
|
||||
*
|
||||
* @param att_name Name of attribute that is searched for
|
||||
* @param default_value When set to true the method searches in the default config (default: false)
|
||||
* @return std::string value
|
||||
*/
|
||||
double get_config_as_double(const std::string& att_name,
|
||||
bool default_value = false);
|
||||
/**
|
||||
* @brief Reads config and default config from json files
|
||||
*
|
||||
* @param path Path to standard config (which can be modified by the user)
|
||||
* @param default_path Path to default config (default: "../default_config.json")
|
||||
*/
|
||||
void read_config(std::string path,
|
||||
std::string default_path = "../default_config.json");
|
||||
|
||||
/**
|
||||
* @brief The Configurator is implemented as a singleton. This method returns a poiter to the Configurator object
|
||||
*
|
||||
* @return Configurator* poiter to singleton Configurator
|
||||
*/
|
||||
static Configurator* instance();
|
||||
|
||||
private:
|
||||
json _config; ///< standard config (can be modified by the user)
|
||||
json _default_config; ///< default config
|
||||
template <typename T> T get_value_from_config(const std::string& att_name, bool default_value);
|
||||
static Configurator* _instance; ///< singleton Configurator
|
||||
Configurator();
|
||||
Configurator(const Configurator&);
|
||||
~Configurator();
|
||||
class CGuard{
|
||||
public:
|
||||
~CGuard(){
|
||||
if( NULL != Configurator::_instance ){
|
||||
delete Configurator::_instance;
|
||||
Configurator::_instance = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
11
include/DebugHelper.hpp
Normal file
11
include/DebugHelper.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
class DebugHelper{
|
||||
|
||||
public:
|
||||
static void hex_dump_human_readable (const char *desc, const void *addr, int len);
|
||||
static void hex_dump_raw(const void *addr, int len);
|
||||
};
|
||||
|
34
include/Definitions.hpp
Normal file
34
include/Definitions.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#define RX_RING_SIZE 1024
|
||||
#define TX_RING_SIZE 1024
|
||||
|
||||
// only needed for mempool creation. was replaced.
|
||||
// NUM_MBUF_POOL_ELEMENTS is used instead
|
||||
//#define NUM_MBUFS 8191
|
||||
|
||||
// Argument "n" in rte_pktmbuf_pool_create
|
||||
#define NUM_MBUF_POOL_ELEMENTS 32767
|
||||
|
||||
#define BURST_SIZE 64
|
||||
// #define MBUF_ARR_SIZE 2 * BURST_SIZE
|
||||
|
||||
#define RSS_HASH_KEY_LENGTH 40
|
||||
|
||||
// used in initializer
|
||||
#define NUM_NON_WORKER_THREADS 1
|
||||
|
||||
// used in PacketContainer.
|
||||
// predefined size of array of mbuf-arrays
|
||||
#define NUM_MBUF_ARRS 30000
|
||||
|
||||
#define TCP_RX_WINDOW 16384
|
||||
|
||||
#define LOG_INFO BOOST_LOG_TRIVIAL(info) << "\e[32m"
|
||||
#define LOG_WARNING BOOST_LOG_TRIVIAL(warning) << "\e[33m "
|
||||
#define LOG_ERROR BOOST_LOG_TRIVIAL(error) << "\e[31m "
|
||||
#define LOG_FATAL BOOST_LOG_TRIVIAL(fatal) << "\e[31m "
|
||||
#define LOG_END "\e[0m"
|
||||
|
||||
// ATTACKE
|
||||
//#define LOG_PKTS_SENT
|
52
include/Initializer.hpp
Normal file
52
include/Initializer.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_mempool.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class Initializer {
|
||||
public:
|
||||
/**
|
||||
* @brief Initializes everything regarding DPDK and configures the ports.
|
||||
*
|
||||
* Especially: Initializes the variable nb_worker_threads
|
||||
*
|
||||
* @param[in] argc
|
||||
* @param[in] argv
|
||||
* @param[out] mbuf_pool
|
||||
* @param[out] nb_worker_threads
|
||||
*/
|
||||
rte_mempool* init_dpdk(int argc, char** argv, uint16_t& nb_worker_threads);
|
||||
|
||||
rte_mempool* init_dpdk_attacker(int argc, char** argv,
|
||||
uint16_t& nb_worker_threads);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief init NIC
|
||||
*
|
||||
* get the NIC by port identifier and bind it to dpdk with given mempool.
|
||||
* Setting up TX/RX queues per ethernet port. Then starting the device and
|
||||
* printing MAC address
|
||||
*
|
||||
* @param port set port identifier to use
|
||||
* @param mbuf_pool set mempool of dpdk to use
|
||||
* @param[in] nb_worker_threads number of worker threads
|
||||
* @return 0 or error code
|
||||
*/
|
||||
void init_port(rte_eth_conf port_conf, uint16_t port,
|
||||
struct rte_mempool* mbuf_pool, uint16_t nb_worker_threads);
|
||||
|
||||
/**
|
||||
* @brief initializes number of threads
|
||||
*
|
||||
* @param[out] nb_worker_threads
|
||||
*/
|
||||
void init_number_threads(uint16_t nb_non_worker_threads,
|
||||
uint16_t& nb_worker_threads);
|
||||
|
||||
rte_mempool* init_dpdk_template(uint16_t nb_non_worker_threads,
|
||||
rte_eth_conf port_conf, int argc,
|
||||
char** argv, uint16_t& nb_worker_threads);
|
||||
};
|
56
include/PacketDissection/MbufContainer.hpp
Normal file
56
include/PacketDissection/MbufContainer.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "Definitions.hpp"
|
||||
|
||||
#define ERROR_STR_MBUF_CONTAINER_INDEX_OUT_OF_BOUNDS \
|
||||
"Index is out of bounds of MbufContainer."
|
||||
|
||||
/**
|
||||
* @brief like the PacketContainer but it only holds mbufs plus some minor
|
||||
* performance improvements
|
||||
*
|
||||
* \todo Has to be documented with more details
|
||||
*
|
||||
*/
|
||||
class MbufContainer {
|
||||
protected:
|
||||
uint16_t _nb_mbufs_in_container;
|
||||
|
||||
rte_mbuf* _mbuf_arr[BURST_SIZE];
|
||||
|
||||
rte_mempool* _mempool;
|
||||
|
||||
public:
|
||||
inline MbufContainer(rte_mempool* mempool)
|
||||
: _mempool(mempool), _nb_mbufs_in_container(0) {}
|
||||
|
||||
/**
|
||||
* @brief Get the mbuf at index
|
||||
*
|
||||
* @param index
|
||||
* @return rte_mbuf*
|
||||
*/
|
||||
inline rte_mbuf* get_mbuf_at_index(int index) {
|
||||
check_index(index);
|
||||
return _mbuf_arr[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the number of mbufs
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_number_of_mbufs() { return _nb_mbufs_in_container; }
|
||||
|
||||
inline void check_index(int index) {
|
||||
if (unlikely(index >= _nb_mbufs_in_container || index < 0)) {
|
||||
throw std::runtime_error(
|
||||
ERROR_STR_MBUF_CONTAINER_INDEX_OUT_OF_BOUNDS);
|
||||
}
|
||||
}
|
||||
};
|
36
include/PacketDissection/MbufContainerReceiving.hpp
Normal file
36
include/PacketDissection/MbufContainerReceiving.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
#include "Definitions.hpp"
|
||||
#include "PacketDissection/MbufContainer.hpp"
|
||||
|
||||
/**
|
||||
* @brief for received mbufs. you poll them, read them and finally... forget
|
||||
* them
|
||||
*
|
||||
*/
|
||||
class MbufContainerReceiving : public MbufContainer {
|
||||
private:
|
||||
uint16_t _rx_port;
|
||||
uint16_t _rx_queue;
|
||||
|
||||
public:
|
||||
inline MbufContainerReceiving(rte_mempool* mempool, uint16_t rx_port,
|
||||
uint16_t rx_queue)
|
||||
: MbufContainer(mempool), _rx_port(rx_port), _rx_queue(rx_queue) {}
|
||||
|
||||
/**
|
||||
* @brief poll mbufs
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t poll_mbufs() {
|
||||
|
||||
_nb_mbufs_in_container =
|
||||
rte_eth_rx_burst(_rx_port, _rx_queue, _mbuf_arr, BURST_SIZE);
|
||||
|
||||
return _nb_mbufs_in_container;
|
||||
}
|
||||
};
|
75
include/PacketDissection/MbufContainerTransmitting.hpp
Normal file
75
include/PacketDissection/MbufContainerTransmitting.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
#include "PacketDissection/MbufContainer.hpp"
|
||||
|
||||
/**
|
||||
* @brief for transmitted mbufs.
|
||||
*
|
||||
*/
|
||||
class MbufContainerTransmitting : public MbufContainer {
|
||||
private:
|
||||
uint16_t _tx_port;
|
||||
uint16_t _tx_queue;
|
||||
|
||||
public:
|
||||
inline MbufContainerTransmitting(rte_mempool* mempool, uint16_t tx_port,
|
||||
uint16_t tx_queue)
|
||||
: MbufContainer(mempool), _tx_port(tx_port), _tx_queue(tx_queue) {}
|
||||
|
||||
/**
|
||||
* @brief add mbuf to container
|
||||
*
|
||||
* This method may delete the mbuf given if the container is full
|
||||
*
|
||||
* @param mbuf
|
||||
*/
|
||||
inline void add_mbuf(rte_mbuf* mbuf) {
|
||||
if (likely(_nb_mbufs_in_container < BURST_SIZE)) {
|
||||
_mbuf_arr[_nb_mbufs_in_container] = mbuf;
|
||||
++_nb_mbufs_in_container;
|
||||
} else {
|
||||
rte_pktmbuf_free(mbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief create new mbuf in the container and return the pointer to it
|
||||
*
|
||||
* @return rte_mbuf*:
|
||||
* - normally: a newly created mbuf is returned
|
||||
* - if container is full and no mbuf can be added anymore: nullptr
|
||||
*/
|
||||
inline rte_mbuf* get_empty_mbuf() {
|
||||
if (likely(_nb_mbufs_in_container < BURST_SIZE)) {
|
||||
_mbuf_arr[_nb_mbufs_in_container] = rte_pktmbuf_alloc(_mempool);
|
||||
return _mbuf_arr[_nb_mbufs_in_container++];
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief send every mbuf contained in the container
|
||||
*
|
||||
*/
|
||||
inline void send_mbufs() {
|
||||
if (likely(_nb_mbufs_in_container > 0)) {
|
||||
|
||||
// send mbufs
|
||||
uint16_t nb_mbufs_sent = rte_eth_tx_burst(
|
||||
_tx_port, _tx_queue, _mbuf_arr, _nb_mbufs_in_container);
|
||||
|
||||
// Free any unsent packets.
|
||||
if (unlikely(nb_mbufs_sent < _nb_mbufs_in_container)) {
|
||||
for (int i = nb_mbufs_sent; i < _nb_mbufs_in_container; ++i) {
|
||||
rte_pktmbuf_free(_mbuf_arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
_nb_mbufs_in_container = 0;
|
||||
}
|
||||
}
|
||||
};
|
563
include/PacketDissection/PacketContainer.hpp
Normal file
563
include/PacketDissection/PacketContainer.hpp
Normal file
@ -0,0 +1,563 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_mempool.h>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Definitions.hpp"
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
#include "PacketDissection/PacketInfoCreator.hpp"
|
||||
|
||||
#define ERROR_STR_INDEX_OUT_OF_BOUNDS \
|
||||
"index is out of bounds of PacketContainer. The highest possible index " \
|
||||
"can be accessed by get_total_number_of_packets()."
|
||||
|
||||
/**
|
||||
* This class can poll, send and hold packets.
|
||||
*
|
||||
* Think of this data type as a list of packets holding the packets themself
|
||||
* as well as meta information per packet. If you want to access a certain
|
||||
* packet (e.g. within a for function) you can use the methods provided with
|
||||
* a packet index.
|
||||
*
|
||||
* You can iterate either only over packets that were polled or over
|
||||
* all packets in the container.
|
||||
* - Usually if you create a packet you also want to send it and do not
|
||||
* look at it anymore after the creation. So the only packets to look at are
|
||||
* those that where being polled. If this is the case it would be more
|
||||
* efficient to only iterate over polled packets.
|
||||
* - The latter includes both packets polled and packets you
|
||||
* created yourselve with one of the corresponding methods. It could be
|
||||
* helpful in other situations.
|
||||
*
|
||||
* The maximum of packets to iterate over is therefore the
|
||||
* number of polled packets / the total number of packets which both can be
|
||||
* accessed each with the corresponding getter method. Remember that the
|
||||
* indices begin at 0 so the last element is at index (nb_packets - 1).
|
||||
*
|
||||
* To manipulate a packet / read data from it you have to get the PacketInfo
|
||||
* object at a cretain index with the corresponding method. Consult the
|
||||
* PacketInfo documentation for further information.
|
||||
*
|
||||
* NOTICE: It is possible that you get nullptr instead of a PacketInfo
|
||||
* pointer if you get a packet with one of the corresponding methods. Test
|
||||
* if this is the case (e.g. ptr == nullptr) before going ahead working with
|
||||
* the PacketInfo object.
|
||||
*
|
||||
* If you want to create a new packet do not construct a new PacketInfo
|
||||
* object. Use the method get_empty_packet instead. This is more efficient.
|
||||
*
|
||||
* An object of this class is initialized with the ID of the rx queue and the
|
||||
* tx queue of the thread that uses the object. Since corresponding [r|t]x
|
||||
* queues each on one port have the same ID it is only necessary to store the ID
|
||||
* of one rx queue and one tx queue.
|
||||
*/
|
||||
class PacketContainer {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Packet Container object
|
||||
*
|
||||
* @param pkt_handler
|
||||
* @param mbuf_pool
|
||||
* @param entrance_port
|
||||
* @param exit_port
|
||||
* @param rx_queue_number ID of the rx queues
|
||||
* @param tx_queue_number ID of the tx queues
|
||||
*/
|
||||
inline PacketContainer(struct rte_mempool* mbuf_pool,
|
||||
uint16_t entrance_port, uint16_t exit_port,
|
||||
uint16_t rx_queue_number, uint16_t tx_queue_number)
|
||||
: _mempool(mbuf_pool), _entrance_port(entrance_port),
|
||||
_exit_port(exit_port), _nb_pkts_polled(0), _nb_pkts_total(0),
|
||||
_nb_pkts_dropped(0), _nb_pkt_arrays(1),
|
||||
_rx_queue_number(rx_queue_number), _tx_queue_number(tx_queue_number) {
|
||||
|
||||
for (int i = 0; i < NUM_MBUF_ARRS; ++i) {
|
||||
_nb_mbufs_in_mbuf_arr[i] = 0;
|
||||
|
||||
for (int j = 0; j < BURST_SIZE; ++j) {
|
||||
_mbuf_arrs[i][j] = nullptr;
|
||||
_pkt_info_arrs[i][j] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~PacketContainer() { empty_container(); }
|
||||
|
||||
/**
|
||||
* @brief Poll packets into the container
|
||||
*
|
||||
* The operation poll_packets does not guarantee that more than 0 packets
|
||||
* were polled. If there are no packets on the NIC port, nothing can be
|
||||
* polled. So you have to be able to check if packets actually were polled.
|
||||
* This could be important, e.g if you want to skip certain parts of your
|
||||
* program if no packets were polled. For the sake of efficiency you do not
|
||||
* do this with a getter that returns the state but with a pass-by-reference
|
||||
* variable that you pass to the poll_packets operation- After the execution
|
||||
* of poll_packets this variable holds the number of packets actually
|
||||
* polled.
|
||||
*
|
||||
* Also if you poll packets but did not send the packets currently being in
|
||||
* the PacketContainer they are going to be overwritten.
|
||||
*
|
||||
* @param[out] nb_pkts_polled after execution: holds number of packets
|
||||
* actually polled.
|
||||
*/
|
||||
inline void poll_packets(uint16_t& nb_pkts_polled) {
|
||||
empty_container();
|
||||
|
||||
_nb_pkts_polled = rte_eth_rx_burst(_entrance_port, _rx_queue_number,
|
||||
_mbuf_arrs[0], BURST_SIZE);
|
||||
|
||||
_nb_pkts_total = _nb_pkts_polled;
|
||||
|
||||
if (_nb_pkts_polled > 0) {
|
||||
_nb_pkt_arrays = 1;
|
||||
_nb_mbufs_in_mbuf_arr[0] = _nb_pkts_polled;
|
||||
}
|
||||
|
||||
extract_header_info();
|
||||
|
||||
// return
|
||||
nb_pkts_polled = _nb_pkts_polled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send packets from the container
|
||||
*
|
||||
* Sent packets are no longer available after being sent.
|
||||
* @return total number of packets send
|
||||
*/
|
||||
inline uint send_packets() {
|
||||
uint sum_pkts_send = 0;
|
||||
if (likely(_nb_pkts_total > 0)) {
|
||||
if (_nb_pkts_dropped != 0) {
|
||||
reorder_mbuf_arrays();
|
||||
}
|
||||
|
||||
for (int i = 0; i < _nb_pkt_arrays; ++i) {
|
||||
uint16_t nb_pkts_to_send = _nb_mbufs_in_mbuf_arr[i];
|
||||
|
||||
// send mbufs
|
||||
uint16_t nb_pkts_sent =
|
||||
rte_eth_tx_burst(_exit_port, _tx_queue_number,
|
||||
_mbuf_arrs[i], nb_pkts_to_send);
|
||||
|
||||
#ifdef LOG_PKTS_SENT
|
||||
LOG_INFO << "Number of packets sent: " << nb_pkts_sent
|
||||
<< " and this should have been sent: "
|
||||
<< nb_pkts_to_send << LOG_END;
|
||||
#endif
|
||||
|
||||
sum_pkts_send += nb_pkts_sent;
|
||||
// Free any unsent packets.
|
||||
if (unlikely(nb_pkts_sent < nb_pkts_to_send)) {
|
||||
for (int j = nb_pkts_sent; j < nb_pkts_to_send; ++j) {
|
||||
rte_pktmbuf_free(_mbuf_arrs[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
empty_container();
|
||||
return sum_pkts_send;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Drop packet.
|
||||
*
|
||||
* @param index Index of the packet to drop.
|
||||
*/
|
||||
inline void drop_packet(int index) {
|
||||
if (index >= _nb_pkts_total) {
|
||||
throw std::runtime_error(ERROR_STR_INDEX_OUT_OF_BOUNDS);
|
||||
}
|
||||
|
||||
int i = -1;
|
||||
int j = -1;
|
||||
calculate_array_coordinates_from_index(index, i, j);
|
||||
|
||||
PacketInfoCreator::destroy_pkt_info(_pkt_info_arrs[i][j]);
|
||||
|
||||
if (unlikely(_mbuf_arrs[i][j] != nullptr)) {
|
||||
rte_pktmbuf_free(_mbuf_arrs[i][j]);
|
||||
}
|
||||
|
||||
_pkt_info_arrs[i][j] = nullptr;
|
||||
_mbuf_arrs[i][j] = nullptr;
|
||||
|
||||
++_nb_pkts_dropped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Drop packet.
|
||||
*
|
||||
* @param index Index of the packet to drop.
|
||||
*/
|
||||
inline void drop_packet(int index, PacketInfoIpv4Tcp* pkt_to_drop) {
|
||||
if (index >= _nb_pkts_total) {
|
||||
throw std::runtime_error(ERROR_STR_INDEX_OUT_OF_BOUNDS);
|
||||
}
|
||||
|
||||
int i = -1;
|
||||
int j = -1;
|
||||
calculate_array_coordinates_from_index(index, i, j);
|
||||
|
||||
delete pkt_to_drop;
|
||||
|
||||
if (unlikely(_mbuf_arrs[i][j] != nullptr)) {
|
||||
rte_pktmbuf_free(_mbuf_arrs[i][j]);
|
||||
}
|
||||
|
||||
_pkt_info_arrs[i][j] = nullptr;
|
||||
_mbuf_arrs[i][j] = nullptr;
|
||||
|
||||
++_nb_pkts_dropped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Take the packet
|
||||
*
|
||||
* Return a PacketInfo object. The corresponding packet will be removed from
|
||||
* the PacketContainer so it is no longer in there and will not be sent. The
|
||||
* only reference available to the packet is the returned PacketInfo
|
||||
* pointer.
|
||||
*
|
||||
* Because the packet is removed from the container the responsibility for
|
||||
* dropping|sending the packet is up to you. Usually you would add this
|
||||
* packet to a packet container and sen dor drop the packet afterwards.
|
||||
*
|
||||
* If you want to just get the pointer to a PacketInfo object that sould
|
||||
* remain in the container do not use this method.
|
||||
*
|
||||
* @param index
|
||||
* @return PacketInfo*
|
||||
*/
|
||||
inline PacketInfo* take_packet(int index) {
|
||||
if (index >= _nb_pkts_total) {
|
||||
throw std::runtime_error(ERROR_STR_INDEX_OUT_OF_BOUNDS);
|
||||
}
|
||||
|
||||
int i, j;
|
||||
calculate_array_coordinates_from_index(index, i, j);
|
||||
PacketInfo* pkt_info = _pkt_info_arrs[i][j];
|
||||
_pkt_info_arrs[i][j] = nullptr;
|
||||
_mbuf_arrs[i][j] = nullptr;
|
||||
++_nb_pkts_dropped;
|
||||
|
||||
++_nb_pkts_dropped;
|
||||
|
||||
return pkt_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief add Packet to Container which already exists but is stored
|
||||
* somewhere else.
|
||||
*
|
||||
* Add Packet to container which already exists but is stored
|
||||
* somewhere else. All values (payload and metadata) of the passed mbuf will
|
||||
* be adopted. These are set as
|
||||
* parameter of the function call.
|
||||
*
|
||||
* @param[in] pkt_container packet container pointer to the packet to be
|
||||
* added
|
||||
* @return index of the newly added packet
|
||||
*/
|
||||
inline int add_packet(PacketInfo* pkt_info) {
|
||||
int i, j;
|
||||
calculate_array_coordinates_from_index(_nb_pkts_total, i, j);
|
||||
_mbuf_arrs[i][j] = pkt_info->get_mbuf();
|
||||
_pkt_info_arrs[i][j] = pkt_info;
|
||||
|
||||
++_nb_pkts_total;
|
||||
++_nb_mbufs_in_mbuf_arr[i];
|
||||
|
||||
if (unlikely(BURST_SIZE * _nb_pkt_arrays < _nb_pkts_total)) {
|
||||
++_nb_pkt_arrays;
|
||||
}
|
||||
|
||||
return _nb_pkts_total - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the PacketInfo object at index
|
||||
*
|
||||
* Use this Method to get a packet and work with it (read, write
|
||||
* information). You do not have to add it to the PacketContainer again. The
|
||||
* packet is still in the Container you only get the reference.
|
||||
*
|
||||
* @param index
|
||||
* @return PacketInfo*
|
||||
*/
|
||||
inline PacketInfo* get_packet_at_index(int index) {
|
||||
if (index >= _nb_pkts_total) {
|
||||
throw std::runtime_error(ERROR_STR_INDEX_OUT_OF_BOUNDS);
|
||||
}
|
||||
|
||||
int i, j;
|
||||
calculate_array_coordinates_from_index(index, i, j);
|
||||
|
||||
return _pkt_info_arrs[i][j];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get new empty packets PacketInfo to specified packet type
|
||||
*
|
||||
* This method is to get you a pointer to an empty PacketInfo object of
|
||||
* specified type. This pointer is diguised as normal PacketInfo. You can
|
||||
* work with the PacketInfo object as you want then. You have to cast the
|
||||
* pointer to specified PacketInfo version to use specific IP and L4
|
||||
* protocol functions. You do not have to add it to the PacketContainer
|
||||
* again. The packet is still in the Container you only get the reference.
|
||||
* This packetInfo already has a mbuf.
|
||||
*
|
||||
* @param pkt_type specifies type of PacketInfo which should be created
|
||||
* @return PacketInfo*
|
||||
*/
|
||||
inline PacketInfo* get_empty_packet(PacketType pkt_type) {
|
||||
int i, j;
|
||||
calculate_array_coordinates_from_index(_nb_pkts_total, i, j);
|
||||
|
||||
++_nb_pkts_total;
|
||||
++_nb_mbufs_in_mbuf_arr[i];
|
||||
|
||||
if (unlikely(BURST_SIZE * _nb_pkt_arrays < _nb_pkts_total)) {
|
||||
++_nb_pkt_arrays;
|
||||
}
|
||||
_mbuf_arrs[i][j] = rte_pktmbuf_alloc(_mempool);
|
||||
_pkt_info_arrs[i][j] =
|
||||
PacketInfoCreator::create_pkt_info(_mbuf_arrs[i][j], pkt_type);
|
||||
return _pkt_info_arrs[i][j];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get new empty packets PacketInfo to a IPv4TCP packet
|
||||
*
|
||||
* This method is to get you a pointer to an empty PacketInfoIpv4Tcp object.
|
||||
* This pointer is diguised as normal PacketInfo. You can work with the
|
||||
* PacketInfo object as you want then. You have to cast the pointer to
|
||||
* PacketInfoIpv4Tcp to use specific IPv4 and TCP functions. You do not have
|
||||
* to add it to the PacketContainer again. The packet is still in the
|
||||
* Container you only get the reference. This packetInfo already has a mbuf.
|
||||
*
|
||||
* @return PacketInfo*
|
||||
*/
|
||||
inline PacketInfo* get_empty_packet() { return get_empty_packet(IPv4TCP); }
|
||||
|
||||
/**
|
||||
* @brief Get the number of polled packets
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_number_of_polled_packets() { return _nb_pkts_polled; }
|
||||
|
||||
/**
|
||||
* @brief Get the total number of packets in the container
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_total_number_of_packets() { return _nb_pkts_total; }
|
||||
|
||||
/**
|
||||
* @brief Get the mempool
|
||||
*
|
||||
* @return rte_mempool*
|
||||
*/
|
||||
inline rte_mempool* get_mempool() { return _mempool; }
|
||||
|
||||
#ifdef TEST
|
||||
uint16_t* get_nb_mbufs_in_mbuf_arr() { return _nb_mbufs_in_mbuf_arr; }
|
||||
|
||||
int get_nb_pkts_dropped() { return _nb_pkts_dropped; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
struct rte_mempool* _mempool;
|
||||
|
||||
uint16_t _rx_queue_number;
|
||||
uint16_t _tx_queue_number;
|
||||
|
||||
/**
|
||||
* Port ID of the port the packets are to be polled
|
||||
* from
|
||||
*/
|
||||
uint16_t _entrance_port;
|
||||
/**
|
||||
* Port ID of the port the packets are to be sent
|
||||
* to
|
||||
*/
|
||||
uint16_t _exit_port;
|
||||
|
||||
/**
|
||||
* Number of packets that where polled. Newly
|
||||
* created or added packets are not counted.
|
||||
*/
|
||||
uint16_t _nb_pkts_polled;
|
||||
/**
|
||||
* Total number of mbufs their references are
|
||||
* stored in _mbuf_arrs. nullptrs in between valid mbuf pointers are
|
||||
* counted, too.
|
||||
*/
|
||||
uint16_t _nb_pkts_total;
|
||||
|
||||
/**
|
||||
* Number of Arrays that are stored in _mbuf_arrs
|
||||
*/
|
||||
int _nb_pkt_arrays;
|
||||
|
||||
/**
|
||||
* Total number of Packets dropped; is increased when a packet is removed
|
||||
* from the container by take_packet or drop_packet
|
||||
* \todo rename to _nb_pkts_removed
|
||||
*/
|
||||
int _nb_pkts_dropped;
|
||||
|
||||
/**
|
||||
* @brief Array of arrays of [rte_mbuf* |
|
||||
* PacketInfo*]
|
||||
*
|
||||
* A 2d-array is used instead of just a 1d-array to
|
||||
* be able to store multiple arrays with the fixed
|
||||
* size of BURST_SIZE. This is necessary if new
|
||||
* packets are created but the first array is full.
|
||||
* In this case a new array would be used to store
|
||||
* newly created packets. Otherwise only one
|
||||
* 1d-Array is used, the 2d-array-array would have
|
||||
* just one element then.
|
||||
*
|
||||
* Each PacketInfo object is assignet to one and
|
||||
* only one mbuf. PacketInfo at index "i" holds
|
||||
* information to mbuf at index "i".
|
||||
*/
|
||||
/**@{*/
|
||||
struct rte_mbuf* _mbuf_arrs[NUM_MBUF_ARRS][BURST_SIZE];
|
||||
PacketInfo* _pkt_info_arrs[NUM_MBUF_ARRS][BURST_SIZE];
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* Number of mbufs in each sub-array of _mbuf_arrs. nullptrs in between
|
||||
* valid mbuf pointers are counted, too.
|
||||
*/
|
||||
uint16_t _nb_mbufs_in_mbuf_arr[NUM_MBUF_ARRS];
|
||||
|
||||
#ifdef TEST
|
||||
public:
|
||||
#endif
|
||||
/**
|
||||
* @brief Reorder the mbuf arrays; meaning remove nullptrs. So no nullptr
|
||||
* will be given to the send_packets_to_port method of the
|
||||
* NetworkPacketHandler.
|
||||
*/
|
||||
inline void reorder_mbuf_arrays() {
|
||||
if (likely(_nb_pkts_total > 0)) {
|
||||
for (int i = 0; i < _nb_pkt_arrays; ++i) {
|
||||
|
||||
// go through mbufs, reorder
|
||||
int len = _nb_mbufs_in_mbuf_arr[i];
|
||||
int nb_elements_to_skip = 0;
|
||||
|
||||
for (int j = 0; j < len; ++j) {
|
||||
if (_mbuf_arrs[i][j] == nullptr) {
|
||||
++nb_elements_to_skip;
|
||||
} else if (nb_elements_to_skip > 0) {
|
||||
_mbuf_arrs[i][j - nb_elements_to_skip] =
|
||||
_mbuf_arrs[i][j];
|
||||
_mbuf_arrs[i][j] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
_nb_mbufs_in_mbuf_arr[i] -= nb_elements_to_skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef TEST
|
||||
protected:
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Calculate the "i" and "j" coordinates for
|
||||
* a 2d array from a 1d integer "index".
|
||||
*
|
||||
* @param[in] index
|
||||
* @param[out] i
|
||||
* @param[out] j
|
||||
*/
|
||||
inline void calculate_array_coordinates_from_index(int index, int& i,
|
||||
int& j) {
|
||||
i = (index - (index % BURST_SIZE)) / BURST_SIZE;
|
||||
j = index % BURST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Does the what
|
||||
* calculate_array_coordinates_from_index does but
|
||||
* in the other direction.
|
||||
*
|
||||
* Beware: The order of the arguments is important!
|
||||
*
|
||||
* @param[in] i first dimesnion index
|
||||
* @param[in] j second dimension index
|
||||
* @param[out] index
|
||||
*/
|
||||
inline void calculate_index_from_array_coordinates(int i, int j,
|
||||
int& index) {
|
||||
index = i * BURST_SIZE + j;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the _state of the container to EMPTY
|
||||
* and assign variables to 0.
|
||||
*/
|
||||
inline void empty_container() {
|
||||
int nb_pkts_remaining = _nb_pkts_total;
|
||||
|
||||
for (int i = 0; i < _nb_pkt_arrays; ++i) {
|
||||
int len = _nb_mbufs_in_mbuf_arr[i];
|
||||
|
||||
for (int j = 0; j < len; ++j) {
|
||||
if (_pkt_info_arrs[i][j] != nullptr) {
|
||||
PacketInfoCreator::destroy_pkt_info(_pkt_info_arrs[i][j]);
|
||||
_pkt_info_arrs[i][j] = nullptr;
|
||||
}
|
||||
|
||||
_mbuf_arrs[i][j] = nullptr;
|
||||
}
|
||||
|
||||
_nb_mbufs_in_mbuf_arr[i] = 0;
|
||||
}
|
||||
|
||||
_nb_pkts_polled = 0;
|
||||
_nb_pkts_total = 0;
|
||||
_nb_pkts_dropped = 0;
|
||||
_nb_pkt_arrays = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates a PacketInfo for every packet
|
||||
* in PacketContainer and saves them with
|
||||
* corresponding index in PacketInfo Array
|
||||
*
|
||||
*/
|
||||
inline void extract_header_info() {
|
||||
for (int i = 0; i < _nb_pkts_polled; ++i) {
|
||||
_pkt_info_arrs[0][i] =
|
||||
fill_info(_mbuf_arrs[0][i], _pkt_info_arrs[0][i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates PacketInfo for given mbuf
|
||||
*
|
||||
* @param[in] mbuf dpdk abstraction of a packet
|
||||
* for which a PacketInfo should be created
|
||||
* @param[out] pkt_inf newly created PacketInfo
|
||||
*/
|
||||
inline PacketInfo* fill_info(rte_mbuf* mbuf, PacketInfo* pkt_inf) {
|
||||
pkt_inf = PacketInfoCreator::create_pkt_info(mbuf);
|
||||
return pkt_inf;
|
||||
}
|
||||
};
|
168
include/PacketDissection/PacketContainerLean.hpp
Normal file
168
include/PacketDissection/PacketContainerLean.hpp
Normal file
@ -0,0 +1,168 @@
|
||||
#pragma once
|
||||
|
||||
#include "PacketDissection/PacketContainer.hpp"
|
||||
|
||||
/**
|
||||
* @brief This class holds the same functions like the PacketContainer except it
|
||||
* only holds mbufs and no PacketInfo
|
||||
*
|
||||
* only send/reorder etc polled packets. Manually created packets are never
|
||||
* dropped.
|
||||
*/
|
||||
class PacketContainerLean : protected PacketContainer {
|
||||
public:
|
||||
inline PacketContainerLean(struct rte_mempool* mbuf_pool,
|
||||
uint16_t entrance_port, uint16_t exit_port,
|
||||
uint16_t rx_queue_number,
|
||||
uint16_t tx_queue_number)
|
||||
: PacketContainer(mbuf_pool, entrance_port, exit_port, rx_queue_number,
|
||||
tx_queue_number),
|
||||
_nb_polled_pkts_dropped(0) {}
|
||||
|
||||
inline ~PacketContainerLean() { empty_container_lean(); }
|
||||
|
||||
inline void poll_mbufs(uint16_t& nb_mbufs_polled) {
|
||||
empty_container_lean();
|
||||
|
||||
_nb_pkts_polled = rte_eth_rx_burst(_entrance_port, _rx_queue_number,
|
||||
_mbuf_arrs[0], BURST_SIZE);
|
||||
|
||||
_nb_pkts_total = _nb_pkts_polled;
|
||||
|
||||
if (likely(_nb_pkts_polled > 0)) {
|
||||
_nb_pkt_arrays = 1;
|
||||
_nb_mbufs_in_mbuf_arr[0] = _nb_pkts_polled;
|
||||
}
|
||||
|
||||
// return
|
||||
nb_mbufs_polled = _nb_pkts_polled;
|
||||
}
|
||||
|
||||
inline uint send_mbufs() {
|
||||
uint sum_mbufs_send = 0;
|
||||
if (likely(_nb_pkts_total > 0)) {
|
||||
if (unlikely(_nb_polled_pkts_dropped != 0)) {
|
||||
reorder_mbuf_arrays();
|
||||
}
|
||||
|
||||
for (int i = 0; i < _nb_pkt_arrays; ++i) {
|
||||
uint16_t nb_pkts_to_send = _nb_mbufs_in_mbuf_arr[i];
|
||||
|
||||
// send mbufs
|
||||
uint16_t nb_pkts_sent =
|
||||
rte_eth_tx_burst(_exit_port, _tx_queue_number,
|
||||
_mbuf_arrs[i], nb_pkts_to_send);
|
||||
|
||||
#ifdef LOG_PKTS_SENT
|
||||
LOG_INFO << "Number of packets sent: " << nb_pkts_sent
|
||||
<< LOG_END;
|
||||
#endif
|
||||
|
||||
sum_mbufs_send += nb_pkts_sent;
|
||||
// Free any unsent packets.
|
||||
if (unlikely(nb_pkts_sent < nb_pkts_to_send)) {
|
||||
for (int j = nb_pkts_sent; j < nb_pkts_to_send; ++j) {
|
||||
rte_pktmbuf_free(_mbuf_arrs[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
empty_container_lean();
|
||||
return sum_mbufs_send;
|
||||
}
|
||||
|
||||
inline void drop_polled_mbuf(int index) {
|
||||
if (index >= _nb_pkts_polled) {
|
||||
throw std::runtime_error(
|
||||
ERROR_STR_INDEX_OUT_OF_BOUNDS
|
||||
" No... actually it is _nb_pkts_polled that is exceeded");
|
||||
}
|
||||
|
||||
int i = -1;
|
||||
int j = -1;
|
||||
calculate_array_coordinates_from_index(index, i, j);
|
||||
|
||||
if (unlikely(_mbuf_arrs[i][j] != nullptr)) {
|
||||
rte_pktmbuf_free(_mbuf_arrs[i][j]);
|
||||
}
|
||||
|
||||
_pkt_info_arrs[i][j] = nullptr;
|
||||
_mbuf_arrs[i][j] = nullptr;
|
||||
|
||||
++_nb_polled_pkts_dropped;
|
||||
}
|
||||
|
||||
inline rte_mbuf* get_empty_mbuf() {
|
||||
int i, j;
|
||||
calculate_array_coordinates_from_index(_nb_pkts_total, i, j);
|
||||
|
||||
++_nb_pkts_total;
|
||||
++_nb_mbufs_in_mbuf_arr[i];
|
||||
|
||||
if (unlikely(BURST_SIZE * _nb_pkt_arrays < _nb_pkts_total)) {
|
||||
++_nb_pkt_arrays;
|
||||
}
|
||||
_mbuf_arrs[i][j] = rte_pktmbuf_alloc(_mempool);
|
||||
|
||||
return _mbuf_arrs[i][j];
|
||||
}
|
||||
|
||||
inline int add_mbuf(rte_mbuf* mbuf) {
|
||||
int i = -1;
|
||||
int j = -1;
|
||||
calculate_array_coordinates_from_index(_nb_pkts_total, i, j);
|
||||
_mbuf_arrs[i][j] = mbuf;
|
||||
|
||||
++_nb_pkts_total;
|
||||
++_nb_mbufs_in_mbuf_arr[i];
|
||||
|
||||
if (unlikely(BURST_SIZE * _nb_pkt_arrays < _nb_pkts_total)) {
|
||||
++_nb_pkt_arrays;
|
||||
}
|
||||
|
||||
return _nb_pkts_total - 1;
|
||||
}
|
||||
|
||||
inline uint16_t get_number_of_polled_mbufs() { return _nb_pkts_polled; }
|
||||
|
||||
inline rte_mbuf* get_mbuf_at_index(int index) {
|
||||
if (unlikely(index >= _nb_pkts_total)) {
|
||||
throw std::runtime_error(ERROR_STR_INDEX_OUT_OF_BOUNDS);
|
||||
}
|
||||
|
||||
int i = -1;
|
||||
int j = -1;
|
||||
calculate_array_coordinates_from_index(index, i, j);
|
||||
|
||||
return _mbuf_arrs[i][j];
|
||||
}
|
||||
|
||||
inline rte_mempool* get_mempool_lean() { return get_mempool(); }
|
||||
|
||||
private:
|
||||
int _nb_polled_pkts_dropped;
|
||||
|
||||
inline void empty_container_lean() {
|
||||
|
||||
empty_mbuf_arr();
|
||||
|
||||
_nb_pkts_polled = 0;
|
||||
_nb_pkts_total = 0;
|
||||
_nb_pkts_dropped = 0;
|
||||
_nb_polled_pkts_dropped = 0;
|
||||
_nb_pkt_arrays = 0;
|
||||
}
|
||||
|
||||
inline void empty_mbuf_arr() {
|
||||
for (int i = 0; i < _nb_pkt_arrays; ++i) {
|
||||
int len = _nb_mbufs_in_mbuf_arr[i];
|
||||
|
||||
for (int j = 0; j < len; ++j) {
|
||||
_mbuf_arrs[i][j] = nullptr;
|
||||
}
|
||||
|
||||
_nb_mbufs_in_mbuf_arr[i] = 0;
|
||||
}
|
||||
}
|
||||
};
|
93
include/PacketDissection/PacketInfo.hpp
Normal file
93
include/PacketDissection/PacketInfo.hpp
Normal file
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @file PacketInfo.hpp
|
||||
* @author Tobias
|
||||
* @brief class to provide general packet information
|
||||
* @date 2021-06-08
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rte_ether.h>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
enum PacketType {
|
||||
NONE,
|
||||
IPv4ICMP,
|
||||
IPv4TCP,
|
||||
IPv4UDP,
|
||||
IPv6ICMP,
|
||||
IPv6TCP,
|
||||
IPv6UDP,
|
||||
IPv4,
|
||||
IPv6,
|
||||
ARP
|
||||
};
|
||||
|
||||
class PacketInfo {
|
||||
public:
|
||||
inline PacketInfo() : _type(NONE), _mbuf(nullptr), _eth_hdr(nullptr) {}
|
||||
|
||||
inline PacketInfo(rte_mbuf* const mbuf, rte_ether_hdr* const eth_hdr)
|
||||
: _type(NONE), _mbuf(mbuf), _eth_hdr(eth_hdr) {}
|
||||
|
||||
inline ~PacketInfo() {
|
||||
//_mbuf = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get pointer to mbuf
|
||||
*
|
||||
* @return rte_mbuf*
|
||||
*/
|
||||
inline rte_mbuf* const get_mbuf() { return _mbuf; }
|
||||
|
||||
/**
|
||||
* @brief Get PacketInfos specialised type
|
||||
*
|
||||
* @return PacketType
|
||||
*/
|
||||
inline PacketType const get_type() { return _type; }
|
||||
|
||||
/**
|
||||
* @brief Get the source MAC-address
|
||||
*
|
||||
* @return rte_ether_addr
|
||||
*/
|
||||
inline rte_ether_addr get_src_mac() { return _eth_hdr->s_addr; }
|
||||
|
||||
/**
|
||||
* @brief Get the destination MAC-address
|
||||
*
|
||||
* @return rte_ether_addr
|
||||
*/
|
||||
inline rte_ether_addr get_dst_mac() { return _eth_hdr->d_addr; }
|
||||
|
||||
protected:
|
||||
inline PacketInfo(PacketType const type, rte_mbuf* const mbuf,
|
||||
rte_ether_hdr* const eth_hdr)
|
||||
: _type(type), _mbuf(mbuf), _eth_hdr(eth_hdr) {}
|
||||
|
||||
inline PacketInfo(PacketType const type, rte_mbuf* const mbuf)
|
||||
: _type(type), _mbuf(mbuf), _eth_hdr(nullptr) {}
|
||||
|
||||
PacketType const _type;
|
||||
rte_ether_hdr* const _eth_hdr;
|
||||
|
||||
inline rte_ether_hdr* const get_eth_hdr() { return _eth_hdr; }
|
||||
|
||||
/**
|
||||
* @brief fill out standart ethernet header
|
||||
*
|
||||
* @param dst_mac MAC-address of destination
|
||||
* @param src_mac MAC-address of claimed source
|
||||
*/
|
||||
inline void fill_eth_hdr(const rte_ether_addr& dst_mac,
|
||||
const rte_ether_addr& src_mac) {
|
||||
_eth_hdr->d_addr = dst_mac;
|
||||
_eth_hdr->s_addr = src_mac;
|
||||
}
|
||||
|
||||
private:
|
||||
rte_mbuf* const _mbuf;
|
||||
};
|
290
include/PacketDissection/PacketInfoCreator.hpp
Normal file
290
include/PacketDissection/PacketInfoCreator.hpp
Normal file
@ -0,0 +1,290 @@
|
||||
/**
|
||||
* @file PacketInfoCreator.hpp
|
||||
* @author Tobias
|
||||
* @brief
|
||||
* @date 2021-06-16
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <rte_ether.h>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "Definitions.hpp"
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Icmp.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Tcp.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Udp.hpp"
|
||||
|
||||
#define RTE_ETHER_ADDR_LEN 6
|
||||
|
||||
#define ETHER_TYPE_IPv4 0x0800
|
||||
|
||||
class PacketInfoCreator {
|
||||
public:
|
||||
/**
|
||||
* @brief Create a PacketInfo object for given mbuf
|
||||
*
|
||||
* @param mbuf dpdk abstraction for one packet
|
||||
* @return PacketInfo*
|
||||
*/
|
||||
inline static PacketInfo* create_pkt_info(rte_mbuf* mbuf) {
|
||||
struct rte_ether_hdr* eth_hdr;
|
||||
eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*);
|
||||
uint16_t offset = (uint16_t)sizeof(struct rte_ether_hdr);
|
||||
|
||||
/// from here on we know the l3 type
|
||||
if (rte_be_to_cpu_16(eth_hdr->ether_type) == ETHER_TYPE_IPv4) {
|
||||
struct rte_ipv4_hdr* ip4_hdr;
|
||||
ip4_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, offset);
|
||||
uint8_t protocol_id = ip4_hdr->next_proto_id;
|
||||
|
||||
if (protocol_id == 6) { // TCP
|
||||
// calculate point where TCP-header begins
|
||||
offset = offset + (ip4_hdr->version_ihl - 64) * 4;
|
||||
// map TCP-header on memory
|
||||
struct rte_tcp_hdr* tcp_hdr;
|
||||
tcp_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr*, offset);
|
||||
// create PacketInfo
|
||||
PacketInfoIpv4Tcp* pkt_inf =
|
||||
new PacketInfoIpv4Tcp(mbuf, eth_hdr, ip4_hdr, tcp_hdr);
|
||||
|
||||
return pkt_inf;
|
||||
} else if (protocol_id == 17) { // UDP
|
||||
offset = offset + (ip4_hdr->version_ihl - 64) * 4;
|
||||
struct rte_udp_hdr* udp_hdr;
|
||||
udp_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_udp_hdr*, offset);
|
||||
|
||||
PacketInfoIpv4Udp* pkt_inf =
|
||||
new PacketInfoIpv4Udp(mbuf, eth_hdr, ip4_hdr, udp_hdr);
|
||||
|
||||
return pkt_inf;
|
||||
} else if (protocol_id == 1) { // ICMP
|
||||
offset = offset + (ip4_hdr->version_ihl - 64) * 4;
|
||||
struct rte_icmp_hdr* icmp_hdr;
|
||||
icmp_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_icmp_hdr*, offset);
|
||||
PacketInfoIpv4Icmp* pkt_inf =
|
||||
new PacketInfoIpv4Icmp(mbuf, eth_hdr, ip4_hdr, icmp_hdr);
|
||||
|
||||
return pkt_inf;
|
||||
} else {
|
||||
printf("packet is neither TCP UDP nor ICMP");
|
||||
return new PacketInfo(mbuf, eth_hdr);
|
||||
}
|
||||
} else if (rte_be_to_cpu_16(eth_hdr->ether_type) == 0x86DD) {
|
||||
/// \TODO: implement IPv6
|
||||
return new PacketInfo(mbuf, eth_hdr);
|
||||
} else if (rte_be_to_cpu_16(eth_hdr->ether_type) == 0x0806) {
|
||||
/// \TODO: implement ARP
|
||||
return new PacketInfo(mbuf, eth_hdr);
|
||||
} else {
|
||||
return new PacketInfo(mbuf, eth_hdr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a PacketInfo object for given packet type
|
||||
*
|
||||
* @param mbuf dpdk abstraction for one packet
|
||||
* @param type specifies Type which PacketInfo should have
|
||||
* @return PacketInfo*
|
||||
*/
|
||||
inline static PacketInfo* create_pkt_info(rte_mbuf* mbuf, PacketType type) {
|
||||
|
||||
int off_set = sizeof(struct rte_ether_hdr);
|
||||
struct rte_ether_hdr* eth_hdr;
|
||||
rte_pktmbuf_append(mbuf, sizeof(struct rte_ether_hdr));
|
||||
eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*);
|
||||
|
||||
switch (type) {
|
||||
case IPv4ICMP: {
|
||||
eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
|
||||
|
||||
struct rte_ipv4_hdr* ip4_hdr;
|
||||
rte_pktmbuf_append(mbuf, sizeof(rte_ipv4_hdr));
|
||||
ip4_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set);
|
||||
off_set = off_set + sizeof(rte_ipv4_hdr);
|
||||
|
||||
rte_pktmbuf_append(mbuf, sizeof(rte_icmp_hdr));
|
||||
rte_icmp_hdr* icmp_hdr;
|
||||
icmp_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_icmp_hdr*, off_set);
|
||||
|
||||
return new PacketInfoIpv4Icmp(mbuf, eth_hdr, ip4_hdr, icmp_hdr);
|
||||
} break;
|
||||
|
||||
case IPv4TCP: {
|
||||
eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); // 0x0008
|
||||
|
||||
struct rte_ipv4_hdr* ip4_hdr;
|
||||
rte_pktmbuf_append(mbuf,
|
||||
sizeof(rte_ipv4_hdr) + sizeof(rte_tcp_hdr));
|
||||
ip4_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set);
|
||||
off_set = off_set + sizeof(rte_ipv4_hdr);
|
||||
|
||||
rte_tcp_hdr* tcp_hdr;
|
||||
tcp_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr*, off_set);
|
||||
|
||||
return new PacketInfoIpv4Tcp(mbuf, eth_hdr, ip4_hdr, tcp_hdr);
|
||||
} break;
|
||||
|
||||
case IPv4UDP: {
|
||||
eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
|
||||
|
||||
struct rte_ipv4_hdr* ip4_hdr;
|
||||
rte_pktmbuf_append(mbuf, sizeof(rte_ipv4_hdr));
|
||||
ip4_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set);
|
||||
off_set = off_set + sizeof(rte_ipv4_hdr);
|
||||
|
||||
rte_pktmbuf_append(mbuf, sizeof(rte_udp_hdr));
|
||||
rte_udp_hdr* udp_hdr;
|
||||
udp_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_udp_hdr*, off_set);
|
||||
|
||||
return new PacketInfoIpv4Udp(mbuf, eth_hdr, ip4_hdr, udp_hdr);
|
||||
} break;
|
||||
|
||||
case IPv6ICMP:
|
||||
return new PacketInfo(mbuf, eth_hdr);
|
||||
break;
|
||||
|
||||
case IPv6TCP:
|
||||
return new PacketInfo(mbuf, eth_hdr);
|
||||
break;
|
||||
|
||||
case IPv6UDP:
|
||||
return new PacketInfo(mbuf, eth_hdr);
|
||||
break;
|
||||
|
||||
default:
|
||||
return new PacketInfo(mbuf, eth_hdr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a minimalized PacketInfo
|
||||
* this Packet is expected to already have a filled ether header
|
||||
* and is only for IPv4
|
||||
* @param mbuf dpdk abstraction for one packet
|
||||
* @param type specifies Type which PacketInfo should have
|
||||
* @return PacketInfo*
|
||||
*/
|
||||
inline static PacketInfo* create_mini_pkt_info(rte_mbuf* mbuf,
|
||||
PacketType type) {
|
||||
int off_set = sizeof(struct rte_ether_hdr);
|
||||
|
||||
switch (type) {
|
||||
|
||||
case IPv4TCP: {
|
||||
|
||||
struct rte_ipv4_hdr* ip4_hdr;
|
||||
ip4_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set);
|
||||
off_set = off_set + sizeof(rte_ipv4_hdr);
|
||||
|
||||
rte_tcp_hdr* tcp_hdr;
|
||||
tcp_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr*, off_set);
|
||||
|
||||
return new PacketInfoIpv4Tcp(mbuf, ip4_hdr, tcp_hdr);
|
||||
} break;
|
||||
|
||||
case IPv4UDP: {
|
||||
|
||||
struct rte_ipv4_hdr* ip4_hdr;
|
||||
ip4_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set);
|
||||
off_set = off_set + sizeof(rte_ipv4_hdr);
|
||||
|
||||
rte_udp_hdr* udp_hdr;
|
||||
udp_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_udp_hdr*, off_set);
|
||||
|
||||
return new PacketInfoIpv4Udp(mbuf, ip4_hdr, udp_hdr);
|
||||
} break;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns a packets destiantion ip
|
||||
* This method takes an mbuf and extract the IPv4 IP-adress.
|
||||
* In case the packet inside the mbuf is no IPv4 packet, 0 will be returned
|
||||
* @param mbuf structure to hand packets over
|
||||
* @return uint32_t packets IP-adress; it's 0, in case of no IPv4
|
||||
*/
|
||||
inline static uint32_t get_dst_ip_from_mbuf(rte_mbuf* mbuf) {
|
||||
|
||||
rte_ether_hdr* eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*);
|
||||
|
||||
if (eth_hdr->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
|
||||
|
||||
int off_set = sizeof(struct rte_ether_hdr);
|
||||
rte_ipv4_hdr* ip_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set);
|
||||
return rte_be_to_cpu_32(ip_hdr->dst_addr);
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline static void destroy_pkt_info(PacketInfo* info) {
|
||||
|
||||
PacketType type = info->get_type();
|
||||
switch (type) {
|
||||
|
||||
case IPv4TCP: {
|
||||
delete static_cast<PacketInfoIpv4Tcp*>(info);
|
||||
} break;
|
||||
|
||||
case IPv4UDP: {
|
||||
delete static_cast<PacketInfoIpv4Udp*>(info);
|
||||
} break;
|
||||
|
||||
case NONE: {
|
||||
delete info;
|
||||
} break;
|
||||
case IPv4ICMP: {
|
||||
delete static_cast<PacketInfoIpv4Icmp*>(info);
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool is_ipv4_tcp(rte_mbuf* mbuf) {
|
||||
struct rte_ether_hdr* eth_hdr;
|
||||
eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*);
|
||||
|
||||
if (rte_be_to_cpu_16(eth_hdr->ether_type) == ETHER_TYPE_IPv4) {
|
||||
uint16_t offset = (uint16_t)sizeof(struct rte_ether_hdr);
|
||||
struct rte_ipv4_hdr* ip4_hdr;
|
||||
ip4_hdr =
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, offset);
|
||||
uint8_t protocol_id = ip4_hdr->next_proto_id;
|
||||
|
||||
if (protocol_id == 6) { // TCP
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
135
include/PacketDissection/PacketInfoIpv4.hpp
Normal file
135
include/PacketDissection/PacketInfoIpv4.hpp
Normal file
@ -0,0 +1,135 @@
|
||||
/**
|
||||
* @file PacketInfoIpv4.hpp
|
||||
* @author Tobias
|
||||
* @brief class which provides IPv4 header information
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_ip.h>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
#include "Definitions.hpp"
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
|
||||
#define IP_HDR_LEN 20
|
||||
#define VERSION_AND_IP_HDR_LEN 0b01000101
|
||||
|
||||
class PacketInfoIpv4 : public PacketInfo {
|
||||
public:
|
||||
PacketInfoIpv4();
|
||||
inline PacketInfoIpv4(rte_mbuf* const mbuf, rte_ether_hdr* const eth_hdr,
|
||||
rte_ipv4_hdr* const ip_hdr)
|
||||
: PacketInfo(IPv4, mbuf, eth_hdr), _ip4_hdr(ip_hdr) {}
|
||||
inline ~PacketInfoIpv4() {
|
||||
// PacketInfo::~PacketInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets destination IP address
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
inline uint32_t get_dst_ip() {
|
||||
return rte_be_to_cpu_32(_ip4_hdr->dst_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets source IP address
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
inline uint32_t get_src_ip() {
|
||||
return rte_be_to_cpu_32(_ip4_hdr->src_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set packets source IP address
|
||||
*
|
||||
* @param ip
|
||||
*/
|
||||
inline void set_src_ip(uint32_t ip) {
|
||||
_ip4_hdr->src_addr = rte_cpu_to_be_32(ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets size in byte
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_packet_size() {
|
||||
return rte_be_to_cpu_16(_ip4_hdr->total_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the ip header struct
|
||||
*
|
||||
* @return rte_ipv4_hdr*
|
||||
*/
|
||||
inline rte_ipv4_hdr* const get_ip_hdr() { return _ip4_hdr; }
|
||||
|
||||
void set_ip_cksm(uint16_t cksm);
|
||||
|
||||
protected:
|
||||
inline PacketInfoIpv4(PacketType const type, rte_mbuf* const mbuf,
|
||||
rte_ether_hdr* const eth_hdr,
|
||||
rte_ipv4_hdr* const ip_hdr)
|
||||
: PacketInfo(type, mbuf, eth_hdr), _ip4_hdr(ip_hdr) {}
|
||||
|
||||
inline PacketInfoIpv4(PacketType const type, rte_mbuf* const mbuf,
|
||||
rte_ipv4_hdr* const ip_hdr)
|
||||
: PacketInfo(type, mbuf), _ip4_hdr(ip_hdr) {}
|
||||
|
||||
/**
|
||||
* @brief fills this packets IPv4 header with neseceties
|
||||
*
|
||||
* @param src_ip IP from which packet was originally send from
|
||||
* @param dst_ip IP packet is send to
|
||||
* @param proto protocol whose header follows after Ip-header
|
||||
* @param payload_len packets number of bytes without IP-header
|
||||
*/
|
||||
inline void fill_ip_hdr(uint32_t src_ip, uint32_t dst_ip, uint8_t proto,
|
||||
uint16_t payload_len) {
|
||||
|
||||
_ip4_hdr->src_addr = rte_cpu_to_be_32(src_ip);
|
||||
_ip4_hdr->dst_addr = rte_cpu_to_be_32(dst_ip);
|
||||
|
||||
_ip4_hdr->version_ihl = VERSION_AND_IP_HDR_LEN;
|
||||
_ip4_hdr->type_of_service = 0;
|
||||
_ip4_hdr->total_length = rte_be_to_cpu_16(payload_len + IP_HDR_LEN);
|
||||
_ip4_hdr->packet_id = 0;
|
||||
_ip4_hdr->fragment_offset = 0;
|
||||
_ip4_hdr->time_to_live = 128;
|
||||
_ip4_hdr->next_proto_id = proto;
|
||||
_ip4_hdr->hdr_checksum = 0;
|
||||
}
|
||||
|
||||
inline void recalculate_ip_checksum() {
|
||||
_ip4_hdr->hdr_checksum = rte_ipv4_cksum(_ip4_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get IP pseudo header checksum
|
||||
*
|
||||
* @return uint16_t IP pseudo header checksum
|
||||
*/
|
||||
inline uint16_t get_pseudo_hdr_cksm() {
|
||||
rte_mbuf* mbuf = get_mbuf();
|
||||
mbuf->l2_len = sizeof(struct rte_ether_hdr);
|
||||
mbuf->l3_len = sizeof(struct rte_ipv4_hdr);
|
||||
return rte_ipv4_phdr_cksum(_ip4_hdr, mbuf->ol_flags);
|
||||
}
|
||||
|
||||
inline uint8_t get_ip_hdr_len() {
|
||||
uint8_t len = _ip4_hdr->version_ihl & 0b00001111;
|
||||
len = len * 4;
|
||||
return len;
|
||||
}
|
||||
|
||||
private:
|
||||
rte_ipv4_hdr* const _ip4_hdr;
|
||||
};
|
45
include/PacketDissection/PacketInfoIpv4Icmp.hpp
Normal file
45
include/PacketDissection/PacketInfoIpv4Icmp.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @file PacketInfoIpv4Icmp.hpp
|
||||
* @author Tobias
|
||||
* @brief class to provide packets IPv4 and ICMP header information
|
||||
* @date 2021-06-08
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_icmp.h>
|
||||
|
||||
#include "PacketDissection/PacketInfoIpv4.hpp"
|
||||
|
||||
class PacketInfoIpv4Icmp : public PacketInfoIpv4 {
|
||||
public:
|
||||
inline PacketInfoIpv4Icmp();
|
||||
inline PacketInfoIpv4Icmp(rte_mbuf* mbuf, rte_ether_hdr* eth_hdr,
|
||||
rte_ipv4_hdr* ip_hdr, rte_icmp_hdr* l4_hdr)
|
||||
: PacketInfoIpv4(IPv4ICMP, mbuf, eth_hdr, ip_hdr), _icmp_hdr(l4_hdr) {}
|
||||
inline ~PacketInfoIpv4Icmp() {
|
||||
// PacketInfoIpv4::~PacketInfoIpv4();
|
||||
_icmp_hdr = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets payload size in byte
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_payload_size() { return 0; }
|
||||
|
||||
private:
|
||||
rte_icmp_hdr* _icmp_hdr;
|
||||
|
||||
/**
|
||||
* @brief Set the icmp header struct
|
||||
*
|
||||
* @param icmp_hdr
|
||||
*/
|
||||
inline void set_icmp_hdr(rte_icmp_hdr* icmp_hdr) {
|
||||
this->_icmp_hdr = icmp_hdr;
|
||||
}
|
||||
};
|
231
include/PacketDissection/PacketInfoIpv4Tcp.hpp
Normal file
231
include/PacketDissection/PacketInfoIpv4Tcp.hpp
Normal file
@ -0,0 +1,231 @@
|
||||
/**
|
||||
* @file PacketInfoIpv4Tcp.hpp
|
||||
* @author Tobias
|
||||
* @brief class to provide packets IPv4 and TCP header information
|
||||
* @date 2021-06-08
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_tcp.h>
|
||||
|
||||
#include "DebugHelper.hpp"
|
||||
#include "Definitions.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4.hpp"
|
||||
#include "PacketDissection/PacketProtTcp.hpp"
|
||||
|
||||
class PacketInfoIpv4Tcp : public PacketInfoIpv4 {
|
||||
public:
|
||||
inline PacketInfoIpv4Tcp();
|
||||
|
||||
inline PacketInfoIpv4Tcp(rte_mbuf* mbuf)
|
||||
: PacketInfoIpv4(
|
||||
IPv4TCP, mbuf, rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*),
|
||||
rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*,
|
||||
(uint16_t)sizeof(struct rte_ether_hdr)))
|
||||
, _tcp_hdr(rte_pktmbuf_mtod_offset(
|
||||
mbuf, struct rte_tcp_hdr*,
|
||||
(sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)))) {}
|
||||
|
||||
inline PacketInfoIpv4Tcp(rte_mbuf* mbuf, rte_ether_hdr* eth_hdr,
|
||||
rte_ipv4_hdr* ip_hdr, rte_tcp_hdr* l4_hdr)
|
||||
: PacketInfoIpv4(IPv4TCP, mbuf, eth_hdr, ip_hdr)
|
||||
, _tcp_hdr(l4_hdr) {}
|
||||
|
||||
inline PacketInfoIpv4Tcp(rte_mbuf* mbuf, rte_ipv4_hdr* ip_hdr,
|
||||
rte_tcp_hdr* l4_hdr)
|
||||
: PacketInfoIpv4(IPv4TCP, mbuf, ip_hdr)
|
||||
, _tcp_hdr(l4_hdr) {}
|
||||
|
||||
inline ~PacketInfoIpv4Tcp() {
|
||||
// PacketInfoIpv4::~PacketInfoIpv4();
|
||||
// _tcp_hdr = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set packets TCP sequence number
|
||||
*
|
||||
* @param seq_num
|
||||
*/
|
||||
inline void set_seq_num(uint32_t seq_num) {
|
||||
PacketProtTcp::set_seq_num(_tcp_hdr, seq_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set packets TCP acknowledgment number
|
||||
*
|
||||
* @param ack_num
|
||||
*/
|
||||
inline void set_ack_num(uint32_t ack_num) {
|
||||
PacketProtTcp::set_ack_num(_tcp_hdr, ack_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP destination port
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_dst_port() {
|
||||
return PacketProtTcp::get_dst_port(_tcp_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP source port
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_src_port() {
|
||||
return PacketProtTcp::get_src_port(_tcp_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP flags
|
||||
* MSB is CWR flag, LSB is FIN flag, NS flag not included
|
||||
* @return uint8_t
|
||||
*/
|
||||
inline uint8_t get_flags() {
|
||||
const char desc[] = "mbuf";
|
||||
return PacketProtTcp::get_flags(
|
||||
_tcp_hdr); // these are FIN to CWR flag, but
|
||||
// i am not shure in which order
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets payload size in byte
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_payload_size() {
|
||||
uint16_t length = get_packet_size();
|
||||
length = length - get_ip_hdr_len();
|
||||
length = length - PacketProtTcp::get_tcp_hdr_len(_tcp_hdr);
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP window size
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_window_size() {
|
||||
return PacketProtTcp::get_window_size(_tcp_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP sequence number
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
inline uint32_t get_seq_num() {
|
||||
return PacketProtTcp::get_seq_num(_tcp_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP acknowledgment number
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
inline uint32_t get_ack_num() {
|
||||
return PacketProtTcp::get_ack_num(_tcp_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP SYN flag
|
||||
*
|
||||
* @return true if flag is set
|
||||
* @return false if flag is not set
|
||||
*/
|
||||
inline bool get_syn_flag() { return PacketProtTcp::get_syn_flag(_tcp_hdr); }
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP ACK flag
|
||||
*
|
||||
* @return true if flag is set
|
||||
* @return false if flag is not set
|
||||
*/
|
||||
inline bool get_ack_flag() { return PacketProtTcp::get_ack_flag(_tcp_hdr); }
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP RST flag
|
||||
*
|
||||
* @return true if flag is set
|
||||
* @return false if flag is not set
|
||||
*/
|
||||
inline bool get_rst_flag() { return PacketProtTcp::get_rst_flag(_tcp_hdr); }
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP FIN flag
|
||||
*
|
||||
* @return true if flag is set
|
||||
* @return false if flag is not set
|
||||
*/
|
||||
inline bool get_fin_flag() { return PacketProtTcp::get_fin_flag(_tcp_hdr); }
|
||||
|
||||
/**
|
||||
* @brief fills empty mbuf with IP and TCP header
|
||||
* If this PacketInfo has a _mbuf and this _mbuf is empty,
|
||||
* then all IP and TCP header information is filled in.
|
||||
* This function doesn't create a new mbuf.
|
||||
* @param src_mac MAC address packet was send from
|
||||
* @param dst_mac MAC address packet is going to be send to
|
||||
* @param src_ip IP address packet originally originated from
|
||||
* @param dst_ip IP address packet is going to be send to
|
||||
* @param src_port TCP port packet originally was send from
|
||||
* @param dst_port TCP port packet should be recieved on
|
||||
* @param seq_num TCP sequence number
|
||||
* @param ack_num TCP acknowledgment number
|
||||
* @param flags TCP flags wich are going to be set, can't set NS flag
|
||||
* @param tcp_window TCP recive window size
|
||||
*/
|
||||
inline void fill_payloadless_tcp_packet(
|
||||
rte_ether_addr src_mac, rte_ether_addr dst_mac, uint32_t src_ip,
|
||||
uint32_t dst_ip, uint16_t src_port, uint16_t dst_port, uint32_t seq_num,
|
||||
uint32_t ack_num, uint8_t flags, uint16_t tcp_window) {
|
||||
// const char desc[] = "mbuf";
|
||||
|
||||
// let PacketInfo handle ethernet filling
|
||||
fill_eth_hdr(dst_mac, src_mac);
|
||||
|
||||
// let prot objekt handle tcp filling
|
||||
PacketProtTcp::fill_payloadless_tcp_header(_tcp_hdr, get_mbuf(),
|
||||
src_port, dst_port, seq_num,
|
||||
ack_num, flags, tcp_window);
|
||||
|
||||
// let PacketInfoIpv4 handle IPv4 filling
|
||||
fill_ip_hdr(src_ip, dst_ip, 6, 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief fills in current checksums
|
||||
* calculates current IPv4 and TCP checksum and changes
|
||||
* them inside the packet
|
||||
*/
|
||||
inline void recalculate_checksums() {
|
||||
rte_ipv4_hdr* ip4_hdr = get_ip_hdr();
|
||||
|
||||
_tcp_hdr->cksum = 0;
|
||||
ip4_hdr->hdr_checksum = 0;
|
||||
_tcp_hdr->cksum = rte_ipv4_udptcp_cksum(ip4_hdr, _tcp_hdr);
|
||||
PacketInfoIpv4::recalculate_ip_checksum();
|
||||
}
|
||||
|
||||
inline void prepare_offloading_checksums() {
|
||||
rte_mbuf* mbuf = get_mbuf();
|
||||
mbuf->ol_flags = PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM;
|
||||
mbuf->l4_len = sizeof(struct rte_tcp_hdr);
|
||||
|
||||
uint16_t cksm = PacketInfoIpv4::get_pseudo_hdr_cksm();
|
||||
PacketProtTcp::fill_tcp_cksm(_tcp_hdr, cksm);
|
||||
}
|
||||
|
||||
inline void set_tcp_cksm(uint16_t cksm) {
|
||||
PacketProtTcp::fill_tcp_cksm(_tcp_hdr, cksm);
|
||||
}
|
||||
|
||||
private:
|
||||
rte_tcp_hdr* _tcp_hdr;
|
||||
};
|
135
include/PacketDissection/PacketInfoIpv4Udp.hpp
Normal file
135
include/PacketDissection/PacketInfoIpv4Udp.hpp
Normal file
@ -0,0 +1,135 @@
|
||||
/**
|
||||
* @file PacketInfoIpv4Udp.hpp
|
||||
* @author @Tobias
|
||||
* @brief class to provide packets IPv4 and UDP header information
|
||||
* @date 2021-06-08
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_udp.h>
|
||||
|
||||
#include "PacketDissection/PacketInfoIpv4.hpp"
|
||||
#include "PacketDissection/PacketProtUdp.hpp"
|
||||
|
||||
#define UDP_HDR_LEN 8
|
||||
|
||||
class PacketInfoIpv4Udp : public PacketInfoIpv4 {
|
||||
public:
|
||||
inline PacketInfoIpv4Udp();
|
||||
|
||||
inline PacketInfoIpv4Udp(rte_mbuf* const mbuf, rte_ether_hdr* const eth_hdr,
|
||||
rte_ipv4_hdr* const ip_hdr,
|
||||
rte_udp_hdr* const l4_hdr)
|
||||
: PacketInfoIpv4(IPv4UDP, mbuf, eth_hdr, ip_hdr), _udp_hdr(l4_hdr) {}
|
||||
|
||||
inline PacketInfoIpv4Udp(rte_mbuf* const mbuf, rte_ipv4_hdr* const ip_hdr,
|
||||
rte_udp_hdr* const l4_hdr)
|
||||
: PacketInfoIpv4(IPv4UDP, mbuf, ip_hdr), _udp_hdr(l4_hdr) {}
|
||||
|
||||
// inline PacketInfoIpv4Udp::~PacketInfoIpv4Udp() {
|
||||
// PacketInfoIpv4::~PacketInfoIpv4();
|
||||
// //_udp_hdr = nullptr;
|
||||
//}
|
||||
|
||||
/**
|
||||
* @brief Get packets UDP destination port
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_dst_port() {
|
||||
return PacketProtUdp::get_dst_port(_udp_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets UDP source port
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_src_port() {
|
||||
return PacketProtUdp::get_src_port(_udp_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets payload size in byte
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t get_payload_size() {
|
||||
uint16_t len = get_packet_size();
|
||||
len = len - get_ip_hdr_len();
|
||||
return len - UDP_HDR_LEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief fills empty mbuf with IP and UDP heder
|
||||
* This PacketInfos _mbuf is going to be filled with all
|
||||
* IP and UDP header information, execpt checksums.
|
||||
* This function doesn't create a new mbuf.
|
||||
* @param src_mac MAC address packet was send from
|
||||
* @param dst_mac MAC address packet is going to be send to
|
||||
* @param src_ip IP address packet originally was send from
|
||||
* @param dst_ip IP address packet is going to be send to
|
||||
* @param src_port TCP port packet originally was send from
|
||||
* @param dst_port TCP port packet is going to be send to
|
||||
*/
|
||||
inline void fill_payloadless_udp_packet(rte_ether_addr src_mac,
|
||||
rte_ether_addr dst_mac,
|
||||
uint32_t src_ip, uint32_t dst_ip,
|
||||
uint16_t src_port,
|
||||
uint16_t dst_port) {
|
||||
|
||||
// let PacketInfo handle ethernet filling
|
||||
fill_eth_hdr(dst_mac, src_mac);
|
||||
|
||||
// let prot objekt handle tcp filling
|
||||
PacketProtUdp::fill_payloadless_udp_header(_udp_hdr, src_port,
|
||||
dst_port);
|
||||
|
||||
// let PacketInfoIpv4 handle IPv4 filling
|
||||
fill_ip_hdr(src_ip, dst_ip, 17, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief calculate current checksums and fill them in
|
||||
* Note, udp checksum doesn't have to be set in IPv4.
|
||||
* @param use_udp_cksm if true the UDP checksum is calculated
|
||||
*/
|
||||
inline void recalculate_checksums(bool use_udp_cksm) {
|
||||
|
||||
_udp_hdr->dgram_cksum = 0;
|
||||
|
||||
if (use_udp_cksm == true) {
|
||||
|
||||
rte_ipv4_hdr* ip_hdr = get_ip_hdr();
|
||||
ip_hdr->hdr_checksum = 0;
|
||||
_udp_hdr->dgram_cksum = rte_ipv4_udptcp_cksum(ip_hdr, _udp_hdr);
|
||||
}
|
||||
PacketInfoIpv4::recalculate_ip_checksum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief prepare mbuf for checksum calculation by hardware
|
||||
* Note, udp checksum doesn't have to be set in IPv4.
|
||||
* @param use_udp_cksm if true the UDP checksum will be calculated
|
||||
*/
|
||||
inline void prepare_offloading_checksums(bool use_udp_cksm) {
|
||||
|
||||
rte_mbuf* mbuf = get_mbuf();
|
||||
mbuf->ol_flags = PKT_TX_IPV4 | PKT_TX_IP_CKSUM;
|
||||
mbuf->l4_len = sizeof(struct rte_udp_hdr);
|
||||
|
||||
if (use_udp_cksm == true) {
|
||||
mbuf->ol_flags |= PKT_TX_UDP_CKSUM;
|
||||
_udp_hdr->dgram_cksum = PacketInfoIpv4::get_pseudo_hdr_cksm();
|
||||
} else {
|
||||
mbuf->l2_len = sizeof(struct rte_ether_hdr);
|
||||
mbuf->l3_len = sizeof(struct rte_ipv4_hdr);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rte_udp_hdr* const _udp_hdr;
|
||||
};
|
58
include/PacketDissection/PacketInfoIpv6Icmp.hpp
Normal file
58
include/PacketDissection/PacketInfoIpv6Icmp.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @file PacketInfoIpv6Icmp.hpp
|
||||
* @author Tobias
|
||||
* @brief class to provide packets IPv6 and ICMP header information
|
||||
* @date 2021-06-09
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_ether.h>
|
||||
#include <rte_icmp.h>
|
||||
#include <rte_ip.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
|
||||
class PacketInfoIpv6Icmp : public PacketInfo {
|
||||
public:
|
||||
inline PacketInfoIpv6Icmp() { /*set_type(IPv6ICMP);*/
|
||||
}
|
||||
inline void set_ip_hdr(rte_ipv6_hdr* ip6_hdr) { this->_ip6_hdr = ip6_hdr; }
|
||||
inline void set_icmp_hdr(rte_icmp_hdr* icmp_hdr) {
|
||||
this->_icmp_hdr = icmp_hdr;
|
||||
}
|
||||
|
||||
/// IPv6 Functions
|
||||
inline uint32_t get_dst_ip() {
|
||||
/*__uint128_t dest_ip = 0;
|
||||
for (short i = 0; i < 16; i++){
|
||||
dest_ip << 8; /// shift left to make space for next part
|
||||
dest_ip = dest_ip + _ip6_hdr->dst_addr[i]; /// add next part
|
||||
}*/
|
||||
std::cout << "PacketInfoIpv6Icmp not yet implemented! ";
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline uint32_t get_src_ip() {
|
||||
/*__uint128_t src_ip = 0;
|
||||
for (short i = 0; i < 16; i++){
|
||||
src_ip << 8; /// shift left to make space for next part
|
||||
src_ip = src_ip + _ip6_hdr->src_addr[i]; /// add next part
|
||||
}*/
|
||||
printf("PacketInfoIpv6Icmp not yet implemented! ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline uint16_t get_packet_size() { return 384; }
|
||||
inline uint16_t get_payload_size() { return 0; }
|
||||
|
||||
private:
|
||||
rte_ipv6_hdr* _ip6_hdr;
|
||||
rte_icmp_hdr* _icmp_hdr;
|
||||
};
|
106
include/PacketDissection/PacketInfoIpv6Tcp.hpp
Normal file
106
include/PacketDissection/PacketInfoIpv6Tcp.hpp
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @file PacketInfoIpv6Tcp.hpp
|
||||
* @author Tobias
|
||||
* @brief class to provide packets IPv6 and TCP header information
|
||||
* @date 2021-06-09
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_ether.h>
|
||||
#include <rte_icmp.h>
|
||||
#include <rte_ip.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_tcp.h>
|
||||
#include <rte_udp.h>
|
||||
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
|
||||
class PacketInfoIpv6Tcp : public PacketInfo {
|
||||
public:
|
||||
inline PacketInfoIpv6Tcp() { /*set_type(IPv6TCP);*/
|
||||
}
|
||||
|
||||
inline void create_reply(rte_mbuf* answ_mbuf, uint32_t seq_num,
|
||||
uint32_t ack_num);
|
||||
|
||||
inline void tear_down_connection(rte_mbuf* return_mbuf,
|
||||
rte_mbuf* forward_mbuf,
|
||||
uint32_t forward_seq_num,
|
||||
uint32_t forward_ack_num);
|
||||
|
||||
inline void set_ip_hdr(rte_ipv6_hdr* ip6_hdr) { this->_ip6_hdr = ip6_hdr; }
|
||||
|
||||
inline void set_tcp_hdr(rte_tcp_hdr* tcp_hdr) { this->_tcp_hdr = tcp_hdr; }
|
||||
|
||||
inline void set_seq_num(uint32_t seq_num) { _tcp_hdr->sent_seq = seq_num; }
|
||||
|
||||
inline void set_ack_num(uint32_t ack_num) { _tcp_hdr->recv_ack = ack_num; }
|
||||
|
||||
/// IPv6 Functions
|
||||
inline uint32_t get_dst_ip() {
|
||||
/*__uint128_t dest_ip = 0;
|
||||
for (short i = 0; i < 16; i++){
|
||||
dest_ip = dest_ip * 256; /// shift left to make space for next
|
||||
part dest_ip = dest_ip + _ip6_hdr->dst_addr[i]; /// add next part
|
||||
}*/
|
||||
std::cout << "PacketInfoIpv6Tcp not yet implemented! ";
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline uint32_t get_src_ip() {
|
||||
/*__uint128_t src_ip = 0;
|
||||
for (short i = 0; i < 16; i++){
|
||||
src_ip = src_ip * 256; /// shift left to make space for next part
|
||||
src_ip = src_ip + _ip6_hdr->src_addr[i]; /// add next part
|
||||
}*/
|
||||
printf("PacketInfoIpv6Tcp not yet implemented! ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline uint16_t get_dst_port() { return _tcp_hdr->dst_port; }
|
||||
|
||||
inline uint16_t get_src_port() { return _tcp_hdr->src_port; }
|
||||
|
||||
inline uint8_t get_flags() { return _tcp_hdr->tcp_flags; }
|
||||
|
||||
inline uint16_t get_packet_size() { return _ip6_hdr->payload_len + 320; }
|
||||
|
||||
inline uint16_t get_payload_size() { return _ip6_hdr->payload_len - 20; }
|
||||
|
||||
inline uint16_t get_window_size() { return _tcp_hdr->rx_win; }
|
||||
|
||||
inline uint32_t get_seq_num() { return _tcp_hdr->sent_seq; }
|
||||
|
||||
inline uint32_t get_ack_num() { return _tcp_hdr->recv_ack; }
|
||||
|
||||
/**
|
||||
* @brief NOT YET IMPLEMENTED FOR IPv6
|
||||
* fills empty mbuf with IP and TCP header
|
||||
* If this PacketInfo has a _mbuf and this _mbuf is empty,
|
||||
* then all IP and TCP header information is filled in.
|
||||
* This function doesn't create a new mbuf.
|
||||
* @param src_ip IP address packet originally originated from
|
||||
* @param dst_ip IP address packet is going to be send to
|
||||
* @param src_port TCP port packet originally was send from
|
||||
* @param dst_port TCP port packet should be recieved on
|
||||
* @param seq_num TCP sequence number
|
||||
* @param ack_num TCP acknowledgment number
|
||||
* @param flags TCP flags wich are going to be set, can't set NS flag
|
||||
*/
|
||||
inline void fill_payloadless_tcp_packet(uint32_t src_ip, uint32_t dst_ip,
|
||||
uint16_t src_port,
|
||||
uint16_t dst_port, uint32_t seq_num,
|
||||
uint32_t ack_num, uint8_t flags);
|
||||
|
||||
inline void re_calculate_checksums(); ///> NOT YET IMPLEMENTED FOR IPv6
|
||||
|
||||
private:
|
||||
rte_ipv6_hdr* _ip6_hdr;
|
||||
rte_tcp_hdr* _tcp_hdr;
|
||||
};
|
65
include/PacketDissection/PacketInfoIpv6Udp.hpp
Normal file
65
include/PacketDissection/PacketInfoIpv6Udp.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file PacketInfoIpv6Udp.hpp
|
||||
* @author Tobias
|
||||
* @brief class to provide packets IPv6 and UDP header information
|
||||
* @date 2021-06-09
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_ether.h>
|
||||
#include <rte_icmp.h>
|
||||
#include <rte_ip.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_tcp.h>
|
||||
#include <rte_udp.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
|
||||
class PacketInfoIpv6Udp : public PacketInfo {
|
||||
public:
|
||||
inline PacketInfoIpv6Udp() { /*set_type(IPv6UDP);*/
|
||||
}
|
||||
|
||||
inline void set_ip_hdr(rte_ipv6_hdr* ip6_hdr) { this->_ip6_hdr = ip6_hdr; }
|
||||
|
||||
inline void set_udp_hdr(rte_udp_hdr* udp_hdr) { this->_udp_hdr = udp_hdr; }
|
||||
|
||||
/// IPv6 Functions
|
||||
inline uint32_t get_dst_ip() {
|
||||
/*__uint128_t dest_ip = 0;
|
||||
for (short i = 0; i < 16; i++){
|
||||
dest_ip << 8; /// shift left to make space for next part
|
||||
dest_ip = dest_ip + _ip6_hdr->dst_addr[i]; /// add next part
|
||||
}*/
|
||||
printf("PacketInfoIpv6Udp not yet implemented! ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline uint32_t get_src_ip() {
|
||||
/*__uint128_t src_ip = 0;
|
||||
for (short i = 0; i < 16; i++){
|
||||
src_ip << 8; /// shift left to make space for next part
|
||||
src_ip = src_ip + _ip6_hdr->src_addr[i]; /// add next part
|
||||
}*/
|
||||
printf("PacketInfoIpv6Udp not yet implemented! ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline uint16_t get_dst_port() { return _udp_hdr->dst_port; }
|
||||
|
||||
inline uint16_t get_src_port() { return _udp_hdr->src_port; }
|
||||
|
||||
inline uint16_t get_packet_size() { return _ip6_hdr->payload_len + 320; }
|
||||
|
||||
inline uint16_t get_payload_size() { return _ip6_hdr->payload_len - 8; }
|
||||
|
||||
private:
|
||||
rte_ipv6_hdr* _ip6_hdr;
|
||||
rte_udp_hdr* _udp_hdr;
|
||||
};
|
198
include/PacketDissection/PacketProtTcp.hpp
Normal file
198
include/PacketDissection/PacketProtTcp.hpp
Normal file
@ -0,0 +1,198 @@
|
||||
/**
|
||||
* @file PacketProtTcp.hpp
|
||||
* @author Tobias
|
||||
* @brief class to extract and change some informations in TCP header
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_tcp.h>
|
||||
|
||||
#define FIN_FLAG_POS 0b00000001
|
||||
#define SYN_FLAG_POS 0b00000010
|
||||
#define RST_FLAG_POS 0b00000100
|
||||
#define ACK_FLAG_POS 0b00010000
|
||||
#define FIRST_4_BIT 0b11110000
|
||||
#define TCP_HDR_SIZE_4BYTE_WORD 0b01010000
|
||||
|
||||
class PacketProtTcp {
|
||||
public:
|
||||
// PacketProtTcp(rte_tcp_hdr* tcp_hdr);
|
||||
|
||||
/**
|
||||
* @brief Set packets TCP sequence number
|
||||
*
|
||||
* @param seq_num
|
||||
*/
|
||||
inline static void set_seq_num(rte_tcp_hdr* tcp_hdr, uint32_t seq_num) {
|
||||
tcp_hdr->sent_seq = rte_cpu_to_be_32(seq_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set packets TCP acknowledgment number
|
||||
*
|
||||
* @param ack_num
|
||||
*/
|
||||
inline static void set_ack_num(rte_tcp_hdr* tcp_hdr, uint32_t ack_num) {
|
||||
tcp_hdr->recv_ack = rte_cpu_to_be_32(ack_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP destination port
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline static uint16_t get_dst_port(rte_tcp_hdr* tcp_hdr) {
|
||||
return rte_be_to_cpu_16(tcp_hdr->dst_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP source port
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline static uint16_t get_src_port(rte_tcp_hdr* tcp_hdr) {
|
||||
return rte_be_to_cpu_16(tcp_hdr->src_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP flags
|
||||
* MSB is CWR flag, LSB is FIN flag, NS flag not included
|
||||
* @return uint8_t
|
||||
*/
|
||||
inline static uint8_t get_flags(rte_tcp_hdr* tcp_hdr) {
|
||||
return tcp_hdr->tcp_flags; // these are FIN to CWR flag, but i am not
|
||||
// shure in which order
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP window size
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline static uint16_t get_window_size(rte_tcp_hdr* tcp_hdr) {
|
||||
return rte_be_to_cpu_16(tcp_hdr->rx_win);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP sequence number
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
inline static uint32_t get_seq_num(rte_tcp_hdr* tcp_hdr) {
|
||||
return rte_be_to_cpu_32(tcp_hdr->sent_seq);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP acknowledgment number
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
inline static uint32_t get_ack_num(rte_tcp_hdr* tcp_hdr) {
|
||||
return rte_be_to_cpu_32(tcp_hdr->recv_ack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP-header length
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline static uint16_t get_tcp_hdr_len(rte_tcp_hdr* tcp_hdr) {
|
||||
return (tcp_hdr->data_off & FIRST_4_BIT) * 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP SYN flag
|
||||
*
|
||||
* @return true if flag is set
|
||||
* @return false if flag is not set
|
||||
*/
|
||||
inline static bool get_syn_flag(rte_tcp_hdr* tcp_hdr) {
|
||||
if ((tcp_hdr->tcp_flags & SYN_FLAG_POS) == SYN_FLAG_POS) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP ACK flag
|
||||
*
|
||||
* @return true if flag is set
|
||||
* @return false if flag is not set
|
||||
*/
|
||||
inline static bool get_ack_flag(rte_tcp_hdr* tcp_hdr) {
|
||||
if ((tcp_hdr->tcp_flags & ACK_FLAG_POS) == ACK_FLAG_POS) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP RST flag
|
||||
*
|
||||
* @return true if flag is set
|
||||
* @return false if flag is not set
|
||||
*/
|
||||
inline static bool get_rst_flag(rte_tcp_hdr* tcp_hdr) {
|
||||
if ((tcp_hdr->tcp_flags & RST_FLAG_POS) == RST_FLAG_POS) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets TCP FIN flag
|
||||
*
|
||||
* @return true if flag is set
|
||||
* @return false if flag is not set
|
||||
*/
|
||||
inline static bool get_fin_flag(rte_tcp_hdr* tcp_hdr) {
|
||||
if ((tcp_hdr->tcp_flags & FIN_FLAG_POS) == FIN_FLAG_POS) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief fills empty mbuf with IP and TCP header
|
||||
* If this PacketInfo has a _mbuf and this _mbuf is empty,
|
||||
* then all IP and TCP header information is filled in.
|
||||
* This function doesn't create a new mbuf.
|
||||
* @param src_ip IP address packet originally originated from
|
||||
* @param dst_ip IP address packet is going to be send to
|
||||
* @param src_port TCP port packet originally was send from
|
||||
* @param dst_port TCP port packet should be reci#include <rte_ip.h>eved on
|
||||
* @param seq_num TCP sequence number
|
||||
* @param ack_num TCP acknowledgment number
|
||||
* @param flags TCP flags wich are going to be set, can't set NS flag
|
||||
* @param rx_win TCP recive side window
|
||||
*/
|
||||
|
||||
inline static void
|
||||
fill_payloadless_tcp_header(rte_tcp_hdr* tcp_hdr, rte_mbuf* mbuf,
|
||||
uint16_t src_port, uint16_t dst_port,
|
||||
uint32_t seq_num, uint32_t ack_num,
|
||||
uint8_t flags, uint16_t rx_win) {
|
||||
|
||||
tcp_hdr->src_port = rte_cpu_to_be_16(src_port);
|
||||
tcp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
|
||||
tcp_hdr->sent_seq = rte_cpu_to_be_32(seq_num);
|
||||
tcp_hdr->recv_ack = rte_cpu_to_be_32(ack_num);
|
||||
tcp_hdr->data_off = TCP_HDR_SIZE_4BYTE_WORD;
|
||||
tcp_hdr->tcp_flags = flags;
|
||||
tcp_hdr->rx_win = rte_cpu_to_be_16(rx_win);
|
||||
tcp_hdr->tcp_urp = 0;
|
||||
tcp_hdr->cksum = 0;
|
||||
}
|
||||
|
||||
inline static void fill_tcp_cksm(rte_tcp_hdr* tcp_hdr, uint16_t cksm) {
|
||||
tcp_hdr->cksum = rte_cpu_to_be_16(cksm);
|
||||
}
|
||||
};
|
45
include/PacketDissection/PacketProtUdp.hpp
Normal file
45
include/PacketDissection/PacketProtUdp.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @file PacketProtUdp.hpp
|
||||
* @author Tobias
|
||||
* @brief provide UDP specific functions
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_ip.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_udp.h>
|
||||
|
||||
class PacketProtUdp {
|
||||
public:
|
||||
/**
|
||||
* @brief Get packets UDP destination port
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline static uint16_t get_dst_port(rte_udp_hdr* const udp_hdr) {
|
||||
return rte_be_to_cpu_16(udp_hdr->dst_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get packets UDP source port
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline static uint16_t get_src_port(rte_udp_hdr* const udp_hdr) {
|
||||
return rte_be_to_cpu_16(udp_hdr->src_port);
|
||||
}
|
||||
|
||||
|
||||
inline static void fill_payloadless_udp_header(rte_udp_hdr* const udp_hdr,
|
||||
uint16_t dst_port, uint16_t src_port) {
|
||||
|
||||
udp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
|
||||
udp_hdr->src_port = rte_cpu_to_be_16(src_port);
|
||||
udp_hdr->dgram_len = rte_cpu_to_be_16(8);
|
||||
udp_hdr->dgram_cksum = 0;
|
||||
}
|
||||
};
|
73
include/RandomNumberGenerator.hpp
Normal file
73
include/RandomNumberGenerator.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Generate random unassigned 16, 32 and 64 bit integer using
|
||||
* XorShift algorithm and rand() for generating a seed.
|
||||
*/
|
||||
class RandomNumberGenerator {
|
||||
public:
|
||||
uint16_t _seed_x16;
|
||||
uint32_t _seed_x32;
|
||||
uint64_t _seed_x64;
|
||||
|
||||
/**
|
||||
* @brief Construct a new Random Number Generator object
|
||||
*/
|
||||
inline RandomNumberGenerator()
|
||||
: _seed_x16(rand()), _seed_x32(rand()), _seed_x64(rand()) {}
|
||||
|
||||
/**
|
||||
* @brief generates a 16 bit unsigned integer between lower limit and
|
||||
* upper limit (1024 and 49151 for valid port numbers)
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t gen_rdm_16_bit_in_interval(uint16_t _lower_limit,
|
||||
uint16_t _upper_limit) {
|
||||
_seed_x16 ^= _seed_x16 << 7;
|
||||
_seed_x16 ^= _seed_x16 >> 9;
|
||||
_seed_x16 ^= _seed_x16 << 8;
|
||||
// this method returns a valid port number
|
||||
// range should be: 1024 to 49152
|
||||
return _seed_x16 % (_upper_limit - _lower_limit) + _lower_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief generates 16 bit unsigned integer
|
||||
*
|
||||
* @return uint16_t
|
||||
*/
|
||||
inline uint16_t gen_rdm_16_bit() {
|
||||
_seed_x16 ^= _seed_x16 << 7;
|
||||
_seed_x16 ^= _seed_x16 >> 9;
|
||||
_seed_x16 ^= _seed_x16 << 8;
|
||||
return _seed_x16;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief generates 32 bit unsigned integer
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
inline uint32_t gen_rdm_32_bit() {
|
||||
_seed_x32 ^= _seed_x32 << 14;
|
||||
_seed_x32 ^= _seed_x32 >> 13;
|
||||
_seed_x32 ^= _seed_x32 << 15;
|
||||
return _seed_x32;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief generates 64 bit unsigned integer
|
||||
*
|
||||
* @return uint64_t
|
||||
*/
|
||||
inline uint64_t gen_rdm_64_bit() {
|
||||
_seed_x64 ^= _seed_x64 << 14;
|
||||
_seed_x64 ^= _seed_x64 >> 23;
|
||||
_seed_x64 ^= _seed_x64 << 33;
|
||||
return _seed_x64;
|
||||
}
|
||||
};
|
449
include/Threads/AttackThread.hpp
Normal file
449
include/Threads/AttackThread.hpp
Normal file
@ -0,0 +1,449 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_ether.h>
|
||||
|
||||
#include "PacketDissection/PacketContainerLean.hpp"
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Tcp.hpp"
|
||||
#include "RandomNumberGenerator.hpp"
|
||||
#include "Threads/ForwardingThread.hpp"
|
||||
|
||||
class AttackThread : public Thread {
|
||||
private:
|
||||
inline void run() {
|
||||
std::cout << "\nRunning on lcore " << rte_lcore_id()
|
||||
<< ". [Ctrl+C to quit]\n"
|
||||
<< std::endl;
|
||||
|
||||
while (likely(_quit == false)) {
|
||||
// have skip iterate field in config and skip for nb of packets
|
||||
iterate();
|
||||
#ifdef SINGLE_ITERATION
|
||||
_quit = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
_running = false;
|
||||
}
|
||||
|
||||
PacketContainerLean* _pkt_container_to_dave;
|
||||
PacketContainerLean* _pkt_container_to_alice;
|
||||
RandomNumberGenerator _rng;
|
||||
unsigned int _nb_worker_threads;
|
||||
|
||||
rte_ether_addr _bob_mac;
|
||||
rte_ether_addr _src_mac;
|
||||
|
||||
uint32_t _bob_ip;
|
||||
uint32_t _alice_ip;
|
||||
|
||||
uint8_t _tcp_flags;
|
||||
|
||||
enum AttackType { SYN_FLOOD, SYN_FIN_ACK, SYN_FIN, UDP_FLOOD, NO_ATTACK };
|
||||
AttackType _attack_type;
|
||||
|
||||
rte_mbuf* _mbuf_origin;
|
||||
|
||||
uint64_t _cycles_old;
|
||||
uint64_t _data_rate;
|
||||
uint64_t _nb_attack_packets;
|
||||
uint64_t _data_rate_per_cycle;
|
||||
uint64_t _delta_cycles_mean;
|
||||
|
||||
uint64_t _total_nb_pkts_to_dave;
|
||||
uint64_t _total_nb_pkts_from_dave;
|
||||
uint64_t _total_nb_pkts_to_alice;
|
||||
uint64_t _total_data_volume_to_alice;
|
||||
uint64_t _total_nb_pkts_from_alice;
|
||||
uint64_t _total_data_volume_from_alice;
|
||||
|
||||
int _iterations;
|
||||
uint _call_send_pkts_every_nth_iteration;
|
||||
|
||||
// ============ not needed
|
||||
|
||||
uint16_t _nb_pkts_to_dave;
|
||||
uint16_t _nb_pkts_to_alice;
|
||||
|
||||
PacketType _pkt_type;
|
||||
|
||||
uint64_t _cycles;
|
||||
uint64_t _delta_cycles;
|
||||
uint64_t _data_volume;
|
||||
|
||||
uint64_t _hz;
|
||||
int _n;
|
||||
|
||||
/**
|
||||
* This method is used in a loop so every parameter is created before
|
||||
* the loop. These you pass to the function which initializes the
|
||||
* variables.
|
||||
*
|
||||
* @param[in] pkt_size
|
||||
* @param[in] cycles
|
||||
* @param[in] delta_cycles
|
||||
* @param[in] cycles_old
|
||||
* @param[in] data_volume
|
||||
* @param[in] data_rate_per_cycle
|
||||
* @param[out] nb_attack_packets
|
||||
*/
|
||||
inline void calculate_nb_attack_packets(int pkt_size) {
|
||||
|
||||
_cycles = rte_get_tsc_cycles();
|
||||
_delta_cycles = _cycles - _cycles_old;
|
||||
|
||||
// data volume to send in bit
|
||||
_data_volume = _delta_cycles * _data_rate_per_cycle;
|
||||
|
||||
_nb_attack_packets = int(_data_volume / (pkt_size * 8));
|
||||
|
||||
if (unlikely(_nb_attack_packets == 0)) {
|
||||
_nb_attack_packets = 2;
|
||||
}
|
||||
|
||||
if (unlikely(_nb_attack_packets >= NUM_MBUF_ARRS * BURST_SIZE - 1)) {
|
||||
_nb_attack_packets = NUM_MBUF_ARRS * BURST_SIZE - 1;
|
||||
LOG_INFO << "maximum reached" << LOG_END;
|
||||
}
|
||||
|
||||
LOG_INFO << "Number of cycles: " << _delta_cycles << LOG_END;
|
||||
|
||||
LOG_INFO << "Duration of a period: " << (_delta_cycles / _hz)
|
||||
<< LOG_END;
|
||||
|
||||
// set _cycles_old
|
||||
_cycles_old = _cycles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param byte1
|
||||
* @param byte2
|
||||
* @param byte3
|
||||
* @param byte4
|
||||
* @return uint32_t
|
||||
*/
|
||||
inline uint32_t calculate_ipv4_address(uint8_t byte1, uint8_t byte2,
|
||||
uint8_t byte3, uint8_t byte4) {
|
||||
return byte1 * 2 ^ 24 + byte2 * 2 ^ 16 + byte3 * 2 ^ 8 + byte4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a bulk of attack packets, add them to the packets
|
||||
* already in the PacketContainer.
|
||||
*/
|
||||
inline void create_attack_packet_burst_tcp(uint32_t nb_pkts,
|
||||
uint8_t tcp_flags) {
|
||||
|
||||
rte_mempool* mempool = _pkt_container_to_dave->get_mempool_lean();
|
||||
|
||||
rte_mbuf* m_copy;
|
||||
|
||||
for (int i = 0; i < nb_pkts; ++i) {
|
||||
m_copy = rte_pktmbuf_copy(_mbuf_origin, mempool, 0, UINT32_MAX);
|
||||
|
||||
if (unlikely(m_copy == nullptr)) {
|
||||
throw std::runtime_error("m_copy is null");
|
||||
}
|
||||
|
||||
PacketInfoIpv4Tcp* pkt_info = static_cast<PacketInfoIpv4Tcp*>(
|
||||
PacketInfoCreator::create_mini_pkt_info(m_copy, IPv4TCP));
|
||||
|
||||
pkt_info->set_src_ip(_rng.gen_rdm_32_bit());
|
||||
|
||||
// select one of the following two, which one suits you better
|
||||
// pkt_info->recalculate_checksums();
|
||||
pkt_info->prepare_offloading_checksums();
|
||||
|
||||
_pkt_container_to_dave->add_mbuf(m_copy);
|
||||
|
||||
delete pkt_info;
|
||||
pkt_info = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a bulk of attack packets, add them to the packets
|
||||
* already in the PacketContainer.
|
||||
*/
|
||||
inline void create_attack_packet_burst_udp(uint32_t nb_pkts) {
|
||||
|
||||
rte_mempool* mempool = _pkt_container_to_dave->get_mempool_lean();
|
||||
|
||||
rte_mbuf* m_copy;
|
||||
|
||||
for (int i = 0; i < nb_pkts; ++i) {
|
||||
m_copy = rte_pktmbuf_copy(_mbuf_origin, mempool, 0, UINT32_MAX);
|
||||
|
||||
if (unlikely(m_copy == nullptr)) {
|
||||
throw std::runtime_error("m_copy is null");
|
||||
}
|
||||
|
||||
PacketInfoIpv4Udp* pkt_info = static_cast<PacketInfoIpv4Udp*>(
|
||||
PacketInfoCreator::create_mini_pkt_info(m_copy, IPv4UDP));
|
||||
|
||||
pkt_info->set_src_ip(_rng.gen_rdm_32_bit());
|
||||
|
||||
// select one of the following two, which one suits you better
|
||||
// pkt_info->recalculate_checksums();
|
||||
pkt_info->prepare_offloading_checksums(false);
|
||||
|
||||
_pkt_container_to_dave->add_mbuf(m_copy);
|
||||
|
||||
delete pkt_info;
|
||||
pkt_info = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline void calculate_cycles() {
|
||||
_cycles = rte_get_tsc_cycles();
|
||||
_delta_cycles = _cycles - _cycles_old;
|
||||
|
||||
if (_n == 1) {
|
||||
_delta_cycles_mean = _delta_cycles;
|
||||
}
|
||||
|
||||
_delta_cycles_mean =
|
||||
(_delta_cycles_mean + _delta_cycles / _n) * _n / (_n + 1);
|
||||
++_n;
|
||||
|
||||
LOG_INFO << "delta_cycles_mean: " << _delta_cycles_mean << LOG_END;
|
||||
|
||||
// LOG_INFO << "Duration of a period: " << (_delta_cycles / _hz) <<
|
||||
// LOG_END;
|
||||
|
||||
_cycles_old = _cycles;
|
||||
}
|
||||
|
||||
public:
|
||||
bool _do_attack;
|
||||
|
||||
inline AttackThread(PacketContainerLean* pkt_container_to_dave,
|
||||
PacketContainerLean* pkt_container_to_alice,
|
||||
unsigned int nb_worker_threads)
|
||||
|
||||
: Thread(), _nb_worker_threads(nb_worker_threads), _iterations(0),
|
||||
_call_send_pkts_every_nth_iteration(0),
|
||||
_pkt_container_to_dave(pkt_container_to_dave),
|
||||
_pkt_container_to_alice(pkt_container_to_alice), _nb_pkts_to_dave(0),
|
||||
_nb_pkts_to_alice(0), _total_nb_pkts_to_dave(0),
|
||||
_total_nb_pkts_from_dave(0), _total_nb_pkts_to_alice(0),
|
||||
_total_data_volume_to_alice(0), _total_nb_pkts_from_alice(0),
|
||||
_total_data_volume_from_alice(0), _pkt_type(NONE), _cycles(0),
|
||||
_delta_cycles(0), _data_volume(0), _nb_attack_packets(0),
|
||||
_hz(rte_get_tsc_hz()), _delta_cycles_mean(0), _n(1),
|
||||
_bob_mac({.addr_bytes = {60, 253, 254, 163, 231, 48}}),
|
||||
_src_mac({.addr_bytes = {60, 253, 254, 163, 231, 88}}),
|
||||
_bob_ip(167772162), _alice_ip(167772161), _tcp_flags(0),
|
||||
_mbuf_origin(nullptr), _do_attack(false) {
|
||||
|
||||
// ===== calculate stuff regarding clock calculation ===== //
|
||||
|
||||
/*
|
||||
_data_rate =
|
||||
int((std::stoi(Configurator::instance()->get_config_as_string(
|
||||
"attack_rate")) *
|
||||
1000000) /
|
||||
_nb_worker_threads);
|
||||
|
||||
_data_rate_per_cycle = int(_data_rate / _hz);
|
||||
|
||||
// if data_rate < hz
|
||||
if (_data_rate_per_cycle == 0) {
|
||||
_data_rate_per_cycle = _data_rate;
|
||||
}
|
||||
|
||||
_cycles_old = rte_get_tsc_cycles();
|
||||
*/
|
||||
|
||||
// ===== read and set attack type ===== //
|
||||
|
||||
std::string attack_type =
|
||||
Configurator::instance()->get_config_as_string("attack_type");
|
||||
|
||||
if (attack_type == "none") {
|
||||
_attack_type = NO_ATTACK;
|
||||
} else if (attack_type == "syn_flood") {
|
||||
_attack_type = SYN_FLOOD;
|
||||
_tcp_flags = 0b00000010;
|
||||
} else if (attack_type == "syn_fin") {
|
||||
_attack_type = SYN_FIN;
|
||||
_tcp_flags = 0b00000011;
|
||||
} else if (attack_type == "syn_fin_ack") {
|
||||
_attack_type = SYN_FIN_ACK;
|
||||
_tcp_flags = 0b00010011;
|
||||
} else if (attack_type == "udp_flood") {
|
||||
_attack_type = UDP_FLOOD;
|
||||
} else {
|
||||
throw std::runtime_error(
|
||||
"String attack_type in config_attacker.json "
|
||||
"does not match any type");
|
||||
}
|
||||
|
||||
LOG_INFO << "Attack type " << attack_type << " is set." << LOG_END;
|
||||
|
||||
// ===== set number of attack packets ===== //
|
||||
|
||||
_nb_attack_packets =
|
||||
Configurator::instance()->get_config_as_unsigned_int(
|
||||
"number_of_attack_packets_per_thread_per_send_call");
|
||||
|
||||
_call_send_pkts_every_nth_iteration =
|
||||
Configurator::instance()->get_config_as_unsigned_int(
|
||||
"call_send_pkts_every_nth_iteration");
|
||||
|
||||
LOG_INFO << "number_of_attack_packets_per_thread_per_send_call : "
|
||||
<< _nb_attack_packets << LOG_END;
|
||||
|
||||
// ===== create origin attack packet ===== //
|
||||
|
||||
_mbuf_origin =
|
||||
rte_pktmbuf_alloc(_pkt_container_to_dave->get_mempool_lean());
|
||||
|
||||
if (_attack_type == SYN_FLOOD || _attack_type == SYN_FIN ||
|
||||
_attack_type == SYN_FIN_ACK) {
|
||||
|
||||
PacketInfo* pkt_info_plain =
|
||||
PacketInfoCreator::create_pkt_info(_mbuf_origin, IPv4TCP);
|
||||
|
||||
PacketInfoIpv4Tcp* pkt_info_origin =
|
||||
static_cast<PacketInfoIpv4Tcp*>(pkt_info_plain);
|
||||
|
||||
pkt_info_origin->fill_payloadless_tcp_packet(
|
||||
_src_mac, _bob_mac, _rng.gen_rdm_32_bit(), _bob_ip,
|
||||
_rng.gen_rdm_16_bit(), 80, 1, 1, _tcp_flags, 64);
|
||||
|
||||
pkt_info_origin->prepare_offloading_checksums();
|
||||
|
||||
delete pkt_info_origin;
|
||||
pkt_info_origin = nullptr;
|
||||
|
||||
} else if (_attack_type == UDP_FLOOD) {
|
||||
|
||||
PacketInfo* pkt_info_plain =
|
||||
PacketInfoCreator::create_pkt_info(_mbuf_origin, IPv4UDP);
|
||||
|
||||
PacketInfoIpv4Udp* pkt_info_origin =
|
||||
static_cast<PacketInfoIpv4Udp*>(pkt_info_plain);
|
||||
|
||||
pkt_info_origin->fill_payloadless_udp_packet(
|
||||
_src_mac, _bob_mac, _rng.gen_rdm_32_bit(), _bob_ip,
|
||||
_rng.gen_rdm_16_bit(), 80);
|
||||
|
||||
pkt_info_origin->prepare_offloading_checksums(false);
|
||||
|
||||
delete pkt_info_origin;
|
||||
pkt_info_origin = nullptr;
|
||||
}
|
||||
|
||||
// ===== attack rate
|
||||
}
|
||||
|
||||
inline ~AttackThread() { rte_pktmbuf_free(_mbuf_origin); }
|
||||
|
||||
inline static int s_run(void* thread_vptr) {
|
||||
AttackThread* thread = static_cast<AttackThread*>(thread_vptr);
|
||||
thread->run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void iterate() {
|
||||
|
||||
// ===== ALICE <--[MALLORY]-- DAVE/BOB ===== //
|
||||
|
||||
_pkt_container_to_alice->poll_mbufs(_nb_pkts_to_alice);
|
||||
_total_nb_pkts_from_dave += _nb_pkts_to_alice;
|
||||
|
||||
// continue if no packets are received
|
||||
if (likely(_nb_pkts_to_alice > 0)) {
|
||||
// drop all packets that do not go to the mallory interface
|
||||
for (int i = 0; i < _nb_pkts_to_alice; i++) {
|
||||
|
||||
rte_mbuf* mbuf = _pkt_container_to_alice->get_mbuf_at_index(i);
|
||||
|
||||
uint32_t ip4_addr =
|
||||
PacketInfoCreator::get_dst_ip_from_mbuf(mbuf);
|
||||
|
||||
if (likely(ip4_addr != 0 && ip4_addr != _alice_ip)) {
|
||||
_pkt_container_to_alice->drop_polled_mbuf(i);
|
||||
} else {
|
||||
_total_data_volume_to_alice += rte_pktmbuf_pkt_len(mbuf);
|
||||
}
|
||||
}
|
||||
_total_nb_pkts_to_alice += _pkt_container_to_alice->send_mbufs();
|
||||
}
|
||||
|
||||
// ===== ALICE --[MALLORY]--> DAVE/BOB ===== //
|
||||
|
||||
_pkt_container_to_dave->poll_mbufs(_nb_pkts_to_dave);
|
||||
_total_nb_pkts_from_alice += _nb_pkts_to_dave;
|
||||
for (int i = 0; i < _nb_pkts_to_dave; ++i) {
|
||||
_total_data_volume_from_alice += rte_pktmbuf_pkt_len(
|
||||
_pkt_container_to_dave->get_mbuf_at_index(i));
|
||||
}
|
||||
|
||||
if (unlikely(_iterations == _call_send_pkts_every_nth_iteration)) {
|
||||
_iterations = 0;
|
||||
|
||||
// create attack packets
|
||||
if (likely(_do_attack)) {
|
||||
if (_attack_type == SYN_FLOOD || _attack_type == SYN_FIN ||
|
||||
_attack_type == SYN_FIN_ACK) {
|
||||
create_attack_packet_burst_tcp(_nb_attack_packets,
|
||||
_tcp_flags);
|
||||
} else if (_attack_type == UDP_FLOOD) {
|
||||
create_attack_packet_burst_udp(_nb_attack_packets);
|
||||
}
|
||||
} else{
|
||||
_total_nb_pkts_to_dave = 0;
|
||||
_total_nb_pkts_from_dave = 0;
|
||||
_total_nb_pkts_to_alice = 0;
|
||||
_total_data_volume_to_alice = 0;
|
||||
_total_nb_pkts_from_alice = 0;
|
||||
_total_data_volume_from_alice = 0;
|
||||
}
|
||||
}
|
||||
|
||||
++_iterations;
|
||||
|
||||
_total_nb_pkts_to_dave = _total_nb_pkts_to_dave +
|
||||
_pkt_container_to_dave->send_mbufs();
|
||||
|
||||
// calculate_cycles();
|
||||
}
|
||||
|
||||
inline uint64_t get_total_nb_pkts_to_dave() {
|
||||
return _total_nb_pkts_to_dave;
|
||||
}
|
||||
|
||||
inline uint64_t get_total_nb_pkts_from_dave() {
|
||||
return _total_nb_pkts_from_dave;
|
||||
}
|
||||
|
||||
inline uint64_t get_total_nb_pkts_to_alice() {
|
||||
return _total_nb_pkts_to_alice;
|
||||
}
|
||||
|
||||
inline uint64_t get_total_data_volume_to_alice() {
|
||||
return _total_data_volume_to_alice;
|
||||
}
|
||||
|
||||
inline uint64_t get_total_nb_pkts_from_alice() {
|
||||
return _total_nb_pkts_from_alice;
|
||||
}
|
||||
|
||||
inline uint64_t get_total_data_volume_from_alice() {
|
||||
return _total_data_volume_from_alice;
|
||||
}
|
||||
|
||||
inline int get_atk_pkt_type() {
|
||||
if ((_attack_type == SYN_FLOOD) || (_attack_type == SYN_FIN) ||
|
||||
(_attack_type == SYN_FIN_ACK)) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
51
include/Threads/DefenseThread.hpp
Normal file
51
include/Threads/DefenseThread.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "PacketDissection/PacketContainer.hpp"
|
||||
#include "Treatment/Treatment.hpp"
|
||||
|
||||
#include "Threads/ForwardingThread.hpp"
|
||||
|
||||
class DefenseThread : public Thread {
|
||||
public:
|
||||
DefenseThread(MbufContainerReceiving* mbuf_container_from_inside,
|
||||
MbufContainerReceiving* mbuf_container_from_outside,
|
||||
MbufContainerTransmitting* mbuf_container_to_inside,
|
||||
MbufContainerTransmitting* mbuf_container_to_outside);
|
||||
|
||||
~DefenseThread() { delete _treatment; }
|
||||
|
||||
void start_treat() { _do_treat = true; }
|
||||
|
||||
void stop_treat() { _do_treat = false; }
|
||||
|
||||
bool _do_treat;
|
||||
|
||||
/**
|
||||
* @brief Wrapper for the run-method
|
||||
*
|
||||
* Static method that calls the run method on a specific thread
|
||||
* object. This is necessary since s_run is used to start a new thread with
|
||||
* the dpdk function "rte_eal_remote_launch" which only takes specific types
|
||||
* of funktions.
|
||||
*
|
||||
* @param thread_obj object of type thread the run method is to be called on
|
||||
* @return int
|
||||
*/
|
||||
static int s_run(void* thread_obj);
|
||||
|
||||
private:
|
||||
Treatment* _treatment;
|
||||
|
||||
MbufContainerReceiving* _mbuf_container_from_outside;
|
||||
MbufContainerReceiving* _mbuf_container_from_inside;
|
||||
MbufContainerTransmitting* _mbuf_container_to_outside;
|
||||
MbufContainerTransmitting* _mbuf_container_to_inside;
|
||||
|
||||
/**
|
||||
* @brief Run thread
|
||||
*
|
||||
* "Main"-routine of a thread. It is executed until the application is quit
|
||||
* or killed.
|
||||
*/
|
||||
void run();
|
||||
};
|
41
include/Threads/ForwardingThread.hpp
Normal file
41
include/Threads/ForwardingThread.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "PacketDissection/PacketContainer.hpp"
|
||||
#include "PacketDissection/PacketContainerLean.hpp"
|
||||
|
||||
#include "Threads/Thread.hpp"
|
||||
|
||||
class ForwardingThread : public Thread {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Thread object
|
||||
*
|
||||
* @param pkt_container_to_inside PacketContainer of packets that come from
|
||||
* the outside port and are to be forwarded to the inside port
|
||||
* @param pkt_container_to_outside PacketContainer of packets that come from
|
||||
* the inside port and are to be forwarded to the outside port
|
||||
*/
|
||||
ForwardingThread(PacketContainer* pkt_container_to_inside,
|
||||
PacketContainer* pkt_container_to_outside)
|
||||
: Thread(), _pkt_container_to_inside(pkt_container_to_inside),
|
||||
_pkt_container_to_outside(pkt_container_to_outside) {}
|
||||
|
||||
ForwardingThread(PacketContainerLean* pkt_container_to_inside,
|
||||
PacketContainerLean* pkt_container_to_outside)
|
||||
: Thread(), _pkt_container_to_inside_lean(pkt_container_to_inside),
|
||||
_pkt_container_to_outside_lean(pkt_container_to_outside) {}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief in AttackThread: to dave
|
||||
*/
|
||||
PacketContainer* _pkt_container_to_inside;
|
||||
PacketContainerLean* _pkt_container_to_inside_lean;
|
||||
// PacketContainerLean* _pkt_container_from_outside_lean;
|
||||
|
||||
/**
|
||||
* @brief in AttackThread: to alice
|
||||
*/
|
||||
PacketContainer* _pkt_container_to_outside;
|
||||
PacketContainerLean* _pkt_container_to_outside_lean;
|
||||
};
|
43
include/Threads/StatisticsThread.hpp
Normal file
43
include/Threads/StatisticsThread.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_ring_core.h>
|
||||
#include <rte_ring_elem.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Threads/Thread.hpp"
|
||||
|
||||
struct Stats {
|
||||
uint64_t attacks;
|
||||
uint64_t bytes;
|
||||
uint64_t dropped;
|
||||
uint64_t packets;
|
||||
uint64_t work_time;
|
||||
uint64_t syn_level;
|
||||
|
||||
Stats* operator+=(const Stats* new_stats);
|
||||
};
|
||||
|
||||
struct StatsMonitor {
|
||||
double attacks_per_second;
|
||||
double attacks_percent;
|
||||
double bytes_per_second;
|
||||
double dropped_per_second;
|
||||
double dropped_percent;
|
||||
double packets_per_second;
|
||||
double proc_speed; // process speed
|
||||
double total_time;
|
||||
};
|
||||
|
||||
class StatisticsThread : public Thread {
|
||||
public:
|
||||
static int s_run(void* thread_vptr);
|
||||
|
||||
void enqueue_statistics(int& id, Stats* new_stats);
|
||||
void update_statistics(Stats* new_stats);
|
||||
|
||||
private:
|
||||
void run();
|
||||
static rte_ring* _s_queue[16];
|
||||
static Stats* _s_stats;
|
||||
};
|
23
include/Threads/Thread.hpp
Normal file
23
include/Threads/Thread.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class Thread {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Thread object
|
||||
*/
|
||||
inline Thread() : _quit(false), _running(true) {}
|
||||
|
||||
/**
|
||||
* @brief quit the thread
|
||||
*/
|
||||
inline void quit() { _quit = true; }
|
||||
|
||||
inline bool is_running() { return _running; }
|
||||
|
||||
protected:
|
||||
bool _quit;
|
||||
bool _running;
|
||||
uint64_t _cycles_old;
|
||||
};
|
904
include/Treatment/Treatment.hpp
Normal file
904
include/Treatment/Treatment.hpp
Normal file
@ -0,0 +1,904 @@
|
||||
#pragma once
|
||||
|
||||
#include "PacketDissection/MbufContainer.hpp"
|
||||
#include "PacketDissection/MbufContainerReceiving.hpp"
|
||||
#include "PacketDissection/MbufContainerTransmitting.hpp"
|
||||
#include "PacketDissection/PacketContainer.hpp"
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Tcp.hpp"
|
||||
#include "rand.hpp"
|
||||
#include "xxh3.hpp"
|
||||
#include "xxhash.hpp"
|
||||
#include <boost/log/core.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <list>
|
||||
#include <sparsehash/dense_hash_map>
|
||||
|
||||
/**
|
||||
* @file Treatment.h
|
||||
* @author Fabienne, Felix, Tim
|
||||
* @brief This header file includes the class structure, structs and needed
|
||||
* includes
|
||||
* @version 0.1
|
||||
* @date 2021-06-10
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*
|
||||
*/
|
||||
|
||||
enum _flag_enum {
|
||||
SYN = 0b00000010,
|
||||
RST = 0b00000100,
|
||||
FIN = 0b00000001,
|
||||
ACK = 0b00010000,
|
||||
FINACK = 0b00010001,
|
||||
SYNACK = 0b00010010,
|
||||
SYNFIN = 0b00000011
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Data struct used as the key in the _densemap.
|
||||
*
|
||||
* This Data struct is used as the key in the densemap. The parameters uniquely
|
||||
* identify each connection, and are therefore satisfying the requirements of
|
||||
* being a key in the densemap.
|
||||
* @param _extip Stores the IP Address of the external host
|
||||
* @param _intip Stores the IP Address of the internal host
|
||||
* @param _extport Stores the Port Address of the external host
|
||||
* @param _intport Stores the Port Address of the internal host
|
||||
*
|
||||
*/
|
||||
class Data {
|
||||
public:
|
||||
u_int32_t _extip;
|
||||
u_int32_t _intip;
|
||||
u_int16_t _extport;
|
||||
u_int16_t _intport;
|
||||
/**
|
||||
* @brief Construct a new Data object from scratch
|
||||
*
|
||||
*/
|
||||
Data()
|
||||
: _extip(0)
|
||||
, _intip(0)
|
||||
, _extport(0)
|
||||
, _intport(0) {}
|
||||
/**
|
||||
* @brief Construct a new Data object
|
||||
*
|
||||
* @param _extip IP Address of external system
|
||||
* @param _intip IP Address of internal system
|
||||
* @param _extport Port of external system
|
||||
* @param _intport Port of internal system
|
||||
*/
|
||||
Data(u_int32_t _extip, u_int32_t _intip, u_int16_t _extport,
|
||||
u_int16_t _intport)
|
||||
: _extip(_extip)
|
||||
, _intip(_intip)
|
||||
, _extport(_extport)
|
||||
, _intport(_intport) {}
|
||||
|
||||
/**
|
||||
* @brief Redefinition of operator==
|
||||
* Needed in order to satisfy the external implementation of the used
|
||||
* hashfunction in combination with googles densemap
|
||||
*
|
||||
* @param d1
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool operator==(const Data& d1) const {
|
||||
return d1._extip == _extip && d1._intip == _intip &&
|
||||
d1._intport == _intport && d1._extport == _extport;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Info Struct used to encode the _offset and wether a finack has been
|
||||
* seen
|
||||
*
|
||||
* @param _offset Stores the difference between Sequence- and ACK-Numbers
|
||||
* @param _finseen Stores if a fin has already been seen
|
||||
* @param _pkt_inf Stores the PacketInfo for an ACK from connection
|
||||
* establishment
|
||||
*/
|
||||
class Info {
|
||||
|
||||
public:
|
||||
int _offset;
|
||||
bool _finseen_to_inside;
|
||||
bool _finseen_to_outside;
|
||||
bool _ack_to_inside_expected;
|
||||
bool _ack_to_outside_expected;
|
||||
std::list<PacketInfoIpv4Tcp*> _pkt_inf_list;
|
||||
/**
|
||||
* @brief Construct a new Info object from scratch
|
||||
*
|
||||
*/
|
||||
Info()
|
||||
: _offset(0)
|
||||
, _finseen_to_inside(false)
|
||||
, _finseen_to_outside(false)
|
||||
, _ack_to_inside_expected(false)
|
||||
, _ack_to_outside_expected(false)
|
||||
, _pkt_inf_list() {}
|
||||
/**
|
||||
* @brief Construct a new Info object
|
||||
* @param _offset Stores the difference between Sequence- and ACK-Numbers
|
||||
* @param _finseen Stores if a fin has already been seen
|
||||
* @param _pkt_inf Stores the PacketInfo for an ACK from connection
|
||||
* establishment
|
||||
*/
|
||||
Info(int offset, bool finseen_to_inside, bool finseen_to_outside,
|
||||
bool ack_to_inside, bool ack_to_outside, PacketInfoIpv4Tcp* pkt_inf)
|
||||
: _offset(offset)
|
||||
, _finseen_to_inside(finseen_to_inside)
|
||||
, _finseen_to_outside(finseen_to_outside)
|
||||
, _ack_to_inside_expected(ack_to_inside)
|
||||
, _ack_to_outside_expected(ack_to_outside) {
|
||||
if (pkt_inf != nullptr) {
|
||||
_pkt_inf_list.push_back(pkt_inf);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief TreatmentHash manages the calculation of the hashvalue over a Data
|
||||
* Struct and is used in the _densemap
|
||||
*
|
||||
*/
|
||||
class TreatmentHash {
|
||||
public:
|
||||
/**
|
||||
* @brief Redefinition of the operator() used in the _densemap and _ackmap
|
||||
*
|
||||
* @param d Data Struct with encodings of internal and external IPs and
|
||||
* ports, which uniquely identify a connection
|
||||
* @return size_t Hashvalue used as the key in both _dense- and _ackmap
|
||||
*/
|
||||
size_t operator()(const Data& d) const { // C++ call by reference
|
||||
return XXH3_64bits_withSeed(
|
||||
&d._extip, sizeof(d._extip),
|
||||
XXH3_64bits_withSeed(
|
||||
&d._intip, sizeof(d._intip),
|
||||
XXH3_64bits_withSeed(
|
||||
&d._extport, sizeof(d._extport),
|
||||
XXH3_64bits(&d._intport, sizeof(d._intport)))));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Treatment class, containing all functionality of the Treatment.
|
||||
*
|
||||
* The Treatment itself provides an implementation of SYN-cookies, combined with
|
||||
* the functionalities of a TCP-Proxy, in order to migitate SYN-Floods. Other
|
||||
* attacks just as SYN-FIN, SYN-FIN-ACK or the UDP-Flood are already migitated
|
||||
* in the analyzer, as the analyzer already contains all the information to do
|
||||
* this. Thus function calls are reduced, ultimatively resulting in a better
|
||||
* performance.
|
||||
*
|
||||
*/
|
||||
class Treatment {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Treatment object
|
||||
*
|
||||
* On construction of a new Treatment object the _s_timestamp is set to its
|
||||
* initial value, a random cookie_secret is calculated and the pointers to
|
||||
* both PacketContainers are being stored in member variables.
|
||||
* @param pkt_to_inside PacketContainer containing the packets with the
|
||||
* destination being the secured network
|
||||
* @param pkt_to_outside PacketContainer containing the packets with the
|
||||
* destination being the internet
|
||||
*/
|
||||
inline Treatment(MbufContainerTransmitting* pkt_send_to_outside,
|
||||
MbufContainerTransmitting* pkt_send_to_inside,
|
||||
u_int8_t syn_thresh)
|
||||
: _cookie_secret(Rand::get_random_64bit_value())
|
||||
, _packet_to_inside(pkt_send_to_inside)
|
||||
, _packet_to_outside(pkt_send_to_outside)
|
||||
, _syn_thresh(syn_thresh)
|
||||
, _skip_syn(0) {
|
||||
|
||||
// disables logging
|
||||
/* auto corehandle = boost::log::core::get();
|
||||
corehandle->set_logging_enabled(false); */
|
||||
|
||||
// Densemap requires you to set an empty key, which is never used by
|
||||
// legit connections Dense_hash_map requires you call set_empty_key()
|
||||
_densemap.set_empty_key(Data(0, 0, 0, 0));
|
||||
|
||||
// immediately after constructing the hash_map, and before calling any
|
||||
// other dense_hash_map method
|
||||
_densemap.set_deleted_key(Data(0, 0, 1, 1));
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Init of Treatment done. Created
|
||||
// cookie_secret, " "_s_timestamp and inserted empty and deleted
|
||||
// key---|";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a new Treatment object for testing purposes, create a
|
||||
* random cookie_secret and init the _s_timestamp
|
||||
*
|
||||
*/
|
||||
inline Treatment() {
|
||||
_cookie_secret = 0;
|
||||
_s_timestamp = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This method checks if the packet to inside is suitable for
|
||||
* treatment and treats it accordingly
|
||||
*
|
||||
* The function treat_packets_to_inside() works on two packetcontainers and
|
||||
* iterates over all elements inside of them. If the packet is not yet
|
||||
* deleted and if it is a TCPIPv4 packet, then treatment begins. Depending
|
||||
* on the flag combinations in the TCPHeader further steps are being taken
|
||||
* in order to fulfill the requirements, which are defined in the activity
|
||||
* diagram "treat_packets()" as seen in the review document. treat_packets()
|
||||
* involves adjustments of sequence and acknowledgement numbers, calculating
|
||||
* and checking syn-cookies. Depending on internal rules packets can be
|
||||
* forwarded, adjusted, stored and dropped on their way through the system.
|
||||
*/
|
||||
inline bool treat_packets_to_inside(PacketInfoIpv4Tcp* _pkt_info) {
|
||||
|
||||
// BOOST_LOG_TRIVIAL(info)<< "Size of densemap before to inside: " <<
|
||||
// _densemap.size();
|
||||
|
||||
/************************************************************************
|
||||
****Treatment of packets with direction towards the internal
|
||||
*network****
|
||||
************************************************************************/
|
||||
// get packetInfo at current position
|
||||
// check if packet has been deleted
|
||||
// check wether packet is IPv4TCP
|
||||
// get the flags of packet i as they will be needed a few times
|
||||
u_int8_t _flags = _pkt_info->get_flags();
|
||||
// SYN-ACK is set, simply forward the packet to the internal
|
||||
// network and create an entry in the _densemap
|
||||
if ((_flags & _flag_enum::SYNFIN) == _flag_enum::SYNFIN) {
|
||||
rte_pktmbuf_free(_pkt_info->get_mbuf());
|
||||
} else if ((_flags & _flag_enum::SYNACK) ==
|
||||
_flag_enum::SYNACK) { // check wether the syn and ack
|
||||
// flag is set
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Received SYN-ACK from
|
||||
// outside---|";
|
||||
// just simply forward the packet to the internal network
|
||||
// also create entry in the _densemap, with _offset
|
||||
// difference =
|
||||
// 0
|
||||
Data insert(_pkt_info->get_src_ip(), _pkt_info->get_dst_ip(),
|
||||
_pkt_info->get_src_port(), _pkt_info->get_dst_port());
|
||||
Info info(0, false, false, false, false, nullptr);
|
||||
_densemap.insert(std::make_pair(insert, info));
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Created new entry for
|
||||
// connection: _extip " << _pkt_info->get_src_ip() << " _extport: "
|
||||
// << _pkt_info->get_src_port()<< " _intip: " <<
|
||||
// _pkt_info->get_dst_ip() << " _intport: " <<
|
||||
// _pkt_info->get_dst_port() << "---|"; place packet in the sending
|
||||
// container to inside
|
||||
_packet_to_inside->add_mbuf(_pkt_info->get_mbuf());
|
||||
|
||||
}
|
||||
// SYN is set, generate cookie hash
|
||||
else if ((_flags & _flag_enum::SYN) == _flag_enum::SYN) {
|
||||
|
||||
if (_skip_syn < _syn_thresh) {
|
||||
++_skip_syn;
|
||||
} else { // SYN to INSIDE
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Received SYN to inside---|";
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Mbuf is: " <<
|
||||
// _pkt_info->get_mbuf() << "---|";
|
||||
/* use this part to calculate the syn-cookie, create a new
|
||||
* packet and send it back to the same side it came from */
|
||||
u_int32_t _cookie = calc_cookie_hash(
|
||||
_s_timestamp, _pkt_info->get_src_ip(),
|
||||
_pkt_info->get_dst_ip(), _pkt_info->get_src_port(),
|
||||
_pkt_info->get_dst_port());
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Calculated cookie is: " <<
|
||||
// _cookie << "---|";
|
||||
|
||||
_cookie = _cookie & 0xFFFFFF00; // got upper bits
|
||||
u_int32_t _seqnum =
|
||||
_cookie |
|
||||
_s_timestamp; // got cookie + 8 bit _s_timestamp
|
||||
// BOOST_LOG_TRIVIAL(info)<<
|
||||
// "|---Calculated cookie with timestamp
|
||||
// is: " << _seqnum << "---|";
|
||||
|
||||
// create the reply for the external connection/host
|
||||
rte_mbuf* reply_mbuf = _packet_to_outside->get_empty_mbuf();
|
||||
if (reply_mbuf == nullptr) {
|
||||
return false;
|
||||
}
|
||||
rte_pktmbuf_append(reply_mbuf, sizeof(struct rte_ether_hdr) +
|
||||
sizeof(struct rte_ipv4_hdr) +
|
||||
sizeof(struct rte_tcp_hdr));
|
||||
PacketInfoIpv4Tcp* reply = new PacketInfoIpv4Tcp(reply_mbuf);
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---The reply is of type: " <<
|
||||
// reply->get_type() << "---|";
|
||||
|
||||
reply->fill_payloadless_tcp_packet(
|
||||
_pkt_info->get_dst_mac(), _pkt_info->get_src_mac(),
|
||||
_pkt_info->get_dst_ip(), _pkt_info->get_src_ip(),
|
||||
_pkt_info->get_dst_port(), _pkt_info->get_src_port(),
|
||||
_seqnum, _pkt_info->get_seq_num() + 1, _flag_enum::SYNACK,
|
||||
_pkt_info->get_window_size());
|
||||
reply->prepare_offloading_checksums();
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Created SYN-ACK with Cookie:
|
||||
// " << reply->get_seq_num()<< "---|"; BOOST_LOG_TRIVIAL(info)
|
||||
// << " |---The new SYN-ACK goes with: extip: " <<
|
||||
// reply->get_dst_ip()<< " extport: " << reply->get_dst_port()<<
|
||||
// " intip: " << reply->get_src_ip() << " intport: " <<
|
||||
// reply->get_src_port() << "---|"; delete/drop received
|
||||
rte_pktmbuf_free(_pkt_info->get_mbuf());
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Dropped incoming packet---|";
|
||||
// now packet is getting send out in the next burst cycle
|
||||
|
||||
delete reply;
|
||||
_skip_syn = 0;
|
||||
}
|
||||
|
||||
}
|
||||
// Case: RST received from outside
|
||||
else if ((_flags & _flag_enum::RST) == _flag_enum::RST) {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Received RST from outside,
|
||||
// ""deleting entry in densemap---|"; erase entry in _densemap with
|
||||
// key = hash(AliceIP, AlicePort, BobIP, BobPort) Send packet to
|
||||
// inside with destIP = BobIP, destPort = BobPort, srcIP = AliceIP,
|
||||
// srcPort = AlicePort erased entry in _densemap
|
||||
_densemap.erase(
|
||||
Data(_pkt_info->get_src_ip(), _pkt_info->get_dst_ip(),
|
||||
_pkt_info->get_src_port(), _pkt_info->get_dst_port()));
|
||||
|
||||
_packet_to_inside->add_mbuf(_pkt_info->get_mbuf());
|
||||
|
||||
}
|
||||
// Case: Received FIN, no FIN-ACK from outside
|
||||
else if (((_flags & _flag_enum::FIN) == _flag_enum::FIN)) {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Received a FIN from outside---|";
|
||||
// create Data fin for the packet
|
||||
// find the entry in our map
|
||||
auto iter = _densemap.find(
|
||||
Data(_pkt_info->get_src_ip(), _pkt_info->get_dst_ip(),
|
||||
_pkt_info->get_src_port(), _pkt_info->get_dst_port()));
|
||||
// Catch case, that we dont interact on empty map
|
||||
if (iter == _densemap.end()) {
|
||||
// drop packet
|
||||
rte_pktmbuf_free(_pkt_info->get_mbuf());
|
||||
// BOOST_LOG_TRIVIAL(info)<< "|---Dropped Packet comming from
|
||||
// outside---|";
|
||||
}
|
||||
|
||||
// Check if fin has already been seen, and we do not have an
|
||||
// finack
|
||||
else if (iter->second._finseen_to_outside == true) {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---FIN-ACK to FIN received from
|
||||
// outside---|"; change the packets ack number tweak by adding
|
||||
// into one line
|
||||
iter->second._finseen_to_inside = true;
|
||||
iter->second._ack_to_outside_expected = true;
|
||||
_pkt_info->set_ack_num(_pkt_info->get_ack_num() -
|
||||
iter->second._offset);
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
|
||||
// delete the entry
|
||||
/* _densemap.erase(Data(
|
||||
_pkt_info->get_src_ip(), _pkt_info->get_dst_ip(),
|
||||
_pkt_info->get_src_port(),
|
||||
_pkt_info->get_dst_port()));
|
||||
//BOOST_LOG_TRIVIAL(info) << "Deleted entry in densemap";
|
||||
*/
|
||||
|
||||
// send packet to inside // aka. do nothing
|
||||
_packet_to_inside->add_mbuf(_pkt_info->get_mbuf());
|
||||
|
||||
} else if (iter->second._finseen_to_inside == false) {
|
||||
// change status _finseen to true
|
||||
iter->second._finseen_to_inside = true;
|
||||
// change the packets ack number
|
||||
_pkt_info->set_ack_num(_pkt_info->get_ack_num() -
|
||||
iter->second._offset);
|
||||
// refresh the checksums
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Changed Finseen to true for
|
||||
// connection: ""extip: " << _pkt_info->get_src_ip()
|
||||
//<< " extport: " << _pkt_info->get_src_port()
|
||||
//<< " intip: " << _pkt_info->get_dst_ip()
|
||||
//<< " intport: " << _pkt_info->get_dst_port() << "---|";
|
||||
|
||||
_packet_to_inside->add_mbuf(_pkt_info->get_mbuf());
|
||||
} else {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Duplicate FIN from
|
||||
// Outside---|";
|
||||
_pkt_info->set_ack_num(_pkt_info->get_ack_num() -
|
||||
iter->second._offset);
|
||||
// refresh the checksums
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
_packet_to_inside->add_mbuf(_pkt_info->get_mbuf());
|
||||
}
|
||||
|
||||
}
|
||||
// CASE: ACK RECEIVED from Alice
|
||||
else if ((_flags & _flag_enum::ACK) == _flag_enum::ACK &&
|
||||
((_flags & _flag_enum::FINACK) != _flag_enum::FINACK)) {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Received ACK from outside---|";
|
||||
Data ack(_pkt_info->get_src_ip(), _pkt_info->get_dst_ip(),
|
||||
_pkt_info->get_src_port(), _pkt_info->get_dst_port());
|
||||
auto id = _densemap.find(ack);
|
||||
if (id == _densemap.end()) { // no entry is here yet
|
||||
// BOOST_LOG_TRIVIAL(info)
|
||||
// << "|---Received ACK to SYN-ACK from outside---|";
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Checking the SYN-COOKIE---|";
|
||||
u_int32_t _cookie_val =
|
||||
_pkt_info->get_ack_num(); // get acknowledgementnumber
|
||||
// from packet
|
||||
bool _legit =
|
||||
check_syn_cookie(_cookie_val - 1,
|
||||
ack); // check for the correkt cookie
|
||||
if (_legit == true) { // the connection is to be established
|
||||
// Take the packet and save it, till the connection
|
||||
// to the internal host is established Use the
|
||||
// densemap for this purpose by setting the pointer
|
||||
// in info to taken_packet
|
||||
rte_mbuf* reply_mbuf = _packet_to_inside->get_empty_mbuf();
|
||||
if (reply_mbuf == nullptr) {
|
||||
return false;
|
||||
}
|
||||
rte_pktmbuf_append(reply_mbuf,
|
||||
sizeof(struct rte_ether_hdr) +
|
||||
sizeof(struct rte_ipv4_hdr) +
|
||||
sizeof(struct rte_tcp_hdr));
|
||||
PacketInfoIpv4Tcp* reply =
|
||||
new PacketInfoIpv4Tcp(reply_mbuf);
|
||||
|
||||
if (reply == nullptr) {
|
||||
// BOOST_LOG_TRIVIAL(fatal) << "created a nullptr";
|
||||
}
|
||||
_densemap.insert(std::make_pair(
|
||||
ack, Info(0, false, false, false, false, _pkt_info)));
|
||||
// Still need to send that syn to inside
|
||||
|
||||
// TO-DO check if _pkt_info is legit there
|
||||
reply->fill_payloadless_tcp_packet(
|
||||
_pkt_info->get_src_mac(), _pkt_info->get_dst_mac(),
|
||||
_pkt_info->get_src_ip(), _pkt_info->get_dst_ip(),
|
||||
_pkt_info->get_src_port(), _pkt_info->get_dst_port(),
|
||||
_pkt_info->get_seq_num() - 1, 123, _flag_enum::SYN,
|
||||
_pkt_info->get_window_size());
|
||||
reply->prepare_offloading_checksums();
|
||||
// BOOST_LOG_TRIVIAL(info)
|
||||
// << "|---Cookie " << _pkt_info->get_ack_num() - 1
|
||||
// << " correct, sending SYN to inside---|";
|
||||
// BOOST_LOG_TRIVIAL(info)
|
||||
//<< "|---SYN to inside goes from " << reply->get_src_ip()
|
||||
// << " to: " << reply->get_dst_ip() << " ---|";
|
||||
|
||||
// now packet is getting send out in the next burst
|
||||
// cycle
|
||||
_packet_to_outside->add_mbuf(reply_mbuf);
|
||||
delete reply;
|
||||
return true;
|
||||
|
||||
} else if (_legit == false) { // the connection is closed
|
||||
// with an rst, drop packet
|
||||
// BOOST_LOG_TRIVIAL(info)
|
||||
// << "|---Cookie incorrect, dropped packet---|";
|
||||
|
||||
// Send RST if (diff>1 XOR hash!=cookie_value)
|
||||
rte_mbuf* rst_mbuf = _packet_to_inside->get_empty_mbuf();
|
||||
if (rst_mbuf == nullptr) {
|
||||
return false;
|
||||
}
|
||||
PacketInfo* rst =
|
||||
PacketInfoCreator::create_pkt_info(rst_mbuf, IPv4TCP);
|
||||
PacketInfoIpv4Tcp* rst4 =
|
||||
static_cast<PacketInfoIpv4Tcp*>(rst);
|
||||
|
||||
rst4->fill_payloadless_tcp_packet(
|
||||
_pkt_info->get_dst_mac(), _pkt_info->get_src_mac(),
|
||||
ack._extip, ack._intip, ack._extport, ack._intport,
|
||||
_pkt_info->get_ack_num(), 0, _flag_enum::RST,
|
||||
_pkt_info
|
||||
->get_window_size()); // fill_payloadless_tcp_packet
|
||||
// already exists, we
|
||||
// just need it from
|
||||
// Tobias
|
||||
rst4->prepare_offloading_checksums();
|
||||
_packet_to_outside->add_mbuf(rst4->get_mbuf());
|
||||
|
||||
rte_pktmbuf_free(_pkt_info->get_mbuf());
|
||||
}
|
||||
|
||||
}
|
||||
// No entry in _densemap -> It is an ACK as a reply to
|
||||
// SYN-ACK entry can be found and its not a reply to an fin
|
||||
// ack
|
||||
else if (unlikely(id->second._finseen_to_inside == true &&
|
||||
id->second._finseen_to_outside == true &&
|
||||
id->second._ack_to_inside_expected == true)) {
|
||||
// BOOST_LOG_TRIVIAL(info)
|
||||
// << "|---ACK to FIN-ACK, Connection Closed---|";
|
||||
// simply manage _offset and thats it
|
||||
_pkt_info->set_ack_num(_pkt_info->get_ack_num() -
|
||||
id->second._offset);
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
|
||||
// delete the entry
|
||||
_densemap.erase(id);
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Deleted entry in
|
||||
// densemap---|";
|
||||
|
||||
_packet_to_inside->add_mbuf(_pkt_info->get_mbuf());
|
||||
|
||||
}
|
||||
// If the connection from inside is not fully established
|
||||
// yet, i need to add it to the queue first
|
||||
else if (unlikely(id->second._pkt_inf_list.empty() == false)) {
|
||||
// now add it to the queue
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Put early ack into
|
||||
// queue---|";
|
||||
id->second._pkt_inf_list.push_back(_pkt_info);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Regular ACK, simply
|
||||
// send---|";
|
||||
// simply manage _offset and thats it
|
||||
_pkt_info->set_ack_num(_pkt_info->get_ack_num() -
|
||||
id->second._offset);
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
|
||||
_packet_to_inside->add_mbuf(_pkt_info->get_mbuf());
|
||||
}
|
||||
}
|
||||
// BOOST_LOG_TRIVIAL(info) << "Size of densemap after to inside: " <<
|
||||
// _densemap.size();
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @brief This method checks if the packet to outside is suitable for
|
||||
* treatment and treats it accordingly
|
||||
*
|
||||
* The function treat_packets_to_outside() works on two packetcontainers and
|
||||
* iterates over all elements inside them. If the packet is not yet deleted
|
||||
* and if it is a TCPIPv4 packet, then treatment begins. Depending on the
|
||||
* flag combinations in the TCPHeader further steps are being taken in order
|
||||
* to fulfill the requirements, which are defined in the activity diagram
|
||||
* "treat_packets()" as seen in the review document. treat_packets()
|
||||
* involves adjustments of sequence and acknowledgement numbers, calculating
|
||||
* and checking syn-cookies. Depending on internal rules packets can be
|
||||
* forwarded, adjusted, stored and dropped on their way through the system.
|
||||
*/
|
||||
inline bool treat_packets_to_outside(PacketInfoIpv4Tcp* _pkt_info) {
|
||||
|
||||
// BOOST_LOG_TRIVIAL(info) << "Size of densemap before to outside: " <<
|
||||
// _densemap.size();
|
||||
/************************************************************************
|
||||
****Treatment of packets with direction towards the external network****
|
||||
************************************************************************/
|
||||
u_int8_t _flags =
|
||||
_pkt_info->get_flags(); // get the flags of packet as
|
||||
// they will be needed a few times
|
||||
// BOOST_LOG_TRIVIAL(info) << "THE TYPE IS" << std::to_string(_flags);
|
||||
if ((_flags & _flag_enum::SYNFIN) == _flag_enum::SYNFIN) {
|
||||
rte_pktmbuf_free(_pkt_info->get_mbuf());
|
||||
} else if ((_flags & _flag_enum::SYNACK) ==
|
||||
_flag_enum::SYNACK) { // check wether the syn&ack flag is
|
||||
// set
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Got
|
||||
// a SYN-ACK comming from inside---|";
|
||||
// Create entry in the Densemap
|
||||
// Reply with the ack stored in _densemap for this specific
|
||||
// connection...
|
||||
|
||||
// Get Data from connection in order to create entry in
|
||||
// _densemap and check _densemap
|
||||
Data dfirst(_pkt_info->get_dst_ip(), _pkt_info->get_src_ip(),
|
||||
_pkt_info->get_dst_port(), _pkt_info->get_src_port());
|
||||
// find according value in _densemap
|
||||
auto id = _densemap.find(dfirst);
|
||||
// unsure about that, was to catch the case, that no ack has
|
||||
// ever been held
|
||||
if (id == _densemap.end()) {
|
||||
// drop packet and delete connection info
|
||||
rte_pktmbuf_free(_pkt_info->get_mbuf());
|
||||
} else if (id->second._pkt_inf_list.empty() == false) {
|
||||
// cast into an ipv4 packet
|
||||
|
||||
bool first_packet = true;
|
||||
for (auto elem : id->second._pkt_inf_list) {
|
||||
|
||||
if (first_packet) {
|
||||
|
||||
// calculate _offset by substracting
|
||||
// internal_ack_num from external_ack_num
|
||||
int offset =
|
||||
elem->get_ack_num() - _pkt_info->get_seq_num() - 1;
|
||||
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---The offset is:" <<
|
||||
// offset << ", the external acknum is: " <<
|
||||
// elem->get_ack_num() << " the internal seqnum is: " <<
|
||||
// _pkt_info->get_seq_num() << " --- |";
|
||||
|
||||
id->second._offset = offset;
|
||||
// adjust the acknum of the ack as a response to
|
||||
// syn ack
|
||||
// outside->set_ack_num(outside->get_ack_num() -
|
||||
// offset);
|
||||
elem->set_ack_num(_pkt_info->get_seq_num() + 1);
|
||||
// refresh checksum
|
||||
elem->prepare_offloading_checksums();
|
||||
// send received ack with adjusted acknum, this
|
||||
// may already contain data
|
||||
_packet_to_inside->add_mbuf(elem->get_mbuf());
|
||||
// erase entry in _pkt_inf
|
||||
|
||||
first_packet = false;
|
||||
} else {
|
||||
|
||||
elem->set_ack_num(elem->get_ack_num() -
|
||||
id->second._offset);
|
||||
|
||||
elem->prepare_offloading_checksums();
|
||||
_packet_to_inside->add_mbuf(elem->get_mbuf());
|
||||
}
|
||||
delete elem;
|
||||
}
|
||||
id->second._pkt_inf_list.clear();
|
||||
} else {
|
||||
// BOOST_LOG_TRIVIAL(fatal) << "No element in the list";
|
||||
}
|
||||
}
|
||||
// check wether the syn flag is set
|
||||
else if ((_flags & _flag_enum::SYN) == _flag_enum::SYN) {
|
||||
// Simply forward the packet
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Forwarding the " "SYN from
|
||||
// internal to external ---|";
|
||||
_packet_to_outside->add_mbuf(_pkt_info->get_mbuf());
|
||||
}
|
||||
// RST received from inside_pkt_
|
||||
else if ((_flags & _flag_enum::RST) == _flag_enum::RST) {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Received an RST from inside---|";
|
||||
Data erase(_pkt_info->get_dst_ip(), _pkt_info->get_src_ip(),
|
||||
_pkt_info->get_dst_port(), _pkt_info->get_src_port());
|
||||
auto id = _densemap.find(erase);
|
||||
if (id == _densemap.end()) {
|
||||
// drop packet
|
||||
rte_pktmbuf_free(_pkt_info->get_mbuf());
|
||||
|
||||
} else {
|
||||
_pkt_info->set_seq_num(_pkt_info->get_seq_num() +
|
||||
id->second._offset);
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
|
||||
_packet_to_outside->add_mbuf(_pkt_info->get_mbuf());
|
||||
|
||||
_densemap.erase(erase);
|
||||
}
|
||||
}
|
||||
// FIN received from inside_pkt
|
||||
else if (((_flags & _flag_enum::FIN) == _flag_enum::FIN)) {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Recevied a FIN from inside---|";
|
||||
// create Data fin for the packet
|
||||
|
||||
// find the entry in our map
|
||||
auto iter = _densemap.find(
|
||||
Data(_pkt_info->get_dst_ip(), _pkt_info->get_src_ip(),
|
||||
_pkt_info->get_dst_port(), _pkt_info->get_src_port()));
|
||||
if (iter == _densemap.end()) {
|
||||
// drop packet
|
||||
rte_pktmbuf_free(_pkt_info->get_mbuf());
|
||||
}
|
||||
else if ((iter->second._finseen_to_inside == true) /* &&
|
||||
((_flags & _flags::FINACK) == _flags::FINACK)*/) {
|
||||
// Check if fin has already been seen and we are not
|
||||
// looking for the reply
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---FIN-ACK for FIN---|";
|
||||
// change the packets seq number
|
||||
iter->second._finseen_to_outside = true;
|
||||
iter->second._ack_to_inside_expected = true;
|
||||
_pkt_info->set_seq_num(_pkt_info->get_seq_num() +
|
||||
iter->second._offset);
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
// delete the entry
|
||||
/* _densemap.erase(Data(
|
||||
_pkt_info->get_dst_ip(), _pkt_info->get_src_ip(),
|
||||
_pkt_info->get_dst_port(),
|
||||
_pkt_info->get_src_port()));
|
||||
*/
|
||||
// send packet to inside // aka. do nothing
|
||||
|
||||
_packet_to_outside->add_mbuf(_pkt_info->get_mbuf());
|
||||
}
|
||||
|
||||
// Case: its the first FIN with piggybagged ack
|
||||
else if (iter->second._finseen_to_outside == false) {
|
||||
// BOOST_LOG_TRIVIAL(info)<< "|---Recevied the first FIN from
|
||||
// inside---|"; change status _finseen to true
|
||||
iter->second._finseen_to_outside = true;
|
||||
// get _offset
|
||||
// change the packets seq number
|
||||
_pkt_info->set_seq_num(_pkt_info->get_seq_num() +
|
||||
iter->second._offset);
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Changed Finseen to true for
|
||||
// connection: " "extip: "
|
||||
/* << _pkt_info->get_dst_ip()
|
||||
<< " extport: " << _pkt_info->get_dst_port()
|
||||
<< " intip: " << _pkt_info->get_src_ip()
|
||||
<< " intport: " << _pkt_info->get_src_port() << "---|"; */
|
||||
|
||||
_packet_to_outside->add_mbuf(_pkt_info->get_mbuf());
|
||||
} else {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|--- Saw duplicate FIN from
|
||||
// outside----|";
|
||||
|
||||
_pkt_info->set_seq_num(_pkt_info->get_seq_num() +
|
||||
iter->second._offset);
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
_packet_to_outside->add_mbuf(_pkt_info->get_mbuf());
|
||||
}
|
||||
}
|
||||
|
||||
// CASE: ACK RECEIVED from Bob
|
||||
else if (((_flags & _flag_enum::ACK) == _flag_enum::ACK) &&
|
||||
((_flags & _flag_enum::FINACK) != _flag_enum::FINACK)) {
|
||||
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Received an ACK from inside---|";
|
||||
Data ack(_pkt_info->get_dst_ip(), _pkt_info->get_src_ip(),
|
||||
_pkt_info->get_dst_port(), _pkt_info->get_src_port());
|
||||
auto id = _densemap.find(ack);
|
||||
// no entry in _densemap, create one and adjust value
|
||||
// accordingly
|
||||
if (id == _densemap.end()) {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Created new entry in the
|
||||
// densemap---|";
|
||||
Info info(0, false, false, false, false, nullptr);
|
||||
_densemap.insert(std::make_pair(ack, info));
|
||||
|
||||
// send out packet, aka do nothing
|
||||
_packet_to_outside->add_mbuf(_pkt_info->get_mbuf());
|
||||
|
||||
} else if (unlikely(id->second._finseen_to_inside == true &&
|
||||
id->second._finseen_to_outside == true &&
|
||||
id->second._ack_to_outside_expected == true)) {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---ACK to FIN-ACK-Packet---|";
|
||||
|
||||
_pkt_info->set_seq_num(_pkt_info->get_seq_num() +
|
||||
id->second._offset);
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
|
||||
_densemap.erase(id);
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Deleted entry in
|
||||
// densemap--|";
|
||||
_packet_to_outside->add_mbuf(_pkt_info->get_mbuf());
|
||||
|
||||
} else {
|
||||
// BOOST_LOG_TRIVIAL(info) << "|---Just a regular
|
||||
// ACK-Packet---|";
|
||||
// it is just a regular packet, simply adjust with
|
||||
// _offset and you are done.
|
||||
_pkt_info->set_seq_num(_pkt_info->get_seq_num() +
|
||||
id->second._offset);
|
||||
_pkt_info->prepare_offloading_checksums();
|
||||
|
||||
_packet_to_outside->add_mbuf(_pkt_info->get_mbuf());
|
||||
}
|
||||
}
|
||||
// BOOST_LOG_TRIVIAL(info) << "Size of densemap after to outside: " <<
|
||||
// _densemap.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief used in the main_lcore timer, in order to increment the
|
||||
* _s_timestamp every 64 seconds This function does nothing besides
|
||||
* incrementing the _s_timestamp by one every time it is called from our
|
||||
* thread
|
||||
* @param timestamp is global, but changed by this function
|
||||
*/
|
||||
inline static void s_increment_timestamp() {
|
||||
// increment _s_timestamp by one
|
||||
++_s_timestamp;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Calculates the Cookiehash from the global _s_timestamp, a global
|
||||
* cookie_secret and unique connection identifiers
|
||||
*
|
||||
* @param _s_timestamp is global
|
||||
* @param _extip
|
||||
* @param _intip
|
||||
* @param _extport
|
||||
* @param _intport
|
||||
* @return u_int32_t
|
||||
*/
|
||||
inline u_int32_t calc_cookie_hash(u_int8_t _s_timestamp, u_int32_t _extip,
|
||||
u_int32_t _intip, u_int16_t _extport,
|
||||
u_int16_t _intport) {
|
||||
|
||||
// use XXH3_64bits as shrinking it is still faster than using XXH32
|
||||
return XXH3_64bits_withSeed(
|
||||
&_s_timestamp, sizeof(_s_timestamp),
|
||||
XXH3_64bits_withSeed(
|
||||
&_extip, sizeof(_extip),
|
||||
XXH3_64bits_withSeed(
|
||||
&_intip, sizeof(_intip),
|
||||
XXH3_64bits_withSeed(
|
||||
&_extport, sizeof(_extport),
|
||||
XXH3_64bits_withSeed(&_intport, sizeof(_intport),
|
||||
_cookie_secret)))));
|
||||
}
|
||||
/**
|
||||
* @brief Check if the syn_cookie was received in the correct timespan and
|
||||
* if the reveiced cookie is correct/like the expected cookie
|
||||
*
|
||||
* @param cookie_value This is the sequencenumber sent away in the syn-ack
|
||||
* @param d d is the data we obtained from our packet, needed to calculate
|
||||
* the expected hash
|
||||
*
|
||||
*/
|
||||
inline bool check_syn_cookie(u_int32_t cookie_value, const Data& d) {
|
||||
// Extract the last 8 bits of the cookie (= timestamp)
|
||||
u_int8_t cookie_timestamp = cookie_value & 0x000000FF;
|
||||
|
||||
u_int8_t diff = _s_timestamp - cookie_timestamp;
|
||||
|
||||
if (diff <= 1) {
|
||||
// Calculate hash
|
||||
u_int32_t hash;
|
||||
|
||||
// Case: same time interval
|
||||
if (diff == 0) {
|
||||
// calculate expected cookie_hash
|
||||
hash = calc_cookie_hash(_s_timestamp, d._extip, d._intip,
|
||||
d._extport, d._intport);
|
||||
hash = hash & 0xFFFFFF00;
|
||||
// stuff cookie_hash with 8 bit _s_timestamp
|
||||
hash |= (u_int8_t)_s_timestamp;
|
||||
}
|
||||
|
||||
if (diff == 1) {
|
||||
// calculate expected cookie_hash for older timeinterval
|
||||
hash = calc_cookie_hash((u_int8_t)(_s_timestamp - 1), d._extip,
|
||||
d._intip, d._extport, d._intport);
|
||||
hash = hash & 0xFFFFFF00;
|
||||
// stuff cookie with 8 bit _s_timestamp
|
||||
hash |= (u_int8_t)(_s_timestamp - 1);
|
||||
}
|
||||
|
||||
// test wether the cookie is as expected; if so, return true
|
||||
if (hash == cookie_value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// return false, so that treat_packets is able to continue
|
||||
return false;
|
||||
}
|
||||
|
||||
inline static u_int8_t _s_timestamp =
|
||||
0; ///< timestamp used to check the legitimacy of SYN-cookies
|
||||
|
||||
u_int64_t _cookie_secret; ///< cookie_secret used to enhance the efficency
|
||||
///< of SYN-cookies
|
||||
u_int8_t _skip_syn;
|
||||
|
||||
u_int8_t _syn_thresh;
|
||||
|
||||
MbufContainerTransmitting*
|
||||
_packet_to_inside; ///< MbufContainer containing packets with
|
||||
///< destination being the internal network
|
||||
|
||||
MbufContainerTransmitting*
|
||||
_packet_to_outside; ///< MbufContainer containing packets with
|
||||
///< destination being the extern network
|
||||
|
||||
google::dense_hash_map<Data, Info, TreatmentHash>
|
||||
_densemap; ///< Map to store information about connections including
|
||||
///< _offset and if a fin has been seen
|
||||
|
||||
friend class Treatment_friend; ///< used for unit tests
|
||||
};
|
44
include/Treatment/rand.hpp
Normal file
44
include/Treatment/rand.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @file rand.hpp
|
||||
* @author Felix, Fabienne
|
||||
* @brief This header includes only one method which returns a random 64bit
|
||||
* unsigned integer
|
||||
* @version 0.1
|
||||
* @date 2021-07-06
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Rand itself provides a method to get a random number. This number is
|
||||
* used in Treatment as cookie_secret
|
||||
*
|
||||
*/
|
||||
class Rand {
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get a random 64bit unsigned integer
|
||||
*
|
||||
* @return u_int64_t
|
||||
*/
|
||||
static u_int64_t get_random_64bit_value() {
|
||||
u_int64_t random64BitNumber = 0;
|
||||
|
||||
u_int64_t value1 = (uint16_t)std::rand();
|
||||
value1 = (value1 << 48);
|
||||
random64BitNumber |= value1;
|
||||
|
||||
u_int64_t value2 = (uint16_t)rand();
|
||||
value2 = (value2 << 32);
|
||||
random64BitNumber |= value2;
|
||||
|
||||
u_int64_t value3 = (uint16_t)rand();
|
||||
random64BitNumber |= value3;
|
||||
|
||||
return random64BitNumber;
|
||||
}
|
||||
};
|
54
include/Treatment/random.hpp
Normal file
54
include/Treatment/random.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* File: random.hpp
|
||||
* --------------
|
||||
* This interface exports functions for generating pseudorandom numbers.
|
||||
*/
|
||||
|
||||
#ifndef _random_h
|
||||
#define _random_h
|
||||
|
||||
/*
|
||||
* Function: randomInteger
|
||||
* Usage: int n = randomInteger(low, high);
|
||||
* ----------------------------------------
|
||||
* Returns a random integer in the range low to high, inclusive.
|
||||
*/
|
||||
|
||||
int randomInteger(int low, int high);
|
||||
|
||||
/*
|
||||
* Function: randomReal
|
||||
* Usage: double d = randomReal(low, high);
|
||||
* ----------------------------------------
|
||||
* Returns a random real number in the half-open interval [low .. high). A
|
||||
* half-open interval includes the first endpoint but not the second, which
|
||||
* means that the result is always greater than or equal to low but
|
||||
* strictly less than high.
|
||||
*/
|
||||
|
||||
double randomReal(double low, double high);
|
||||
|
||||
/*
|
||||
* Function: randomChance
|
||||
* Usage: if (randomChance(p)) . . .
|
||||
* ---------------------------------
|
||||
* Returns true with the probability indicated by p. The argument p must
|
||||
* be a floating-point number between 0 (never) and 1 (always). For
|
||||
* example, calling randomChance(.30) returns true 30 percent of the time.
|
||||
*/
|
||||
|
||||
bool randomChance(double p);
|
||||
|
||||
/*
|
||||
* Function: setRandomSeed
|
||||
* Usage: setRandomSeed(seed);
|
||||
* ---------------------------
|
||||
* Sets the internal random number seed to the specified value. You can
|
||||
* use this function to set a specific starting point for the pseudorandom
|
||||
* sequence or to ensure that program behavior is repeatable during the
|
||||
* debugging phase.
|
||||
*/
|
||||
|
||||
void setRandomSeed(int seed);
|
||||
|
||||
#endif
|
55
include/Treatment/xxh3.hpp
Normal file
55
include/Treatment/xxh3.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* xxHash - Extremely Fast Hash algorithm
|
||||
* Development source file for `xxh3`
|
||||
* Copyright (C) 2019-2020 Yann Collet
|
||||
*
|
||||
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You can contact the author at:
|
||||
* - xxHash homepage: https://www.xxhash.com
|
||||
* - xxHash source repository: https://github.com/Cyan4973/xxHash
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: This file used to host the source code of XXH3_* variants.
|
||||
* during the development period.
|
||||
* The source code is now properly integrated within xxhash.h.
|
||||
*
|
||||
* xxh3.h is no longer useful,
|
||||
* but it is still provided for compatibility with source code
|
||||
* which used to include it directly.
|
||||
*
|
||||
* Programs are now highly discouraged to include xxh3.h.
|
||||
* Include `xxhash.h` instead, which is the officially supported interface.
|
||||
*
|
||||
* In the future, xxh3.h will start to generate warnings, then errors,
|
||||
* then it will be removed from source package and from include directory.
|
||||
*/
|
||||
|
||||
/* Simulate the same impact as including the old xxh3.h source file */
|
||||
|
||||
#define XXH_INLINE_ALL
|
||||
#include "xxhash.hpp"
|
5325
include/Treatment/xxhash.hpp
Normal file
5325
include/Treatment/xxhash.hpp
Normal file
File diff suppressed because it is too large
Load Diff
25447
include/json.hpp
Normal file
25447
include/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
113
install-requirements.sh
Normal file
113
install-requirements.sh
Normal file
@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
|
||||
export DPDK_VER=20.02
|
||||
export PCI_IF="0000:1a:00.3"
|
||||
|
||||
# check user privilege
|
||||
if [ `whoami` != 'root' ]; then
|
||||
echo "Please run this as root..., don't worry about it..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# get hugepage mount
|
||||
echo "updating fstab"
|
||||
r=`grep hugetlbfs /etc/fstab`
|
||||
if [ $? -eq 1 ]; then
|
||||
echo "huge /mnt/huge hugetlbfs defaults 0 0" >> /etc/fstab
|
||||
fi
|
||||
|
||||
if [ ! -d /mnt/huge ]; then
|
||||
mkdir /mnt/huge
|
||||
chmod 777 /mnt/huge/
|
||||
fi
|
||||
|
||||
echo "Updating sysctl"
|
||||
r=`grep nr_hugepages /etc/sysctl.conf`
|
||||
if [ $? -eq 1 ]; then
|
||||
echo "vm.nr_hugepages=256" >> /etc/sysctl.conf
|
||||
# also make sure it is live on this run, in case fstab has been already updated
|
||||
sysctl -w vm.nr_hugepages=256
|
||||
fi
|
||||
|
||||
echo "checking for iommu in GRUB"
|
||||
r=`grep iommu=pt /etc/default/grub`
|
||||
if [ $? -eq 1 ]; then
|
||||
echo "iommu is missing from grub"
|
||||
echo "please edit /etc/default/grub and make to append the below to GRUB_CMDLINE_LINUX"
|
||||
echo "default_hugepagesz=1G hugepagesz=1G hugepages=8 iommu=pt intel_iommu=on pci=assign-busses"
|
||||
echo 'example: GRUB_CMDLINE_LINUX="console=tty0 console=ttyS1,115200n8 biosdevname=0 net.ifnames=1 default_hugepagesz=1G hugepagesz=1G hugepages=8 iommu=pt intel_iommu=on pci=assign-busses"'
|
||||
echo "after that run: update-grub && reboot"
|
||||
echo "this will reboot your machine!"
|
||||
echo "other things you may want to add are:"
|
||||
echo "maxcpus=32"
|
||||
echo "isolcpus=3-31"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
r=`grep intel_iommu=on /etc/default/grub`
|
||||
if [ $? -eq 1 ]; then
|
||||
echo "iommu is missing from grub"
|
||||
echo "please edit /etc/default/grub and make to append the below to GRUB_CMDLINE_LINUX"
|
||||
echo "default_hugepagesz=1G hugepagesz=1G hugepages=8 iommu=pt intel_iommu=on pci=assign-busses"
|
||||
|
||||
echo 'example: GRUB_CMDLINE_LINUX="console=tty0 console=ttyS1,115200n8 biosdevname=0 net.ifnames=1 default_hugepagesz=1G hugepagesz=1G hugepages=8 iommu=pt intel_iommu=on pci=assign-busses"'
|
||||
echo "after that run: update-grub && reboot"
|
||||
echo "this will reboot your machine!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Going into /opt ..."
|
||||
mkdir /opt
|
||||
cd /opt
|
||||
|
||||
echo "Installing packages..."
|
||||
apt-get -y update
|
||||
apt-get -y install build-essential python3 python3-pip python3-pyelftools libnuma-dev pciutils libpcap-dev liblua5.3-dev libelf-dev git doxygen hugepages libmnl0 libmnl-dev libkmod2 libkmod-dev libelf1 libelf-dev libc6-dev-i386 libncurses5-dev libreadline-dev libdpdk-dev autoconf flex bison graphviz libboost-all-dev plantuml
|
||||
apt-get -y install linux-headers-`uname -r` || apt -y install linux-headers-generic
|
||||
pip3 install --user meson ninja
|
||||
|
||||
echo "Installing sparsehash" # from github
|
||||
git clone https://github.com/sparsehash/sparsehash.git sparsehash
|
||||
cd sparsehash
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
make clean
|
||||
cd ..
|
||||
rm -r sparsehash
|
||||
|
||||
echo "Setting env..."
|
||||
export RTE_TARGET=x86_64-native-linuxapp-gcc
|
||||
export RTE_SDK=/opt/dpdk-$DPDK_VER
|
||||
ln -s /usr/bin/python3 /usr/bin/python
|
||||
|
||||
echo "Downloading DPDK..."
|
||||
if [ ! -f /opt/dpdk-$DPDK_VER.tar.xz ]; then
|
||||
wget https://fast.dpdk.org/rel/dpdk-$DPDK_VER.tar.xz
|
||||
fi
|
||||
|
||||
echo "Unpacking DPDK..."
|
||||
rm -rf dpdk-$DPDK_VER/
|
||||
tar xvf dpdk-$DPDK_VER.tar.xz
|
||||
rm -rf dpdk-$DPDK_VER.tar.xz
|
||||
|
||||
echo "Installing DPDK..."
|
||||
cd dpdk-$DPDK_VER
|
||||
make config T=x86_64-native-linuxapp-gcc CONFIG_RTE_EAL_IGB_UIO=y
|
||||
make install T=x86_64-native-linuxapp-gcc DESTDIR=install CONFIG_RTE_EAL_IGB_UIO=y
|
||||
|
||||
cd ..
|
||||
|
||||
echo "binding dpdk interface $PCI_IF"
|
||||
modprobe uio
|
||||
insmod /opt/dpdk-$DPDK_VER/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko
|
||||
modprobe vfio-pci
|
||||
modprobe uio_pci_generic
|
||||
dpdkdevbind=/opt/dpdk-$DPDK_VER/usertools/dpdk-devbind.py
|
||||
$dpdkdevbind --force -u $PCI_IF
|
||||
$dpdkdevbind -b igb_uio $PCI_IF
|
||||
$dpdkdevbind -s
|
||||
|
||||
echo "finished"
|
||||
echo "all requirements should now be installed"
|
||||
echo "you can now configure and install AEGIS"
|
26
install.sh
Executable file
26
install.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
###########################################################
|
||||
## AEGIS INSTALLATION
|
||||
## This script will help you install AEGIS on your system
|
||||
## It will build meson with buildtype release
|
||||
## and optimization level 3.
|
||||
## Run it inside your terminal in the root folder of the
|
||||
## project.
|
||||
###########################################################
|
||||
|
||||
# check user privilege
|
||||
if [ `whoami` != 'root' ]; then
|
||||
echo "Please run this as root..., don't worry about it..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -r build_release
|
||||
meson --buildtyp release -Db_lto = true --optimization 3 build_release
|
||||
echo "########\nmeson finished preparations"
|
||||
cd build_release
|
||||
ninja
|
||||
echo "########\nninja finished local build"
|
||||
strip aegis
|
||||
cd ..
|
||||
meson install
|
||||
echo "########\nAEGIS is now installed on your system"
|
112
meson.build
Normal file
112
meson.build
Normal file
@ -0,0 +1,112 @@
|
||||
project('Aegis', 'cpp',
|
||||
# Get version number from file.
|
||||
# Fallback to "more" for Windows compatibility.
|
||||
version: run_command(find_program('cat', 'more'),
|
||||
files('VERSION')).stdout().strip(),
|
||||
license: 'BSD',
|
||||
default_options: ['cpp_std=c++17', 'buildtype=debug', 'default_library=static', ],
|
||||
meson_version: '>= 0.58.0'
|
||||
)
|
||||
|
||||
# check the OS is supported, rather than going any further
|
||||
supported_exec_envs = ['linux']
|
||||
exec_env = host_machine.system()
|
||||
if not supported_exec_envs.contains(exec_env)
|
||||
error('unsupported system type "@0@"'.format(exec_env))
|
||||
endif
|
||||
|
||||
# set up some global vars for compiler, platform, configuration, etc.
|
||||
compiler = meson.get_compiler('cpp')
|
||||
compiler_version = compiler.version()
|
||||
|
||||
# set include directory (where the header files live)
|
||||
inc = include_directories('include')
|
||||
|
||||
#project_libary = libary('project',files[sources])
|
||||
|
||||
# find dependencies
|
||||
dpdk_dep = dependency('libdpdk', required : false)
|
||||
project_dep = declare_dependency(include_directories : inc)
|
||||
pthread_dep = dependency('threads')
|
||||
boost_dep = dependency('boost', modules: ['filesystem','system','log'])
|
||||
|
||||
if boost_dep.found()
|
||||
message('boost found')
|
||||
|
||||
message('building on: "' + exec_env + '"')
|
||||
message('with compiler: "' + compiler.version() + '"')
|
||||
message('host machine: "' + host_machine.system() + '"')
|
||||
|
||||
subdir('doc')
|
||||
subdir('source')
|
||||
|
||||
if dpdk_dep.found()
|
||||
executable(
|
||||
'aegis',
|
||||
sources,
|
||||
include_directories : inc,
|
||||
dependencies : [dpdk_dep,pthread_dep,boost_dep]
|
||||
)
|
||||
|
||||
# ============= A T T A C K E R ================= #
|
||||
|
||||
executable(
|
||||
'syntflut',
|
||||
sources_attack,
|
||||
include_directories : inc,
|
||||
dependencies : [dpdk_dep,pthread_dep,boost_dep],
|
||||
cpp_args : '-DATTACK'
|
||||
)
|
||||
endif
|
||||
|
||||
|
||||
#================ T E S T S ==================== #
|
||||
|
||||
catch2_dep = dependency('catch2',
|
||||
fallback : ['catch2', 'catch2_dep'],
|
||||
required: true)
|
||||
|
||||
catch2 = declare_dependency(sources:'catch.cpp',dependencies:[catch2_dep])
|
||||
|
||||
subdir('test')
|
||||
|
||||
inc_test = include_directories('include', 'test/libdpdk_dummy/include')
|
||||
|
||||
# create new string array which has the same elements like sources but without the source/main.cpp file
|
||||
sources_tests = []
|
||||
foreach string : sources
|
||||
if (string != 'source/main.cpp') and (string != 'source/Initializer.cpp')
|
||||
sources_tests += [string]
|
||||
endif
|
||||
endforeach
|
||||
|
||||
# create test targets
|
||||
foreach t : test_sources_dict.keys()
|
||||
exe_name = t+'_test'
|
||||
test_name = t+'_test'
|
||||
|
||||
sources_this_test = sources_tests + [test_sources_dict.get(t)]
|
||||
|
||||
e = executable(
|
||||
exe_name,
|
||||
sources_this_test,
|
||||
include_directories : inc_test,
|
||||
dependencies : [catch2, pthread_dep, boost_dep],
|
||||
cpp_args : '-DTEST'
|
||||
)
|
||||
|
||||
test(test_name, e, suite:['unit_tests', 'catch2'])
|
||||
message('built test ' + test_name)
|
||||
|
||||
endforeach
|
||||
|
||||
# this does not affect any part of the build, for information only.
|
||||
message('\n=================\nMeson prepared build\nrun Ninja to build\n=================\n')
|
||||
endif
|
||||
|
||||
if not boost_dep.found()
|
||||
warning('boost not found')
|
||||
endif
|
||||
if not dpdk_dep.found()
|
||||
warning('dpdk not found; only unit tests can be executed')
|
||||
endif
|
11
meson_options.txt
Normal file
11
meson_options.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# Please keep these options sorted alphabetically.
|
||||
|
||||
option('disable_drivers', type: 'string', value: '', description: 'Comma-separated list of drivers to explicitly disable.')
|
||||
option('enable_docs', type: 'boolean', value: false, description: 'build documentation')
|
||||
option('enable_kmods', type: 'boolean', value: false, description: 'build kernel modules')
|
||||
option('examples', type: 'string', value: '', description: 'Comma-separated list of examples to build by default')
|
||||
option('machine', type: 'string', value: 'native', description: 'set the target machine type')
|
||||
option('max_ethports', type: 'integer', value: 32, description: 'maximum number of Ethernet devices')
|
||||
option('max_lcores', type: 'integer', value: 128, description: 'maximum number of cores/threads supported by EAL')
|
||||
option('max_numa_nodes', type: 'integer', value: 4, description: 'maximum number of NUMA nodes supported by EAL')
|
||||
option('tests', type: 'boolean', value: true, description: 'build unit tests')
|
286
source/Attacker/main.cpp
Normal file
286
source/Attacker/main.cpp
Normal file
@ -0,0 +1,286 @@
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <signal.h>
|
||||
|
||||
#include "Cli.hpp"
|
||||
#include "ConfigurationManagement/Configurator.hpp"
|
||||
#include "Initializer.hpp"
|
||||
#include "PacketDissection/PacketContainer.hpp"
|
||||
#include "Threads/AttackThread.hpp"
|
||||
|
||||
void handle_quit(int signum);
|
||||
void terminate(AttackThread** thread_arr, uint16_t nb_worker_threads);
|
||||
|
||||
bool quit = false;
|
||||
std::chrono::time_point<std::chrono::system_clock> start, end;
|
||||
uint64_t nb_pkts_to_dave = 0;
|
||||
uint64_t nb_pkts_from_dave = 0;
|
||||
uint64_t nb_atk_pkts = 0;
|
||||
uint64_t nb_pkts_to_alice = 0;
|
||||
uint64_t nb_pkts_from_alice = 0;
|
||||
uint64_t data_volume_to_alice = 0;
|
||||
uint64_t data_volume_from_alice = 0;
|
||||
int pkt_type_used = 0;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// ===== INITIALIZE ===== //
|
||||
// Register signal and signal handler
|
||||
signal(SIGINT, handle_quit);
|
||||
|
||||
Configurator::instance()->read_config("../test/config_attacker.json");
|
||||
|
||||
Initializer* init = new Initializer();
|
||||
unsigned int lcore_id;
|
||||
uint16_t dave_port = 0;
|
||||
uint16_t alice_port = 1;
|
||||
uint16_t nb_worker_threads = 0;
|
||||
|
||||
struct rte_mempool* mbuf_pool =
|
||||
init->init_dpdk_attacker(argc, argv, nb_worker_threads);
|
||||
|
||||
// create thread objects
|
||||
AttackThread* thread_arr[nb_worker_threads];
|
||||
PacketContainerLean* pkt_containers_to_alice[nb_worker_threads];
|
||||
PacketContainerLean* pkt_containers_to_dave[nb_worker_threads];
|
||||
for (int i = 0; i < nb_worker_threads; i++) {
|
||||
|
||||
pkt_containers_to_alice[i] =
|
||||
new PacketContainerLean(mbuf_pool, dave_port, alice_port, i, i);
|
||||
pkt_containers_to_dave[i] =
|
||||
new PacketContainerLean(mbuf_pool, alice_port, dave_port, i, i);
|
||||
|
||||
thread_arr[i] =
|
||||
new AttackThread(pkt_containers_to_alice[i],
|
||||
pkt_containers_to_dave[i], nb_worker_threads);
|
||||
}
|
||||
|
||||
// start each thread on an own lcore
|
||||
lcore_id = rte_lcore_id();
|
||||
|
||||
// run every thread except the last one
|
||||
for (int i = 0; i < nb_worker_threads; ++i) {
|
||||
lcore_id = rte_get_next_lcore(lcore_id, true, true);
|
||||
|
||||
rte_eal_remote_launch(
|
||||
static_cast<lcore_function_t*>(AttackThread::s_run), thread_arr[i],
|
||||
lcore_id);
|
||||
}
|
||||
|
||||
std::cout << "\nRunning. [Ctrl+C to quit]\n" << std::endl;
|
||||
|
||||
// =================== START CLI ==================== //
|
||||
|
||||
std::string input = "";
|
||||
const std::string NAME = "syntflut";
|
||||
const char* PATH_ATTACKING_FILE = "/home/guru/is_attacking/attacking";
|
||||
|
||||
enum State { RUNNING, IDLE };
|
||||
State state = IDLE;
|
||||
|
||||
while (input != "exit") {
|
||||
|
||||
std::cout << NAME << "> ";
|
||||
std::cin >> input;
|
||||
std::cout << std::endl;
|
||||
|
||||
if (input == "start") {
|
||||
if (state == IDLE) {
|
||||
|
||||
for (int i = 0; i < nb_worker_threads; ++i) {
|
||||
thread_arr[i]->_do_attack = true;
|
||||
}
|
||||
|
||||
// start measuring time running
|
||||
|
||||
start = std::chrono::system_clock::now();
|
||||
|
||||
// Start GUI
|
||||
|
||||
std::ofstream outfile(PATH_ATTACKING_FILE);
|
||||
outfile.close();
|
||||
|
||||
// ===== RUN ===== //
|
||||
|
||||
state = RUNNING;
|
||||
|
||||
} else { // state == RUNNING
|
||||
std::cout << "Cannot start if program is already running."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
} else if (input == "stop") {
|
||||
if (state == IDLE) {
|
||||
std::cout << "Cannot stop if program is not running."
|
||||
<< std::endl;
|
||||
|
||||
} else { // state == RUNNING
|
||||
|
||||
// Stop GUI
|
||||
std::remove(PATH_ATTACKING_FILE);
|
||||
|
||||
end = std::chrono::system_clock::now();
|
||||
|
||||
nb_pkts_to_dave = 0;
|
||||
nb_pkts_from_dave = 0;
|
||||
nb_pkts_to_alice = 0;
|
||||
nb_pkts_from_alice = 0;
|
||||
data_volume_to_alice = 0;
|
||||
data_volume_from_alice = 0;
|
||||
pkt_type_used = 0;
|
||||
|
||||
for (int i = 0; i < nb_worker_threads; ++i) {
|
||||
// rescue Informations
|
||||
nb_pkts_to_dave +=
|
||||
thread_arr[i]->get_total_nb_pkts_to_dave();
|
||||
nb_pkts_from_dave +=
|
||||
thread_arr[i]->get_total_nb_pkts_from_dave();
|
||||
nb_pkts_to_alice +=
|
||||
thread_arr[i]->get_total_nb_pkts_to_alice();
|
||||
nb_pkts_from_alice +=
|
||||
thread_arr[i]->get_total_nb_pkts_from_alice();
|
||||
data_volume_to_alice +=
|
||||
thread_arr[i]->get_total_data_volume_to_alice();
|
||||
data_volume_from_alice +=
|
||||
thread_arr[i]->get_total_data_volume_from_alice();
|
||||
pkt_type_used += thread_arr[i]->get_atk_pkt_type();
|
||||
|
||||
thread_arr[i]->_do_attack = false;
|
||||
}
|
||||
|
||||
// print attack statistics
|
||||
std::chrono::duration<double> elapsed_seconds = end - start;
|
||||
std::cout << "\nduration of attack:\t\t\t\t"
|
||||
<< elapsed_seconds.count() << " seconds" << std::endl;
|
||||
int pkt_size = -1;
|
||||
if (pkt_type_used > 1) { // TCP: tcp + ip + ether
|
||||
pkt_size = 20 + 20 + 14;
|
||||
} else { // UDP: udp + ip + ether
|
||||
pkt_size = 8 + 20 + 14;
|
||||
}
|
||||
nb_atk_pkts = nb_pkts_to_dave - nb_pkts_from_alice;
|
||||
std::cout << "attack packets sent:\t\t\t\t" << nb_atk_pkts
|
||||
<< std::endl;
|
||||
|
||||
std::cout << "data volume sent (without L1 header):\t\t"
|
||||
<< nb_atk_pkts * pkt_size / 1048576 << " MByte"
|
||||
<< std::endl;
|
||||
|
||||
std::cout << "data volume sent (with L1 header):\t\t"
|
||||
<< nb_atk_pkts * 84 / 1048576 << " MByte"
|
||||
<< std::endl;
|
||||
|
||||
std::cout << "average attack rate (without L1 header):\t"
|
||||
<< nb_atk_pkts * pkt_size / elapsed_seconds.count() /
|
||||
1048576 * 8
|
||||
<< " Mbps" << std::endl;
|
||||
|
||||
std::cout << "average attack rate (with L1 header):\t\t"
|
||||
<< nb_atk_pkts * 84 / elapsed_seconds.count() /
|
||||
1048576 * 8
|
||||
<< " Mbps" << std::endl;
|
||||
|
||||
std::cout << "average attack packet rate:\t\t\t"
|
||||
<< nb_atk_pkts / elapsed_seconds.count() / 1000
|
||||
<< " Kpps" << std::endl;
|
||||
|
||||
std::cout << "\nnumber packets sent from alice:\t\t\t"
|
||||
<< nb_pkts_from_alice << std::endl;
|
||||
|
||||
std::cout << "number packets recieved by alice:\t\t"
|
||||
<< nb_pkts_to_alice << std::endl;
|
||||
|
||||
std::cout << "average data rate sent from alice:\t\t"
|
||||
<< data_volume_from_alice / elapsed_seconds.count() /
|
||||
1024 * 8
|
||||
<< " Kbps" << std::endl;
|
||||
|
||||
std::cout << "average data rate recieved by alice:\t\t"
|
||||
<< data_volume_to_alice / elapsed_seconds.count() /
|
||||
1024 * 8
|
||||
<< " Kbps" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
/*
|
||||
std::cout << "\nstats for testing:" << std::endl;
|
||||
|
||||
std::cout << "number packets sent from dave:\t\t\t"
|
||||
<< nb_pkts_from_dave << std::endl;
|
||||
|
||||
std::cout << "number packets recieved by dave:\t\t\t"
|
||||
<< nb_pkts_to_dave << std::endl;
|
||||
|
||||
std::cout << "attack time:\t\t\t\t\t\t\t\t"
|
||||
<< elapsed_seconds.count() <<"s" << std::endl;
|
||||
*/
|
||||
|
||||
state = IDLE;
|
||||
}
|
||||
|
||||
} else if (input == "exit") {
|
||||
|
||||
// Stop GUI
|
||||
if (state == RUNNING) {
|
||||
std::remove(PATH_ATTACKING_FILE);
|
||||
}
|
||||
|
||||
} else if (input == "help" || input == "h") {
|
||||
std::cout << "start\tstart " << NAME << std::endl
|
||||
<< "stop\tstop " << NAME << std::endl
|
||||
<< "help, h\tprint commands " << std::endl
|
||||
<< "exit\texit " << NAME << std::endl
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "Command unknown. Try 'h' or 'help'." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== END CLI ==================== //
|
||||
|
||||
// ===== TERMINATE ===== //
|
||||
terminate(thread_arr, nb_worker_threads);
|
||||
|
||||
// destruct objects on heap
|
||||
for (int i = 0; i < nb_worker_threads; ++i) {
|
||||
|
||||
delete thread_arr[i];
|
||||
thread_arr[i] = nullptr;
|
||||
|
||||
delete pkt_containers_to_dave[i];
|
||||
pkt_containers_to_dave[i] = nullptr;
|
||||
|
||||
delete pkt_containers_to_alice[i];
|
||||
pkt_containers_to_alice[i] = nullptr;
|
||||
}
|
||||
|
||||
delete init;
|
||||
init = nullptr;
|
||||
|
||||
// cleanup eal
|
||||
rte_eal_mp_wait_lcore();
|
||||
rte_eal_cleanup();
|
||||
|
||||
// YOU ARE TERMINATED
|
||||
}
|
||||
|
||||
void handle_quit(int signum) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void terminate(AttackThread** thread_arr, uint16_t nb_worker_threads) {
|
||||
std::cout << "\nterminating..." << std::endl;
|
||||
|
||||
for (int i = 0; i < nb_worker_threads - 1; ++i) {
|
||||
#ifndef SINGLE_ITERATION
|
||||
thread_arr[i]->quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
// wait for threads to end
|
||||
for (int i = 0; i < nb_worker_threads - 1; ++i) {
|
||||
while (thread_arr[i]->is_running()) {
|
||||
// wait
|
||||
}
|
||||
}
|
||||
}
|
107
source/Cli.cpp
Normal file
107
source/Cli.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include "Cli.hpp"
|
||||
|
||||
Cli::Cli() {
|
||||
add_to_commands_list("help, h", "Help Screen", std::bind(&Cli::print_help, &*this, std::placeholders::_1));
|
||||
add_to_commands_list("exit", "Exit Program", std::bind(&Cli::exit_program, &*this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void Cli::add_to_commands_list(std::string names, std::string desc, Func func) {
|
||||
Command cmd = std::make_tuple(names, desc, func);
|
||||
_commands.push_back(cmd);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//------------------------------------------- Run --------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
void Cli::run() {
|
||||
while(!_exit) { iterate(); }
|
||||
}
|
||||
|
||||
void Cli::iterate() {
|
||||
// Ask for input
|
||||
std::cout << "\033[1;36mAegis: \033[0m";
|
||||
std::string input;
|
||||
std::cin >> input;
|
||||
|
||||
// Get parameters
|
||||
std::deque<std::string> parameters;
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
std::istringstream iss(line);
|
||||
std::string arg;
|
||||
while (iss >> arg) {
|
||||
parameters.push_back(arg);
|
||||
}
|
||||
|
||||
// Call matching function
|
||||
Func todo = get_function(input);
|
||||
todo(parameters);
|
||||
}
|
||||
|
||||
Func Cli::get_function(std::string input) {
|
||||
for (Command cmd : _commands) {
|
||||
// Split command names from _commands
|
||||
std::vector<std::string> names;
|
||||
boost::split(names, std::get<0>(cmd), boost::is_any_of(", "));
|
||||
|
||||
// Check if input matches any of the names
|
||||
for (std::string name : names) {
|
||||
if (name == input) {
|
||||
return std::get<2>(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default: Basic help command
|
||||
Cli cli;
|
||||
return std::bind(&Cli::default_help, cli, std::placeholders::_1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------- Local Methods --------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
void Cli::default_help(Args args) {
|
||||
print("Try 'help'");
|
||||
}
|
||||
|
||||
void Cli::exit_program(Args args) {
|
||||
_exit = true;
|
||||
}
|
||||
|
||||
void Cli::print_help(Args args) {
|
||||
print("Commands:\n");
|
||||
if (_commands.size() == 0) {
|
||||
print("Expty.");
|
||||
return;
|
||||
}
|
||||
|
||||
// determine max length of first elements
|
||||
int max_size = 0;
|
||||
for (auto& c : _commands) {
|
||||
int len = std::get<0>(c).length();
|
||||
max_size = (len > max_size) ? len : max_size;
|
||||
}
|
||||
|
||||
// print every available command
|
||||
for (auto& c : _commands) {
|
||||
int spaces_to_add = max_size - std::get<0>(c).length();
|
||||
if (spaces_to_add < 0 || spaces_to_add > 50) { throw "Internal fatal error."; }
|
||||
|
||||
|
||||
std::string command_text;
|
||||
command_text += std::get<0>(c);
|
||||
for (int i = 0; i < spaces_to_add; i++) { command_text += " "; }
|
||||
command_text += " " + std::get<1>(c);
|
||||
print(command_text);
|
||||
}
|
||||
}
|
||||
|
||||
void Cli::syn(Args args) {
|
||||
if (!args.empty()) {
|
||||
print("SYN " + args[0]);
|
||||
} else {
|
||||
print("SYN");
|
||||
}
|
||||
}
|
89
source/Configurator.cpp
Normal file
89
source/Configurator.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include "Configurator.hpp"
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/log/utility/setup/common_attributes.hpp>
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//------------------------- Constructor/ Destructor -----------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
Configurator::Configurator(){}
|
||||
|
||||
Configurator* Configurator::_instance = nullptr;
|
||||
|
||||
Configurator* Configurator::instance(){ // Speicherbereinigung
|
||||
static CGuard g;
|
||||
if (!_instance){
|
||||
_instance = new Configurator ();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
Configurator::~Configurator(){}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------- Read Config ----------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
void Configurator::read_config(std::string path,
|
||||
std::string default_path){
|
||||
// Read Standard Config
|
||||
std::ifstream config_file(path);
|
||||
if(config_file.is_open()){
|
||||
config_file >> _config;
|
||||
LOG_INFO << "Config loaded Succesfully" << LOG_END;
|
||||
}
|
||||
else {
|
||||
LOG_INFO << "No Config-File found at " + path << LOG_END;
|
||||
throw std::runtime_error("No Config-File found at " + path);
|
||||
}
|
||||
|
||||
// Read Default Config
|
||||
std::ifstream default_config_file(default_path);
|
||||
if(default_config_file.is_open()){
|
||||
default_config_file >> _default_config;
|
||||
LOG_INFO << "Default Config loaded Succesfully" << LOG_END;
|
||||
}
|
||||
else {
|
||||
LOG_ERROR << "No Config-File found at default path " + default_path << LOG_END;
|
||||
throw std::runtime_error("No Config-File found at deafult path " + default_path);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//-------------------------------- Get-Methods ----------------------------------
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
bool Configurator::entry_exists(const std::string att_name) {
|
||||
bool in_default_config = _default_config.find(att_name) != _default_config.end();
|
||||
bool in_standard_config = _config.find(att_name) != _config.end();
|
||||
return in_default_config || in_standard_config;
|
||||
}
|
||||
|
||||
std::string Configurator::get_config_as_string(const std::string& att_name, bool default_value) {
|
||||
return Configurator::get_value_from_config<std::string>(att_name, default_value);
|
||||
}
|
||||
|
||||
unsigned int Configurator::get_config_as_unsigned_int(const std::string& att_name, bool default_value) {
|
||||
return Configurator::get_value_from_config<int>(att_name, default_value);
|
||||
}
|
||||
|
||||
bool Configurator::get_config_as_bool(const std::string& att_name, bool default_value) {
|
||||
return Configurator::get_value_from_config<bool>(att_name, default_value);
|
||||
}
|
||||
|
||||
float Configurator::get_config_as_float(const std::string& att_name, bool default_value) {
|
||||
return Configurator::get_value_from_config<float>(att_name, default_value);
|
||||
}
|
||||
|
||||
double Configurator::get_config_as_double(const std::string& att_name, bool default_value) {
|
||||
return Configurator::get_value_from_config<double>(att_name, default_value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T Configurator::get_value_from_config(const std::string& att_name, bool default_value) {
|
||||
bool search_in_default_config = !(_config.find(att_name) != _config.end()) || default_value;
|
||||
if (!search_in_default_config) { return _config[att_name]; }
|
||||
return _default_config[att_name];
|
||||
}
|
||||
|
||||
//TODO Mehrdimensionale Attribute suchen
|
64
source/DebugHelper.cpp
Normal file
64
source/DebugHelper.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "DebugHelper.hpp"
|
||||
|
||||
void DebugHelper::hex_dump_human_readable (const char *desc, const void *addr, int len) {
|
||||
int i;
|
||||
unsigned char buff[17];
|
||||
unsigned char *pc = (unsigned char*)addr;
|
||||
|
||||
// Output description if given.
|
||||
if (desc != nullptr)
|
||||
printf ("%s:\n", desc);
|
||||
|
||||
if (len == 0) {
|
||||
printf(" ZERO LENGTH\n");
|
||||
return;
|
||||
}
|
||||
if (len < 0) {
|
||||
printf(" NEGATIVE LENGTH: %i\n",len);
|
||||
return;
|
||||
}
|
||||
|
||||
// Process every byte in the data.
|
||||
for (i = 0; i < len; i++) {
|
||||
// Multiple of 16 means new line (with line offset).
|
||||
|
||||
if ((i % 16) == 0) {
|
||||
// Just don't print ASCII for the zeroth line.
|
||||
if (i != 0)
|
||||
printf (" || %s\n", buff);
|
||||
|
||||
// Output the offset.
|
||||
printf (" %04x ||", i);
|
||||
}
|
||||
|
||||
// Now the hex code for the specific character.
|
||||
printf (" %02x", pc[i]);
|
||||
|
||||
// And store a printable ASCII character for later.
|
||||
if ((pc[i] < 0x20) || (pc[i] > 0x7e))
|
||||
buff[i % 16] = '.';
|
||||
else
|
||||
buff[i % 16] = pc[i];
|
||||
buff[(i % 16) + 1] = '\0';
|
||||
}
|
||||
|
||||
// Pad out last line if not exactly 16 characters.
|
||||
while ((i % 16) != 0) {
|
||||
printf (" ");
|
||||
i++;
|
||||
}
|
||||
|
||||
// And print the final ASCII bit.
|
||||
printf (" || %s\n", buff);
|
||||
}
|
||||
|
||||
void DebugHelper::hex_dump_raw(const void *addr, int len) {
|
||||
unsigned char* pc = (unsigned char*) addr;
|
||||
unsigned char res[2 * len + 1];
|
||||
res[2 * len] = '\0';
|
||||
|
||||
for(unsigned int i = 0; i < len; i++) {
|
||||
printf((char *)res + i * 2, "%02X", pc[i]);
|
||||
}
|
||||
printf ("%s\n", res);
|
||||
}
|
278
source/Initializer.cpp
Normal file
278
source/Initializer.cpp
Normal file
@ -0,0 +1,278 @@
|
||||
|
||||
#include <rte_eal.h>
|
||||
#include <rte_lcore.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "ConfigurationManagement/Configurator.hpp"
|
||||
#include "Definitions.hpp"
|
||||
|
||||
#include "Initializer.hpp"
|
||||
|
||||
rte_mempool* Initializer::init_dpdk(int argc, char** argv,
|
||||
uint16_t& nb_worker_threads) {
|
||||
|
||||
uint8_t hash_key[RSS_HASH_KEY_LENGTH] = {
|
||||
0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
|
||||
0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
|
||||
0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
|
||||
0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
|
||||
};
|
||||
|
||||
rte_eth_conf port_conf = {
|
||||
.rxmode = {.mq_mode = ETH_MQ_RX_RSS,
|
||||
.max_rx_pkt_len = RTE_ETHER_MAX_LEN,
|
||||
.offloads = DEV_RX_OFFLOAD_CHECKSUM},
|
||||
.txmode =
|
||||
{
|
||||
.offloads =
|
||||
(DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM |
|
||||
DEV_TX_OFFLOAD_TCP_CKSUM),
|
||||
},
|
||||
.rx_adv_conf = {.rss_conf =
|
||||
{
|
||||
.rss_key = hash_key,
|
||||
.rss_key_len = RSS_HASH_KEY_LENGTH,
|
||||
.rss_hf =
|
||||
ETH_RSS_IP | ETH_RSS_TCP | ETH_RSS_UDP,
|
||||
}},
|
||||
};
|
||||
|
||||
return init_dpdk_template(NUM_NON_WORKER_THREADS, port_conf, argc, argv,
|
||||
nb_worker_threads);
|
||||
}
|
||||
|
||||
rte_mempool* Initializer::init_dpdk_attacker(int argc, char** argv,
|
||||
uint16_t& nb_worker_threads) {
|
||||
rte_eth_conf port_conf = {
|
||||
.rxmode =
|
||||
{
|
||||
.max_rx_pkt_len = RTE_ETHER_MAX_LEN,
|
||||
},
|
||||
.txmode =
|
||||
{
|
||||
.offloads =
|
||||
(DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM |
|
||||
DEV_TX_OFFLOAD_TCP_CKSUM),
|
||||
},
|
||||
};
|
||||
|
||||
return init_dpdk_template(0, port_conf, argc, argv, nb_worker_threads);
|
||||
}
|
||||
|
||||
rte_mempool* Initializer::init_dpdk_template(uint16_t nb_non_worker_threads,
|
||||
rte_eth_conf port_conf, int argc,
|
||||
char** argv,
|
||||
uint16_t& nb_worker_threads) {
|
||||
int ret;
|
||||
unsigned int nb_ports;
|
||||
uint16_t portid;
|
||||
struct rte_mempool* mbuf_pool;
|
||||
|
||||
// initialize eal
|
||||
ret = rte_eal_init(argc, argv);
|
||||
if (ret < 0) {
|
||||
rte_exit(EXIT_FAILURE, "Cannot init EAL\n");
|
||||
}
|
||||
|
||||
// initialize number of worker threads
|
||||
init_number_threads(nb_non_worker_threads, nb_worker_threads);
|
||||
|
||||
// Check that there is an even number of ports to send/receive on.
|
||||
nb_ports = rte_eth_dev_count_avail();
|
||||
if (nb_ports < 2 || (nb_ports & 1)) {
|
||||
rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");
|
||||
}
|
||||
|
||||
// Creates a new mempool in memory to hold the mbufs.
|
||||
|
||||
// This argument must be lower or equal to RTE_MEMPOOL_CACHE_MAX_SIZE (=
|
||||
// 512)
|
||||
// and n / 1.5. It is advised to choose cache_size to have "n modulo
|
||||
// cache_size
|
||||
// == 0". size from basicfwd program in dpdk examples: 250
|
||||
unsigned cache_size = RTE_MEMPOOL_CACHE_MAX_SIZE;
|
||||
if (cache_size > NUM_MBUF_POOL_ELEMENTS / 1.5) {
|
||||
cache_size = unsigned(NUM_MBUF_POOL_ELEMENTS / 1.5);
|
||||
}
|
||||
|
||||
while (NUM_MBUF_POOL_ELEMENTS % cache_size != 0 || cache_size == 0) {
|
||||
cache_size -= 1;
|
||||
}
|
||||
|
||||
mbuf_pool =
|
||||
rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUF_POOL_ELEMENTS, cache_size,
|
||||
0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
|
||||
|
||||
if (mbuf_pool == nullptr) {
|
||||
rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
|
||||
}
|
||||
|
||||
// Initialize all ports.
|
||||
try {
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
init_port(port_conf, portid, mbuf_pool, nb_worker_threads);
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
rte_exit(EXIT_FAILURE, "Cannot init port %" PRIu16 "\n", portid);
|
||||
}
|
||||
|
||||
return mbuf_pool;
|
||||
}
|
||||
|
||||
void Initializer::init_port(rte_eth_conf port_conf, uint16_t port,
|
||||
struct rte_mempool* mbuf_pool,
|
||||
uint16_t nb_worker_threads) {
|
||||
// the "port" is a port_id which is fetched in the main-function by the
|
||||
// Makro RTE_ETH_FOREACH_DEV The mbuf_pool is needed for queue
|
||||
// initialization
|
||||
|
||||
const uint16_t rx_rings =
|
||||
nb_worker_threads; // rte_lcore_count() many worker threads with an
|
||||
// rx queue on each port
|
||||
const uint16_t tx_rings = rx_rings; // number of rx and tx queues
|
||||
uint16_t nb_rxd = RX_RING_SIZE; // size of queues
|
||||
uint16_t nb_txd = TX_RING_SIZE;
|
||||
int retval; // return value for later procedure calls
|
||||
uint16_t q; // counting variable used for for loop
|
||||
struct rte_eth_dev_info
|
||||
dev_info; // information about NIC, on which pci_slot...
|
||||
struct rte_eth_txconf txconf; // filled later with default value of NIC
|
||||
|
||||
// test if port exists
|
||||
if (!rte_eth_dev_is_valid_port(port))
|
||||
throw std::exception();
|
||||
|
||||
// fill def_info with data
|
||||
rte_eth_dev_info_get(port, &dev_info);
|
||||
// test if queue has offload capacity; if MBUF offload is possible
|
||||
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
|
||||
// |= is not allowed operator. negation of DEV_TX_OFFL...
|
||||
port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE;
|
||||
// test if checksum offloading is possible
|
||||
if (((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) ==
|
||||
DEV_TX_OFFLOAD_TCP_CKSUM) &&
|
||||
((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) ==
|
||||
DEV_TX_OFFLOAD_IPV4_CKSUM)) {
|
||||
std::cout << "ethernet device is checksum offloading capable"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "ethernet device is not checksum offloading capable"
|
||||
<< std::endl;
|
||||
}
|
||||
if (((dev_info.tx_queue_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) ==
|
||||
DEV_TX_OFFLOAD_IPV4_CKSUM) &&
|
||||
((dev_info.tx_queue_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) ==
|
||||
DEV_TX_OFFLOAD_TCP_CKSUM)) {
|
||||
std::cout << "queue is checksum offloading capable" << std::endl;
|
||||
} else {
|
||||
std::cout << "queue is not checksum offloading capable" << std::endl;
|
||||
}
|
||||
|
||||
// Configure the Ethernet device.
|
||||
// address NIC; assign queues; 1 queue per port
|
||||
retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
|
||||
if (retval != 0)
|
||||
throw std::exception();
|
||||
|
||||
retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd);
|
||||
if (retval != 0)
|
||||
throw std::exception();
|
||||
|
||||
// Allocate and set up RX queues per Ethernet port.
|
||||
for (q = 0; q < rx_rings; q++) {
|
||||
retval = rte_eth_rx_queue_setup(
|
||||
port, q, nb_rxd, rte_eth_dev_socket_id(port), NULL, mbuf_pool);
|
||||
if (retval < 0)
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
// initializes tx config for passing it to the queue setup
|
||||
txconf = dev_info.default_txconf;
|
||||
txconf.offloads = port_conf.txmode.offloads;
|
||||
// Allocate and set up 1 TX queue per Ethernet port.
|
||||
for (q = 0; q < tx_rings; q++) {
|
||||
retval = rte_eth_tx_queue_setup(port, q, nb_txd,
|
||||
rte_eth_dev_socket_id(port), &txconf);
|
||||
if (retval < 0)
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
// Start the Ethernet port.
|
||||
retval = rte_eth_dev_start(port);
|
||||
if (retval < 0)
|
||||
throw std::exception();
|
||||
|
||||
// Display the port MAC address.
|
||||
struct rte_ether_addr addr;
|
||||
rte_eth_macaddr_get(port, &addr);
|
||||
printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8
|
||||
" %02" PRIx8 " %02" PRIx8 "\n",
|
||||
port, addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2],
|
||||
addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]);
|
||||
|
||||
// Enable RX in promiscuous mode for the Ethernet device.
|
||||
// TODO: do we need it
|
||||
rte_eth_promiscuous_enable(port);
|
||||
}
|
||||
|
||||
void Initializer::init_number_threads(uint16_t nb_non_worker_threads,
|
||||
uint16_t& nb_worker_threads) {
|
||||
// calculate default value of worker threads
|
||||
uint16_t nb_worker_threads_default =
|
||||
rte_lcore_count() - nb_non_worker_threads;
|
||||
|
||||
// check if value exists or if it has to be calculated
|
||||
if (Configurator::instance()->entry_exists("number_of_worker_threads")) {
|
||||
std::string nb = Configurator::instance()->get_config_as_string(
|
||||
"number_of_worker_threads");
|
||||
|
||||
uint16_t nb_int = 0;
|
||||
|
||||
try { /* value is convertable to an integer */
|
||||
nb_int = std::stoi(nb);
|
||||
} catch (
|
||||
std::exception& e) { /* value is not convertable to an integer */
|
||||
throw std::runtime_error(
|
||||
"The given value at key 'number_of_worker_threads' in "
|
||||
"config.json is not "
|
||||
"convertable to an integer value. Set "
|
||||
"number_of_worker_threads "
|
||||
"either to 'default' or to a value less or equal than " +
|
||||
std::to_string(nb_worker_threads_default) +
|
||||
" and bigger than 0.");
|
||||
}
|
||||
|
||||
if (nb_int > nb_worker_threads_default) {
|
||||
throw std::runtime_error(
|
||||
"The given value at key 'number_of_worker_threads' in "
|
||||
"config.json is out of bounds. Set "
|
||||
"number_of_worker_threads "
|
||||
"either to 'default' or to a value smaller or equal than " +
|
||||
std::to_string(nb_worker_threads_default) +
|
||||
" and bigger than 0.");
|
||||
} else if (nb_int <= 0) {
|
||||
throw std::runtime_error(
|
||||
"The given value at key 'number_of_worker_threads' in "
|
||||
"config.json is out of bounds. "
|
||||
"Either "
|
||||
"set number_of_worker_threads "
|
||||
"to 'default' or set it to a value less or equal than " +
|
||||
std::to_string(nb_worker_threads_default) +
|
||||
" and greater than 0.");
|
||||
}
|
||||
|
||||
nb_worker_threads = nb_int;
|
||||
|
||||
LOG_INFO << "Value " << nb_int
|
||||
<< " for number_of_worker_threads found in config.json. Using "
|
||||
<< nb_int << " worker threads and " << nb_non_worker_threads
|
||||
<< " non worker thread." << LOG_END;
|
||||
} else {
|
||||
nb_worker_threads = nb_worker_threads_default;
|
||||
LOG_INFO << "No value for number_of_worker_threads found in "
|
||||
"config_attacker.json. Using "
|
||||
<< nb_worker_threads << " worker threads and "
|
||||
<< nb_non_worker_threads << " non worker thread." << LOG_END;
|
||||
}
|
||||
}
|
127
source/Threads/DefenseThread.cpp
Normal file
127
source/Threads/DefenseThread.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#include <rte_cycles.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
#include "Definitions.hpp"
|
||||
|
||||
#include "Threads/DefenseThread.hpp"
|
||||
|
||||
// ===== PUBLIC ===== //
|
||||
|
||||
DefenseThread::DefenseThread(
|
||||
MbufContainerReceiving* mbuf_container_from_inside,
|
||||
MbufContainerReceiving* mbuf_container_from_outside,
|
||||
MbufContainerTransmitting* mbuf_container_to_inside,
|
||||
MbufContainerTransmitting* mbuf_container_to_outside)
|
||||
: Thread()
|
||||
, _mbuf_container_from_inside(mbuf_container_from_inside)
|
||||
, _mbuf_container_from_outside(mbuf_container_from_outside)
|
||||
, _mbuf_container_to_inside(mbuf_container_to_inside)
|
||||
, _mbuf_container_to_outside(mbuf_container_to_outside)
|
||||
, _do_treat(false) {
|
||||
|
||||
_treatment =
|
||||
new Treatment(_mbuf_container_to_outside, _mbuf_container_to_inside, 0);
|
||||
}
|
||||
|
||||
int DefenseThread::s_run(void* thread_vptr) {
|
||||
DefenseThread* thread = static_cast<DefenseThread*>(thread_vptr);
|
||||
thread->run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ===== PRIVATE ===== //
|
||||
|
||||
void DefenseThread::run() {
|
||||
/*
|
||||
LOG_INFO << "\nRunning on lcore " << rte_lcore_id() << ". [Ctrl+C to quit]"
|
||||
<< LOG_END;
|
||||
*/
|
||||
|
||||
// Run until the application is quit or killed.
|
||||
while (likely(_quit == false)) {
|
||||
|
||||
// std::cout << _do_treat << std::endl;
|
||||
|
||||
// continue if no packets are received
|
||||
int mbufs_from_inside = _mbuf_container_from_inside->poll_mbufs();
|
||||
/* if (mbufs_from_inside != 0) {
|
||||
BOOST_LOG_TRIVIAL(info)
|
||||
<< "Number of packets received from inside: "
|
||||
<< mbufs_from_inside;
|
||||
} */
|
||||
bool keep = true;
|
||||
for (int i = 0; i < mbufs_from_inside; ++i) {
|
||||
rte_mbuf* mbuf = _mbuf_container_from_inside->get_mbuf_at_index(i);
|
||||
|
||||
if (PacketInfoCreator::is_ipv4_tcp(mbuf) == true &&
|
||||
_do_treat == true) {
|
||||
PacketInfoIpv4Tcp* pkt_info = new PacketInfoIpv4Tcp(mbuf);
|
||||
keep = _treatment->treat_packets_to_outside(pkt_info);
|
||||
if (keep == false) {
|
||||
// delete PacketInfo
|
||||
delete pkt_info;
|
||||
}
|
||||
} else {
|
||||
// fwd
|
||||
// std::cout << _do_treat;
|
||||
_mbuf_container_to_outside->add_mbuf(mbuf);
|
||||
}
|
||||
}
|
||||
|
||||
_mbuf_container_to_inside->send_mbufs();
|
||||
_mbuf_container_to_outside->send_mbufs();
|
||||
|
||||
// _mbuf_container_to_inside->send_mbufs();
|
||||
// _mbuf_container_to_outside->send_mbufs();
|
||||
|
||||
// for mbuf in pktsFromOutside
|
||||
// pktInfoCreator::determinePacketType without creating a pktinfo
|
||||
// create packetInfo with obtained type
|
||||
// if tcp: treat
|
||||
// else: fwd
|
||||
// destroy pktInfo
|
||||
// Pakete von innen, auch die selbsterzeugten bevorzugen
|
||||
|
||||
// continue if no packets are received
|
||||
|
||||
int mbufs_from_outside = _mbuf_container_from_outside->poll_mbufs();
|
||||
/* if (mbufs_from_outside != 0) {
|
||||
BOOST_LOG_TRIVIAL(info)
|
||||
<< "Number of packets received from outside: "
|
||||
<< mbufs_from_outside;
|
||||
} */
|
||||
for (int i = 0; i < mbufs_from_outside; ++i) {
|
||||
rte_mbuf* mbuf = _mbuf_container_from_outside->get_mbuf_at_index(i);
|
||||
|
||||
if (PacketInfoCreator::is_ipv4_tcp(mbuf) == true &&
|
||||
_do_treat == true) {
|
||||
PacketInfoIpv4Tcp* pkt_info = new PacketInfoIpv4Tcp(mbuf);
|
||||
keep = _treatment->treat_packets_to_inside(
|
||||
static_cast<PacketInfoIpv4Tcp*>(pkt_info));
|
||||
if (keep == false) {
|
||||
// delete PacketInfo
|
||||
delete pkt_info;
|
||||
}
|
||||
} else {
|
||||
// std::cout << _do_treat;
|
||||
_mbuf_container_to_inside->add_mbuf(mbuf);
|
||||
}
|
||||
}
|
||||
/* if (_mbuf_container_to_inside->get_number_of_mbufs() > 0) {
|
||||
BOOST_LOG_TRIVIAL(info)
|
||||
<< "Number of packets sent to inside: "
|
||||
<< _mbuf_container_to_inside->get_number_of_mbufs();
|
||||
}
|
||||
if (_mbuf_container_to_outside->get_number_of_mbufs() > 0) {
|
||||
BOOST_LOG_TRIVIAL(info)
|
||||
<< "Number of packets sent to outside: "
|
||||
<< _mbuf_container_to_outside->get_number_of_mbufs();
|
||||
} */
|
||||
|
||||
_mbuf_container_to_inside->send_mbufs();
|
||||
_mbuf_container_to_outside->send_mbufs();
|
||||
}
|
||||
|
||||
_running = false;
|
||||
}
|
55
source/Threads/StatisticsThread.cpp
Normal file
55
source/Threads/StatisticsThread.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "Threads/StatisticsThread.hpp"
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------- StatisticsThread -----------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
rte_ring* StatisticsThread::_s_queue[16];
|
||||
|
||||
int StatisticsThread::s_run(void* thread_vptr) {
|
||||
StatisticsThread* thread = static_cast<StatisticsThread*>(thread_vptr);
|
||||
thread->run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StatisticsThread::run() {
|
||||
// Check for new statistics in each rte_ring
|
||||
while (_quit != false) {
|
||||
for (rte_ring* ring : _s_queue) {
|
||||
// Get stats from queue and update them
|
||||
Stats* out;
|
||||
rte_ring_dequeue(ring, (void**)&out);
|
||||
|
||||
if (true) { // \TODO test if empty
|
||||
update_statistics(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StatisticsThread::enqueue_statistics(int& id, Stats* new_stats) {
|
||||
// enqueue statistics
|
||||
rte_ring* ring = _s_queue[id];
|
||||
rte_ring_enqueue(ring, new_stats);
|
||||
}
|
||||
|
||||
Stats* StatisticsThread::_s_stats;
|
||||
|
||||
void StatisticsThread::update_statistics(Stats* new_stats) {
|
||||
//_s_stats += new_stats;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------- Stats ----------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
Stats* Stats::operator+=(const Stats* new_stats) {
|
||||
this->attacks += new_stats->attacks;
|
||||
this->bytes += new_stats->bytes;
|
||||
this->dropped += new_stats->dropped;
|
||||
this->packets += new_stats->packets;
|
||||
this->work_time += new_stats->work_time;
|
||||
this->syn_level += new_stats->syn_level;
|
||||
|
||||
return this;
|
||||
}
|
5
source/Threads/Thread.cpp
Normal file
5
source/Threads/Thread.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "Threads/Thread.hpp"
|
||||
|
||||
Thread::Thread() : _quit(false) {}
|
||||
|
||||
void Thread::quit() { _quit = true; }
|
3
source/capture/meson.build
Normal file
3
source/capture/meson.build
Normal file
@ -0,0 +1,3 @@
|
||||
message(' executable: capture ')
|
||||
sources = files('pkt-capture.cpp')
|
||||
message(' ------------------------------ ')
|
240
source/capture/pkt-capture.cpp
Normal file
240
source/capture/pkt-capture.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
/**
|
||||
* @file pkt-capture.cpp
|
||||
*
|
||||
* @brief Capture packets with dpdk
|
||||
*
|
||||
**/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <rte_cycles.h>
|
||||
#include <rte_eal.h>
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_mbuf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define RX_RING_SIZE 1024
|
||||
#define TX_RING_SIZE 1024
|
||||
|
||||
#define NUM_MBUFS 8191
|
||||
#define MBUF_CACHE_SIZE 250
|
||||
#define BURST_SIZE 32
|
||||
|
||||
/**
|
||||
* @brief set port configuration
|
||||
*
|
||||
*/
|
||||
|
||||
// "Portconfig", given by DPDK.
|
||||
// this struct is a data type with which you have to configure the NIC
|
||||
// first you create the configuration file which later can be applicated to the
|
||||
// NIC
|
||||
static const struct rte_eth_conf port_conf_default = {
|
||||
// TODO: what does this dot mean?
|
||||
// the structure of this config-struct is given by the DPDK itself
|
||||
.rxmode =
|
||||
{
|
||||
.max_rx_pkt_len = RTE_ETHER_MAX_LEN,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief init NIC
|
||||
*
|
||||
* get the NIC by port identifier and bind it to dpdk with given mempool.
|
||||
* Setting up TX/RX queues per ethernet port. Then starting the device and
|
||||
* printing MAC address
|
||||
*
|
||||
* @param port set port identifier to use
|
||||
* @param mbuf_pool set mempool of dpdk to use
|
||||
* @return 0 or error code
|
||||
*/
|
||||
static inline int port_init(uint16_t port, struct rte_mempool* mbuf_pool) {
|
||||
// the "port" is a port_id which is fetched in the main-function by the
|
||||
// Makro RTE_ETH_FOREACH_DEV The mbuf_pool is needed for queue
|
||||
// initialisation
|
||||
|
||||
// config
|
||||
struct rte_eth_conf port_conf = port_conf_default;
|
||||
|
||||
// number of rx and tx queues (i guess)
|
||||
const uint16_t rx_rings = 1, tx_rings = 1;
|
||||
// size of queues
|
||||
uint16_t nb_rxd = RX_RING_SIZE;
|
||||
uint16_t nb_txd = TX_RING_SIZE;
|
||||
// return value for later procedure calls
|
||||
int retval;
|
||||
// counting variable used for for loop
|
||||
uint16_t q;
|
||||
// information about NIC, on which pci_slot...
|
||||
struct rte_eth_dev_info dev_info;
|
||||
// filled later with default value of NIC
|
||||
// TODO: research in doku!
|
||||
struct rte_eth_txconf txconf;
|
||||
|
||||
// does port exist?
|
||||
if (!rte_eth_dev_is_valid_port(port))
|
||||
return -1;
|
||||
|
||||
// fill def_info with data
|
||||
rte_eth_dev_info_get(port, &dev_info);
|
||||
// does queue have offload capacity? Is MBUF offload possible (bool)?
|
||||
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
|
||||
// |= is not allowed operator. negation of DEV_TX_OFFL...
|
||||
port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE;
|
||||
|
||||
/* Configure the Ethernet device. */
|
||||
// address NIC; assign queues; 1 queue per port
|
||||
retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
|
||||
if (retval != 0)
|
||||
return retval;
|
||||
|
||||
// nb_rxd ist size of queue (i guess)
|
||||
retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd);
|
||||
if (retval != 0)
|
||||
return retval;
|
||||
|
||||
/* Allocate and set up 1 RX queue per Ethernet port. */
|
||||
// TODO: This may be the key to RSS
|
||||
for (q = 0; q < rx_rings; q++) {
|
||||
retval = rte_eth_rx_queue_setup(
|
||||
port, q, nb_rxd, rte_eth_dev_socket_id(port), NULL, mbuf_pool);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
}
|
||||
|
||||
// initializes tx config for passing it to the queue setup
|
||||
txconf = dev_info.default_txconf;
|
||||
txconf.offloads = port_conf.txmode.offloads;
|
||||
/* Allocate and set up 1 TX queue per Ethernet port. */
|
||||
for (q = 0; q < tx_rings; q++) {
|
||||
retval = rte_eth_tx_queue_setup(port, q, nb_txd,
|
||||
rte_eth_dev_socket_id(port), &txconf);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Start the Ethernet port. */
|
||||
// see doc
|
||||
retval = rte_eth_dev_start(port);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
/* Display the port MAC address. */
|
||||
struct rte_ether_addr addr;
|
||||
rte_eth_macaddr_get(port, &addr);
|
||||
printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8
|
||||
" %02" PRIx8 " %02" PRIx8 "\n",
|
||||
port, addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2],
|
||||
addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]);
|
||||
|
||||
/* Enable RX in promiscuous mode for the Ethernet device. */
|
||||
// see doc
|
||||
// do we need it?
|
||||
rte_eth_promiscuous_enable(port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reading from input and writing to output
|
||||
*
|
||||
* This is the main thread that does the work, reading from an input port and
|
||||
* writing to an output port.
|
||||
*/
|
||||
static __attribute__((noreturn)) void lcore_main(void) {
|
||||
// noreturn extension to void
|
||||
// TODO: see doc!
|
||||
uint16_t port;
|
||||
|
||||
/*
|
||||
* Check that the port is on the same NUMA node as the polling thread
|
||||
* for best performance.
|
||||
*/
|
||||
RTE_ETH_FOREACH_DEV(port) {
|
||||
// Ignore this, if we dont use NUMA
|
||||
if (rte_eth_dev_socket_id(port) > 0 &&
|
||||
rte_eth_dev_socket_id(port) != (int)rte_socket_id())
|
||||
printf("WARNING, port %u is on remote NUMA node to "
|
||||
"polling thread.\n\tPerformance will "
|
||||
"not be optimal.\n",
|
||||
port);
|
||||
}
|
||||
|
||||
printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n", rte_lcore_id());
|
||||
|
||||
/* Run until the application is quit or killed. */
|
||||
for (;;) {
|
||||
/*
|
||||
* Receive packets on a port and forward them on the paired
|
||||
* port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc.
|
||||
*/
|
||||
RTE_ETH_FOREACH_DEV(port) {
|
||||
|
||||
/* Get burst of RX packets, from first port of pair. */
|
||||
// poll packets
|
||||
struct rte_mbuf* bufs[BURST_SIZE];
|
||||
const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE);
|
||||
|
||||
if (unlikely(nb_rx == 0))
|
||||
continue;
|
||||
|
||||
/* Send burst of TX packets, to second port of pair. */
|
||||
const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0, bufs, nb_rx);
|
||||
|
||||
/* Free any unsent packets. */
|
||||
if (unlikely(nb_tx < nb_rx)) {
|
||||
uint16_t buf;
|
||||
for (buf = nb_tx; buf < nb_rx; buf++)
|
||||
rte_pktmbuf_free(bufs[buf]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief init and call per lcore
|
||||
*
|
||||
* The main function, which does initialization and calls the per-lcore
|
||||
* functions.
|
||||
*/
|
||||
int main(int argc, char* argv[]) {
|
||||
struct rte_mempool* mbuf_pool;
|
||||
unsigned nb_ports;
|
||||
uint16_t portid;
|
||||
|
||||
/* Initialize the Environment Abstraction Layer (EAL). */
|
||||
int ret = rte_eal_init(argc, argv);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
|
||||
|
||||
argc -= ret;
|
||||
argv += ret;
|
||||
|
||||
/* Check that there is an even number of ports to send/receive on. */
|
||||
nb_ports = rte_eth_dev_count_avail();
|
||||
if (nb_ports < 2 || (nb_ports & 1))
|
||||
rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");
|
||||
|
||||
/* Creates a new mempool in memory to hold the mbufs. */
|
||||
mbuf_pool = rte_pktmbuf_pool_create(
|
||||
"MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0,
|
||||
RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
|
||||
|
||||
if (mbuf_pool == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
|
||||
|
||||
/* Initialize all ports. */
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
if (port_init(portid, mbuf_pool) != 0)
|
||||
rte_exit(EXIT_FAILURE, "Cannot init port %" PRIu16 "\n", portid);
|
||||
}
|
||||
|
||||
if (rte_lcore_count() > 1)
|
||||
printf("\nWARNING: Too many lcores enabled. Only 1 used.\n");
|
||||
|
||||
/* Call lcore_main on the master core only. */
|
||||
lcore_main();
|
||||
|
||||
return 0;
|
||||
}
|
187
source/main.cpp
Normal file
187
source/main.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include "ConfigurationManagement/Configurator.hpp"
|
||||
#include "Initializer.hpp"
|
||||
#include "PacketDissection/PacketContainer.hpp"
|
||||
#include "Threads/DefenseThread.hpp"
|
||||
|
||||
void handle_quit(int signum);
|
||||
void terminate(DefenseThread** thread_arr, uint16_t nb_worker_threads);
|
||||
|
||||
bool quit = false;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// ===== INITIALIZE ===== //
|
||||
// Register signal and signal handler
|
||||
signal(SIGINT, handle_quit);
|
||||
|
||||
Configurator::instance()->read_config("../config.json");
|
||||
|
||||
Initializer* init = new Initializer();
|
||||
unsigned int lcore_id;
|
||||
uint16_t inside_port = 1;
|
||||
uint16_t outside_port = 0;
|
||||
uint16_t nb_worker_threads = 0;
|
||||
|
||||
struct rte_mempool* mbuf_pool =
|
||||
init->init_dpdk(argc, argv, nb_worker_threads);
|
||||
|
||||
// create thread objects
|
||||
DefenseThread* thread_arr[nb_worker_threads];
|
||||
MbufContainerReceiving* pkt_containers_from_outside[nb_worker_threads];
|
||||
MbufContainerReceiving* pkt_containers_from_inside[nb_worker_threads];
|
||||
MbufContainerTransmitting* pkt_containers_to_inside[nb_worker_threads];
|
||||
MbufContainerTransmitting* pkt_containers_to_outside[nb_worker_threads];
|
||||
|
||||
for (int i = 0; i < nb_worker_threads; i++) {
|
||||
|
||||
pkt_containers_from_outside[i] =
|
||||
new MbufContainerReceiving(mbuf_pool, outside_port, i);
|
||||
pkt_containers_from_inside[i] =
|
||||
new MbufContainerReceiving(mbuf_pool, inside_port, i);
|
||||
pkt_containers_to_inside[i] =
|
||||
new MbufContainerTransmitting(mbuf_pool, inside_port, i);
|
||||
pkt_containers_to_outside[i] =
|
||||
new MbufContainerTransmitting(mbuf_pool, outside_port, i);
|
||||
|
||||
thread_arr[i] = new DefenseThread(
|
||||
pkt_containers_from_inside[i], pkt_containers_from_outside[i],
|
||||
pkt_containers_to_inside[i], pkt_containers_to_outside[i]);
|
||||
}
|
||||
|
||||
// start each thread on an own lcore
|
||||
lcore_id = rte_lcore_id();
|
||||
|
||||
for (int i = 0; i < nb_worker_threads; ++i) {
|
||||
lcore_id = rte_get_next_lcore(lcore_id, true, true);
|
||||
|
||||
rte_eal_remote_launch(
|
||||
static_cast<lcore_function_t*>(DefenseThread::s_run), thread_arr[i],
|
||||
lcore_id);
|
||||
}
|
||||
|
||||
/*
|
||||
uint64_t hz = rte_get_tsc_hz();
|
||||
u_int64_t cycles = rte_get_tsc_cycles();
|
||||
u_int64_t old_cycles = cycles;
|
||||
while (likely(quit == false)) {
|
||||
cycles = rte_get_tsc_cycles();
|
||||
if (cycles - old_cycles > 64 * hz) {
|
||||
Treatment::s_increment_timestamp();
|
||||
old_cycles = cycles;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// =================== START CLI ==================== //
|
||||
|
||||
std::string input = "";
|
||||
const std::string NAME = "aegis";
|
||||
|
||||
enum State { RUNNING, IDLE };
|
||||
State state = IDLE;
|
||||
|
||||
while (input != "exit") {
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << NAME << "> " << std::flush;
|
||||
std::cin >> input;
|
||||
std::cout << std::endl;
|
||||
|
||||
if (input == "start") {
|
||||
if (state == IDLE) {
|
||||
|
||||
for (int i = 0; i < nb_worker_threads; ++i) {
|
||||
thread_arr[i]->start_treat();
|
||||
}
|
||||
|
||||
state = RUNNING;
|
||||
|
||||
} else { // state == RUNNING
|
||||
std::cout << "Cannot start if program is already running."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
} else if (input == "stop") {
|
||||
if (state == IDLE) {
|
||||
std::cout << "Cannot stop if program is not running."
|
||||
<< std::endl;
|
||||
|
||||
} else { // state == RUNNING
|
||||
|
||||
for (int i = 0; i < nb_worker_threads; ++i) {
|
||||
thread_arr[i]->stop_treat();
|
||||
}
|
||||
|
||||
state = IDLE;
|
||||
}
|
||||
|
||||
} else if (input == "exit") {
|
||||
|
||||
// do nothing; while loop stops
|
||||
|
||||
} else if (input == "help" || input == "h") {
|
||||
std::cout << "start\tstart " << NAME << std::endl
|
||||
<< "stop\tstop " << NAME << std::endl
|
||||
<< "help, h\tprint commands " << std::endl
|
||||
<< "exit\texit " << NAME << std::endl
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "Command unknown. Try 'h' or 'help'." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== END CLI ==================== //
|
||||
|
||||
// ===== TERMINATE ===== //
|
||||
terminate(thread_arr, nb_worker_threads);
|
||||
|
||||
// destruct objects on heap
|
||||
for (int i = 0; i < nb_worker_threads; ++i) {
|
||||
delete thread_arr[i];
|
||||
thread_arr[i] = nullptr;
|
||||
|
||||
delete pkt_containers_from_inside[i];
|
||||
pkt_containers_from_inside[i] = nullptr;
|
||||
|
||||
delete pkt_containers_from_outside[i];
|
||||
pkt_containers_from_outside[i] = nullptr;
|
||||
|
||||
delete pkt_containers_to_inside[i];
|
||||
pkt_containers_to_inside[i] = nullptr;
|
||||
|
||||
delete pkt_containers_to_inside[i];
|
||||
pkt_containers_to_inside[i] = nullptr;
|
||||
}
|
||||
|
||||
delete init;
|
||||
init = nullptr;
|
||||
|
||||
// cleanup eal
|
||||
rte_eal_mp_wait_lcore();
|
||||
rte_eal_cleanup();
|
||||
|
||||
// YOU ARE TERMINATED
|
||||
}
|
||||
|
||||
void handle_quit(int signum) {
|
||||
// do nothing
|
||||
// quit = true;
|
||||
}
|
||||
//
|
||||
|
||||
void terminate(DefenseThread** thread_arr, uint16_t nb_worker_threads) {
|
||||
std::cout << "\nterminating..." << std::endl;
|
||||
|
||||
for (int i = 0; i < nb_worker_threads; ++i) {
|
||||
thread_arr[i]->quit();
|
||||
}
|
||||
|
||||
// wait for threads to end
|
||||
for (int i = 0; i < nb_worker_threads - 1; ++i) {
|
||||
while (thread_arr[i]->is_running()) {
|
||||
// wait
|
||||
}
|
||||
}
|
||||
}
|
21
source/meson.build
Normal file
21
source/meson.build
Normal file
@ -0,0 +1,21 @@
|
||||
sources = [
|
||||
'source/main.cpp',
|
||||
'source/Initializer.cpp',
|
||||
'source/DebugHelper.cpp',
|
||||
'source/ConfigurationManagement/Configurator.cpp',
|
||||
'source/Threads/DefenseThread.cpp',
|
||||
'source/Cli.cpp',
|
||||
#'source/Threads/StatisticsThread.cpp',
|
||||
]
|
||||
|
||||
# Attacker
|
||||
sources_attack = [
|
||||
'source/Attacker/main.cpp'
|
||||
]
|
||||
|
||||
foreach string : sources
|
||||
if string != 'source/main.cpp'
|
||||
sources_attack += [string]
|
||||
endif
|
||||
endforeach
|
||||
|
10
subprojects/catch2.wrap
Normal file
10
subprojects/catch2.wrap
Normal file
@ -0,0 +1,10 @@
|
||||
[wrap-file]
|
||||
directory = Catch2-2.11.1
|
||||
|
||||
source_url = https://github.com/catchorg/Catch2/archive/v2.11.1.zip
|
||||
source_filename = Catch2-2.11.1.zip
|
||||
source_hash = da97f7acd94ea6e1f26aae4a6edf5d10d020666efaec22781f6ac42371569d2c
|
||||
|
||||
patch_url = https://wrapdb.mesonbuild.com/v1/projects/catch2/2.11.1/1/get_zip
|
||||
patch_filename = catch2-2.11.1-1-wrap.zip
|
||||
patch_hash = b7b46c5dd5092d5bce6fa9e88c7ae29e089adaba2f972288c9ed665e7a589650
|
67
subprojects/gui/gui.py
Normal file
67
subprojects/gui/gui.py
Normal file
@ -0,0 +1,67 @@
|
||||
import sys
|
||||
from os import path
|
||||
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
|
||||
from PyQt5.QtCore import QTimer
|
||||
from PyQt5.QtGui import QPixmap
|
||||
|
||||
WINDOW_TITLE = "Attack Status"
|
||||
POSITION = [0, 0]
|
||||
SIZE = [912, 513]
|
||||
|
||||
FOLDER = ""
|
||||
if not path.isfile(FOLDER + "gui.py"):
|
||||
FOLDER = "subprojects/gui/"
|
||||
PATH_ATTACK_FILE = "/home/guru/is_attacking/attacking" # Location of 'attacking'-file (interface)
|
||||
PATH_SMILEY = FOLDER + "img/smiley.png"
|
||||
PATH_SKULL = [FOLDER + "img/skull_black.png", FOLDER + "img/skull_orange.png"]
|
||||
|
||||
DELTA_TIME = 300
|
||||
GREEN = "#7cb342"
|
||||
ORANGE = "#e65100"
|
||||
BLACK = "#000000"
|
||||
|
||||
class Window(QWidget):
|
||||
run = True # Run/stop loop
|
||||
inverted = True # Use inverted colors
|
||||
|
||||
def __init__(self):
|
||||
# Initialize window
|
||||
super().__init__()
|
||||
self.setWindowTitle(WINDOW_TITLE)
|
||||
self.setGeometry(POSITION[0], POSITION[1], SIZE[0], SIZE[1])
|
||||
|
||||
# Show image
|
||||
self.image = QLabel(self)
|
||||
self.loop()
|
||||
self.show()
|
||||
|
||||
def loop(self):
|
||||
# Start timer
|
||||
if self.run:
|
||||
QTimer.singleShot(DELTA_TIME, self.loop)
|
||||
|
||||
# Update image
|
||||
if path.isfile(PATH_ATTACK_FILE):
|
||||
self.inverted = not self.inverted
|
||||
if self.inverted:
|
||||
self.update_image(PATH_SKULL[1], BLACK)
|
||||
else:
|
||||
self.update_image(PATH_SKULL[0], ORANGE)
|
||||
else:
|
||||
self.update_image(PATH_SMILEY, GREEN)
|
||||
|
||||
def update_image(self, image_path, background_color):
|
||||
self.image.setPixmap(QPixmap(image_path))
|
||||
self.setStyleSheet("background-color: " + background_color)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run app until closed
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
app.exec_()
|
||||
|
||||
# Terminate
|
||||
window.run = False
|
||||
sys.exit()
|
||||
|
BIN
subprojects/gui/img/skull_black.png
Normal file
BIN
subprojects/gui/img/skull_black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
BIN
subprojects/gui/img/skull_orange.png
Normal file
BIN
subprojects/gui/img/skull_orange.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
BIN
subprojects/gui/img/smiley.png
Normal file
BIN
subprojects/gui/img/smiley.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
BIN
subprojects/packagecache/Catch2-2.11.1.zip
Normal file
BIN
subprojects/packagecache/Catch2-2.11.1.zip
Normal file
Binary file not shown.
BIN
subprojects/packagecache/catch2-2.11.1-1-wrap.zip
Normal file
BIN
subprojects/packagecache/catch2-2.11.1-1-wrap.zip
Normal file
Binary file not shown.
37
test/Attacker/Attacker_test.cpp
Normal file
37
test/Attacker/Attacker_test.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include <rte_cycles.h>
|
||||
|
||||
TEST_CASE("tsc timer", "[]") {
|
||||
// count and print seconds since test started
|
||||
// stop at 30 seconds
|
||||
// const std::string clear(100, '\n');
|
||||
const uint64_t MAX_SECONDS = 30;
|
||||
uint64_t cycles_old = 0;
|
||||
uint64_t cycles = 0;
|
||||
uint64_t hz = rte_get_tsc_hz();
|
||||
uint64_t seconds = 0;
|
||||
uint64_t delta_t = 0;
|
||||
|
||||
// print initial message
|
||||
std::cout << "cycles : " << cycles << "\t"
|
||||
<< "hz : " << hz << "\t"
|
||||
<< "seconds : " << seconds << "\t" << std::endl;
|
||||
|
||||
while (seconds < MAX_SECONDS) {
|
||||
cycles_old = cycles;
|
||||
cycles = rte_get_tsc_cycles();
|
||||
hz = rte_get_tsc_hz();
|
||||
|
||||
// calculate
|
||||
delta_t = uint64_t(1 / hz * (cycles - cycles_old));
|
||||
seconds += delta_t;
|
||||
|
||||
// print
|
||||
// std::cout << clear;
|
||||
std::cout << "cycles : " << cycles << "\t"
|
||||
<< "hz : " << hz << "\t"
|
||||
<< "seconds : " << seconds << "\t" << std::endl;
|
||||
}
|
||||
}
|
1
test/Attacker/meson.build
Normal file
1
test/Attacker/meson.build
Normal file
@ -0,0 +1 @@
|
||||
Attacker_sources = ['test/Attacker/Attacker_test.cpp']
|
16
test/Attacker/namespace-alice.sh
Normal file
16
test/Attacker/namespace-alice.sh
Normal file
@ -0,0 +1,16 @@
|
||||
# create network namespace aegisns
|
||||
ip netns add AEGISNS
|
||||
# assing interface enp4s0f0 to aegisns
|
||||
ip link set enp5s0f0 netns AEGISNS
|
||||
# assing ip to interface
|
||||
ip netns exec AEGISNS ip add add dev enp5s0f0 10.0.0.1/24
|
||||
# bring the link up
|
||||
ip netns exec AEGISNS ip link set dev enp5s0f0 up
|
||||
# add the standard route for the interface
|
||||
ip netns exec AEGISNS route add default gw 10.0.0.2 enp5s0f0
|
||||
# show wether the project has been successful
|
||||
ip netns exec AEGISNS ifconfig
|
||||
ip netns exec AEGISNS route
|
||||
|
||||
|
||||
|
14
test/Attacker/namespace-bob.sh
Executable file
14
test/Attacker/namespace-bob.sh
Executable file
@ -0,0 +1,14 @@
|
||||
# create network namespace aegisns
|
||||
ip netns add AEGISNS
|
||||
# assing interface enp4s0f0 to aegisns
|
||||
ip link set enp4s0f0 netns AEGISNS
|
||||
# assing ip to interface
|
||||
ip netns exec AEGISNS ip add add dev enp4s0f0 10.0.0.2/24
|
||||
# bring the link up
|
||||
ip netns exec AEGISNS ip link set dev enp4s0f0 up
|
||||
# add the standard route for the interface
|
||||
ip netns exec AEGISNS route add default gw 10.0.0.1 enp4s0f0
|
||||
# show wether the project has been successful
|
||||
ip netns exec AEGISNS ifconfig
|
||||
ip netns exec AEGISNS route
|
||||
|
52
test/ConfigurationManagement/Configurator_test.cpp
Normal file
52
test/ConfigurationManagement/Configurator_test.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "ConfigurationManagement/Configurator.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
TEST_CASE("Json Datei einlesen", "[]") {
|
||||
|
||||
REQUIRE_NOTHROW(Configurator::instance()->read_config(
|
||||
"../test/ConfigurationManagement/config_test.json"));
|
||||
|
||||
REQUIRE(Configurator::instance()->get_config_as_bool("BOOLEAN") == true);
|
||||
REQUIRE(Configurator::instance()->get_config_as_unsigned_int(
|
||||
"UNSIGNED_INT") == 42);
|
||||
REQUIRE(Configurator::instance()->get_config_as_string("STRING") ==
|
||||
"Hello World.");
|
||||
REQUIRE(Configurator::instance()->get_config_as_float("FLOAT") == 1.337f);
|
||||
REQUIRE(Configurator::instance()->get_config_as_double("DOUBLE") == -3.001);
|
||||
}
|
||||
|
||||
TEST_CASE("nicht existierende Json-Datei", "[]") {
|
||||
REQUIRE_THROWS(Configurator::instance()->read_config("non-existent.json"));
|
||||
REQUIRE_THROWS(Configurator::instance()->read_config("non-existent.json",
|
||||
"typo.json"));
|
||||
}
|
||||
|
||||
TEST_CASE("Boost-Beispiel") {
|
||||
LOG_INFO << "Dies ist eine Info Message" << LOG_END;
|
||||
LOG_WARNING << "Dies ist eine Warn-Nachricht" << LOG_END;
|
||||
}
|
||||
|
||||
TEST_CASE("Entry does (not) exist") {
|
||||
REQUIRE_NOTHROW(Configurator::instance()->read_config(
|
||||
"../test/ConfigurationManagement/config_test.json",
|
||||
"../test/ConfigurationManagement/default_config_test.json"));
|
||||
|
||||
REQUIRE(Configurator::instance()->entry_exists("fhk4bhf1mx0f") == false);
|
||||
REQUIRE(Configurator::instance()->entry_exists("STRING") == true);
|
||||
REQUIRE(Configurator::instance()->entry_exists("X") == true);
|
||||
}
|
||||
|
||||
TEST_CASE("Default Config") {
|
||||
REQUIRE_NOTHROW(Configurator::instance()->read_config(
|
||||
"../test/ConfigurationManagement/config_test.json",
|
||||
"../test/ConfigurationManagement/default_config_test.json"));
|
||||
|
||||
REQUIRE(Configurator::instance()->get_config_as_unsigned_int(
|
||||
"UNSIGNED_INT") == 42);
|
||||
REQUIRE(Configurator::instance()->get_config_as_unsigned_int("UNSIGNED_INT",
|
||||
true) == 666);
|
||||
REQUIRE(Configurator::instance()->get_config_as_string("X") == "80085");
|
||||
}
|
7
test/ConfigurationManagement/config_test.json
Normal file
7
test/ConfigurationManagement/config_test.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"STRING" : "Hello World.",
|
||||
"BOOLEAN" : true,
|
||||
"UNSIGNED_INT" : 42,
|
||||
"FLOAT" : 1.337,
|
||||
"DOUBLE" : -3.001
|
||||
}
|
4
test/ConfigurationManagement/default_config_test.json
Normal file
4
test/ConfigurationManagement/default_config_test.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"UNSIGNED_INT": 666,
|
||||
"X": "80085"
|
||||
}
|
9
test/Initializer/default_config_test.json
Normal file
9
test/Initializer/default_config_test.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"STRING" : "Hello World.",
|
||||
"BOOLEAN" : true,
|
||||
"UNSIGNED_INT" : 666,
|
||||
"FLOAT" : 1.337,
|
||||
"DOUBLE" : -3.001,
|
||||
"X" : "80085",
|
||||
"Y" : "Hi"
|
||||
}
|
49
test/Initializer_test.cpp
Normal file
49
test/Initializer_test.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
#include "ConfigurationManagement/Configurator.hpp"
|
||||
|
||||
TEST_CASE("Calculate number of threads", "[]") {
|
||||
/*
|
||||
Configurator::instance()->read_config("../test/config.json");
|
||||
|
||||
uint16_t nb_worker_threads = 0;
|
||||
// calculate default value of worker threads
|
||||
uint16_t nb_worker_threads_default = 12;
|
||||
|
||||
// get number of threads from config
|
||||
std::string nb = Configurator::instance()->get_config_as_string(
|
||||
"number_of_worker_threads");
|
||||
|
||||
if (nb == "default") {
|
||||
nb_worker_threads = nb_worker_threads_default;
|
||||
}
|
||||
else {
|
||||
|
||||
uint16_t nb_int = std::stoi(nb);
|
||||
|
||||
REQUIRE(nb_int == 11);
|
||||
|
||||
if (nb_int > nb_worker_threads_default) {
|
||||
throw std::runtime_error(
|
||||
"number_of_worker_threads is greater than the maximal possible "
|
||||
"number of worker threads. Either s number_of_worker_threads "
|
||||
"to 'default' or set it to a valu smaller or equal than " +
|
||||
std::to_string(nb_worker_threads_default) + " and bigger than 0.");
|
||||
} else if (nb_int <= 0) {
|
||||
throw std::runtime_error(
|
||||
"number_of_worker_threads is greater than or equal 0. Either "
|
||||
" set number_of_worker_threads "
|
||||
" to 'default' or set it to a value less or equal than " +
|
||||
std::to_string(nb_worker_threads_default) + " and greater than 0.");
|
||||
}
|
||||
|
||||
nb_worker_threads = nb_int;
|
||||
}
|
||||
|
||||
REQUIRE(nb_worker_threads <= nb_worker_threads_default);
|
||||
REQUIRE(nb_worker_threads_default > 0);
|
||||
REQUIRE(nb_worker_threads_default == 11);
|
||||
*/
|
||||
}
|
292
test/PacketDissection/PacketContainer_test.cpp
Normal file
292
test/PacketDissection/PacketContainer_test.cpp
Normal file
@ -0,0 +1,292 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
#include "Definitions.hpp"
|
||||
#include "PacketDissection/PacketContainer.hpp"
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
#include "PacketDissection/PacketInfoCreator.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Icmp.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Tcp.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Udp.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv6Icmp.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv6Tcp.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv6Udp.hpp"
|
||||
|
||||
TEST_CASE("PacketContainer", "[]") {
|
||||
// === I N I T === //
|
||||
uint16_t inside_port = 0;
|
||||
uint16_t outside_port = 1;
|
||||
struct rte_mempool mbuf_pool_struct;
|
||||
struct rte_mempool* mbuf_pool = &mbuf_pool_struct;
|
||||
CHECK(mbuf_pool != nullptr);
|
||||
|
||||
PacketContainer* pkt_container =
|
||||
new PacketContainer(mbuf_pool, inside_port, outside_port, 0, 0);
|
||||
CHECK(pkt_container != nullptr);
|
||||
|
||||
// === S E C T I O N S == //
|
||||
SECTION("get_empty_packet", "[]") {
|
||||
|
||||
SECTION("default", "[]") {
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 0);
|
||||
|
||||
PacketInfo* pkt_info = pkt_container->get_empty_packet();
|
||||
CHECK(pkt_info != nullptr);
|
||||
CHECK(pkt_info->get_mbuf() != nullptr);
|
||||
CHECK(pkt_info->get_type() == IPv4TCP);
|
||||
|
||||
CHECK(pkt_container->get_total_number_of_packets() >=
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 1);
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
}
|
||||
|
||||
SECTION("IPv4TCP", "[]") {
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 0);
|
||||
|
||||
PacketInfo* pkt_info = pkt_container->get_empty_packet(IPv4TCP);
|
||||
CHECK(pkt_info != nullptr);
|
||||
CHECK(pkt_info->get_mbuf() != nullptr);
|
||||
CHECK(pkt_info->get_type() == IPv4TCP);
|
||||
|
||||
CHECK(pkt_container->get_total_number_of_packets() >=
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 1);
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("create more packets than burst size", "[]") {
|
||||
|
||||
SECTION("fill till BURST_SIZE", "[]") {
|
||||
for (int i = 0; i < BURST_SIZE; ++i) {
|
||||
PacketInfo* pkt_info = pkt_container->get_empty_packet();
|
||||
CHECK(pkt_info != nullptr);
|
||||
}
|
||||
|
||||
CHECK(pkt_container->get_total_number_of_packets() == BURST_SIZE);
|
||||
}
|
||||
|
||||
SECTION("fill till BURST_SIZE + 1", "[]") {
|
||||
for (int i = 0; i < BURST_SIZE + 1; ++i) {
|
||||
PacketInfo* pkt_info = pkt_container->get_empty_packet();
|
||||
CHECK(pkt_info != nullptr);
|
||||
}
|
||||
|
||||
CHECK(pkt_container->get_total_number_of_packets() ==
|
||||
BURST_SIZE + 1);
|
||||
}
|
||||
|
||||
CHECK(pkt_container->get_total_number_of_packets() >=
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
}
|
||||
|
||||
SECTION("get_packet_at_index", "[]") {
|
||||
|
||||
SECTION("general", "[]") {
|
||||
// add empty packet
|
||||
PacketInfo* pkt_info_0 = pkt_container->get_empty_packet();
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 1);
|
||||
|
||||
PacketInfo* pkt_info_1 = pkt_container->get_packet_at_index(
|
||||
pkt_container->get_total_number_of_packets() - 1);
|
||||
CHECK(pkt_info_0 == pkt_info_1);
|
||||
CHECK(pkt_info_1 != nullptr);
|
||||
CHECK(pkt_info_1->get_mbuf() != nullptr);
|
||||
CHECK(pkt_info_1->get_type() == IPv4TCP);
|
||||
|
||||
CHECK(pkt_container->get_total_number_of_packets() >=
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
CHECK_NOTHROW(pkt_container->get_packet_at_index(
|
||||
pkt_container->get_total_number_of_packets() - 1));
|
||||
CHECK_THROWS(pkt_container->get_packet_at_index(
|
||||
pkt_container->get_total_number_of_packets()));
|
||||
}
|
||||
|
||||
SECTION("test out of bounds error", "[]") {
|
||||
for (int i = 0; i < int(BURST_SIZE / 2); ++i) {
|
||||
pkt_container->get_empty_packet();
|
||||
}
|
||||
|
||||
CHECK(pkt_container->get_total_number_of_packets() ==
|
||||
int(BURST_SIZE / 2));
|
||||
|
||||
for (int i = 0; i < int(BURST_SIZE / 2); ++i) {
|
||||
CHECK_NOTHROW(pkt_container->get_packet_at_index(i));
|
||||
}
|
||||
|
||||
for (int i = int(BURST_SIZE / 2); i < BURST_SIZE; ++i) {
|
||||
CHECK_THROWS(pkt_container->get_packet_at_index(i));
|
||||
}
|
||||
|
||||
CHECK_THROWS(pkt_container->get_packet_at_index(
|
||||
pkt_container->get_total_number_of_packets()));
|
||||
CHECK_NOTHROW(pkt_container->get_packet_at_index(
|
||||
pkt_container->get_total_number_of_packets() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("take_packet and add_packet", "[]") {
|
||||
|
||||
PacketInfo* pkt_info_0 = pkt_container->get_empty_packet();
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 1);
|
||||
|
||||
PacketInfo* pkt_info_1 = pkt_container->take_packet(0);
|
||||
CHECK(pkt_info_0 == pkt_info_1);
|
||||
CHECK(pkt_info_1 != nullptr);
|
||||
CHECK(pkt_info_1->get_mbuf() != nullptr);
|
||||
CHECK(pkt_container->get_packet_at_index(0) == nullptr);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 1);
|
||||
CHECK(pkt_container->get_total_number_of_packets() >=
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
|
||||
pkt_container->add_packet(pkt_info_1);
|
||||
CHECK(pkt_container->get_total_number_of_packets() >=
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 2);
|
||||
CHECK(pkt_container->get_packet_at_index(1) == pkt_info_1);
|
||||
CHECK(pkt_container->get_packet_at_index(0) == nullptr);
|
||||
}
|
||||
|
||||
SECTION("drop_packet", "[]") {
|
||||
|
||||
SECTION("default") {
|
||||
PacketInfo* pkt_info_0 = pkt_container->get_empty_packet();
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 1);
|
||||
|
||||
pkt_container->drop_packet(0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() >=
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 1);
|
||||
CHECK(pkt_container->get_packet_at_index(0) == nullptr);
|
||||
|
||||
CHECK_NOTHROW(pkt_container->drop_packet(0));
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 1);
|
||||
CHECK(pkt_container->get_packet_at_index(0) == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("poll_packets", "[]") {
|
||||
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 0);
|
||||
|
||||
uint16_t nb_pkts_polled;
|
||||
pkt_container->poll_packets(nb_pkts_polled);
|
||||
CHECK(pkt_container->get_number_of_polled_packets() > 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() ==
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
CHECK(nb_pkts_polled == pkt_container->get_number_of_polled_packets());
|
||||
|
||||
CHECK_NOTHROW(pkt_container->get_packet_at_index(nb_pkts_polled - 1));
|
||||
PacketInfo* pkt_info =
|
||||
pkt_container->get_packet_at_index(nb_pkts_polled - 1);
|
||||
CHECK(pkt_info != nullptr);
|
||||
CHECK(pkt_info->get_mbuf() != nullptr);
|
||||
}
|
||||
|
||||
SECTION("send_packets", "[]") {
|
||||
|
||||
SECTION("do not drop") {
|
||||
SECTION("send created packets") {
|
||||
PacketInfo* pkt_info = pkt_container->get_empty_packet();
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 1);
|
||||
}
|
||||
|
||||
SECTION("send polled packets") {
|
||||
uint16_t nb_polled_pkts;
|
||||
pkt_container->poll_packets(nb_polled_pkts);
|
||||
|
||||
CHECK(nb_polled_pkts > 0);
|
||||
}
|
||||
|
||||
SECTION("send polled and created packets") {
|
||||
uint16_t nb_polled_pkts;
|
||||
pkt_container->poll_packets(nb_polled_pkts);
|
||||
CHECK(nb_polled_pkts > 0);
|
||||
|
||||
PacketInfo* pkt_info = pkt_container->get_empty_packet();
|
||||
CHECK(pkt_container->get_total_number_of_packets() >
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
}
|
||||
|
||||
pkt_container->send_packets();
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 0);
|
||||
}
|
||||
|
||||
SECTION("drop and send created packets") {
|
||||
|
||||
const int PKTS_TO_POLL = 4;
|
||||
int nb_pkts_to_drop = -1;
|
||||
|
||||
for (int i = 0; i < PKTS_TO_POLL; ++i) {
|
||||
pkt_container->get_empty_packet();
|
||||
}
|
||||
|
||||
CHECK(pkt_container->get_total_number_of_packets() >
|
||||
pkt_container->get_number_of_polled_packets());
|
||||
CHECK(pkt_container->get_total_number_of_packets() == PKTS_TO_POLL);
|
||||
|
||||
SECTION("drop first packet") {
|
||||
nb_pkts_to_drop = 1;
|
||||
CHECK(pkt_container->get_nb_mbufs_in_mbuf_arr()[0] ==
|
||||
PKTS_TO_POLL);
|
||||
CHECK(pkt_container->get_nb_pkts_dropped() == 0);
|
||||
pkt_container->drop_packet(0);
|
||||
CHECK(pkt_container->get_nb_pkts_dropped() == 1);
|
||||
}
|
||||
|
||||
SECTION("drop second packet") {
|
||||
nb_pkts_to_drop = 1;
|
||||
CHECK(pkt_container->get_nb_mbufs_in_mbuf_arr()[0] ==
|
||||
PKTS_TO_POLL);
|
||||
CHECK(pkt_container->get_nb_pkts_dropped() == 0);
|
||||
pkt_container->drop_packet(1);
|
||||
CHECK(pkt_container->get_nb_pkts_dropped() == 1);
|
||||
}
|
||||
|
||||
SECTION("drop second and third packet") {
|
||||
nb_pkts_to_drop = 2;
|
||||
CHECK(pkt_container->get_nb_mbufs_in_mbuf_arr()[0] ==
|
||||
PKTS_TO_POLL);
|
||||
CHECK(pkt_container->get_nb_pkts_dropped() == 0);
|
||||
pkt_container->drop_packet(1);
|
||||
pkt_container->drop_packet(2);
|
||||
CHECK(pkt_container->get_nb_pkts_dropped() == 2);
|
||||
}
|
||||
|
||||
SECTION("drop last packet") {
|
||||
nb_pkts_to_drop = 1;
|
||||
CHECK(pkt_container->get_nb_mbufs_in_mbuf_arr()[0] ==
|
||||
PKTS_TO_POLL);
|
||||
CHECK(pkt_container->get_nb_pkts_dropped() == 0);
|
||||
pkt_container->drop_packet(PKTS_TO_POLL - 1);
|
||||
CHECK(pkt_container->get_nb_pkts_dropped() == 1);
|
||||
}
|
||||
|
||||
pkt_container->reorder_mbuf_arrays();
|
||||
CHECK(pkt_container->get_nb_mbufs_in_mbuf_arr()[0] ==
|
||||
PKTS_TO_POLL - nb_pkts_to_drop);
|
||||
|
||||
pkt_container->send_packets();
|
||||
CHECK(pkt_container->get_number_of_polled_packets() == 0);
|
||||
CHECK(pkt_container->get_total_number_of_packets() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// === D E L E T E O B J E C T S === //
|
||||
delete pkt_container;
|
||||
pkt_container = nullptr;
|
||||
}
|
132
test/PacketDissection/PacketInfo_test.cpp
Normal file
132
test/PacketDissection/PacketInfo_test.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
#include "ConfigurationManagement/Configurator.hpp"
|
||||
#include "Initializer.hpp"
|
||||
#include "PacketDissection/PacketInfo.hpp"
|
||||
#include "PacketDissection/PacketInfoCreator.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Icmp.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Tcp.hpp"
|
||||
#include "PacketDissection/PacketInfoIpv4Udp.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
#include <iostream>
|
||||
|
||||
TEST_CASE("Creation","[]")
|
||||
{
|
||||
|
||||
SECTION("PacketInfo","[]"){
|
||||
PacketInfo pkt_inf;
|
||||
rte_mbuf* mbuf;
|
||||
//REQUIRE_NOTHROW(pkt_inf.set_mbuf(mbuf));
|
||||
//REQUIRE_NOTHROW(nbuf = pkt_inf.get_mbuf());
|
||||
//CHECK(mbuf == nbuf);
|
||||
CHECK(pkt_inf.get_type() == NONE);
|
||||
}
|
||||
|
||||
SECTION("Creation: IPv4ICMP", "[]") {
|
||||
// PacketInfoIpv4Icmp* pkt_inf =
|
||||
// static_cast<PacketInfoIpv4Icmp*>(PacketInfoCreator::create_pkt_info(IPv4ICMP));
|
||||
PacketInfoIpv4Icmp pkt_inf;
|
||||
CHECK(pkt_inf.get_type() == IPv4ICMP);
|
||||
// pkt_inf->set_mbuf(mbuf);
|
||||
// struct rte_ipv4_hdr* ip_hdr = rte_pktmbuf_mtod_offset(mbuf, struct
|
||||
// rte_ipv4_hdr*, 0); REQUIRE_NOTHROW(pkt_inf->set_ip_hdr(ip_hdr));
|
||||
// struct rte_icmp_hdr* l4_header = rte_pktmbuf_mtod_offset(mbuf, struct
|
||||
// rte_icmp_hdr*, 20);
|
||||
// REQUIRE_NOTHROW(pkt_inf->set_icmp_hdr(l4_header)); uint32_t num;
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_dst_ip());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_src_ip());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_packet_size());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_payload_size());
|
||||
}
|
||||
|
||||
SECTION("Creation: IPv4TCP", "[]") {
|
||||
// PacketInfoIpv4Tcp* pkt_inf =
|
||||
// static_cast<PacketInfoIpv4Tcp*>(PacketInfoCreator::create_pkt_info(IPv4TCP));
|
||||
PacketInfoIpv4Tcp pkt_inf;
|
||||
CHECK(pkt_inf.get_type() == IPv4TCP);
|
||||
// pkt_inf->set_mbuf(mbuf);
|
||||
// struct rte_ipv4_hdr* ip_hdr = rte_pktmbuf_mtod_offset(mbuf, struct
|
||||
// rte_ipv4_hdr*, 0); REQUIRE_NOTHROW(pkt_inf->set_ip_hdr(ip_hdr));
|
||||
// struct rte_tcp_hdr* l4_header = rte_pktmbuf_mtod_offset(mbuf, struct
|
||||
// rte_tcp_hdr*, 20); REQUIRE_NOTHROW(pkt_inf->set_tcp_hdr(l4_header));
|
||||
// uint32_t num;
|
||||
// uint32_t num2;
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_dst_ip());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_src_ip());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_packet_size());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_payload_size());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_dst_port());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_src_port());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_flags());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_window_size());
|
||||
// CHECK_NOTHROW(pkt_inf->set_ack_num(num));
|
||||
// CHECK_NOTHROW(num2= pkt_inf->get_ack_num());
|
||||
// CHECK(num == num2);
|
||||
// CHECK_NOTHROW(pkt_inf->set_seq_num(num));
|
||||
// CHECK_NOTHROW(num = pkt_inf->get_seq_num());
|
||||
// CHECK(num == num2);
|
||||
}
|
||||
|
||||
SECTION("Creation: IPv4UDP", "[]") {
|
||||
// PacketInfoIpv4Udp* pkt_inf =
|
||||
// static_cast<PacketInfoIpv4Udp*>(PacketInfoCreator::create_pkt_info(IPv4UDP));
|
||||
PacketInfoIpv4Udp pkt_inf;
|
||||
CHECK(pkt_inf.get_type() == IPv4UDP);
|
||||
// pkt_inf->set_mbuf(mbuf);
|
||||
// struct rte_ipv4_hdr* ip_hdr = rte_pktmbuf_mtod_offset(mbuf, struct
|
||||
// rte_ipv4_hdr*, 0); REQUIRE_NOTHROW(pkt_inf->set_ip_hdr(ip_hdr));
|
||||
// struct rte_udp_hdr* l4_header = rte_pktmbuf_mtod_offset(mbuf, struct
|
||||
// rte_udp_hdr*, 20); REQUIRE_NOTHROW(pkt_inf->set_udp_hdr(l4_header));
|
||||
// uint32_t num;
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_dst_ip());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_src_ip());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_packet_size());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_payload_size());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_dst_port());
|
||||
// CHECK_NOTHROW(num= pkt_inf->get_src_port());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Transformation", "[]") {
|
||||
|
||||
SECTION("keeping Type", "[]") {
|
||||
PacketInfo* pkt_inf;
|
||||
// pkt_inf = PacketInfoCreator::create_pkt_info(IPv4ICMP);
|
||||
pkt_inf = new PacketInfoIpv4Icmp;
|
||||
PacketInfoIpv4Icmp* pkt_inf_icmp;
|
||||
pkt_inf_icmp = static_cast<PacketInfoIpv4Icmp*>(pkt_inf);
|
||||
CHECK(pkt_inf_icmp->get_type() == IPv4ICMP);
|
||||
|
||||
// PacketInfoCreator::create_pkt_info(IPv4TCP)
|
||||
pkt_inf = new PacketInfoIpv4Tcp;
|
||||
PacketInfoIpv4Tcp* pkt_inf_tcp;
|
||||
pkt_inf_tcp = static_cast<PacketInfoIpv4Tcp*>(pkt_inf);
|
||||
CHECK(pkt_inf_tcp->get_type() == IPv4TCP);
|
||||
|
||||
// PacketInfoCreator::create_pkt_info(IPv4UDP)
|
||||
pkt_inf = new PacketInfoIpv4Udp;
|
||||
PacketInfoIpv4Udp* pkt_inf_udp;
|
||||
pkt_inf_udp = static_cast<PacketInfoIpv4Udp*>(pkt_inf);
|
||||
CHECK(pkt_inf_udp->get_type() == IPv4UDP);
|
||||
|
||||
// PacketInfoCreator::create_pkt_info(NONE)
|
||||
pkt_inf = new PacketInfo;
|
||||
CHECK(pkt_inf->get_type() == NONE);
|
||||
|
||||
PacketInfo* pkt_inf_arr[5];
|
||||
pkt_inf_arr[0] = pkt_inf_icmp;
|
||||
pkt_inf_arr[1] = pkt_inf_tcp;
|
||||
pkt_inf_arr[2] = pkt_inf_udp;
|
||||
pkt_inf_arr[3] = pkt_inf;
|
||||
CHECK(pkt_inf_arr[0]->get_type() == IPv4ICMP);
|
||||
CHECK(pkt_inf_arr[1]->get_type() == IPv4TCP);
|
||||
CHECK(pkt_inf_arr[2]->get_type() == IPv4UDP);
|
||||
CHECK(pkt_inf_arr[3]->get_type() == NONE);
|
||||
|
||||
// clean up
|
||||
delete pkt_inf;
|
||||
delete pkt_inf_icmp;
|
||||
delete pkt_inf_tcp;
|
||||
delete pkt_inf_udp;
|
||||
delete pkt_inf_arr;
|
||||
}
|
||||
}
|
||||
|
456
test/RandomNumberGenerator/RandomNumberGenerator_test.cpp
Normal file
456
test/RandomNumberGenerator/RandomNumberGenerator_test.cpp
Normal file
@ -0,0 +1,456 @@
|
||||
#include "RandomNumberGenerator.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
#include <iostream>
|
||||
#include <time.h> // is used for testing the time in the 3rd test case
|
||||
|
||||
TEST_CASE("random_number_generator_basic", "[]") {
|
||||
|
||||
// This test was written to check basic functions like whether different
|
||||
// numbers are generated.
|
||||
SECTION("check_whether_different_16", "[]") {
|
||||
// creates a new RNG object
|
||||
RandomNumberGenerator* xor_shift = new RandomNumberGenerator();
|
||||
|
||||
// creates two pseudo random 16 bit numbers
|
||||
u_int16_t test_1 = xor_shift->gen_rdm_16_bit();
|
||||
u_int16_t test_2 = xor_shift->gen_rdm_16_bit();
|
||||
|
||||
// printes these numbers out
|
||||
std::cout << "1st generated 16 bit int: " << test_1 << std::endl;
|
||||
std::cout << "2nd generated 16 bit int: " << test_2 << std::endl;
|
||||
|
||||
// checks whether these numbers are different
|
||||
// test1 == test2 wouldn't means that the test isn't random.
|
||||
// This section just exists to see whether the algorithm basically works
|
||||
// and generates numbers.
|
||||
CHECK(test_1 != test_2);
|
||||
}
|
||||
|
||||
// The same test like above but for the 32 bit algorithm:
|
||||
SECTION("CheckWhetherDifferent32", "[]") {
|
||||
RandomNumberGenerator xor_shift;
|
||||
u_int32_t test_1 = xor_shift.gen_rdm_32_bit();
|
||||
u_int32_t test_2 = xor_shift.gen_rdm_32_bit();
|
||||
std::cout << "1st generated 32 bit int: " << test_1 << std::endl;
|
||||
std::cout << "2nd generated 32 bit int: " << test_2 << std::endl;
|
||||
CHECK(test_1 != test_2);
|
||||
}
|
||||
|
||||
// The same test like above but for the 64 bit algorithm:
|
||||
SECTION("CheckWhetherDifferent64", "[]") {
|
||||
RandomNumberGenerator xor_shift;
|
||||
u_int64_t test_1 = xor_shift.gen_rdm_64_bit();
|
||||
u_int64_t test_2 = xor_shift.gen_rdm_64_bit();
|
||||
std::cout << "1st generated 64 bit int: " << test_1 << std::endl;
|
||||
std::cout << "2nd generated 64 bit int: " << test_2 << std::endl;
|
||||
CHECK(test_1 != test_2);
|
||||
// empty line for better layout in testlog
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// This test checks the type of the return value.
|
||||
// This particular section is for 16 bit
|
||||
SECTION("CheckSize16", "[]") {
|
||||
// Creates a RNG and generates a number like above
|
||||
RandomNumberGenerator xor_shift;
|
||||
u_int16_t test_value = xor_shift.gen_rdm_16_bit();
|
||||
std::cout << "values that are generated for checking the size: "
|
||||
<< std::endl;
|
||||
std::cout << "generated value: " << test_value << std::endl;
|
||||
// checks wheter the size of the return value is 16 bit or 2 byte
|
||||
CHECK(sizeof(test_value) == 2);
|
||||
}
|
||||
|
||||
// The same for 32 bit
|
||||
SECTION("CheckSize32", "[]") {
|
||||
RandomNumberGenerator xor_shift;
|
||||
u_int32_t test_value = xor_shift.gen_rdm_32_bit();
|
||||
std::cout << "generated value (32 bit): " << test_value << std::endl;
|
||||
// checks wheter the size of the return value is 32 bit or 4 byte
|
||||
CHECK(sizeof(test_value) == 4);
|
||||
}
|
||||
|
||||
// The same for 64 bit
|
||||
SECTION("CheckSize64", "[]") {
|
||||
RandomNumberGenerator xor_shift;
|
||||
u_int64_t test_value = xor_shift.gen_rdm_64_bit();
|
||||
std::cout << "generated value (64 bit): " << test_value << std::endl;
|
||||
// checks wheter the size of the return value is 64 bit or 8 byte
|
||||
CHECK(sizeof(test_value) == 8);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// Checks whether different numbers are generated when using different RNGs
|
||||
SECTION(
|
||||
"Check whether different when using different RNG objects for 16 bit",
|
||||
"[]") {
|
||||
// creating two objects
|
||||
RandomNumberGenerator xor_shift_1;
|
||||
RandomNumberGenerator xor_shift_2;
|
||||
// generating two values of 16 bit
|
||||
std::cout << "16 bit seed 1: " << xor_shift_1._seed_x16 << std::endl;
|
||||
std::cout << "16 bit seed 2: " << xor_shift_2._seed_x16 << std::endl;
|
||||
u_int16_t test_1_16_bit = xor_shift_1.gen_rdm_16_bit();
|
||||
u_int16_t test_2_16_bit = xor_shift_2.gen_rdm_16_bit();
|
||||
CHECK(test_1_16_bit != test_2_16_bit);
|
||||
}
|
||||
|
||||
// the same for 32 bit again:
|
||||
SECTION(
|
||||
"Check whether different when using different RNG objects for 32 bit",
|
||||
"[]") {
|
||||
RandomNumberGenerator xor_shift_1;
|
||||
RandomNumberGenerator xor_shift_2;
|
||||
std::cout << "32 bit seed 1: " << xor_shift_1._seed_x32 << std::endl;
|
||||
std::cout << "32 bit seed 2: " << xor_shift_2._seed_x32 << std::endl;
|
||||
u_int32_t test_1_32_bit = xor_shift_1.gen_rdm_32_bit();
|
||||
u_int32_t test_2_32_bit = xor_shift_2.gen_rdm_32_bit();
|
||||
CHECK(test_1_32_bit != test_2_32_bit);
|
||||
}
|
||||
|
||||
// the same for 64 bit again:
|
||||
SECTION(
|
||||
"Check whether different when using different RNG objects for 64 bit",
|
||||
"[]") {
|
||||
RandomNumberGenerator xor_shift_1;
|
||||
RandomNumberGenerator xor_shift_2;
|
||||
std::cout << "64 bit seed 1: " << xor_shift_1._seed_x64 << std::endl;
|
||||
std::cout << "64 bit seed 2: " << xor_shift_2._seed_x64 << std::endl;
|
||||
u_int64_t test_1_64_bit = xor_shift_1.gen_rdm_64_bit();
|
||||
u_int64_t test_2_64_bit = xor_shift_2.gen_rdm_64_bit();
|
||||
CHECK(test_1_64_bit != test_2_64_bit);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// This test checks whether two RNGs generate the same number after the seed
|
||||
// is set to the same number
|
||||
SECTION("Check whether the same numbers are generated with the same seed "
|
||||
"for 16 bit",
|
||||
"[]") {
|
||||
RandomNumberGenerator xor_shift_1;
|
||||
RandomNumberGenerator xor_shift_2;
|
||||
// set the seed to the same value in both RNGs
|
||||
xor_shift_1._seed_x16 = 30000;
|
||||
xor_shift_2._seed_x16 = 30000;
|
||||
std::cout << "16 bit seed for RNG 1: " << xor_shift_1._seed_x16
|
||||
<< std::endl;
|
||||
std::cout << "16 bit seed for RNG 2: " << xor_shift_2._seed_x16
|
||||
<< std::endl;
|
||||
u_int16_t test_1_16_bit = xor_shift_1.gen_rdm_16_bit();
|
||||
u_int16_t test_2_16_bit = xor_shift_2.gen_rdm_16_bit();
|
||||
std::cout << "number generated from RNG 1: " << xor_shift_1._seed_x16
|
||||
<< std::endl;
|
||||
std::cout << "number generated from RNG 2: " << xor_shift_2._seed_x16
|
||||
<< std::endl;
|
||||
// check whether the results are the same too
|
||||
CHECK(test_1_16_bit == test_2_16_bit);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// the same test for 32 bit
|
||||
SECTION("Check whether the same numbers are generated with the same seed "
|
||||
"for 32 bit",
|
||||
"[]") {
|
||||
RandomNumberGenerator xor_shift_1;
|
||||
RandomNumberGenerator xor_shift_2;
|
||||
// set the seed to the same value in both RNGs
|
||||
xor_shift_1._seed_x32 = 30000000;
|
||||
xor_shift_2._seed_x32 = 30000000;
|
||||
std::cout << "32 bit seed for RNG 1: " << xor_shift_1._seed_x32
|
||||
<< std::endl;
|
||||
std::cout << "32 bit seed for RNG 2: " << xor_shift_2._seed_x32
|
||||
<< std::endl;
|
||||
u_int32_t test_1_32_bit = xor_shift_1.gen_rdm_32_bit();
|
||||
u_int32_t test_2_32_bit = xor_shift_2.gen_rdm_32_bit();
|
||||
std::cout << "number generated from RNG 1: " << xor_shift_1._seed_x32
|
||||
<< std::endl;
|
||||
std::cout << "number generated from RNG 2: " << xor_shift_2._seed_x32
|
||||
<< std::endl;
|
||||
// check whether the results are the same too
|
||||
CHECK(test_1_32_bit == test_2_32_bit);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// the same test for 64 bit
|
||||
SECTION("Check whether the same numbers are generated with the same seed "
|
||||
"for 64 bit",
|
||||
"[]") {
|
||||
RandomNumberGenerator xor_shift_1;
|
||||
RandomNumberGenerator xor_shift_2;
|
||||
// set the seed to the same value in both RNGs
|
||||
xor_shift_1._seed_x64 = 30000000000;
|
||||
xor_shift_2._seed_x64 = 30000000000;
|
||||
std::cout << "64 bit seed for RNG 1: " << xor_shift_1._seed_x64
|
||||
<< std::endl;
|
||||
std::cout << "64 bit seed for RNG 2: " << xor_shift_2._seed_x64
|
||||
<< std::endl;
|
||||
u_int64_t test_1_64_bit = xor_shift_1.gen_rdm_64_bit();
|
||||
u_int64_t test_2_64_bit = xor_shift_2.gen_rdm_64_bit();
|
||||
std::cout << "number generated from RNG 1: " << xor_shift_1._seed_x64
|
||||
<< std::endl;
|
||||
std::cout << "number generated from RNG 2: " << xor_shift_2._seed_x64
|
||||
<< std::endl;
|
||||
// check whether the results are the same too
|
||||
CHECK(test_1_64_bit == test_2_64_bit);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
SECTION("Check whether generated numbers are really in the interval",
|
||||
"[]") {
|
||||
RandomNumberGenerator xor_shift;
|
||||
u_int16_t test_value;
|
||||
int lower_limit = 1024;
|
||||
int upper_limit = 49151;
|
||||
bool no_number_has_been_outside_the_interval = true;
|
||||
// inside the for loop an if statement checks for 1,000,000 generated
|
||||
// numbers whether they are really in the interval
|
||||
for (int i = 0; i < 10000000; i++) {
|
||||
test_value =
|
||||
xor_shift.gen_rdm_16_bit_in_interval(lower_limit, upper_limit);
|
||||
if (test_value < lower_limit || test_value > upper_limit) {
|
||||
no_number_has_been_outside_the_interval = false;
|
||||
}
|
||||
}
|
||||
std::cout << "No generated number has been outside the interval? (1 "
|
||||
"means true) --> "
|
||||
<< no_number_has_been_outside_the_interval << std::endl;
|
||||
std::cout << std::endl;
|
||||
CHECK(no_number_has_been_outside_the_interval == true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("RandomNumberGeneratorStatistics", "[]") {
|
||||
|
||||
// The result of the chi square test shows how uniform the generated numbers
|
||||
// are distributed
|
||||
// A big chi square means that the actual frequencies vary widely from the
|
||||
// theoretical frequencies.
|
||||
SECTION("ChiSquare16", "[]") {
|
||||
RandomNumberGenerator xor_shift;
|
||||
// 65536 - 1 = 2 ^ 16 different numbers can be generated
|
||||
int r = 65536 - 1;
|
||||
// 1,000,000 numbers are generated
|
||||
int n = 1000000;
|
||||
u_int16_t t;
|
||||
// this array counts how often each number from 0 to r is returned as a
|
||||
// result
|
||||
int f[r] = {};
|
||||
for (int i = 0; i < r; i++) {
|
||||
f[i] = 0;
|
||||
}
|
||||
for (int i = 1; i < n; i++) {
|
||||
t = xor_shift.gen_rdm_16_bit_in_interval(1024, 49151);
|
||||
f[t]++;
|
||||
}
|
||||
double chisquare = 0.0;
|
||||
for (int i = 0; i < r; i++) {
|
||||
// chi square is calculated
|
||||
chisquare = chisquare + ((f[i] - n / r) * (f[i] - n / r) / (n / r));
|
||||
}
|
||||
std::cout << "+++ chi square test for gen_rdm_16_bit_in_interval() +++"
|
||||
<< std::endl;
|
||||
std::cout << "chi square is: " << chisquare << std::endl;
|
||||
double k = sqrt(chisquare / (n + chisquare));
|
||||
std::cout << "k is: " << k << std::endl;
|
||||
|
||||
// k is in [0; k_max] with k_max ≈ 1
|
||||
// Calculating k_norm wouldn't make sense.
|
||||
// 0 means that every number is generated equally frequent
|
||||
// 1 means not random at all
|
||||
|
||||
// A bad result could be improved by returning _seed_x16 instead of
|
||||
// _seed_x16 % 48128 + 1024 (valid port number) in
|
||||
// RandomNumberGenerator.cpp.
|
||||
|
||||
CHECK(k < 1.0);
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
SECTION("ChiSquare16", "[]") {
|
||||
RandomNumberGenerator xor_shift;
|
||||
// 65526 - 1 = 2 ^ 16 different numbers can be generated
|
||||
int r = 65536 - 1;
|
||||
// 1,000,000 numbers are generated
|
||||
int n = 1000000;
|
||||
u_int16_t t;
|
||||
// this array counts how often each number from 0 to r is returned as a
|
||||
// result
|
||||
int f[r] = {};
|
||||
for (int i = 0; i < r; i++) {
|
||||
f[i] = 0;
|
||||
}
|
||||
for (int i = 1; i < n; i++) {
|
||||
t = xor_shift.gen_rdm_16_bit();
|
||||
f[t]++;
|
||||
}
|
||||
double chisquare = 0.0;
|
||||
for (int i = 0; i < r; i++) {
|
||||
// chi square is calculated
|
||||
chisquare = chisquare + ((f[i] - n / r) * (f[i] - n / r) / (n / r));
|
||||
}
|
||||
std::cout << "+++ chi square test for gen_rdm_16_bit() +++"
|
||||
<< std::endl;
|
||||
std::cout << "chi square is: " << chisquare << std::endl;
|
||||
double k = sqrt(chisquare / (n + chisquare));
|
||||
std::cout << "k is: " << k << std::endl;
|
||||
|
||||
CHECK(k < 1.0);
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// the following test fails due to an segmentation violation signal
|
||||
// 32 bit seems to be to big
|
||||
|
||||
/*SECTION("ChiSquare32", "[]") {
|
||||
RandomNumberGenerator xor_shift;
|
||||
u_int32_t r = 4294967296 - 1;
|
||||
u_int64_t n = 10000000000;
|
||||
u_int32_t t;
|
||||
int f[r] = {};
|
||||
for (u_int64_t i = 0; i < r; i++) {
|
||||
f[i] = 0;
|
||||
}
|
||||
for (u_int64_t i = 1; i < n; i++) {
|
||||
t = xor_shift.gen_rdm_32_bit();
|
||||
f[t]++;
|
||||
}
|
||||
double chisquare = 0.0;
|
||||
for (int i = 0; i < r; i++) {
|
||||
chisquare = chisquare + ((f[i] - n / r) * (f[i] - n / r) / (n / r));
|
||||
}
|
||||
std::cout << "chi square is: " << chisquare << std::endl;
|
||||
double k = sqrt(chisquare / (n + chisquare));
|
||||
std::cout << "k is: " << k << std::endl;
|
||||
// k is in [0; k_max] with k_max ≈ 1
|
||||
// 0 means independence
|
||||
// 1 means not random at all
|
||||
CHECK(k < 1.0);
|
||||
}*/
|
||||
}
|
||||
|
||||
TEST_CASE("RandomNumberGeneratorTime", "[]") {
|
||||
|
||||
// The following section is calculating the time for generating n
|
||||
// 16 bit numbers with a single RNG object
|
||||
SECTION("TestTime16", "[]") {
|
||||
// the following two lines initialize and start the timer
|
||||
double time1 = 0.0, tstart;
|
||||
tstart = clock();
|
||||
// creating a RNG object
|
||||
RandomNumberGenerator xor_shift;
|
||||
// amount of numbers generated
|
||||
// can be changed if neccessary, but it you will get a segmentation
|
||||
// violation error if it's to big
|
||||
long n = 10000000;
|
||||
// variable to store generated number
|
||||
uint16_t test_value;
|
||||
// generating those numbers
|
||||
for (long i = 0; i < n; i++) {
|
||||
test_value = xor_shift.gen_rdm_16_bit();
|
||||
}
|
||||
// stops the timer and calculates the difference between start and end
|
||||
time1 += clock() - tstart;
|
||||
// prints out the time
|
||||
std::cout << "time needed to generate " << n
|
||||
<< " 16 bit numbers: " << time1 / CLOCKS_PER_SEC << " s"
|
||||
<< std::endl;
|
||||
CHECK(time1 / CLOCKS_PER_SEC < 10.0);
|
||||
}
|
||||
|
||||
// This test calculates the time needed to generate a certain amount of 16
|
||||
// bit ints with rand() allowowing a comparison with xorShift
|
||||
SECTION("TestTime16Rand", "[]") {
|
||||
double time1 = 0.0, tstart;
|
||||
tstart = clock();
|
||||
long n = 10000000;
|
||||
uint16_t test_value;
|
||||
for (long i = 0; i < n; i++) {
|
||||
test_value = rand();
|
||||
}
|
||||
time1 += clock() - tstart;
|
||||
std::cout << "time needed to generate " << n
|
||||
<< " 16 bit numbers with rand(): " << time1 / CLOCKS_PER_SEC
|
||||
<< " s" << std::endl;
|
||||
CHECK(time1 / CLOCKS_PER_SEC < 10.0);
|
||||
}
|
||||
|
||||
// the same test for 32 bit numbers
|
||||
SECTION("TestTime32", "[]") {
|
||||
double time1 = 0.0, tstart;
|
||||
tstart = clock();
|
||||
RandomNumberGenerator xor_shift;
|
||||
long n = 10000000;
|
||||
uint32_t test_value;
|
||||
for (long i = 0; i < n; i++) {
|
||||
test_value = xor_shift.gen_rdm_32_bit();
|
||||
}
|
||||
time1 += clock() - tstart;
|
||||
std::cout << "time needed to generate " << n
|
||||
<< " 32 bit numbers: " << time1 / CLOCKS_PER_SEC << " s"
|
||||
<< std::endl;
|
||||
CHECK(time1 / CLOCKS_PER_SEC < 1.0);
|
||||
}
|
||||
|
||||
// true 32 bit numbers with shifting and rand() for comparison to the
|
||||
// section above
|
||||
SECTION("TestTime32Rand", "[]") {
|
||||
double time1 = 0.0, tstart;
|
||||
tstart = clock();
|
||||
long n = 10000000;
|
||||
uint32_t test_value;
|
||||
for (long i = 0; i < n; i++) {
|
||||
test_value = (uint16_t)rand();
|
||||
test_value |= (uint16_t)rand() << 16;
|
||||
}
|
||||
time1 += clock() - tstart;
|
||||
std::cout << "time needed to generate " << n
|
||||
<< " 32 bit numbers with rand() and shifting: "
|
||||
<< time1 / CLOCKS_PER_SEC << " s" << std::endl;
|
||||
CHECK(time1 / CLOCKS_PER_SEC < 1.0);
|
||||
}
|
||||
|
||||
// the same test for 64 bit numbers
|
||||
SECTION("TestTime64", "[]") {
|
||||
double time1 = 0.0, tstart;
|
||||
tstart = clock();
|
||||
RandomNumberGenerator xor_shift;
|
||||
long n = 10000000;
|
||||
uint64_t test_value;
|
||||
for (long i = 0; i < n; i++) {
|
||||
test_value = xor_shift.gen_rdm_64_bit();
|
||||
}
|
||||
time1 += clock() - tstart;
|
||||
std::cout << "time needed to generate " << n
|
||||
<< " 64 bit numbers: " << time1 / CLOCKS_PER_SEC << " s"
|
||||
<< std::endl;
|
||||
CHECK(time1 / CLOCKS_PER_SEC < 1.0);
|
||||
}
|
||||
|
||||
// true 64 bit numbers with shifting and rand() for comparison to the
|
||||
// section above
|
||||
SECTION("TestTime64Rand", "[]") {
|
||||
double time1 = 0.0, tstart;
|
||||
tstart = clock();
|
||||
long n = 10000000;
|
||||
uint64_t test_value = 0;
|
||||
for (long i = 0; i < n; i++) {
|
||||
// the following lines have been copied from
|
||||
// Treatment::create_cookie_secret()
|
||||
u_int64_t value1 = (uint16_t)rand();
|
||||
value1 = (value1 << 48);
|
||||
test_value |= value1;
|
||||
u_int64_t value2 = (uint16_t)rand();
|
||||
value2 = (value2 << 32);
|
||||
test_value |= value2;
|
||||
u_int64_t value3 = (uint16_t)rand();
|
||||
test_value |= value3;
|
||||
}
|
||||
time1 += clock() - tstart;
|
||||
std::cout << "time needed to generate " << n
|
||||
<< " 64 bit numbers with rand() and shifting: "
|
||||
<< time1 / CLOCKS_PER_SEC << " s" << std::endl;
|
||||
CHECK(time1 / CLOCKS_PER_SEC < 1.0);
|
||||
}
|
||||
}
|
1302
test/Treatment/Treatment_test.cpp
Normal file
1302
test/Treatment/Treatment_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
6
test/config_attacker.json
Normal file
6
test/config_attacker.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"attack_type": "syn_flood",
|
||||
"number_of_worker_threads": "4",
|
||||
"number_of_attack_packets_per_thread_per_send_call": 100,
|
||||
"call_send_pkts_every_nth_iteration": 1
|
||||
}
|
32
test/libdpdk_dummy/include/rte_branch_prediction.h
Normal file
32
test/libdpdk_dummy/include/rte_branch_prediction.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef _RTE_BRANCH_PREDICTION_H_
|
||||
#define _RTE_BRANCH_PREDICTION_H_
|
||||
|
||||
/**
|
||||
* Check if a branch is likely to be taken.
|
||||
*
|
||||
* This compiler builtin allows the developer to indicate if a branch is
|
||||
* likely to be taken. Example:
|
||||
*
|
||||
* if (likely(x > 1))
|
||||
* do_stuff();
|
||||
*
|
||||
*/
|
||||
#ifndef likely
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#endif /* likely */
|
||||
|
||||
/**
|
||||
* Check if a branch is unlikely to be taken.
|
||||
*
|
||||
* This compiler builtin allows the developer to indicate if a branch is
|
||||
* unlikely to be taken. Example:
|
||||
*
|
||||
* if (unlikely(x < 1))
|
||||
* do_stuff();
|
||||
*
|
||||
*/
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif /* unlikely */
|
||||
|
||||
#endif /* _RTE_BRANCH_PREDICTION_H_ */
|
62
test/libdpdk_dummy/include/rte_byteorder.h
Normal file
62
test/libdpdk_dummy/include/rte_byteorder.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define rte_cpu_to_be_16(x) rte_bswap16(x)
|
||||
#define rte_be_to_cpu_16(x) rte_bswap16(x)
|
||||
|
||||
#define rte_cpu_to_be_32(x) rte_bswap32(x)
|
||||
#define rte_be_to_cpu_32(x) rte_bswap32(x)
|
||||
|
||||
#define rte_bswap16(x) \
|
||||
((uint16_t)(__builtin_constant_p(x) ? rte_constant_bswap16(x) \
|
||||
: rte_arch_bswap16(x)))
|
||||
|
||||
#define rte_bswap32(x) \
|
||||
((uint32_t)(__builtin_constant_p(x) ? rte_constant_bswap32(x) \
|
||||
: rte_arch_bswap32(x)))
|
||||
|
||||
typedef uint16_t rte_be16_t;
|
||||
|
||||
typedef uint32_t rte_be32_t;
|
||||
|
||||
/**
|
||||
* An internal function to swap bytes in a
|
||||
* 16-bit value.
|
||||
*
|
||||
* It is used by rte_bswap16() when the
|
||||
* value is constant. Do not use this
|
||||
* function directly; rte_bswap16() is
|
||||
* preferred.
|
||||
*/
|
||||
static inline uint16_t rte_constant_bswap16(uint16_t x) {
|
||||
return (uint16_t)(((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal function to swap bytes in a 32-bit value.
|
||||
*
|
||||
* It is used by rte_bswap32() when the value is constant. Do not use
|
||||
* this function directly; rte_bswap32() is preferred.
|
||||
*/
|
||||
static inline uint32_t rte_constant_bswap32(uint32_t x) {
|
||||
return ((x & 0x000000ffUL) << 24) | ((x & 0x0000ff00UL) << 8) |
|
||||
((x & 0x00ff0000UL) >> 8) | ((x & 0xff000000UL) >> 24);
|
||||
}
|
||||
|
||||
static inline uint16_t rte_arch_bswap16(uint16_t _x) {
|
||||
uint16_t x = _x;
|
||||
asm volatile("xchgb %b[x1],%h[x2]" : [ x1 ] "=Q"(x) : [ x2 ] "0"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* An architecture-optimized byte swap for a 32-bit value.
|
||||
*
|
||||
* Do not use this function directly. The preferred function is rte_bswap32().
|
||||
*/
|
||||
static inline uint32_t rte_arch_bswap32(uint32_t _x) {
|
||||
uint32_t x = _x;
|
||||
asm volatile("bswap %[x]" : [ x ] "+r"(x));
|
||||
return x;
|
||||
}
|
14
test/libdpdk_dummy/include/rte_common.h
Normal file
14
test/libdpdk_dummy/include/rte_common.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#define RTE_MIN(a, b) \
|
||||
__extension__({ \
|
||||
typeof(a) _a = (a); \
|
||||
typeof(b) _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
|
||||
#define RTE_STD_C11 __extension__
|
||||
#else
|
||||
#define RTE_STD_C11
|
||||
#endif
|
3
test/libdpdk_dummy/include/rte_config.h
Normal file
3
test/libdpdk_dummy/include/rte_config.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define RTE_PKTMBUF_HEADROOM 128
|
14
test/libdpdk_dummy/include/rte_cycles.h
Normal file
14
test/libdpdk_dummy/include/rte_cycles.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint64_t rte_get_tsc_cycles() {
|
||||
unsigned int lo, hi;
|
||||
__asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
return ((uint64_t)hi << 32) | lo;
|
||||
}
|
||||
|
||||
uint64_t rte_get_tsc_hz() {
|
||||
// 1.8 GHz
|
||||
return 1800000000;
|
||||
}
|
1
test/libdpdk_dummy/include/rte_eal.h
Normal file
1
test/libdpdk_dummy/include/rte_eal.h
Normal file
@ -0,0 +1 @@
|
||||
#pragma once
|
44
test/libdpdk_dummy/include/rte_ethdev.h
Normal file
44
test/libdpdk_dummy/include/rte_ethdev.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_mbuf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct rte_eth_conf {
|
||||
/*
|
||||
uint32_t link_speeds;
|
||||
struct rte_eth_rxmode rxmode;
|
||||
struct rte_eth_txmode txmode;
|
||||
uint32_t lpbk_mode;
|
||||
struct {
|
||||
struct rte_eth_rss_conf rss_conf;
|
||||
struct rte_eth_vmdq_dcb_conf vmdq_dcb_conf;
|
||||
struct rte_eth_dcb_rx_conf dcb_rx_conf;
|
||||
struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
|
||||
} rx_adv_conf;
|
||||
union {
|
||||
struct rte_eth_vmdq_dcb_tx_conf vmdq_dcb_tx_conf;
|
||||
struct rte_eth_dcb_tx_conf dcb_tx_conf;
|
||||
struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
|
||||
} tx_adv_conf;
|
||||
uint32_t dcb_capability_en;
|
||||
struct rte_fdir_conf fdir_conf;
|
||||
struct rte_intr_conf intr_conf;
|
||||
*/
|
||||
};
|
||||
|
||||
static inline uint16_t rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id,
|
||||
struct rte_mbuf** tx_pkts,
|
||||
uint16_t nb_pkts) {
|
||||
for (int i = 0; i < nb_pkts; ++i) {
|
||||
rte_pktmbuf_free(tx_pkts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint16_t rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id,
|
||||
struct rte_mbuf** rx_pkts,
|
||||
const uint16_t nb_pkts) {
|
||||
rte_mempool* mp;
|
||||
for (int i = 0; i < nb_pkts; ++i) {
|
||||
rx_pkts[i] = rte_pktmbuf_alloc(mp);
|
||||
}
|
||||
}
|
22
test/libdpdk_dummy/include/rte_ether.h
Normal file
22
test/libdpdk_dummy/include/rte_ether.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_common.h>
|
||||
|
||||
#define RTE_ETHER_ADDR_LEN 6
|
||||
|
||||
struct rte_ether_addr {
|
||||
uint8_t addr_bytes[RTE_ETHER_ADDR_LEN];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct rte_ether_hdr {
|
||||
struct rte_ether_addr d_addr;
|
||||
RTE_STD_C11
|
||||
union {
|
||||
struct rte_ether_addr s_addr;
|
||||
struct {
|
||||
struct rte_ether_addr S_addr;
|
||||
} S_un;
|
||||
};
|
||||
rte_be16_t ether_type;
|
||||
} __attribute__((__packed__));
|
12
test/libdpdk_dummy/include/rte_icmp.h
Normal file
12
test/libdpdk_dummy/include/rte_icmp.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct rte_icmp_hdr {
|
||||
uint8_t icmp_type; /* ICMP packet type. */
|
||||
uint8_t icmp_code; /* ICMP packet code. */
|
||||
rte_be16_t icmp_cksum; /* ICMP packet checksum. */
|
||||
rte_be16_t icmp_ident; /* ICMP packet identifier. */
|
||||
rte_be16_t icmp_seq_nb; /* ICMP packet sequence number. */
|
||||
} __attribute__((__packed__));
|
139
test/libdpdk_dummy/include/rte_ip.h
Normal file
139
test/libdpdk_dummy/include/rte_ip.h
Normal file
@ -0,0 +1,139 @@
|
||||
#pragma once
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_mbuf_core.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define RTE_IPV4_HDR_IHL_MASK (0x0f)
|
||||
#define RTE_IPV4_IHL_MULTIPLIER (4)
|
||||
#define IPPROTO_UDP IPPROTO_UDP
|
||||
|
||||
struct rte_ipv4_hdr {
|
||||
uint8_t version_ihl;
|
||||
uint8_t type_of_service;
|
||||
rte_be16_t total_length;
|
||||
rte_be16_t packet_id;
|
||||
rte_be16_t fragment_offset;
|
||||
uint8_t time_to_live;
|
||||
uint8_t next_proto_id;
|
||||
rte_be16_t hdr_checksum;
|
||||
rte_be32_t src_addr;
|
||||
rte_be32_t dst_addr;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct rte_ipv6_hdr {
|
||||
rte_be32_t vtc_flow;
|
||||
rte_be16_t payload_len;
|
||||
uint8_t proto;
|
||||
uint8_t hop_limits;
|
||||
uint8_t src_addr[16];
|
||||
uint8_t dst_addr[16];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
static inline uint8_t rte_ipv4_hdr_len(const struct rte_ipv4_hdr* ipv4_hdr) {
|
||||
return (uint8_t)((ipv4_hdr->version_ihl & RTE_IPV4_HDR_IHL_MASK) *
|
||||
RTE_IPV4_IHL_MULTIPLIER);
|
||||
}
|
||||
|
||||
static inline uint16_t __rte_raw_cksum_reduce(uint32_t sum) {
|
||||
sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
|
||||
sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
|
||||
return (uint16_t)sum;
|
||||
}
|
||||
|
||||
static inline uint32_t __rte_raw_cksum(const void* buf, size_t len,
|
||||
uint32_t sum) {
|
||||
/* workaround gcc strict-aliasing warning */
|
||||
uintptr_t ptr = (uintptr_t)buf;
|
||||
typedef uint16_t __attribute__((__may_alias__)) u16_p;
|
||||
const u16_p* u16_buf = (const u16_p*)ptr;
|
||||
|
||||
while (len >= (sizeof(*u16_buf) * 4)) {
|
||||
sum += u16_buf[0];
|
||||
sum += u16_buf[1];
|
||||
sum += u16_buf[2];
|
||||
sum += u16_buf[3];
|
||||
len -= sizeof(*u16_buf) * 4;
|
||||
u16_buf += 4;
|
||||
}
|
||||
while (len >= sizeof(*u16_buf)) {
|
||||
sum += *u16_buf;
|
||||
len -= sizeof(*u16_buf);
|
||||
u16_buf += 1;
|
||||
}
|
||||
|
||||
/* if length is in odd bytes */
|
||||
if (len == 1)
|
||||
sum += *((const uint8_t*)u16_buf);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static inline uint16_t rte_raw_cksum(const void* buf, size_t len) {
|
||||
uint32_t sum;
|
||||
|
||||
sum = __rte_raw_cksum(buf, len, 0);
|
||||
return __rte_raw_cksum_reduce(sum);
|
||||
}
|
||||
|
||||
static inline uint16_t rte_ipv4_cksum(const struct rte_ipv4_hdr* ipv4_hdr) {
|
||||
uint16_t cksum;
|
||||
cksum = rte_raw_cksum(ipv4_hdr, rte_ipv4_hdr_len(ipv4_hdr));
|
||||
return (uint16_t)~cksum;
|
||||
}
|
||||
|
||||
static inline uint16_t rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr* ipv4_hdr,
|
||||
uint64_t ol_flags) {
|
||||
struct ipv4_psd_header {
|
||||
uint32_t src_addr; /* IP address of source host. */
|
||||
uint32_t dst_addr; /* IP address of destination host. */
|
||||
uint8_t zero; /* zero. */
|
||||
uint8_t proto; /* L4 protocol type. */
|
||||
uint16_t len; /* L4 length. */
|
||||
} psd_hdr;
|
||||
|
||||
psd_hdr.src_addr = ipv4_hdr->src_addr;
|
||||
psd_hdr.dst_addr = ipv4_hdr->dst_addr;
|
||||
psd_hdr.zero = 0;
|
||||
psd_hdr.proto = ipv4_hdr->next_proto_id;
|
||||
|
||||
if (ol_flags & PKT_TX_TCP_SEG) {
|
||||
psd_hdr.len = 0;
|
||||
} else {
|
||||
psd_hdr.len = rte_cpu_to_be_16(
|
||||
(uint16_t)(rte_be_to_cpu_16(ipv4_hdr->total_length) -
|
||||
sizeof(struct rte_ipv4_hdr)));
|
||||
}
|
||||
|
||||
return rte_raw_cksum(&psd_hdr, sizeof(psd_hdr));
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr* ipv4_hdr, const void* l4_hdr) {
|
||||
uint32_t cksum;
|
||||
uint32_t l3_len, l4_len;
|
||||
uint8_t ip_hdr_len;
|
||||
|
||||
ip_hdr_len = rte_ipv4_hdr_len(ipv4_hdr);
|
||||
l3_len = rte_be_to_cpu_16(ipv4_hdr->total_length);
|
||||
if (l3_len < ip_hdr_len)
|
||||
return 0;
|
||||
|
||||
l4_len = l3_len - ip_hdr_len;
|
||||
|
||||
cksum = rte_raw_cksum(l4_hdr, l4_len);
|
||||
cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0);
|
||||
|
||||
cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
|
||||
cksum = (~cksum) & 0xffff;
|
||||
/*
|
||||
* Per RFC 768:If the computed checksum is zero for UDP,
|
||||
* it is transmitted as all ones
|
||||
* (the equivalent in one's complement arithmetic).
|
||||
*/
|
||||
if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP)
|
||||
cksum = 0xffff;
|
||||
|
||||
return (uint16_t)cksum;
|
||||
}
|
3
test/libdpdk_dummy/include/rte_lcore.h
Normal file
3
test/libdpdk_dummy/include/rte_lcore.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
static unsigned int rte_lcore_id() { return 1; }
|
119
test/libdpdk_dummy/include/rte_mbuf.h
Normal file
119
test/libdpdk_dummy/include/rte_mbuf.h
Normal file
@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <rte_branch_prediction.h>
|
||||
#include <rte_common.h>
|
||||
#include <rte_config.h>
|
||||
#include <rte_mbuf_core.h>
|
||||
#include <rte_mempool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define __rte_mbuf_sanity_check(m, is_h) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf* m) {
|
||||
__rte_mbuf_sanity_check(m, 0);
|
||||
return m->data_off;
|
||||
}
|
||||
|
||||
static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf* m) {
|
||||
m->data_off = (uint16_t)RTE_PKTMBUF_HEADROOM;
|
||||
//(uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len);
|
||||
}
|
||||
|
||||
static inline void rte_pktmbuf_reset(struct rte_mbuf* m) {
|
||||
m->next = NULL;
|
||||
m->pkt_len = 0;
|
||||
m->tx_offload = 0;
|
||||
m->vlan_tci = 0;
|
||||
m->vlan_tci_outer = 0;
|
||||
m->nb_segs = 1;
|
||||
m->port = UINT16_MAX;
|
||||
|
||||
m->ol_flags &= (1ULL << 61);
|
||||
m->packet_type = 0;
|
||||
rte_pktmbuf_reset_headroom(m);
|
||||
|
||||
m->data_len = 0;
|
||||
__rte_mbuf_sanity_check(m, 1);
|
||||
}
|
||||
|
||||
static struct rte_mbuf* rte_pktmbuf_alloc(struct rte_mempool* mp) {
|
||||
|
||||
struct rte_mbuf* m = NULL;
|
||||
m = new struct rte_mbuf;
|
||||
if (m != NULL) {
|
||||
m->refcnt = 1;
|
||||
m->nb_segs = 1;
|
||||
m->next = NULL;
|
||||
rte_pktmbuf_reset(m);
|
||||
|
||||
m->buf_addr = new uint8_t[2000];
|
||||
m->buf_len = 0;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static inline void rte_pktmbuf_free(struct rte_mbuf* m) {
|
||||
struct rte_mbuf* m_next;
|
||||
|
||||
if (m != NULL)
|
||||
__rte_mbuf_sanity_check(m, 1);
|
||||
|
||||
delete[] m->buf_addr;
|
||||
m->buf_addr = nullptr;
|
||||
|
||||
while (m != NULL) {
|
||||
m_next = m->next;
|
||||
delete m;
|
||||
m = m_next;
|
||||
}
|
||||
}
|
||||
|
||||
static inline char* rte_pktmbuf_prepend(struct rte_mbuf* m, uint16_t len) {
|
||||
__rte_mbuf_sanity_check(m, 1);
|
||||
|
||||
if (unlikely(len > rte_pktmbuf_headroom(m))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* NB: elaborating the subtraction like this instead of using
|
||||
* -= allows us to ensure the result type is uint16_t
|
||||
* avoiding compiler warnings on gcc 8.1 at least */
|
||||
m->data_off = static_cast<uint16_t>(m->data_off - len);
|
||||
m->data_len = static_cast<uint16_t>(m->data_len + len);
|
||||
m->pkt_len = (m->pkt_len + len);
|
||||
|
||||
return (char*)m->buf_addr + m->data_off;
|
||||
}
|
||||
|
||||
static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf* m) {
|
||||
__rte_mbuf_sanity_check(m, 0);
|
||||
return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) - m->data_len);
|
||||
}
|
||||
|
||||
static inline struct rte_mbuf* rte_pktmbuf_lastseg(struct rte_mbuf* m) {
|
||||
__rte_mbuf_sanity_check(m, 1);
|
||||
while (m->next != NULL)
|
||||
m = m->next;
|
||||
return m;
|
||||
}
|
||||
|
||||
static inline char* rte_pktmbuf_append(struct rte_mbuf* m, uint16_t len) {
|
||||
void* tail;
|
||||
struct rte_mbuf* m_last;
|
||||
|
||||
__rte_mbuf_sanity_check(m, 1);
|
||||
|
||||
m_last = rte_pktmbuf_lastseg(m);
|
||||
if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
|
||||
return NULL;
|
||||
|
||||
tail = (char*)m_last->buf_addr + m_last->data_off + m_last->data_len;
|
||||
m_last->data_len = (uint16_t)(m_last->data_len + len);
|
||||
m->pkt_len = (m->pkt_len + len);
|
||||
return (char*)tail;
|
||||
}
|
183
test/libdpdk_dummy/include/rte_mbuf_core.h
Normal file
183
test/libdpdk_dummy/include/rte_mbuf_core.h
Normal file
@ -0,0 +1,183 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_common.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define rte_pktmbuf_mtod_offset(m, t, o) \
|
||||
((t)((char*)(m)->buf_addr + (m)->data_off + (o)))
|
||||
|
||||
#define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
|
||||
|
||||
#define PKT_RX_VLAN (1ULL << 0)
|
||||
|
||||
#define PKT_RX_RSS_HASH (1ULL << 1)
|
||||
|
||||
#define PKT_RX_FDIR (1ULL << 2)
|
||||
|
||||
#define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
|
||||
|
||||
#define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
|
||||
|
||||
#define PKT_RX_OUTER_IP_CKSUM_BAD (1ULL << 5)
|
||||
|
||||
#define PKT_RX_EIP_CKSUM_BAD \
|
||||
RTE_DEPRECATED(PKT_RX_EIP_CKSUM_BAD) PKT_RX_OUTER_IP_CKSUM_BAD
|
||||
|
||||
#define PKT_RX_VLAN_STRIPPED (1ULL << 6)
|
||||
|
||||
#define PKT_RX_IP_CKSUM_MASK ((1ULL << 4) | (1ULL << 7))
|
||||
|
||||
#define PKT_RX_IP_CKSUM_UNKNOWN 0
|
||||
#define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
|
||||
#define PKT_RX_IP_CKSUM_GOOD (1ULL << 7)
|
||||
#define PKT_RX_IP_CKSUM_NONE ((1ULL << 4) | (1ULL << 7))
|
||||
|
||||
#define PKT_RX_L4_CKSUM_MASK ((1ULL << 3) | (1ULL << 8))
|
||||
|
||||
#define PKT_RX_L4_CKSUM_UNKNOWN 0
|
||||
#define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
|
||||
#define PKT_RX_L4_CKSUM_GOOD (1ULL << 8)
|
||||
#define PKT_RX_L4_CKSUM_NONE ((1ULL << 3) | (1ULL << 8))
|
||||
|
||||
#define PKT_RX_IEEE1588_PTP (1ULL << 9)
|
||||
|
||||
#define PKT_RX_IEEE1588_TMST (1ULL << 10)
|
||||
|
||||
#define PKT_RX_FDIR_ID (1ULL << 13)
|
||||
|
||||
#define PKT_RX_FDIR_FLX (1ULL << 14)
|
||||
|
||||
#define PKT_RX_QINQ_STRIPPED (1ULL << 15)
|
||||
|
||||
#define PKT_RX_LRO (1ULL << 16)
|
||||
|
||||
/* There is no flag defined at offset 17. It is free for any future use. */
|
||||
|
||||
#define PKT_RX_SEC_OFFLOAD (1ULL << 18)
|
||||
|
||||
#define PKT_RX_SEC_OFFLOAD_FAILED (1ULL << 19)
|
||||
|
||||
#define PKT_RX_QINQ (1ULL << 20)
|
||||
|
||||
#define PKT_RX_OUTER_L4_CKSUM_MASK ((1ULL << 21) | (1ULL << 22))
|
||||
|
||||
#define PKT_RX_OUTER_L4_CKSUM_UNKNOWN 0
|
||||
#define PKT_RX_OUTER_L4_CKSUM_BAD (1ULL << 21)
|
||||
#define PKT_RX_OUTER_L4_CKSUM_GOOD (1ULL << 22)
|
||||
#define PKT_RX_OUTER_L4_CKSUM_INVALID ((1ULL << 21) | (1ULL << 22))
|
||||
|
||||
/* add new RX flags here, don't forget to update PKT_FIRST_FREE */
|
||||
|
||||
#define PKT_FIRST_FREE (1ULL << 23)
|
||||
#define PKT_LAST_FREE (1ULL << 40)
|
||||
|
||||
/* add new TX flags here, don't forget to update PKT_LAST_FREE */
|
||||
|
||||
#define PKT_TX_OUTER_UDP_CKSUM (1ULL << 41)
|
||||
|
||||
#define PKT_TX_UDP_SEG (1ULL << 42)
|
||||
|
||||
#define PKT_TX_SEC_OFFLOAD (1ULL << 43)
|
||||
|
||||
#define PKT_TX_MACSEC (1ULL << 44)
|
||||
|
||||
#define PKT_TX_TUNNEL_VXLAN (0x1ULL << 45)
|
||||
#define PKT_TX_TUNNEL_GRE (0x2ULL << 45)
|
||||
#define PKT_TX_TUNNEL_IPIP (0x3ULL << 45)
|
||||
#define PKT_TX_TUNNEL_GENEVE (0x4ULL << 45)
|
||||
|
||||
#define PKT_TX_TUNNEL_MPLSINUDP (0x5ULL << 45)
|
||||
#define PKT_TX_TUNNEL_VXLAN_GPE (0x6ULL << 45)
|
||||
#define PKT_TX_TUNNEL_GTP (0x7ULL << 45)
|
||||
|
||||
#define PKT_TX_TUNNEL_IP (0xDULL << 45)
|
||||
|
||||
#define PKT_TX_TUNNEL_UDP (0xEULL << 45)
|
||||
/* add new TX TUNNEL type here */
|
||||
#define PKT_TX_TUNNEL_MASK (0xFULL << 45)
|
||||
|
||||
#define PKT_TX_QINQ (1ULL << 49)
|
||||
|
||||
#define PKT_TX_QINQ_PKT PKT_TX_QINQ
|
||||
|
||||
#define PKT_TX_TCP_SEG (1ULL << 50)
|
||||
|
||||
#define PKT_TX_IEEE1588_TMST (1ULL << 51)
|
||||
|
||||
#define PKT_TX_L4_NO_CKSUM (0ULL << 52)
|
||||
#define PKT_TX_TCP_CKSUM (1ULL << 52)
|
||||
|
||||
#define PKT_TX_SCTP_CKSUM (2ULL << 52)
|
||||
|
||||
#define PKT_TX_UDP_CKSUM (3ULL << 52)
|
||||
|
||||
#define PKT_TX_L4_MASK (3ULL << 52)
|
||||
|
||||
#define PKT_TX_IP_CKSUM (1ULL << 54)
|
||||
|
||||
#define PKT_TX_IPV4 (1ULL << 55)
|
||||
|
||||
#define PKT_TX_IPV6 (1ULL << 56)
|
||||
|
||||
#define PKT_TX_VLAN (1ULL << 57)
|
||||
/* this old name is deprecated */
|
||||
#define PKT_TX_VLAN_PKT PKT_TX_VLAN
|
||||
|
||||
#define PKT_TX_OUTER_IP_CKSUM (1ULL << 58)
|
||||
|
||||
#define PKT_TX_OUTER_IPV4 (1ULL << 59)
|
||||
|
||||
#define PKT_TX_OUTER_IPV6 (1ULL << 60)
|
||||
|
||||
enum {
|
||||
RTE_MBUF_L2_LEN_BITS = 7,
|
||||
RTE_MBUF_L3_LEN_BITS = 9,
|
||||
RTE_MBUF_L4_LEN_BITS = 8,
|
||||
RTE_MBUF_TSO_SEGSZ_BITS = 16,
|
||||
RTE_MBUF_OUTL3_LEN_BITS = 9,
|
||||
RTE_MBUF_OUTL2_LEN_BITS = 7
|
||||
};
|
||||
|
||||
struct rte_mbuf {
|
||||
void* buf_addr;
|
||||
uint16_t buf_len;
|
||||
|
||||
struct rte_mbuf* next;
|
||||
uint32_t pkt_len;
|
||||
uint16_t vlan_tci;
|
||||
uint16_t vlan_tci_outer;
|
||||
uint16_t nb_segs;
|
||||
uint16_t port;
|
||||
uint64_t ol_flags;
|
||||
uint32_t packet_type;
|
||||
uint16_t data_len;
|
||||
uint16_t data_off;
|
||||
uint16_t refcnt;
|
||||
|
||||
/* fields to support TX offloads */
|
||||
RTE_STD_C11
|
||||
union {
|
||||
uint64_t tx_offload;
|
||||
__extension__ struct {
|
||||
uint64_t l2_len : RTE_MBUF_L2_LEN_BITS;
|
||||
uint64_t l3_len : RTE_MBUF_L3_LEN_BITS;
|
||||
uint64_t l4_len : RTE_MBUF_L4_LEN_BITS;
|
||||
uint64_t tso_segsz : RTE_MBUF_TSO_SEGSZ_BITS;
|
||||
/*
|
||||
* Fields for Tx offloading of tunnels.
|
||||
* These are undefined for packets which don't request
|
||||
* any tunnel offloads (outer IP or UDP checksum,
|
||||
* tunnel TSO).
|
||||
*
|
||||
* PMDs should not use these fields unconditionally
|
||||
* when calculating offsets.
|
||||
*
|
||||
* Applications are expected to set appropriate tunnel
|
||||
* offload flags when they fill in these fields.
|
||||
*/
|
||||
uint64_t outer_l3_len : RTE_MBUF_OUTL3_LEN_BITS;
|
||||
uint64_t outer_l2_len : RTE_MBUF_OUTL2_LEN_BITS;
|
||||
/* uint64_t unused:RTE_MBUF_TXOFLD_UNUSED_BITS; */
|
||||
};
|
||||
};
|
||||
};
|
3
test/libdpdk_dummy/include/rte_mempool.h
Normal file
3
test/libdpdk_dummy/include/rte_mempool.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
struct rte_mempool {};
|
16
test/libdpdk_dummy/include/rte_tcp.h
Normal file
16
test/libdpdk_dummy/include/rte_tcp.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct rte_tcp_hdr {
|
||||
rte_be16_t src_port;
|
||||
rte_be16_t dst_port;
|
||||
rte_be32_t sent_seq;
|
||||
rte_be32_t recv_ack;
|
||||
uint8_t data_off;
|
||||
uint8_t tcp_flags;
|
||||
rte_be16_t rx_win;
|
||||
rte_be16_t cksum;
|
||||
rte_be16_t tcp_urp;
|
||||
} __attribute__((__packed__));
|
10
test/libdpdk_dummy/include/rte_udp.h
Normal file
10
test/libdpdk_dummy/include/rte_udp.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
|
||||
struct rte_udp_hdr {
|
||||
rte_be16_t src_port;
|
||||
rte_be16_t dst_port;
|
||||
rte_be16_t dgram_len;
|
||||
rte_be16_t dgram_cksum;
|
||||
} __attribute__((__packed__));
|
14
test/libdpdk_dummy/libdpdk_dummy_test.cpp
Normal file
14
test/libdpdk_dummy/libdpdk_dummy_test.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_mempool.h>
|
||||
|
||||
TEST_CASE("rte_mbuf", "[]") {
|
||||
struct rte_mbuf* mbuf;
|
||||
struct rte_mempool* mempool = nullptr;
|
||||
|
||||
mbuf = rte_pktmbuf_alloc(mempool);
|
||||
CHECK(mbuf != nullptr);
|
||||
}
|
15
test/meson.build
Normal file
15
test/meson.build
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
# ..each entry will be a test executable
|
||||
# ..the structure of the test directory should be equivalent
|
||||
# ..to the structure in source/ or include/
|
||||
|
||||
# Syntax:
|
||||
# 'Name of the Test (e.g. class name)' : 'Path/to/source/file'
|
||||
test_sources_dict = {
|
||||
#'PacketInfo' : 'test/PacketDissection/PacketInfo_test.cpp',
|
||||
'PacketContainer' : 'test/PacketDissection/PacketContainer_test.cpp',
|
||||
'Configurator' : 'test/ConfigurationManagement/Configurator_test.cpp',
|
||||
'libdpdk_dummy' : 'test/libdpdk_dummy/libdpdk_dummy_test.cpp',
|
||||
'Treatment' : 'test/Treatment/Treatment_test.cpp',
|
||||
'RandomNumberGenerator' : 'test/RandomNumberGenerator/RandomNumberGenerator_test.cpp',
|
||||
}
|
Loading…
Reference in New Issue
Block a user