Skip to content

Commit

Permalink
cleaned up script and added makefile
Browse files Browse the repository at this point in the history
  • Loading branch information
fcangialosi committed Sep 24, 2018
1 parent 05ad7c0 commit 325c4bf
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 51 deletions.
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.PHONY:
all:
npm install
sed "22iSRC=$(shell pwd)" mm-live > mm-live-tmp
sudo chmod +x mm-live-tmp
sudo mv mm-live-tmp /usr/local/bin/mm-live
78 changes: 50 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,69 @@
mm-live
=======
# mm-live

Live plotting for [mahimahi](https://github.com/ravinet/mahimahi/). Mahimahi
comes with a very nice live plotting system already, but unfortunately it does
not work over ssh, which is the main context in which I use mahimahi. This
system fills that void by creating a server that any number of clients can
Live plotting for the [mahimahi](https://github.com/fcangialosi/mahimahi/) link
emulator.
Mahimahi comes with a very nice native live plotting system already, but unfortunately it does
not work over ssh and is not easily configurable.
This system fills that void by creating a server that any number of clients can
connect to simultaneously through their web browser. The server pushes the raw
throughput and delay data to the clients using websockets and the browser plots
the data using d3.
the data using d3.


Dependencies
============

* node.js / npm (tested with v8/v5, but should work with others as well)
* python
* [mahimahi](https://github.com/fcangialosi/mahimahi/)


Install
=======

If you have all the required dependencies installed already, installing
`mm-live` should be as simple as running `make` in the root of this repository.

The Makefile defaults to placing the executable in /usr/local/bin, which usually
requires root. If you'd like to install it elsewhere, just change the
destination directory in the Makefile (and ensure this destination directory is
included in your PATH environment variable).


Usage
=====

To live plot the throughput and delay of any mahimahi shell, simply add
`mm-live` as the outer-most shell.
`mm-live` as the outer-most shell.

For example, to start a server with 50ms delay, 48Mbps bandwidth, and 1BDP
droptail buffers, with live plotting:
`mm-live` takes two required arguments before the inner shells:
1. "uplink" or "downlink" -- the direction of traffic to monitor in the graph
2. server-port (integer) -- starts the live plotting server on this port

`mm-live mm-delay 25 mm-link --uplink-queue="droptail" --uplink-queue-args="packets=100" --uplink-log=test.log ~/bw12.mahi ~/bw48.mahi`
For example to emulate a link with 100ms RTT, 48Mbps bandwidth, and 1BDP
droptail buffers, and start monitoring the uplink on port 8080, run:

This will create a server on port 8088. If the IP address of your server is
1.2.3.4, you can view it from the following URL in your browser:
`mm-live uplink 8080 mm-delay 50 mm-link --uplink-queue="droptail" --uplink-queue-args="packets=400"`

`1.2.3.4:8088/`
Then simply point your web-browser to `http://[IP]:8080`.

The plot will look something like this (throughput in Mbps plotted in purple,
delay in ms plotted in blue):
The server output log is stored in the current directory at `server.[server-port].log` by default. If the visualization is not displaying, you should check here for any errors.

![Example Screenshot](/screenshot.png)
For more information, run `mm-live --help`

The UI is very plain and does not automatically adjust well to differnet
scenarios at the moment. It also doesn't yet support differentiating multiple
flows, it just shows aggregate throughput leaving the entire shell. Improving
the plotting is future work.

Dependencies
============
Demo
====

![Demo](mm-live-demo.gif)


(Instructions assume all of these are already installed in the typical
locations):
Current Limitations
===================

* Node.js
* Python
* Mahimahi
* Axes are fixed and do not adjust automatically adjust to zoom as values
change.
* Only uplink or downlink can be monitored at a given time, not both
* Only supports aggregate throughput, cannot monitor individual flows

(none of these limitations are fundamental so I hope to fix them in the future)
107 changes: 101 additions & 6 deletions mm-live
Original file line number Diff line number Diff line change
@@ -1,16 +1,111 @@
#!/bin/bash

function usage() {
echo "mm-live 0.2"
echo "Frank Cangialosi <frankc@csail.mit.edu>"
echo "Mahimahi live graphing utility (works over ssh!)"
echo ""
echo "USAGE:"
echo -e "\tmm-live [(uplink|downlink)] [server-port] [mm-delay ... [mm-link ...] ...]"
echo ""
echo "LIMITATIONS:"
echo -e "\t- mm-live must be the outer-most shell"
echo -e "\t- there must be both an mm-delay and mm-link shell inside"
echo -e "\t- mm-live can monitor uplink or downlink, but not both at the same time"
echo -e ""
echo "EXAMPLE:"
echo -e "\tmm-live mm-delay 25 mm-link --uplink-queue-args=\"packets=200\" --uplink-queue=\"droptail\" 12Mbps 12Mbps"
echo -e "\t(Monitors a 12Mbps link with 200 packets of buffering and a 50ms RTT)"
exit 1
}


###############################################################################
# Monitor uplink or downlink?
if [ "$#" -lt 2 ]; then
echo -e "error: must pass 'downlink' or 'uplink' as first arg to mm-live\n"
usage
fi
if [[ "$1" != "uplink" ]] && [[ "$1" != "downlink" ]]; then
echo -e "error: expected 'uplink' or 'downlink', but got $1\n"
usage
fi
MONITOR_LINK=$1
###############################################################################

###############################################################################
# Parse server port
if [ "$#" -lt 3 ] || [ $(($2)) -le 0 ]; then
echo -e "error: must pass server port as second arg to mm-live\n"
usage
fi
SERVER_PORT=$2
###############################################################################

###############################################################################
# Find RTT of delay shell
i=0
mm_delay_pos=-1
for var in "$@"
do
if [[ "$var" == "mm-delay" ]]; then
mm_delay_pos=$((i+2))
break
fi
i=$((i+1))
done
if [ "$mm_delay_pos" -lt 0 ]; then
echo -e "error: could not find mm-delay shell\n"
usage
fi
one_way=${@:$mm_delay_pos:1}
RTT=$(($one_way*2))
###############################################################################

###############################################################################
# Find log file if it was passed
i=0
LOG_NAME=""
LOG_ARG=""
for var in "$@"
do
if [[ "$var" = *"$MONITOR_LINK-log="* ]]; then
IFS="=" read -r -a tmp <<< "$var"
LOG_NAME="${tmp[1]}"
break
fi
if [[ "$var" = *"$MONITOR_LINK-log"* ]]; then
log_pos=$((i+2))
LOG_NAME=${@:$log_pos:1}
break
fi
i=$((i+1))
done
if [[ "$LOG_NAME" == "" ]]; then
LOG_NAME="/tmp/$MONITOR_LINK.log"
LOG_ARG="--$MONITOR_LINK-log=$LOG_NAME"
fi
###############################################################################


###############################################################################
# MAIN #
###############################################################################

# clean tmp log file
rm -f /tmp/uplink.log
touch /tmp/uplink.log
echo "==> Cleaning log file"
rm -f $LOG_NAME
touch $LOG_NAME

# start following log and feeding to web server
tail -f /tmp/uplink.log | python live.py 50 | node index.js > server.log 2>&1 &
echo "==> Starting server"
tail -f $LOG_NAME | python $SRC/mm-live-parse.py $RTT | node $SRC/mm-live-server.js $SERVER_PORT > server.$SERVER_PORT.log 2>&1 &

# run inner shell
$@ --uplink-log=/tmp/uplink.log
echo "==> Starting mahimahi"
echo "${@:3} $LOG_ARG"
${@:3} $LOG_ARG

# stop server
# TODO make this more graceful
pkill -P $$

###############################################################################
Binary file added mm-live-demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion index.html → mm-live-index.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
var g_right = 1150;
var g_bottom = height - 100;
var globalX = 0;
var duration = 50;
var duration = 100;
var max = 10;
var step = (duration / 1000);
var max_points = (max / step);
Expand Down
File renamed without changes.
17 changes: 3 additions & 14 deletions index.js → mm-live-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,14 @@ var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req,res) {
res.sendFile(__dirname + '/index.html');
res.sendFile(__dirname + '/mm-live-index.html');
});

//var data = [];

io.on('connection', function(socket) {
console.log('client connected');
socket.on('disconnect', function() {
console.log('client disconnected');
});
// var i = 0;
//setInterval(function() {
// console.log(i);
// console.log(data);
// //io.emit('data', data[i]);
// i+=1;
//}, 500);
});

process.stdin.resume();
Expand All @@ -34,15 +25,13 @@ process.stdin.on('data', function(chunk) {
'delay' : parseFloat(spsp[2])
}
io.emit('data', d);
//data.push(d);
//console.log(data);
}
});
process.stdin.on('end', function() {
console.log('end');
});


http.listen(8080, function() {
console.log('listening on 8080');
http.listen(parseInt(process.argv[2]), function() {
console.log('Visualization server listening on', process.argv[2]);
});
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "mm-live",
"version": "0.0.1",
"dependencies": {
"express": "^4.15.3",
"socket.io": "^2.0.1"
"express": "^4.16.3",
"socket.io": "^2.1.1"
}
}
Binary file removed screenshot.png
Binary file not shown.

0 comments on commit 325c4bf

Please sign in to comment.