From 30c7b88763f488473586559e1efdf6d82f69e843 Mon Sep 17 00:00:00 2001 From: Martin Meszaros Date: Fri, 22 May 2020 17:05:02 +0200 Subject: [PATCH 1/7] Add gitignore --- .gitignore | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a5c935 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Created by https://www.gitignore.io/api/c++ +# Edit at https://www.gitignore.io/?templates=c++ + +### C++ ### +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +cellsim +saturatr +saturatr-m + +# End of https://www.gitignore.io/api/c++ From cf29a1743d2e4e89c92cf6eae2b753eedb59aa5b Mon Sep 17 00:00:00 2001 From: Martin Meszaros Date: Fri, 22 May 2020 17:10:49 +0200 Subject: [PATCH 2/7] Revert "Unfortunately an Ethernet sockaddr_ll is not the full length?!" This reverts commit 7a000d9bb208e14557a7474f4b1c6174a68e4bcd. This seems to no longer be the case, as it causes the following error as soon as a packet should be forwarded: ``` address length = 20 recvfrom (unexpected address length) ``` --- sender/packetsocket.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sender/packetsocket.cc b/sender/packetsocket.cc index db3bc26..526da42 100644 --- a/sender/packetsocket.cc +++ b/sender/packetsocket.cc @@ -86,10 +86,8 @@ vector< string > PacketSocket::recv_raw( void ) exit( 1 ); } - if ( source_address_len != 18 ) { - fprintf( stderr, "address length = %d\n", - source_address_len ); - perror( "recvfrom (unexpected address length)" ); + if ( source_address_len != sizeof( source_address ) ) { + perror( "recvfrom (unexpected address length" ); exit( 1 ); } From a4578226be457dcdc0573102661e084d1e970fa0 Mon Sep 17 00:00:00 2001 From: Martin Meszaros Date: Fri, 22 May 2020 17:17:46 +0200 Subject: [PATCH 3/7] add the binaries to gitignore --- .gitignore | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8a5c935..6e27cc4 100644 --- a/.gitignore +++ b/.gitignore @@ -37,5 +37,9 @@ cellsim saturatr saturatr-m - -# End of https://www.gitignore.io/api/c++ +buffer-setpoint +cellsim-tap +controlled-delay +depend +send1way +# End of http-://www.gitignore.io/api/c++ From 1b2e13b4f5fc4defde676d5e639c5ea300596dbe Mon Sep 17 00:00:00 2001 From: Martin Meszaros Date: Fri, 22 May 2020 17:21:18 +0200 Subject: [PATCH 4/7] Add script to run cellsim. It uses the `mm-delay-graph` and `mm-throughput-graph` scripts from the [https://github.com/ravinet/mahimahi}(Mahimahi) project for graphing. So have it installed or get the scripts from there. It uses the same parameters as cellsim so run it the same way: `./emulate.sh UP_TRACE DOWN TRACE LOSSRATE INTERNET_IF CLIENT_IF [UPLINK_LOG] [DOWNLINK_LOG]` --- emulate.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100755 emulate.sh diff --git a/emulate.sh b/emulate.sh new file mode 100755 index 0000000..a8c9fe0 --- /dev/null +++ b/emulate.sh @@ -0,0 +1,63 @@ +#!/bin/bash +trap 'finalize' 2 + +if [ $# -lt 5 ]; then + echo "Usage : $0 up_trace down_trace lossrate internet_facing_if client_facing_if uplink_log downlink_log" + exit +fi ; + +BRIDGE_NAME="br0" +THROUGHPUT_GRAPH_RESOLUTION=100 + +UP_TRACE="$1" +DOWN_TRACE="$2" +LOSSRATE="$3" +INTERNET_IF="$4" +CLIENT_IF="$5" + +UPLOG_SET=false +DOWNLOG_SET=false + +if [ -z "$6" ] +then + UPLINK_LOG="" +else + UPLOG_SET=true + UPLINK_LOG="$6" +fi + +if [ -z "$7" ] +then + DOWNLINK_LOG="" +else + DOWNLOG_SET=true + DOWNLINK_LOG="$7" +fi + + +finalize(){ + echo "# bringing bridge \"$BRIDGE_NAME\" up" + ifconfig "$BRIDGE_NAME" up + + if [ "$UPLOG_SET" = true ] + then + echo "# generating graphs for uplink from log $UPLINK_LOG..." + mm-delay-graph "$UPLINK_LOG" > $(dirname "${UPLINK_LOG}")/delay-graph-up.svg + mm-throughput-graph $THROUGHPUT_GRAPH_RESOLUTION "$UPLINK_LOG" > $(dirname "${UPLINK_LOG}")/throughput-graph-up.svg + fi + + if [ "$DOWNLOG_SET" = true ] + then + echo "# generating graphs for downlink from log $DOWNLINK_LOG..." + echo $(dirname "${DOWNLINK_LOG}")/throughput-graph-down.svg + mm-delay-graph "$DOWNLINK_LOG" > $(dirname "${DOWNLINK_LOG}")/delay-graph-down.svg + mm-throughput-graph $THROUGHPUT_GRAPH_RESOLUTION "$DOWNLINK_LOG" > $(dirname "${DOWNLINK_LOG}")/throughput-graph-down.svg + fi +} + +ifconfig "$BRIDGE_NAME" down +sender/cellsim-setup.sh "$CLIENT_IF" "$INTERNET_IF" +sender/cellsim "$UP_TRACE" "$DOWN_TRACE" "$LOSSRATE" "$INTERNET_IF" "$CLIENT_IF" $UPLINK_LOG $DOWNLINK_LOG + +#finalize + From c12bcafb75ce93faca88c6c21fef1dac98862330 Mon Sep 17 00:00:00 2001 From: Martin Meszaros Date: Fri, 22 May 2020 17:29:26 +0200 Subject: [PATCH 5/7] Let Saturatr use actual MTU Saturatr was not sending MTU sized packets, which caused wrong bitrate calculations. Additionally, traces generated with Saturatr would cause cellsim to actually emulate a higher bitrate than there actually was. This commit assumes the typical Ethernet MTU of 1500 bytes (which is true at least for the Telekom.de LTE network using the `internet.telekom` APN. It would be better to have Path MTU discovery here or at least have a parameter for specifying the MTU. If your provider uses NAT64 (like Telekom.de with the `internet.v6.telekom` APN), 40 bytes have to be subtracted from the MTU instead of 28 bytes. --- sender/saturateservo.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sender/saturateservo.cc b/sender/saturateservo.cc index 90cd837..9a19522 100644 --- a/sender/saturateservo.cc +++ b/sender/saturateservo.cc @@ -5,6 +5,8 @@ #include "payload.hh" #include "acker.hh" +const int MTU = 1500 - 28; // MTU - (sizeof(IP4HEADER) + (sizeof(UDPHEADER)) + SaturateServo::SaturateServo( const char * s_name, FILE* log_file, const Socket & s_listen, @@ -119,7 +121,7 @@ void SaturateServo::tick( void ) outgoing.recv_timestamp = 0; outgoing.sender_id = _send_id; - _send.send( Socket::Packet( _remote, outgoing.str( 1400 ) ) ); + _send.send( Socket::Packet( _remote, outgoing.str( MTU ) ) ); /* printf( "%s pid=%d DATA SENT %d senderid=%d seq=%d, send_time=%ld, recv_time=%ld\n", @@ -139,7 +141,7 @@ void SaturateServo::tick( void ) outgoing.recv_timestamp = 0; outgoing.sender_id = _send_id; - _send.send( Socket::Packet( _remote, outgoing.str( 1400 ) ) ); + _send.send( Socket::Packet( _remote, outgoing.str( MTU ) ) ); /* printf( "%s pid=%d DATA SENT senderid=%d seq=%d, send_time=%ld, recv_time=%ld\n", From 40e1c5aee4cf8c62ae55ab0c8185bad8a05ee512 Mon Sep 17 00:00:00 2001 From: Martin Meszaros Date: Fri, 22 May 2020 17:44:53 +0200 Subject: [PATCH 6/7] Compile despite warnings --- sender/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sender/Makefile b/sender/Makefile index ce0f1a5..90c4eeb 100644 --- a/sender/Makefile +++ b/sender/Makefile @@ -3,7 +3,7 @@ objects = socket.o hist.o rate-estimate.o payload.o history.o delay-servo.o acke executables = send1way buffer-setpoint controlled-delay saturatr cellsim cellsim-tap CXX = g++ -CXXFLAGS = -g -O3 -std=c++0x -ffast-math -pedantic -Werror -Wall -Wextra -Weffc++ -fno-default-inline -pipe -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE +CXXFLAGS = -g -O3 -std=c++0x -ffast-math -pedantic -Wall -Wextra -Weffc++ -fno-default-inline -pipe -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE LIBS = -lm -lrt all: $(executables) From 75fa819b2935535ce997f4ee4ff760cb3ef5da33 Mon Sep 17 00:00:00 2001 From: Martin Meszaros Date: Fri, 31 Jul 2020 18:49:00 +0200 Subject: [PATCH 7/7] Make saturatr work on Raspberry PI --- sender/acker.cc | 5 +++-- sender/acker.hh | 2 +- sender/delay-servo.cc | 3 ++- sender/packetsocket.cc | 3 ++- sender/saturateservo.cc | 5 +++-- sender/saturatr.cc | 9 +++++---- sender/socket.cc | 2 +- sender/socket.hh | 2 +- 8 files changed, 18 insertions(+), 13 deletions(-) diff --git a/sender/acker.cc b/sender/acker.cc index 3bae12c..93630b4 100644 --- a/sender/acker.cc +++ b/sender/acker.cc @@ -3,6 +3,7 @@ #include "acker.hh" #include "payload.hh" #include "saturateservo.hh" +#include Acker::Acker( const char *s_name, FILE* log_file_handle, const Socket & s_listen, const Socket & s_send, const Socket::Address & s_remote, const bool s_server, const int s_ack_id ) : _name( s_name ), @@ -50,7 +51,7 @@ void Acker::recv( void ) outgoing.ack_number = contents->sequence_number; _send.send( Socket::Packet( _remote, outgoing.str( sizeof( SatPayload ) ) ) ); - fprintf( _log_file,"%s DATA RECEIVED senderid=%d, seq=%d, send_time=%ld, recv_time=%ld, 1delay=%.4f \n", + fprintf( _log_file,"%s DATA RECEIVED senderid=%" PRId32 ", seq=%" PRId32 ", send_time=%" PRId64 ", recv_time=%" PRId64 ", 1delay=%.4f \n", _name.c_str(), _server ? contents->sender_id : _ack_id, contents->sequence_number, contents->sent_timestamp, contents->recv_timestamp,oneway ); } @@ -83,7 +84,7 @@ void Acker::tick( void ) uint64_t Acker::wait_time( void ) const { if ( _server ) { - return 1000000000; + return (uint64_t) 1000000000; } int diff = _next_ping_time - Socket::timestamp(); diff --git a/sender/acker.hh b/sender/acker.hh index 0b450da..34e7c95 100644 --- a/sender/acker.hh +++ b/sender/acker.hh @@ -21,7 +21,7 @@ private: uint64_t _next_ping_time; - static const int _ping_interval = 1000000000; + static const uint32_t _ping_interval = 1000000000; int _foreign_id; diff --git a/sender/delay-servo.cc b/sender/delay-servo.cc index 93d8a8c..aace0e4 100644 --- a/sender/delay-servo.cc +++ b/sender/delay-servo.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include "delay-servo.hh" @@ -37,7 +38,7 @@ void DelayServo::recv( void ) _hist.packet_received( *contents ); _packets_received++; double loss_rate = (double) _hist.num_lost() / (double) _packets_sent; - printf( "%s seq = %d delay = %f recvrate = %f queueest = %f outstanding = %d Mbps = %f lost = %.5f%% arrivemilli = %ld\n", + printf( "%s seq = %" PRId32 " delay = %f recvrate = %f queueest = %f outstanding = %" PRId32 " Mbps = %f lost = %.5f%% arrivemilli = %" PRId64 "\n", _name.c_str(), contents->sequence_number, (double) (contents->recv_timestamp - contents->sent_timestamp) / 1.0e9, diff --git a/sender/packetsocket.cc b/sender/packetsocket.cc index 526da42..51de447 100644 --- a/sender/packetsocket.cc +++ b/sender/packetsocket.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include "packetsocket.hh" @@ -81,7 +82,7 @@ vector< string > PacketSocket::recv_raw( void ) perror( "recvfrom" ); exit( 1 ); } else if ( bytes_read > BUFFER_SIZE ) { - fprintf( stderr, "Received size (%ld) too long (> %d)!\n", + fprintf( stderr, "Received size (%" PRId64 ") too long (> %" PRId32 ")!\n", bytes_read, BUFFER_SIZE ); exit( 1 ); } diff --git a/sender/saturateservo.cc b/sender/saturateservo.cc index 9a19522..4d65965 100644 --- a/sender/saturateservo.cc +++ b/sender/saturateservo.cc @@ -4,6 +4,7 @@ #include "socket.hh" #include "payload.hh" #include "acker.hh" +#include const int MTU = 1500 - 28; // MTU - (sizeof(IP4HEADER) + (sizeof(UDPHEADER)) @@ -67,7 +68,7 @@ void SaturateServo::recv( void ) int64_t rtt_ns = contents->recv_timestamp - contents->sent_timestamp; double rtt = rtt_ns / 1.e9; - fprintf( _log_file, "%s ACK RECEIVED senderid=%d, seq=%d, send_time=%ld, recv_time=%ld, rtt=%.4f, %d => ", + fprintf( _log_file, "%s ACK RECEIVED senderid=%" PRId32 ", seq=%" PRId32 ", send_time=%" PRId64 ", recv_time=%" PRId64 ", rtt=%.4f, %" PRId32 " => ", _name.c_str(),_server ? _foreign_id : contents->sender_id , contents->ack_number, contents->sent_timestamp, contents->recv_timestamp, (double)rtt, _window ); /* increase-decrease rules */ @@ -88,7 +89,7 @@ uint64_t SaturateServo::wait_time( void ) const int num_outstanding = _packets_sent - _max_ack_id - 1; if ( _remote == UNKNOWN ) { - return 1000000000; + return (uint64_t) 1000000000; } if ( num_outstanding < _window ) { diff --git a/sender/saturatr.cc b/sender/saturatr.cc index aafa171..67412da 100644 --- a/sender/saturatr.cc +++ b/sender/saturatr.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include "acker.hh" #include "saturateservo.hh" @@ -54,7 +55,7 @@ int main( int argc, char *argv[] ) FILE* log_file; char log_file_name[50]; - sprintf(log_file_name,"%s-%d-%d",server ? "server" : "client",(int)(ts/1e9),sender_id); + sprintf(log_file_name,"%s-%" PRId32 "-%" PRId32 "",server ? "server" : "client",(int)(ts/1e9),sender_id); log_file=fopen(log_file_name,"w"); SaturateServo saturatr( "OUTGOING", log_file, feedback_socket, data_socket, remote_data_address, server, sender_id ); @@ -81,11 +82,11 @@ int main( int argc, char *argv[] ) uint64_t next_transmission_delay = std::min( saturatr.wait_time(), acker.wait_time() ); if ( next_transmission_delay == 0 ) { - fprintf( stderr, "ZERO %ld %ld\n", saturatr.wait_time(), acker.wait_time() ); + fprintf( stderr, "ZERO %" PRId64 " %" PRId64 "\n", saturatr.wait_time(), acker.wait_time() ); } - timeout.tv_sec = next_transmission_delay / 1000000000; - timeout.tv_nsec = next_transmission_delay % 1000000000; + timeout.tv_sec = next_transmission_delay / (uint64_t)1000000000; + timeout.tv_nsec = next_transmission_delay % (uint64_t)1000000000; ppoll( poll_fds, 2, &timeout, NULL ); if ( poll_fds[ 0 ].revents & POLLIN ) { diff --git a/sender/socket.cc b/sender/socket.cc index 7459922..8eb9649 100644 --- a/sender/socket.cc +++ b/sender/socket.cc @@ -141,6 +141,6 @@ uint64_t Socket::timestamp( void ) exit( 1 ); } - uint64_t ret = ts.tv_sec * 1000000000 + ts.tv_nsec; + uint64_t ret = ts.tv_sec * (uint64_t) 1000000000 + ts.tv_nsec; return ret; } diff --git a/sender/socket.hh b/sender/socket.hh index 87979a4..2705db3 100644 --- a/sender/socket.hh +++ b/sender/socket.hh @@ -38,7 +38,7 @@ public: {} Packet( const Address &s_addr, const std::string &s_payload, const struct timespec &ts ) - : addr( s_addr ), payload( s_payload ), timestamp( ts.tv_sec * 1000000000 + ts.tv_nsec ) + : addr( s_addr ), payload( s_payload ), timestamp( ts.tv_sec * (uint64_t) 1000000000 + ts.tv_nsec ) {} };