Commit 44cca42d authored by Andreas Schmidt's avatar Andreas Schmidt

Implement loss gathering type.

parent c3b549f4
Pipeline #90 failed with stage
......@@ -8,6 +8,8 @@
#define MAX_PAYLOAD_LENGTH 65528 // maximum UDP packet length (2^16 - 8)
#define SEQNO_SPACE UINT16_MAX // 2**16 as seqno is uint16_t
#define GF_BITS 8
#define K_START 4
......
add_library(PRRT ../defines.h socket.c block.c block.h packet.c packet.h receiver.c receiver.h clock.c clock.h channelStateInformation.c channelStateInformation.h processes/feedbackReceiver.c processes/feedbackReceiver.h processes/dataTransmitter.c processes/dataTransmitter.h codingParams.c codingParams.h vdmcode/block_code.c vdmcode/block_code.h codingParams.c codingParams.h stores/forwardPacketTable.c stores/forwardPacketTable.h processes/dataReceiver.c processes/dataReceiver.h)
add_library(PRRT ../defines.h socket.c block.c block.h packet.c packet.h receiver.c receiver.h clock.c clock.h channelStateInformation.c channelStateInformation.h processes/feedbackReceiver.c processes/feedbackReceiver.h processes/dataTransmitter.c processes/dataTransmitter.h codingParams.c codingParams.h vdmcode/block_code.c vdmcode/block_code.h codingParams.c codingParams.h stores/forwardPacketTable.c stores/forwardPacketTable.h processes/dataReceiver.c processes/dataReceiver.h stores/lossGatherer.c stores/lossGatherer.h)
set_property(TARGET PRRT PROPERTY C_STANDARD 99)
\ No newline at end of file
......@@ -27,8 +27,6 @@ typedef struct prrtPacket {
#define PRRT_PACKET_GENERAL_HEADER_SIZE 8
#define PRRT_PACKET_ENCODED_GENERAL_HEADER_LENGTH 4
#define SEQNO_SPACE UINT16_MAX // 2**16 as seqno is uint16_t
typedef struct prrtPacketDataPayload {
uint32_t timestamp;
uint16_t group_round_trip_time;
......
......@@ -5,6 +5,7 @@
#include <string.h>
#include <unistd.h>
#include <sys/poll.h>
#include <assert.h>
#include "../defines.h"
#include "packet.h"
#include "../util/dbg.h"
......@@ -19,6 +20,7 @@
PrrtSocket *PrrtSocket_create(const uint8_t is_sender)
{
assert(sizeof(float) == 4);
PrrtSocket *sock_ptr = (PrrtSocket*) calloc(1, sizeof(PrrtSocket));
check_mem(sock_ptr);
......
#include <stddef.h>
#include <malloc.h>
#include "../../defines.h"
#include "../../util/common.h"
#include "../../util/dbg.h"
#include "lossGatherer.h"
LossGatherer *LossGatherer_create()
{
LossGatherer *lg = calloc(1, sizeof(LossGatherer));
check_mem(lg);
lg->bitmap = Bitmap_create(false, SEQNO_SPACE);
return lg;
error:
PERROR("Could not create loss gatherer.%s", "");
return NULL;
}
bool LossGatherer_destroy(LossGatherer *lossGatherer)
{
Bitmap_destroy(lossGatherer->bitmap);
free(lossGatherer);
return true;
}
LossStatistics LossGatherer_calculate_statistics(LossGatherer *lossGatherer, uint32_t start, uint16_t length)
{
check(length != 0, "Cannot calculate stats over empty sequence.");
bool x0 = LossGatherer_check_loss(lossGatherer, start);
LossStatistics statistics = {
.errorCount = (uint16_t) x0,
.packetCount = length,
.gapCount = (uint16_t) x0,
.burstCount = (uint16_t) (1 - ((uint16_t) x0)),
};
statistics.gapLength = statistics.gapCount;
statistics.burstLength = statistics.burstCount;
bool isInGap = x0;
uint16_t i = 0;
for(i = 1; i < length; i++) {
bool currentPosition = LossGatherer_check_loss(lossGatherer, start + i);
statistics.errorCount += currentPosition;
if(isInGap && currentPosition) {
statistics.gapLength++;
} else if(isInGap && (currentPosition == false)) {
isInGap = false;
statistics.burstCount++;
statistics.burstLength++;
} else if((isInGap == false) && currentPosition) {
isInGap = true;
statistics.gapCount++;
statistics.gapLength++;
} else {
statistics.burstLength++;
}
}
return statistics;
error:
PERROR("Stats error.%s","");
}
bool LossGatherer_check_loss(LossGatherer *lossGatherer, uint32_t sequenceNumber)
{
return Bitmap_get(lossGatherer->bitmap, sequenceNumber);
}
bool LossGatherer_mark_loss(LossGatherer *lossGatherer, uint32_t sequenceNumber)
{
return Bitmap_set(lossGatherer->bitmap, sequenceNumber, true);
}
#ifndef PRRT_LOSSGATHERER_H
#define PRRT_LOSSGATHERER_H
#include "../../util/bitmap.h"
typedef struct lossGatherer {
Bitmap* bitmap;
uint16_t start;
} LossGatherer;
typedef struct lossStatistics {
uint16_t packetCount;
uint16_t errorCount;
uint16_t gapLength;
uint16_t gapCount;
uint16_t burstLength;
uint16_t burstCount;
} LossStatistics;
LossGatherer* LossGatherer_create();
LossStatistics LossGatherer_calculate_statistics(LossGatherer *lossGatherer, uint32_t start, uint16_t length);
bool LossGatherer_mark_loss(LossGatherer* lossGatherer, uint32_t sequenceNumber);
bool LossGatherer_check_loss(LossGatherer *lossGatherer, uint32_t sequenceNumber);
bool LossGatherer_destroy(LossGatherer* lossGatherer);
#define LossStatistics_get_packet_loss_rate(stats) (((float) stats.errorCount) / stats.packetCount)
#define LossStatistics_get_avg_gap_length(stats) (((float) stats.gapLength) / stats.gapCount)
#define LossStatistics_get_avg_burst_length(stats) (((float) stats.burstLength) / stats.burstCount)
#endif //PRRT_LOSSGATHERER_H
......@@ -32,7 +32,7 @@ bool Bitmap_get(Bitmap *bitmap, uint32_t position)
return (bool) ((bitmap->data[byte_offset] & (1 << bit_offset)) != 0);
}
void Bitmap_set(Bitmap *bitmap, uint32_t position, bool value)
bool Bitmap_set(Bitmap *bitmap, uint32_t position, bool value)
{
uint32_t byte_offset = position / 32;
uint32_t bit_offset = position % 32;
......@@ -41,6 +41,7 @@ void Bitmap_set(Bitmap *bitmap, uint32_t position, bool value)
} else {
bitmap->data[byte_offset] &= ~(1 << bit_offset);
}
return true;
}
void Bitmap_set_range(Bitmap *bitmap, uint32_t start, uint32_t length, bool value)
......
......@@ -11,7 +11,7 @@ typedef struct bitmap {
Bitmap *Bitmap_create(bool initialValue, uint32_t elementCount);
bool Bitmap_get(Bitmap* bitmap, uint32_t position);
void Bitmap_set(Bitmap* bitmap, uint32_t position, bool value);
bool Bitmap_set(Bitmap* bitmap, uint32_t position, bool value);
void Bitmap_set_range(Bitmap *bitmap, uint32_t start, uint32_t length, bool value);
uint32_t Bitmap_sum_ones(Bitmap *bitmap, uint32_t start, uint32_t length);
uint32_t Bitmap_sum_zeros(Bitmap *bitmap, uint32_t start, uint32_t length);
......
add_subdirectory(lib/gtest-1.7.0)
include_directories(SYSTEM ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
add_executable(prrtTests bitmap_tests.cpp forward_packet_table_tests.cpp bptree_tests.cpp PrrtBlock_tests.cpp)
add_executable(prrtTests bitmap_tests.cpp lossGatherer_tests.cpp forward_packet_table_tests.cpp bptree_tests.cpp PrrtBlock_tests.cpp)
set_property(TARGET prrtTests PROPERTY C_STANDARD 99)
target_link_libraries(prrtTests LINK_PUBLIC PRRT UTIL gtest gtest_main)
\ No newline at end of file
#include <gtest/gtest.h>
extern "C" {
#include "src/prrt/stores/lossGatherer.h"
}
class LossGathererTest : public ::testing::Test {
protected:
virtual void SetUp()
{
lg = LossGatherer_create();
}
virtual void TearDown()
{
LossGatherer_destroy(lg);
}
LossGatherer *lg;
};
TEST_F(LossGathererTest, CreateDestroy)
{
LossGatherer *lg = LossGatherer_create();
void *n = NULL;
ASSERT_NE(n, lg);
ASSERT_NE(n, lg->bitmap);
LossGatherer_destroy(lg);
}
TEST_F(LossGathererTest, CheckLoss)
{
ASSERT_FALSE(LossGatherer_check_loss(lg, 0));
ASSERT_FALSE(LossGatherer_check_loss(lg, 1));
ASSERT_FALSE(LossGatherer_check_loss(lg, 2));
ASSERT_FALSE(LossGatherer_check_loss(lg, 3));
ASSERT_FALSE(LossGatherer_check_loss(lg, 4));
LossGatherer_mark_loss(lg, 2);
LossGatherer_mark_loss(lg, 3);
ASSERT_FALSE(LossGatherer_check_loss(lg, 0));
ASSERT_FALSE(LossGatherer_check_loss(lg, 1));
ASSERT_TRUE(LossGatherer_check_loss(lg, 2));
ASSERT_TRUE(LossGatherer_check_loss(lg, 3));
ASSERT_FALSE(LossGatherer_check_loss(lg, 4));
}
TEST_F(LossGathererTest, CalculateStatistics)
{
LossGatherer_mark_loss(lg, 8);
LossGatherer_mark_loss(lg, 9);
LossStatistics stats = LossGatherer_calculate_statistics(lg, 0, 10);
printf("PC: %d, EC: %d, GC: %d, GL: %d, BC: %d, BL: %d\n", stats.packetCount, stats.errorCount, stats.gapCount,
stats.gapLength, stats.burstCount, stats.burstLength);
ASSERT_EQ(10, stats.packetCount);
ASSERT_EQ(2, stats.errorCount);
ASSERT_EQ(1, stats.gapCount);
ASSERT_EQ(2, stats.gapLength);
ASSERT_EQ(8, stats.burstLength);
ASSERT_EQ(1, stats.burstCount);
LossGatherer_mark_loss(lg, 0);
LossGatherer_mark_loss(lg, 1);
ASSERT_TRUE(LossGatherer_check_loss(lg, 0));
ASSERT_TRUE(LossGatherer_check_loss(lg, 1));
ASSERT_FALSE(LossGatherer_check_loss(lg, 2));
ASSERT_FALSE(LossGatherer_check_loss(lg, 3));
ASSERT_FALSE(LossGatherer_check_loss(lg, 7));
ASSERT_TRUE(LossGatherer_check_loss(lg, 8));
ASSERT_TRUE(LossGatherer_check_loss(lg, 9));
ASSERT_FALSE(LossGatherer_check_loss(lg, 10));
printf("PLR: %f, ABL: %f, AGL: %f\n", LossStatistics_get_packet_loss_rate(stats),
LossStatistics_get_avg_burst_length(stats), LossStatistics_get_avg_gap_length(stats));
stats = LossGatherer_calculate_statistics(lg, 0, 20);
printf("PC: %d, EC: %d, GC: %d, GL: %d, BC: %d, BL: %d\n", stats.packetCount, stats.errorCount, stats.gapCount,
stats.gapLength, stats.burstCount, stats.burstLength);
ASSERT_EQ(20, stats.packetCount);
ASSERT_EQ(4, stats.errorCount);
ASSERT_EQ(2, stats.gapCount);
ASSERT_EQ(4, stats.gapLength);
ASSERT_EQ(16, stats.burstLength);
ASSERT_EQ(2, stats.burstCount);
printf("PLR: %f, ABL: %f, AGL: %f\n", LossStatistics_get_packet_loss_rate(stats),
LossStatistics_get_avg_burst_length(stats), LossStatistics_get_avg_gap_length(stats));
LossGatherer_mark_loss(lg, 2);
LossGatherer_mark_loss(lg, 3);
stats = LossGatherer_calculate_statistics(lg, 0, 20);
printf("PC: %d, EC: %d, GC: %d, GL: %d, BC: %d, BL: %d\n", stats.packetCount, stats.errorCount, stats.gapCount,
stats.gapLength, stats.burstCount, stats.burstLength);
ASSERT_EQ(20, stats.packetCount);
ASSERT_EQ(6, stats.errorCount);
ASSERT_EQ(2, stats.gapCount);
ASSERT_EQ(6, stats.gapLength);
ASSERT_EQ(14, stats.burstLength);
ASSERT_EQ(2, stats.burstCount);
printf("PLR: %f, ABL: %f, AGL: %f\n", LossStatistics_get_packet_loss_rate(stats),
LossStatistics_get_avg_burst_length(stats), LossStatistics_get_avg_gap_length(stats));
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment