/*********************************************************************
 * DBS: Distributed Benchmark System
 * Copyright (c) 1995, 1996 Yukio Murayama
 * Copyright (c) 1995, 1996 Nara Institute of Science and Technology
 * All rights reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided only with the following
 * conditions are satisfied:
 *
 * 1. Both the copyright notice and this permission notice appear in
 *    all copies of the software, derivative works or modified versions,
 *    and any portions thereof, and that both notices appear in
 *    supporting documentation.
 * 2. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgement:
 *      This product includes software developed by Nara Institute of 
 *      Science and Technology and its contributors.
 * 3. Neither the name of Nara Institute of Science and Technology nor 
 *    the names of its contributors may be used to endorse or promote 
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND NARA 
 * INSTITUTE OF SCIENCE AND TECHNOLOGY DISCLAIMS ANY LIABILITY OF 
 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF 
 * THIS SOFTWARE. ALSO, THERE IS NO WARRANTY IMPLIED OR OTHERWISE, 
 * NOR IS SUPPORT PROVIDED.
 *
 * Feedback of the results generated from any improvements or
 * extensions made to this software would be much appreciated.
 * Any such feedback should be sent to:
 *
 *  Yukio Murayama
 *  E-mail:  <yukio-m@is.aist-nara.ac.jp>
 *  URL:     <http://shika.aist-nara.ac.jp/member/yukio-m/index.html>
 *  Address: Graduate School of Information Science, 
 *           Nara Institute of Science and Technology,
 *           Takayama 8916-5, Ikoma, Nara, Japan
 *
 * Nara Institute of Science and Technology has the rights to 
 * redistribute these changes.
 *********************************************************************/

DBS (Destributed Benchmark System) Version 1.1 User's Manual   

                                     奈良先端科学技術大学院大学
                                     情報科学研究科  情報ネットワーク講座
                                     奈良県生駒市高山町8916-5
                                     村山公保 (yukio-m@is.aist-nara.ac.jp)

◎DBSとは

  DBSとはTCPのすべての機能を評価することを目的に作られたTCPベンチマークツー
  ルです。

    - 複数のホストの間で同時にデータ転送を行う。
    - 一つ一つのデータの送受信時刻を記録する。

  という2つの機能により，ネットワークを輻輳させパケットが喪失する状況をつく
  り出し，それぞれのデータ転送ストリームのスループットの時刻変動を測定するこ
  とができます。これにより，データ転送ストリーム間の相互作用の分析ができ，そ
  の結果，TCPの性能や，データリンクの性能，ホストやルータの性能，ネットワー
  クシステムの性能などの評価分析に利用できます。

  ・前提
    - 各ホストはNTPなどを利用して時刻の同期がとれている必要があります。

  ・特徴
    - TCP，UDPのアプリケーションレベルでのスループットの時刻変動を測定できる。
    - 多点間のホストで複数のデータ転送が可能である。
    - 複雑なトラヒックパターンを指定できる。MPEGなどのデータ転送を模倣できる。
    - OSのカーネル内部にTCP DEBUG機能がある場合には，その値を記録することが
      できる。この機能を利用すると，TCP/IP疑似ヘッダの情報，再送したセグメン
      ト，輻輳ウィンドウサイズ，ラウンドトリップ時間などがわかる。


◎プログラムの名称と機能

 dbsc      DBSコントローラ

  DBSコントローラはDBSの実験をコントロールするコマンドです。コマンドファイル
  の入力，DBSデーモンへの指令，結果の受信，ファイルへの保存を行います。

 dbsd      DBSデーモン

  DBSデーモンは実験ホスト群で動作させるデーモンです。DBSコントローラからの指
  示に従いトラヒックを送受信します。

 dbs_view  DBSビューワ

  DBSビューワは結果のファイルを処理してシーケンス番号の推移，スループット，
  遅延時間等のグラフを描画します。動作させるためにはperlとGnu Plot V3.5が必
  要です。


◎使い方

 dbsc [-p port_number] [-d] [-v] command_file

   command_file   後述するコマンドファイルを指定する。
   -p port_number デフォルトのポート番号(10710)以外のポート番号を利用するときに
                  指定する。
   -d             デバッグモードで実行する。
   -v             Versionおよびhelpを表示する。

 dbsd [-p port_number] [-d] [-D] [-v] [-h allow_host]

   -p port_number デフォルトのポート番号(10710)以外のポート番号を利用するときに
                  指定する。
   -h allow_host  コマンドの送信を許可するホストを指定する。
   -d             デバッグモードで実行する。
   -D             inetdから起動する時に指定する。
   -v             Versionおよびhelpを表示する。

 dbs_view

  DBSビューワにはたくさんのオプションがあります。-fは必須。他はオプションで
  す。通常は-pオプションを付けてください。全く同じパラメータで再度グラフを表
  示したいときは-pオプションを省略できます。処理が若干速くなります。

    -f  file file ...  : コマンドファイルのファイル名(複数指定可)
                         出力されたファイルを指定するのではなく，dbscの実行
                         時に指定したファイル
    -a       area      : グラフを表示するエリアの指定"[0:2][0:1000]"のように
                         指定する。("ダブルクォーテーション"も付けること)
    -sq   [s|r|u|S|R|U]: アプリケーションレベルのシーケンス番号表示
                         s: 送信セグメントのシーケンス番号をStep Lineで表示
                         r: 受信セグメントのシーケンス番号をStep Lineで表示
                         u: UDPで喪失したセグメントをStep Lineで表示
                         S: 送信セグメントのシーケンス番号をDotで表示
                         R: 受信セグメントのシーケンス番号をDotで表示
                         U: UDPで喪失したセグメントをDotで表示
    -th      [s|r]     : アプリケーションレベルのスループット表示
                         s: 送信セグメントのスループットをLineで表示
                         r: 受信セグメントのスループットをLineで表示
                         t: 受信セグメントのスループットの合計をLineで表示
                         S: 送信セグメントのスループットをStep Lineで表示
                         R: 受信セグメントのスループットをStep Lineで表示
                         T: 受信セグメントのスループットの合計をStep Lineで表示
    -delay             : アプリケーションレベルの遅延時間表示
    -jitter  [s|r]     : アプリケーションレベルのJitter表示
                         s: 送信セグメントのジッタをStep Lineで表示
                         r: 受信セグメントのジッタをStep Lineで表示
    -tsq     [s|r|a|d] : カーネルレベルのシーケンス番号表示
                         s: 送信セグメントのシーケンス番号をStep Lineで表示
                         r: 受信セグメントのシーケンス番号をStep Lineで表示
                         a: 送信セグメントに対するACKのシーケンス番号をStep
                            Lineで表示
                         d: 喪失した送信セグメントのシーケンス番号をStep Line
                            で表示
    -tth     [s|r]     : カーネルレベルのスループット表示
                         s: 送信セグメントのスループットをLineで表示
                         r: 受信セグメントのスループットをLineで表示
                         S: 送信セグメントのスループットをStep Lineで表示
                         R: 受信セグメントのスループットをStep Lineで表示
    -twin    [w|s]     : 輻輳ウィンドウサイズとスロースタート閾値表示
                         w: Congestion Window
                         s: Slow Start Shreshold
    -tlost   [s|a]     : 喪失セグメントの計算
                         s: 喪失した送信セグメントを検出処理
                         a: 喪失したACKの検出処理
    -trtt    [m|s|o]   : ラウンドトリップ時間と再送タイムアウトの表示
                         m: RTT(ラウンドトリップ時間)をStep Lineで表示
                         s: カーネル内部でのRTTの計測値をStep Lineで表示
                         o: カーネル内部でのRTO(再送タイムアウト)を
                            Step Lineで表示
    -tdelay  [s|a]     : カーネルレベルの遅延時間の表示
                         s: 送信セグメントの遅延時間をStep Lineで表示
                         a: ACKの遅延時間をStep Lineで表示
    -tjitter [s|r]     : カーネルレベルのJitterの表示
                         s: 送信セグメントのジッタをStep Lineで表示
                         r: 受信セグメントのジッタをStep Lineで表示
    -ulost             : UDPの喪失データグラムの計算
    -t      time(sec)  : 時間間隔の粒度(デフォルト0.1秒)
    -p                 : スループット，喪失セグメント等の計算処理をする。
    -ps                : PostScriptで出力
    -eps               : EPSで出力
    -color             : ColorのPSまたはEPSで出力(-ps，-eps指定時のみ有効)
    -title #           : fileの何ワード目をtitleに使うか。

  dbs_viewはたくさんの中間ファイルを作ります。ですから，出力ファイル名をコマ
  ンドファイルに記述するときは，

    file= host1_host2/data1

  のように，ディレクトリ名/ファイル名と指定することを勧めます。なお，ディレ
  クトリは実験前にmkdirであらかじめ作成してください。なおこの設定で，
  -title 1とすると"host1_host2"，-title 2とすると"data1"，-titleを指定しない
  と"host1_host2/data1"のそれぞれがプロットしたデータの題名になります。


◎DBSデーモンをinetdから起動する方法

  dbsdを
    /usr/local/etc/dbsd
  にコピーしてください。

  /etc/servicesに次の行を追加してください。

    dbs             10710/tcp

  /etc/inetd.confに次の行を追加してください。

    dbs stream tcp nowait root /usr/local/etc/dbsd dbsd -D

  inetdのプロセス番号を調べ，

    kill -HUP プロセス番号

  を実行してください。以上でinetdから自動的にdbsdが起動されるようになります。
  なお，特定のホスト以外のホストからコマンドを受け付けないようにしたい場合に
  は，

    dbs stream tcp nowait root /usr/local/etc/dbsd dbsd -D -h cmdhost

  のように，dbsd -Dの後に"-h ホスト名"を書いてください。

◎実験方法

  1. すべての実験ホストでDBSデーモンを起動する。(inetd.confに登録した場合は不
     要)
  2. DBSコントローラを起動し，実験終了まで待つ。
     実験修了時間の目安はend_time+20秒+αです。
  3. DBSビューワでグラフを表示する。


◎コマンドファイルの書き方

  コマンドファイルのサンプルを示します。フリーフォーマットになっており改行や
  空白行は自由に入れられます。順番も自由です。また，#から行末まではコメント
  と見なされます。

  # Sample 1
  {                                             
          sender {
                  hostname  = host1;
                  hostname_cmd  = host1;
                  port      = 0;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  send_buff = 65535;
                  recv_buff = 65535;Sample 2 
                  mem_align = 2048;
                  pattern {2048,   2048,     0.0,      0.0}
          }
          receiver {
                  hostname  = host2;
                  hostname_cmd  = host2;
                  port      = 20001;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  recv_buff = 65535;
                  send_buff = 65535;
                  mem_align = 2048;
                  pattern {2048,   2048,     0.0,      0.0}
          }
          file           = ether/test1;
          protocol       = TCP;
          start_time     = 0.0;
          connection_mode= BEFORE;
          end_time       = 30;
          send_times     = 2048;
  }

  # Sample 2 
  # MPEG1 Traffic Model
  {                                             
          sender {
                  hostname  = host1;
                  port      = 12300;
                  mem_align = 2048;
                  pattern { 40000,  1024,    0.04,      0;
                             2000,  1024,    0.04,      0;
                             2000,  1024,    0.04,      0;
                            10000,  1024,    0.04,      0;
                             2000,  1024,    0.04,      0;
                             2000,  1024,    0.04,      0;
                            10000,  1024,    0.04,      0;
                             2000,  1024,    0.04,      0;
                             2000,  1024,    0.04,      0;
                            10000,  1024,    0.04,      0;
                             2000,  1024,    0.04,      0;
                             2000,  1024,    0.04,      0;}
            }
            receiver {
                    hostname  = host2;
                    port      = 12300;
                    mem_align = 2048;
                    pattern {2048,   2048,     0.0,      0.0}
            }
            file           = ether/test2;
            protocol       = UDP;
            start_time     = 0.0;
            end_time       = 30;
            send_times     = 100;
  }

・コマンドファイルの書式

  コマンドファイルは次のような書式になっています。データ転送ストリームの数だ
  け設定を書く必要があります。複数のデータ転送をする場合には，port番号やfile
  名の指定が同じにならないように注意してください。
  
  { 
      sender   {送信ホストの設定; 送信トラヒックパターン}
      receiver {受信ホストの設定; 受信パターン}
      コネクションの設定;
  }
  
  { 
      sender   {送信ホストの設定; 送信トラヒックパターン}
      receiver {受信ホストの設定; 受信パターン}
      コネクションの設定;
  }
  .
  .
  .



・送信トラヒックパターンの書式

  pattern {
    データの大きさ, 一回に送信する大きさ, 送信の時間間隔, 送信の待ち時間;
    データの大きさ, 一回に送信する大きさ, 送信の時間間隔, 送信の待ち時間;
             .               .                  .               .       ;
             .               .                  .               .       ;
  }

  それぞれ次のような意味を持ちます。

  データの大きさ: 一つのデータ
  一回に送信する大きさ: 「データの大きさ」を数回のシステムコールにわけて送信
  送信の時間間隔: 送信レート制御
  送信の待ち時間: システムのオーバヘッド

  図で表すと次のようになります。


  データの大きさ       |<-------------->|     |<-------->|   |<---------->|

  一回に送信する大きさ |<-->|<-->|<-->|       |<->|<->|      |<---->|<---->|

                       +----+----+----+-+     +---+---+--+   +------+------+
  送信セグメント       |    |    |    | |     |   |   |  |   |      |      |
  (送信データグラム)   +----+----+----+-+     +---+---+--+   +------+------+

  送信の待ち時間                        |<--->|          |<->|

  送信の時間間隔       |<-------------------->|<------------>|

  時間の経過           ---------------------------------------------------->


・受信パターンの書式

  pattern {
    バッファの大きさ, 一回に受信する大きさ, 受信の時間間隔, 受信の待ち時間;
    バッファの大きさ, 一回に受信する大きさ, 受信の時間間隔, 受信の待ち時間;
             .               .                  .               .         ;
             .               .                  .               .         ;
  }

  通常の設定では「一回に受信する大きさ」毎に受信時刻を記録する。しかし，TCP
  では，1回のrecvシステムコールで受信するサイズは不定である。受信サイズにか
  かわらず，recvシステムコールごとに受信時刻や受信データサイズを記録するこ
  とができるが，若干注意が必要である。設定は次の通りである。

  -「バッファの大きさ」はrecvシステムコールで使用するバッファサイズを設定する。
  -「一回に受信する大きさ」に-1を設定する。
  - receiver {} の設定で record_buff (受信時刻を記録するバッファの大きさ)を
    指定する。これは，recvシステムコールを実行する回数は環境によって変化す
    るので，自動的に適切な値を選ぶことができないからである。
    省略時には現バージョンのDBSでは送信回数分のバッファが設定される。


・送受信ホストの設定

  hostname        通信実験を行なうホスト(インターフェース)名かIPアドレス
  hostname_cmd    コマンドを受信するインターフェース名かIPアドレス(省略可，省
                  略時はhostnameと同じに設定される)
  port            通信実験時のポート番号
                  コネクションを張るときにクライアントとなる側は0に設定できる。
                  その場合はOSがport番号を自動的に設定する。
  so_debug        ON:   so_debugオプションを使用する
                  OFF:  so_debugオプションを使用しない(省略時)
  tcp_trace       ON:   送受信のシステムコール毎にコントロールブロックの値を
                        記録する。
                  OFF:  コントロールブロックの値を記録しない(省略時)
                  AFTER:データの送受信終了後まとめてコントロールブロックの値
                        を記録する。このオプションを利用するためには
                        netinet/tcp_debug.hのTCP_NDEEBUGの値を大きくしてカー
                        ネルを再構築する必要がある。
  no_delay        ON:   no_delayオプションを使用する
                  OFF:  no_delayオプションを使用しない(省略時)
  mss             TCPセグメントサイズの指定。(効果はOSに依存する)
  recv_buff       受信バッファのサイズ(省略可，省略時はホストのデフォルト値)
  send_buff       送信バッファのサイズ(省略可，省略時はホストのデフォルト値)
  record_buff     受信時刻を記録するバッファのサイズを指定する。
                  受信ホストでpatternの「一回に受信する大きさ」に-1を設定した
                  場合に使用する。省略時には送信回数分のバッファが用意される。
                  「一回に受信する大きさ」に-1が設定されていない場合には無視
                  される。
  trace_buff      TCP DEBUGを記録するバッファのサイズを指定する。
                  省略時には送信回数の3倍分のバッファが用意される。
  mem_align       送受信のバッファをページ境界に整列されるときに利用する
                  単位はbyte。
  align_offset    整列した送受信のバッファの位置を移動するときに利用する
                  単位はbyte。
  align_pad       送受信のバッファを大きく用意する時に使用する。単位はbyte。
  file            出力ファイル名


・コネクションの設定

  protocol        トランスポートのプロトコル (TCP または UDP)
  start_time      送信開始時刻(秒)。精度は0.01秒程度。
  connection_mode AFTER:   コネクションの確立を測定する
                  BEFORE:  データ送信前にコネクションをあらかじめ確立する(省
                           略時)
  server          RECEIVER:コネクションを送信ホストから受信ホスト向きに張る
                           (省略時)
                  SENDER:  コネクションを受信ホストから送信ホストに張る
                  このオプションはFire Wallを挟んでコネクションを張りたいと
                  きに役立つかも知れない。
  end_time        測定の終了または中断時刻(秒)
  send_times      送信側のトラヒックパターンを何回送信するか


◎出力ファイル

  次のファイルが出力されます。

  .tはアプリケーションレベルの送受信時刻
  .cはアプリケーションレベルのコネクションの確率・解放時刻
  .td_*はTCP DEBUG機能を利用して取り出したデータ。
      td_s_* は送信ホスト
      td_r_* は受信ホスト

  数字の意味は
    0  TA_INPUT     セグメント受信時
    1  TA_OUTPUT    セグメント送信時
    2  TA_USER      システムコール実行時
    3  TA_RESPOND   
    4  TA_DROP      処理しきれなくてセグメントが捨てられたとき

・アプリケーションレベルの送受信時刻(.t)

  send_sequence   送信シーケンス番号
  send_size       送信サイズ(byte)
  send_time       送信時刻(秒)
  recv_sequence   受信シーケンス番号
  recv_size       受信サイズ(byte)
  recv_time       受信時刻(秒)

・コネクションの確立・解放(.c)

  1行目  client                     server
  2行目  コネクション確立開始時刻   コネクション確立受理時刻
  3行目  コネクション確立完了時刻   コネクション解放開始時刻
  4行目  コネクション解放開始時刻   コネクション解放終了時刻
  5行目  コネクション解放終了時刻

・tcp_traceの出力結果(.td*)

  td_time         コントロールブロックが記録された時刻
  act             コントロールブロックがどの関数によって記録されたかを示す
                  フラグ
  th_seq          TCPヘッダの送信シーケンス番号
  th_ack          TCPヘッダの確認応答番号
  len             パケットに含まれるデータの長さ
  th_flags        TCPヘッダのTCPフラグ
  t_state         コネクションの状態
  t_rxtshift      再送時間のlog(2)
  t_rxtcur        再送時間
  t_dupacks       2重確認応答を受け取った個数
  t_maxseg        最大セグメント長
  t_force         1の場合は強制的に送信
  t_flags         送受信を制御するTCPのフラグ
  snd_una         送信した確認応答の番号
  snd_nxt         次に送信する確認応答の番号
  snd_wl1         ウィンドウを更新するセグメントのシーケンス番号
  snd_wl2         ウィンドウを更新するセグメントの確認応答番号
  iss             送信シーケンス番号の初期値
  snd_wnd         送信ウィンドウの大きさ
  rcv_wnd         受信ウィンドウの大きさ
  rcv_nxt         次に受信するシーケンス番号
  irs             受信シーケンス番号の初期値
  rcv_adv         相手のホストへ通達したウィンドウの大きさ
  snd_max         送信した最大シーケンス番号(再送するときに利用される)
  snd_cwnd        輻輳ウィンドウの大きさ
  snd_ssthresh    スロースタートの閾値
  t_idle          停止している時間
  t_rtt           ラウンドトリップ時間
  t_rtseq         時刻を計測したシーケンス番号
  t_srtt          平滑化したラウンドトリップ時間
  t_rttvar        ラウンドトリップ時間の分散
  max_sndwnd      送信された最大ウィンドウの大きさ
