J-Sim INET Tutorial -> DVMRP Examples

DVMRP on A Four-Router Network

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. Simulation Setup

Step 1. Build the network

 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.

Step 2. Configure the interfaces of the routers

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 }

Step 3. Hook up simulator and boot up all the routers

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.


2. Examining DVMRP

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.

2.1 Route Exchange

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)

Line 2-11
At time 1.036, all routers discovered all their neighbors. There are 10 NEIGHBOR-UP events, each for an interface.
Line 12-21
Upon receipt of a NEIGHBOR-UP event, DVMRP sends a route request to the neighbor and the neighbor will reply with a route report. Therefore, at time 3.128, after about the 2-second round-trip time, each router receives an initial route report from each neighbor.
Line 22-25
We implement the delayed triggered update and the delay is 5 seconds by default. So at time 8.128, each router sends triggered updates to its neighbors.
Line 26-29
At time 9.244, after about 1-second link propagation delay, all routers receive the triggered updates from its neighbors. Due to the topology, only router n8 and n16 learn new routes to each other, and then 5 seconds later, they send out triggered updates again.

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:

  1. The key of the route. For example, the key of the second entry in /test/n0/dvmrp (line 35) is (0,24,0)(0,-8,0). It is in the format of (source, destination, incoming interface)(source mask, destination mask, incoming interface mask). For unicast routes, we only care the destination, so the masks for source and incoming interface are set to be zero's. The pair of destination 24 (110002) and mask -8 (110002) indicates that this entry is destined to the network "11xxx2" gatewayed by the router n24.
  2. Next hop and the outgoing interfaces. The print-out of this for the second entry of /test/n0/dvmrp (line 35) is "24-{2}", meaning that the network address of the next hop is 24 via the interface 2. The notation "??" for the next hop denotes that this field is not applicable, and the set of the outgoing interfaces may be an empty set denoted by "{}".
  3. Metric and list of dependents. The metric here is hop count. The list of dependents indicates the downstream routers of this router in the multicast tree rooted at the destination node of this route. The first curly parenthesis contains the set of network addresses of the dependents. The second curly parenthesis contains the corresponding outgoing interface to the dependent.
  4. Timeout field. It indicates the time when this route expires.

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.

 

 

2.2 Route Exchange under Link Failure

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:

  1. Timers are set for those held-down routes for 120 seconds (therefore the routes will be expired at time 140.0 + 120.0 = 260.0 and 146.076 + 120.0 = 266.076).
  2. Both routers (n0 and n8) remove each other from the lists of dependents of the affected routes (the loopback routes in this case).

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.

 

 

2.3 Forwarding of Data Packets, Prune and Prune Timeout

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
Line 197
Create the 100 "up" port at the CSL of each router. The port is used to manually inject and receive the multicast data packet.
Line 198
Shorten the prune life time from 2 hours (the default value) to 20 seconds to speed up the timeouts of the prune states.
Line 199
Turned on the garbage display flag at CSL's to observe the data packet being dropped at the leaf routers of the multicast tree.
Line 200
Inject the data packet to the up port at n16, destined to the multicast group -111. (Note: In the default address scheme, the positive long integers are used for unicast addresses, and the negative long integers are for multicast addresses.)

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.

Line 202-205
Router n16 receives the MCAST-QUERY event, adds a new forwarding cache entry and forwards the data packet to n0 and n24.
Line 206-211
The DVMRP instance in router n0 receives the MCAST-QUERY, indicating that the data packet has arrived at n0 from n16. Since n0 is a leaf node, it sends back a prune message to n16 (line 208) and at the same time, discards the data packet (line 211).
Line 212-215
The DVMRP instance in router n24 receives the MCAST-QUERY, indicating that the data packet has arrived at n24 from n16. Router n24 forwards the packet to n8 after adding the forwarding cache entry in line 214-215.
Line 216-217
Router n16 receives the prune message from n0 and prunes the outgoing interface to n0 from the corresponding forwarding cache entry.
Line 218-223
The DVMRP instance in router n8 receives the MCAST-QUERY, indicating that the data packet has arrived at n8 from n24. Again, n8 is a leaf node, it sends back a prune message (line 220) and discards the packet (line 223).
Line 224-226
Router n24 receives the prune message from n8, prunes the interface and sends another prune message upstream.
Line 227-228
Router n16 receives the prune messages from n24 and prunes the interface from the forwarding cache entry. This wave of pruning process ends here.

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:

  1. Uptream router. Could be <null> if the router is the root (source) of the multicast tree.
  2. Prune states. It consists of a set of symbols, each for an outgoing interface. The symbol "." denotes that the corresponding interface is not a downstream dependent. The symbol "+" denotes that the corresponding interface is a downstream dependent and is not being pruned. A timeout value denotes that the interface is pruned and the time when the pruned state will expire. In the above print-out, each interface is either not a dependent, or pruned.
  3. The graft retransmission timeout and the counter counting for the times of retransmission backoffs. This field is printed only when a graft message is pending and waiting for acknowledgement from upstream.
  4. The "SentPruneUpstream" flag. This field is printed only when a prune was sent upstream before and no graft has been sent and cleared since.

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 "??".

 

 

2.4 Graft

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.

Line 258-262
Continue the simulation until time 500.0.
Line 263
Restore the prune life time back to 2 hours.
Line 264-278
Send another multicast data packet to trim the tree branches before any router joins the multicast group. The pruning process is the same as what we have seen in the previous section except that the forwarding caches have been created and installed in the earlier pruning process.

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.

Line 290-291
Upon receipt of a host join event (line 290), n0 creates, if not yet done so, a "group" forwarding cache entry for the multicast group -111 with the interface 5 in the set of outgoing interfaces (line 291). (Note: A "group" forwarding cache entry is a forwarding cache with unspecified source and incoming interface.)
Line 292-293
Router n0 adds the interface 5 to the set of outgoing interfaces of any existing source-specific forwarding cache entry. In this case, the only entry available is (source, group, incoming interface) = (16, -111, 1) (line 292). For any existing forwarding cache entry with the "sentPruneUpstream" flag on, n0 then sends a graft message upstream toward the source (line 293).
Line 294-295
Similarly, n8 receives a host join event (line 294) and then sends a graft message upstream for any existing forwarding cache entry with the "sentPruneUpstream" flag on (line 295). Router n8 did not create a "group" forwarding cache entry because n8 itself joins the multicast group as a "multihomed" router.
Line 296-298
Upon receipt of the graft message from n0 (line 296), n16 grafts the downstream interface for the corresponding forwarding cache entry (line 297), and replies a graft-acknowledgment message (line 298).
Line 299-302
Similarly, router n24 receives the graft message from n8 (line 299), grafts the downstream interface for the corresponding forwarding cache entry (line 300), continues the graft message upstream toward the source since the "sentPruneUpstream" flag is on (line 301), and replies to n8 a graft-acknowledgment message (line 302).
Line 304-306
About one unit of link delay later, n16 receives another graft message from n24 (line 304), grafts the downstream interface for the corresponding forwarding cache entry (line 305), and replies a graft-acknowledgment message (line 306).
Line 303,307-308
Router n0, n8 and n24 receive graft-acknowledgment messages and clear the pending graft states.

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.

 

 

2.5 Prune and Graft in Case of a Link Failure

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:

  1. how to use the "setflag" command to turn on/off different debug levels,
  2. how to use the "watch" command to add watchers,
  3. how to enable/disable a component, and all in all,
  4. how to, interactively, change the component settings during simulation, to create a more dynamic testing and verification process.

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)