summaryrefslogtreecommitdiff
path: root/src/ns3/simulate.org
diff options
context:
space:
mode:
Diffstat (limited to 'src/ns3/simulate.org')
-rw-r--r--src/ns3/simulate.org498
1 files changed, 498 insertions, 0 deletions
diff --git a/src/ns3/simulate.org b/src/ns3/simulate.org
new file mode 100644
index 0000000..b6674d4
--- /dev/null
+++ b/src/ns3/simulate.org
@@ -0,0 +1,498 @@
+
+
+
+* Run simulations
+ To run all the simulations, execute the following call:
+ #+NAME: runSim
+ #+CALL: runBW(lat=runLat(nbSens=runNbSensors(nbHop=runNbHop())))
+
+ #+RESULTS: runSim
+
+** Experiments
+
+*** Sensors Position
+ #+NAME: runSensorsPos
+ #+BEGIN_SRC bash :noweb yes :results output
+ <<singleRun>>
+ simKey="SENSORSPOS"
+ for sensorsNumber in $(seq 5 2 15)
+ do
+ for positionSeed in $(seq 1 10)
+ do
+ run
+ done
+ done
+ #+END_SRC
+
+*** Sensors Send Interval
+ #+NAME: runSendInterval
+ #+BEGIN_SRC bash :noweb yes :results output
+ <<singleRun>>
+ simKey="SENDINTERVAL"
+ for sensorsNumber in $(seq 5 2 15)
+ do
+ for sensorsSendInterval in $(seq 10 10 100)
+ do
+ run
+ done
+ done
+ #+END_SRC
+
+*** Bandwidth
+ #+NAME: runBW
+ #+BEGIN_SRC bash :noweb yes :results output
+ <<singleRun>>
+ simKey="BW"
+ for sensorsNumber in $(seq 1 10)
+ do
+ for linksBandwidth in $(seq 10 20 100)
+ do
+ run
+ done
+ done
+ #+END_SRC
+
+ #+RESULTS: runBW
+
+ #+RESULTS:
+
+*** Latency
+ #+NAME: runLat
+ #+BEGIN_SRC bash :noweb yes :results output
+ <<singleRun>>
+ simKey="LATENCY"
+ for sensorsNumber in $(seq 1 10)
+ do
+ for linksLatency in $(seq 1 1 10)
+ do
+ run
+ done
+ done
+ #+END_SRC
+
+ #+RESULTS: runLat
+
+ #+RESULTS:
+
+*** Number of sensors
+ #+NAME: runNbSensors
+ #+BEGIN_SRC bash :noweb yes :results output
+ <<singleRun>>
+ simKey="NBSENSORS"
+ for sensorsNumber in $(seq 1 15)
+ do
+ run
+ done
+ #+END_SRC
+
+ #+RESULTS:
+
+*** Number of Hop
+ #+NAME: runNbHop
+ #+BEGIN_SRC bash :noweb yes :results output
+ <<singleRun>>
+ simKey="NBHOP"
+ for sensorsNumber in $(seq 1 10)
+ do
+ for nbHop in $(seq 1 10)
+ do
+ run
+ done
+ done
+ #+END_SRC
+
+ #+RESULTS: runNbHop
+
+
+** Single Run
+
+ #+NAME: singleRun
+ #+BEGIN_SRC bash :eval never :noweb yes :results output
+ simulator="simulator/simulator"
+ parseEnergyScript="./parseEnergy.awk"
+ parseDelayScript="./parseDelay.awk"
+ logFolder="logs/"
+ export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${NS3_PATH}/build/lib
+
+ # Default Parameters
+ sensorsSendInterval=1 # DON'T GO BELOW 1 SECONDS !!!!!!! Simulator will stay stuck
+ sensorsPktSize=192 # 1 byte temperature (-128 à +128 °C) and 4Byte sensorsId
+ sensorsNumber=5
+ nbHop=10 # Cf paper AC/Yunbo
+ linksBandwidth=10000 # 10Ge links (to be coherent with energy values of ECOFEN/literature)
+ linksLatency=11
+ positionSeed=5
+ simKey="NOKEY"
+
+ run () {
+ # If another function want to handle simulation (tipically used on g5k)
+ type -t handleSim > /dev/null && { handleSim; return; }
+
+ local logFile="${logFolder}/${simKey}_${sensorsSendInterval}SSI_${sensorsPktSize}SPS_${sensorsNumber}SN_${nbHop}NH_${linksBandwidth}LB_${linksLatency}LL_${positionSeed}PS.org"
+ [ -f "$logFile" ] && return
+ local simCMD="$simulator --sensorsSendInterval=${sensorsSendInterval} --sensorsPktSize=${sensorsPktSize} --sensorsNumber=${sensorsNumber} --nbHop=${nbHop} --linksBandwidth=${linksBandwidth} --linksLatency=${linksLatency} --positionSeed=${positionSeed} 2>&1"
+ local log=$(bash -c "$simCMD")
+
+ # Compute some metrics
+ energyLog=$(echo "$log" | $parseEnergyScript)
+ avgDelay=$(echo "$log" | $parseDelayScript)
+ totalEnergy=$(echo "$energyLog" | awk 'BEGIN{power=0;FS=","}NR!=1{power+=$2}END{print(power)}')
+ sensorsEnergy=$(echo "$energyLog" |awk -F',' 'BEGIN{sumW=0}$1<0{sumW+=$2}END{print sumW}')
+ networkEnergy=$(echo "$energyLog" |awk -F',' 'BEGIN{sumN=0}$1>=0{sumN+=$2}END{print sumN}')
+ nbPacketCloud=$(echo "$log"|grep -c "CloudSwitch receive")
+ nbNodes=$(echo "$log"|awk '/Simulation used/{print($3)}')
+ ns3Version=$(echo "$log"|awk '/NS-3 Version/{print($3)}')
+
+ # Save logs
+ echo -e "#+TITLE: $(date) ns-3 (version ${ns3Version}) simulation\n" > $logFile
+ echo "* Environment Variables" >> $logFile
+ env >> $logFile
+ echo "* Full Command" >> $logFile
+ echo "$simCMD" >> $logFile
+ echo "* Output" >> $logFile
+ echo "$log" >> $logFile
+ echo "* Energy CSV (negative nodeId = WIFI, 0 = AP (Wireless+Wired), positive nodeId = ECOFEN" >> $logFile
+ echo "$energyLog" >> $logFile
+ echo "* Metrics" >> $logFile
+ echo "-METRICSLINE- sensorsSendInterval:${sensorsSendInterval} sensorsPktSize:${sensorsPktSize} sensorsNumber:${sensorsNumber} nbHop:${nbHop} linksBandwidth:${linksBandwidth} linksLatency:${linksLatency} totalEnergy:$totalEnergy nbPacketCloud:$nbPacketCloud nbNodes:$nbNodes avgDelay:${avgDelay} ns3Version:${ns3Version} simKey:${simKey} positionSeed:${positionSeed} sensorsEnergy:${sensorsEnergy} networkEnergy:${networkEnergy}" >> $logFile
+ }
+
+ #+END_SRC
+
+** Grid 5000
+*** Master Node Script
+ This code generate and distribute simulation argument to the slave worker nodes and
+ run start their simulations processes:
+ #+BEGIN_SRC sh :tangle ./g5k-root.sh :shebang "#!/bin/bash" :noweb yes
+ ##### Arguments #####
+ nHost=20 # At least 20 host x)
+ nProcesses=3 # Max number of parrallel simulations (don't go too high, your process will be killed (arround 8))
+ nHours=4 # Reservation duration
+ simArgsLoc=~/args/ # Don't change this path witouth changing it in workder scripts
+ finishedFile="$simArgsLoc/finished-microBenchmarks.txt"
+ logsFinalDst=~/logs/
+ #####################
+
+ # Check
+ [ "$1" == "subscribe" ] && subscribe=1 ||subscribe=0
+ [ "$1" == "deploy" ] && deploy=1 || deploy=0
+ [ "$1" == "-p" ] && progress=1 || progress=0
+
+ handleSim () {
+ [ -z "${argId}" ] && argId=1 || argId=$(( argId + 1 ))
+ outF="$simArgsLoc/${argId}.sh" # Args file based on host name (avoid conflict)
+
+ # Add Shebang
+ echo '#!/bin/bash' > $outF
+ echo "finishedFile=\"$finishedFile\"" >> $outF
+ echo "nProcesses=$nProcesses" >> $outF
+ echo "logsFinalDst=\"$logsFinalDst\"" >> $outF
+ # Save arguments
+ echo "sensorsSendInterval=${sensorsSendInterval}" >> $outF
+ echo "sensorsPktSize=${sensorsPktSize}" >> $outF
+ echo "nbHop=${nbHop}" >> $outF
+ echo "simKey=\"${simKey}\"" >> $outF
+ echo "sensorsNumber=${sensorsNumber}" >> $outF
+ echo "linksLatency=${linksLatency}" >> $outF
+ echo "sensorsNumber=${sensorsNumber}" >> $outF
+ echo "linksBandwidth=${linksBandwidth}" >> $outF
+ echo "positionSeed=${positionSeed}" >> $outF
+ }
+
+
+ # Start subscribe/deploy
+ if [ $subscribe -eq 1 ]
+ then
+ echo "Starting oarsub..."
+ oarsub -l host=$nHost,walltime=$nHours 'sleep "10d"' # Start reservation
+ echo "Please join your node manually when your reservation is ready by using oarsub -C <job-id>"
+ exit 0
+ elif [ $deploy -eq 1 ]
+ then
+ echo "Starting deployment..."
+
+ ##### Usefull Variables #####
+ wai=$(dirname "$(readlink -f $0)") # Where Am I ?
+ hostList=($(cat $OAR_NODE_FILE | uniq))
+ #############################
+
+ # Initialize logsFinalDst
+ mkdir -p $logsFinalDst
+ rm -rf $logsFinalDst/* # Clean log dst just in case (it is dangerous but avoid conflict)
+ mkdir -p $simArgsLoc
+ rm -rf $simArgsLoc/* # Clean old args
+
+ # Add your simulation code block here
+ <<runNbSensors>>
+ <<runSendInterval>>
+ <<runSensorsPos>>
+
+ # Distribute argument according to subsribed nodes
+ cd $simArgsLoc
+ curHostId=0
+ for file in $(find ./ -type f)
+ do
+ [ $curHostId -eq $nHost ] && curHostId=0
+ mv -- ${file} ${hostList[$curHostId]}-$(basename ${file})
+ curHostId=$(( curHostId + 1 ))
+ done
+ cd -
+
+
+ # Run simulations
+ echo "Host who finished their work:" > $finishedFile
+ for host in ${hostList[@]}
+ do
+ echo "Start simulations on node $host"
+ oarsh lguegan@$host bash g5k-worker.sh &
+ done
+
+ exit 0
+ elif [ $progress -eq 1 ]
+ then
+ alreadyFinished=$(cat $finishedFile| tail -n +2| wc -l)
+ percent=$(echo $alreadyFinished $nHost| awk '{print $1/$2*100}')
+ echo "Progression: " $alreadyFinished/$nHost "(${percent}%)"
+ else
+ echo "Invalid arguments, make sure you know what you are doing !"
+ exit 1
+ fi
+ #+END_SRC
+*** Worker Node Script
+ Almost like the [[microBenchmarksSingle][single run script]] but with additionnal code to handle g5k simulation platform (arguments,logs etc..).
+ #+BEGIN_SRC sh :tangle ./g5k-worker.sh :shebang "#!/bin/bash" :noweb yes
+ export NS3_PATH=~/.bin/ns-3/ns-3.29/
+ g5kLogFolder="/tmp/logs/"
+ mkdir -p $g5kLogFolder # Create log folder just in case
+ rm -rf $g5kLogFolder/* # Clean previous logs just in case
+
+ hostname=$(hostname)
+
+ # Run simulations with sourced arguments :D
+ simArgsLoc=~/args/ # Don't change this path without changing it in root scripts
+
+ argsId=0
+ argsFile="$simArgsLoc/${hostname}-args-${argsId}.sh" # Arguments generated by Root Node
+ curNProcesses=0 # Start with no processes
+ for argsFile in $(find $simArgsLoc -type f -name "$hostname*")
+ do
+ <<singleRun>>
+ logFolder=$g5kLogFolder # Don't forget override default g5kLogFolder
+ source $argsFile # Fetch argument
+ run & # Run async
+ ((curNProcesses+=1)) # Increase by 2
+ [ $curNProcesses -ge $nProcesses ] && { curNProcesses=0; wait; }
+ done
+ wait # Wait until the end of all simulations
+
+ cp -r $g5kLogFolder/* "$logsFinalDst" # Fetch log from tmp into nfs
+ echo $(hostname) >> $finishedFile # Just say I finished
+ #+END_SRC
+
+* Logs Analysis
+ To Generate all the plots, please execute the following line:
+ #+NAME: runAnalysis
+ #+CALL: plotToPDF(plots=genAllPlots(data=logToCSV()))
+
+ #+RESULTS: runAnalysis
+
+** R Scripts
+*** Generate all plots script
+ Available variables:
+ |---------------------|
+ | Name |
+ |---------------------|
+ | sensorsSendInterval |
+ | sensorsPktSize |
+ | sensorsNumber |
+ | nbHop |
+ | linksBandwidth |
+ | linksLatency |
+ | totalEnergy |
+ | nbPacketCloud |
+ | nbNodes |
+ | avgDelay |
+ | simKey |
+ |---------------------|
+
+ #+NAME: genAllPlots
+ #+BEGIN_SRC R :noweb yes :results output
+ <<RUtils>>
+# easyPlotGroup("linksLatency","totalEnergy", "LATENCY","sensorsNumber")
+# easyPlotGroup("linksBandwidth","totalEnergy", "BW","sensorsNumber")
+ easyPlot("sensorsNumber","totalEnergy", "NBSENSORS")
+ easyPlotGroup("positionSeed", "totalEnergy","SENSORSPOS","sensorsNumber")
+ easyPlotGroup("positionSeed", "avgDelay","SENSORSPOS","sensorsNumber")
+ easyPlotGroup("sensorsSendInterval","sensorsEnergy","SENDINTERVAL","sensorsNumber")
+ easyPlotGroup("sensorsSendInterval","networkEnergy","SENDINTERVAL","sensorsNumber")
+
+ #+END_SRC
+
+ #+RESULTS: genAllPlots
+
+*** R Utils
+ RUtils is intended to load logs (data.csv) and providing
+ simple plot function for them.
+
+ #+NAME: RUtils
+ #+BEGIN_SRC R :eval never
+ library("tidyverse")
+
+ # Fell free to update the following
+ labels=c(nbNodes="Number of nodes",sensorsNumber="Number of sensors",totalEnergy="Total Energy (J)",
+ nbHop="Number of hop (AP to Cloud)", linksBandwidth="Links Bandwidth (Mbps)", avgDelay="Average Application Delay (s)",
+ linksLatency="Links Latency (ms)", sensorsSendInterval="Sensors Send Interval (s)", positionSeed="Position Seed",
+ sensorsEnergy="Sensors Wifi Energy Consumption (J)", networkEnergy="Network Energy Consumption (J)")
+
+ # Load Data
+ data=read_csv("logs/data.csv")
+
+ # Get label according to varName
+ getLabel=function(varName){
+ if(is.na(labels[varName])){
+ return(varName)
+ }
+ return(labels[varName])
+ }
+
+ easyPlot=function(X,Y,KEY){
+ curData=data%>%filter(simKey==KEY)
+ stopifnot(NROW(curData)>0)
+ ggplot(curData,aes_string(x=X,y=Y))+geom_point()+geom_line()+xlab(getLabel(X))+ylab(getLabel(Y))
+ ggsave(paste0("plots/",KEY,"-",X,"_",Y,".png"))
+ }
+
+ easyPlotGroup=function(X,Y,KEY,GRP){
+ curData=data%>%filter(simKey==KEY) %>% mutate(!!GRP:=as.character(UQ(rlang::sym(GRP)))) # %>%mutate(sensorsNumber=as.character(sensorsNumber))
+ stopifnot(NROW(curData)>0)
+ ggplot(curData,aes_string(x=X,y=Y,color=GRP,group=GRP))+geom_point()+geom_line()+xlab(getLabel(X))+ylab(getLabel(Y)) + labs(color = getLabel(GRP))
+ ggsave(paste0("plots/",KEY,"-",X,"_",Y,".png"))
+ }
+ #+END_SRC
+
+** Plots -> PDF
+ Merge all plots in plots/ folder into a pdf file.
+ #+NAME: plotToPDF
+ #+BEGIN_SRC bash :results output :noweb yes
+ orgFile="plots/plots.org"
+ <<singleRun>> # To get all default arguments
+
+ # Write helper function
+ function write {
+ echo "$1" >> $orgFile
+ }
+
+ echo "#+TITLE: Analysis" > $orgFile
+ write "#+LATEX_HEADER: \usepackage{fullpage}"
+ write "#+OPTIONS: toc:nil"
+ # Default arguments
+ write '\begin{center}'
+ write '\begin{tabular}{lr}'
+ write 'Parameters & Values\\'
+ write '\hline'
+ write "sensorsPktSize & ${sensorsPktSize} bytes\\\\"
+ write "sensorsSendInterval & ${sensorsSendInterval}s\\\\"
+ write "sensorsNumber & ${sensorsNumber}\\\\"
+ write "nbHop & ${nbHop}\\\\"
+ write "linksBandwidth & ${linksBandwidth}Mbps\\\\"
+ write "linksLatency & ${linksLatency}ms\\\\"
+ write '\end{tabular}'
+ write '\newline'
+ write '\end{center}'
+
+ for plot in $(find plots/ -type f -name "*.png")
+ do
+ write "\includegraphics[width=0.5\linewidth]{$(basename ${plot})}"
+ done
+
+ # Export to pdf
+ emacs $orgFile --batch -f org-latex-export-to-pdf --kill
+ #+END_SRC
+
+ #+RESULTS:
+
+** Log -> CSV
+ logToCSV extract usefull data from logs and put them into logs/data.csv.
+
+ #+NAME: logToCSV
+ #+BEGIN_SRC bash :results none
+ csvOutput="logs/data.csv"
+
+ # First save csv header line
+ aLog=$(find logs/ -type f -name "*.org"|head -n 1)
+ metrics=$(cat $aLog|grep "\-METRICSLINE\-"|sed "s/-METRICSLINE-//g")
+ echo $metrics | awk '{for(i=1;i<=NF;i++){split($i,elem,":");printf(elem[1]);if(i<NF)printf(",");else{print("")}}}' > $csvOutput
+
+ # Second save all values
+ for logFile in $(find logs/ -type f -name "*.org")
+ do
+ metrics=$(cat $logFile|grep "\-METRICSLINE\-"|sed "s/-METRICSLINE-//g")
+ echo $metrics | awk '{for(i=1;i<=NF;i++){split($i,elem,":");printf(elem[2]);if(i<NF)printf(",");else{print("")}}}' >> $csvOutput
+ done
+ #+END_SRC
+
+
+
+
+
+
+** Custom Plots
+
+ #+NAME: ssiNet
+ #+BEGIN_SRC R :noweb yes :results graphics :file plots/sensorsSendInterval-net.png
+ <<RUtils>>
+
+ data%>%filter(simKey=="SENDINTERVAL",sensorsNumber==20) %>% ggplot(aes(x=sensorsSendInterval,y=networkEnergy))+xlab(getLabel("sensorsSendInterval"))+ylab(getLabel("networkEnergy"))+
+ geom_line()+labs(title="For 20 sensors")
+ ggsave("plots/sensorsSendInterval-net.png",dpi=80)
+ #+END_SRC
+
+ #+RESULTS:
+ [[file:plots/sensorsSendInterval-net.png]]
+
+
+ #+NAME: ssiWifi
+ #+BEGIN_SRC R :noweb yes :results graphics :file plots/sensorsSendInterval-wifi.png
+ <<RUtils>>
+ data%>%filter(simKey=="SENDINTERVAL",sensorsNumber==20) %>% ggplot(aes(x=sensorsSendInterval,y=sensorsEnergy))+xlab(getLabel("sensorsSendInterval"))+ylab(getLabel("sensorsEnergy"))+
+ geom_line() + geom_line()+labs(title="For 20 sensors")
+ ggsave("plots/sensorsSendInterval-wifi.png",dpi=80)
+ #+END_SRC
+
+ #+RESULTS: ssiWifi
+ [[file:plots/sensorsSendInterval-wifi.png]]
+
+ #+RESULTS:
+ [[file:plots/sensorsSendInterval.png]]
+
+
+
+
+
+
+ #+BEGIN_SRC R :results graphics :noweb yes :file plot-final.png :session *R*
+ <<RUtils>>
+ simTime=1800
+
+ # Network
+ data=read_csv("logs/data.csv")
+ data=data%>%filter(simKey=="NBSENSORS")
+ dataC5=data%>%filter(sensorsNumber==5)%>% mutate(energy=networkEnergy/simTime) %>%select(energy,sensorsNumber)
+ dataC10=data%>%filter(sensorsNumber==10)%>%mutate(energy=networkEnergy/simTime) %>%select(energy,sensorsNumber)
+ dataNet=rbind(dataC5,dataC10)%>%mutate(type="Network")
+
+ # Network
+ dataS5=data%>%filter(sensorsNumber==5)%>% mutate(energy=sensorsEnergy/simTime) %>%select(energy,sensorsNumber)
+ dataS10=data%>%filter(sensorsNumber==10)%>%mutate(energy=sensorsEnergy/simTime) %>%select(energy,sensorsNumber)
+ dataS=rbind(dataS5,dataS10)%>%mutate(type="Sensors")
+
+ data=rbind(dataNet,dataS)%>%mutate(sensorsNumber=as.character(sensorsNumber))
+
+ ggplot(data)+geom_bar(aes(x=sensorsNumber,y=energy,fill=type),stat="identity")+xlab("Sensors Number")+ylab("Power Consumption (W)")+guides(fill=guide_legend(title="Part"))
+ ggsave("plot-final.png",dpi=80)
+
+ #+END_SRC
+
+ #+RESULTS:
+ [[file:plot-final.png]]
+