ns-node.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:16k
源码类别:

通讯编程

开发平台:

Visual C++

  1. # -*- Mode:tcl; tcl-indent-level:8; tab-width:8; indent-tabs-mode:t -*-
  2. #
  3. # Time-stamp: <2000-09-22 09:41:04 haoboy>
  4. #
  5. # Copyright (c) 1996-2000 Regents of the University of California.
  6. # All rights reserved.
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions
  9. # are met:
  10. # 1. Redistributions of source code must retain the above copyright
  11. #    notice, this list of conditions and the following disclaimer.
  12. # 2. Redistributions in binary form must reproduce the above copyright
  13. #    notice, this list of conditions and the following disclaimer in the
  14. #    documentation and/or other materials provided with the distribution.
  15. # 3. All advertising materials mentioning features or use of this software
  16. #    must display the following acknowledgement:
  17. #  This product includes software developed by the MASH Research
  18. #  Group at the University of California Berkeley.
  19. # 4. Neither the name of the University nor of the Research Group may be
  20. #    used to endorse or promote products derived from this software without
  21. #    specific prior written permission.
  22. # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. # SUCH DAMAGE.
  33. #
  34. # @(#) $Header: /cvsroot/nsnam/ns-2/tcl/lib/ns-node.tcl,v 1.89 2001/11/06 06:16:21 tomh Exp $
  35. #
  36. Node set nn_ 0
  37. Node proc getid {} {
  38. set id [Node set nn_]
  39. Node set nn_ [expr $id + 1]
  40. return $id
  41. }
  42. # The list of modules to be installed. More can be added via node-config. 
  43. # Base should always be the first module in this list.
  44. Node set module_list_ { Base }
  45. Node proc enable-module { mod_name } {
  46. Node instvar module_list_
  47. if { [lsearch $module_list_ $mod_name] < 0 } {
  48. lappend module_list_ $mod_name
  49. }
  50. }
  51. Node proc disable-module { mod_name } {
  52. Node instvar module_list_
  53. set pos [lsearch $module_list_ $mod_name]
  54. if { $pos >= 0 } {
  55. set module_list_ [lreplace $module_list_ $pos $pos]
  56. }
  57. }
  58. Node instproc init args {
  59. eval $self next $args
  60.         $self instvar id_ agents_ dmux_ neighbor_ rtsize_ address_ 
  61. nodetype_ multiPath_ ns_ rtnotif_ ptnotif_
  62. set ns_ [Simulator instance]
  63. set id_ [Node getid]
  64. $self nodeid $id_ ;# Propagate id_ into c++ space
  65. if {[llength $args] != 0} {
  66. set address_ [lindex $args 0]
  67. } else {
  68. set address_ $id_
  69. }
  70. $self cmd addr $address_; # Propagate address_ into C++ space
  71. #$ns_ add-node $self $id_        
  72. set neighbor_ ""
  73. set agents_ ""
  74. set dmux_ ""
  75.         set rtsize_ 0
  76. set ptnotif_ {}
  77. set rtnotif_ {}
  78. set nodetype_ [$ns_ get-nodetype]
  79. $self mk-default-classifier
  80. # XXX Eventually these two should also be converted to modules
  81. set multiPath_ [$class set multiPath_]
  82. }
  83. # XXX This instproc is backward compatibility; when satellite node, mobile
  84. # node (incl. MIP) are converted to routing modules, this should be merged 
  85. # into init{}
  86. Node instproc mk-default-classifier {} {
  87. Node instvar module_list_
  88. # At minimum we should enable base module
  89. foreach modname [Node set module_list_] {
  90. $self register-module [new RtModule/$modname]
  91. }
  92. }
  93. Node instproc id {} {
  94. return [$self set id_]
  95. }
  96. Node instproc node-addr {} {
  97. return [$self set address_]
  98. }
  99. #----------------------------------------------------------------------
  100. # XXX This should eventually go away, as we replace nodetype_ with 
  101. # routing modules
  102. Node instproc node-type {} {
  103. return [$self set nodetype_]
  104. }
  105. #----------------------------------------------------------------------
  106. #
  107. # Module registration
  108. #
  109. Node instproc register-module { mod } {
  110. $self instvar reg_module_
  111. $mod register $self
  112. set reg_module_([$mod module-name]) $mod
  113. }
  114. Node instproc unregister-module { mod } {
  115. $self instvar reg_module_
  116. $mod unregister
  117. # We do not explicitly check the existence of reg_module_($name).
  118. # If not, tcl will issue an error by itself. 
  119. unset reg_module_([$mod module-name])
  120. delete $mod
  121. }
  122. Node instproc list-modules {} {
  123. $self instvar reg_module_
  124. set ret ""
  125. foreach n [array names reg_module_] {
  126. lappend ret $reg_module_($n)
  127. }
  128. return $ret
  129. }
  130. Node instproc get-module { name } {
  131. $self instvar reg_module_
  132. # Must do an error check here.
  133. if [info exists reg_module_($name)] {
  134. return $reg_module_($name)
  135. } else {
  136. return ""
  137. }
  138. }
  139. #
  140. # Address classifier manipulation
  141. #
  142. # Increase the routing table size counter - keeps track of rtg table 
  143. # size for each node. For bookkeeping only.
  144. Node instproc incr-rtgtable-size {} {
  145. $self instvar rtsize_
  146. incr rtsize_
  147. }
  148. Node instproc decr-rtgtable-size {} {
  149. $self instvar rtsize_
  150. incr rtsize_ -1
  151. }
  152. Node instproc entry {} {
  153. return [$self set classifier_]
  154. }
  155. # Place classifier $clsfr at the node entry point. 
  156. #
  157. # - Place the existing entry at slot $hook of the new classifier. Usually 
  158. #   it is an address classifier sitting in a node entry, so this means that
  159. #   a special address should be assigned to pass packets to the original 
  160. #   classifier, if this is necessary. 
  161. #
  162. # - Associate the new classifier with $module (stored in mod_assoc_). This
  163. #   information is used later when the associated classifier is replaced, 
  164. #   then $module will be notified of this event and requested to unregister.
  165. #
  166. # - The original classifier is stored in hook_assoc_, this is used in 
  167. #   install-entry{} to connect the new classifier to the "classifier chain"
  168. #   to which the replaced classifier is linked.
  169. #
  170. # - To install at the entry something derived from Connector rather than 
  171. #   Classifier, you should specify $hook as "target". 
  172. Node instproc insert-entry { module clsfr {hook ""} } {
  173. $self instvar classifier_ mod_assoc_ hook_assoc_
  174. if { $hook != "" } {
  175. # Build a classifier "chain" when specified
  176. set hook_assoc_($clsfr) $classifier_
  177. if { $hook == "target" } {
  178. $clsfr target $classifier_
  179. } elseif { $hook != "" } {
  180. $clsfr install $hook $classifier_
  181. }
  182. }
  183. # Associate this module to the classifier, so if the classifier is
  184. # removed later, we'll remove the module as well.
  185. set mod_assoc_($clsfr) $module
  186. set classifier_ $clsfr
  187. }
  188. # We separate insert-entry from install-entry because we need a method to 
  189. # replace the current entry classifier and _remove_ routing functionality 
  190. # associated with that classifier. These two methods cannot be merged by 
  191. # checking whether $hook is empty. 
  192. Node instproc install-entry { module clsfr {hook ""} } {
  193. $self instvar classifier_ mod_assoc_ hook_assoc_
  194. if [info exists classifier_] {
  195. if [info exists mod_assoc_($classifier_)] {
  196. $self unregister-module $mod_assoc_($classifier_)
  197. unset mod_assoc_($classifier_)
  198. }
  199. # Connect the new classifier to the existing classifier chain,
  200. # if there is any.
  201. if [info exists hook_assoc_($classifier_)] {
  202. if { $hook == "target" } {
  203. $clsfr target $hook_assoc($classifier_)
  204. } elseif { $hook != "" } {
  205. $clsfr install $hook $hook_assoc_($classifier_)
  206. }
  207. set hook_assoc_($clsfr) $hook_assoc_($classifier_)
  208. unset hook_assoc_($classifier_)
  209. }
  210. }
  211. set mod_assoc_($clsfr) $module
  212. set classifier_ $clsfr
  213. }
  214. # CHANGE:
  215. # Node no longer keeps list of all rtmodules to be notified.
  216. # Instead we now have a chain (linked list) of modules, 
  217. # with rtnotif_ being the head of this linked list. 
  218. # Routing info flows from thru all rtmodules linked by this 
  219. # chain.
  220. # Whenever a route is added or deleted, $module should be notified
  221. Node instproc route-notify { module } {
  222. $self instvar rtnotif_
  223. if {$rtnotif_ == ""} {
  224. set rtnotif_ $module
  225. } else {
  226. $rtnotif_ route-notify $module
  227. }
  228. $module cmd route-notify $self
  229. }
  230. Node instproc unreg-route-notify { module } {
  231. $self instvar rtnotif_
  232. if {$rtnotif_ != ""} {
  233. if {$rtnotif_ == $module} {
  234. set rtnotif_ [$rtnotif_ set next_rtm_]
  235. } else {
  236. $rtnotif_ unreg-route-notify $module
  237. }
  238. }
  239. $module cmd unreg-route-notify $self
  240. }
  241. Node instproc add-route { dst target } {
  242. $self instvar rtnotif_
  243. # Notify every module that is interested about this 
  244. # route installation
  245. if {$rtnotif_ != ""} {
  246. $rtnotif_ add-route $dst $target
  247. }
  248. $self incr-rtgtable-size
  249. }
  250. Node instproc delete-route args {
  251. $self instvar rtnotif_
  252. if {$rtnotif_ != ""} {
  253. eval $rtnotif_ delete-route $args
  254. }
  255. $self decr-rtgtable-size
  256. }
  257. #
  258. # Node support for detailed dynamic unicast routing
  259. #
  260. Node instproc init-routing rtObject {
  261. $self instvar multiPath_ routes_ rtObject_
  262. set nn [$class set nn_]
  263. for {set i 0} {$i < $nn} {incr i} {
  264. set routes_($i) 0
  265. }
  266. if ![info exists rtObject_] {
  267. $self set rtObject_ $rtObject
  268. }
  269. $self set rtObject_
  270. }
  271. Node instproc rtObject? {} {
  272.     $self instvar rtObject_
  273. if ![info exists rtObject_] {
  274. return ""
  275. } else {
  276. return $rtObject_
  277.     }
  278. }
  279. Node instproc intf-changed {} {
  280. $self instvar rtObject_
  281. if [info exists rtObject_] { ;# i.e. detailed dynamic routing
  282. $rtObject_ intf-changed
  283. }
  284. }
  285. #----------------------------------------------------------------------
  286. # XXX Eventually add-routes{} and delete-routes{} should be 
  287. # unified with add-route{} for a single interface to install routes.
  288. # Node support for equal cost multi path routing
  289. Node instproc add-routes {id ifs} {
  290. $self instvar classifier_ multiPath_ routes_ mpathClsfr_
  291. if !$multiPath_ {
  292. if {[llength $ifs] > 1} {
  293. warn "$class::$proc cannot install multiple routes"
  294. set ifs [lindex $ifs 0]
  295. }
  296. $self add-route $id [$ifs head]
  297. set routes_($id) 1
  298. return
  299. }
  300. if {$routes_($id) <= 0 && [llength $ifs] == 1 && 
  301. ![info exists mpathClsfr_($id)]} {
  302. $self add-route $id [$ifs head]
  303. set routes_($id) 1
  304. } else {
  305. if ![info exists mpathClsfr_($id)] {
  306. #
  307. # 1. get new MultiPathClassifier,
  308. # 2. migrate existing routes to that mclassifier
  309. # 3. install the mclassifier in the node classifier_
  310. #
  311. set mpathClsfr_($id) [new Classifier/MultiPath]
  312. if {$routes_($id) > 0} {
  313. assert "$routes_($id) == 1"
  314. $mpathClsfr_($id) installNext 
  315. [$classifier_ in-slot? $id]
  316. }
  317. $classifier_ install $id $mpathClsfr_($id)
  318. }
  319. foreach L $ifs {
  320. $mpathClsfr_($id) installNext [$L head]
  321. incr routes_($id)
  322. }
  323. }
  324. }
  325. Node instproc delete-routes {id ifs nullagent} {
  326. $self instvar mpathClsfr_ routes_
  327. if [info exists mpathClsfr_($id)] {
  328. foreach L $ifs {
  329. set nonLink([$L head]) 1
  330. }
  331. foreach {slot link} [$mpathClsfr_($id) adjacents] {
  332. if [info exists nonLink($link)] {
  333. $mpathClsfr_($id) clear $slot
  334. incr routes_($id) -1
  335. }
  336. }
  337. } else {
  338. $self delete-route $id $nullagent
  339. incr routes_($id) -1
  340. # Notice that after this operation routes_($id) may not 
  341. # necessarily be 0.
  342. }
  343. }
  344. # Enable multicast routing support in this node. 
  345. # XXX This instproc should ONLY be used when you want multicast only on a 
  346. # subset of nodes as a means to save memory. If you want to run multicast on
  347. # your entire topology, use [new Simulator -multicast on].
  348. Node instproc enable-mcast args {
  349. # Do NOT add Mcast using Node enable-module, because the latter 
  350. # enables mcast for all nodes that may be created later
  351. $self register-module [new RtModule/Mcast]
  352. }
  353. #--------------------------------------------------------------
  354. #
  355. # Port classifier manipulation
  356. #
  357. Node instproc alloc-port { nullagent } {
  358. return [[$self set dmux_] alloc-port $nullagent]
  359. }
  360. Node instproc agent port {
  361. $self instvar agents_
  362. foreach a $agents_ {
  363. if { [$a set agent_port_] == $port } {
  364. return $a
  365. }
  366. }
  367. return ""
  368. }
  369. Node instproc demux {} {
  370. return [$self set dmux_]
  371. }
  372. # Install $demux as the default demuxer of the node, place the existing demux
  373. # at $port of the new demuxer. 
  374. #
  375. # XXX Here we do not have a similar difference like that between 
  376. # "insert-entry" and "install-entry", because even if a demux 
  377. # is replaced, the associated routing module should not be removed. 
  378. #
  379. # This is a rather arbitrary decision, but we do not have better clue
  380. # how demuxers will be used among routing modules.
  381. Node instproc install-demux { demux {port ""} } {
  382. $self instvar dmux_ address_
  383. if { $dmux_ != "" } {
  384. $self delete-route $dmux_
  385. if { $port != "" } {
  386. $demux install $port $dmux_
  387. }
  388. }
  389. set dmux_ $demux
  390. $self add-route $address_ $dmux_
  391. }
  392. # Whenever an agent is attached or detached, $module should be notified.
  393. Node instproc port-notify { module } {
  394. $self instvar ptnotif_
  395. lappend ptnotif_ $module
  396. }
  397. Node instproc unreg-port-notify { module } {
  398. $self instvar ptnotif_
  399. set pos [lsearch $ptnotif_ $module]
  400. if { $pos >= 0 } {
  401. set ptnotif_ [lreplace $ptnotif_ $pos $pos]
  402. }
  403. }
  404. #
  405. # Attach an agent to a node: pick a port and bind the agent to the port.
  406. #
  407. # To install module-specific demuxers, do that in your module's register{}
  408. # method. Since this method will be called during Node::init{}, when 
  409. # Node::attach{} is called dmux_ will already be present hence the following
  410. # default dmux_ construction will not be triggered.
  411. #
  412. Node instproc attach { agent { port "" } } {
  413. $self instvar agents_ address_ dmux_ 
  414. #
  415. # Assign port number (i.e., this agent receives
  416. # traffic addressed to this host and port)
  417. #
  418. lappend agents_ $agent
  419. #
  420. # Attach agents to this node (i.e., the classifier inside).
  421. # We call the entry method on ourself to find the front door
  422. # (e.g., for multicast the first object is not the unicast classifier)
  423. #
  424. # Also, stash the node in the agent and set the local addr of 
  425. # this agent.
  426. #
  427. $agent set node_ $self
  428. $agent set agent_addr_ [AddrParams addr2id $address_]
  429. #
  430. # If a port demuxer doesn't exist, create it.
  431. #
  432. if { $dmux_ == "" } {
  433. # Use the default mask_ and port_ values
  434. set dmux_ [new Classifier/Port]
  435. # point the node's routing entry to itself
  436. # at the port demuxer (if there is one)
  437. $self add-route $address_ $dmux_
  438. }
  439. if { $port == "" } {
  440. set port [$dmux_ alloc-port [[Simulator instance] nullagent]]
  441. }
  442. $agent set agent_port_ $port
  443. $self add-target $agent $port
  444. }
  445. # XXX For backward compatibility. When both satellite node and mobile node
  446. # are converted to modules, this should be merged into attach{}.
  447. Node instproc add-target { agent port } {
  448. $self instvar ptnotif_
  449. # Replaces the following line from old ns (2.1b7 and earlier)
  450. #   $self add-target $agent $port
  451. foreach m [$self set ptnotif_] {
  452. $m attach $agent $port
  453. }
  454. }
  455. # Detach an agent from a node.
  456. Node instproc detach { agent nullagent } {
  457. $self instvar agents_ dmux_
  458. #
  459. # remove agent from list
  460. #
  461. set k [lsearch -exact $agents_ $agent]
  462. if { $k >= 0 } {
  463. set agents_ [lreplace $agents_ $k $k]
  464. }
  465. #
  466. # sanity -- clear out any potential linkage
  467. #
  468. $agent set node_ ""
  469. $agent set agent_addr_ 0
  470. $agent target $nullagent
  471. # Install nullagent to sink transit packets   
  472. $dmux_ install [$agent set agent_port_] $nullagent
  473. foreach m [$self set ptnotif_] {
  474. $m detach $agent $nullagent
  475. }
  476. }
  477. # reset all agents attached to this node
  478. Node instproc reset {} {
  479. $self instvar agents_
  480. foreach a $agents_ {
  481. $a reset
  482. }
  483. foreach m [$self list-modules] {
  484. $m reset
  485. }
  486. }
  487. #
  488. # Some helpers
  489. #
  490. Node instproc neighbors {} {
  491. $self instvar neighbor_
  492. return [lsort $neighbor_]
  493. }
  494. Node instproc add-neighbor {p {pushback 0}} {
  495. $self instvar neighbor_
  496. lappend neighbor_ $p
  497. #added for keeping the neighbor list in the Node (for pushback) - ratul
  498. if { $pushback == 1 } {
  499. $self cmd add-neighbor $p
  500. }
  501. }
  502. Node instproc is-neighbor { node } {
  503. $self instvar neighbor_
  504. return [expr [lsearch $neighbor_ $node] != -1]
  505. }