Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions alphartc_gym/tests/data/rtt/trace_rtt_200.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"type": "video",
"downlink": {},
"uplink": {
"trace_pattern": [
{
"duration": 1000,
"capacity": 1000,
"rtt": 200,
"loss": 0,
"jitter": 0,
"time": 0.0
}
]
}
}
16 changes: 16 additions & 0 deletions alphartc_gym/tests/data/rtt/trace_rtt_400.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"type": "video",
"downlink": {},
"uplink": {
"trace_pattern": [
{
"duration": 1000,
"capacity": 1000,
"rtt": 400,
"loss": 0,
"jitter": 0,
"time": 0.0
}
]
}
}
16 changes: 16 additions & 0 deletions alphartc_gym/tests/data/rtt/trace_rtt_600.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"type": "video",
"downlink": {},
"uplink": {
"trace_pattern": [
{
"duration": 1000,
"capacity": 1000,
"rtt": 600,
"loss": 0,
"jitter": 0,
"time": 0.0
}
]
}
}
24 changes: 24 additions & 0 deletions alphartc_gym/tests/data/rtt/trace_rtt_pattern_2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"type": "video",
"downlink": {},
"uplink": {
"trace_pattern": [
{
"duration": 2000,
"capacity": 1000,
"loss": 0,
"rtt": 200,
"jitter": 0,
"time": 0.0
},
{
"duration": 2000,
"capacity": 1000,
"loss": 0,
"rtt": 400,
"jitter": 0,
"time": 0.0
}
]
}
}
32 changes: 32 additions & 0 deletions alphartc_gym/tests/data/rtt/trace_rtt_pattern_3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"type": "video",
"downlink": {},
"uplink": {
"trace_pattern": [
{
"duration": 2000,
"capacity": 1000,
"loss": 0,
"rtt": 200,
"jitter": 0,
"time": 0.0
},
{
"duration": 2000,
"capacity": 1000,
"loss": 0,
"rtt": 200,
"jitter": 0,
"time": 0.0
},
{
"duration": 2000,
"capacity": 1000,
"loss": 0,
"rtt": 200,
"jitter": 0,
"time": 0.0
}
]
}
}
40 changes: 40 additions & 0 deletions alphartc_gym/tests/data/rtt/trace_rtt_pattern_4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"type": "video",
"downlink": {},
"uplink": {
"trace_pattern": [
{
"duration": 2000,
"capacity": 1000,
"loss": 0,
"rtt": 200,
"jitter": 0,
"time": 0.0
},
{
"duration": 2000,
"capacity": 1000,
"loss": 0,
"rtt": 400,
"jitter": 0,
"time": 0.0
},
{
"duration": 2000,
"capacity": 1000,
"loss": 0,
"rtt": 300,
"jitter": 0,
"time": 0.0
},
{
"duration": 2000,
"capacity": 1000,
"loss": 0,
"rtt": 500,
"jitter": 0,
"time": 0.0
}
]
}
}
114 changes: 114 additions & 0 deletions alphartc_gym/tests/test_gym_rtt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from alphartc_gym import gym
import os, json


ERROR = 0.05


def get_gym_stats(trace_path, duration_time_ms=3000, bandwidth_bps=1000):
total_stats = []
g = gym.Gym()
g.reset(trace_path=trace_path, duration_time_ms=duration_time_ms)

while True:
stats, done = g.step(bandwidth_bps)
if not done:
total_stats += stats
else:
return total_stats


def cal_pkt_transmit_time_ms(header_bytes, payload_bytes, bw_kps):
return (header_bytes + payload_bytes) * 8 / bw_kps


def get_info_from_trace(trace_file):
with open(trace_file, 'r') as f:
return json.loads(f.read())


def get_abs_path_by_name(trace_name):
trace_path = os.path.join(
os.path.dirname(__file__),
"data/rtt",
trace_name)
return trace_path


def single_rtt_available(trace_path):
total_stats = get_gym_stats(trace_path)
assert (total_stats)

for stats in total_stats:
assert (isinstance(stats, dict))


def single_rtt_persistence(trace_path):
# get information from trace
trace_data = get_info_from_trace(trace_path)
trace_pattern = trace_data["uplink"]["trace_pattern"]
one_way_delay = trace_pattern[0]["rtt"] / 2
bandwidth_kbps = trace_pattern[0]["capacity"]

total_stats = get_gym_stats(trace_path)
assert (total_stats)

for status in total_stats:
transmission_delay = cal_pkt_transmit_time_ms(status["header_length"],
status["payload_size"], bw_kps=bandwidth_kbps)
predict_arrival_time_ms = status["send_time_ms"] + one_way_delay + transmission_delay
assert abs(status["arrival_time_ms"] - predict_arrival_time_ms) <= ERROR * status["arrival_time_ms"]


def single_rtt_dynamically(trace_path, run_times=1):
# get information from trace
trace_data = get_info_from_trace(trace_path)
trace_pattern = trace_data["uplink"]["trace_pattern"]
one_way_delay_list = sorted([item["rtt"] / 2 for item in trace_pattern])
rtt_sample_cnt = [0] * len(one_way_delay_list)
bandwidth_kbps = trace_pattern[0]["capacity"]
duration_time_ms = sum([item["duration"] for item in trace_pattern]) * run_times

total_stats = get_gym_stats(trace_path, duration_time_ms=duration_time_ms)
assert (total_stats)

for status in total_stats:
transmission_delay = cal_pkt_transmit_time_ms(status["header_length"],
status["payload_size"], bw_kps=bandwidth_kbps)
actual_delay = status["arrival_time_ms"] - status["send_time_ms"] - transmission_delay
rtt_in_trace = False
for i in range(len(one_way_delay_list)):
if abs(actual_delay - one_way_delay_list[i]) <= ERROR * one_way_delay_list[i]:
rtt_sample_cnt[i] += 1
rtt_in_trace = True

assert rtt_in_trace == True, "actual rtt not exist in trace"

for i in range(len(rtt_sample_cnt)):
assert rtt_sample_cnt[i] > 0
if i:
assert abs(rtt_sample_cnt[i-1] - rtt_sample_cnt[i]) <= ERROR * rtt_sample_cnt[i]


def test_rtt_available():
traces_name = ["trace_rtt_200.json", "trace_rtt_400.json", "trace_rtt_600.json"]
for trace in traces_name:
trace_path = get_abs_path_by_name(trace)
single_rtt_available(trace_path)


def test_rtt_persistence():
traces_name = ["trace_rtt_200.json", "trace_rtt_400.json", "trace_rtt_600.json"]
for trace in traces_name:
trace_path = get_abs_path_by_name(trace)
single_rtt_persistence(trace_path)


def test_rtt_dynamically():
traces_name = ["trace_rtt_pattern_2.json", "trace_rtt_pattern_3.json", "trace_rtt_pattern_4.json"]
for trace in traces_name:
trace_path = get_abs_path_by_name(trace)
single_rtt_dynamically(trace_path, run_times=20)
9 changes: 9 additions & 0 deletions ns-app/scratch/webrtc_test/trace_player.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "ns3/point-to-point-net-device.h"
#include "ns3/simulator.h"
#include "ns3/string.h"
#include "ns3/channel.h"

#include <nlohmann/json.hpp>
#include <boost/lexical_cast.hpp>
Expand Down Expand Up @@ -40,6 +42,9 @@ void TracePlayer::LoadTrace() {
TraceItem ti;
ti.capacity_ = lexical_cast<decltype(ti.capacity_)>(trace["capacity"]);
ti.duration_ms_ = lexical_cast<decltype(ti.duration_ms_)>(trace["duration"]);
if (trace.find("rtt") != trace.end()) {
ti.rtt_ms_ = lexical_cast<std::uint64_t>(trace["rtt"]);
}
traces.push_back(std::move(ti));
}
traces_.swap(traces);
Expand All @@ -55,6 +60,10 @@ void TracePlayer::PlayTrace(size_t trace_index) {
const auto &trace = traces_[trace_index];
for (size_t i = 0; i < nodes_.GetN(); i++) {
auto node = nodes_.Get(i);
// set delay in channel
if (trace.rtt_ms_) {
node->GetDevice(0)->GetChannel()->SetAttribute("Delay", StringValue(std::to_string(trace.rtt_ms_.value()/2.0) + "ms"));
}
for (size_t j = 0; j < node->GetNDevices(); j++) {
auto device =
dynamic_cast<PointToPointNetDevice *>(PeekPointer(node->GetDevice(j)));
Expand Down
2 changes: 2 additions & 0 deletions ns-app/scratch/webrtc_test/trace_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
#include <string>
#include <cinttypes>
#include <vector>
#include <boost/optional.hpp>

struct TraceItem {
std::uint64_t capacity_;
std::uint64_t duration_ms_;
boost::optional<std::uint64_t> rtt_ms_;
};

class TracePlayer {
Expand Down