# -*- Tcl -*-
# 
# Class for obtaining all flow statistics.
# Copyright (c) 2002, Hiroyuki Ohsaki.
# All rights reserved.
# 
# $Id: flowstats.tcl,v 1.2 2005/11/02 09:17:37 oosaki Exp $
# 

# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY.  No author or distributor
# accepts responsibility to anyone for the consequences of using it
# or for whether it serves any particular purpose or works at all,
# unless he says so in writing.  Refer to the GNU Emacs General Public
# License for full details.

# Everyone is granted permission to copy, modify and redistribute
# this code, but only under the conditions described in the
# GNU Emacs General Public License.   A copy of this license is
# supposed to have been given to you along with GNU Emacs so you
# can know your rights and responsibilities.  It should be in a
# file named COPYING.  Among other things, the copyright notice
# and this notice must be preserved on all copies.

Class FlowStats

# create FlowStats object
Simulator instproc init-flowstats {start} {
  $self instvar fstat_
  
  set fstat_ [new FlowStats $self $start]
  return $fstat_
}

# display all flow statistics via invoking FlowStats::show
Simulator instproc show-flowstats {} {
  $self instvar fstat_
  
  $fstat_ show
  return $fstat_
}

# create flow monitor for all TCP agents, and initialize at START
FlowStats instproc init {ns start} {
  $self instvar ns_ start_ fmtbl_
  
  set ns_ $ns
  set start_ $start
  foreach agent [Agent/TCP info instances] {
    set fmtbl_($agent) [new FlowMonitor $ns $agent $start]
    $ns at $start "$fmtbl_($agent) reset"
  }
}

# fetch Agent/TCP state variables, calcurate statistics, and display
# them in standard output
FlowStats instproc show {} {
  $self instvar ns_ start_ fmtbl_

  set intv [expr [$ns_ now] - $start_]
  puts "**** Flow Statistics ****"
  puts "Warm-Up Time\t$start_"
  puts "Simulation Time\t[$ns_ now]"
  puts "Duration\t$intv"
  foreach agent [Agent/TCP info instances] {
    # agent information
    set src_addr [$agent set agent_addr_]
    set src_port [$agent set agent_port_]
    set dst_addr [$agent set dst_addr_]
    set dst_port [$agent set dst_port_]
    # TCP configuration variables
    set tick [$agent set tcpTick_]
    set size [$agent set packetSize_]
    # TCP state variables (accumulative)
    set fmon $fmtbl_($agent)
    set ack [expr [$agent set ack_] - [$fmon set ack_]]
    set psent [expr [$agent set ndatapack_] - [$fmon set ndatapack_]]
    set bsent [expr [$agent set ndatabytes_] - [$fmon set ndatabytes_]]
    set nretx [expr [$agent set nrexmit_] - [$fmon set nrexmit_]]
    set pretx [expr [$agent set nrexmitpack_] - [$fmon set nrexmitpack_]]
    set bretx [expr [$agent set nrexmitbytes_] - [$fmon set nrexmitbytes_]]
    # TCP state variables
    set cwnd [$agent set cwnd_]
    set awnd [$agent set awnd_]
    set maxwnd [$agent set window_]
    set ssthresh [$agent set ssthresh_]
    set rtt [$agent set rtt_]
    set srtt [$agent set srtt_]
    set rttvar [$agent set rttvar_]
    # average throughput in bit/sec
    set thr [expr ($ack + 0.0) * $size * 8 / $intv]
    # packet loss probability
    set loss 0
    if { $psent > 0 } {
      set loss [expr ($pretx + 0.0) / $psent]
    }
    # dump all statistics
    puts "\n---- Node $src_addr.$src_port -> Node $dst_addr.$dst_port ----"
    puts "Throughput\t$thr"
    puts "Pkts Rcvd\t$ack"
    puts "Pkts Sent\t$psent"
    puts "Pkts Lost\t$pretx"
    puts "Pkt Loss Pr\t$loss"
    puts "Bytes Rcvd\t[expr ($ack + 0.0) * $size]"
    puts "Bytes Sent\t$bsent"
    puts "Bytes Lost\t$bretx"
    puts "Packet Size\t$size"
    puts "TCP Tick\t$tick"
    puts "SS Thresh\t$ssthresh"
    puts "Cur Window\t$cwnd"
    puts "Avg Window\t$awnd"
    puts "Max Window\t$maxwnd"
    puts "RTT Estimate\t[expr $rtt * $tick]"
    puts "RTT Smoothed\t[expr $srtt * $tick / 8]"
    puts "RTT Var.\t[expr $rttvar * $tick]"
  }
}

