ns-mpls-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-11 15:10:21 haoboy>
  4. #  This program is free software; you can redistribute it and/or
  5. #  modify it under the terms of the GNU General Public License,
  6. #  version 2, as published by the Free Software Foundation.
  7. #
  8. #  This program is distributed in the hope that it will be useful,
  9. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. #  GNU General Public License for more details.
  12. #
  13. #  You should have received a copy of the GNU General Public License along
  14. #  with this program; if not, write to the Free Software Foundation, Inc.,
  15. #  59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  16. #
  17. #  The copyright of this module includes the following
  18. #  linking-with-specific-other-licenses addition:
  19. #
  20. #  In addition, as a special exception, the copyright holders of
  21. #  this module give you permission to combine (via static or
  22. #  dynamic linking) this module with free software programs or
  23. #  libraries that are released under the GNU LGPL and with code
  24. #  included in the standard release of ns-2 under the Apache 2.0
  25. #  license or under otherwise-compatible licenses with advertising
  26. #  requirements (or modified versions of such code, with unchanged
  27. #  license).  You may copy and distribute such a system following the
  28. #  terms of the GNU GPL for this module and the licenses of the
  29. #  other code concerned, provided that you include the source code of
  30. #  that other code when and as the GNU GPL requires distribution of
  31. #  source code.
  32. #
  33. #  Note that people who make modified versions of this module
  34. #  are not obligated to grant this special exception for their
  35. #  modified versions; it is their choice whether to do so.  The GNU
  36. #  General Public License gives permission to release a modified
  37. #  version without this exception; this exception also makes it
  38. #  possible to release a modified version which carries forward this
  39. #  exception.
  40. #  Original source contributed by Gaeil Ahn. See below.
  41. #
  42. #  $Header: /cvsroot/nsnam/ns-2/tcl/mpls/ns-mpls-node.tcl,v 1.5 2005/09/16 03:05:45 tomh Exp $
  43. ###########################################################################
  44. # Copyright (c) 2000 by Gaeil Ahn                                   #
  45. # Everyone is permitted to copy and distribute this software.   #
  46. # Please send mail to fog1@ce.cnu.ac.kr when you modify or distribute     #
  47. # this sources.   #
  48. ###########################################################################
  49. #
  50. # XXX MPLS is NOT compatible with hierarchical routing, because:
  51. #
  52. # 1) MPLS classifier is explicitly coupled with unicast address classifier,
  53. #    which does not support hierarchical routing. The reason is MPLS needs 
  54. #    to check whether a route update is an update, a new entry, or a 
  55. #    "no change". This is not as straightforward and efficient when the 
  56. #    MPLS classifier is decoupled from the unicast address classifier, because
  57. #    through add-route{} interface, Node can only tell this module that a new
  58. #    route is added, but not whether this is an update, a new entry, or 
  59. #    a "no change". I don't have a clean solution yet. - haoboy
  60. #
  61. RtModule/MPLS instproc register { node } {
  62. $self instvar classifier_
  63. $self attach-node $node
  64. $node route-notify $self
  65. $node port-notify $self
  66.         set classifier_ [new Classifier/Addr/MPLS]
  67.         $classifier_ set-node $node $self
  68. $node install-entry $self $classifier_ 0
  69. $self attach-classifier $classifier_
  70. }
  71. #RtModule/MPLS instproc route-notify { module } { }
  72. # Done common routing module interfaces. Now is our own processing.
  73. RtModule/MPLS instproc enable-data-driven {} {
  74. [$self set classifier_] cmd enable-data-driven
  75. }
  76. RtModule/MPLS instproc enable-control-driven {} {
  77. [$self set classifier_] cmd enable-control-driven
  78. }
  79. RtModule/MPLS instproc make-ldp {} {
  80. set ldp [new Agent/LDP]
  81. $self cmd attach-ldp $ldp
  82. $ldp set-mpls-module $self
  83. [$self node] attach $ldp
  84. return $ldp
  85. }
  86. RtModule/MPLS instproc exist-fec {fec phb} {
  87.         return [[$self set classifier_] exist-fec $fec $phb]
  88. }
  89. RtModule/MPLS instproc get-incoming-iface {fec lspid} {
  90.         return [[$self set classifier_] GetInIface $fec $lspid]
  91. }
  92. RtModule/MPLS instproc get-incoming-label {fec lspid} {
  93.         return [[$self set classifier_] GetInLabel $fec $lspid]
  94. }
  95. RtModule/MPLS instproc get-outgoing-label {fec lspid} {
  96.         return [[$self set classifier_] GetOutLabel $fec $lspid]
  97. }
  98. RtModule/MPLS instproc get-outgoing-iface {fec lspid} {
  99.         return [[$self set classifier_] GetOutIface $fec $lspid]
  100. }
  101. RtModule/MPLS instproc get-fec-for-lspid {lspid} {
  102.         return [[$self set classifier_] get-fec-for-lspid $lspid]
  103. }
  104. RtModule/MPLS instproc in-label-install {fec lspid iface label} {
  105. set dontcare [Classifier/Addr/MPLS dont-care]
  106. $self label-install $fec $lspid $iface $label $dontcare $dontcare
  107. }
  108. RtModule/MPLS instproc out-label-install {fec lspid iface label} {
  109. set dontcare [Classifier/Addr/MPLS dont-care]
  110. $self label-install $fec $lspid $dontcare $dontcare $iface $label
  111. }
  112. RtModule/MPLS instproc in-label-clear {fec lspid} {
  113. set dontcare [Classifier/Addr/MPLS dont-care]
  114. $self label-clear $fec $lspid -1 -1 $dontcare $dontcare
  115. }
  116. RtModule/MPLS instproc out-label-clear {fec lspid} {
  117. set dontcare [Classifier/Addr/MPLS dont-care]
  118. $self label-clear $fec $lspid $dontcare $dontcare -1 -1
  119. }
  120. RtModule/MPLS instproc label-install {fec lspid iif ilbl oif olbl} {
  121.         [$self set classifier_] LSPsetup $fec $lspid $iif $ilbl $oif $olbl
  122. }
  123. RtModule/MPLS instproc label-clear {fec lspid iif ilbl oif olbl} {
  124.         [$self set classifier_] LSPrelease $fec $lspid $iif $ilbl $oif $olbl
  125. }
  126. RtModule/MPLS instproc flow-erlsp-install {fec phb lspid} {
  127.         [$self set classifier_] ErLspBinding $fec $phb $lspid
  128. }
  129. RtModule/MPLS instproc erlsp-stacking {erlspid tunnelid} {
  130.         [$self set classifier_] ErLspStacking -1 $erlspid -1 $tunnelid
  131. }
  132. RtModule/MPLS instproc flow-aggregation {fineFec finePhb coarseFec coarsePhb} {
  133.         [$self set classifier_] FlowAggregation $fineFec $finePhb $coarseFec 
  134. $coarsePhb
  135. }
  136. RtModule/MPLS instproc enable-reroute {option} {
  137.         $self instvar classifier_ 
  138.         $classifier_ set enable_reroute_ 1
  139.         if {$option == "drop"} {
  140. $classifier_ set reroute_option_ 0
  141.         } elseif {$option == "L3"} {
  142. $classifier_ set reroute_option_ 1
  143.         } elseif {$option == "new"} {
  144. $classifier_ set reroute_option_ 2
  145.         } else {
  146. $classifier_ set reroute_option_ 0
  147. }
  148. }
  149. RtModule/MPLS instproc reroute-binding {fec phb lspid} {
  150.         [$self set classifier_] aPathBinding $fec $phb -1 $lspid
  151. }
  152. RtModule/MPLS instproc lookup-nexthop {node fec} {
  153.         set ns [Simulator instance]
  154.         set routingtable [$ns get-routelogic]
  155.         set nexthop [$routingtable lookup $node $fec]
  156.         return $nexthop
  157. }
  158. RtModule/MPLS instproc get-nexthop {fec} {
  159. # find a next hop for fec
  160.         set nodeid [[$self node] id]
  161.         set nexthop [$self lookup-nexthop $nodeid $fec]
  162.         return $nexthop
  163. }
  164. RtModule/MPLS instproc get-link-status {hop} {
  165. if {$hop < 0} {
  166. return "down"
  167. }
  168. set nexthop [$self get-nexthop $hop]
  169. if {$nexthop == $hop} {
  170. set status "up"
  171. } else {
  172. set status "down"
  173. }
  174. return $status
  175. }
  176. RtModule/MPLS instproc is-egress-lsr { fec } {
  177.         # Determine whether I am a egress-lsr for fec. 
  178.         if { [[$self node] id] == $fec } {
  179. return  "1"
  180.         }
  181.         set nexthopid [$self get-nexthop $fec]
  182.         if { $nexthopid < 0 } {
  183. return "-1"
  184.         }
  185.         set nexthop [[Simulator instance] get-node-by-id $nexthopid]
  186. if { [$nexthop get-module "MPLS"] == "" } {
  187. return  "1"
  188.         } else {
  189. return  "-1"
  190.         }
  191. }
  192. # distribute labels based on routing protocol
  193. RtModule/MPLS instproc ldp-trigger-by-routing-table {} {
  194.         if { [[$self set classifier_] cmd control-driven?] != 1 } {
  195. return
  196.         }
  197.         set ns [Simulator instance]
  198. for {set i 0} {$i < [$ns get-number-of-nodes]} {incr i} {
  199. # select a node
  200. set host [$ns get-node-by-id $i]
  201. if { [$self is-egress-lsr [$host id]] == 1 } {
  202. # distribute label
  203. $self ldp-trigger-by-control [$host id] *
  204. }
  205.         }
  206. }
  207. RtModule/MPLS instproc ldp-trigger-by-control {fec pathvec} {
  208. lappend pathvec [[$self node] id]
  209. set inlabel [$self get-incoming-label $fec -1]
  210. set nexthop [$self get-nexthop $fec]
  211. set ldpagents [lsort [$self get-ldp-agents]]
  212. for {set i 0} {$i < [llength $ldpagents]} {incr i 1} {
  213. set ldpagent [lindex $ldpagents $i]
  214. if { [$ldpagent peer-ldpnode] == $nexthop } {
  215. continue
  216. }
  217. if { $inlabel == -1 } {
  218. if { [$self is-egress-lsr $fec] == 1 } {
  219. # This is egress LSR
  220. set inlabel 0
  221. } else {
  222. set inlabel [$self new-incoming-label]
  223. $self in-label-install $fec -1 -1 $inlabel
  224. }
  225. }
  226. $ldpagent new-msgid
  227. $ldpagent send-mapping-msg $fec $inlabel $pathvec -1
  228. }
  229. }
  230. RtModule/MPLS instproc ldp-trigger-by-data {reqmsgid src fec pathvec} {
  231. if { [$self is-egress-lsr $fec] == 1 } {
  232. # This is a egress node
  233. return
  234. }
  235. set outlabel [$self get-outgoing-label $fec -1]
  236. if { $outlabel > -1  } {
  237. # reroute check !! to establish altanative path
  238. set outiface [$self get-outgoing-iface $fec -1]
  239. if { [$self get-link-status $outiface] == "up" } {
  240. # LSP was already setup
  241. return
  242. }
  243. }
  244. lappend pathvec [[$self node] id]      
  245. set nexthop [$self get-nexthop $fec]
  246. set ldpagent [$self get-ldp-agent $nexthop]
  247. if { $ldpagent == "" } {
  248. return
  249. }
  250. if {$reqmsgid > -1} {
  251. # on-demand mode
  252. set working [$ldpagent msgtbl-get-msgid $fec -1 $src]
  253. if { $working < 0 } {
  254. # have to make new request-msg
  255. set newmsgid [$ldpagent new-msgid]
  256. $ldpagent msgtbl-install $newmsgid $fec -1 
  257. $src $reqmsgid
  258. $ldpagent send-request-msg $fec $pathvec
  259. } else {
  260. # $self is already tring to setup a LSP
  261. # So, need not to send a request-msg
  262. }
  263. } else {
  264. # not on-demand mode
  265. if {$fec == $nexthop} {
  266. # This is a penultimate hop
  267. set outlabel 0
  268. } else {
  269. set outlabel [$self new-outgoing-label]
  270. }
  271. $self out-label-install $fec -1 $nexthop $outlabel
  272. $ldpagent new-msgid
  273. $ldpagent send-mapping-msg $fec $outlabel $pathvec -1
  274. }
  275. }
  276. RtModule/MPLS instproc make-explicit-route {fec er lspid rc} {
  277. $self ldp-trigger-by-explicit-route -1 [[$self node] id] $fec "*" 
  278. $er $lspid $rc
  279. }
  280. RtModule/MPLS instproc ldp-trigger-by-explicit-route {reqmsgid src fec 
  281. pathvec er lspid rc} {
  282. $self instvar classifier_
  283. set outlabel [$self get-outgoing-label $fec $lspid]
  284. if { $outlabel > -1 } {
  285. # LSP was already setup
  286. return
  287. }
  288. if { [[$self node] id] != $src && [[$self node] id] == $fec } {
  289. # This is a egress node
  290. set ldpagent [$self get-ldp-agent $src]
  291. if { $ldpagent != "" } {
  292. $ldpagent new-msgid
  293. $ldpagent send-cr-mapping-msg $fec 0 $lspid $reqmsgid
  294. }
  295. return
  296. }
  297. lappend pathvec [[$self node] id]
  298. set er [split $er "_"]
  299. set erlen [llength $er]
  300. for {set i 0} {$i <= $erlen} {incr i 1} {
  301. if { $i != $erlen } {
  302. set erhop [lindex $er $i]
  303. } else {
  304. set erhop $fec
  305. }
  306. set stackERhop -1
  307. if { $erhop >= [Classifier/Addr/MPLS minimum-lspid] } {
  308. # This is the ER-Hop and LSPid (ER-LSP)
  309. set lspidFEC [$self get-fec-for-lspid $erhop]
  310. set inlabel  [$self get-incoming-label -1 $erhop]
  311. set outlabel [$self get-outgoing-label -1 $erhop]
  312. if { $lspidFEC == $fec } {
  313. # splice two LSPs
  314. if { $outlabel <= -1 } {
  315. continue
  316. }
  317. if { $inlabel < 0 } {
  318. set inlabel [$self new-incoming-label]
  319. $self in-label-install -1 $erhop 
  320. $src $inlabel
  321. }
  322. set ldpagent [$self get-ldp-agent $src]
  323. $ldpagent new-msgid
  324. $ldpagent send-cr-mapping-msg $fec $inlabel 
  325. $lspid $reqmsgid
  326. return
  327. }
  328. # $lspidFEC != $fec
  329. # do stack operation
  330. set existExplicitPeer [$self exist-ldp-agent $lspidFEC]
  331. if { $outlabel > -1 && $existExplicitPeer == "1" } {
  332. set stackERhop $erhop 
  333. set erhop $lspidFEC
  334. } elseif { $outlabel > -1 && $existExplicitPeer == "0" } {
  335. set nexthop [$self get-outgoing-iface -1 
  336. $erhop]
  337. set iiface  [$self get-incoming-iface -1 
  338. $erhop]
  339. set ldpagent [$self get-ldp-agent $nexthop]
  340. set working [$ldpagent msgtbl-get-msgid $fec 
  341. $lspid $src]
  342. if { $working < 0 } {
  343. # have to make new request-msg
  344. set newmsgid [$ldpagent new-msgid]
  345. $ldpagent msgtbl-install $newmsgid 
  346. $fec $lspid $src $reqmsgid
  347. # determine whether labelpass or 
  348. # labelstack
  349. if {($iiface == $src) && 
  350. ($inlabel > -1) } {
  351. $ldpagent msgtbl-set-labelpass $newmsgid
  352. } else {
  353. $ldpagent msgtbl-set-labelstack $newmsgid $erhop
  354. }
  355. $ldpagent send-cr-request-msg $fec 
  356. $pathvec $er $lspid $rc
  357. }
  358. return
  359. } else {
  360. continue
  361. }
  362. }
  363. if { [lsearch $pathvec $erhop] < 0 } {
  364. set nexthop [$self get-nexthop $erhop]
  365. if { [$self is-egress-lsr $nexthop] == 1 } {
  366. # not exist MPLS-node to process a required 
  367. # er-LSP
  368. set ldpagent [$self get-ldp-agent $src]
  369. if { $erhop == $fec } {
  370. # This is a final node
  371. $ldpagent new-msgid
  372. $ldpagent send-cr-mapping-msg $fec 0 
  373. $lspid $reqmsgid
  374. } else {
  375. # be a wrong er list
  376. $ldpagent new-msgid
  377. $ldpagent send-notification-msg 
  378. "NoRoute" $lspid
  379. }
  380. } else {
  381. set ldpagent [$self get-ldp-agent $nexthop]
  382. set working [$ldpagent msgtbl-get-msgid $fec 
  383. $lspid $src]
  384. if { $working < 0 } {
  385. # have to make new request-msg
  386. set newmsgid [$ldpagent new-msgid]
  387. set id [$ldpagent msgtbl-install 
  388. $newmsgid $fec 
  389. $lspid $src $reqmsgid]
  390. ## for label stack
  391. if { $stackERhop > -1 } {
  392. $ldpagent msgtbl-set-labelstack $newmsgid $stackERhop
  393. }
  394. $ldpagent send-cr-request-msg $fec $pathvec $er $lspid $rc
  395. }
  396. return
  397. }
  398. }
  399. set ldpagent [$self get-ldp-agent $src]
  400. if { $ldpagent != "" } {
  401. $ldpagent new-msgid
  402. $ldpagent send-notification-msg "NoRoute" $lspid
  403. }
  404. }
  405. RtModule/MPLS instproc ldp-trigger-by-withdraw {fec lspid} {
  406. set inlabel  [$self get-incoming-label $fec $lspid]
  407. set iniface  [$self get-incoming-iface $fec $lspid]
  408. $self in-label-clear $fec $lspid
  409. if {$iniface > -1} {
  410. set ldpagent [$self get-ldp-agent $iniface]
  411. if { $ldpagent != "" } {
  412. $ldpagent new-msgid
  413. $ldpagent send-withdraw-msg $fec $lspid
  414. }
  415. } else {
  416. # several upstream nodes may share a label.
  417. # so inform all upstream nodes to withdraw the label
  418. set nexthop [$self get-nexthop $fec]
  419. set ldpagents [lsort [$self get-ldp-agents]]
  420. for {set i 0} {$i < [llength $ldpagents]} {incr i 1} {
  421. set ldpagent [lindex $ldpagents $i]
  422. if { [$ldpagent peer-ldpnode] == $nexthop } {
  423. continue
  424. }
  425. $ldpagent new-msgid
  426. $ldpagent send-withdraw-msg $fec $lspid
  427. }
  428. }   
  429. }
  430. RtModule/MPLS instproc ldp-trigger-by-release {fec lspid} {
  431. set outlabel  [$self get-outgoing-label $fec $lspid]
  432. if {$outlabel < 0} {
  433. return
  434. }
  435. set nexthop [$self get-outgoing-iface $fec $lspid]
  436. $self out-label-clear $fec $lspid 
  437. set ldpagent [$self get-ldp-agent $nexthop]
  438. if { $ldpagent != "" } {
  439. $ldpagent new-msgid
  440. $ldpagent send-release-msg $fec $lspid
  441. }   
  442. }
  443. # Debugging
  444. RtModule/MPLS instproc trace-mpls {} {
  445.         [$self set classifier_] set trace_mpls_ 1
  446. }
  447. RtModule/MPLS instproc pft-dump {} {
  448.         # dump the records within Partial Forwarding Table(PFT)
  449.         set nodeid [[$self node] id]
  450.         [$self set classifier_] PFTdump $nodeid
  451. }
  452. RtModule/MPLS instproc erb-dump {} {
  453.         # dump the records within Explicit Route information Base(ERB)
  454.         set nodeid [[$self node] id]
  455.         [$self set classifier_] ERBdump $nodeid
  456. }
  457. RtModule/MPLS instproc lib-dump {} {
  458.         # dump the records within Label Information Base(LIB)
  459.         set nodeid [[$self node] id]
  460.         [$self set classifier_] LIBdump $nodeid
  461. }