%description:
Testing TCP communication speed
    TCP
    TCP_NSC
%#--------------------------------------------------------------------------------------------------------------
%testprog: opp_run
%#--------------------------------------------------------------------------------------------------------------
%file: test.ned

import inet.applications.ethernet.EtherAppCli;
import inet.common.queue.Sink;
import inet.linklayer.ieee80211.Ieee80211Nic;
import inet.mobility.single.CircleMobility;
import inet.mobility.static.StationaryMobility;
import inet.node.wireless.AccessPoint;
import inet.physicallayer.ieee80211.packetlevel.Ieee80211ScalarRadioMedium;


module Ieee80211NicAdhoc extends Ieee80211Nic
{
    parameters:
        mgmtType = "Ieee80211MgmtAdhoc";
}

module ThroughputClient
{
    parameters:
        int idx;
        int maxCli;
        int maxSrv;
        @networkNode();
        @display("i=device/wifilaptop");
        **.interfaceTableModule = "";
    gates:
        input radioIn @directIn;

    submodules:
        cli: EtherAppCli {
            parameters:
                registerSAP = false;
                destAddress = "20:00:00:00:00:0"+string(idx % maxSrv);
                @display("b=40,24;p=180,60,col");
        }
        wlan: Ieee80211NicAdhoc {
            parameters:
                @display("p=112,134;q=queue");
        }
        mobility: CircleMobility {
            parameters:
                startAngle = 360deg * idx / maxCli;
                @display("p=50,141");
        }
    connections allowunconnected:
        wlan.radioIn <-- radioIn;
        cli.out --> wlan.upperLayerIn;
}

module ThroughputServer
{
    parameters:
        int idx;
        int maxSrv;
        @networkNode();
        @display("i=device/wifilaptop");
        **.interfaceTableModule = "";
    gates:
        input radioIn @directIn;

    submodules:
        sink: Sink {
            parameters:
                @display("p=210,68,col");
        }
        wlan: Ieee80211NicAdhoc {
            parameters:
                @display("p=120,158;q=queue");
        }
        mobility: StationaryMobility {
            parameters:
                initialX = 350m * (idx+1) / maxSrv;
                @display("p=50,141");
        }
    connections allowunconnected:
        wlan.radioIn <-- radioIn;
        sink.in++ <-- wlan.upperLayerOut;
}

network Throughput
{
    parameters:
        int numCli;
        int numSrv;
        @display("b=297,203");
    submodules:
        cliHost[numCli]: ThroughputClient {
            parameters:
                idx = index;
                maxCli = numCli;
                maxSrv = numSrv;
                wlan.mac.address = "auto";
                @display("r=,,#707070");
        }
        srvHost[numSrv]: ThroughputServer {
            parameters:
                idx = index;
                maxSrv = numSrv;
                wlan.mac.address = "20:00:00:00:00:0"+string(index);
                @display("p=350,350;r=,,#707070");
        }
        radioMedium: Ieee80211ScalarRadioMedium {
            parameters:
                @display("p=61,46");
        }
}

%#--------------------------------------------------------------------------------------------------------------
%inifile: omnetpp.ini

[General]
network = Throughput
#cmdenv-output-file = omnetpp.log
#debug-on-errors = true
tkenv-plugin-path = ../../../etc/plugins
sim-time-limit = 50s
**.vector-recording = false

**.constraintAreaMinX = 0m
**.constraintAreaMinY = 0m
**.constraintAreaMinZ = 0m
**.constraintAreaMaxX = 400m
**.constraintAreaMaxY = 400m
**.constraintAreaMaxZ = 0m

**.debug = true
**.coreDebug = false
**.channelNumber = 0
**.mgmt.numChannels = 1

# positions
**.mobility.cx = 200m
**.mobility.cy = 200m
**.mobility.r = 100m
**.mobility.speed = 1 mps
**.mobility.updateInterval = 100ms

# channel physical parameters
*.radioMedium.mediumLimitCache.carrierFrequency = 2.4GHz
*.radioMedium.mediumLimitCache.maxTransmissionPower = 20mW

# access point

# nic settings
#for validation
**.wlan*.*.dataBitrate = 11Mbps
**.wlan*.*.mgmtBitrate = 11Mbps
**.wlan*.*.multicastBitrate = 11Mbps
**.wlan*.*.controlBitrate = 11Mbps
#for validation
**.mac.address = "auto"
**.mac.maxQueueSize = 14
**.mac.rtsThresholdBytes = 3000B
**.wlan*.mac.retryLimit = 7
**.wlan*.mac.cwMinData = 31
**.wlan*.mac.cwMinBroadcast = 31

**.radio.transmitterPower = 20.0mW
**.radio.thermalNoise = -110dBm
**.radio.sensitivity = -85dBm
**.radio.pathLossAlpha = 2
**.radio.snirThreshold = 4dB

# cli
**.cli.reqLength = 1250B
**.cli.respLength = 0
**.cli.destStation = ""

description = "10 host to 10 host on adhoc"
Throughput.numCli = 10
Throughput.numSrv = 10
**.cli.sendInterval = 10ms

%#--------------------------------------------------------------------------------------------------------------
%postrun-command: Rscript check.r
%#--------------------------------------------------------------------------------------------------------------
%file: check.r
#!/usr/bin/env Rscript

options(echo=FALSE)
options(width=160)
library("omnetpp", warn.conflicts=FALSE)

#TEST parameters
scafile <- 'results/General-#0.sca'
linecount <- 10 # count of client-server pairs
rcvdBytes <-  11000000/8 # bytes
expectedRate <- 52.46 # %
maxDeviation <- 2.0 # %   (checking expectedRate +/- maxDeviation)
unbalancedRate <- 20.0 # %
# begin TEST:
expectedRateMin <- expectedRate - maxDeviation
expectedRateMax <- expectedRate + maxDeviation

dataset <- loadDataset(scafile)

cat("\nOMNETPP TEST RESULT:\n")

sink <- dataset$scalars[grep("\\.srvHost\\[\\d\\]\\.sink", dataset$scalars$module),]
#print(sink)
secs <- (sink$value[sink$name == "rcvdPk:count"] / sink$value[sink$name == "packetPerSec"])
sinkRcvd <- sink[sink$name == "rcvdPk:sum(packetBytes)",]

#print(sinkRcvd)
cnt <- length(sinkRcvd$value)
#print(cnt)

cat("  IEEE80211 TEST RESULT:\n")

sinkRcvd$rate <- sinkRcvd$value * 100 / (rcvdBytes * secs)

avgValue <- sum(sinkRcvd$value) / length(sinkRcvd$value)
sinkRcvd$urate <- (sinkRcvd$value - avgValue) * 100 / avgValue

cat("    SPEED ")

rate <- sum(sinkRcvd$value) * 100 / (rcvdBytes * max(secs))
isGood <- (rate >= expectedRateMin) & (rate <= expectedRateMax)
if(length(sinkRcvd$value) == linecount & isGood)
{
    cat("OK\n")
} else {
    cat("BAD: rate is", rate, "%, expected rate is", expectedRate, "%\n")
    print(sinkRcvd)
    cat("\n")
}

sinkRcvd$isGood <- (sinkRcvd$urate >= -unbalancedRate) & (sinkRcvd$urate <= unbalancedRate)

#print(sinkRcvd)

cat("    BALANCE ")

if(length(sinkRcvd$value) == linecount & min(sinkRcvd$isGood))
{
    cat("OK\n")
} else {
    cat("BAD:\n")
#    print(sinkRcvd[!sinkRcvd$isGood,])
    print(sinkRcvd)
    cat("\n")
}

cat("END\n")

%#--------------------------------------------------------------------------------------------------------------
%contains: postrun-command(1).out

OMNETPP TEST RESULT:
  IEEE80211 TEST RESULT:
    SPEED OK
    BALANCE OK
END

%#--------------------------------------------------------------------------------------------------------------
