Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

mm-file-delay: Emulating variable-delay links #135

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions scripts/mm-delay-graph
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ my @signal_delay_samples = sort { $a <=> $b } keys %signal_delay;

for ( my $ts = $signal_delay_samples[ -1 ]; $ts >= $signal_delay_samples[ 0 ]; $ts-- ) {
if ( not defined $signal_delay{ $ts } ) {
$signal_delay{ $ts } = $signal_delay{ $ts + 1 } + 1;
$signal_delay{ $ts } = $signal_delay{ $ts + 1 };
}
}

Expand All @@ -135,7 +135,7 @@ my $graph_max = $signal_delays[-1] * 1.2;
# make graph
open GNUPLOT, q{| gnuplot} or die;

my $lower_limit = min( 30, int $pp50 );
my $lower_limit = 0;

print GNUPLOT <<END;
set xlabel "time (s)"
Expand All @@ -144,7 +144,7 @@ set logscale y
set yrange [$lower_limit:$graph_max]
set ytics add ($lower_limit)
set key center outside top horizontal
set terminal svg size 1024,560 fixed enhanced fname 'Arial' solid mouse standalone name "Delay"
set terminal png size 1024,560
set output "/dev/stdout"
END

Expand Down
12 changes: 9 additions & 3 deletions scripts/mm-throughput-graph
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ LINE: while ( <> ) {

# parse and validate line
my ( $timestamp, $event_type, $num_bytes, $delay ) = split /\s+/, $_;

if ($event_type eq q{d}){
$num_bytes = $delay;
$delay = 0;
}
if ( not defined $num_bytes ) {
die q{Format: timestamp event_type num_bytes [delay]};
}
Expand Down Expand Up @@ -110,6 +113,9 @@ LINE: while ( <> ) {
(defined $signal_delay{ $timestamp - $delay })
? $signal_delay{ $timestamp - $delay }
: POSIX::DBL_MAX );
} elsif ( $event_type eq q{d} ) {
$capacity{ $bin } -= $num_bits;
$capacity_sum -= $num_bits;
} else {
die qq{Unknown event type: $event_type};
}
Expand Down Expand Up @@ -163,7 +169,7 @@ my @signal_delay_samples = sort { $a <=> $b } keys %signal_delay;

for ( my $ts = $signal_delay_samples[ -1 ]; $ts >= $signal_delay_samples[ 0 ]; $ts-- ) {
if ( not defined $signal_delay{ $ts } ) {
$signal_delay{ $ts } = $signal_delay{ $ts + 1 } + 1;
$signal_delay{ $ts } = $signal_delay{ $ts + 1 };
}
}

Expand Down Expand Up @@ -196,7 +202,7 @@ set xlabel "time (s)"
set ylabel "throughput (Mbits/s)"
set key center outside top horizontal
set style fill solid 0.2 noborder
set terminal svg size 1024,560 fixed fname 'Arial' rounded solid mouse standalone name "Throughput"
set terminal png size 1024,560
set output "/dev/stdout"
END

Expand Down
7 changes: 7 additions & 0 deletions src/frontend/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ mm_delay_SOURCES = delayshell.cc delay_queue.hh delay_queue.cc
mm_delay_LDADD = -lrt ../util/libutil.a ../packet/libpacket.a
mm_delay_LDFLAGS = -pthread

bin_PROGRAMS += mm-file-delay
mm_file_delay_SOURCES = filedelayshell.cc file_delay_queue.hh file_delay_queue.cc
mm_file_delay_LDADD = -lrt ../util/libutil.a ../packet/libpacket.a
mm_file_delay_LDFLAGS = -pthread

bin_PROGRAMS += mm-loss
mm_loss_SOURCES = lossshell.cc loss_queue.hh loss_queue.cc
mm_loss_LDADD = -lrt ../util/libutil.a ../packet/libpacket.a
Expand Down Expand Up @@ -49,6 +54,8 @@ libmod_deepcgi_la_CPPFLAGS = # empty
install-exec-hook:
chown root $(DESTDIR)$(bindir)/mm-delay
chmod u+s $(DESTDIR)$(bindir)/mm-delay
chown root $(DESTDIR)$(bindir)/mm-file-delay
chmod u+s $(DESTDIR)$(bindir)/mm-file-delay
chown root $(DESTDIR)$(bindir)/mm-loss
chmod u+s $(DESTDIR)$(bindir)/mm-loss
chown root $(DESTDIR)$(bindir)/mm-onoff
Expand Down
59 changes: 59 additions & 0 deletions src/frontend/file_delay_queue.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* -*-mode:c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

#include <limits>
#include <fstream>
#include <iostream>
#include "file_delay_queue.hh"
#include "timestamp.hh"

using namespace std;

FileDelayQueue::FileDelayQueue(const std::string & delay_file_name, uint64_t time_res_ms) : delays_(), time_res_ms_(time_res_ms), packet_queue_()
{
ifstream delay_file(delay_file_name);
uint64_t delay;

if (not delay_file.good()) {
throw runtime_error(delay_file_name + ": error while opening for reading.");
}

/* Read file, line-by-line. */
string line;
while (delay_file.good() and getline(delay_file, line))
{
delay = stoi(line);
delays_.push_back(delay);
}
}

void FileDelayQueue::read_packet( const string & contents )
{
uint64_t packet_timestamp = timestamp();
uint64_t delay_index = packet_timestamp/time_res_ms_;
uint64_t delay = delays_[delay_index % delays_.size()];
packet_queue_.emplace(packet_timestamp + delay, contents );
}

void FileDelayQueue::write_packets( FileDescriptor & fd )
{
while ( (!packet_queue_.empty())
&& (packet_queue_.front().first <= timestamp()) ) {
fd.write( packet_queue_.front().second );
packet_queue_.pop();
}
}

unsigned int FileDelayQueue::wait_time( void ) const
{
if ( packet_queue_.empty() ) {
return numeric_limits<uint16_t>::max();
}

const auto now = timestamp();

if ( packet_queue_.front().first <= now ) {
return 0;
} else {
return packet_queue_.front().first - now;
}
}
34 changes: 34 additions & 0 deletions src/frontend/file_delay_queue.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* -*-mode:c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

#ifndef FILE_DELAY_QUEUE_HH
#define FILE_DELAY_QUEUE_HH

#include <queue>
#include <cstdint>
#include <string>
#include "file_descriptor.hh"

class FileDelayQueue
{
private:
std::vector< uint64_t > delays_;
uint64_t time_res_ms_;
std::queue< std::pair<uint64_t, std::string> > packet_queue_;
/* release timestamp, contents */

public:

FileDelayQueue(const std::string & delay_file_name, uint64_t time_res_ms);

void read_packet( const std::string & contents );

void write_packets( FileDescriptor & fd );

unsigned int wait_time( void ) const;

bool pending_output( void ) const { return wait_time() <= 0; }

static bool finished( void ) { return false; }
};

#endif /* FILE_DELAY_QUEUE_HH */
48 changes: 48 additions & 0 deletions src/frontend/filedelayshell.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* -*-mode:c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

#include <vector>
#include <string>

#include "file_delay_queue.hh"
#include "util.hh"
#include "ezio.hh"
#include "packetshell.cc"

using namespace std;

int main( int argc, char *argv[] )
{
try {
/* clear environment while running as root */
char ** const user_environment = environ;
environ = nullptr;

check_requirements( argc, argv );

if ( argc < 3 ) {
throw runtime_error( "Usage: " + string( argv[ 0 ] ) + " delay_file_name time_resolution_ms [command...]" );
}

string delay_file = argv[1];
uint64_t time_res_ms = std::stoi(argv[2]);

vector< string > command;

if ( argc == 3 ) {
command.push_back( shell_path() );
} else {
for ( int i = 3; i < argc; i++ ) {
command.push_back( argv[ i ] );
}
}

PacketShell<FileDelayQueue> file_delay_shell_app( "file-delay", user_environment );

file_delay_shell_app.start_uplink( "[delay " + delay_file + "]", command, delay_file, time_res_ms);
file_delay_shell_app.start_downlink( delay_file, time_res_ms );
return file_delay_shell_app.wait_for_exit();
} catch ( const exception & e ) {
print_exception( e );
return EXIT_FAILURE;
}
}
Binary file added src/frontend/mm-file-delay
Binary file not shown.