J-Sim INET Tutorial -> DVMRP Examples
September 10, 2001
This example examines the basic operations of DVMRP on a four-router network. Each router runs only the DVMRP protocol (drcl.inet.protocol.dvmrp.DVMRP).
Figure 1: The network topology for this example.

1 cd [mkdir drcl.comp.Component /test]
2 set link_ [java::new drcl.inet.Link]
3 $link_ setPropDelay 1.0
4 set adjMatrix_ [java::new {int[][]} 4 {{1 2 3} {3 0} {0 3} {0 1 2}}]
5 set ids_ [java::new {long[]} 4 {0 8 16 24}]
6 java::call drcl.inet.InetUtil createTopology [! .] $adjMatrix_ $ids_ $link_
7 set nb [mkdir drcl.inet.NodeBuilder .nodeBuilder]
8 mkdir drcl.inet.protocol.dvmrp.DVMRP $nb/dvmrp
9 $nb build [! n*]
The only new thing here is, as highlighted, using the array of node ID's in drcl.inet.InetUtil.createTopology(...). The method will then assign the ID's to the nodes after they are created.
In the INET framework, if a router is a gateway router or a border router of a network, then it should have appropriate settings for the interfaces that are located at the network boundary. Imagine that if the other routers look at, for example, the router n16 from its interfaces, they will only see the network address (16, -8), or (100002, 110002), or 10xxx2.
To configure the interface setting, we call drcl.inet.Node.setInterfaceInfo(interfaceIndex_, interfaceInfo_), for each interface of each router, as follows:
10 for {set i 0} {$i < 3} {incr i} {
11 ! n0 setInterfaceInfo $i [java::new drcl.inet.data.InterfaceInfo 0 -8]
12 ! n24 setInterfaceInfo $i [java::new drcl.inet.data.InterfaceInfo 24 -8]
13 }
14 for {set i 0} {$i < 2} {incr i} {
15 ! n8 setInterfaceInfo $i [java::new drcl.inet.data.InterfaceInfo 8 -8]
16 ! n16 setInterfaceInfo $i [java::new drcl.inet.data.InterfaceInfo 16 -8]
17 }
18 set sim [attach_simulator .]
19 source DVMRP_common.tcl
20 setflag debug true -at {debug_route debug_timeout debug_mcast_query debug_prune debug_graft} n*/dvmrp
21 watch -c -label FC -add n*/csl/.rt_mcast@
22 $sim stop
23 run n*
In line19, the DVMRP_common.tcl is loaded in so that we can use commands to create multicast group join/leave events and inject multicast data packets. In line 20, we turn on several debug levels at all DVMRP instances. In line 21, we add a watcher, with label "FC", to listen to all the multicast route (or forwarding cache entry) events. Before we boot up all the routers in line 23 which will trigger the simulator to start, we make the simulator stop (NOTE: After created, a simulator can start any time when a component sends data. To have the simulator not triggered by such events, we must make it stop first. Only the resume methods can resume a stopped simulator.) and then we will resume and control the simulation flow to examine all the DVMRP operations in the following section.
We examine the operations of route exchange, prune, prune timeout, graft and topology change with different scenarios. The scenarios are run and explained in a step-by-step fashion in the following subsections. The commands that are inputed by user at the terminal are highlighted in boldface. The resulting debug messages may be highlighted in different colors for better readability.
To observe the unicast routes established in DVMRP by exchanging the route reports, we let the simulation run for some time so that the routes are stabilized and then we examine the routing table in each router by the "cat" command.
First, we let the simulation run until the time instance 50.0
1 TCL0> $sim resumeTo 50.0
2 DEBUG| 1.036| /test/n0/dvmrp/| NEIGHBOR UP EVENT: <24,-8>
3 DEBUG| 1.036| /test/n8/dvmrp/| NEIGHBOR UP EVENT: <24,-8>
4 DEBUG| 1.036| /test/n16/dvmrp/| NEIGHBOR UP EVENT: <24,-8>
5 DEBUG| 1.036| /test/n24/dvmrp/| NEIGHBOR UP EVENT: <8,-8>
6 DEBUG| 1.036| /test/n0/dvmrp/| NEIGHBOR UP EVENT: <8,-8>
7 DEBUG| 1.036| /test/n0/dvmrp/| NEIGHBOR UP EVENT: <16,-8>
8 DEBUG| 1.036| /test/n24/dvmrp/| NEIGHBOR UP EVENT: <16,-8>
9 DEBUG| 1.036| /test/n8/dvmrp/| NEIGHBOR UP EVENT: <0,-8>
10 DEBUG| 1.036| /test/n16/dvmrp/| NEIGHBOR UP EVENT: <0,-8>
11 DEBUG| 1.036| /test/n24/dvmrp/| NEIGHBOR UP EVENT: <0,-8>
12 DEBUG| 3.128| /test/n0/dvmrp/| Initial route from neighbor: 24-(0,24,0)(0,-8,0) 24(2) metric:1(changed)--dependents:()
13 DEBUG| 3.128| /test/n8/dvmrp/| Initial route from neighbor: 24-(0,24,0)(0,-8,0) 24(0) metric:1(changed)--dependents:()
14 DEBUG| 3.128| /test/n16/dvmrp/| Initial route from neighbor: 24-(0,24,0)(0,-8,0) 24(1) metric:1(changed)--dependents:()
15 DEBUG| 3.128| /test/n24/dvmrp/| Initial route from neighbor: 8-(0,8,0)(0,-8,0) 8(1) metric:1(changed)--dependents:()
16 DEBUG| 3.128| /test/n0/dvmrp/| Initial route from neighbor: 8-(0,8,0)(0,-8,0) 8(0) metric:1(changed)--dependents:()
17 DEBUG| 3.128| /test/n0/dvmrp/| Initial route from neighbor: 16-(0,16,0)(0,-8,0) 16(1) metric:1(changed)--dependents:()
18 DEBUG| 3.128| /test/n24/dvmrp/| Initial route from neighbor: 16-(0,16,0)(0,-8,0) 16(2) metric:1(changed)--dependents:()
19 DEBUG| 3.128| /test/n8/dvmrp/| Initial route from neighbor: 0-(0,0,0)(0,-8,0) 0(1) metric:1(changed)--dependents:()
20 DEBUG| 3.128| /test/n16/dvmrp/| Initial route from neighbor: 0-(0,0,0)(0,-8,0) 0(0) metric:1(changed)--dependents:()
21 DEBUG| 3.128| /test/n24/dvmrp/| Initial route from neighbor: 0-(0,0,0)(0,-8,0) 0(0) metric:1(changed)--dependents:()
22 DEBUG| 8.128| /test/n0/dvmrp/| TRIGGERED UPDATE: # of changed entries = 3
23 DEBUG| 8.128| /test/n8/dvmrp/| TRIGGERED UPDATE: # of changed entries = 2
24 DEBUG| 8.128| /test/n16/dvmrp/| TRIGGERED UPDATE: # of changed entries = 2
25 DEBUG| 8.128| /test/n24/dvmrp/| TRIGGERED UPDATE: # of changed entries = 3
26 DEBUG| 9.244| /test/n8/dvmrp/| Initial route from neighbor: 0-(0,16,0)(0,-8,0) 0(1) metric:2(changed)--dependents:()
27 DEBUG| 9.244| /test/n16/dvmrp/| Initial route from neighbor: 0-(0,8,0)(0,-8,0) 0(0) metric:2(changed)--dependents:()
28 DEBUG| 14.244| /test/n8/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
29 DEBUG| 14.244| /test/n16/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
Before we examine the routing table, let us confirm the route exchange operations that occured during the time interval: (Review Topology)
At this point, the routes are stabilized. No more triggered updates are sent.
Now, we examine the routing tables in the routers:
30 tcl0> cat n*/dvmrp (Review Topology)
31 ----- /test/n0/dvmrp/ -----:
32 ifset: all physical ifs
33 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
34 (0,0,0)(0,-8,0) ??-() metric:0--dependents:(8,16,24){0,1,2} timeout:NaN
35 (0,24,0)(0,-8,0) 24-{2} metric:1--dependents:() timeout:NaN
36 (0,8,0)(0,-8,0) 8-{0} metric:1--dependents:(16){1} timeout:NaN
37 (0,16,0)(0,-8,0) 16-{1} metric:1--dependents:(8){0} timeout:NaN
38 ----- /test/n16/dvmrp/ -----:
39 ifset: all physical ifs
40 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
41 (0,16,0)(0,-8,0) ??-() metric:0--dependents:(0,24){0,1} timeout:NaN
42 (0,24,0)(0,-8,0) 24-{1} metric:1--dependents:() timeout:NaN
43 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:() timeout:NaN
44 (0,8,0)(0,-8,0) 0-{0} metric:2--dependents:() timeout:NaN
45 ----- /test/n24/dvmrp/ -----:
46 ifset: all physical ifs
47 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
48 (0,24,0)(0,-8,0) ??-() metric:0--dependents:(0,8,16){0,1,2} timeout:NaN
49 (0,8,0)(0,-8,0) 8-{1} metric:1--dependents:() timeout:NaN
50 (0,16,0)(0,-8,0) 16-{2} metric:1--dependents:() timeout:NaN
51 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:() timeout:NaN
52 ----- /test/n8/dvmrp/ -----:
53 ifset: all physical ifs
54 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
55 (0,8,0)(0,-8,0) ??-() metric:0--dependents:(24,0){0,1} timeout:NaN
56 (0,24,0)(0,-8,0) 24-{0} metric:1--dependents:() timeout:NaN
57 (0,0,0)(0,-8,0) 0-{1} metric:1--dependents:() timeout:NaN
58 (0,16,0)(0,-8,0) 0-{1} metric:2--dependents:() timeout:NaN
The first line in each router's display shows the "ifset" (interface set) configuration. One can configure the DVMRP to operate on a specific set of interfaces. By default, it operates on all physical (opposed to "virtual" or "tunnel") interfaces. (In a later example, we will demonstrate how to configure DVMRP to run on a set of virtual interfaces.) Followed by the "ifset" configuration is the unicast routes that the DVMRP instances learn from route exchanges. As indicated in the first line followed by "ifset", a route entry is printed in one line in the format of:
Fields 1, 2 and 4 are common fields in a route entry (implemented by drcl.inet.data.RTEntry) while the 3rd one is the extended field and is defined by the protocol that creates it. For example, the unicast route entries maintained by a distance vector protocol would have only the metric field defined in the extended part. In DVMRP, as we will see in Section 2.3, the extended part of a forwarding cache entry (used for forwarding multicast data packets) stores the prune states and other related information.
Note that each router contains a route entry to itself with metric of zero. We call those entries the loopback routes.
In this scenario, we intentionally bring down the link between n0 and n8 and then observe how the DVMRP's adapt to it.
59 tcl0> $sim resumeTo 100.0 60 tcl0> 61 DEBUG| 61.036| /test/n0/dvmrp/| REGULAR UPDATE 62 DEBUG| 61.036| /test/n8/dvmrp/| REGULAR UPDATE 63 DEBUG| 61.036| /test/n16/dvmrp/| REGULAR UPDATE 64 DEBUG| 61.036| /test/n24/dvmrp/| REGULAR UPDATE
First, we let the simulation run to the time instance 100.0. Observed that at time 61.036, the regular update occurs at each router. The interval for regular updates is 60 seconds by default and it is initiated upon the receipt of a NEIGHBOR-UP event (at time 1.036, line 2-11, in this example).
We then emulate the link failure by disabling the link between n0 and n8: (Review Topology)
65 tcl0> setflag component false n0/0@/-/..
One can disable a component by turning off its component flag with the "setflag" command. The path expression "n0/0@/-/.." references to the component that n0 is connected to via its 0@ port. Specifically, "n0/0@/-" references to the port that "n0/0@" is connected to, and "<a port path>/.." references to the host component of the port. We can certainly find out what the link component is between n0 and n8 (/test/.link0 in this example), and disable it, but since we know n0 is connected to n8 via the 0@ port from the adjacency matrix we used to construct the topology, it would be easier this way.
66 tcl0> $sim resumeTo 160.0
67 tcl0>
68 DEBUG| 121.036| /test/n0/dvmrp/| REGULAR UPDATE
69 DEBUG| 121.036| /test/n8/dvmrp/| REGULAR UPDATE
70 DEBUG| 121.036| /test/n16/dvmrp/| REGULAR UPDATE
71 DEBUG| 121.036| /test/n24/dvmrp/| REGULAR UPDATE
72 DEBUG| 140.0| /test/n8/dvmrp/| NEIGHBOR DOWN EVENT: <0,-8>
73 DEBUG| 140.0| /test/n8/dvmrp/| hold-down (0,0,0)(0,-8,0):0-{1}-metric:INF(changed)--dependents:()-260.0 due to NEIGHBOR TIMEOUT: 0
74 DEBUG| 140.0| /test/n8/dvmrp/| hold-down (0,16,0)(0,-8,0):0-{1}-metric:INF(changed)--dependents:()-260.0 due to NEIGHBOR TIMEOUT: 0
75 DEBUG| 140.0| /test/n0/dvmrp/| NEIGHBOR DOWN EVENT: <8,-8>
76 DEBUG| 140.0| /test/n0/dvmrp/| hold-down (0,8,0)(0,-8,0):8-{0}-metric:INF(changed)--dependents:()-260.0 due to NEIGHBOR TIMEOUT: 8
77 DEBUG| 145.0| /test/n8/dvmrp/| TRIGGERED UPDATE: # of changed entries = 2
78 DEBUG| 145.0| /test/n0/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
79 DEBUG| 146.076| /test/n16/dvmrp/| hold-down (0,8,0)(0,-8,0):0-{0}-metric:2--dependents:()-NaN due to route invalidation from NEXT-HOP neighbor
--->metric:INF(changed)--dependents:()
80 DEBUG| 151.076| /test/n16/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
* The events occured at n0 are colored in blue to distinguish what else at n8.
At time 140.0, the DVMRP instances in n0 and n8 receive the NEIGHBOR-DOWN event from the core service layer. (Note: The "hello" service in the core service layer runs every 10 seconds by default. If for three times that it does not receive the hello message from a neighbor, then it exports the NEIGHBOR-DOWN event to the interested upper layer protocols. That is the reason why the time 140.0.) DVMRP's responded the event by "holding down" the affected routes and then initiating triggered updates to their neighbors. As shown in the debug messages, two routes are held down by these two routers, and n16 is also affected because the route from n16 to n8 is via n0. Let us examine the routing tables at this time instance:
81 tcl0> cat n*/dvmrp (Review Topology)
82 ----- /test/n0/dvmrp/ -----:
83 ifset: all physical ifs
84 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
85 (0,0,0)(0,-8,0) ??-() metric:0--dependents:(16,24){1,2} timeout:NaN
86 (0,24,0)(0,-8,0) 24-{2} metric:1--dependents:() timeout:NaN
87 (0,8,0)(0,-8,0) 8-{0} metric:INF--dependents:() timeout:260.0
88 (0,16,0)(0,-8,0) 16-{1} metric:1--dependents:() timeout:NaN
89 ----- /test/n16/dvmrp/ -----:
90 ifset: all physical ifs
91 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
92 (0,16,0)(0,-8,0) ??-() metric:0--dependents:(0,24){0,1} timeout:NaN
93 (0,24,0)(0,-8,0) 24-{1} metric:1--dependents:() timeout:NaN
94 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:() timeout:NaN
95 (0,8,0)(0,-8,0) 0-{0} metric:INF--dependents:() timeout:266.076
96 ----- /test/n24/dvmrp/ -----:
97 ifset: all physical ifs
98 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
99 (0,24,0)(0,-8,0) ??-() metric:0--dependents:(0,8,16){0,1,2} timeout:NaN
100 (0,8,0)(0,-8,0) 8-{1} metric:1--dependents:(16){2} timeout:NaN
101 (0,16,0)(0,-8,0) 16-{2} metric:1--dependents:(8){1} timeout:NaN
102 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:() timeout:NaN
103 ----- /test/n8/dvmrp/ -----:
104 ifset: all physical ifs
105 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
106 (0,8,0)(0,-8,0) ??-() metric:0--dependents:(24){0} timeout:NaN
107 (0,24,0)(0,-8,0) 24-{0} metric:1--dependents:() timeout:NaN
108 (0,0,0)(0,-8,0) 0-{1} metric:INF--dependents:() timeout:260.0
109 (0,16,0)(0,-8,0) 0-{1} metric:INF--dependents:() timeout:260.0
* The fields highlighted in boldface are transitionally set due to the NEIGHBOR-DOWN events. Compare it with the previous routing tables.
Two points are in place:
We would expect that all the affected routers will pick up new routes from the next regular updates. Let us continue the simulation and check:
110 tcl0> $sim resumeTo 220.0 (Review Topology)
111 DEBUG| 181.036| /test/n0/dvmrp/| REGULAR UPDATE
112 DEBUG| 181.036| /test/n8/dvmrp/| REGULAR UPDATE
113 DEBUG| 181.036| /test/n16/dvmrp/| REGULAR UPDATE
114 DEBUG| 181.036| /test/n24/dvmrp/| REGULAR UPDATE
115 DEBUG| 182.15200000000002| /test/n0/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,8,0)(0,-8,0):8-{0}-metric:INF--dependents:(16){1}-260.0
--->24-metric:2(changed)--dependents:(16){1}
116 DEBUG| 182.15200000000002| /test/n8/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,16,0)(0,-8,0):0-{1}-metric:INF--dependents:()-260.0
--->24-metric:2(changed)--dependents:()
117 DEBUG| 182.15200000000002| /test/n8/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,0,0)(0,-8,0):0-{1}-metric:INF--dependents:()-260.0
--->24-metric:2(changed)--dependents:()
118 DEBUG| 182.15200000000002| /test/n16/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,8,0)(0,-8,0):0-{0}-metric:INF--dependents:()-266.076
--->24-metric:2(changed)--dependents:()
119 DEBUG| 187.15200000000002| /test/n0/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
120 DEBUG| 187.15200000000002| /test/n8/dvmrp/| TRIGGERED UPDATE: # of changed entries = 2
121 DEBUG| 187.15200000000002| /test/n16/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
* The events occured at n0 are colored in blue to distinguish what else at n8 and n16.
Indeed, at time 182.152, all the affected routers learn new routes from n24's updates. The process ends with the triggered updates from all the affected nodes at time 187.152. Let us check the routing tables again:
122 tcl0> cat n*/dvmrp (Review Topology)
123 ----- /test/n0/dvmrp/ -----:
124 ifset: all physical ifs
125 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
126 (0,0,0)(0,-8,0) ??-() metric:0--dependents:(16,24){1,2} timeout:NaN
127 (0,24,0)(0,-8,0) 24-{2} metric:1--dependents:() timeout:NaN
128 (0,8,0)(0,-8,0) 24-{2} metric:2--dependents:() timeout:NaN
129 (0,16,0)(0,-8,0) 16-{1} metric:1--dependents:() timeout:NaN
130 ----- /test/n16/dvmrp/ -----:
131 ifset: all physical ifs
132 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
133 (0,16,0)(0,-8,0) ??-() metric:0--dependents:(0,24){0,1} timeout:NaN
134 (0,24,0)(0,-8,0) 24-{1} metric:1--dependents:() timeout:NaN
135 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:() timeout:NaN
136 (0,8,0)(0,-8,0) 24-{1} metric:2--dependents:() timeout:NaN
137 ----- /test/n24/dvmrp/ -----:
138 ifset: all physical ifs
139 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
140 (0,24,0)(0,-8,0) ??-() metric:0--dependents:(0,8,16){0,1,2} timeout:NaN
141 (0,8,0)(0,-8,0) 8-{1} metric:1--dependents:(0,16){0,2} timeout:NaN
142 (0,16,0)(0,-8,0) 16-{2} metric:1--dependents:(8){1} timeout:NaN
143 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:(8){1} timeout:NaN
144 ----- /test/n8/dvmrp/ -----:
145 ifset: all physical ifs
146 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
147 (0,8,0)(0,-8,0) ??-() metric:0--dependents:(24){0} timeout:NaN
148 (0,24,0)(0,-8,0) 24-{0} metric:1--dependents:() timeout:NaN
149 (0,0,0)(0,-8,0) 24-{0} metric:2--dependents:() timeout:NaN
150 (0,16,0)(0,-8,0) 24-{0} metric:2--dependents:() timeout:NaN
* The fields highlighted in boldface are the final results due to the link failure. Compare it with the previous stabilized routing tables.
Notice how the new routes are learned and the list of dependents are adapted to the new topology.
Now for the rest of the scenarios, let us bring back the link:
tcl0> $sim resumeTo 250
DEBUG| 241.036| /test/n0/dvmrp/| REGULAR UPDATE
DEBUG| 241.036| /test/n8/dvmrp/| REGULAR UPDATE
DEBUG| 241.036| /test/n16/dvmrp/| REGULAR UPDATE
DEBUG| 241.036| /test/n24/dvmrp/| REGULAR UPDATE
151 tcl0> setflag component true n0/0@/-/..
152 tcl0> $sim resumeTo 350.0 (Review Topology)
153 DEBUG| 251.036| /test/n0/dvmrp/| NEIGHBOR UP EVENT: <8,-8>
154 DEBUG| 251.036| /test/n8/dvmrp/| NEIGHBOR UP EVENT: <0,-8>
155 DEBUG| 253.18800000000002| /test/n0/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,8,0)(0,-8,0):24-{2}-metric:2--dependents:()-NaN
--->8-metric:1(changed)--dependents:()
156 DEBUG| 253.18800000000002| /test/n8/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,0,0)(0,-8,0):24-{0}-metric:2--dependents:()-NaN
--->0-metric:1(changed)--dependents:()
157 DEBUG| 258.188| /test/n0/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
158 DEBUG| 258.188| /test/n8/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
159 DEBUG| 301.036| /test/n16/dvmrp/| REGULAR UPDATE
160 DEBUG| 301.036| /test/n24/dvmrp/| REGULAR UPDATE
161 DEBUG| 311.036| /test/n0/dvmrp/| REGULAR UPDATE
162 DEBUG| 311.036| /test/n8/dvmrp/| REGULAR UPDATE
* The events occured at n0 are colored in blue to distinguish what else at n8.
Examine the routing tables:
163 tcl0> cat n*/dvmrp (Review Topology)
164 ----- /test/n0/dvmrp/ -----:
165 ifset: all physical ifs
166 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
167 (0,0,0)(0,-8,0) ??-() metric:0--dependents:(8,16,24){0,1,2} timeout:NaN
168 (0,24,0)(0,-8,0) 24-{2} metric:1--dependents:() timeout:NaN
169 (0,8,0)(0,-8,0) 8-{0} metric:1--dependents:() timeout:NaN
170 (0,16,0)(0,-8,0) 16-{1} metric:1--dependents:() timeout:NaN
171 ----- /test/n16/dvmrp/ -----:
172 ifset: all physical ifs
173 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
174 (0,16,0)(0,-8,0) ??-() metric:0--dependents:(0,24){0,1} timeout:NaN
175 (0,24,0)(0,-8,0) 24-{1} metric:1--dependents:() timeout:NaN
176 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:() timeout:NaN
177 (0,8,0)(0,-8,0) 24-{1} metric:2--dependents:() timeout:NaN
178 ----- /test/n24/dvmrp/ -----:
179 ifset: all physical ifs
180 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
181 (0,24,0)(0,-8,0) ??-() metric:0--dependents:(0,8,16){0,1,2} timeout:NaN
182 (0,8,0)(0,-8,0) 8-{1} metric:1--dependents:(16){2} timeout:NaN
183 (0,16,0)(0,-8,0) 16-{2} metric:1--dependents:(8){1} timeout:NaN
184 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:() timeout:NaN
185 ----- /test/n8/dvmrp/ -----:
186 ifset: all physical ifs
187 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
188 (0,8,0)(0,-8,0) ??-() metric:0--dependents:(24,0){0,1} timeout:NaN
189 (0,24,0)(0,-8,0) 24-{0} metric:1--dependents:() timeout:NaN
190 (0,0,0)(0,-8,0) 0-{1} metric:1--dependents:() timeout:NaN
191 (0,16,0)(0,-8,0) 24-{0} metric:2--dependents:() timeout:NaN
The resulting stabilized routes are exactly the same as what we got in the beginning.
In this scenario, we will inject a multicast data packet at n16. Since there is no receiver, all branches of the multicast tree will be pruned. We will then observe the tree growing back when the prune states expire.
192 tcl0> $sim resumeTo 400.0 193 DEBUG| 361.036| /test/n16/dvmrp/| REGULAR UPDATE 194 DEBUG| 361.036| /test/n24/dvmrp/| REGULAR UPDATE 195 DEBUG| 371.036| /test/n0/dvmrp/| REGULAR UPDATE 196 DEBUG| 371.036| /test/n8/dvmrp/| REGULAR UPDATE
When the simulation suspends, continue with the following commands:
197 tcl0> mkdir n*/csl/100@up
java0x15d
198 tcl0> ! n0/dvmrp setPruneLifetime 20
199 tcl0> setflag garbagedisplay true recursively n*/csl
200 tcl0> send_mcast_pkt -message "To Group -111" -from n16/csl/100@up -to -111 -size 1024
Nothing happens because we have not resumed the simulation:
201 tcl0> $sim resumeTo 420.0 (Review Topology)
202 DEBUG| 400.0| /test/n16/dvmrp/| MCAST QUERY for (16,-111,-1)(-1,-1,-1)
203 DEBUG| 400.0| /test/n16/dvmrp/| MCAST QUERY: matched rt entries: ((0,16,0)(0,-8,0):??-null-metric:0--dependents:(0,24){0,1}-NaN)
204 DEBUG| 400.0| /test/n16/dvmrp/| MCAST QUERY: add fc entry: src=16, srcmask=-8, upstream=9223372036854775791(if=-1), dependentIfs={0,1}, outgoingIfs={0,1}
205 FC| EVENT--400.0--test/n16/csl/rt/.rt_mcast@event--RT Entry Added--(16,-111,0)(-8,-1,0):??-{0,1}-upstream:<null>--(+ + .)-NaN--
206 DEBUG| 402.044| /test/n0/dvmrp/| MCAST QUERY for (16,-111,1)(-1,-1,-1)
207 DEBUG| 402.044| /test/n0/dvmrp/| MCAST QUERY: matched rt entries: ((0,16,0)(0,-8,0):16-{1}-metric:1--dependents:()-NaN)
208 DEBUG| 402.044| /test/n0/dvmrp/| SEND PRUNE to 16 at if 1: <DVMRP_FC>sz24--cmd:prune--versioin:3--source:16--group:-111--srcmask:-8--prune_lifetime:20
209 DEBUG| 402.044| /test/n0/dvmrp/| MCAST QUERY: add fc entry: src=16, srcmask=-8, upstream=16(if=1), dependentIfs={}, outgoingIfs={}
210 FC| EVENT--402.044--test/n0/csl/rt/.rt_mcast@event--RT Entry Added--(16,-111,1)(-8,-1,-1):??-{}-upstream:16--(. . .)--sentPruneUpstream-NaN--
211 GARBAGE| 402.044| /test/n0/csl/pd/| sz1044(INET)20--src:#10--dest:#FFFFFFFFFFFFFF91--prot:100--TTL:255--#hops:2--tos:#0___<sz1024:To Group -111>___| no route for the pkt
212 DEBUG| 402.044| /test/n24/dvmrp/| MCAST QUERY for (16,-111,2)(-1,-1,-1)
213 DEBUG| 402.044| /test/n24/dvmrp/| MCAST QUERY: matched rt entries: ((0,16,0)(0,-8,0):16-{2}-metric:1--dependents:(8){1}-NaN)
214 DEBUG| 402.044| /test/n24/dvmrp/| MCAST QUERY: add fc entry: src=16, srcmask=-8, upstream=16(if=2), dependentIfs={1}, outgoingIfs={1}
215 FC| EVENT--402.044--test/n24/csl/rt/.rt_mcast@event--RT Entry Added--(16,-111,2)(-8,-1,-1):??-{1}-upstream:16--(. + .)-NaN--
216 DEBUG| 403.08799999999997| /test/n16/dvmrp/| PRUNE from neighbor 0 at if 0
217 FC| EVENT--403.08799999999997--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{0,1}-upstream:<null>--(+ + .)-NaN,(16,-111,0)(-8,-1,0):??-{1}-upstream:<null>--(423.08799999999997 + .)-NaN)--(prune)
218 DEBUG| 404.08799999999997| /test/n8/dvmrp/| MCAST QUERY for (16,-111,0)(-1,-1,-1)
219 DEBUG| 404.08799999999997| /test/n8/dvmrp/| MCAST QUERY: matched rt entries: ((0,16,0)(0,-8,0):24-{0}-metric:2--dependents:()-NaN)
220 DEBUG| 404.08799999999997| /test/n8/dvmrp/| SEND PRUNE to 24 at if 0: <DVMRP_FC>sz24--cmd:prune--versioin:3--source:16--group:-111--srcmask:-8--prune_lifetime:20
221 DEBUG| 404.08799999999997| /test/n8/dvmrp/| MCAST QUERY: add fc entry: src=16, srcmask=-8, upstream=24(if=0), dependentIfs={}, outgoingIfs={}
222 FC| EVENT--404.08799999999997--test/n8/csl/rt/.rt_mcast@event--RT Entry Added--(16,-111,0)(-8,-1,-1):??-{}-upstream:24--(. . .)--sentPruneUpstream-NaN--
223 GARBAGE| 404.08799999999997| /test/n8/csl/pd/| sz1044(INET)20--src:#10--dest:#FFFFFFFFFFFFFF91--prot:100--TTL:255--#hops:3--tos:#0___<sz1024:To Group -111>___| no route for the pkt
224 DEBUG| 405.13199999999995| /test/n24/dvmrp/| PRUNE from neighbor 8 at if 1
225 FC| EVENT--405.13199999999995--test/n24/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,2)(-8,-1,-1):??-{1}-upstream:16--(. + .)-NaN,(16,-111,2)(-8,-1,-1):??-{}-upstream:16--(. 425.13199999999995 .)-NaN)--(prune)
226 DEBUG| 405.13199999999995| /test/n24/dvmrp/| SEND PRUNE to 16 at if 2: <DVMRP_FC>sz24--cmd:prune--versioin:3--source:16--group:-111--srcmask:-8--prune_lifetime:20
227 DEBUG| 406.17599999999993| /test/n16/dvmrp/| PRUNE from neighbor 24 at if 1
228 FC| EVENT--406.17599999999993--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{1}-upstream:<null>--(423.08799999999997 + .)-NaN,(16,-111,0)(-8,-1,0):??-{}-upstream:<null>--(423.08799999999997 426.17599999999993 .)-NaN)--(prune)
* The events occured at n0 or due to n0 are colored in blue to distinguish what else at n16, n24 and n8.
The MCAST-QUERY event occurs when the multicast data packet arrives at a router and there does not exist a corresponding forwarding cache entry for the packet. For example, line 202 tells us that n16 receives a data packet destined to -111. DVMRP uses this event to install the forwarding cache entry from the dependent list of the corresponding unicast route in the routing table maintained by its own (line 203-204). The corresponding change in the routing table in the core service layer (CSL) is shown as the "FC" events. For example, the FC event in line 205 corresponds to the debug message in line 204. Same token applies to line 210 to line 209, line 215 to line 214, and line 222 to line 221.
An FC event can be an addition event (with the "RT Entry Added" remark), a modification event (with the "RT Entry Modified" remark) or a removal event (with the "RT Entry Removed" remark). We have seen, and will only see, the first two types of FC events in this example. In particular, in line 217, 225 and 228 reported are modification FC events due to receipt of prune messages from downstream routers. This type of events lists two route entries in the line. The first one is the entry before the modification (underlined) and the second one is the updated one.
Note: Instead of maintaining the forwarding cache entries itself, DVMRP stores them in the routing table maintained in the CSL. Now we check the routing tables in the CSL's to see the forwarding cache entries installed during the above pruning process:
229 tcl0> cat n*/csl/rt (Review Topology)
230 ----- /test/n0/csl/rt/ -----:
231 (16,-111,1)(-8,-1,-1) ??-{} upstream:16--(. . .)--sentPruneUpstream timeout:NaN
232 ----- /test/n16/csl/rt/ -----:
233 (16,-111,0)(-8,-1,0) ??-{} upstream:<null>--(423.08799999999997 426.17599999999993 .) timeout:NaN
234 ----- /test/n24/csl/rt/ -----:
235 (16,-111,2)(-8,-1,-1) ??-{} upstream:16--(. 425.13199999999995 .)--sentPruneUpstream timeout:NaN
236 ----- /test/n8/csl/rt/ -----:
237 (16,-111,0)(-8,-1,-1) ??-{} upstream:24--(. . .)--sentPruneUpstream timeout:NaN
Each entry is printed in the format similar to what we have seen when examining the unicast routes maintained in DVMRP. What differs is the extended part. The extended part of a forwarding cache entry consists of the following fields:
Now we run to the time when the prune states expire and examine the forwarding cache entries again:
238 tcl0> $sim resumeFor 20.0
239 DEBUG| 421.036| /test/n16/dvmrp/| REGULAR UPDATE
240 DEBUG| 421.036| /test/n24/dvmrp/| REGULAR UPDATE
241 DEBUG| 423.08799999999997| /test/n16/dvmrp/| PRUNE-TIMEOUT: cancel prune on ifs {0}
242 FC| EVENT--423.08799999999997--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{}-upstream:<null>--(+ 426.17599999999993 .)-NaN,(16,-111,0)(-8,-1,0):??-{0}-upstream:<null>--(+ 426.17599999999993 .)-NaN)--(graft)
243 DEBUG| 425.13199999999995| /test/n24/dvmrp/| PRUNE-TIMEOUT: cancel prune on ifs {1}
244 FC| EVENT--425.13199999999995--test/n24/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,2)(-8,-1,-1):??-{}-upstream:16--(. + .)--sentPruneUpstream-NaN,(16,-111,2)(-8,-1,-1):??-{1}-upstream:16--(. + .)--sentPruneUpstream-NaN)--(graft)
245 DEBUG| 426.17599999999993| /test/n16/dvmrp/| PRUNE-TIMEOUT: cancel prune on ifs {1}
246 FC| EVENT--426.17599999999993--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{0}-upstream:<null>--(+ + .)-NaN,(16,-111,0)(-8,-1,0):??-{0,1}-upstream:<null>--(+ + .)-NaN)--(graft)
247 DEBUG| 431.036| /test/n0/dvmrp/| REGULAR UPDATE
248 DEBUG| 431.036| /test/n8/dvmrp/| REGULAR UPDATE
249 tcl0> cat n*/csl/rt (Review Topology)
250 ----- /test/n0/csl/rt/ -----:
251 (16,-111,1)(-8,-1,-1) ??-{} upstream:16--(. . .)--sentPruneUpstream timeout:NaN
252 ----- /test/n16/csl/rt/ -----:
253 (16,-111,0)(-8,-1,0) ??-{0,1} upstream:<null>--(+ + .) timeout:NaN
254 ----- /test/n24/csl/rt/ -----:
255 (16,-111,2)(-8,-1,-1) ??-{1} upstream:16--(. + .) timeout:NaN
256 ----- /test/n8/csl/rt/ -----:
257 (16,-111,0)(-8,-1,-1) ??-{} upstream:24--(. . .)--sentPruneUpstream timeout:NaN
Now all the tree branches grow back due to the prune state timeout. Note that the interfaces that are downstream dependents and not being pruned should also appear in the set of the outgoing interfaces printed beside the next hop field "??".
In this scenario, we make routers join the multicast group when all the tree branches being pruned away and observe how the tree branches are grafted back.
258 tcl0> $sim resumeTo 500.0
259 DEBUG| 481.036| /test/n16/dvmrp/| REGULAR UPDATE
260 DEBUG| 481.036| /test/n24/dvmrp/| REGULAR UPDATE
261 DEBUG| 491.036| /test/n0/dvmrp/| REGULAR UPDATE
262 DEBUG| 491.036| /test/n8/dvmrp/| REGULAR UPDATE
263 tcl0> ! n0/dvmrp setPruneLifetime [expr 2*60*60]
264 tcl0> send_mcast_pkt -message "To Group -111, #1" -from n16/csl/100@up -to -111 -size 1024
265 tcl0> $sim resumeFor 20.0 (Review Topology)
266 DEBUG| 502.044| /test/n0/dvmrp/| MCAST QUERY for (16,-111,1)(-1,-1,-1)
267 DEBUG| 502.044| /test/n0/dvmrp/| SEND PRUNE to 16 at if 1: <DVMRP_FC>sz24--cmd:prune--versioin:3--source:16--group:-111--srcmask:-8--prune_lifetime:7200
268 GARBAGE| 502.044| /test/n0/csl/pd/| sz1044(INET)20--src:#10--dest:#FFFFFFFFFFFFFF91--prot:100--TTL:255--#hops:2--tos:#0___<sz1024:To Group -111, #1>___| no route for the pkt
269 DEBUG| 503.08799999999997| /test/n16/dvmrp/| PRUNE from neighbor 0 at if 0
270 FC| EVENT--503.08799999999997--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{0,1}-upstream:<null>--(+ + .)-NaN,(16,-111,0)(-8,-1,0):??-{1}-upstream:<null>--(7703.088 + .)-NaN)--(prune)
271 DEBUG| 504.08799999999997| /test/n8/dvmrp/| MCAST QUERY for (16,-111,0)(-1,-1,-1)
272 DEBUG| 504.08799999999997| /test/n8/dvmrp/| SEND PRUNE to 24 at if 0: <DVMRP_FC>sz24--cmd:prune--versioin:3--source:16--group:-111--srcmask:-8--prune_lifetime:7200
273 GARBAGE| 504.08799999999997| /test/n8/csl/pd/| sz1044(INET)20--src:#10--dest:#FFFFFFFFFFFFFF91--prot:100--TTL:255--#hops:3--tos:#0___<sz1024:To Group -111, #1>___| no route for the pkt
274 DEBUG| 505.13199999999995| /test/n24/dvmrp/| PRUNE from neighbor 8 at if 1
275 FC| EVENT--505.13199999999995--test/n24/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,2)(-8,-1,-1):??-{1}-upstream:16--(. + .)-NaN,(16,-111,2)(-8,-1,-1):??-{}-upstream:16--(. 7705.132 .)-NaN)--(prune)
276 DEBUG| 505.13199999999995| /test/n24/dvmrp/| SEND PRUNE to 16 at if 2: <DVMRP_FC>sz24--cmd:prune--versioin:3--source:16--group:-111--srcmask:-8--prune_lifetime:7200
277 DEBUG| 506.17599999999993| /test/n16/dvmrp/| PRUNE from neighbor 24 at if 1
278 FC| EVENT--506.17599999999993--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{1}-upstream:<null>--(7703.088 + .)-NaN,(16,-111,0)(-8,-1,0):??-{}-upstream:<null>--(7703.088 7706.1759999999995 .)-NaN)--(prune)
* The events occured at n0 or due to n0 are colored in blue to distinguish what else related to n8.
Make sure all the tree branches are pruned:
279 tcl0> cat n*/csl/rt (Review Topology)
280 ----- /test/n0/csl/rt/ -----:
281 (16,-111,1)(-8,-1,-1) ??-{} upstream:16--(. . .)--sentPruneUpstream timeout:NaN
282 ----- /test/n16/csl/rt/ -----:
283 (16,-111,0)(-8,-1,0) ??-{} upstream:<null>--(7703.088 7706.1759999999995 .) timeout:NaN
284 ----- /test/n24/csl/rt/ -----:
285 (16,-111,2)(-8,-1,-1) ??-{} upstream:16--(. 7705.132 .)--sentPruneUpstream timeout:NaN
286 ----- /test/n8/csl/rt/ -----:
287 (16,-111,0)(-8,-1,-1) ??-{} upstream:24--(. . .)--sentPruneUpstream timeout:NaN
Now let n0 and n8 joins the multicast group -111:
288 tcl0> host_event -join -111 -router n0/5@ -host none -router n8 -host none
In the above command, n0 joins the group -111 due to a host joins at the interface 5 (which is imaginary and not actually existent, therefore the followed host argument is "none") while n8 itself joins as a "multihomed" router.
Continue the simulation to observe the grafting process:
289 tcl0> $sim resumeFor 10.0 (Review Topology)
290 DEBUG| 520.0| /test/n0/dvmrp/| MCAST HOST JOIN EVENT: -111 at if 5
291 FC| EVENT--520.0--test/n0/csl/rt/.rt_mcast@event--RT Entry Added--(0,-111,0)(0,-1,0):??-{5}-null-NaN--
292 FC| EVENT--520.0--test/n0/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,1)(-8,-1,-1):??-{}-upstream:16--(. . .)--sentPruneUpstream-NaN,(16,-111,1)(-8,-1,-1):??-{5}-upstream:16--(. . .)--sentPruneUpstream-NaN)--(graft)
293 DEBUG| 520.0| /test/n0/dvmrp/| SEND GRAFT to 16 at if 1: <DVMRP_FC>sz20--cmd:graft--versioin:3--source:16--group:-111--srcmask:-8
294 DEBUG| 520.0| /test/n8/dvmrp/| MCAST HOST JOIN EVENT: -111 at if -1
295 DEBUG| 520.0| /test/n8/dvmrp/| SEND GRAFT to 24 at if 0: <DVMRP_FC>sz20--cmd:graft--versioin:3--source:16--group:-111--srcmask:-8
296 DEBUG| 521.04| /test/n16/dvmrp/| GRAFT from neighbor 0 at if 0
297 FC| EVENT--521.04--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{}-upstream:<null>--(7703.088 7706.1759999999995 .)-NaN,(16,-111,0)(-8,-1,0):??-{0}-upstream:<null>--(+ 7706.1759999999995 .)-NaN)--(graft)
298 DEBUG| 521.04| /test/n16/dvmrp/| SEND GRAFT-ACK to 0 at if 0: <DVMRP_FC>sz20--cmd:graft-ack--versioin:3--source:16--group:-111--srcmask:-8
299 DEBUG| 521.04| /test/n24/dvmrp/| GRAFT from neighbor 8 at if 1
300 FC| EVENT--521.04--test/n24/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,2)(-8,-1,-1):??-{}-upstream:16--(. 7705.132 .)--sentPruneUpstream-NaN,(16,-111,2)(-8,-1,-1):??-{1}-upstream:16--(. + .)--sentPruneUpstream-NaN)--(graft)
301 DEBUG| 521.04| /test/n24/dvmrp/| SEND GRAFT to 16 at if 2: <DVMRP_FC>sz20--cmd:graft--versioin:3--source:16--group:-111--srcmask:-8
302 DEBUG| 521.04| /test/n24/dvmrp/| SEND GRAFT-ACK to 8 at if 1: <DVMRP_FC>sz20--cmd:graft-ack--versioin:3--source:16--group:-111--srcmask:-8
303 DEBUG| 522.0799999999999| /test/n0/dvmrp/| GRAFT-ACK from neighbor 16 at if 1
304 DEBUG| 522.0799999999999| /test/n16/dvmrp/| GRAFT from neighbor 24 at if 1
305 FC| EVENT--522.0799999999999--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{0}-upstream:<null>--(+ 7706.1759999999995 .)-NaN,(16,-111,0)(-8,-1,0):??-{0,1}-upstream:<null>--(+ + .)-NaN)--(graft)
306 DEBUG| 522.0799999999999| /test/n16/dvmrp/| SEND GRAFT-ACK to 24 at if 1: <DVMRP_FC>sz20--cmd:graft-ack--versioin:3--source:16--group:-111--srcmask:-8
307 DEBUG| 522.0799999999999| /test/n8/dvmrp/| GRAFT-ACK from neighbor 24 at if 0
308 DEBUG| 523.1199999999998| /test/n24/dvmrp/| GRAFT-ACK from neighbor 16 at if 2
* The events occured at n0 or related to n0 are colored in blue to distinguish what else related to n8.
At this point, the tree branches are all grafted back. Let us verify this from the routing tables in the CSL's:
309 tcl0> cat n*/csl/rt (Review Topology)
310 ----- /test/n0/csl/rt/ -----:----- /test/n0/csl/rt/ -----:
311 (16,-111,1)(-8,-1,-1) ??-{5} upstream:16--(. . .) timeout:NaN
312 (0,-111,0)(0,-1,0) ??-{5} timeout:NaN
313 ----- /test/n16/csl/rt/ -----:
314 (16,-111,0)(-8,-1,0) ??-{0,1} upstream:<null>--(+ + .) timeout:NaN
315 ----- /test/n24/csl/rt/ -----:
316 (16,-111,2)(-8,-1,-1) ??-{1} upstream:16--(. + .) timeout:NaN
317 ----- /test/n8/csl/rt/ -----:
318 (16,-111,0)(-8,-1,-1) ??-{} upstream:24--(. . .) timeout:NaN
The prune states are indeed removed and the outgoing interfaces are appropriately installed. As a result, the tree has fully grown back from the two join events.
In this section, we will demonstrate how a multicast tree migrates to adapt to topology changes in DVMRP.
First, let n0 leave the multicast group -111.
319 tcl0> $sim resumeTo 570.0
320 DEBUG| 541.0360000000001| /test/n16/dvmrp/| REGULAR UPDATE
321 DEBUG| 541.0360000000001| /test/n24/dvmrp/| REGULAR UPDATE
322 DEBUG| 551.0360000000001| /test/n0/dvmrp/| REGULAR UPDATE
323 DEBUG| 551.0360000000001| /test/n8/dvmrp/| REGULAR UPDATE
324 tcl0> host_event -leave -111 -router n0/5@ -host none
325 tcl0> $sim resumeFor 10.0
326 DEBUG| 570.0| /test/n0/dvmrp/| MCAST HOST LEAVE EVENT: -111 at if 5
327 FC| EVENT--570.0--test/n0/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,1)(-8,-1,-1):??-{5}-upstream:16--(. . .)-NaN,(16,-111,1)(-8,-1,-1):??-{}-upstream:16--(. . .)-NaN)--(prune)
328 FC| EVENT--570.0--test/n0/csl/rt/.rt_mcast@event--RT Entry Modified--((0,-111,0)(0,-1,0):??-{5}-null-NaN,(0,-111,0)(0,-1,0):??-{}-null-NaN)--(prune)
Note that n0 does not send a prune message upstream, so we need to inject another data packet to actually trim the (n16 -> n0) branch.
329 tcl0> watch -c -label ROUTER_8 -add n8/csl/100@up
330 tcl0> send_mcast_pkt -message "To Group -111, #2" -from n16/csl/100@up -to -111 -size 1024
331 tcl0> $sim resumeFor 20.0 (Review Topology)
332 DEBUG| 582.044| /test/n0/dvmrp/| MCAST QUERY for (16,-111,1)(-1,-1,-1)
333 DEBUG| 582.044| /test/n0/dvmrp/| SEND PRUNE to 16 at if 1: <DVMRP_FC>sz24--cmd:prune--versioin:3--source:16--group:-111--srcmask:-8--prune_lifetime:7200
334 GARBAGE| 582.044| /test/n0/csl/pd/| sz1044<INET>sz20--source:16--destination:-111--protocol:100--TTL:255--#hops:2--router alert:false--tos:0--id:152--flag:<none>--fragmentOffset:0--ext:<null>==sz1024:To Group -111, #2| no route for the pkt| true
335 DEBUG| 583.088| /test/n16/dvmrp/| PRUNE from neighbor 0 at if 0
336 FC| EVENT--583.088--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{0,1}-upstream:<null>--(+ + .)-NaN,(16,-111,0)(-8,-1,0):??-{1}-upstream:<null>--(7783.124 + .)-NaN)--(prune)
337 ROUTER_8| pkt:sz1024:To Group -111, #2--dest:-111--src:16--tos:0--incoming:0
338 DEBUG| 584.088| /test/n8/dvmrp/| MCAST QUERY for (16,-111,0)(-1,-1,-1)
The prune process initiated at n0 should look very familiar to what we have seen before. Note that we added another watcher (line 329) at n8/csl/100@up with label "ROUTER_8" to observe the data packet being delivered at n8, the multihomed router (line 337).
At this point, there should be only one branch (n16 -> n24 -> n8) left for the multicast tree. Let us verify this in the routing tables in the CSL's:
339 tcl0> cat n*/csl/rt (Review Topology)
340 ----- /test/n0/csl/rt/ -----:
341 (16,-111,1)(-8,-1,-1) ??-{} upstream:16--(. . .)--sentPruneUpstream timeout:NaN
342 (0,-111,0)(0,-1,0) ??-{} timeout:NaN
343 ----- /test/n16/csl/rt/ -----:
344 (16,-111,0)(-8,-1,0) ??-{1} upstream:<null>--(7783.088 + .) timeout:NaN
345 ----- /test/n24/csl/rt/ -----:
346 (16,-111,2)(-8,-1,-1) ??-{1} upstream:16--(. + .) timeout:NaN
347 ----- /test/n8/csl/rt/ -----:
348 (16,-111,0)(-8,-1,-1) ??-{} upstream:24--(. . .) timeout:NaN
Now, bring down the link between n8 and n24, which is part of the remaing branch of the multicast tree:
349 tcl0> $sim resumeTo 610.0 350 DEBUG| 601.0360000000001| /test/n16/dvmrp/| REGULAR UPDATE 351 DEBUG| 601.0360000000001| /test/n24/dvmrp/| REGULAR UPDATE 352 tcl0> setflag component false n8/0@/-/..
Since DVMRP needs to modify the forwarding cache entries in response to changes in the unicast route entries it maintains (synchronizing forwarding cache with the unicast route, as we call it), we turn on the debug flag to observe this type of event:
353 tcl0> setflag debug true -at debug_sync_fc n*/dvmrp
Continue the simulation until this wave of changes are over:
354 tcl0> $sim resumeFor 120.0 (Review Topology)
355 DEBUG| 611.0360000000001| /test/n0/dvmrp/| REGULAR UPDATE
356 DEBUG| 611.0360000000001| /test/n8/dvmrp/| REGULAR UPDATE
357 DEBUG| 661.0360000000001| /test/n16/dvmrp/| REGULAR UPDATE
358 DEBUG| 661.0360000000001| /test/n24/dvmrp/| REGULAR UPDATE
359 DEBUG| 665.0| /test/n24/dvmrp/| NEIGHBOR DOWN EVENT: <8,-8>
360 DEBUG| 665.0| /test/n24/dvmrp/| SYNC fc entries with the rt entry: (0,24,0)(0,-8,0):??-null-metric:0--dependents:(0,16){0,2}-NaN
361 DEBUG| 665.0| /test/n24/dvmrp/| hold-down (0,8,0)(0,-8,0):8-{1}-metric:INF(changed)--dependents:(16){2}-785.0 due to NEIGHBOR TIMEOUT: 8
362 DEBUG| 665.0| /test/n24/dvmrp/| SYNC fc entries with the rt entry: (0,16,0)(0,-8,0):16-{2}-metric:1--dependents:()-NaN
363 FC| EVENT--665.0--test/n24/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,2)(-8,-1,-1):??-{1}-upstream:16--(. + .)-NaN,(16,-111,2)(-8,-1,-1):??-{}-upstream:16--(. . .)-NaN)--
364 DEBUG| 665.0| /test/n8/dvmrp/| NEIGHBOR DOWN EVENT: <24,-8>
365 DEBUG| 665.0| /test/n8/dvmrp/| SYNC fc entries with the rt entry: (0,8,0)(0,-8,0):??-null-metric:0--dependents:(0){1}-NaN
366 DEBUG| 665.0| /test/n8/dvmrp/| hold-down (0,24,0)(0,-8,0):24-{0}-metric:INF(changed)--dependents:()-785.0 due to NEIGHBOR TIMEOUT: 24
367 DEBUG| 665.0| /test/n8/dvmrp/| hold-down (0,16,0)(0,-8,0):24-{0}-metric:INF(changed)--dependents:()-785.0 due to NEIGHBOR TIMEOUT: 24
368 DEBUG| 670.0| /test/n24/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
369 DEBUG| 670.0| /test/n8/dvmrp/| TRIGGERED UPDATE: # of changed entries = 2
370 DEBUG| 671.0360000000001| /test/n0/dvmrp/| REGULAR UPDATE
371 DEBUG| 671.0360000000001| /test/n8/dvmrp/| REGULAR UPDATE
372 DEBUG| 671.112| /test/n16/dvmrp/| hold-down (0,8,0)(0,-8,0):24-{1}-metric:2--dependents:()-NaN due to route invalidation from NEXT-HOP neighbor
--->metric:INF(changed)--dependents:()
373 DEBUG| 672.152| /test/n8/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,24,0)(0,-8,0):24-{0}-metric:INF--dependents:()-785.0
--->0-metric:2(changed)--dependents:()
374 DEBUG| 672.152| /test/n8/dvmrp/| SYNC fc entries with the rt entry: (0,24,0)(0,-8,0):0-{1}-metric:2(changed)--dependents:()-NaN
375 DEBUG| 672.152| /test/n8/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,16,0)(0,-8,0):24-{0}-metric:INF--dependents:()-785.0
--->0-metric:2(changed)--dependents:()
376 DEBUG| 672.152| /test/n8/dvmrp/| SYNC fc entries with the rt entry: (0,16,0)(0,-8,0):0-{1}-metric:2(changed)--dependents:()-NaN
377 FC| EVENT--672.152--test/n8/csl/rt/.rt_mcast@event--RT Entry Removed--(16,-111,0)(-8,-1,-1):??-{}-upstream:24--(. . .)-NaN--
378 FC| EVENT--672.152--test/n8/csl/rt/.rt_mcast@event--RT Entry Added--(16,-111,1)(-8,-1,-1):??-{}-upstream:0--(. . .)-NaN--
379 DEBUG| 672.152| /test/n16/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,8,0)(0,-8,0):24-{1}-metric:INF(changed)--dependents:()-791.076
--->0-metric:2(changed)--dependents:()
380 DEBUG| 672.152| /test/n16/dvmrp/| SYNC fc entries with the rt entry: (0,8,0)(0,-8,0):0-{0}-metric:2(changed)--dependents:()-NaN
381 DEBUG| 672.152| /test/n24/dvmrp/| Better route from NON-NEXT-HOP neighbor: (0,8,0)(0,-8,0):8-{1}-metric:INF--dependents:(16){2}-785.0
--->0-metric:2(changed)--dependents:(16){2}
382 DEBUG| 672.152| /test/n24/dvmrp/| SYNC fc entries with the rt entry: (0,8,0)(0,-8,0):0-{0}-metric:2(changed)--dependents:(16){2}-NaN
383 DEBUG| 676.076| /test/n16/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
384 DEBUG| 677.152| /test/n8/dvmrp/| TRIGGERED UPDATE: # of changed entries = 2
385 DEBUG| 677.152| /test/n24/dvmrp/| TRIGGERED UPDATE: # of changed entries = 1
386 DEBUG| 677.152| /test/n0/dvmrp/| SYNC fc entries with the rt entry: (0,8,0)(0,-8,0):8-{0}-metric:1--dependents:(16){1}-NaN
387 DEBUG| 677.152| /test/n24/dvmrp/| SYNC fc entries with the rt entry: (0,8,0)(0,-8,0):0-{0}-metric:2--dependents:()-NaN
388 DEBUG| 678.2280000000001| /test/n0/dvmrp/| SYNC fc entries with the rt entry: (0,8,0)(0,-8,0):8-{0}-metric:1--dependents:(16,24){1,2}-NaN
389 DEBUG| 678.248| /test/n0/dvmrp/| SYNC fc entries with the rt entry: (0,24,0)(0,-8,0):24-{2}-metric:1--dependents:(8){0}-NaN
390 DEBUG| 678.248| /test/n0/dvmrp/| SYNC fc entries with the rt entry: (0,16,0)(0,-8,0):16-{1}-metric:1--dependents:(8){0}-NaN
391 FC| EVENT--678.248--test/n0/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,1)(-8,-1,-1):??-{}-upstream:16--(. . .)--sentPruneUpstream-NaN,(16,-111,1)(-8,-1,-1):??-{0}-upstream:16--(+ . .)-NaN)--
392 DEBUG| 678.248| /test/n0/dvmrp/| SEND GRAFT to 16 at if 1: <DVMRP_FC>sz20--cmd:graft--versioin:3--source:16--group:-111--srcmask:-8
393 DEBUG| 679.288| /test/n16/dvmrp/| GRAFT from neighbor 0 at if 0
394 FC| EVENT--679.288--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{1}-upstream:<null>--(7783.124 + .)-NaN,(16,-111,0)(-8,-1,0):??-{0,1}-upstream:<null>--(+ + .)-NaN)--(graft)
395 DEBUG| 679.288| /test/n16/dvmrp/| SEND GRAFT-ACK to 0 at if 0: <DVMRP_FC>sz20--cmd:graft-ack--versioin:3--source:16--group:-111--srcmask:-8
396 DEBUG| 680.328| /test/n0/dvmrp/| GRAFT-ACK from neighbor 16 at if 1
397 DEBUG| 721.0360000000001| /test/n16/dvmrp/| REGULAR UPDATE
398 DEBUG| 721.0360000000001| /test/n24/dvmrp/| REGULAR UPDATE
We leave tracing these messages as an exercise to the readers.
Now, examine the routing table in DVMRP's and in CSL's to see how the unicast routes and the multicast tree have adapted to the topology change (changes are highlighted in boldface):
399 tcl0> cat n*/dvmrp (Review Topology)
400 ----- /test/n0/dvmrp/ -----:
401 ifset: all physical ifs
402 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
403 (0,0,0)(0,-8,0) ??-() metric:0--dependents:(8,16,24){0,1,2} timeout:NaN
404 (0,24,0)(0,-8,0) 24-{2} metric:1--dependents:(8){0} timeout:NaN
405 (0,8,0)(0,-8,0) 8-{0} metric:1--dependents:(16,24){1,2} timeout:NaN
406 (0,16,0)(0,-8,0) 16-{1} metric:1--dependents:(8){0} timeout:NaN
407 ----- /test/n16/dvmrp/ -----:
408 ifset: all physical ifs
409 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
410 (0,16,0)(0,-8,0) ??-() metric:0--dependents:(0,24){0,1} timeout:NaN
411 (0,24,0)(0,-8,0) 24-{1} metric:1--dependents:() timeout:NaN
412 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:() timeout:NaN
413 (0,8,0)(0,-8,0) 0-{0} metric:2--dependents:() timeout:NaN
414 ----- /test/n24/dvmrp/ -----:
415 ifset: all physical ifs
416 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
417 (0,24,0)(0,-8,0) ??-() metric:0--dependents:(0,16){0,2} timeout:NaN
418 (0,8,0)(0,-8,0) 0-{0} metric:2--dependents:() timeout:NaN
419 (0,16,0)(0,-8,0) 16-{2} metric:1--dependents:() timeout:NaN
420 (0,0,0)(0,-8,0) 0-{0} metric:1--dependents:() timeout:NaN
421 ----- /test/n8/dvmrp/ -----:
422 ifset: all physical ifs
423 Entry:<key> <next_hop>-<out_ifs> <metric--dependents(dependent_ifs)> <timeout>
424 (0,8,0)(0,-8,0) ??-() metric:0--dependents:(0){1} timeout:NaN
425 (0,24,0)(0,-8,0) 0-{1} metric:2--dependents:() timeout:NaN
426 (0,0,0)(0,-8,0) 0-{1} metric:1--dependents:() timeout:NaN
427 (0,16,0)(0,-8,0) 0-{1} metric:2--dependents:() timeout:NaN
428 tcl0> cat n*/csl/rt (Review Topology)
429 ----- /test/n0/csl/rt/ -----:
430 (16,-111,1)(-8,-1,-1) ??-{0} upstream:16--(+ . .) timeout:NaN
431 (0,-111,0)(0,-1,0) ??-{} timeout:NaN
432 ----- /test/n16/csl/rt/ -----:
433 (16,-111,0)(-8,-1,0) ??-{0,1} upstream:<null>--(+ + .) timeout:NaN
434 ----- /test/n24/csl/rt/ -----:
435 (16,-111,2)(-8,-1,-1) ??-{} upstream:16--(. . .) timeout:NaN
436 ----- /test/n8/csl/rt/ -----:
437 (16,-111,1)(-8,-1,-1) ??-{} upstream:0--(. . .) timeout:NaN
Notice that the (n8->n0->n16) branch grows and the old branch (n24->n16) remains there but redundant. Now inject another data packet to trim the redundant branch:
438 tcl0> $sim resumeTo 750.0
439 DEBUG| 731.0360000000001| /test/n0/dvmrp/| REGULAR UPDATE
440 DEBUG| 731.0360000000001| /test/n8/dvmrp/| REGULAR UPDATE
441 tcl0> send_mcast_pkt -message "To Group -111, #3" -from n16/csl/100@up -to -111 -size 1024
442 tcl0> $sim resumeFor 20.0 (Review Topology)
443 DEBUG| 752.044| /test/n24/dvmrp/| MCAST QUERY for (16,-111,2)(-1,-1,-1)
444 DEBUG| 752.044| /test/n24/dvmrp/| SEND PRUNE to 16 at if 2: <DVMRP_FC>sz24--cmd:prune--versioin:3--source:16--group:-111--srcmask:-8--prune_lifetime:7200
445 GARBAGE| 752.044| /test/n24/csl/pd/| sz1044<INET>sz20--source:16--destination:-111--protocol:100--TTL:255--#hops:2--router alert:false--tos:0--id:196--flag:<none>--fragmentOffset:0--ext:<null>==sz1024:To Group -111, #3| no route for the pkt| true
446 DEBUG| 753.088| /test/n16/dvmrp/| PRUNE from neighbor 24 at if 1
447 FC| EVENT--753.088--test/n16/csl/rt/.rt_mcast@event--RT Entry Modified--((16,-111,0)(-8,-1,0):??-{0,1}-upstream:<null>--(+ + .)-NaN,(16,-111,0)(-8,-1,0):??-{0}-upstream:<null>--(+ 7953.124 .)-NaN)--(prune)
448 ROUTER_8| pkt:sz1024:To Group -111, #3--dest:-111--src:16--tos:0--incoming:1
449 DEBUG| 754.088| /test/n8/dvmrp/| MCAST QUERY for (16,-111,1)(-1,-1,-1)
Now let us check if the redundant branch is trimmed in the routing tables in CSL's:
450 tcl0> cat n*/csl/rt (Review Topology)
451 ----- /test/n0/csl/rt/ -----:
452 (16,-111,1)(-8,-1,-1) ??-{0} upstream:16--(+ . .) timeout:NaN
453 (0,-111,0)(0,-1,0) ??-{} timeout:NaN
454 ----- /test/n16/csl/rt/ -----:
455 (16,-111,0)(-8,-1,0) ??-{0} upstream:<null>--(+ 7953.088 .) timeout:NaN
456 ----- /test/n24/csl/rt/ -----:
457 (16,-111,2)(-8,-1,-1) ??-{} upstream:16--(. . .)--sentPruneUpstream timeout:NaN
458 ----- /test/n8/csl/rt/ -----:
459 (16,-111,1)(-8,-1,-1) ??-{} upstream:0--(. . .) timeout:NaN
This is the end of the example. In summary, we have examined the DVMRP implementation from several scenarios, and learned:
The source codes are available as two script files: DVMRP_common.tcl and DVMRP1.tcl. To run the example, download the two files into the same directory and run the second script in J-Sim. The script runs the example in a batched manner rather than interactively as demonstrated here.
Where we go next
DVMRP on a 4-boundary-router and 3-core-router network. (under construction)