[Previous section] [Back to the index] [Next section]
In this section I will give you an example for a new protocol that could be implemented in ns. You should probably become fairly familiar with ns before you try this yourself, and some C++ knowledge is definitely necessary. You should also read at least the chapters 3.1-3.3 from "ns Notes and Documentation" (now renamed ns Manual) to understand the interaction between Tcl and C++.
この節では, ns上に新たなプロトコルを実装する際の例について説明していきます. この節の内容を自分で試す前に, たぶん十分nsに慣れ親しんでる 必要があると思いますし, ちょっとしたC++の知識は間違いなく必要です. あとはtclとC++間のやりとりを理解するためにns Manualの3.1-3.3節を 読んどいてください.
The code in this section implements some sort of simple 'ping' protocol (inspired by the 'ping requestor' in chapter 9.6 of the "ns Notes and Documentation" (now renamed ns Manual), but fairly different). One node will be able to send a packet to another node which will return it immediately, so that the round-trip-time can be calculated.
この節のコードはある種の単純な`ping'プロトコルを実装するものです (ns Manualの9.6章にある`ping requestor'に触発されたもんです). 1つのノードはパケットを他のノードに送信することができて, 受信側の ノードはすぐに返事をするというものです. つまり往復時間(RTT)が計算できるわけです.
I understand that the code presented here might not be the best possible implementation, and I am sure it can be improved, though I hope it is easy to understand, which is the main priority here. However, suggestions can be sent here.
私はこの節のコードが最善の実装じゃないだろうってことは理解してますし, 改善されうるもんだということを認識してます. でも, ここでの一番重要なことは, 簡単に理解できるってことだと思ってます. とは言っても, 良いコメントがあったらここへ送ってください.
VII.1. The header file
In the new header file 'ping.h' we first have to declare the data structure
for the new Ping packet header which is going to carry the relevant data.
新たなヘッダファイル`ping.h'で, 最初に適切なデータを運ぶための 新たなPingパケットヘッダのデータ構造を宣言しなくちゃいけません.
|
charの`ret'は, 送信者からpingされているノードへ送信される方向では0に セットされ, 逆向き(つまりping reply)では1に設定されます. doubleの`send_time'はパケットが送信された際の時刻をパケットに記録する もので, 後でRTTを計算するときに使われます.
The following piece of code declares the class 'PingAgent' as a subclass of the class 'Agent'.
以下のコードはclass `PingAgent'をclass `Agent'のサブクラスとして定義します.
|
以下の節では, `PingAgent()'のコンストラクタ, 関数`command()', この宣言で再定義される`recv()'を定義するC++のコードを示していきます. intの`off_ping_'はパケットのpingヘッダにアクセスするために使われます. ローカルなオブジェクトのスコープを表す変数には, 通常最後に'_'を つけることに注意してください.
You can download the full header file here (I suggest you do that and take a quick look at it, since the code that was presented here isn't totally complete).
完全なヘッダファイルをここからダウンロードできます. (ここで示しているコードは完全なものじゃないので, ちらっとみるだけに しておいた方が良いと思います).
VII.2. The C++ code
First the linkage between the C++ code and Tcl code has to be defined.
It is not necessary that you fully understand this code, but it would help
you to read the chapters 3.1-3.3 in the
"ns Manual" if you
haven't done that yet to understand it.
C++のコードとtclのコード間の結合を最初に定義しなくちゃいけません. このコードを完全に理解する必要はないけど, もしまだ理解してないのだったら, ns Manualの3.1-3.3章を読むと助けになると思います.
|
The next piece of code is the constructor for the class 'PingAgent'. It binds the variables which have to be accessed both in Tcl and C++.
次のコードはclass `PingAgent'のコンストラクタです. TclとC++の両方でアクセスされる変数を関係づける(bind?)ものです.
|
The function 'command()' is called when a Tcl command for the class 'PingAgent' is executed. In our case that would be '$pa send' (assuming 'pa' is an instance of the Agent/Ping class), because we want to send ping packets from the Agent to another ping agent. You basically have to parse the command in the 'command()' function, and if no match is found, you have to pass the command with its arguments to the 'command()' function of the base class (in this case 'Agent::command()'). The code might look very long because it's commented heavily.
関数`command()'はclass `PingAgent()'のためのtclコードが実行される 時に呼び出されます. 今回の場合, エージェントから他のエージェントへ pingパケットを送信したいので, 呼び出しは'$pa send' (`pa'がAgent/Ping classのインスタンスだと仮定してます)の際に なるでしょう. 基本的には, command()関数内の命令(command)をパースしなければいけなくて, もしマッチするものがなければ, その命令は引数ごと, 基本クラスの`command()'関数(この場合`Agent::command()')にわたされなければ なりません. 大量のコメントがあるせいでコードはとっても長く見えるかもしれません.
|
The function 'recv()' defines the actions to be taken when a packet is received. If the 'ret' field is 0, a packet with the same value for the 'send_time' field, but with the 'ret' field set to 1 has to be returned. If 'ret' is 1, a Tcl function (which has to be defined by the user in Tcl) is called and processed the event (Important note to users of the ns version 2.1b2: 'Address::instance().NodeShift_[1]' has to be replaced with 'NODESHIFT' to get the example to work under ns 2.1b2).
関数`recv()'はパケットが受信された際に取られる動作を定義します. もし`ret'フィールドが0だったら, 受信したパケットの `send_time'フィールドの値を新たなパケットの`send_time'フィールドにセットし, `ret'フィールドを1にしたものが送信者に送り返されます. もし`ret'が1の場合(これは送信者がecho replyを受け取った場合), Tclの関数 (これはユーザによってtclで定義されなければならない)が呼び出されて (対応する?)イベントが処理されます. (ns 2.1b2のユーザへの重要なお知らせ: ns 2.1b2でこの例題を正しく動作させるには 'Address::instance().NodeShift_[1]'を `NODESHIFT'に置き換えなくてはいけません.)
|
ここからファイルをダウンロードできます. もっとも面白い部分は, Tclの関数`recv'で呼び出され, pingノードのidとRTT(ms表記)をパラメータとする `tcl.eval()'関数 でしょう. この関数のコードがどう書かれるかについてはVII.4節で示すとして, まずnsを再コンパイルする前に他のいくつかのファイルを編集しなくちゃいけません.
VII.3. Necessary changes
You will have to change some things in some of the ns source files if you want to add a new agent, especially if it uses a new packet format. I suggest you always mark your changes with comments, use #ifdef, etc., so you can easily remove your changes or port them to new ns releases.
新しいエージェントを加えたい, とくに新しいパケットフォーマットを使う 場合には, nsのソースファイルのいくつかの部分を変更しなくちゃいけません. 常に自分が変更した部分にコメントつきで(ifdefとか使って) マークしといた方が良いです. そうしとけば自分の加えた変更を簡単に削除できるし新しいバージョンのnsに 移植するも簡単です.
We're going to need a new packet type for the ping agent, so the first step is to edit the file 'packet.h'. There you can find the definitions for the packet protocol IDs (i.e. PT_TCP, PT_TELNET, etc.). Add a new definition for PT_PING there. In my edited version of packet.h, the last few lines of enum packet_t {} looks like the following code (it might look a bit different in earlier/later releases).
pingエージェントのための新しいパケット形式が必要なので, 最初に`packet.h'を編集します. ファイルでは, パケットプロトコルID (たとえばPT_TCP, PT_TELNETなど)の 定義が見つかるでしょう. PT_PINGのための新しい定義をファイルに加えましょう. 私が編集しているバージョンのpacket.hでは, enum packet_t{}の最後の 数行は次のようなコードになってます(たぶん古い/新しいリリースでは ちょこっと違ってるかもしれません).
|
You also have to edit the p_info() in the same file to include "Ping".
同様に, 同じファイル内のp_info()にPingを加えなくてはいけません.
|
Remember that you have to do a 'make depend' before you do the 'make', otherwise these two files might not be recompiled.
`make'と叩く前に`make depend'を忘れないように. 忘れるとこれらの2つのファイルは再コンパイルされません.
The file 'tcl/lib/ns-default.tcl' has to be edited too. This is the file where all default values for the Tcl objects are defined. Insert the following line to set the default packet size for Agent/Ping.
'tcl/lib/ns-default.tcl'も編集しなくちゃいけません. このファイルは, Tclオブジェクトの全てのデフォルトの値が定義されてるものです. Agent/Ping用にデフォルトのパケットサイズを加えます.
|
You also have to add an entry for the new ping packets in the file 'tcl/lib/ns-packet.tcl' in the list at the beginning of the file. It would look like the following piece of code.
同様に, 'tcl/lib/ns-packet.tcl'の最初にあるリスト中に新しいpingパケット用の エントリを加えなくてはいけません.
|
The last change is a change that has to be applied to the 'Makefile'. You have to add the file 'ping.o' to the list of object files for ns. In my version the last lines of the edited list look like this:
最後の変更点は, 'Makefile'に関するものです. 'ping.o'をnsのオブジェクトファイルのリストに加えます. 私のバージョンでは, 編集したリストの最後の数行は以下のようになってます:
|
You should be able to recompile ns now simply by typing 'make' in the ns directory. If you are having any problems, please email ns-users.
さあ, nsディレクトリで単純にmakeとたたけば再コンパイル可能なはずです. もし何か問題があったらns-usersにメールしてください.
VII.4. The Tcl code
I'm not going to present the full code for a Tcl example for
the Ping agent now. You can download a full example
here. But I will show you how
to write the 'recv' procedure that is called from the 'recv()'
function in the C++ code when a ping 'echo' packet is received.
今のところ, Pingエージェントのtclのコードの全てを説明するつもりはありません. 完全なファイルはここからダウンロードしてください. だけど, ping 'echo'パケットが受け取られた時の, C++のrecv()関数から呼ばれる tclのecv手続きをどのように書くかのみを説明します.
|
このコードはほんとに簡単に理解できるでしょう. 単に新しいことは, エージェントが接続されている ノードのnode idを得るには, 基本クラス'Agent'のメンバ変数'node_'を アクセスすれば良いということだけです.
Now you can try some experiments of your own. A very simple experiment would be to not set the 'ret' field in the packets to 1. You can probably guess what is going to happen. You can also try to add some code that allows the user to send ping packets with '$pa send $node' (where 'pa' is a ping agent and 'node' a node) without having to connect the agent 'pa' with the ping agent on 'node' first, though that might be a little bit more complicated than it sounds at first. You can also read the chapter 9.6 from the "ns Manual" to learn more about creating your own agents. Good luck.
これで自分自身でいろいろ実験できるでしょ. とても簡単な実験は, パケットの'ret'フィールドを1にセットすることじゃ ないですよ. この場合何が起きるか予想できるでしょ? あとは, pingエージェントをノードにつなげないで ユーザがpingパケットをノードに(直接) '$pa send $node'でpingパケットを 送れるようにするってのもできるよね. だけど, 最初にやるにしてはちょっと複雑すぎるかもしれない. 自分でエージェントを作ることに関しては, ns Manualの9.6章を読むのが 良いのでは.
[Previous section] [Back to the index] [Next section]
Marc Greis greis@cs.uni-bonn.de日本語に関しての文句などは,
こちら