NS2的NODE類

Node是網絡拓撲的重要組成部分,時NS2複合網絡組件的一個大類。複合組件(如node和link)不是TclObject類的派生類,而是NS2中獨立的類,一個ns2節點本質是一個分類器的集合。

節點結構圖:
每個節點至少包含一下幾個部分:一個地址或者id_,初始值是0,當節點建立時模擬的名字空間將自動加1;一個鄰居鏈表neighbor_;一個代理鏈表agent_;一個節點類型識別器nodetype_;一個路由模塊。
Tcl對象:1)地址分類器(address classifier),用來判斷分組的目標地址,把傳入的包分派到正確的鏈路。
~ns/classifier/classifier-addr.{h/cc};
            2)端口分類器(port classifier),用來判斷分組的目標Agent,把傳入的包分派到爭取的代理。~ns/classifier/classifier-port.{ h/cc}。

 

節點建立:
set ns [new Simulator]                      set ns [new Simulator -multicast on]
$ns node
設置節點:(控制函數、地址和端口號管理、代理管理、添加鄰居)
控制函數:$node entry:返回節點入口地址;$node reset:重新設置節點上所有代理。
地址和端口號管理:$node id:返回節點的節點號;$node agent(port):返回一個端口號爲port的代理的句柄;
             alloc-port:返回下一個可獲得的端口號;
             add-route/routes:單播時增加路由路徑從而產生classifier_。$node add-route <destination id> <TclObject>
                                       $node add-routes <destination id> <TclObjects>添加多重路由路徑到同一個目的地。
             delete-routes():包括參數id,一個TclObject的列表和一個模擬器的空代理的指針。
代理管理:attach():把制定的代理加入到一個agents_鏈表中,給該代理分配一個端口號並設置它的源地址。設置代理的指針爲它的入口。例如節點的entry()添加一個節點上的多路服用的端口(dmux_)的指針到代理相應的dmux_分類器。相反的detach()從代理
agents_中移除代理,代理目標指針指向空代理的入口。
添加鄰居:過程add-neighbor()用於增加一個鄰居到這個鏈表中,neighbors()用於返回鄰居鏈表。

配置節點:
  使用函數simulator::node-config{}配置即將創建的節點屬性,這種節點配置方法主要針對移動節點和衛星。
  e.g: 

#設定模擬需要的一些屬性,比如mobilenode的Channel、MAC、LL層的類型,天線類型,節點數目,場景的長寬尺寸等。
  set val(chan) Channel/WirelessChannel ;#信道類型
  set val(prop) Propagation/TwoRayGround ;#無線-傳播模型
  set val(netif) Phy/WirelessPhy ;#網絡接口類型
  set val(mac) Mac/802_11 ;#MAC類型
  set val(ifq) Queue/DropTail/PriQueue ;#接口隊列類型
  set val(ll) LL ;#鏈路層類型
  set val(ant) Antenna/OmniAntenna ;#天線模型
  set val(ifqlen) 50 ;#ifq中的最大分組
  set val(nn) 2 ;#移動節點數
  set val(rp) AODV ;#路由協議
  set val(x) 500 ;#拓撲結構的X軸範圍
  set val(y) 500 ;#拓撲結構的Y軸範圍
  $set ns [new Simulator]
#建立節點(mobilenode)之前,先配置節點的一些參數。agentTrace表示應用層的trace,在trace文件中用#AGT表示;routerTrace表示路由的trace,在toace文件中用RTR表示;macTrace表示MAC層的trace,
#在trace文件中用MAC表示;movementTrace表示記錄節點移動命令的trace,在trace文件中用M表示。
  $ns node-config -addressType def/ ;#設定節點地址類型:def(flat) & hierarchical
  -adhocRouting $val(rp) / ;#設定移動節點所使用的路由協議
  -llType $val(ll) / ;#設定移動節點的邏輯鏈路層
  -macType $val(mac) / ;#設定移動節點的MAC層
  -ifqType $val(ifq) / ;#設定移動節點的隊列類型
  -ifqLen $val(ifqlen) / ;#設定移動節點的隊列長度
  -antType $val(ant) / ;#設定移動節點的天線類型
  -propType $val(prop) / ;#設定移動節點的無線信號傳輸模型
  -phyType $val(netif) / ;#設定移動節點物理層類型
  -channelType $val(chan) / ;#設定移動節點的無線信道類型
  -topoInstance $topo / ;#設定移動節點的拓撲對象
  -agentTrace ON / ;#是否打開應用層的trace
  -routerTrace ON / ;#是否打開路由的trace
  -macTrace OFF / ;#是否打開MAC層的trace
  -movementTrace OFF ;#是否打開節點位置和移動信息的trace

#建立兩個節點(mobilenode),關閉節點的隨機運動功能,即節點的運動完全由我們指定。
  for {set i 0} {$i > shift_) & mask_); }
   virtual void recv(Packet* p, Handler* h);
  //recv()函數的實現參考源文件~ns/classifier/classifier.cc
   virtual NsObject* find(Packet*);
  // find()函數的實現參考源文件~ns/classifier/classifier.cc
   virtual int classify(Packet *);
   virtual void clear(int slot); //從表中刪除對象
   virtual void install(int slot, NsObject*); //從表中增加對象
  protected:
   virtual int command(int argc, const char*const* argv);
   void alloc(int); // alloc()函數動態的分配足夠的空間來放置slot
   NsObject** slot_; /* table that maps slot number to a NsObject */
   int nslot_;
   int maxslot_;
   int offset_; // offset for Packet::access()
   int shift_;
   int mask_;
   NsObject *default_target_;
   int nsize_; //what size of nslot_ should be
  };
  ——————————————————————————————————
  e.g:~ns/classifier/classifier.cc
  void Classifier::recv(Packet* p, Handler*h)
  {
   NsObject* node = find(p);
   if (node == NULL) {
   Packet::free(p);
   return;
   }
   node->recv(p,h);
  }
  NsObject* Classifier::find(Packet* p)
  {
   NsObject* node = NULL;
   int cl = classify(p);
   if (cl = nslot_ || (node = slot_[cl]) == 0) {
   if (default_target_)
   return default_target_;
   Tcl::instance().evalf("%s no-slot %ld", name(), cl);
   if (cl == TWICE) {
   cl = classify(p);
   if (cl = nslot_ || (node = slot_[cl]) == 0)
   return (NULL);
   }
   }
   return (node);
  }
  當classifier收到一個分組時(即recv()函數被調用時),recv()函數首先調用find()函數來處理該分組,find()函數會調用classify()函數,不同類型的classifier對classify()函數定義不同,但各種classify函數都會對分組作檢查然後返回一個slot索引值。如果索引值有效,並指向一個有效的TclObject,recv()函數就會把分組傳遞給該TclObject,即調用該TclObject的recv()函數;如果索引無效,就會清除該分組並返回。
  ——————————————————————————————————
  幾種主要的Classifier類:
  1.address classifier:按分組目的地址進行匹配,用來支持單播分組轉發,通過對分組的目的地址做位運算來產生一個slot number。該類對應的classify()函數定義參考~ns/classifier/classifier-addr.cc。
  ——————————————————————————————————
  int AddressClassifier::classify(Packet *p)
  {
   hdr_ip* iph = hdr_ip::access(p);
   return mshift(iph->daddr());
  };
  iph->daddr()函數返回分組IP頭中的目的地址,mshift(int val)函數的定義在前面Classifier類的定義中可以找到,其中mask_和shift_的值可以通過Otcl來設置,缺省值分別爲0xffffffff和0,即mshift(int val)直接返回val的值。
  ——————————————————————————————————
  2.port classifier:按分組目的端口進行匹配,將分組傳遞給相應的Agent對象。該類對應的classify()函數定義參考~ns/classifier/classifier-addr.cc。
 ——————————————————————————————————
  int PortClassifier::classify(Packet *p)
  {
   hdr_ip* iph = hdr_ip::access(p);
   return iph->dport();
  };
  iph->dport()函數返回分組IP頭中的目的端口。
  ——————————————————————————————————
  3.replicator:與普通classifier不同,不使用classify()函數,作用是生成一個分組的多份拷貝,並把這些拷貝轉發給slot表中的所有對象。在組播分組轉發時,一個分組需要被轉發給多個目標對象,生成分組拷貝的工作由replicator完成。Replicator類的定義及其recv()函數的定義參考~ns/mcast/replicator.cc。
  ——————————————————————————————————
  class Replicator : public Classifier
  {
  public:
   Replicator();
   void recv(Packet*, Handler* h = 0);
   virtual int classify(Packet*) {/*NOTREACHED*/ return -1;};
  protected:
   virtual int command(int argc, const char*const* argv);
   int ignore_;
   int direction_;
  };
  void Replicator::recv(Packet* p, Handler*)
  {
   hdr_ip* iph = hdr_ip::access(p);
   hdr_cmn* ch = hdr_cmn::access(p);
   if (maxslot_ saddr(), iph->daddr(), ch->iface());
   Packet::free(p);
   return;
   }
  ……
   for (int i = 0; i recv(p->copy());
   }
   /* we know that maxslot is non-null */
   slot_[maxslot_]->recv(p);
  }
  可以看到Replicator類的recv()函數並不調用classify()函數,它只是爲slot表中的每一個對象複製一份該分組的拷貝,並把拷貝發送給該對象,表中的最後一個對象收到的是原始的分組,而原始分組和拷貝實際上是完全一樣的。


  ——————————————————————————————————
  Classifier類提供了一些Tcl實例過程,用戶可以在Tcl中對Classifier對象進行控制。主要實例過程:
  1. alloc-port :尋找一個空閒的slot。
  2. clear :將號碼爲index的slot清空。
  3. installNext:在最後一個slot後插入一個新的指向object的表項,並返回該表項的slot號碼:如果object爲空,會返回錯誤信息。
  4. slot :產旬號碼爲index的slot對應對象名,如果該slot爲空,會返回錯誤信息。
  5. findslot:查詢一個object所在的slot號碼,如果該object爲空,會返回錯誤信息,如果在表中沒有找到該object,會返回-1。
  6. install :將號碼爲index的slot所指向的對象設爲object。
  e.g. Classifier類部分Tcl實例過程的使用方法舉例,參見

  ——————————————————————————————————
  set ns [new Simulator] ;#建立一個Simulator對象的實例並把它賦值給變量ns。
  set node [$ns node] ;#新建一個節點並賦值給node。
  set udp0 [new Agent/UDP] ;#新建一個UDP Agent並賦值給udp0。
  set udp1 [new Agent/UDP] ;#新建一個UDP Agent並賦值給udp1。
  set null [new Agent/Null] ;#新建一個UDP Agent並賦值給null。
  $ns attach-agent $node $udp0; #將UDP Agent udp0綁定到node上。
  puts "[[$node set dmux_] slot 0]" ;#查詢號碼爲0的slot對應的對象名並將其輸出。
  puts "$udp0" ;#輸出udp0的值。
  puts "[[$node set dmux_] findslot $udp0]" ;#查詢udp0所在的slot號碼並輸出。
  puts "[[$node set dmux_] findslot $null]" ;#查詢null所在的slot號碼,表中沒有找到該對象,返回-1,並輸出。
  puts "============================================="
  puts "[[$node set dmux_] installNext $udp1]";#在最後一個slot 0後插入一個新的指向對象udp1的表項,返回
  ;#該表項的slot號碼1,並輸出。
  puts "[[$node set dmux_] slot 1]" ;#查詢號碼爲1的slot對應的對象名並將其輸出。
  puts "$udp1" ;#輸出udp1的值。
  puts "============================================="
  [$node set dmux_] install 0 $udp1 ;#將號碼爲0的slot所指向的對象設爲udp1。
  puts "[[$node set dmux_] slot 0]" ;#查詢號碼爲0的slot對應的對象名並將其輸出。
  puts "============================================="
  puts "[[$node set dmux_] alloc-port $null]" ;#尋找一個空閒的slot並輸出。
  [$node set dmux_] clear 0 ;# 將號碼爲0的slot清空。
  puts "[[$node set dmux_] alloc-port $null]" ;#尋找一個空閒的slot並輸出。
  puts "============================================="
  puts "[[$node set dmux_] slot 0]" ;# 查詢號碼爲0的slot對應的對象名,該object爲空,故返回錯誤信息。
  $ns run
  運行結果:
  ——————————————————————————————————
  相關Tcl命令:

     1. set $node [$ns node]:建立一個節點實例。
  2. $node id:返回該節點id。
  3. $node neighbors:返回鄰居節點的列表。
  4. $node add-neighbor <neighbor_node>:增加一個鄰居節點(注:這是單向的鄰居,即“neighbor node”是node的鄰居,但node不是“neighbor node”的鄰居)。
  5. $node node-addr:返回節點的地址(address)。地址類型爲def時,節點地址與節點id相同;地址類型爲hierarchical時,節點地址是一個字符串。
  6. $node reset:重置連到這個node上的所有agent。
  7. $node agent <port_num> :返回port_num端口所指向的agent對象,如果port_num端口沒有指向任何對象,返回null字符串。
  8. $node attach <agent> <optional:port_num> :將agent對象連接到節點上,如果沒有指定端口號,節點會自己分配一個空閒的端口,並把agent連接到該端口上;如果指定端口爲port_num,節點會把agent連接到端口port_num上。
  9. $node detach <agent> <null_agent>:將agent與節點分離,並把一個null_agent連接到agent原來所在的端口上。
    10. $node incr-rtgtable-size對象變量rtsize_用於保持對每個節點路由表大小的記錄,該命令用於當每次路由入口加入分類器時增加路由表的大小。
     11.$node add-route <destination_id> <target>用於增加單播路由的分類器,目標是一個Tcl對象,如果<destination_id>和節點的id相同,則該對象可能就是dmux_的入口(節點的端口複用器)。否則它通常是該目的鏈表的頭。
      12.$ns_ node [<hier_addr>]創建和返回一個節點的實例。若<hier_addr>給出,指派節點地址爲<hier_addr>類型。注意:當層次地址通過set-address-format hierarchical{}或者node-config-addressType hierarchical{}調用時,<hier_addr>必須被使用。

 

 

原文地址 http://elaine172xiaoxiao.spaces.live.com/blog/cns!94020BE8ACC017C9!215.entry
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章