Cisconinja’s Blog

EIGRP SIA-Query and SIA-Reply

Posted by Andy on September 18, 2009

EIGRP SIA Query and Reply

R1:
interface Serial0/0
 ip address 10.0.12.1 255.255.255.0
 ip hold-time eigrp 1 500
 no keepalive
!
router eigrp 1
 network 10.0.0.0
 eigrp log-neighbor-changes

R2:
interface Loopback0
 ip address 10.2.2.2 255.255.255.0
!
interface Serial0/0
 ip address 10.0.12.2 255.255.255.0
 no keepalive
!
interface Serial0/1
 ip address 10.0.23.2 255.255.255.0
!
router eigrp 1
 timers active-time 1
 network 10.0.0.0
 eigrp log-neighbor-changes

R3:
interface Loopback0
 ip address 10.3.3.3 255.255.255.0
!
interface Serial0/0
 ip address 10.0.23.3 255.255.255.0
!
router eigrp 1
 timers active-time 1
 network 10.0.0.0
 eigrp log-neighbor-changes

This first example uses IOS version 12.0(5), which does not have support for SIA-query and SIA-reply messages.  The active timer has been lowered to 1 minute on R2 and R3 in order to see the results faster.  Keepalives have been disabled on the R1-R2 link and the hold timer increased on R1 to prevent R2 from discovering that R1 is down before the active timer expires.  We will shut down R1 S0/0 so that R1 stops receiving traffic from R2, and then shut down R3’s loopback:

R1:
interface Serial0/0
 shutdown

R3:
interface Loopback0
 shutdown

When R3’s loopback gets shutdown, R3 sends a query to R2 for 10.3.3.0/24.  R2 acknowledges the query and sends queries to both R1 and R3 for the route.  R3 acknowledges the query and sends a reply with it’s current metric (infinity).  R2 does not receive an ACK to the query that it sent to R1 so it continues to retransmit it.  R3 continues to wait on a reply from R2, but R2 can’t reply until it receives an ACK and a reply from R1:

1-R3-Topology-Table

1-R2-Topology-Table

R3#debug eigrp packets update ack query reply
Mar 1 00:14:26.075: EIGRP: Enqueueing QUERY on Serial0/0 iidbQ un/rely 0/1 serno 23-23
Mar 1 00:14:26.079: EIGRP: Enqueueing QUERY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/0 peerQ un/rely 0/0 serno 23-23
Mar 1 00:14:26.079: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.23.2
Mar 1 00:14:26.079: AS 1, Flags 0x0, Seq 21/28 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 23-23
Mar 1 00:14:26.159: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:14:26.159: AS 1, Flags 0x0, Seq 0/21 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 00:14:26.191: EIGRP: Received QUERY on Serial0/0 nbr 10.0.23.2
Mar 1 00:14:26.191: AS 1, Flags 0x0, Seq 31/21 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:14:26.191: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:14:26.195: Ack seq 31 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:14:26.195: EIGRP: Sending ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:14:26.195: AS 1, Flags 0x0, Seq 0/31 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:14:26.207: EIGRP: Enqueueing REPLY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 24-24
Mar 1 00:14:26.211: EIGRP: Sending REPLY on Serial0/0 nbr 10.0.23.2
Mar 1 00:14:26.211: AS 1, Flags 0x0, Seq 22/31 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 24-24
Mar 1 00:14:26.255: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:14:26.255: AS 1, Flags 0x0, Seq 0/22 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1

 

R2#debug eigrp packets update ack query reply
Mar 1 00:14:26.823: EIGRP: Received QUERY on Serial0/1 nbr 10.0.23.3
Mar 1 00:14:26.823: AS 1, Flags 0x0, Seq 21/28 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:14:26.823: EIGRP: Enqueueing ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:14:26.827: Ack seq 21 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:14:26.827: EIGRP: Sending ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:14:26.827: AS 1, Flags 0x0, Seq 0/21 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:14:26.839: EIGRP: Enqueueing QUERY on Serial0/0 iidbQ un/rely 0/1 serno 18-18
Mar 1 00:14:26.839: EIGRP: Enqueueing QUERY on Serial0/1 iidbQ un/rely 0/1 serno 18-18
Mar 1 00:14:26.843: EIGRP: Enqueueing QUERY on Serial0/0 nbr 10.0.12.1 iidbQ un/rely 0/0 peerQ un/rely 0/0 serno 18-18
Mar 1 00:14:26.843: EIGRP: Enqueueing QUERY on Serial0/1 nbr 10.0.23.3 iidbQ un/rely 0/0 peerQ un/rely 0/0 serno 18-18
Mar 1 00:14:26.843: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1
Mar 1 00:14:26.847: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:14:26.847: EIGRP: Sending QUERY on Serial0/1 nbr 10.0.23.3
Mar 1 00:14:26.847: AS 1, Flags 0x0, Seq 31/21 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:14:26.911: EIGRP: Received ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:14:26.911: AS 1, Flags 0x0, Seq 0/31 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 00:14:26.935: EIGRP: Received REPLY on Serial0/1 nbr 10.0.23.3
Mar 1 00:14:26.935: AS 1, Flags 0x0, Seq 22/31 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:14:26.935: EIGRP: Enqueueing ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:14:26.935: Ack seq 22 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:14:26.935: EIGRP: Sending ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:14:26.935: AS 1, Flags 0x0, Seq 0/22 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:14:31.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 1, RTO 5000
Mar 1 00:14:31.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:14:36.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 2, RTO 5000
Mar 1 00:14:36.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:14:41.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 3, RTO 5000
Mar 1 00:14:41.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:14:46.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 4, RTO 5000
Mar 1 00:14:46.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:14:51.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 5, RTO 5000
Mar 1 00:14:51.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:14:56.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 6, RTO 5000
Mar 1 00:14:56.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:01.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 7, RTO 5000
Mar 1 00:15:01.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:06.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 8, RTO 5000
Mar 1 00:15:06.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:11.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 9, RTO 5000
Mar 1 00:15:11.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:16.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 10, RTO 5000
Mar 1 00:15:16.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:21.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 11, RTO 5000
Mar 1 00:15:21.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:26.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 12, RTO 5000
Mar 1 00:15:26.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:31.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 13, RTO 5000
Mar 1 00:15:31.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:36.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 14, RTO 5000
Mar 1 00:15:36.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:41.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 15, RTO 5000
Mar 1 00:15:41.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:46.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 16, RTO 5000
Mar 1 00:15:46.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:51.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 17, RTO 5000
Mar 1 00:15:51.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:15:56.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 18, RTO 5000
Mar 1 00:15:56.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:16:01.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 19, RTO 5000
Mar 1 00:16:01.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:16:06.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 20, RTO 5000
Mar 1 00:16:06.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18

The active timer expires first on R3, and R3 assumes R2 is the cause of the problem and clears the adjacency.  A couple seconds later, the adjacency is reestablished and all updates must be resent between R2 and R3.  The active timer expires on R2 a few seconds later and R2 clears the adjacency with R1.  It no longer needs to send a reply to R3 since R3 already reset the adjacency between R2 and R3:

R3#debug eigrp packets update ack query reply
Mar 1 00:16:05.295: %DUAL-3-SIA: Route 10.3.3.0/24 stuck-in-active state in IP-EIGRP 1. Cleaning up
Mar 1 00:16:05.295: %DUAL-5-NBRCHANGE: IP-EIGRP 1: Neighbor 10.0.23.2 (Serial0/0) is down: stuck in active
Mar 1 00:16:07.659: %DUAL-5-NBRCHANGE: IP-EIGRP 1: Neighbor 10.0.23.2 (Serial0/0) is up: new adjacency
Mar 1 00:16:07.659: EIGRP: Enqueueing UPDATE on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 1-1
Mar 1 00:16:07.663: EIGRP: Sending UPDATE on Serial0/0 nbr 10.0.23.2
Mar 1 00:16:07.663: AS 1, Flags 0x1, Seq 23/0 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 1-1
Mar 1 00:16:09.051: EIGRP: Received UPDATE on Serial0/0 nbr 10.0.23.2
Mar 1 00:16:09.051: AS 1, Flags 0x1, Seq 32/0 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 00:16:09.067: EIGRP: Enqueueing UPDATE on Serial0/0 iidbQ un/rely 0/1 serno 25-26
Mar 1 00:16:09.071: EIGRP: Enqueueing UPDATE on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 25-26
Mar 1 00:16:09.663: EIGRP: Sending UPDATE on Serial0/0 nbr 10.0.23.2, retry 1, RTO 3000
Mar 1 00:16:09.663: AS 1, Flags 0x1, Seq 23/32 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2 serno 1-1
Mar 1 00:16:09.707: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:16:09.707: AS 1, Flags 0x0, Seq 0/23 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2
Mar 1 00:16:09.711: EIGRP: Sending UPDATE on Serial0/0 nbr 10.0.23.2
Mar 1 00:16:09.711: AS 1, Flags 0x0, Seq 24/32 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 25-26
Mar 1 00:16:09.739: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:16:09.739: AS 1, Flags 0x0, Seq 0/24 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1

 

R2#debug eigrp packets update ack query reply
Mar 1 00:16:08.363: %DUAL-5-NBRCHANGE: IP-EIGRP 1: Neighbor 10.0.23.3 (Serial0/1) is down: peer restarted
Mar 1 00:16:09.695: %DUAL-5-NBRCHANGE: IP-EIGRP 1: Neighbor 10.0.23.3 (Serial0/1) is up: new adjacency
Mar 1 00:16:09.695: EIGRP: Enqueueing UPDATE on Serial0/1 nbr 10.0.23.3 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 1-18
Mar 1 00:16:09.699: EIGRP: Sending UPDATE on Serial0/1 nbr 10.0.23.3
Mar 1 00:16:09.699: AS 1, Flags 0x1, Seq 32/0 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 1-18
Mar 1 00:16:10.383: EIGRP: Received UPDATE on Serial0/1 nbr 10.0.23.3
Mar 1 00:16:10.383: AS 1, Flags 0x1, Seq 23/32 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 00:16:10.383: EIGRP: Enqueueing ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:16:10.387: Ack seq 23 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:16:10.387: EIGRP: Sending ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:16:10.387: AS 1, Flags 0x0, Seq 0/23 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:16:10.395: EIGRP: Received UPDATE on Serial0/1 nbr 10.0.23.3
Mar 1 00:16:10.395: AS 1, Flags 0x0, Seq 24/32 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:16:10.395: EIGRP: Enqueueing ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:16:10.399: Ack seq 24 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:16:10.399: EIGRP: Sending ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:16:10.399: AS 1, Flags 0x0, Seq 0/24 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:16:11.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 21, RTO 5000
Mar 1 00:16:11.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:16:16.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 22, RTO 5000
Mar 1 00:16:16.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:16:21.347: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 23, RTO 5000
Mar 1 00:16:21.347: AS 1, Flags 0x0, Seq 30/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 00:16:21.403: %DUAL-3-SIA: Route 10.3.3.0/24 stuck-in-active state in IP-EIGRP 1. Cleaning up
Mar 1 00:16:21.403: %DUAL-5-NBRCHANGE: IP-EIGRP 1: Neighbor 10.0.12.1 (Serial0/0) is down: stuck in active

Note: The active timer is not exact and seems to vary quite a bit from the actual configured time.  In my tests, it took as long as 1 minute over the configured active time for a route to be declared SIA, so the active time may end up expiring on R2 before R3.

The full exchange of non-hello EIGRP packets between R2 and R3 from the time 10.3.3.0/24 went down looks like this:

1-Wireshark

Resetting the adjacency between R2 and R3 obviously does not help the situation and wastes bandwidth and processing on both routers as the adjacency has to be reestablished and updates resent.  Let’s try the same scenario again on IOS version 12.4(15)T5, which supports SIA-query and SIA-reply messages:

R1:
interface Serial0/0
 shutdown

R3:
interface Loopback0
 shutdown

The first part of what happens is the same as before.  R3 sends a query to R2 for 10.3.3.0/24.  R2 acknowledges the query and sends queries to both R1 and R3 for the route.  R3 acknowledges the query and sends a reply with it’s current metric (infinity).  R2 does not receive an ACK to the query that it sent to R1 so it continues to retransmit it.  R3 continues to wait on a reply from R2, but R2 can’t reply until it receives an ACK and a reply from R1:

R3#debug eigrp packets update ack query reply siaquery siareply
Mar 1 00:06:33.299: EIGRP: Enqueueing QUERY on Serial0/0 iidbQ un/rely 0/1 serno 10-10
Mar 1 00:06:33.303: EIGRP: Enqueueing QUERY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/0 peerQ un/rely 0/0 serno 10-10
Mar 1 00:06:33.307: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.23.2
Mar 1 00:06:33.307: AS 1, Flags 0x0, Seq 9/7 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 10-10
Mar 1 00:06:33.531: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:06:33.531: AS 1, Flags 0x0, Seq 0/9 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 00:06:33.535: EIGRP: Received QUERY on Serial0/0 nbr 10.0.23.2
Mar 1 00:06:33.535: AS 1, Flags 0x0, Seq 13/9 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:06:33.535: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:06:33.539: Ack seq 13 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:06:33.543: EIGRP: Sending ACK on Serial0/0 nbr
10.0.23.2
Mar 1 00:06:33.543: AS 1, Flags 0x0, Seq 0/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:06:33.551: EIGRP: Enqueueing REPLY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 11-11
Mar 1 00:06:33.559: EIGRP: Sending REPLY on Serial0/0 nbr 10.0.23.2
Mar 1 00:06:33.559: AS 1, Flags 0x0, Seq 10/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 11-11
Mar 1 00:06:33.759: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:06:33.759: AS 1, Flags 0x0, Seq 0/10 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1

 

R2#debug eigrp packets update ack query reply siaquery siareply
Mar 1 00:06:33.787: EIGRP: Received QUERY on Serial0/1 nbr 10.0.23.3
Mar 1 00:06:33.787: AS 1, Flags 0x0, Seq 9/7 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:06:33.791: EIGRP: Enqueueing ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:06:33.791: Ack seq 9 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:06:33.795: EIGRP: Sending ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:06:33.799: AS 1, Flags 0x0, Seq 0/9 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:06:33.803: EIGRP: Enqueueing QUERY on Serial0/0 iidbQ un/rely 0/1 serno 6-6
Mar 1 00:06:33.803: EIGRP: Enqueueing QUERY on Serial0/1 iidbQ un/rely 0/1 serno 6-6
Mar 1 00:06:33.807: EIGRP: Enqueueing QUERY on Serial0/0 nbr 10.0.12.1 iidbQ un/rely 0/0 peerQ un/rely 0/0 serno 6-6
Mar 1 00:06:33.807: EIGRP: Enqueueing QUERY on Serial0/1 nbr 10.0.23.3 iidbQ un/rely 0/0 peerQ un/rely 0/0 serno 6-6
Mar 1 00:06:33.811: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1
Mar 1 00:06:33.815: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 6-6
Mar 1 00:06:33.815: EIGRP: Sending QUERY on Serial0/1 nbr 10.0.23.3
Mar 1 00:06:33.819: AS 1, Flags 0x0, Seq 13/9 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 6-6
Mar 1 00:06:33.887: EIGRP: Received ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:06:33.887: AS 1, Flags 0x0, Seq 0/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 00:06:33.979: EIGRP: Received REPLY on Serial0/1 nbr 10.0.23.3
Mar 1 00:06:33.979: AS 1, Flags 0x0, Seq 10/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:06:33.979: EIGRP: Enqueueing ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:06:33.979: Ack seq 10 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:06:33.983: EIGRP: Sending ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:06:33.983: AS 1, Flags 0x0, Seq 0/10 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:06:38.815: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 1, RTO 5000
Mar 1 00:06:38.819: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 6-6
Mar 1 00:06:43.819: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 2, RTO 5000
Mar 1 00:06:43.823: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 6-6
Mar 1 00:06:48.823: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 3, RTO 5000
Mar 1 00:06:48.827: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 6-6
Mar 1 00:06:53.827: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 4, RTO 5000
Mar 1 00:06:53.831: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 6-6
Mar 1 00:06:58.831: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 5, RTO 5000
Mar 1 00:06:58.835: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 6-6
Mar 1 00:07:03.835: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 6, RTO 5000
Mar 1 00:07:03.839: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 6-6

After approximately half of the configured active timer, R2 and R3 both send an SIA-query to the neighbor that hasn’t replied yet.  (R2’s SIA-query never actually gets sent to R1 since RTP uses a window size of 1 packet and it is still waiting for an ACK to the original query).  R2 ACKs R3’s SIA-query and sends an SIA-reply.  R3 resets the active timer when it receives the SIA-reply.  Since R2 does not receive an SIA-reply from R1, it does not reset the active timer, and once the active timer expires it declares the route stuck in active and resets the adjacency with R1.  R2 is then able to finally reply to R3’s query, and the R2-R3 adjacency does not have to be reestablished:

R3#debug eigrp packets update ack query reply siaquery siareply
Mar 1 00:07:06.087: EIGRP: Enqueueing SIAQUERY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 12-12
Mar 1 00:07:06.095: EIGRP: Sending SIAQUERY on Serial0/0 nbr 10.0.23.2
Mar 1 00:07:06.095: AS 1, Flags 0x0, Seq 11/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 12-12
Mar 1 00:07:06.131: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:07:06.131: AS 1, Flags 0x0, Seq 0/11 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 00:07:06.135: EIGRP: Received SIAREPLY on Serial0/0 nbr 10.0.23.2
Mar 1 00:07:06.135: AS 1, Flags 0x0, Seq 15/11 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:07:06.135: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:07:06.139: Ack seq 15 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:07:06.139: EIGRP: Sending ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:07:06.143: AS 1, Flags 0x0, Seq 0/15 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:07:33.655: EIGRP: Received REPLY on Serial0/0 nbr 10.0.23.2
Mar 1 00:07:33.659: AS 1, Flags 0x0, Seq 16/11 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:07:33.659: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:07:33.659: Ack seq 16 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:07:33.663: EIGRP: Sending ACK on Serial0/0 nbr 10.0.23.2
Mar 1 00:07:33.667: AS 1, Flags 0x0, Seq 0/16 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0

 

R2#debug eigrp packets update ack query reply siaquery siareply
Mar 1 00:07:03.847: EIGRP: Enqueueing SIAQUERY on Serial0/0 nbr 10.0.12.1 iidbQ un/rely 0/1 peerQ un/rely 0/1 serno 7-7
Mar 1 00:07:06.367: EIGRP: Received SIAQUERY on Serial0/1 nbr 10.0.23.3
Mar 1 00:07:06.367: AS 1, Flags 0x0, Seq 11/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 00:07:06.371: EIGRP: Enqueueing ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:07:06.371: Ack seq 11 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:07:06.375: EIGRP: Sending ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:07:06.375: AS 1, Flags 0x0, Seq 0/11 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 00:07:06.387: EIGRP: Enqueueing SIAREPLY on Serial0/1 nbr 10.0.23.3 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 8-8
Mar 1 00:07:06.395: EIGRP: Sending SIAREPLY on Serial0/1 nbr 10.0.23.3
Mar 1 00:07:06.395: AS 1, Flags 0x0, Seq 15/11 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 8-8
Mar 1 00:07:06.535: EIGRP: Received ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:07:06.539: AS 1, Flags 0x0, Seq 0/15 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 00:07:08.839: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 7, RTO 5000
Mar 1 00:07:08.843: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2 serno 6-6
Mar 1 00:07:13.843: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 8, RTO 5000
Mar 1 00:07:13.847: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2 serno 6-6
Mar 1 00:07:18.847: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 9, RTO 5000
Mar 1 00:07:18.851: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2 serno 6-6
Mar 1 00:07:23.851: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 10, RTO 5000
Mar 1 00:07:23.855: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2 serno 6-6
Mar 1 00:07:28.855: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.12.1, retry 11, RTO 5000
Mar 1 00:07:28.859: AS 1, Flags 0x0, Seq 12/3 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2 serno 6-6
Mar 1 00:07:33.859: %DUAL-3-SIA: Route 10.3.3.0/24 stuck-in-active state in IP-EIGRP(0) 1. Cleaning up
Mar 1 00:07:33.863: %DUAL-5-NBRCHANGE: IP-EIGRP(0) 1: Neighbor 10.0.12.1 (Serial0/0) is down: stuck in active
Mar 1 00:07:33.875: EIGRP: Enqueueing REPLY on Serial0/1 nbr 10.0.23.3 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 9-9
Mar 1 00:07:33.887: EIGRP: Sending REPLY on Serial0/1 nbr 10.0.23.3
Mar 1 00:07:33.891: AS 1, Flags 0x0, Seq 16/11 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 9-9
Mar 1 00:07:34.039: EIGRP: Received ACK on Serial0/1 nbr 10.0.23.3
Mar 1 00:07:34.043: AS 1, Flags 0x0, Seq 0/16 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1

The full exchange of EIGRP packets between R2 and R3 from the time 10.3.3.0/24 went down excluding hellos looks like this:

2-Wireshark

The two packets that show up as ‘unknown’ in wireshark are the SIA-query (OpCode 10) and the SIA-reply (OpCode 11).  No updates needed to be resent.

EIGRP attempts to send up to 3 SIA-queries to a neighbor about an active route.  Each SIA-query is sent at an interval of 1/2 of the active timer, and each SIA-reply causes the active timer to be reset.  After 3, the router stops sending SIA-queries even if an SIA-reply has been successfully received for each one and allows the active timer to expire if the reply to the original query still hasn’t been received.  To demonstrate this, we will set the active time back to the default of 3 minutes on R2.

R2:
router eigrp 1
 timers active-time 3

R1:
interface Serial0/0
 shutdown

R3:
interface Loopback0
 shutdown

R3#debug eigrp packets update ack query reply siaquery siareply
Mar 1 01:56:43.315: EIGRP: Enqueueing QUERY on Serial0/0 iidbQ un/rely 0/1 serno 14-14
Mar 1 01:56:43.319: EIGRP: Enqueueing QUERY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/0 peerQ un/rely 0/0 serno 14-14
Mar 1 01:56:43.323: EIGRP: Sending QUERY on Serial0/0 nbr 10.0.23.2
Mar 1 01:56:43.323: AS 1, Flags 0x0, Seq 13/16 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 14-14
Mar 1 01:56:43.547: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:56:43.551: AS 1, Flags 0x0, Seq 0/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 01:56:43.551: EIGRP: Received QUERY on Serial0/0 nbr 10.0.23.2
Mar 1 01:56:43.555: AS 1, Flags 0x0, Seq 22/13 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 01:56:43.555: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:56:43.555: Ack seq 22 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 01:56:43.559: EIGRP: Sending ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:56:43.563: AS 1, Flags 0x0, Seq 0/22 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 01:56:43.579: EIGRP: Enqueueing REPLY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 15-15
Mar 1 01:56:43.583: EIGRP: Sending REPLY on Serial0/0 nbr 10.0.23.2
Mar 1 01:56:43.583: AS 1, Flags 0x0, Seq 14/22 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 15-15
Mar 1 01:56:43.735: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:56:43.739: AS 1, Flags 0x0, Seq 0/14 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 01:57:13.963: EIGRP: Enqueueing SIAQUERY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 16-16
Mar 1 01:57:13.971: EIGRP: Sending SIAQUERY on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:13.971: AS 1, Flags 0x0, Seq 15/22 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 16-16
Mar 1 01:57:14.099: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:14.103: AS 1, Flags 0x0, Seq 0/15 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 01:57:14.107: EIGRP: Received SIAREPLY on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:14.111: AS 1, Flags 0x0, Seq 23/15 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 01:57:14.111: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:14.111: Ack seq 23 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 01:57:14.115: EIGRP: Sending ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:14.119: AS 1, Flags 0x0, Seq 0/23 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 01:57:45.863: EIGRP: Enqueueing SIAQUERY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 17-17
Mar 1 01:57:45.871: EIGRP: Sending SIAQUERY on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:45.871: AS 1, Flags 0x0, Seq 16/23 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 17-17
Mar 1 01:57:45.979: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:45.979: AS 1, Flags 0x0, Seq 0/16 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 01:57:46.003: EIGRP: Received SIAREPLY on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:46.003: AS 1, Flags 0x0, Seq 24/16 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 01:57:46.003: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:46.007: Ack seq 24 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 01:57:46.011: EIGRP: Sending ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:57:46.011: AS 1, Flags 0x0, Seq 0/24 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 01:58:18.447: EIGRP: Enqueueing SIAQUERY on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/1 peerQ un/rely 0/0 serno 18-18
Mar 1 01:58:18.455: EIGRP: Sending SIAQUERY on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:18.455: AS 1, Flags 0x0, Seq 17/24 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 18-18
Mar 1 01:58:18.575: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:18.579: AS 1, Flags 0x0, Seq 0/17 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 01:58:18.583: EIGRP: Received SIAREPLY on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:18.587: AS 1, Flags 0x0, Seq 26/17 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/0
Mar 1 01:58:18.587: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:18.587: Ack seq 26 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 01:58:18.591: EIGRP: Sending ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:18.595: AS 1, Flags 0x0, Seq 0/26 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 1/0
Mar 1 01:58:51.695: %DUAL-3-SIA: Route 10.3.3.0/24 stuck-in-active state in IP-EIGRP(0) 1. Cleaning up
Mar 1 01:58:51.699: %DUAL-5-NBRCHANGE: IP-EIGRP(0) 1: Neighbor 10.0.23.2 (Serial0/0) is down: stuck in active
Mar 1 01:58:56.391: %DUAL-5-NBRCHANGE: IP-EIGRP(0) 1: Neighbor 10.0.23.2 (Serial0/0) is up: new adjacency
Mar 1 01:58:56.391: EIGRP: Enqueueing UPDATE on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/1 peerQ un/rely 0/0
Mar 1 01:58:56.403: EIGRP: Received UPDATE on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:56.403: AS 1, Flags 0x1, Seq 27/0 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 01:58:56.407: EIGRP: Sending UPDATE on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:56.407: AS 1, Flags 0x1, Seq 18/27 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1
Mar 1 01:58:56.411: EIGRP: Enqueueing UPDATE on Serial0/0 iidbQ un/rely 0/1 serno 7-7
Mar 1 01:58:56.415: EIGRP: Enqueueing UPDATE on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 7-7
Mar 1 01:58:56.523: EIGRP: Received UPDATE on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:56.527: AS 1, Flags 0x8, Seq 28/18 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2
Mar 1 01:58:56.527: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:56.531: Ack seq 28 iidbQ un/rely 0/1 peerQ un/rely 1/1
Mar 1 01:58:56.535: EIGRP: Sending UPDATE on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:56.539: AS 1, Flags 0x8, Seq 19/28 idbQ 0/0 iidbQ un/rely 0/1 peerQ un/rely 0/1 serno 7-7
Mar 1 01:58:56.695: EIGRP: Received UPDATE on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:56.695: AS 1, Flags 0x8, Seq 29/19 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2
Mar 1 01:58:56.695: EIGRP: Enqueueing UPDATE on Serial0/0 iidbQ un/rely 0/1 serno 19-20
Mar 1 01:58:56.699: EIGRP: Enqueueing ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:56.699: Ack seq 29 iidbQ un/rely 0/1 peerQ un/rely 1/1
Mar 1 01:58:56.703: EIGRP: Sending UPDATE on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:56.707: AS 1, Flags 0x8, Seq 20/29 idbQ 0/0 iidbQ un/rely 0/1 peerQ un/rely 0/1 serno 7-7
Mar 1 01:58:56.711: EIGRP: Enqueueing UPDATE on Serial0/0 nbr 10.0.23.2 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 19-20
Mar 1 01:58:56.827: EIGRP: Received ACK on Serial0/0 nbr 10.0.23.2
Mar 1 01:58:56.831: AS 1, Flags 0x0, Seq 0/20 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/2

The route remains active for a little over 2 minutes (twice the active time and four times the SIA retransmit interval).  When the original reply still hasn’t been received from R2 and the active time expires after 3 SIA-queries/replies, R3 resets the adjacency and updates are resent.

Advertisement

Posted in EIGRP | Leave a Comment »

Offset-lists in EIGRP

Posted by Andy on September 7, 2009

EIGRP Offset Lists

R1:
interface Loopback0
 ip address 10.1.1.1 255.255.255.0
!
interface Serial0/0
 bandwidth 128
 ip address 10.0.12.1 255.255.255.0
!
router eigrp 1
 network 10.0.0.0

R2:
interface Serial0/0
 bandwidth 128
 ip address 10.0.12.2 255.255.255.0
!
router eigrp 1
 network 10.0.0.0

The minimum bandwidth for 10.1.1.0/24 at R2 is 128k and the cumulative delay is 25,000 microseconds (20,000 serial + 5,000 loopback), so R2 calculates the metric as:

Metric = 256 * (10^7 / 128) + 256 * 2500

= 20,000,000 + 640,000

= 20,640,000

1-R2-Show-IP-Route

Now we will add an offset of 10,000 to all routes advertised by R1:

R1:
router eigrp 1
 offset-list 0 out 10000

Let’s see how this effected the update sent by R1.  The first picture shows the update before the offset-list was applied, and the second shows the update after being applied:

1-R1-Update

2-R1-Update

Loopback interfaces have a default delay of 5,000 microseconds and the value carried in the update for delay is after it has been multiplied by 256, so before the offset-list R1 advertises it as 128,000.  After the offset-list was configured, the delay advertised in the update increased to 138,000, so the offset is applied to delay after it has been multiplied by 256.  Since the delay is cumulative along the path and the offset is applied after the delay has been multiplied by 256, the overall metric for routers receiving the update will increase by the same value configured in the offset.  On R2, the composite metric has increased from 20,640,000 to 20,650,000:

2-R2-Show-IP-Route

To determine the actual delay along the path (in tens of microseconds), R2 divides the delay value received in the update by 256, and then adds it’s own delay on the receiving interface:

Delay = (138,000 / 256) + 2,000

= 2539.0625

When converted back to microseconds and rounded down, this matches the total delay of 25,390 shown for the route on R2.  To find the delay that will be added by the configured offset value, you could also multiply by 10/256:

10,000 * (10/256) = 390 microseconds

 

The configured offset will match the offset applied to the composite metric as long as K3 = 1 and K5 = 0.  If either of these are changed it isn’t quite as simple.  Let’s try changing K3 to a value of 20 first.  We will also remove the offset-list and then add it again after we have seen the initial update and metric calculation:

R1:
router eigrp 1
 metric weights 0 1 0 20 0 0
 no offset-list 0 out 10000

R2:
router eigrp 1
 metric weights 0 1 0 20 0 0

3-R1-Update

3-R2-Show-IP-Route

The update still contains a delay of 128,000, so we know that the value carried in the update must be before being multiplied by K3.  R2 multiplies the delay of the receiving interface by 256, adds this to the delay in the received update and multiplies the sum by K3, and also adds the bandwidth component:

Metric = 256 * (10^7 / 128) + 20 * (128,000 + (256 * 2,000))

= 20,000,000 + 12,800,000

= 32,800,000

Let’s put the offset-list back on:

R1:
router eigrp 1
 offset-list 0 out 10000

4-R1-Update

4-R2-Show-IP-Route

The update contains 138,000 for the delay value like before when K3 was 1.  R2 calculates the metric as 

Metric = 256 * (10^7 / 128) + 20 * (138,000 + (256 * 2,000))

= 20,000,000 + 13,000,000

= 33,000,000

Since the offset gets multiplied by K3 just like the rest of the delay, the actual metric increases by K3 * offset, or 200,000 in this case.  The calculation for total delay of the path does not depend on K-values, so R2 calculates the same total delay of 25,390 microseconds.  Let’s try changing K3 to 0:

R1:
router eigrp 1
 metric weights 0 1 0 0 0 0
 no offset-list 0 out 10000

R2:
router eigrp 1
 metric weights 0 1 0 0 0 0

5-R1-Update

5-R2-Show-IP-Route

R1:
router eigrp 1
 offset-list 0 out 10000

 

6-R1-Update

6-R2-Show-IP-Route

If K3=0, the offset has no effect on the overall metric since it only adds to the delay.  R2 is still able to calculate the correct total delay for the route however since the delay value is carried in route TLVs regardless of the K-values.

 

Next, we will look at what happens when K5 ≠ 0.  The K-values will be set to: K1=1, K2=0, K3=20, K4=1, K5=64.  The offset-list is again removed:

R1:
router eigrp 1
 metric weights 0 1 0 20 1 64
 no offset-list 0 out 10000

R2:
router eigrp 1
 metric weights 0 1 0 20 1 64

The received delay is 128,000 like before.  Since K5 is non-zero, R2 performs an additional calculation and calculates the metric as:

Metric = (256 * (10^7 / 128) + 20 * (128,000 + (256 * 2,000))) * (64 / (255 + 1))

= (20,000,000 + 12,800,000) * (64/256)

= 8,200,000

7-R2-Show-IP-Route

Add the offset again:

R1:
router eigrp 1
 offset-list 0 out 10000

Metric = (256 * (10^7 / 128) + 20 * (138,000 + (256 * 2,000))) * (64 / (255 + 1))

= (20,000,000 + 13,000,000) * (64/256)

= 8,250,000

8-R2-Show-IP-Route

The configured offset value is multiplied by K3, and (if K5 ≠ 0) also by (K5 / (reliability + K4)).  Therefore the actual amount that the configured offset will cause the metric to increase can be calculated as:

Metric increase = K3 * offset * (K5 / (reliability + K4))

In the example we just did, the offset of 10,000 caused the metric to increase by 50,000:

Metric increase = 20 * 10,000 * (64 / (255 +1))

= 50,000

 

Most of the time with offset-lists we are trying to add a certain amount to the overall metric of a route, so it would be much more useful to know the amount of offset that we need to add in order to get the desired metric increase.  Solving the equation for offset gives us:

offset = metric increase * (reliability + K4) / (K3 * K5)

Let’s try another example and see if it works.  We will pick some new K-values and remove the offset-list:

R1:
router eigrp 1
 metric weights 0 5 0 10 45 4
 no offset-list 0 out 10000

R2:
router eigrp 1
 metric weights 0 5 0 10 45 4

9-R2-Show-IP-Route

The metric for the route is now 1,418,666.  Let’s see if we can add 81,334 to it to make it an even 1,500,000.  That means we should have to offset the metric by:

offset = 81,334 * (255 + 45) / (10 * 4)

= 610,005

R1:
router eigrp 1
 offset-list 0 out 610005

10-R2-Show-IP-Route

Looks like it worked perfectly.  The delay added was:

610,005 * (10/256) = 23,828 microseconds

which makes the total delay of the route now 48,828 microseconds.

Posted in EIGRP | Leave a Comment »

Testing EIGRP metric with non-default K-values

Posted by Andy on September 6, 2009

In this post we will look at how changing EIGRP K-values from their defaults effects the metric calculation and how it effects when updates are sent.  The topology and configurations for this example are shown below:

EIGRP Topology

R1:
interface Loopback0
 ip address 10.1.1.1 255.255.255.0
!
interface Serial0/0
 ip address 10.0.12.1 255.255.255.0
!
router eigrp 1
 passive-interface Loopback0
 network 10.0.0.0
 metric weights 0 1 1 1 1 1

R2:
interface FastEthernet0/0
 ip address 10.2.2.2 255.255.255.0
!
interface Serial0/0
 bandwidth 100
 ip address 10.0.12.2 255.255.255.0
 load-interval 30
!
interface Serial0/1
 ip address 10.0.23.2 255.255.255.0
 load-interval 30
!
router eigrp 1
 passive-interface FastEthernet0/0
 network 10.0.0.0
 metric weights 0 1 1 1 1 1

R3:
interface Serial0/0
 ip address 10.0.23.3 255.255.255.0
 load-interval 30
!
router eigrp 1
 network 10.0.0.0
 metric weights 0 1 1 1 1 1

Each of the K-values has been set to 1 on all routers.  The bandwidth of the R1-R2 link has also been lowered to 100k on R2.

The EIGRP metric is calculated as:

Metric = ((k1 * BW) + ((k2 * BW)/(256 – load)) + (k3 * delay)) * (k5 / (reliability + k4))

BW = 256 * (10^7 / interface BW in kbps)

load = txload on the interface

delay = 256 * interface delay in tens of microseconds

reliability = reliability rating on the interface

Of the 4 metric components, only the delay is added at each hop.  The other 3 (BW, load, reliability) use the worst value of any single link in the path.  When calculating the composite metric, each individual component is rounded down.   For example, loopback interfaces have a default bandwidth of 8 Gbps:

1-R1-BW

R1 therefore calculates the bandwidth as 10^7 / (8 * 10^6).  The bandwidth value is rounded down (from 1.25 to 1) before being multiplied by 256, and the value carried for BW in the route TLV is 256 (instead of 320, if the rounding had occurred after):

1-R1-BW-Wireshark

When the calculation is reversed, the result is that as far as R1’s topolgy table and any neighbors that R1 is advertising the route to are concerned, the BW is 10 Gbps, as shown in the topology table on R1:

1-R1-Metric

A similar method of rounding occurs for each of the other components.  Loopback interfaces have a default delay of 5000 microseconds and the reliability and load on the interface are 255 and 1 respectively.  The overall calculated metric on R1 is:

Metric = ((1 * 256) + ((1 * 256)/(256 – 1)) + (1 * 128,000)) * (1 / (255 + 1))

= (256 + 1 + 128000) / 256

= 128,257 / 256

=  501

The load component was rounded down (from 256/255 to 1) prior to being multiplied by (k5 / (reliability + k4)) and the final metric was again rounded down (from 501.0039 to 501).  R2’s calculation works the same way:

Metric = ((1 * 25,600,000) + ((1 * 25,600,000)/(256 – 1)) + (1 * 640,000)) * (1 / (255 + 1))

= (25,600,000 + 100,392 + 640,000) / 256

= 26,340,392 / 256

= 102,892

1-R2-Metric

R3 computes the metric as:

Metric = ((1 * 25,600,000) + ((1 * 25,600,000)/(256 – 1)) + (1 * 1,152,000)) * (1 / (255 + 1))

= (25,600,000 + 100,392 + 1,152,000) / 256

= 26,852,392 / 256

= 104,892

1-R3-Metric

As you can see, only the delay increased when R2 advertised the route to R3 (by 20,000 microseconds, the default on a serial interface) since the other 3 values only use the worst value in the path and the BW, load, and reliability on the R2-R3 link from R3’s perspective are either better than or equal to the worst values that were advertised by R2.

 

And now for the main point of this example, to show how including load and reliability in the equation effects updates being sent.  Many sources incorrectly say that including load and reliability in the equation is not recommended because it will cause updates to be sent frequently when the load and/or reliability change.  The actual behavior is that EIGRP advertises the route only at the start of the adjacency or after an event that causes updates to be resent, with whatever the current worst load and reliability rating along the path are.  In many cases this could be even worse than if updates were frequently sent to update the load and reliability ratings, because the load and/or reliability can change dramatically after an update has been sent and neighboring routers continue to assume the original load/reliability values that were advertised before the change.  To demonstrate this, we will add an additional router, R4, with links to R1 and R3:

EIGRP Topology3

 

R1:
interface Serial0/2
 ip address 10.0.14.1 255.255.255.0
 load-interval 30

R3:
interface Serial0/1
 ip address 10.0.34.3 255.255.255.0
 load-interval 30

R4:
interface Serial0/0
 bandwidth 100
 ip address 10.0.14.4 255.255.255.0
 load-interval 30
 delay 2001
!
interface Serial0/1
 ip address 10.0.34.4 255.255.255.0
 load-interval 30
!
router eigrp 1
 network 10.0.0.0
 metric weights 0 1 1 1 1 1

The bandwidth on the R1-R4 link is configured as 100k like the R1-R2 link and the delay as 20,010 microseconds to make the path through R2 preferred by R3.  R3 keeps the path through R4 as an FS but since unequal cost load balancing is not configured, R3 will only use the original link to reach R1:

3-R3-ShowTopology

3-R3-RouteTable

Next, we will use a host on the 10.2.2.0/24 subnet connected to R2 to send approximately 96kbps of traffic to R1 (for more information on the method of generating traffic, see WFQ tests):

flood.pl --port=1000 --size=1496 --delay=125 10.1.1.1

All traffic is sent out S0/0 on R2 and the txload increases to 234:

3-R2-Load

After several minutes, R2 still has not updated the metric in it’s topology and also has not sent an update to R3:

4-R2-ShowTopology

4-R3-ShowTopology

4-R3-RouteTable

Although the R1-R2 link is almost entirely saturated and R3 would have a better path through R4, it is unaware of this because updates are not sent to dynamically update the load and reliability.  Next we will clear the R1-R2 adjacency, causing updates to be resent (clearing the R2 to R3 adjacency would not refresh the load value, because R2 simply sends R3 the same information about 10.1.1.0/24 that already exists in it’s routing table):

R2#clear ip eigrp neighbors 10.0.12.1

R2 receives an update from R1 and records the higher of the received load value (1) and the load of the receiving link (232).  R2 then sends an update to R3 and R3 records the higher of the received load value (232) and the receiving link (1).  R3’s metric for 10.1.1.0/24 through R2 is now higher than through R4, so R3 now uses the path through R4 instead:

5-R3-ShowTopology

5-R3-RouteTable

Note: The FD of the successor on R3 in the topology table as well as the metric in the route table show 104,893, while the FD listed in the topology table for the route on the third line says 104,892 (the original FD of the route through R2).  I think this happens whenever the router is able to switch to an FS for a route without having to go active – the route table and FD through the successor show the new value but the overall FD for the route shows the original FD for the route.

Let’s check the topology table on R2:

5-R2-ShowTopology

That’s strange, R2 and R3 both show the correct load value but the FD at R2 doesn’t match the AD that R3 calculated through R2.  Using the formula, the FD at R2 should be:

Metric = ((1 * 25,600,000) + ((1 * 25,600,000)/(256 – 232)) + (1 * 640,000)) * (1 / (255 + 1))

= (25,600,000 + 1,066,666 + 640,000) / 256

= 27,306,666 / 256

= 106,666

R3 calculated the AD correctly for R2 and also calculated it’s own FD of 108,666 through R2 correctly.  Looking back at the previous topology table on R2 we can see that the metric hasn’t changed at all on R2 – R2 is still calculating the metric as if there is a load of 1.  It appears that although R2 records the higher of the two load values (the one in the received update and the one on the receiving interface) and also advertises the higher one to R3, it only uses the one in the received update for it’s own calculation.  I can’t figure out why this would be desirable since a saturated link between R1 and R2 effects R2 just as much as R3 or any other upstream routers, but there are already enough reasons not to use load or reliability in a production network anyway.

 

As one last test, we will stop the traffic generator.  After a few seconds the interface load is updated on R2 and drops back to 1:

6-R2-Load

Like before, R2 does not dynamically refresh the load value in it’s own topology table or send updates to it’s neighbors.  R3 continues to use the route through R4 to reach 10.1.1.0/24 until something causes updates to be resent between R1 and R2:

6-R3-RouteTable

Posted in EIGRP | Leave a Comment »

Virtual Fragmentation Reassembly

Posted by Andy on June 14, 2009

In this post we will look at virtual fragmentation reassembly and a few examples of where it is useful.  The topology and configurations for this example are shown below:

VFR Topology2

R1:
interface FastEthernet0/0
 ip address 10.1.1.1 255.255.255.0
!
interface Serial0/0
 ip address 10.0.12.1 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 Serial0/0

R2:
interface Serial0/0
 ip address 10.0.12.2 255.255.255.0
!
interface Serial0/1
 ip address 10.0.23.2 255.255.255.0
!
ip route 10.0.34.0 255.255.255.0 Serial0/1
ip route 10.1.1.0 255.255.255.0 Serial0/0

R3:
interface Serial0/0
 ip address 10.0.23.3 255.255.255.0
!
interface Serial0/1
 ip address 10.0.34.3 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 Serial0/0

R4:
interface Serial0/0
 ip address 10.0.34.4 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 Serial0/0

With virtual fragmentation reassembly enabled, a router holds fragments received on an interface until all fragments of a packet have been received and the packet can be reassembled.  The router can then make decisions based on the L4 and other information available in the reassembled packet that would otherwise not be available in the non-initial fragments.  The original fragments are then forwarded based on the information in the reassembled packet, and the reassmbled packet is discarded. 

 

First we will look at how this can be useful in CBAC, also known as IOS classic firewall.  R1 is set up as a TFTP and HTTP server and has a 250 KB file in flash, which R4 will download.  R3 will inspect TFTP and HTTP inbound on S0/1.  R2 S0/1 MTU is lowered to 300, causing fragmentation to occur at R2 for return traffic:

R1:
ip http server
ip http path flash:
tftp-server flash:asdf.txt

R3:
ip inspect audit-trail
ip inspect name asdf http
ip inspect name asdf tftp
!
access-list 100 deny ip any any
!
interface Serial0/0
 ip access-group 100 in
!
interface Serial0/1
 ip inspect asdf in

R2:
interface Serial0/1
 ip mtu 300

Next we will start the download on R4:

R4#copy http://10.0.12.1/asdf.txt null:
Loading http://10.0.12.1/asdf.txt !
%Error reading http://10.0.12.1/asdf.txt (Broken pipe)

The transfer fails.  Both R1 and R4 have specified a TCP MSS of 536 bytes in their first packet:

3-Wireshark

4-Wireshark

 

The rest of the first part of the exchange looks as shown below Wireshark.  R4 sends an HTTP GET to R1, and the first data packet sent by R1 is an unfragmented 292 byte packet.  After this, all packets  sent by R1 are fragmented.  The majority of them are a 304 byte initial fragment followed by a 300 byte 2nd fragment due to the MSS of 536 on R4 and MTU of 300 on R2 S0/1 (536B of data + 20B TCP header + 20B IP header = 576; fragmented by R2 into 300B and 276B; add 20B IP header to 2nd fragment and 4B HDLC to both fragments = 304B and 300B):

2-Wireshark

Let’s compare this sequence of packets that we see in Wireshark to the CBAC debug output:

R3#debug ip inspect protocol tcp
Mar 1 01:22:07.895: %FW-6-SESS_AUDIT_TRAIL_START: Start http session: initiator (10.0.34.4:21143) -- responder (10.0.12.1:80)
Mar 1 01:22:07.895: CBAC* sis 66F0A118 pak 663FE6F4 SIS_CLOSED/LISTEN TCP SYN SEQ 1282798572 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:07.895: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 48, proto=6
Mar 1 01:22:07.895: CBAC: data length for this packet is zero, returning
Mar 1 01:22:08.003: CBAC* sis 66F0A118 pak 663FE340 SIS_OPENING/SYNSENT TCP SYN ACK 1282798573 SEQ 590243577 LEN 0 (10.0.12.1:80) <= (10.0.34.4:21143)
Mar 1 01:22:08.003: CBAC* Details of Pak 663FE340 IP: s=10.0.12.1 (Serial0/0), d=10.0.34.4 (Serial0/1), len 48, proto=6
Mar 1 01:22:08.007: CBAC: data length for this packet is zero, returning
Mar 1 01:22:08.135: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPENING/SYNRCVD TCP ACK 590243578 SEQ 1282798573 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:08.139: CBAC* sis 66F0A118 http L7 inspect result: PASS packet
Mar 1 01:22:08.139: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6
Mar 1 01:22:08.139: CBAC: data length for this packet is zero, returning
Mar 1 01:22:08.143: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590243578 SEQ 1282798573 LEN 127 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:08.143: CBAC* sis 66F0A118 http L7 inspect result: PASS packet
Mar 1 01:22:08.143: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 171, proto=6
Mar 1 01:22:08.147: CBAC: pak seq = 1282798573, rcvwnd = 4128 rcvnxt = 590243578
Mar 1 01:22:08.375: CBAC* sis 66F0A118 pak 663FE340 SIS_OPEN/ESTAB TCP ACK 1282798700 SEQ 590243578 LEN 248 (10.0.12.1:80) <= (10.0.34.4:21143)
Mar 1 01:22:08.375: CBAC* sis 66F0A118 http L7 inspect result: PASS packet
Mar 1 01:22:08.375: CBAC* Details of Pak 663FE340 IP: s=10.0.12.1 (Serial0/0), d=10.0.34.4 (Serial0/1), len 292, proto=6
Mar 1 01:22:08.375: CBAC: pak seq = 590243578, rcvwnd = 4001 rcvnxt = 1282798700
Mar 1 01:22:08.379: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590243826 SEQ 1282798700 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:08.379: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6
Mar 1 01:22:08.379: CBAC: data length for this packet is zero, returning
Mar 1 01:22:08.475: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590244115 SEQ 1282798700 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:08.475: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6
Mar 1 01:22:08.475: CBAC: data length for this packet is zero, returning
Mar 1 01:22:08.495: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590244115 SEQ 1282798700 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:08.495: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6
Mar 1 01:22:08.499: CBAC: data length for this packet
is zero, returning
Mar 1 01:22:08.571: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590244611 SEQ 1282798700 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:08.571: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6
Mar 1 01:22:08.571: CBAC: data length for this packet is zero, returning
Mar 1 01:22:08.691: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590245147 SEQ 1282798700 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:08.691: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6
Mar 1 01:22:08.691: CBAC: data length for this packet is zero, returning

By comparing the source/destination address and the length shown in the debug output, it’s easy to correlate them to the Wireshark output.  The first several packets match Wireshark exactly, but after the 292 byte unfragmented packet from R1, we see only ACKs from R4.  The fragmented packets from R1 are forwarded to R4 without even being checked by CBAC as long as the L3 information matches the L3 information of the session.  This is somewhat similar to how ACLs handle IP fragments, except that in this case not even the initial fragment is examined by CBAC to determine the L4 information.  Part way through the transfer, R1 happens to send a 161-byte packet that does not need fragmentation at R2:

5-Wireshark

This packet also shows up in the debug output since it is unfragmented and can be inspected by CBAC:

Mar 1 01:22:10.347: CBAC* sis 66F0A118 pak 663FE340 SIS_OPEN/ESTAB TCP ACK 1282798700 SEQ 590257277 LEN 117 (10.0.12.1:80) <= (10.0.34.4:21143)
Mar 1 01:22:10.347: CBAC* sis 66F0A118 L4 inspect result: DROP packet 663FE340 (10.0.12.1:80) (10.0.34.4:21143) bytes 117 ErrStr = Out-Of-Order Segment http
Mar 1 01:22:10.351: CBAC* Details of Pak 663FE340 IP: s=10.0.12.1 (Serial0/0), d=10.0.34.4 (Serial0/1), len 161, proto=6
Mar 1 01:22:10.351: CBAC: pak seq = 590257277, rcvwnd = 4001 rcvnxt = 1282798700
Mar 1 01:22:10.351: CBAC Storing the packet 663FE340 into OOO queue of session 66F0A118

As shown in the log message, CBAC believes this is an out of order segment based on the TCP sequence number since it did not inspect any of the intermediate packets.  As explained here, CBAC allows the packet to pass but stores a copy in memory.  If it turns out to be an out of order packet, future packets should be able to fill in the gap in sequence numbers.  Shortly after this, we begin seeing this debug message for R4’s ACKs:

Mar 1 01:22:11.035: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590261146 SEQ 1282798700 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:11.039: CBAC* sis 66F0A118 L4 inspect result: DROP packet 663FE6F4 (10.0.34.4:21143) (10.0.12.1:80) bytes 0 ErrStr = Invalid Ack (or no Ack) http
Mar 1 01:22:11.039: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6

CBAC thinks this is an invalid ACK by R4 since it does not believe that sequence number has been sent yet by R1.  As shown in the message, the packet is dropped.  R1 can still send packets to R4, but R4 can no longer acknowledge them.  Since R1 does not receive an ACK it continues trying to resend sequence number 590,260,074:

6-Wireshark

R4 receives them all and after each one tries to tell R1 it already received that sequence number and wants 590,262,754 instead, but the ACKs continue to be dropped:

Mar 1 01:22:11.615: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590262754 SEQ 1282798700 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:11.615: CBAC* sis 66F0A118 L4 inspect result: DROP packet 663FE6F4 (10.0.34.4:21143) (10.0.12.1:80) bytes 0 ErrStr = Invalid Ack (or no Ack) http
Mar 1 01:22:11.615: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6
Mar 1 01:22:12.759: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590262754 SEQ 1282798700 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:12.763: CBAC* sis 66F0A118 L4 inspect result: DROP packet 663FE6F4 (10.0.34.4:21143) (10.0.12.1:80) bytes 0 ErrStr = Invalid Ack (or no Ack) http
Mar 1 01:22:12.763: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6
Mar 1 01:22:14.363: CBAC* sis 66F0A118 pak 663FE6F4 SIS_OPEN/ESTAB TCP ACK 590262754 SEQ 1282798700 LEN 0 (10.0.34.4:21143) => (10.0.12.1:80)
Mar 1 01:22:14.363: CBAC* sis 66F0A118 L4 inspect result: DROP packet 663FE6F4 (10.0.34.4:21143) (10.0.12.1:80) bytes 0 ErrStr = Invalid Ack (or no Ack) http
Mar 1 01:22:14.367: CBAC* Details of Pak 663FE6F4 IP: s=10.0.34.4 (Serial0/1), d=10.0.12.1 (Serial0/0), len 44, proto=6

25 seconds after R3 received the second unfragmented packet from R1, we see the following log messages:

Mar 1 01:22:35.619: CBAC: Responder's OOO Idle timeout handler with Session 66F0A118
Mar 1 01:22:35.619: CBAC: TCP OOO timeout handling method called for session 66F0A118
Mar 1 01:22:35.619: CBAC: OOO queue timer exceeded the retry threshold. Deleting the session 66F0A118
Mar 1 01:22:35.623: %FW-6-SESS_AUDIT_TRAIL: Stop http session: initiator (10.0.34.4:21143) sent 127 bytes -- responder (10.0.12.1:80) sent 248 bytes
Mar 1 01:22:35.627: %FW-4-TCP_OoO_SEG: Deleting session as expected TCP segment with seq:590243826 has not arrived even after 25 seconds - session 10.0.34.4:21143 to 10.0.12.1:80

R3 deletes the session from it’s state table because the expected out-of-order segments have not arrived.  The sequence number of the first 292-byte unfragmented packet was 590,243,578; subtracting HDLC, IP, and TCP headers leaves 248 bytes of data, which explains why R3 was still looking for 590,243,826.  The audit trail log message also proves that CBAC did not inspect initial fragments, as it believes R1 sent 248 bytes of data when in fact it has sent about 19,000 bytes.  Let’s enable virtual fragmentation reassembly on R3 S0/0 and try the transfer again:

R3:
interface Serial0/0
 ip virtual-reassembly

R4#copy http://10.0.12.1/asdf.txt null:
Loading http://10.0.12.1/asdf.txt !!
255324 bytes copied in 17.828 secs (14322 bytes/sec)

R3 is now able to inspect the reassembled packets correctly and the transfer completes successfully. An example of reassmbled packet being inspected by R3 is shown below:

R3#debug ip inspect protocol tcp
Mar 1 02:27:42.155: CBAC sis 66F0A118 pak 6678EDF8 SIS_OPEN/ESTAB TCP ACK 168810932 SEQ 1043666778 LEN 536 (10.0.12.1:80) <= (10.0.34.4:53749)
Mar 1 02:27:42.159: CBAC sis 66F0A118 http L7 inspect result: PASS packet
Mar 1 02:27:42.159: CBAC sis 66F0A118 http L7 inspect result: PASS packet
Mar 1 02:27:42.159: CBAC Details of Pak 6678EDF8 IP: s=10.0.12.1 (Serial0/0), d=10.0.34.4 (Serial0/1), len 304, proto=6
Mar 1 02:27:42.159: CBAC: pak seq = 1043666778, rcvwnd = 4001 rcvnxt = 168810932

As shown by the debug, the 536-byte reassembled TCP segment is inspected, which results in both fragments being forwarded.  The reassembled packet is then dropped.

 

Next we will try a TFTP transfer.  Virtual fragmentation reassembly has been disabled again on R3:

R4#copy tftp://10.0.12.1/asdf.txt null:
Accessing tftp://10.0.12.1/asdf.txt...
Loading asdf.txt from 10.0.12.1 (via Serial0/0): !... [timed out]
%Error reading tftp://10.0.12.1/asdf.txt (Timed out)

The start of the transfer in Wireshark is shown below:

8-Wireshark

The transfer appears to be working in both directions.  Notice that every single packet from R1 gets fragmented by R2 since they are all a fixed size.  Since CBAC does not examine fragmented packets, it does not even see an initial response from R1.  The session remains in the SIS_OPENING state and R3 has a pre-generated session in the state table where it is still waiting for a response from R1 on a port above 1023:

7-R3-Show-IP-Inspect

The transfer continues to work until the UDP session timeout expires (30 seconds by default).  At this point, the session is deleted and the fragmented packets are dropped since their L3 information does not match anything in the session table:

Mar 1 03:57:50.927: %FW-6-SESS_AUDIT_TRAIL: Stop tftp session: initiator (10.0.34.4:63208) sent 17 bytes -- responder (10.0.12.1:69) sent 0 bytes

9-Wireshark

Let’s try it again with virtual fragmentation reassembly enabled on R3 S0/0:

R3:
interface Serial0/0
 ip virtual-reassembly 

R4#copy tftp://10.0.12.1/asdf.txt null:
Accessing tftp://10.0.12.1/asdf.txt...
Loading asdf.txt from 10.0.12.1 (via Serial0/0): !
[OK - 255324 bytes]
255324 bytes copied in 159.280 secs (1603 bytes/sec)

R3#debug ip inspect protocol udp
R3#debug ip inspect protocol tftp
Mar 1 03:20:25.211: CBAC UDP: sis 66F09E40 pak 66F554A0 SIS_OPEN UDP packet (10.0.12.1:50791) => (10.0.34.4:65521) datalen 516
Mar 1 03:20:25.215: TFTP DATA Channel 66F09E40 state SIS_OPEN
Mar 1 03:20:25.215: TFTP Code : DATA, packet length : 516
Mar 1 03:20:25.215: CBAC sis 66F09E40 tftp-data L7 inspect result: PASS packet
Mar 1 03:20:25.423: CBAC* UDP: sis 66F09E40 pak 663FE6F4 SIS_OPEN UDP packet (10.0.12.1:50791) <= (10.0.34.4:65521) datalen 4
Mar 1 03:20:25.423: TFTP DATA Channel 66F09E40 state SIS_OPEN
Mar 1 03:20:25.423: TFTP Code : ACK
Mar 1 03:20:25.423: CBAC* sis 66F09E40 tftp-data L7 inspect result: PASS packet

Again, CBAC is now able to correctly inspect the TFTP traffic and the transfer is successful.

 

 

Next we will remove the CBAC configuration and try the same two transfers using the zone-based firewall.  Virtual fragmentation reassembly has also been removed.  The ZBFW configuration on R3 is:

R3:
class-map type inspect match-all tftp
 match protocol tftp
class-map type inspect match-all web
 match protocol http
!
policy-map type inspect asdf
 class type inspect web
  inspect
 class type inspect tftp
  inspect
 class class-default
!
zone security inside
zone security outside
zone-pair security inside-outside source inside destination outside
 service-policy type inspect asdf
!
interface Serial0/0
 zone-member security outside
!
interface Serial0/1
 zone-member security inside

We’ll try the HTTP transfer first:

R4#copy http://10.0.12.1/asdf.txt null:
Loading http://10.0.12.1/asdf.txt !
%Error reading http://10.0.12.1/asdf.txt (Broken pipe)

The transfer fails.  I’m not aware of any equivalent debugs for ZBFW that show per-packet information and inspection results, but Wireshark is sufficient for finding the problem.  Edit: I found out afterward that CBAC debugs will also work for ZBFW.  Shown below is a capture on R3 S0/1 followed by a capture on R3 S0/0:

11-Wireshark

10-Wireshark

Every packet in the transfer is the same on each interface up until #139 on S0/1, at 13:40:47.135.  This ACK is never seen on R3 S0/0.  Instead, we see only traffic coming from R1 after this point.  The sequence number in every packet sent by R1 after this point is 1,590,239,484 and the acknowledgement number sent by R4 is 1,590,242,700, which also indicates that R4 is receiving data from R1 but R1 is not receiving ACKs from R4.  In the sessions table, we see the exact same number of bytes sent in each direction as we saw for the HTTP transfer with CBAC:

12-R3-ZBFW

The problem is the same that we had with CBAC.  Fragmented packets are not examined, and R3 therefore believes that R4 is sending invalid ACKs and begins dropping them.  Like before, enabling virtual fragmentation reassembly fixes the problem:

R3:
interface Serial0/0
 ip virtual-reassembly

The transfer now works, and R3 shows the correct number of bytes transferred in the session:

R4#copy http://10.0.12.1/asdf.txt null:
Loading http://10.0.12.1/asdf.txt !!
255324 bytes copied in 15.232 secs (16762 bytes/sec)

Mar 1 04:07:48.907: %FW-6-SESS_AUDIT_TRAIL: Stop http session: initiator (10.0.34.4:60779) sent 127 bytes -- responder (10.0.12.1:80) sent 255572 bytes

 

 

Next we will try the TFTP transfer with virtual fragmentation reassembly disabled:

R4#copy tftp://10.0.12.1/asdf.txt null:
Accessing tftp://10.0.12.1/asdf.txt...
%Error opening tftp://10.0.12.1/asdf.txt (Timed out)

The transfer fails.  Shown below are captures on R3 S0/1 and then R3 S0/0:

14-Wireshark-R3-S1

14-Wireshark-R3-S0

These captures show that the inspection logic used by ZBFW is a little more detailed than CBAC (at least for TFTP).  With ZBFW, none of the acknowledgements from R4 to R1 are allowed because R3 does not believe that it is a valid acknowledgement since it is not aware of R1 sending data.  With CBAC, the acknowledgements were always allowed even though the firewall had not seen the data block that was being acknowledged pass through it.  Therefore the transfer fails almost immediately with the ZBFW, while with CBAC it takes a while and could actually finish if the transfer completes before the UDP timeout expires.  Once again enabling virtual fragmentation reassembly fixes the problem:

R3:
interface Serial0/0
 ip virtual-reassembly

R4#copy tftp://10.0.12.1/asdf.txt null:
Accessing tftp://10.0.12.1/asdf.txt...
Loading asdf.txt from 10.0.12.1 (via Serial0/0): !
[OK - 255324 bytes]
255324 bytes copied in 146.804 secs (1739 bytes/sec)

 

 

Next we will look at some of the types of invalid fragments and fragment attacks that virtual fragmentation reassembly can prevent as well as some of it’s configurable settings.  The ZBFW configuration has been removed from R3.  Colasoft Packet Builder will be used to send packets from a PC at 10.1.1.10 connected to R1 to R4.  First, a correctly fragmented ICMP echo with 100 bytes of data will be sent.  The ICMP echo is sent in 2 fragments 1 second apart, the first containing the 8-byte ICMP header and 80 bytes of data with the More Fragments flag set, and the second containing the last 20 bytes of data and a Fragment Offset of 11 (88 octets).

R3:
interface Serial0/0
 ip virtual-reassembly

First fragment:

15-Colasoft-1

Second fragment:

15-Colasoft-2

R3#debug ip virtual-reassembly
Mar 1 00:24:47.747: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:0, offset:0, len:88) in fast path...
Mar 1 00:24:47.747: IP_VFR: created frag state for sa:10.1.1.10, da:10.0.34.4, id:0...
Mar 1 00:24:47.747: IP_VFR: pak incomplete cpak-offset:0, cpak-len:88, flag: 1
Mar 1 00:24:47.747: IP_VFR: dgrm incomplete, returning...
Mar 1 00:24:48.747: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:0, offset:88, len:20) in fast path...
Mar 1 00:24:48.747: IP_VFR: cpak-offset:0, cpak-len:88, npak-offset:88
Mar 1 00:24:48.747: IP_VFR: dgrm complete, switching the frags.
Mar 1 00:24:48.747: IP_VFR: switching fragment (sa:10.1.1.10, da:10.0.34.4, id:0, offset:0, len:88)
Mar 1 00:24:48.751: IP VFR:Enqueing packet to IP queue
Mar 1 00:24:48.751: IP_VFR: switching fragment (sa:10.1.1.10, da:10.0.34.4, id:0, offset:88, len:20)
Mar 1 00:24:48.751: IP VFR:Enqueing packet to IP queue
Mar 1 00:24:48.751: IP_VFR: all fragments have been switched.
Mar 1 00:24:48.755: IP_VFR: pak_subblock_free - pak 0x667907E4
Mar 1 00:24:48.759: IP_VFR: deleted frag state for sa:10.1.1.10, da:10.0.34.4, id:0
Mar 1 00:24:48.759: IP_VFR: pak_subblock_free - pak 0x6678AB50

R4#debug ip packet detail
Mar 1 00:24:48.843: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 00:24:48.843: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 108, rcvd 3
Mar 1 00:24:48.847: IP Fragment, Ident = 0, fragment offset = 0
Mar 1 00:24:48.847: ICMP type=8, code=0
Mar 1 00:24:48.847: IP: recv fragment from 10.1.1.10 offset 0 bytes
Mar 1 00:24:48.871: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 00:24:48.871: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 40, rcvd 3
Mar 1 00:24:48.875: IP Fragment, Ident = 0, fragment offset = 88
Mar 1 00:24:48.875: IP: recv fragment from 10.1.1.10 offset 88 bytes
Mar 1 00:24:48.875: IP: tableid=0, s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), routed via FIB
Mar 1 00:24:48.875: IP: s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), len 128, sending
Mar 1 00:24:48.879: ICMP type=0, code=0

The fragments pass virtual reassembly on R3 and R4 is able to reassemble the ICMP echo and send an unfragmented reply.  We can also see that although the fragments arrive 1 second apart at R3, they arrive almost simultaneously at R4 because R3 does not forward any of the fragments until it has received all of them and verified that they are valid.  Let’s try lowering the fragment offset of the second fragment from 11 (88 octects) to 10 (80 octets) so that part of the data in the second fragment overlaps the first fragment:

16-Colasoft-1

16-Colasoft-2

R3#debug ip virtual-reassembly
Mar 1 00:37:50.339: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:0, offset:0, len:88) in fast path...
Mar 1 00:37:50.339: IP_VFR: created frag state for sa:10.1.1.10, da:10.0.34.4, id:0...
Mar 1 00:37:50.339: IP_VFR: pak incomplete cpak-offset:0, cpak-len:88, flag: 1
Mar 1 00:37:50.339: IP_VFR: dgrm incomplete, returning...
Mar 1 00:37:51.303: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:0, offset:80, len:20) in fast path...
Mar 1 00:37:51.303: IP_VFR: cpak-offset:0, cpak-len:88, npak-offset:80
Mar 1 00:37:51.303: %IP_VFR-3-OVERLAP_FRAGMENTS: Serial0/0: from the host 10.1.1.10 destined to 10.0.34.4
Mar 1 00:37:51.307: IP_VFR: err while checking for compltns of dgrm
Mar 1 00:37:51.307: IP_VFR: deleted frag state for sa:10.1.1.10, da:10.0.34.4, id:0

R3 generates a log message reporting the overlapping fragments and drops them both without forwarding them to R4. 

 

Another type of attack that could be performed is sending several incomplete fragments.  With VFR disabled on R3 S0/0, we will send 5 different copies of the second fragment from the previous example, each with a different IP Identification number:

R4#debug ip packet detail
Mar 1 00:59:10.395: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 00:59:10.395: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 40, rcvd 3
Mar 1 00:59:10.399: IP Fragment, Ident = 1, fragment offset = 80
Mar 1 00:59:10.399: IP: recv fragment from 10.1.1.10 offset 80 bytes
Mar 1 00:59:11.403: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 00:59:11.403: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 40, rcvd 3
Mar 1 00:59:11.407: IP Fragment, Ident = 2, fragment offset = 80
Mar 1 00:59:11.407: IP: recv fragment from 10.1.1.10 offset 80 bytes
Mar 1 00:59:12.447: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 00:59:12.447: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 40, rcvd 3
Mar 1 00:59:12.447: IP Fragment, Ident = 3, fragment offset = 80
Mar 1 00:59:12.451: IP: recv fragment from 10.1.1.10 offset 80 bytes
Mar 1 00:59:13.403: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 00:59:13.403: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 40, rcvd 3
Mar 1 00:59:13.407: IP Fragment, Ident = 4, fragment offset = 80
Mar 1 00:59:13.407: IP: recv fragment from 10.1.1.10 offset 80 bytes
Mar 1 00:59:14.419: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 00:59:14.419: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 40, rcvd 3
Mar 1 00:59:14.423: IP Fragment, Ident = 5, fragment offset = 80
Mar 1 00:59:14.423: IP: recv fragment from 10.1.1.10 offset 80 bytes

R4 receives all the fragments and holds them in memory while waiting for the other fragments.  After about 40 seconds, they have not arrived so R4 sends an ICMP Fragmentation Reassembly Time Exceeded message back to R1 for each fragment:

R4#debug ip packet detail
Mar 1 00:59:51.563: IP: tableid=0, s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), routed via FIB
Mar 1 00:59:51.563: IP: s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), len 56, sending
Mar 1 00:59:51.563: ICMP type=11, code=1
Mar 1 00:59:51.567: IP: tableid=0, s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), routed via FIB
Mar 1 00:59:51.567: IP: s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), len 56, sending
Mar 1 00:59:51.571: ICMP type=11, code=1
Mar 1 00:59:51.571: IP: tableid=0, s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), routed via FIB
Mar 1 00:59:51.571: IP: s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), len 56, sending
Mar 1 00:59:51.575: ICMP type=11, code=1
Mar 1 00:59:51.575: IP: tableid=0, s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), routed via FIB
Mar 1 00:59:51.575: IP: s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), len 56, sending
Mar 1 00:59:51.579: ICMP type=11, code=1
Mar 1 00:59:51.579: IP: tableid=0, s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), routed via FIB
Mar 1 00:59:51.579: IP: s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), len 56, sending
Mar 1 00:59:51.583: ICMP type=11, code=1

This results in wasted resources on R4 as well as wasted bandwidth on the R3-R4 link.  With VFR on R3, the fragments would never have been forwarded because the remaining fragments never arrived.  The timeout and max-reassemblies options can be used to tune the amount of resources that VFR uses for this.  We will set a maximum of 3 reassemblies and a timeout of 10 seconds and send the same 5 non-initial fragments again:

R3:
interface Serial0/0
 ip virtual-reassembly max-reassemblies 3 timeout 10

R3#debug ip virtual-reassembly
Mar 1 01:19:05.111: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:1, offset:80, len:20) in fast path...
Mar 1 01:19:05.111: IP_VFR: created frag state for sa:10.1.1.10, da:10.0.34.4, id:1...
Mar 1 01:19:05.111: IP_VFR: dgrm incomplete, returning...
Mar 1 01:19:06.123: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:2, offset:80, len:20) in fast path...
Mar 1 01:19:06.123: IP_VFR: created frag state for sa:10.1.1.10, da:10.0.34.4, id:2...
Mar 1 01:19:06.123: IP_VFR: dgrm incomplete, returning...
Mar 1 01:19:07.095: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:3, offset:80, len:20) in fast path...
Mar 1 01:19:07.095: IP_VFR: created frag state for sa:10.1.1.10, da:10.0.34.4, id:3...
Mar 1 01:19:07.095: IP_VFR: dgrm incomplete, returning...
Mar 1 01:19:08.151: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:4, offset:80, len:20) in fast path...
Mar 1 01:19:08.151: %IP_VFR-4-FRAG_TABLE_OVERFLOW: Serial0/0: the fragment table has reached its maximum threshold 3
Mar 1 01:19:09.135: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:5, offset:80, len:20) in fast path...
Mar 1 01:19:15.111: IP VFR: frag state expired -src-addr:10.1.1.10, dst-addr:10.0.34.4, ip-id:1...
Mar 1 01:19:15.111: IP_VFR: deleted frag state for sa:10.1.1.10, da:10.0.34.4, id:1
Mar 1 01:19:16.123: IP VFR: frag state expired -src-addr:10.1.1.10, dst-addr:10.0.34.4, ip-id:2...
Mar 1 01:19:16.123: IP_VFR: deleted frag state for sa:10.1.1.10, da:10.0.34.4, id:2
Mar 1 01:19:17.095: IP VFR: frag state expired -src-addr:10.1.1.10, dst-addr:10.0.34.4, ip-id:3...
Mar 1 01:19:17.095: IP_VFR: deleted frag state for sa:10.1.1.10, da:10.0.34.4, id:3

The first three fragments arrive and are stored in memory for reassembly.  When the fourth fragment arrives, the max-reassemblies threshold is exceeded and a log message is generated, and the fourth and fifth fragments are dropped.  After 10 seconds, the first three fragments are also dropped since they have not been fully reassembled yet. 

 

The max-fragments option controls the max amount of fragments allowed for a single datagram.  To test this out we will first disable VFR on R3 and send an ICMP echo to R4 that is split into 4 fragments.  The first fragment contains the 8-byte ICMP header and the remaining 3 fragments each contain 8 bytes of data.  First fragment:

17-Colasoft-1

Second fragment:

17-Colasoft-2

Third fragment:

17-Colasoft-3

Fourth fragment:

17-Colasoft-4

R4 reassembles the fragments and sends a 52-byte reply (20B IP header + 8B ICMP header + 24B of data):

R4#debug ip packet detail
Mar 1 01:43:28.883: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 01:43:28.883: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 28, rcvd 3
Mar 1 01:43:28.883: IP Fragment, Ident = 1, fragment offset = 0
Mar 1 01:43:28.887: ICMP type=8, code=0
Mar 1 01:43:28.887: IP: recv fragment from 10.1.1.10 offset 0 bytes
Mar 1 01:43:29.851: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 01:43:29.851: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 28, rcvd 3
Mar 1 01:43:29.855: IP Fragment, Ident = 1, fragment offset = 8
Mar 1 01:43:29.855: IP: recv fragment from 10.1.1.10 offset 8 bytes
Mar 1 01:43:30.831: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 01:43:30.835: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 28, rcvd 3
Mar 1 01:43:30.835: IP Fragment, Ident = 1, fragment offset = 16
Mar 1 01:43:30.835: IP: recv fragment from 10.1.1.10 offset 16 bytes
Mar 1 01:43:31.855: IP: tableid=0, s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), routed via RIB
Mar 1 01:43:31.855: IP: s=10.1.1.10 (Serial0/0), d=10.0.34.4 (Serial0/0), len 28, rcvd 3
Mar 1 01:43:31.859: IP Fragment, Ident = 1, fragment offset = 24
Mar 1 01:43:31.859: IP: recv fragment from 10.1.1.10 offset 24 bytes
Mar 1 01:43:31.859: IP: tableid=0, s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), routed via FIB
Mar 1 01:43:31.859: IP: s=10.0.34.4 (local), d=10.1.1.10 (Serial0/0), len 52, sending
Mar 1 01:43:31.863: ICMP type=0, code=0

Let’s try it again with VFR configured on R3 for a max of 2 fragments per datagram:

R3:
interface Serial0/0
 ip virtual-reassembly max-fragments 2 timeout 10

R3#debug ip virtual-reassembly
Mar 1 01:45:18.091: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:1, offset:0, len:8) in fast path...
Mar 1 01:45:18.091: IP_VFR: created frag state for sa:10.1.1.10, da:10.0.34.4, id:1...
Mar 1 01:45:18.091: IP_VFR: pak incomplete cpak-offset:0, cpak-len:8, flag: 1
Mar 1 01:45:18.091: IP_VFR: dgrm incomplete, returning...
Mar 1 01:45:19.055: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:1, offset:8, len:8) in fast path...
Mar 1 01:45:19.055: IP_VFR: cpak-offset:0, cpak-len:8, npak-offset:8
Mar 1 01:45:19.059: IP_VFR: pak incomplete cpak-offset:8, cpak-len:8, flag: 1
Mar 1 01:45:19.059: IP_VFR: dgrm incomplete, returning...
Mar 1 01:45:20.087: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:1, offset:16, len:8) in fast path...
Mar 1 01:45:20.087: %IP_VFR-4-TOO_MANY_FRAGMENTS: Serial0/0: Too many fragments per datagram (more than 2) - sent by 10.1.1.10, destined to 10.0.34.4
Mar 1 01:45:20.087: IP_VFR: deleted frag state for sa:10.1.1.10, da:10.0.34.4, id:1
Mar 1 01:45:21.087: IP_VFR: fragment (sa:10.1.1.10, da:10.0.34.4, id:1, offset:24, len:8) in fast path...
Mar 1 01:45:21.091: IP_VFR: created frag state for sa:10.1.1.10, da:10.0.34.4, id:1...
Mar 1 01:45:21.091: IP_VFR: dgrm incomplete, returning...
Mar 1 01:45:31.091: IP VFR: frag state expired -src-addr:10.1.1.10, dst-addr:10.0.34.4, ip-id:1...
Mar 1 01:45:31.091: IP_VFR: deleted frag state for sa:10.1.1.10, da:10.0.34.4, id:1

When the third fragment is received, R3 drops all three fragments and generates a log message that too many fragments were received for the datagram.  The fourth fragment arrives a second later and R3 creates a new entry for it.  Since the first three fragments were already dropped and the datagram cannot be reassembled, the fourth fragment ends up getting dropped 10 seconds later when the timeout expires.

 

Finally, VFR can also be configured to drop all incoming fragments on an interface whether or not they are part of a valid datagram with the drop-fragments option.  The same 4 fragments are sent again 1 second apart:

R3:
interface Serial0/0
 ip virtual-reassembly drop-fragments

R3#debug ip virtual-reassembly
Mar 1 01:55:49.911: IP_VFR: in drop mode
Mar 1 01:55:50.887: IP_VFR: in drop mode
Mar 1 01:55:51.919: IP_VFR: in drop mode
Mar 1 01:55:52.883: IP_VFR: in drop mode

Posted in Security | Leave a Comment »

Policy Based Routing ‘set’ Commands

Posted by Andy on May 29, 2009

Here we will look at the various set commands that can be used in PBR and some of the differences between them.  The topology and configurations for this example are shown below:

PBR topology2

R1:
interface Loopback1
 ip address 1.1.1.1 255.255.255.255
!
interface Loopback2
 ip address 1.1.1.2 255.255.255.255
!
interface Serial0/0
 ip address 10.0.12.1 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 10.0.12.2

R2:
no ip cef
!
interface FastEthernet0/0
 ip address 10.0.234.2 255.255.255.0
 no ip route-cache
!
interface Serial0/0
 encapsulation frame-relay
 no ip route-cache
!
interface Serial0/0.1 point-to-point
 ip address 10.1.23.2 255.255.255.0
 no ip route-cache
 frame-relay interface-dlci 101
!
interface Serial0/0.2 point-to-point
 ip address 10.2.23.2 255.255.255.0
 no ip route-cache
 frame-relay interface-dlci 102
!
interface Serial0/0.3 point-to-point
 ip address 10.3.23.2 255.255.255.0
 no ip route-cache
 frame-relay interface-dlci 103
!
interface Serial0/0.4 point-to-point
 ip address 10.4.23.2 255.255.255.0
 no ip route-cache
 frame-relay interface-dlci 104
!
interface Serial0/0.5 point-to-point
 ip address 10.5.23.2 255.255.255.0
 no ip route-cache
 frame-relay interface-dlci 105
!
interface Serial0/0.6 point-to-point
ip address 10.6.23.2 255.255.255.0
no ip route-cache
frame-relay interface-dlci 106
!
interface Serial0/0.7 point-to-point
ip address 10.7.23.2 255.255.255.0
no ip route-cache
frame-relay interface-dlci 107
!
interface Serial0/1
 ip address 10.0.12.2 255.255.255.0
 no ip route-cache

!
ip route 1.1.1.0 255.255.255.0 10.0.12.1

R3:
interface FastEthernet0/0
 ip address 10.0.234.3 255.255.255.0
!
interface Serial0/0
 encapsulation frame-relay
!
interface Serial0/0.1 point-to-point
 ip address 10.1.23.3 255.255.255.0
 frame-relay interface-dlci 101
!
interface Serial0/0.2 point-to-point
 ip address 10.2.23.3 255.255.255.0
 frame-relay interface-dlci 102
!
interface Serial0/0.3 point-to-point
 ip address 10.3.23.3 255.255.255.0
 frame-relay interface-dlci 103
!
interface Serial0/0.4 point-to-point
 ip address 10.4.23.3 255.255.255.0
 frame-relay interface-dlci 104
!
interface Serial0/0.5 point-to-point
 ip address 10.5.23.3 255.255.255.0
 frame-relay interface-dlci 105
!
interface Serial0/0.6 point-to-point
ip address 10.6.23.3 255.255.255.0
frame-relay interface-dlci 106
!
interface Serial0/0.7 point-to-point
ip address 10.7.23.3 255.255.255.0
frame-relay interface-dlci 107
!
interface FastEthernet0/1
 ip address 10.0.34.3 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 10.0.234.2

R4:
interface FastEthernet0/0
 ip address 10.0.234.4 255.255.255.0
!
interface FastEthernet0/1
 ip address 10.0.34.4 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 10.0.234.2

R2 will policy route packets received from R1.  CEF and fast switching have been disabled on R2 so that all packets can be seen in debug output.  First we will configure PBR on R2 to route traffic sourced from R1 loopback#1 out F0/0 to R3 using set ip next-hop:

R2:
access-list 1 permit 1.1.1.1
!
route-map pbr permit 10
 match ip address 1
 set ip next-hop 10.0.234.3
!
interface Serial0/1
 ip policy route-map pbr

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet

Mar 1 00:31:18.031: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:31:18.031: IP: route map pbr, item 10, permit
Mar 1 00:31:18.035: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 00:31:18.035: IP: Serial0/1 to FastEthernet0/0 10.0.234.3
Mar 1 00:31:18.035: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.234.3, len 100, forward

The packet is forwarded as expected using the next-hop address in the route-map.  Next let’s configure R2 to route packets from R1 loopback#2 out F0/0 to R3 using set ip default next-hop:

R2:
access-list 2 permit 1.1.1.2
!
route-map pbr permit 20
 match ip address 2
 set ip default next-hop 10.0.234.3

R1#ping 10.0.34.3 repeat 1 source loopback2

R2#debug ip policy
R2#debug ip packet
Mar 1 00:36:03.479: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:36:03.479: IP: route map pbr, item 20, permit
Mar 1 00:36:03.483: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 00:36:03.483: IP: Serial0/1 to FastEthernet0/0 10.0.234.3
Mar 1 00:36:03.483: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.234.3, len 100, forward

So far the results of each look the same.  The difference between adding the default keyword is the order of operations that is used.  Without default, the router first attempts to route using PBR.  If there is no match or a match on a deny statement the router then uses the normal forwarding process.  With the default keyword, the router instead attempts to use the routing table first and if no route can be found then tries PBR.  Let’s add a static route to 10.0.34.0/24 to demonstrate this:

R2:
ip route 10.0.34.0 255.255.255.0 Serial0/0.1

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet
Mar 1 00:48:56.915: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), routed via RIB
Mar 1 00:48:56.915: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:48:56.915: IP: route map pbr, item 10, permit
Mar 1 00:48:56.915: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 00:48:56.919: IP: Serial0/1 to FastEthernet0/0 10.0.234.3
Mar 1 00:48:56.919: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.234.3, len 100, forward

R1#ping 10.0.34.3 repeat 1 source loopback2

R2#debug ip policy
R2#debug ip packet

Mar 1 00:49:08.239: IP: tableid=0, s=1.1.1.2 (Serial0/1), d=10.0.34.3 (Serial0/0.1), routed via RIB
Mar 1 00:49:08.239: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:49:08.239: IP: route map pbr, item 20, permit
Mar 1 00:49:08.243: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3 (Serial0/0.1), len 100, policy rejected -- normal forwarding
Mar 1 00:49:08.243: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3 (Serial0/0.1), g=10.0.34.3, len 100, forward

R2 now forwards traffic from R1 loopback #2 out S0/0.1 as specified by the routing table instead of using PBR.  Traffic from R1 loopback #1 continues to be sent out F0/0.

 

Next we will change the route-map statements to use an interface rather than a next-hop address.  The default keyword can also be used when setting an interface, and it has the same effect that we just saw of changing the order of operation.  Traffic from R1 loopback #1 will use set interface and traffic from R1 loopback #2 will use set default interface.  We will use F0/0 as the exit interface to demonstrate the problems that can occur when using a multiaccess network in a set interface statement.  We will also remove the static route to 10.0.34.0/24 that we created previously:

R2:
route-map pbr permit 10
 no set ip next-hop 10.0.234.3
 set interface FastEthernet0/0
!
route-map pbr permit 20
 no set ip default next-hop 10.0.234.3
 set default interface FastEthernet0/0
!
no ip route 10.0.34.0 255.255.255.0 Serial0/0.1

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet

Mar 1 00:56:06.603: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:56:06.603: IP: route map pbr, item 10, permit
Mar 1 00:56:06.603: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy rejected -- normal forwarding
Mar 1 00:56:06.607: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, unroutable

R1#ping 10.0.34.3 repeat 1 source loopback2

R2#debug ip policy
R2#debug ip packet

Mar 1 00:56:10.923: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:56:10.923: IP: route map pbr, item 20, permit
Mar 1 00:56:10.923: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 00:56:10.927: IP: Serial0/1 to FastEthernet0/0 10.0.34.3
Mar 1 00:56:10.927: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.34.3, len 100, forward
Mar 1 00:56:10.931: IP: s=1.1.1.2 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, encapsulation failed

Both pings fail.  Interestingly, each fails for a different reason and gives a different ping response output.  The ping from loopback #1 (using set interface) attempts to use PBR first.  Finding no L2 address to use for 10.0.34.3 on F0/0, PBR rejects the packet and attempts to use normal forwarding.  No matching route exists so the packet is dropped and an ICMP unreachable is sent to R1.  The ping from loopback #2 (using set default interface) attempts to use the route table first.  No route to the destination exists so R2 next tries PBR.  PBR does not know what L2 address to use for 10.0.34.3 on F0/0 so it generates an ‘encapsulation failed’ message and simply drops the packet with no notification to R1.  Let’s put a static route back on R2 using an outgoing interface of F0/0 in the static route:

R2:
ip route 10.0.34.0 255.255.255.0 FastEthernet0/0

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet

Mar 1 01:14:02.179: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), routed via RIB
Mar 1 01:14:02.179: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 01:14:02.183: IP: route map pbr, item 10, permit
Mar 1 01:14:02.183: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 01:14:02.183: IP: Serial0/1 to FastEthernet0/0 10.0.34.3
Mar 1 01:14:02.187: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.34.3, len 100, forward
Mar 1 01:14:02.191: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, encapsulation failed

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet

Mar 1 01:14:21.887: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), routed via RIB
Mar 1 01:14:21.887: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 01:14:21.891: IP: route map pbr, item 10, permit
Mar 1 01:14:21.891: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 01:14:21.891: IP: Serial0/1 to FastEthernet0/0 10.0.34.3
Mar 1 01:14:21.891: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.34.3, len 100, forward

The first ping from loopback #1 fails again.  This time, however, when the normal forwarding process finds a match for the static route with an outgoing interface of F0/0, it sends an ARP for 10.0.34.3 which is answered with proxy ARP by R3.  The next ping is policy routed using the ARP cache entry.  This combined with the behavior that we saw when no route existed in the routing table shows that PBR does not even attempt to perform address resolution by itself on a multiaccess network, but if the L2 address is known (either from normal forwarding or a static entry), PBR will make use of it and successfully route the packet.

 

Both set ip next-hop and set ip default next-hop require that the next-hop be found on a directly connected subnet (PBR will fail if it is not and the next set statement or normal forwarding will be used).  With set ip next-hop recursive, the next-hop address does not need to be directly connected.  Instead a recursive lookup is performed (if necessary) on the next-hop address, and matching traffic is forwarded to the next-hop(s) used by that route entry according to the switching path in use on the router.  A benefit of this is that load balancing can be used.  Since we are using process switching, load balancing will take place per packet.  We will create a loopback on R3 and multiple static routes to it on R2.  We will then set the recursive next-hop address to R3’s loopback.  The static route left over from before will also be removed:

R3:
interface Loopback3
 ip address 3.3.3.3 255.255.255.0

R2:
no ip route 10.0.34.0 255.255.255.0 FastEthernet0/0
ip route 3.3.3.0 255.255.255.0 10.1.23.3
ip route 3.3.3.0 255.255.255.0 10.2.23.3
ip route 3.3.3.0 255.255.255.0 10.3.23.3
!
route-map pbr permit 10
 no set interface FastEthernet0/0
 set ip next-hop recursive 3.3.3.3

1-R2-Route-Table

Note: Using a recursive lookup with PBR to send traffic to a route entry does not count as a “turn” for that path in the load-balancing equation if the destination address is outside the range of the route.  If no traffic is ever sent to the actual destination of the route, all PBR traffic will be sent to the path that is next in line, and no load-balancing will occur.  Therefore to demonstrate load-balancing, a packet is sent to 3.3.3.3 in between each packet from R1 loopback #1.

R1#ping 10.0.34.3 repeat 1 source loopback1
R1#ping 3.3.3.3 repeat 1 source s0/0
R1#ping 10.0.34.3 repeat 1 source loopback1
R1#ping 3.3.3.3 repeat 1 source s0/0
R1#ping 10.0.34.3 repeat 1 source loopback1
R1#ping 3.3.3.3 repeat 1 source s0/0
R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet
Mar 1 01:46:47.595: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 01:46:47.595: IP: route map pbr, item 10, permit
Mar 1 01:46:47.599: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.3), len 100, policy routed
Mar 1 01:46:47.599: IP: Serial0/1 to Serial0/0.3 10.3.23.3
Mar 1 01:46:47.599: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.3), g=10.3.23.3, len 100, forward

 

Mar 1 01:47:06.951: IP: tableid=0, s=10.0.12.1 (Serial0/1), d=3.3.3.3 (Serial0/0.3), routed via RIB
Mar 1 01:47:06.955: IP: s=10.0.12.1 (Serial0/1), d=3.3.3.3 (Serial0/0.3), len 100, policy rejected -- normal forwarding
Mar 1 01:47:06.955: IP: s=10.0.12.1 (Serial0/1), d=3.3.3.3 (Serial0/0.3), g=10.3.23.3, len 100, forward

 

Mar 1 01:47:11.951: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 01:47:11.951: IP: route map pbr, item 10, permit
Mar 1 01:47:11.955: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.2), len 100, policy routed
Mar 1 01:47:11.955: IP: Serial0/1 to Serial0/0.2 10.2.23.3
Mar 1 01:47:11.955: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.2), g=10.2.23.3, len 100, forward

 

Mar 1 01:47:15.055: IP: tableid=0, s=10.0.12.1 (Serial0/1), d=3.3.3.3 (Serial0/0.2), routed via RIB
Mar 1 01:47:15.055: IP: s=10.0.12.1 (Serial0/1), d=3.3.3.3 (Serial0/0.2), len 100, policy rejected -- normal forwarding
Mar 1 01:47:15.055: IP: s=10.0.12.1 (Serial0/1), d=3.3.3.3 (Serial0/0.2), g=10.2.23.3, len 100, forward

 

Mar 1 01:47:17.439: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 01:47:17.439: IP: route map pbr, item 10, permit
Mar 1 01:47:17.439: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), len 100, policy routed
Mar 1 01:47:17.439: IP: Serial0/1 to Serial0/0.1 10.1.23.3
Mar 1 01:47:17.443: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), g=10.1.23.3, len 100, forward

 

Mar 1 01:47:22.635: IP: tableid=0, s=10.0.12.1 (Serial0/1), d=3.3.3.3 (Serial0/0.1), routed via RIB
Mar 1 01:47:22.635: IP: s=10.0.12.1 (Serial0/1), d=3.3.3.3 (Serial0/0.1), len 100, policy rejected -- normal forwarding
Mar 1 01:47:22.639: IP: s=10.0.12.1 (Serial0/1), d=3.3.3.3 (Serial0/0.1), g=10.1.23.3, len 100, forward

 

Mar 1 01:47:24.615: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 01:47:24.615: IP: route map pbr, item 10, permit
Mar 1 01:47:24.615: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.3), len 100, policy routed
Mar 1 01:47:24.619: IP: Serial0/1 to Serial0/0.3 10.3.23.3
Mar 1 01:47:24.619: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.3), g=10.3.23.3, len 100, forward

 

 

Each of the set commands that we have looked at so far with the exception of set ip next-hop recursive allow multiple interfaces or next-hop addresses to be listed in a single set statement.  If the 1st interface (or interface associated with the next-hop address, if a next-hop is used) is down or L2 address is unknown, the rest of the interfaces/addresses in the list are tried in order.  Let’s look at an example using set interface.  We will have R2 attempt to route traffic from R1 loopback #1 out S0/0.1, then F0/0, then S0/0.2.  All previous static routes and set commands have also been removed:

R2:
route-map pbr permit 10
 set interface Serial0/0.1 FastEthernet0/0 Serial0/0.2

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet

Mar 1 02:28:19.723: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:28:19.723: IP: route map pbr, item 10, permit
Mar 1 02:28:19.727: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), len 100, policy routed
Mar 1 02:28:19.727: IP: Serial0/1 to Serial0/0.1 10.0.34.3
Mar 1 02:28:19.727: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), g=10.0.34.3, len 100, forward

R2:
interface Serial0/0.1 point-to-point
 shutdown

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet

Mar 1 02:29:07.211: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:29:07.211: IP: route map pbr, item 10, permit
Mar 1 02:29:07.211: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.2), len 100, policy routed
Mar 1 02:29:07.215: IP: Serial0/1 to Serial0/0.2 10.0.34.3
Mar 1 02:29:07.215: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.2), g=10.0.34.3, len 100, forward

R2:
interface Serial0/0.2 point-to-point
 shutdown

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet
Mar 1 02:29:54.835: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:29:54.835: IP: route map pbr, item 10, permit
Mar 1 02:29:54.835: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy rejected -- normal forwarding
Mar 1 02:29:54.839: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, unroutable

The first packet is sent out S0/0.1 since it is the first interface in the list and is up.  When the 2nd packet arrives S0/0.1 is shutdown.  F0/0 is next in the list, but R2 does not know what next-hop address to use so it is skipped also and the 2nd packet is sent out S0/0.2.  When the 3rd packet arrives S0/0.2 is shut down also.  PBR has no interfaces left to try, so the RIB is tried next.  R2 has no route to the destination so it is dropped and an unreachable sent to R1.

 

 

Yet another available command with PBR is set ip next-hop verify-availability.  This can either be used with CDP or object tracking.  We will take a look at it’s use with CDP first.  When used with CDP, reachability to the next-hop is verified by confirming that the device is a CDP neighbor.  To use it in this way, set ip next-hop verify-availability is entered without any arguments.  The set ip next-hop command is also required, which contains the list of next-hop addresses to be verified against the CDP neighbor table.  If only a subset of next-hops should use CDP verification a separate route-map entry must be used for the ones that should not be checked because all set ip next-hop commands are combined into a single line and set ip next-hop verify-availability will enable the CDP verification check for all of them.  Let’s try an example:

R2:
no route-map pbr
route-map pbr permit 10
 set ip next-hop 10.0.234.3
 set ip next-hop verify-availability
!
ip route 10.0.34.0 255.255.255.0 Serial0/0.1

2-R2-CDP

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet
Mar 1 00:22:48.959: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:22:48.959: IP: route map pbr, item 10, permit
Mar 1 00:22:48.959: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 00:22:48.959: IP: Serial0/1 to FastEthernet0/0 10.0.234.3
Mar 1 00:22:48.959: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.234.3, len 100, forward

R2 has an entry for R3 in it’s CDP table and the packet is successfully policy routed to the configured next-hop on F0/0.  Next we will shutdown R3 F0/0:

R3:
interface FastEthernet0/0
 shutdown

After the CDP holdtime for R3 expires it is removed from R2’s CDP neighbors table. When another packet arrives from R1 loopback #1, the CDP verification fails and R2 attempts to use normal routing which results in the packet being sent on S0/0.1:

3-R2-CDP

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet

Mar 1 00:33:43.483: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), routed via RIB
Mar 1 00:33:43.483: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:33:43.483: IP: route map pbr, item 10, permit
Mar 1 00:33:43.483: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), len 100, policy rejected -- normal forwarding
Mar 1 00:33:43.483: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), g=10.0.34.3, len 100, forward

Without using next-hop verification in this example, R2 would not have fallen back to normal routing when R3 F0/0 went down.  Instead R2 would either keep sending traffic to the configured next-hop address unsuccessfully (if the L2 address is known) or keep trying to ARP for 10.0.234.3 (if the L2 address is unknown):

R2:
route-map pbr permit 10
 no set ip next-hop verify-availability
 

4-R2-ARP

R1#ping 10.0.34.3 repeat 2 source loopback1

R2#debug ip policy
R2#debug ip packet
Mar 1 00:53:57.391: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), routed via RIB
Mar 1 00:53:57.391: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:53:57.391: IP: route map pbr, item 10, permit
Mar 1 00:53:57.391: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 00:53:57.395: IP: Serial0/1 to FastEthernet0/0 10.0.234.3
Mar 1 00:53:57.395: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.234.3, len 100, forward
Mar 1 00:53:57.399: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, encapsulation failed
Mar 1 00:53:59.423: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), routed via RIB
Mar 1 00:53:59.423: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 00:53:59.423: IP: route map pbr, item 10, permit
Mar 1 00:53:59.423: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 00:53:59.427: IP: Serial0/1 to FastEthernet0/0 10.0.234.3
Mar 1 00:53:59.427: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.234.3, len 100, forward
Mar 1 00:53:59.431: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, encapsulation failed
 

Using CDP verification can also be used with the default keyword by using a combination of set ip default next-hop and set ip default next-hop verify-availability.  Like the other examples, this reverses the order of operation so that normal routing is attempted first.  The second way to use set ip next-hop verify-availability is with object tracking.  This configuration does not use the addresses listed in set ip next-hop.  Instead a next-hop address, sequence number, and object number are listed as arguments to the set ip next-hop verify-availability command.  Only 1 next-hop can be listed per command but the use of sequence numbers allows multiple next-hops to be used and attempted in order.  The next-hop address is considered reachable if the tracked object is up.  We will create a loopback on R4 and track reachability to it on R2 using an IP SLA:

R4:
interface Loopback4
 ip address 4.4.4.4 255.255.255.0

R2:
ip route 4.4.4.0 255.255.255.0 10.0.234.4
!
ip sla 1
 icmp-echo 4.4.4.4
ip sla schedule 1 life forever start-time now
!
track 1 rtr 1 reachability

Next we will create the route-map on R2.  R2 should send traffic from R1 to R4 whenever R4’s loopback is confirmed as reachable by the SLA:

R2:
no route-map pbr
route-map pbr permit 10
 set ip next-hop verify-availability 10.0.234.4 10 track 1

Let’s test it out:

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet

Mar 1 01:36:25.071: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), routed via RIB
Mar 1 01:36:25.071: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 01:36:25.075: IP: route map pbr, item 10, permit
Mar 1 01:36:25.075: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 01:36:25.075: IP: Serial0/1 to FastEthernet0/0 10.0.234.4
Mar 1 01:36:25.079: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.234.4, len 100, forward

R2 policy routes the packet using the configured next-hop of 10.0.234.4.  Next we will shutdown R4’s loopback:

R4:
interface Loopback4
 shutdown

When the next echo is sent by R2’s SLA, no response is received and the tracked object changes state to down:

Mar 1 01:37:13.487: %TRACKING-5-STATE: 1 rtr 1 reachability Up->Down

If another ping is sent by R1, it does not pass the reachability check by PBR on R2. R2 resorts to normal forwarding and uses the static route out S0/0.1:

R1#ping 10.0.34.3 repeat 1 source loopback1

R2#debug ip policy
R2#debug ip packet

Mar 1 01:37:49.415: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), routed via RIB
Mar 1 01:37:49.415: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 01:37:49.419: IP: route map pbr, item 10, permit
Mar 1 01:37:49.419: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), len 100, policy rejected -- normal forwarding
Mar 1 01:37:49.419: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), g=10.0.34.3, len 100, forward

Using object tracking to verify reachability of a next-hop is not supported with the default keyword in front of it.

 

 

 

PBR can contain multiple set commands within a single route-map sequence number.  If multiple set commands are configured, the order that PBR will attempt them in is:

1. set ip next-hop verify-availability  – with object tracking only

2. set ip next-hop – either alone or with CDP verification

3. set ip next-hop recursive

4. set interface

5. Route table

6. set ip default next-hop – either alone or with CDP verification

7. set default interface

The set commands will automatically be arranged into this order in the configuration regardless of what order they are entered in.  To demonstrate this, we will configure several set commands using each method, with each one using a different exit interface or next-hop.  We will then cause them to fail in order of preference to verify that the next preferred method is used.  Assume that all loopback interfaces on R3 and R4, and all static routes, route-maps, IP SLAs, and tracked objects on R2 have been deleted prior to the configuration below in order to make the configuration easier to follow.  An explanation of why each packet is routed the way that it is is shown at the end:

R3:
interface Loopback3
 ip address 3.3.3.3 255.255.255.0

R4:
interface Loopback4
 ip address 4.4.4.4 255.255.255.255

!
interface Loopback5
 ip address 4.4.4.5 255.255.255.255

R2:
ip route 1.1.1.0 255.255.255.0 10.0.12.1
ip route 3.3.3.0 255.255.255.0 Serial0/0.6
ip route 4.4.4.0 255.255.255.0 10.0.234.4
ip route 10.0.34.0 255.255.255.0 Serial0/0.4
!
ip sla 1
 icmp-echo 4.4.4.4
ip sla 2
 icmp-echo 4.4.4.5
ip sla schedule 1 life forever start-time now
ip sla schedule 2 life forever start-time now
!
track 1 rtr 1 reachability
track 2 rtr 2 reachability
!
route-map pbr permit 10
 set ip next-hop verify-availability 10.0.234.4 100 track 1
 set ip next-hop verify-availability 10.0.234.3 200 track 2
 set ip next-hop 10.7.23.3
 set ip next-hop verify-availability
 set ip next-hop recursive 3.3.3.3
 set interface Serial0/0.5
 set ip default next-hop 10.3.23.3 10.2.23.3
 set ip default next-hop verify-availability
 set default interface Serial0/0.1

 

R1#ping 10.0.34.3 repeat 1 source loopback1

#1
Mar 1 02:08:50.927: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.4), routed via RIB
Mar 1 02:08:50.927: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:08:50.931: IP: route map pbr, item 10, permit
Mar 1 02:08:50.931: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 02:08:50.931: IP: Serial0/1 to FastEthernet0/0 10.0.234.4
Mar 1 02:08:50.935: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.234.4, len 100, forward

R4:
interface Loopback4
 shutdown

#2
Mar 1 02:10:43.883: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.4), routed via RIB
Mar 1 02:10:43.883: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:10:43.887: IP: route map pbr, item 10, permit
Mar 1 02:10:43.887: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), len 100, policy routed
Mar 1 02:10:43.887: IP: Serial0/1 to FastEthernet0/0 10.0.234.3
Mar 1 02:10:43.891: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (FastEthernet0/0), g=10.0.234.3, len 100, forward

R4:
interface Loopback5
 shutdown

#3
Mar 1 02:12:30.903: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.4), routed via RIB
Mar 1 02:12:30.903: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:12:30.903: IP: route map pbr, item 10, permit
Mar 1 02:12:30.907: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.7), len 100, policy routed
Mar 1 02:12:30.907: IP: Serial0/1 to Serial0/0.7 10.7.23.3
Mar 1 02:12:30.907: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.7), g=10.7.23.3, len 100, forward

R2:
interface Serial0/0.7 point-to-point
 shutdown

#4
Mar 1 02:13:05.751: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.4), routed via RIB
Mar 1 02:13:05.751: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:13:05.755: IP: route map pbr, item 10, permit
Mar 1 02:13:05.755: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.6), len 100, policy routed
Mar 1 02:13:05.755: IP: Serial0/1 to Serial0/0.6 3.3.3.3
Mar 1 02:13:05.755: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.6), g=3.3.3.3, len 100, forward

R2:
no ip route 3.3.3.0 255.255.255.0 Serial0/0.6

#5
Mar 1 02:13:35.219: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.4), routed via RIB
Mar 1 02:13:35.219: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:13:35.223: IP: route map pbr, item 10, permit
Mar 1 02:13:35.223: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.5), len 100, policy routed
Mar 1 02:13:35.223: IP: Serial0/1 to Serial0/0.5 10.0.34.3
Mar 1 02:13:35.227: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.5), g=10.0.34.3, len 100, forward

R2:
interface Serial0/0.5 point-to-point
 shutdown

#6
Mar 1 02:13:47.243: IP: tableid=0, s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.4), routed via RIB
Mar 1 02:13:47.243: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:13:47.247: IP: route map pbr, item 10, permit
Mar 1 02:13:47.247: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.4), len 100, policy rejected -- normal forwarding
Mar 1 02:13:47.247: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.4), g=10.0.34.3, len 100, forward

R2:
no ip route 10.0.34.0 255.255.255.0 Serial0/0.4

#7
Mar 1 02:15:58.471: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:15:58.471: IP: route map pbr, item 10, permit
Mar 1 02:15:58.475: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.3), len 100, policy routed
Mar 1 02:15:58.475: IP: Serial0/1 to Serial0/0.3 10.3.23.3
Mar 1 02:15:58.475: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.3), g=10.3.23.3, len 100, forward

R2:
interface Serial0/0.3 point-to-point
 no cdp enable

#8
Mar 1 02:19:05.127: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:19:05.127: IP: route map pbr, item 10, permit
Mar 1 02:19:05.127: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.2), len 100, policy routed
Mar 1 02:19:05.127: IP: Serial0/1 to Serial0/0.2 10.2.23.3
Mar 1 02:19:05.127: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.2), g=10.2.23.3, len 100, forward

R2:
interface Serial0/0.2 point-to-point
 shutdown

#9
Mar 1 02:19:15.831: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:19:15.831: IP: route map pbr, item 10, permit
Mar 1 02:19:15.831: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), len 100, policy routed
Mar 1 02:19:15.835: IP: Serial0/1 to Serial0/0.1 10.0.34.3
Mar 1 02:19:15.835: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3 (Serial0/0.1), g=10.0.34.3, len 100, forward

R2:
interface Serial0/0.1 point-to-point
 shutdown

#10
Mar 1 02:19:26.767: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy match
Mar 1 02:19:26.767: IP: route map pbr, item 10, permit
Mar 1 02:19:26.767: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, policy rejected -- normal forwarding
Mar 1 02:19:26.771: IP: s=1.1.1.1 (Serial0/1), d=10.0.34.3, len 100, unroutable

 

#1. Of all the set commands configured, set ip next-hop verify-availability with object tracking takes precedence.  The lowest sequence number is 100 and the tracked object is up so it is policy routed to 10.0.234.4.

#2. The tracked object for sequence number 100 is down.  Sequence number 200 is up so the packet is policy routed to 10.0.234.3.

#3. Both next-hops that use object tracking are down.  The next method to use is set ip next-hop.  The next-hop is in the CDP neighbor table so the packet is policy routed to 10.7.23.3.

#4. The interface where 10.7.23.3 was found is now down.  The next attempted method is set ip next-hop recursive.  R2 has a static route to the configured recursive next-hop address out of S0/0.6, so the packet is policy routed out S0/0.6.

#5. R2 no longer has a route to reach the recursive next-hop so the next method, set interface, is used and the packet is policy routed out S0/0.5.

#6. All remaining set commands use the default keyword, so R2 uses normal routing to send the packet out S0/0.4.

#7. There is no matching route in the route table anymore.  The next method to use is set ip default next-hop.  10.3.23.3 is the first listed next-hop and is in the CDP neighbor table so the packet is policy routed to 10.3.23.3.

#8. CDP has been disabled on S0/0.3 so availability can no longer be verified.  The next address listed in set ip default next-hop is still in the CDP neighbor table so the packet is policy routed to 10.2.23.3.

#9. The only remaining set command that is still valid, set default interface, is used and the packet is policy routed out S0/0.1.

#10. PBR fails and normal routing fails so the packet is dropped.

Posted in PBR | Leave a Comment »

RIP and RIPng Behavior with Lower AD Routes

Posted by Andy on May 6, 2009

Here we will look at the behavior of RIPv2 and RIPng for a route when a better administrative distance route exists.  The topology and configurations are shown below.  All interfaces on all routers run RIPv2 with no auto-summary and RIPng:

rip-topology

R1:
ipv6 unicast-routing
!
interface Loopback0
 ip address 1.1.1.1 255.255.255.0
 ipv6 address 2001:0:0:1::1/64
 ipv6 rip asdf enable
!
interface Serial0/0
 ip address 10.0.12.1 255.255.255.0
 ipv6 address 2001:0:0:12::1/64
 ipv6 rip asdf enable
!
router rip
 version 2
 passive-interface Loopback0
 network 1.0.0.0
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip asdf

R2:
ipv6 unicast-routing
!
interface Serial0/0
 ip address 10.0.12.2 255.255.255.0
 ipv6 address 2001:0:0:12::2/64
 ipv6 rip asdf enable
!
interface Serial0/1
 ip address 10.0.23.2 255.255.255.0
 ipv6 address 2001:0:0:23::2/64
 ipv6 rip asdf enable
!
router rip
 version 2
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip asdf

R3:
ipv6 unicast-routing
!
interface Serial0/0
 ip address 10.0.23.3 255.255.255.0
 ipv6 address 2001:0:0:23::3/64
 ipv6 rip asdf enable
!
router rip
 version 2
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip asdf

Next we will create an OSPF process between R1 and R2 and use it to advertise R1 Loopback1 to R2:

R1:
router ospf 1
 network 0.0.0.0 255.255.255.255 area 0
!
interface Loopback0
 ip ospf network point-to-point
 ipv6 ospf network point-to-point
 ipv6 ospf 1 area 0
!
interface Serial0/0
 ipv6 ospf 1 area 0

R2:
router ospf 1
 network 10.0.12.2 0.0.0.0 area 0
!
interface Serial0/0
 ipv6 ospf 1 area 0

R2 replaces the RIPv2 and RIPng routes to R1 Loopback0 with the OSPF routes because of their lower AD:

1-r2-route-table2

1-r2-route-table-ipv62

Although R2 still hears about R1’s loopback in RIP advertisements, it does not advertise it to R3 in either RIPv2 or RIPng and R3 therefore does not have a route to it.  The route must be present in the routing table in order for RIPv1/RIPv2 and RIPng to include it in advertisements:

R2#debug ip rip
Mar 1 00:22:09.267: RIP: received v2 update from 10.0.12.1 on Serial0/0
Mar 1 00:22:09.271: 1.1.1.0/24 via 0.0.0.0 in 1 hops
Mar 1 00:22:16.471: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 00:22:16.471: RIP: build update entries
Mar 1 00:22:16.471: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0

R2#debug ipv6 rip
Mar 1 00:22:57.627: RIPng: response received from FE80::C601:9FF:FEFC:0 on Serial0/0 for asdf
Mar 1 00:22:57.627: src=FE80::C601:9FF:FEFC:0 (Serial0/0)
Mar 1 00:22:57.631: dst=FF02::9
Mar 1 00:22:57.631: sport=521, dport=521, length=52
Mar 1 00:22:57.631: command=2, version=1, mbz=0, #rte=2
Mar 1 00:22:57.631: tag=0, metric=1, prefix=2001:0:0:1::/64
Mar 1 00:22:57.631: tag=0, metric=1, prefix=2001:0:0:12::/64
Mar 1 00:23:13.255: RIPng: Sending multicast update on Serial0/1 for asdf
Mar 1 00:23:13.255: src=FE80::C602:9FF:FEFC:0
Mar 1 00:23:13.255: dst=FF02::9 (Serial0/1)
Mar 1 00:23:13.259: sport=521, dport=521, length=52
Mar 1 00:23:13.259: command=2, version=1, mbz=0, #rte=2
Mar 1 00:23:13.259: tag=0, metric=1, prefix=2001:0:0:12::/64
Mar 1 00:23:13.259: tag=0, metric=1, prefix=2001:0:0:23::/64

Let’s try creating a separate OSPF process between R2 and R3 and redistributing RIP into it:

R2:
interface Serial0/1
 ipv6 ospf 2 area 0
!
router ospf 2
 network 10.0.23.2 0.0.0.0 area 0
 redistribute rip metric 100 subnets
!
ipv6 router ospf 2
 redistribute rip asdf metric 100

R3:
interface Serial0/0
 ipv6 ospf 2 area 0
!
router ospf 2
 network 0.0.0.0 255.255.255.255 area 0

R1’s loopback is not redistributed into OSPF process #2 for the same reason – the route must be present in the routing table as a RIP route in order to be redistributed.  R3 still does not have a route to R1’s loopback:

 2-r3-route-table

2-r3-route-table-ipv6

 

One difference between RIPv2 and RIPng when there is a better AD route already in the routing table is that RIPng keeps the route in the RIP database, while RIPv2 does not:

3-r2-rip-db

3-r2-ripng-db

The significance of this is that if the better AD route is removed, the RIPng route is immediately installed in the routing table.  RIPv2 on the other hand must wait until it hears the next periodic update for the route – up to 30 seconds using default timers:

R2:
no ipv6 router ospf 1

R2#debug ipv6 routing
Mar 1 00:41:38.395: IPv6RT0: ospf 1, Delete 2001:0:0:1::/64 from table
Mar 1 00:41:38.399: IPv6RT0: rip asdf, Backup call for 2001:0:0:1::/64
Mar 1 00:41:38.399: IPv6RT0: rip asdf, Route add 2001:0:0:1::/64 [new]
Mar 1 00:41:38.399: IPv6RT0: rip asdf, Add 2001:0:0:1::/64 to table
Mar 1 00:41:38.399: IPv6RT0: rip asdf, Adding next-hop FE80::C601:9FF:FEFC:0 over Serial0/0 for 2001:0:0:1::/64, [120/2]
Mar 1 00:41:38.415: IPv6RT0: Event: 2001:0:0:1::/64, Del, owner ospf, previous None
Mar 1 00:41:38.415: IPv6RT0: Event: 2001:0:0:1::/64, Add, owner rip, previous None

R2:
no router ospf 1

R2#debug ip routing
R2#debug ip rip

Mar 1 00:44:02.743: RT: NET-RED 1.1.1.0/24
Mar 1 00:44:02.775: RT: delete route to 1.1.1.0/24
Mar 1 00:44:02.775: RT: NET-RED 1.1.1.0/24
Mar 1 00:44:02.775: RT: delete network route to 1.0.0.0
Mar 1 00:44:02.775: RT: NET-RED 1.0.0.0/8
Mar 1 00:44:27.987: RIP: received v2 update from 10.0.12.1 on Serial0/0
Mar 1 00:44:27.991: 1.1.1.0/24 via 0.0.0.0 in 1 hops
Mar 1 00:44:27.991: RT: SET_LAST_RDB for 1.1.1.0/24
NEW rdb: via 10.0.12.1
Mar 1 00:44:27.995: RT: add 1.1.1.0/24 via 10.0.12.1, rip metric [120/1]
Mar 1 00:44:27.995: RT: NET-RED 1.1.1.0/24

Since R2 now has the RIPv2 and RIPng routes to R1 Loopback0 in the routing table, they are eligible for route advertisement and redistribution.  R3 learns the route from R2 through both RIP and OSPF and adds the lower AD OSPF routes.  Like we saw on R2 previously, the RIP route is kept in the RIPng database but not in the RIPv2 database:

4-r3-route-table

4-r3-route-table-ipv6

5-r3-rip-db

5-r3-ripng-db

Posted in IPv6, RIP | Leave a Comment »

RIP and RIPng Metrics

Posted by Andy on May 4, 2009

In this post we will look at a few things relating to metric calculations in RIPv2 and RIPng.  The topology and configurations are shown below.  All interfaces on all routers run RIPv2 with no auto-summary and RIPng:

rip-hop-count1

R1:
ipv6 unicast-routing
!
interface Loopback1
 ip address 1.1.1.1 255.255.255.0
 ipv6 address 2001:0:0:1111::1/64
 ipv6 rip asdf enable
!
interface Serial0/0
 ip address 10.0.12.1 255.255.255.0
 ipv6 address 2001:12::1/64
 ipv6 rip asdf enable
!
router rip
 version 2
 passive-interface default
 no passive-interface Serial0/0
 network 1.0.0.0
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip asdf

R2:
ipv6 unicast-routing
!
interface Loopback1
 ip address 2.2.2.2 255.255.255.0
 ipv6 address 2001:0:0:2222::2/64
 ipv6 rip asdf enable
!
interface Serial0/0
 ip address 10.0.12.2 255.255.255.0
 ipv6 address 2001:12::2/64
 ipv6 rip asdf enable
!
interface Serial0/1
 ip address 10.0.23.2 255.255.255.0
 ipv6 address 2001:23::2/64
 ipv6 rip asdf enable
!
router rip
 version 2
 passive-interface Loopback1
 network 2.0.0.0
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip asdf

R3:
ipv6 unicast-routing
!
interface Loopback1
 ip address 3.3.3.3 255.255.255.0
 ipv6 address 2001:0:0:3333::3/64
 ipv6 rip asdf enable
!
interface Serial0/0
 ip address 10.0.23.3 255.255.255.0
 ipv6 address 2001:23::3/64
 ipv6 rip asdf enable
!
interface Serial0/1
 ip address 10.0.34.3 255.255.255.0
 ipv6 address 2001:34::3/64
 ipv6 rip asdf enable
!
router rip
 version 2
 passive-interface Loopback1
 network 3.0.0.0
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip asdf

R4:
ipv6 unicast-routing
!
interface Loopback1
 ip address 4.4.4.4 255.255.255.0
 ipv6 address 2001:0:0:4444::4/64
 ipv6 rip asdf enable
!
interface Serial0/0
 ip address 10.0.34.4 255.255.255.0
 ipv6 address 2001:34::4/64
 ipv6 rip asdf enable
!
router rip
 version 2
 network 4.0.0.0
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip asdf

The routing tables of each router look like this:

1-r1-route-table

1-r2-route-table

1-r3-route-table

1-r4-route-table1

1-r1-route-table-ipv6

1-r2-route-table-ipv6

1-r3-route-table-ipv6

1-r4-route-table-ipv61

Notice that the RIPng routes are listed as 1 hop higher than the equivalent RIPv2 routes.  For example, R2 sees R1’s loopback as 1 hop in RIPv2 and 2 hops in RIPng.  Let’s take a look at the RIPv2 and RIPng updates on R2 being received from R1 and sent to R3:

R2#debug ip rip
Mar 1 00:46:36.895: RIP: received v2 update from 10.0.12.1 on Serial0/0
Mar 1 00:46:36.895: 1.1.1.0/24 via 0.0.0.0 in 1 hops
Mar 1 00:46:40.167: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 00:46:40.167: RIP: build update entries
Mar 1 00:46:40.167: 1.1.1.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 00:46:40.171: 2.2.2.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:46:40.171: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0

R2#debug ipv6 rip
Mar 1 00:46:55.487: RIPng: response received from FE80::C601:9FF:FEFC:0 on Serial0/0 for asdf
Mar 1 00:46:55.487: src=FE80::C601:9FF:FEFC:0 (Serial0/0)
Mar 1 00:46:55.491: dst=FF02::9
Mar 1 00:46:55.491: sport=521, dport=521, length=52
Mar 1 00:46:55.491: command=2, version=1, mbz=0, #rte=2
Mar 1 00:46:55.491: tag=0, metric=1, prefix=2001:0:0:1111::/64
Mar 1 00:46:55.491: tag=0, metric=1, prefix=2001:12::/64
Mar 1 00:47:14.139: RIPng: Sending multicast update on Serial0/1 for asdf
Mar 1 00:47:14.139: src=FE80::C602:9FF:FEFC:0
Mar 1 00:47:14.139: dst=FF02::9 (Serial0/1)
Mar 1 00:47:14.143: sport=521, dport=521, length=92
Mar 1 00:47:14.143: command=2, version=1, mbz=0, #rte=4
Mar 1 00:47:14.143: tag=0, metric=1, prefix=2001:12::/64
Mar 1 00:47:14.143: tag=0, metric=1, prefix=2001:23::/64
Mar 1 00:47:14.143: tag=0, metric=1, prefix=2001:0:0:2222::/64
Mar 1 00:47:14.147: tag=0, metric=2, prefix=2001:0:0:1111::/64

Both updates look the same – R1’s loopback is received from R1 as metric 1 and advertised to R3 as metric 2.  The reason for the difference in metric in the routing table and RIP database is that RIPng metrics are incremented inbound before being added to the routing table/RIP database, while RIPv1 and RIPv2 metrics are incremented outbound.  Equivalent RIPng routes will always show up as 1 hop higher than RIPv2 routes if no offsets are applied.

 

Next we will look at a bug that is present in many IOS versions that results in RIPv1 and RIPv2 hop counts not incrementing.  We will turn RIPv2 auto-summary back on for R3 and R4:

R3:
router rip
 auto-summary

R4:
router rip
auto-summary

R3 stops advertising 1.1.1.0/24 and 2.2.2.0/24 and starts advertising 1.0.0.0/8 and 2.0.0.0/8 to R4.  After R4’s flush timer expires for the /24 routes, it’s routing table now looks like this:

2-r4-route-table

1.0.0.0/8 has the same metric as the old /24 route, but 2.0.0.0/8 is listed as metric 1 instead of metric 2.  Let’s take a look at sent and received updates in the direction of R1 to R4.  R3 receives the same routes and metrics from R2:

R3#debug ip rip
Mar 1 01:01:37.891: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 01:01:37.891: 1.1.1.0/24 via 0.0.0.0 in 2 hops
Mar 1 01:01:37.895: 2.2.2.0/24 via 0.0.0.0 in 1 hops
Mar 1 01:01:37.895: 10.0.12.0/24 via 0.0.0.0 in 1 hops

When the summarized routes are advertised to R4, 1.0.0.0/8 is incremented but 2.0.0.0/8 is advertised as metric 1, the same metric it was received as:

R3#debug ip rip
Mar 1 01:01:41.647: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.34.3)
Mar 1 01:01:41.647: RIP: build update entries
Mar 1 01:01:41.647: 1.0.0.0/8 via 0.0.0.0, metric 3, tag 0
Mar 1 01:01:41.651: 2.0.0.0/8 via 0.0.0.0, metric 1, tag 0
Mar 1 01:01:41.651: 3.0.0.0/8 via 0.0.0.0, metric 1, tag 0
Mar 1 01:01:41.651: 10.0.12.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 01:01:41.651: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0

R4 receives the update from R3:

R4#debug ip rip
Mar 1 01:01:41.679: RIP: received v2 update from 10.0.34.3 on Serial0/0
Mar 1 01:01:41.679: 1.0.0.0/8 via 0.0.0.0 in 3 hops
Mar 1 01:01:41.683: 2.0.0.0/8 via 0.0.0.0 in 1 hops
Mar 1 01:01:41.683: 3.0.0.0/8 via 0.0.0.0 in 1 hops
Mar 1 01:01:41.683: 10.0.12.0/24 via 0.0.0.0 in 2 hops
Mar 1 01:01:41.687: 10.0.23.0/24 via 0.0.0.0 in 1 hops

When R4 sends an update out loopback1, 1.0.0.0/8 is again incremented and 2.0.0.0/8 is not.  3.0.0.0/8, which was received as metric 1, is also not incremented:

R4#debug ip rip
Mar 1 01:01:56.191: RIP: sending v2 update to 224.0.0.9 via Loopback1 (4.4.4.4)
Mar 1 01:01:56.191: RIP: build update entries
Mar 1 01:01:56.191: 1.0.0.0/8 via 0.0.0.0, metric 4, tag 0
Mar 1 01:01:56.195: 2.0.0.0/8 via 0.0.0.0, metric 1, tag 0
Mar 1 01:01:56.195: 3.0.0.0/8 via 0.0.0.0, metric 1, tag 0
Mar 1 01:01:56.195: 10.0.0.0/8 via 0.0.0.0, metric 1, tag 0

This bug, which prevents the hop count from incrementing, occurs whenever a received route has metric 1 and is summarized before being advertised.  If the received metric is greater than 1, the hop count continues to increment like normal.  This occurs for RIPv1 routes when they are summarized at classful boundaries, RIPv2 auto-summary routes, and RIPv2 interface summary routes.  The bug occurred in various 12.4 mainline IOS versions that were tested and no longer occurred in 12.4(20)T, so it appears to have been fixed in some 12.4 T-train release.

 

Summary routes in both RIPv2 and RIPng use the lowest metric of any child route within their range as the metric for the summary route.  To demonstrate this, we will first create a few more loopbacks on R1 and redistribute them into RIP with various metrics.  We will also turn auto-summary off again on R3 and R4:

R1:
router rip
 no network 1.0.0.0
!
interface Loopback1
 no ipv6 rip asdf enable
!
interface Loopback2
 ip address 1.1.2.1 255.255.255.0
 ipv6 address 2001:0:0:1112::1/64
!
interface Loopback3
 ip address 1.1.3.1 255.255.255.0
 ipv6 address 2001:0:0:1113::1/64
!
interface Loopback4
 ip address 1.1.4.1 255.255.255.0
 ipv6 address 2001:0:0:1114::1/64
!
ip access-list standard Loop1
 permit 1.1.1.0
ip access-list standard Loop2
 permit 1.1.2.0
ip access-list standard Loop3
 permit 1.1.3.0
ip access-list standard Loop4
 permit 1.1.4.0
!
route-map RIPv2 permit 10
 match ip address Loop1
 set metric 3
!
route-map RIPv2 permit 20
 match ip address Loop2
 set metric 4
!
route-map RIPv2 permit 30
 match ip address Loop3
 set metric 5
!
route-map RIPv2 permit 40
 match ip address Loop4
 set metric 6
!
router rip
 redistribute connected route-map RIPv2
!
ipv6 prefix-list Loop1 seq 5 permit 2001:0:0:1111::/64
!
ipv6 prefix-list Loop2 seq 5 permit 2001:0:0:1112::/64
!
ipv6 prefix-list Loop3 seq 5 permit 2001:0:0:1113::/64
!
ipv6 prefix-list Loop4 seq 5 permit 2001:0:0:1114::/64
!
route-map RIPng permit 10
match ipv6 address prefix-list Loop1
set metric 3
!
route-map RIPng permit 20
match ipv6 address prefix-list Loop2
set metric 4
!
route-map RIPng permit 30
match ipv6 address prefix-list Loop3
set metric 5
!
route-map RIPng permit 40
match ipv6 address prefix-list Loop4
set metric 6
!
ipv6 router rip asdf
 redistribute connected route-map RIPng

R3:
router rip
 no auto-summary

R4:
router rip
 no auto-summary

Before creating the summary routes, let’s verify that the redistributed routes have the correct metrics:

R1#debug ip rip
Mar 1 01:33:23.859: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.12.1)
Mar 1 01:33:23.859: RIP: build update entries
Mar 1 01:33:23.859: 1.1.1.0/24 via 0.0.0.0, metric 3, tag 0
Mar 1 01:33:23.863: 1.1.2.0/24 via 0.0.0.0, metric 4, tag 0
Mar 1 01:33:23.863: 1.1.3.0/24 via 0.0.0.0, metric 5, tag 0
Mar 1 01:33:23.863: 1.1.4.0/24 via 0.0.0.0, metric 6, tag 0

R1#debug ipv6 rip
Mar 1 01:33:54.007: RIPng: Sending multicast update on Serial0/0 for asdf
Mar 1 01:33:54.007: src=FE80::C601:9FF:FEFC:0
Mar 1 01:33:54.011: dst=FF02::9 (Serial0/0)
Mar 1 01:33:54.011: sport=521, dport=521, length=112
Mar 1 01:33:54.011: command=2, version=1, mbz=0, #rte=5
Mar 1 01:33:54.011: tag=0, metric=3, prefix=2001:0:0:1111::/64
Mar 1 01:33:54.011: tag=0, metric=1, prefix=2001:12::/64
Mar 1 01:33:54.015: tag=0, metric=4, prefix=2001:0:0:1112::/64
Mar 1 01:33:54.015: tag=0, metric=5, prefix=2001:0:0:1113::/64
Mar 1 01:33:54.015: tag=0, metric=6, prefix=2001:0:0:1114::/64

3-r4-route-table

3-r4-route-table-ipv6

Now we will create the summary routes:

R1:
interface Serial0/0
 ip summary-address rip 1.1.0.0 255.255.248.0
 ipv6 rip asdf summary-address 2001:0:0:1110::/60

Let’s check how the summaries are being advertised on R1:

R1#debug ip rip
Mar 1 01:33:11.163: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.12.1)
Mar 1 01:33:11.163: RIP: build update entries
Mar 1 01:33:11.163: 1.1.0.0/21 via 0.0.0.0, metric 4, tag 0

R1#debug ipv6 rip
Mar 1 01:33:43.747: RIPng: Sending multicast update on Serial0/0 for asdf
Mar 1 01:33:43.747: src=FE80::C601:9FF:FEFC:0
Mar 1 01:33:43.751: dst=FF02::9 (Serial0/0)
Mar 1 01:33:43.751: sport=521, dport=521, length=52
Mar 1 01:33:43.751: command=2, version=1, mbz=0, #rte=2
Mar 1 01:33:43.751: tag=0, metric=1, prefix=2001:12::/64
Mar 1 01:33:43.751: tag=0, metric=3, prefix=2001:0:0:1110::/60

RIPng used the lowest child metric (3) as the metric for the summary route.  RIPv2, however, gave it a metric of 4.  This relates to another possible bug, where routes redistributed into RIPv2 that are manually summarized have an additional hop added to the metric.  Some additional info can be found here.  Let’s try putting the RIPv2 summary on R2 instead and see if this goes away:

R1:
interface Serial0/0
 no ip summary-address rip 1.1.0.0 255.255.248.0

R2#debug ip rip
Mar 1 01:46:25.751: RIP: received v2 update from 10.0.12.1 on Serial0/0
Mar 1 01:46:25.755: 1.1.1.0/24 via 0.0.0.0 in 3 hops
Mar 1 01:46:25.755: 1.1.2.0/24 via 0.0.0.0 in 4 hops
Mar 1 01:46:25.755: 1.1.3.0/24 via 0.0.0.0 in 5 hops
Mar 1 01:46:25.755: 1.1.4.0/24 via 0.0.0.0 in 6 hops
Mar 1 01:46:47.503: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 01:46:47.503: RIP: build update entries
Mar 1 01:46:47.503: 1.1.1.0/24 via 0.0.0.0, metric 4, tag 0
Mar 1 01:46:47.507: 1.1.2.0/24 via 0.0.0.0, metric 5, tag 0
Mar 1 01:46:47.507: 1.1.3.0/24 via 0.0.0.0, metric 6, tag 0
Mar 1 01:46:47.507: 1.1.4.0/24 via 0.0.0.0, metric 7, tag 0
Mar 1 01:46:47.507: 2.2.2.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 01:46:47.511: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0

R2:
interface Serial0/1
 ip summary-address rip 1.1.0.0 255.255.248.0

R2#debug ip rip
Mar 1 01:47:41.935: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 01:47:41.935: RIP: build update entries
Mar 1 01:47:41.935: 1.1.0.0/21 via 0.0.0.0, metric 4, tag 0
Mar 1 01:47:41.939: 2.2.2.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 01:47:41.939: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0

R2 now correctly uses the lowest child metric as the metric for the summary.

4-r4-route-table

4-r4-route-table-ipv6

 

 

As mentioned earlier, the bug where routes received with a hop count of 1 are not incremented applies to manual summary routes also.  If any child route has a metric of 1 the summary route metric will not be incremented.  To demonstrate this we will change the seed metric of R1 Loopback1 to 1:

R1:
route-map RIPv2 permit 10
 match ip address Loop1
 set metric 1

R2#debug ip rip
Mar 1 02:02:15.843: RIP: received v2 update from 10.0.12.1 on Serial0/0
Mar 1 02:02:15.843: 1.1.1.0/24 via 0.0.0.0 in 1 hops
Mar 1 02:02:15.847: 1.1.2.0/24 via 0.0.0.0 in 4 hops
Mar 1 02:02:15.847: 1.1.3.0/24 via 0.0.0.0 in 5 hops
Mar 1 02:02:15.847: 1.1.4.0/24 via 0.0.0.0 in 6 hops
Mar 1 02:02:27.599: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 02:02:27.599: RIP: build update entries
Mar 1 02:02:27.599: 1.1.0.0/21 via 0.0.0.0, metric 1, tag 0
Mar 1 02:02:27.603: 2.2.2.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 02:02:27.603: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0

The advertised metric remains at 1.

Posted in IPv6, RIP | Leave a Comment »

RIP Timers

Posted by Andy on April 27, 2009

This post will take a look at the various timers used in RIP and RIPng, and some of the differences between how they are supposed to work and how they actually do work .  RIPv2 with no auto-summary and RIPng are enabled for every interface on each router.  The topology and configurations of each router are shown below:

rip-timers3

R1:
ipv6 unicast-routing
!
interface Serial0/0
 ip address 10.0.12.1 255.255.255.0
 ipv6 address 2001:DB8:0:12::1/64
 ipv6 address FE80::1 link-local
 ipv6 rip test enable
!
router rip
 version 2
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip test

R2:
ipv6 unicast-routing
!
interface Serial0/0
 ip address 10.0.12.2 255.255.255.0
 ipv6 address 2001:DB8:0:12::2/64
 ipv6 address FE80::2 link-local
 ipv6 rip test enable
!
interface Serial0/1
 ip address 10.0.23.2 255.255.255.0
 ipv6 address 2001:DB8:0:23::2/64
 ipv6 address FE80::2 link-local
 ipv6 rip test enable
!
router rip
 version 2
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip test

R3:
ipv6 unicast-routing
!
interface FastEthernet0/0
 ip address 10.0.34.3 255.255.255.0
 ipv6 address 2001:DB8:0:34::3/64
 ipv6 address FE80::3 link-local
 ipv6 rip test enable
!
interface Serial0/0
 ip address 10.0.23.3 255.255.255.0
 ipv6 address 2001:DB8:0:23::3/64
 ipv6 address FE80::3 link-local
 ipv6 rip test enable
!
router rip
 version 2
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip test

R4:
ipv6 unicast-routing
!
interface Loopback0
 ip address 4.4.4.4 255.255.255.0
 ipv6 address 2001:DB8:0:4444::4/64
 ipv6 address FE80::4 link-local
 ipv6 rip test enable
!
interface FastEthernet0/0
 ip address 10.0.34.4 255.255.255.0
 ipv6 address 2001:DB8:0:34::4/64
 ipv6 address FE80::4 link-local
 ipv6 rip test enable
!
router rip
 version 2
 passive-interface Loopback0
 network 4.0.0.0
 network 10.0.0.0
 no auto-summary
!
ipv6 router rip test

The update interval configured under the routing process controls when RIP updates are sent.  Updates are sent at the configured interval minus a random amount of time up to 15% of the update interval.  For RIPv1/RIPv2, the update period can also be controlled per interface using ip rip advertise.  This command is nowhere to be found in Cisco’s documentation, but it does just what it sounds like it should.  Here R2 is configured to send updates out S0/1 every 10 seconds (minus the random jitter time), while S0/0 continues to use the default of 30 seconds:

R2:
interface Serial0/1
 ip rip advertise 10

R2#debug ip rip
Mar 1 00:10:55.471: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 00:10:55.471: RIP: build update entries
Mar 1 00:10:55.471: 4.4.4.0/24 via 0.0.0.0, metric 3, tag 0
Mar 1 00:10:55.471: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:10:55.471: 10.0.34.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 00:11:00.967: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 00:11:00.967: RIP: build update entries
Mar 1 00:11:00.967: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:11:09.515: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 00:11:09.515: RIP: build update entries
Mar 1 00:11:09.515: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:11:19.343: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 00:11:19.343: RIP: build update entries
Mar 1 00:11:19.343: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:11:23.023: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 00:11:23.023: RIP: build update entries
Mar 1 00:11:23.023: 4.4.4.0/24 via 0.0.0.0, metric 3, tag 0
Mar 1 00:11:23.027: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:11:23.027: 10.0.34.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 00:11:29.131: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 00:11:29.131: RIP: build update entries
Mar 1 00:11:29.131: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:11:38.599: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 00:11:38.599: RIP: build update entries
Mar 1 00:11:38.599: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:11:47.939: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 00:11:47.939: RIP: build update entries
Mar 1 00:11:47.939: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0

RIPng does not have a way of controlling the update period per interface.  RIPv1/RIPv2 also support the configuration of a flash update threshold, designed to suppress flash updates from being sent if the next periodic update is due to be sent in less than the configured interval.  We will configure R4 with a flash update threshold of 30 seconds and shutdown it’s loopback interface:

R4:
router rip
 flash-update-threshold 30

1-rip-flash-interval1

R4:
interface Loopback0
 shutdown

R4#debug ip rip
Mar 1 00:31:23.931: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.4)
Mar 1 00:31:23.931: RIP: build flash update entries
Mar 1 00:31:23.931: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:31:32.103: RIP: sending v2 update to 224.0.0.9 via FastEthernet0/0 (10.0.34.4)
Mar 1 00:31:32.103: RIP: build update entries
Mar 1 00:31:32.103: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0

Unfortunately the command does not seem to work.  With an update period of 30 seconds and flash update threshold of 30 seconds, all flash updates should be suppressed.  R4 sends a flash update about the unreachable network out F0/0, even though the periodic update is due about 9 seconds later.  A search showed that some other people have run into this problem as well:

flash-update-threshold??

Flash-update-threshold, has anyone seen this work in a lab?

 

The invalid/timeout timer is 180 seconds by default in RIPv2:

2-r3-show-ip-protocols1

The invalid timer is reset for a route each time an update is received for it from the best route source.  The current routing table on R3 looks like this:

2-r3-show-ip-route1

R3 has learned 2 routes from RIP.  4.4.4.0/24 was learned on F0/0 from R4 and 10.0.12.0/24 was learned on S0/0 from R2.  As expected, both routes were last heard from less than 30 seconds ago since no updates were missed.  Now we will shut down R4 F0/0 so that R3 stops receiving RIP updates from it:

R4:
interface FastEthernet0/0
 shutdown

R3 receives the last update from R4 at 00:52:06.079, just prior to shutting down the interface:

R3#debug ip rip
Mar 1 00:52:06.079: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 00:52:06.079: 4.4.4.0/24 via 0.0.0.0 in 1 hops

Since no updates about 4.4.4.0/24 are received from R4, the timer for the route continues incrementing:

3-r3-show-ip-route1

Just over 180 seconds after the last update was received, log messages show that the route has been deleted and entered holddown.  We can also see that a flash update is sent for the route a couple seconds later, using poison-reverse rules to advertise it as unreachable out both S0/0 and F0/0.  The route continues to be included in periodic updates out each interface as well:

R3#debug ip rip
R3#debug ip routing
Mar 1 00:55:09.315: RT: delete route to 4.4.4.0 via 10.0.34.4, rip metric [120/1]
Mar 1 00:55:09.315: RT: SET_LAST_RDB for 4.4.4.0/24
OLD rdb: via 11.13.11.13
Mar 1 00:55:09.319: RT: no routes to 4.4.4.0, entering holddown
Mar 1 00:55:09.319: RT: NET-RED 4.4.4.0/24
Mar 1 00:55:11.323: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 00:55:11.323: RIP: build flash update entries
Mar 1 00:55:11.323: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:55:11.327: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 00:55:11.327: RIP: build flash update entries
Mar 1 00:55:11.327: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:55:27.775: RIP: sending v2 update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 00:55:27.775: RIP: build update entries
Mar 1 00:55:27.775: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:55:27.779: 10.0.12.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 00:55:27.779: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:55:30.955: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 00:55:30.955: RIP: build update entries
Mar 1 00:55:30.955: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:55:30.955: 10.0.34.0/24 via 0.0.0.0, metric 1, tag 0

There are a couple confusing things about the debug outputs shown above.  First, although it says the route has been deleted from the routing table, it actually is still in both the routing table and RIP database at this point.  The route is listed as “possibly down”, but continues to be used for forwarding packets:

4-r3-show-ip-route1

4-r3-rip-database1

R3#debug ip packet
R3#ping 4.4.4.4 repeat 1

Type escape sequence to abort.
Sending 1, 100-byte ICMP Echos to 4.4.4.4, timeout is 2 seconds:

Mar 1 00:55:48.871: IP: tableid=0, s=10.0.34.3 (local), d=4.4.4.4 (FastEthernet0/0), routed via RIB
Mar 1 00:55:48.871: IP: s=10.0.34.3 (local), d=4.4.4.4 (FastEthernet0/0), len 100, sending

Another possibly confusing thing is that the output shows the route entering holddown.  We will look at what happens when a route enters holddown and the circumstances that cause the holddown timer to be used later, but for now it is important to note that the behavior we are seeing – the route showing up as possibly down in both the routing table and RIP database, and poison-reverse being used to advertise the route as unreachable immediately in flash updates and then periodically in regular updates – is caused by the invalid timer expiring, not by entering the holddown state.  To show this, we will set the holddown timer to 0.  We will also reduce the invalid timer to 120 and keep the other timers at their defaults:

R3:
router rip
 timers basic 30 120 0 240

5-r3-show-ip-protocols1

After bringing R4 F0/0 back up and allowing the network to converge, we will shut it down again:

R4:
interface FastEthernet0/0
 shutdown

R3 receives the last update from R4 at 01:12:57.635, just prior to the shutdown:

R3#debug ip rip
Mar 1 01:12:57.635: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 01:12:57.639: 4.4.4.0/24 via 0.0.0.0 in 1 hops

A little over 120 seconds later, the route again shows up as possibly down in the routing table and RIP database, and is advertised as unreachable:

R3#debug ip routing
R3#debug ip rip

Mar 1 01:14:59.551: RT: delete route to 4.4.4.0 via 10.0.34.4, rip metric [120/1]
Mar 1 01:14:59.555: RT: SET_LAST_RDB for 4.4.4.0/24
OLD rdb: via 11.13.11.13
Mar 1 01:14:59.555: RT: no routes to 4.4.4.0, entering holddown
Mar 1 01:14:59.555: RT: NET-RED 4.4.4.0/24
Mar 1 01:15:01.559: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 01:15:01.559: RIP: build flash update entries
Mar 1 01:15:01.559: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 01:15:01.563: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 01:15:01.563: RIP: build flash update entries
Mar 1 01:15:01.563: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 01:15:03.639: RT: 4.4.4.0 came out of holddown
Mar 1 01:15:15.451: RIP: sending v2 update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 01:15:15.451: RIP: build update entries
Mar 1 01:15:15.451: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 01:15:15.455: 10.0.12.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 01:15:15.455: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 01:15:21.479: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 01:15:21.479: RIP: build update entries
Mar 1 01:15:21.479: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 01:15:21.483: 10.0.34.0/24 via 0.0.0.0, metric 1, tag 0

5-r3-show-ip-route1

5-r3-rip-database1

 

 

There are a few differences in the use of the invalid timer in RIPng, mostly related to naming and display output.  Instead of the invalid timer, RIPng (at least in IOS syntax) calls it the route timeout or expiration timer.  Instead of counting upward from the time the last route update was heard, RIPng counts downward starting at the value of the invalid timer, and the timer is only shown in the RIP database:

6-r3-ripng-database1

Like RIPv1 and RIPv2, RIPng uses a 180 second invalid timer by default:

6-r3-ripng1

We will shut down R4 F0/0 so that R3 stops receiving updates from it:

R4:
interface FastEthernet0/0
 shutdown

Note: RIPng on R4 would sometimes send a flash update advertising all known networks as unreachable as it was shutdown.  I’m not sure why it happened sometimes and not others, but it may be necessary to filter the route inbound on R3 or outbound on R4 instead of shutting down R4 F0/0 in order to see the invalid timer expire if this keeps occuring.

R3 receives the last update from R4 at 01:33:14.979, just prior to the shutdown:

R3#debug ipv6 rip
Mar 1 01:33:14.979: RIPng: response received from FE80::4 on FastEthernet0/0 for test
Mar 1 01:33:14.979: src=FE80::4 (FastEthernet0/0)
Mar 1 01:33:14.979: dst=FF02::9
Mar 1 01:33:14.979: sport=521, dport=521, length=52
Mar 1 01:33:14.983: command=2, version=1, mbz=0, #rte=2
Mar 1 01:33:14.983: tag=0, metric=1, prefix=2001:DB8:0:4444::/64
Mar 1 01:33:14.983: tag=0, metric=1, prefix=2001:DB8:0:34::/64

180 seconds later, the invalid timer expires and the route is removed from the routing table. Flash updates are sent about the unreachable route 1 second later, followed by the regular periodic updates a few seconds after that:

R3#debug ipv6 routing
R3#debug ipv6 rip

Mar 1 01:36:14.983: IPv6RT0: rip test, Delete backup for 2001:DB8:0:34::/64
Mar 1 01:36:14.983: RIPng: 2001:DB8:0:34::/64, expired, ttg is 0
Mar 1 01:36:14.983: RIPng: Deleting 2001:DB8:0:34::/64
Mar 1 01:36:14.983: IPv6RT0: rip test, Delete 2001:DB8:0:4444::/64 from table
Mar 1 01:36:14.983: RIPng: 2001:DB8:0:4444::/64, expired, ttg is 120
Mar 1 01:36:14.983: RIPng: Triggered update requested
Mar 1 01:36:14.983: RIPng: Next RIB walk in 2000
Mar 1 01:36:14.983: IPv6RT0: Event: 2001:DB8:0:4444::/64, Del, owner rip, previous None
Mar 1 01:36:15.983: RIPng: generating triggered update for test
Mar 1 01:36:15.983: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 01:36:15.983: src=FE80::3
Mar 1 01:36:15.983: dst=FF02::9 (Serial0/0)
Mar 1 01:36:15.987: sport=521, dport=521, length=32
Mar 1 01:36:15.987: command=2, version=1, mbz=0, #rte=1
Mar 1 01:36:15.987: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 01:36:15.991: RIPng: Suppressed null multicast update on FastEthernet0/0 for test
Mar 1 01:36:16.983: RIPng: Next RIB walk in 118000
Mar 1 01:36:29.099: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 01:36:29.099: src=FE80::3
Mar 1 01:36:29.099: dst=FF02::9 (Serial0/0)
Mar 1 01:36:29.103: sport=521, dport=521, length=72
Mar 1 01:36:29.103: command=2, version=1, mbz=0, #rte=3
Mar 1 01:36:29.103: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 01:36:29.103: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 01:36:29.103: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 01:36:29.107: RIPng: Sending multicast update on FastEthernet0/0 for test
Mar 1 01:36:29.107: src=FE80::3
Mar 1 01:36:29.107: dst=FF02::9 (FastEthernet0/0)
Mar 1 01:36:29.111: sport=521, dport=521, length=72
Mar 1 01:36:29.111: command=2, version=1, mbz=0, #rte=3
Mar 1 01:36:29.111: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 01:36:29.111: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 01:36:29.111: tag=0, metric=2, prefix=2001:DB8:0:12::/64

7-r3-show-ipv6-route1 

7-r3-ripng-database1

As shown in the routing table above, when the invalid timer expires the route is immediately removed from the routing table, unlike RIPv1 and RIPv2.  In the RIPng database, it is listed as expired, and 2 additional timers that we will look at shortly are now listed as well for the failed route.  One other difference compared to RIPv1/RIPv2 is that by default RIPng does not use poison-reverse.  When R3 sent flash updates about the unreachable route, the update on F0/0 was suppressed (the message at 01:36:15.991) because the only route to be advertised in the flash update was known on that interface.  The periodic update on F0/0 (at 01:36:29.111) also does not include a route entry for 2001:db8:0:4444::/64.  Poison-reverse can be enabled at the routing process in RIPng as shown below:

R3:
ipv6 router rip test
 poison-reverse

However, this is not the same as RIPv1/2 behavior.  RIPv1/2 use poison-reverse only for unreachable routes, with all other routes using simple split-horizon rules (if split-horizon is enabled).  RIPng uses split-horizon with poison-reverse for all non-directly-connected routes regardless of their metric if it is enabled.  With all interfaces once again enabled and the network converged, R3’s routing table and RIPng updates look like this:

8-r3-show-ipv6-route1

R3#debug ipv6 rip
Mar 1 01:42:38.311: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 01:42:38.311: src=FE80::3
Mar 1 01:42:38.311: dst=FF02::9 (Serial0/0)
Mar 1 01:42:38.315: sport=521, dport=521, length=92
Mar 1 01:42:38.315: command=2, version=1, mbz=0, #rte=4
Mar 1 01:42:38.315: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 01:42:38.315: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 01:42:38.315: tag=0, metric=16, prefix=2001:DB8:0:12::/64
Mar 1 01:42:38.319: tag=0, metric=2, prefix=2001:DB8:0:4444::/64
Mar 1 01:42:38.319: RIPng: Sending multicast update on FastEthernet0/0 for test
Mar 1 01:42:38.319: src=FE80::3
Mar 1 01:42:38.323: dst=FF02::9 (FastEthernet0/0)
Mar 1 01:42:38.323: sport=521, dport=521, length=92
Mar 1 01:42:38.323: command=2, version=1, mbz=0, #rte=4
Mar 1 01:42:38.323: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 01:42:38.323: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 01:42:38.327: tag=0, metric=2, prefix=2001:DB8:0:12::/64
Mar 1 01:42:38.327: tag=0, metric=16, prefix=2001:DB8:0:4444::/64

2001:db8:0:12::/64, known on S0/0, is advertised back out S0/0 as unreachable.  2001:db8:0:4444::/64, known on F0/0, is advertised back out F0/0 as unreachable.

 

Next we will look at the flush timer, first in RIPv1/2.  The flush timer controls when a route that has not been updated is removed entirely from the routing table and RIP database.  We will be using the same scenario again, where R4 F0/0 fails.  First we will set the timers back to their defaults:

R3:
router rip
 default timers basic

The default flush timer is 240 seconds in RIPv1/2:

9-r3-show-ip-protocols

Now we will shut down R4 F0/0 again:

R4:
interface FastEthernet0/0
 shutdown

R3 receives the last update from R4 at 00:25:11.695, just prior to the shutdown:

R3#debug ip rip
Mar 1 00:25:11.695: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 00:25:11.695: 4.4.4.0/24 via 0.0.0.0 in 1 hops

A little over 180 seconds later, the invalid timer expires.  Like we saw earlier, the route is listed as possibly down in the routing table and RIP database, and is advertised as unreachable using poison-reverse.  The route continues to be advertised in periodic updates until the flush timer expires, after approximately 240 seconds:

R3#debug ip routing
R3#debug ip rip
Mar 1 00:28:14.927: RT: delete route to 4.4.4.0 via 10.0.34.4, rip metric [120/1]
Mar 1 00:28:14.927: RT: SET_LAST_RDB for 4.4.4.0/24
OLD rdb: via 11.13.11.13
Mar 1 00:28:14.931: RT: no routes to 4.4.4.0, entering holddown
Mar 1 00:28:14.931: RT: NET-RED 4.4.4.0/24
Mar 1 00:28:16.931: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 00:28:16.931: RIP: build flash update entries
Mar 1 00:28:16.931: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:28:16.931: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 00:28:16.931: RIP: build flash update entries
Mar 1 00:28:16.931: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:28:38.879: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 00:28:38.879: RIP: build update entries
Mar 1 00:28:38.879: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:28:38.883: 10.0.34.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:28:40.039: RIP: sending v2 update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 00:28:40.039: RIP: build update entries
Mar 1 00:28:40.039: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:28:40.039: 10.0.12.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 00:28:40.039: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:29:08.763: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 00:29:08.763: RIP: build update entries
Mar 1 00:29:08.763: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:29:08.767: 10.0.34.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:29:09.463: RIP: sending v2 update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 00:29:09.463: RIP: build update entries
Mar 1 00:29:09.463: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 00:29:09.463: 10.0.12.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 00:29:09.467: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 00:29:14.931: RT: delete subnet route to 4.4.4.0/24
Mar 1 00:29:14.931: RT: NET-RED 4.4.4.0/24
Mar 1 00:29:14.935: RT: delete network route to 4.0.0.0
Mar 1 00:29:14.935: RT: NET-RED 4.0.0.0/8

Using default timers, this means the route is advertised as unreachable for 60 seconds.  Once the flush timer expires and the 2nd delete message appears in the logs, the route is removed and no longer included in updates or used for forwarding.

 

In RIPng, the flush timer is called the garbage collection timer.  The garbage collect timer is 120 seconds by default and does not start until the invalid timer expires, unlike RIPv1/2 where the flush timer begins at the time the last update was received:

10-r3-ripng

Now we will shut down R4 F0/0 again:

R4:
interface FastEthernet0/0
 shutdown

R3 receives the last update from R4 at 00:31:20.699, just prior to the shutdown:

R3#debug ipv6 rip
Mar 1 00:31:20.699: RIPng: response received from FE80::4 on FastEthernet0/0 for test
Mar 1 00:31:20.699: src=FE80::4 (FastEthernet0/0)
Mar 1 00:31:20.703: dst=FF02::9
Mar 1 00:31:20.703: sport=521, dport=521, length=52
Mar 1 00:31:20.703: command=2, version=1, mbz=0, #rte=2
Mar 1 00:31:20.703: tag=0, metric=1, prefix=2001:DB8:0:4444::/64
Mar 1 00:31:20.703: tag=0, metric=1, prefix=2001:DB8:0:34::/64

180 seconds later, the invalid timer expires, and the behavior that we saw earlier when the RIPng invalid timer expires begins.  The RIP database shows how long the route will continue to be advertised (the garbage collect timer).  The route continues to be advertised in periodic updates using simple split-horizon rules until the garbage collect timer expires, after approximately 300 total seconds:

R3#debug ipv6 routing
R3#debug ipv6 rip

Mar 1 00:34:20.703: IPv6RT0: rip test, Delete backup for 2001:DB8:0:34::/64
Mar 1 00:34:20.703: RIPng: 2001:DB8:0:34::/64, expired, ttg is 0
Mar 1 00:34:20.703: RIPng: Deleting 2001:DB8:0:34::/64
Mar 1 00:34:20.707: IPv6RT0: rip test, Delete 2001:DB8:0:4444::/64 from table
Mar 1 00:34:20.707: RIPng: 2001:DB8:0:4444::/64, expired, ttg is 120
Mar 1 00:34:20.707: RIPng: Triggered update requested
Mar 1 00:34:20.707: RIPng: Next RIB walk in 2000
Mar 1 00:34:20.711: IPv6RT0: Event: 2001:DB8:0:4444::/64, Del, owner rip, previous None
Mar 1 00:34:21.707: RIPng: generating triggered update for test
Mar 1 00:34:21.707: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 00:34:21.707: src=FE80::3
Mar 1 00:34:21.707: dst=FF02::9 (Serial0/0)
Mar 1 00:34:21.711: sport=521, dport=521, length=32
Mar 1 00:34:21.711: command=2, version=1, mbz=0, #rte=1
Mar 1 00:34:21.711: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 00:34:21.715: RIPng: Suppressed null multicast update on FastEthernet0/0 for test

10-r3-ripng-database

R3#debug ipv6 routing
R3#debug ipv6 rip

Mar 1 00:34:26.715: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 00:34:26.715: src=FE80::3
Mar 1 00:34:26.715: dst=FF02::9 (Serial0/0)
Mar 1 00:34:26.719: sport=521, dport=521, length=72
Mar 1 00:34:26.719: command=2, version=1, mbz=0, #rte=3
Mar 1 00:34:26.719: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:34:26.719: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:34:26.719: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 00:34:26.723: RIPng: Sending multicast update on FastEthernet0/0 for test
Mar 1 00:34:26.723: src=FE80::3
Mar 1 00:34:26.723: dst=FF02::9 (FastEthernet0/0)
Mar 1 00:34:26.727: sport=521, dport=521, length=72
Mar 1 00:34:26.727: command=2, version=1, mbz=0, #rte=3
Mar 1 00:34:26.727: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:34:26.727: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:34:26.727: tag=0, metric=2, prefix=2001:DB8:0:12::/64
Mar 1 00:34:56.207: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 00:34:56.207: src=FE80::3
Mar 1 00:34:56.207: dst=FF02::9 (Serial0/0)
Mar 1 00:34:56.211: sport=521, dport=521, length=72
Mar 1 00:34:56.211: command=2, version=1, mbz=0, #rte=3
Mar 1 00:34:56.211: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:34:56.211: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:34:56.211: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 00:34:56.215: RIPng: Sending multicast update on FastEthernet0/0 for test
Mar 1 00:34:56.215: src=FE80::3
Mar 1 00:34:56.215: dst=FF02::9 (FastEthernet0/0)
Mar 1 00:34:56.219: sport=521, dport=521, length=72
Mar 1 00:34:56.219: command=2, version=1, mbz=0, #rte=3
Mar 1 00:34:56.219: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:34:56.219: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:34:56.219: tag=0, metric=2, prefix=2001:DB8:0:12::/64
Mar 1 00:35:23.631: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 00:35:23.631: src=FE80::3
Mar 1 00:35:23.631: dst=FF02::9 (Serial0/0)
Mar 1 00:35:23.635: sport=521, dport=521, length=72
Mar 1 00:35:23.635: command=2, version=1, mbz=0, #rte=3
Mar 1 00:35:23.635: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:35:23.635: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:35:23.635: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 00:35:23.639: RIPng: Sending multicast update on FastEthernet0/0 for test
Mar 1 00:35:23.639: src=FE80::3
Mar 1 00:35:23.639: dst=FF02::9 (FastEthernet0/0)
Mar 1 00:35:23.643: sport=521, dport=521, length=72
Mar 1 00:35:23.643: command=2, version=1, mbz=0, #rte=3
Mar 1 00:35:23.643: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:35:23.643: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:35:23.643: tag=0, metric=2, prefix=2001:DB8:0:12::/64
Mar 1 00:35:53.387: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 00:35:53.387: src=FE80::3
Mar 1 00:35:53.387: dst=FF02::9 (Serial0/0)
Mar 1 00:35:53.391: sport=521, dport=521, length=72
Mar 1 00:35:53.391: command=2, version=1, mbz=0, #rte=3
Mar 1 00:35:53.391: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:35:53.391: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:35:53.391: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 00:35:53.395: RIPng: Sending multicast update on FastEthernet0/0 for test
Mar 1 00:35:53.395: src=FE80::3
Mar 1 00:35:53.395: dst=FF02::9 (FastEthernet0/0)
Mar 1 00:35:53.399: sport=521, dport=521, length=72
Mar 1 00:35:53.399: command=2, version=1, mbz=0, #rte=3
Mar 1 00:35:53.399: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:35:53.399: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:35:53.399: tag=0, metric=2, prefix=2001:DB8:0:12::/64
Mar 1 00:36:19.371: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 00:36:19.371: src=FE80::3
Mar 1 00:36:19.371: dst=FF02::9 (Serial0/0)
Mar 1 00:36:19.375: sport=521, dport=521, length=72
Mar 1 00:36:19.375: command=2, version=1, mbz=0, #rte=3
Mar 1 00:36:19.375: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:36:19.375: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:36:19.375: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 00:36:19.379: RIPng: Sending multicast update on FastEthernet0/0 for test
Mar 1 00:36:19.379: src=FE80::3
Mar 1 00:36:19.379: dst=FF02::9 (FastEthernet0/0)
Mar 1 00:36:19.383: sport=521, dport=521, length=72
Mar 1 00:36:19.383: command=2, version=1, mbz=0, #rte=3
Mar 1 00:36:19.383: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 00:36:19.383: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 00:36:19.383: tag=0, metric=2, prefix=2001:DB8:0:12::/64
Mar 1 00:36:20.703: RIPng: Deleting 2001:DB8:0:4444::/64
Mar 1 00:36:20.703: RIPng: Next RIB walk in 159284

11-r3-ripng-database

 

 

Next we will look at the holddown timer, first in RIPv1/2.  The holddown timer prevents updates for a route from being accepted until it expires under certain conditions.  By default, the holddown timer is 180 seconds:

12-r3-show-ip-protocols

For testing out the holddown timer, we will add an additional link between R1 and R4:

rip-timers22

R1:
interface Serial0/1
 ip address 10.0.14.1 255.255.255.0
 ipv6 address 2001:DB8:0:14::1/64
 ipv6 address FE80::1 link-local
 ipv6 rip test enable
 

R4:
interface Serial0/0
 ip address 10.0.14.4 255.255.255.0
 ipv6 address 2001:DB8:0:14::4/64
 ipv6 address FE80::4 link-local
 ipv6 rip test enable

The holddown timer is perhaps the most confusing and poorly explained of the RIP timers.  The sources I’ve looked at each say slightly different things about what it does, none of which is completely correct.  We will first look at what the holddown timer doesn’t do by testing out what various sources say about it.  From Routing TCP/IP Volume 1:

If the distance to a destination increases (for example, the hop count increases from two to four), the router sets a holddown timer for that route. Until the timer expires, the router will not accept any new updates for the route.

and also:

The third timer is the holddown timer, although RFC 1058 does not call for the use of holddowns. The Cisco implementation of RIP does use them. An update with a hop count higher than the metric recorded in the route table will cause the route to go into holddown for 180 seconds (again, six update periods).

This says if the metric from the current best source increases, the route is placed in holddown.  R3 currently has a 1 hop route to 4.4.4.0/24 through R4.  We will offset the metric for the route by 1 outbound on R4 and see if the route gets placed in holddown:

R4:
access-list 1 permit 4.4.4.0

!
router rip
 offset-list 1 out 1 FastEthernet0/0

R3#debug ip routing
R3#debug ip rip

Mar 1 02:38:09.167: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 02:38:09.171: 4.4.4.0/24 via 0.0.0.0 in 2 hops
Mar 1 02:38:09.171: RT: rip's 4.4.4.0/24 (via 10.0.34.4) metric changed from distance/metric [120/1] to [120/2]
Mar 1 02:38:09.171: RT: NET-RED 4.4.4.0/24
Mar 1 02:38:09.175: 10.0.12.0/24 via 0.0.0.0 in 2 hops
Mar 1 02:38:09.175: 10.0.14.0/24 via 0.0.0.0 in 1 hops
Mar 1 02:38:11.175: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 02:38:11.175: RIP: build flash update entries - suppressing null update
Mar 1 02:38:11.175: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 02:38:11.179: RIP: build flash update entries
Mar 1 02:38:11.179: 4.4.4.0/24 via 0.0.0.0, metric 3, tag 0

12-r3-show-ip-route

Instead of placing the route in holddown, R3 accepts the increased metric immediately, records it in the RIP database and routing table, and sends a flash update on S0/0 2 seconds later about the increased metric.

 

 

From the 12.4 Command Reference:

A route enters into a holddown state when an update packet is received that indicates the route is unreachable. The route is marked inaccessible and advertised as unreachable. However, the route is still used for forwarding packets. When holddown expires, routes advertised by other sources are accepted and the route is no longer inaccessible.

Based on this description, if we shut down R4’s loopback so that it is advertised as unreachable, R3 should place the route into holddown.  If we bring it back up a few seconds later, the update should be ignored by R3.  Let’s test this out:

R4:
interface Loopback0
 shutdown

R3#debug ip routing
R3#debug ip rip

Mar 1 02:56:04.723: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 02:56:04.723: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 02:56:04.727: RT: del 4.4.4.0/24 via 10.0.34.4, rip metric [120/2]
Mar 1 02:56:04.727: RT: delete subnet route to 4.4.4.0/24
Mar 1 02:56:04.727: RT: NET-RED 4.4.4.0/24
Mar 1 02:56:04.731: RT: delete network route to 4.0.0.0
Mar 1 02:56:04.731: RT: NET-RED 4.0.0.0/8
Mar 1 02:56:06.731: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 02:56:06.731: RIP: build flash update entries
Mar 1 02:56:06.731: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 02:56:06.735: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 02:56:06.735: RIP: build flash update entries
Mar 1 02:56:06.735: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0

R4:
interface Loopback0
 no shutdown

R3#debug ip routing
R3#debug ip rip

Mar 1 02:56:19.587: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 02:56:19.587: 4.4.4.0/24 via 0.0.0.0 in 2 hops
Mar 1 02:56:19.591: RT: SET_LAST_RDB for 4.4.4.0/24
NEW rdb: via 10.0.34.4
Mar 1 02:56:19.591: RT: add 4.4.4.0/24 via 10.0.34.4, rip metric [120/2]
Mar 1 02:56:19.591: RT: NET-RED 4.4.4.0/24
Mar 1 02:56:21.595: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 02:56:21.595: RIP: build flash update entries - suppressing null update
Mar 1 02:56:21.595: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 02:56:21.599: RIP: build flash update entries
Mar 1 02:56:21.599: 4.4.4.0/24 via 0.0.0.0, metric 3, tag 0

R3 receives the flash update from R4 advertising 4.4.4.0/24 as unreachable, removes it from the routing table, and sends a flash update on S0/0 advertising it as unreachable.  When R4’s loopback comes back up and R3 receives a flash update advertising it as reachable 15 seconds later, R3 accepts the update immediately – so the route is clearly not in holddown.  The count-to-infinity problem – which the holddown timer is supposed to prevent – can even occur in this scenario with some unlucky timing of updates.  With all interfaces back up and the network converged, we will shutdown the R4 loopback again:

R4:
interface Loopback0
 shutdown

R3 receives the flash update from R4 at 03:11:03.063 and immediately deletes the route:

R3#debug ip routing
R3#debug ip rip

Mar 1 03:11:03.063: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 03:11:03.063: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 03:11:03.063: RT: del 4.4.4.0/24 via 10.0.34.4, rip metric [120/2]
Mar 1 03:11:03.063: RT: delete subnet route to 4.4.4.0/24
Mar 1 03:11:03.063: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:03.063: RT: delete network route to 4.0.0.0
Mar 1 03:11:03.063: RT: NET-RED 4.0.0.0/8
Mar 1 03:11:03.067: 10.0.12.0/24 via 0.0.0.0 in 2 hops
Mar 1 03:11:03.067: 10.0.14.0/24 via 0.0.0.0 in 1 hops

R2’s periodic update timer for the R2-R3 link happens to expire right after this.  R2 has not gotten the flash update yet that 4.4.4.0/24 is unreachable, so R2’s update includes 4.4.4.0/24 with a metric of 3.  R3 receives the periodic update from R2 at 03:11:04.987, approximately 1.9 seconds after the flash update was received from R4:

R3#debug ip routing
R3#debug ip rip

Mar 1 03:11:04.987: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 03:11:04.987: 4.4.4.0/24 via 0.0.0.0 in 3 hops
Mar 1 03:11:04.991: RT: SET_LAST_RDB for 4.4.4.0/24
NEW rdb: via 10.0.23.2
Mar 1 03:11:04.991: RT: add 4.4.4.0/24 via 10.0.23.2, rip metric [120/3]
Mar 1 03:11:04.995: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:04.995: 10.0.12.0/24 via 0.0.0.0 in 1 hops
Mar 1 03:11:04.995: 10.0.14.0/24 via 0.0.0.0 in 2 hops

At 03:11:05.063, exactly 2 seconds after the flash update from R4 was received, R3 sends a flash update for 4.4.4.0/24 – however the flash update does not list the route as unreachable, which caused the flash update to occur in the first place, but rather in it’s current state.  This is key to what allows the problem to occur.  Flash updates are delayed for 2 seconds and once the delay period expires, updates are sent for the route in whatever current state it is in.  R3 increments the metric and sends a flash update for the route back to R4.  R3 does not send a flash update for the route to R2 due to split-horizon rules:

R3#debug ip rip
Mar 1 03:11:05.063: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 03:11:05.063: RIP: build flash update entries
Mar 1 03:11:05.063: 4.4.4.0/24 via 0.0.0.0, metric 4, tag 0
Mar 1 03:11:05.067: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 03:11:05.067: RIP: build flash update entries - suppressing null update

R4 receives the update from R3, adds the route to the RIP database and routing table, and starts the 2 second delay for it’s flash update about the route:

R4#debug ip routing
R4#debug ip rip

Mar 1 03:11:05.203: RIP: received v2 update from 10.0.34.3 on FastEthernet0/0
Mar 1 03:11:05.203: 4.4.4.0/24 via 0.0.0.0 in 4 hops
Mar 1 03:11:05.207: RT: SET_LAST_RDB for 4.4.4.0/24
NEW rdb: via 10.0.34.3
Mar 1 03:11:05.207: RT: add 4.4.4.0/24 via 10.0.34.3, rip metric [120/4]
Mar 1 03:11:05.207: RT: NET-RED 4.4.4.0/24
 

R2 receives a flash update from R1 at about the same time advertising the route as unreachable. R2 removes the route from the routing table and also starts it’s 2 second flash update delay for the route:

R2#debug ip routing
R2#debug ip rip

Mar 1 03:11:05.739: RIP: received v2 update from 10.0.12.1 on Serial0/0
Mar 1 03:11:05.739: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 03:11:05.743: RT: del 4.4.4.0/24 via 10.0.12.1, rip metric [120/2]
Mar 1 03:11:05.743: RT: delete subnet route to 4.4.4.0/24
Mar 1 03:11:05.743: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:05.747: RT: delete network route to 4.0.0.0
Mar 1 03:11:05.747: RT: NET-RED 4.0.0.0/8

On R4, the 2 second delay for the flash update expires from the time it was received with a hop-count of 4 from R3.  No further updates about the route have been received during the delay period, so the hop-count is incremented and the route is advertised to R1:

R4#debug ip rip
Mar 1 03:11:07.211: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.4)
Mar 1 03:11:07.211: RIP: build flash update entries - suppressing null update
Mar 1 03:11:07.211: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.14.4)
Mar 1 03:11:07.215: RIP: build flash update entries
Mar 1 03:11:07.215: 4.4.4.0/24 via 0.0.0.0, metric 5, tag 0

On R2, the 2 second delay expires as well from the time it was received with an unreachable metric from R1.  No further changes have occurred so the route is advertised as unreachable out all interfaces:

R2#debug ip rip
Mar 1 03:11:07.747: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 03:11:07.747: RIP: build flash update entries
Mar 1 03:11:07.747: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 03:11:07.751: RIP: sending v2 flash update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 03:11:07.751: RIP: build flash update entries
Mar 1 03:11:07.751: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
 

R3 receives the flash update from R2, deletes the route, and starts the 2 second flash update delay.  However, the update arrives too late, as R3 already incorrectly advertised the route to R4 approximately 3 seconds earlier.  This results in 2 circles of updates, 1 advertising the route as unreachable and 1 with an incrementing hop-count.  The 2 updates will circulate approximately every 8 seconds (4x the flash update delay) and the route will be continually added and removed until eventually the incrementing hop-count reaches 16:

R3#debug ip routing
R3#debug ip rip
Mar 1 03:11:08.143: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 03:11:08.143: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 03:11:08.147: RT: del 4.4.4.0/24 via 10.0.23.2, rip metric [120/3]
Mar 1 03:11:08.147: RT: delete subnet route to 4.4.4.0/24
Mar 1 03:11:08.147: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:08.151: RT: delete network route to 4.0.0.0
Mar 1 03:11:08.151: RT: NET-RED 4.0.0.0/8
Mar 1 03:11:10.151: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 03:11:10.151: RIP: build flash update entries
Mar 1 03:11:10.151: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 03:11:10.155: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 03:11:10.155: RIP: build flash update entries
Mar 1 03:11:10.155: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 03:11:11.235: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 03:11:11.235: 4.4.4.0/24 via 0.0.0.0 in 7 hops
Mar 1 03:11:11.239: RT: SET_LAST_RDB for 4.4.4.0/24
NEW rdb: via 10.0.23.2
Mar 1 03:11:11.239: RT: add 4.4.4.0/24 via 10.0.23.2, rip metric [120/7]
Mar 1 03:11:11.239: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:13.243: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 03:11:13.243: RIP: build flash update entries
Mar 1 03:11:13.243: 4.4.4.0/24 via 0.0.0.0, metric 8, tag 0
Mar 1 03:11:13.247: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 03:11:13.247: RIP: build flash update entries - suppressing null update
Mar 1 03:11:14.483: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 03:11:14.483: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 03:11:14.483: RT: del 4.4.4.0/24 via 10.0.23.2, rip metric [120/7]
Mar 1 03:11:14.487: RT: delete subnet route to 4.4.4.0/24
Mar 1 03:11:14.487: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:14.487: RT: delete network route to 4.0.0.0
Mar 1 03:11:14.487: RT: NET-RED 4.0.0.0/8
Mar 1 03:11:16.487: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 03:11:16.487: RIP: build flash update entries
Mar 1 03:11:16.487: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 03:11:16.491: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 03:11:16.491: RIP: build flash update entries
Mar 1 03:11:16.491: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 03:11:19.375: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 03:11:19.375: 4.4.4.0/24 via 0.0.0.0 in 11 hops
Mar 1 03:11:19.375: RT: SET_LAST_RDB for 4.4.4.0/24
NEW rdb: via 10.0.23.2
Mar 1 03:11:19.379: RT: add 4.4.4.0/24 via 10.0.23.2, rip metric [120/11]
Mar 1 03:11:19.379: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:21.379: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 03:11:21.379: RIP: build flash update entries
Mar 1 03:11:21.379: 4.4.4.0/24 via 0.0.0.0, metric 12, tag 0
Mar 1 03:11:21.383: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 03:11:21.383: RIP: build flash update entries - suppressing null update
Mar 1 03:11:22.587: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 03:11:22.587: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 03:11:22.587: RT: del 4.4.4.0/24 via 10.0.23.2, rip metric [120/11]
Mar 1 03:11:22.591: RT: delete subnet route to 4.4.4.0/24
Mar 1 03:11:22.591: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:22.591: RT: delete network route to 4.0.0.0
Mar 1 03:11:22.595: RT: NET-RED 4.0.0.0/8
Mar 1 03:11:24.595: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 03:11:24.595: RIP: build flash update entries
Mar 1 03:11:24.595: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 03:11:24.599: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 03:11:24.599: RIP: build flash update entries
Mar 1 03:11:24.599: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0 
Mar 1 03:11:27.619: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 03:11:27.619: 4.4.4.0/24 via 0.0.0.0 in 15 hops
Mar 1 03:11:27.623: RT: SET_LAST_RDB for 4.4.4.0/24
NEW rdb: via 10.0.23.2
Mar 1 03:11:27.623: RT: add 4.4.4.0/24 via 10.0.23.2, rip metric [120/15]
Mar 1 03:11:27.627: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:29.627: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 03:11:29.627: RIP: build flash update entries
Mar 1 03:11:29.627: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 03:11:29.631: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 03:11:29.631: RIP: build flash update entries - suppressing null update
Mar 1 03:11:30.139: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 03:11:30.139: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 03:11:30.139: RT: del 4.4.4.0/24 via 10.0.23.2, rip metric [120/15]
Mar 1 03:11:30.139: RT: delete subnet route to 4.4.4.0/24
Mar 1 03:11:30.143: RT: NET-RED 4.4.4.0/24
Mar 1 03:11:30.143: RT: delete network route to 4.0.0.0
Mar 1 03:11:30.143: RT: NET-RED 4.0.0.0/8
Mar 1 03:11:32.147: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 03:11:32.147: RIP: build flash update entries
Mar 1 03:11:32.147: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 03:11:32.151: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 03:11:32.151: RIP: build flash update entries
Mar 1 03:11:32.151: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0

 

 

From Cisco Press ICND 2:

After hearing a poisoned route, start a holddown timer for that one route. Until the timer expires, do not believe any other routing information about the failed route, because believing that information may cause a routing loop. However, information learned from the neighbor that originally advertised the working route can be believed before the holddown timer expires.

This says the same thing as the command reference, with the addition of allowing information from the original route source to be believed during the holddown.  We will test this out on R2.  With all interfaces up again, R2 currently has a 2-hop route to 4.4.4.0/24 through R1:

13-r2-show-ip-route

The route through R3 is 3 hops because of the offset-list we applied on R4 F0/0 earlier, so it is not in the routing table or RIP database.  If the route is advertised as unreachable by R1, and then R2 receives an update from R3 advertising it as metric 3, it should be ignored based on the definition above.  To test this out, we will first shut down R4 F0/0 and then shut down R4’s loopback:

R4:
interface FastEthernet0/0
 shutdown
!
interface Loopback0
 shutdown

R4 sends a flash update advertising the route as unreachable, and R1 sends a flash update to R2.  R3 does not receive an update from R4 so it will continue advertising 4.4.4.0/24 to R2 as reachable until the invalid timer expires for the route:

R2#debug ip routing
R2#debug ip rip

Mar 1 04:09:43.699: RIP: received v2 update from 10.0.12.1 on Serial0/0
Mar 1 04:09:43.699: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 04:09:43.703: RT: del 4.4.4.0/24 via 10.0.12.1, rip metric [120/2]
Mar 1 04:09:43.703: RT: delete subnet route to 4.4.4.0/24
Mar 1 04:09:43.703: RT: NET-RED 4.4.4.0/24
Mar 1 04:09:43.707: RT: delete network route to 4.0.0.0
Mar 1 04:09:43.707: RT: NET-RED 4.0.0.0/8
Mar 1 04:09:43.707: 10.0.14.0/24 via 0.0.0.0 in 1 hops
Mar 1 04:09:45.707: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 04:09:45.707: RIP: build flash update entries
Mar 1 04:09:45.707: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:09:45.711: RIP: sending v2 flash update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 04:09:45.711: RIP: build flash update entries
Mar 1 04:09:45.711: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:09:55.147: RIP: received v2 update from 10.0.23.3 on Serial0/1
Mar 1 04:09:55.147: 4.4.4.0/24 via 0.0.0.0 in 3 hops
Mar 1 04:09:55.151: RT: SET_LAST_RDB for 4.4.4.0/24
NEW rdb: via 10.0.23.3
Mar 1 04:09:55.151: RT: add 4.4.4.0/24 via 10.0.23.3, rip metric [120/3]
Mar 1 04:09:55.155: RT: NET-RED 4.4.4.0/24
Mar 1 04:09:55.155: 10.0.14.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:09:55.155: 10.0.34.0/24 via 0.0.0.0 in 1 hops
Mar 1 04:09:57.155: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 04:09:57.155: RIP: build flash update entries
Mar 1 04:09:57.155: 4.4.4.0/24 via 0.0.0.0, metric 4, tag 0
Mar 1 04:09:57.159: RIP: sending v2 flash update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 04:09:57.159: RIP: build flash update entries - suppressing null update

R2 receives one of R3’s periodic updates about 12 seconds after hearing of the unreachable route from R1 and, despite what the book says, accepts the information immediately from R3.  Until the invalid timer expires on R3, all 4 routers have incorrect routing information.  R4 now believes it has a 5-hop route to it’s own former network through R1:

14-r4-show-ip-route

If R4 F0/0 comes back up before the invalid expires on R3, a different type of count-to-infinity problem occurs.  R3 still believes it has a route to 4.4.4.0/24 through R4 since it did not receive the update advertising it as unreachable while R4 F0/0 was down.  R4 believes it knows 4.4.4.0/24 through R1, so split-horizon will not prevent R4 from advertising it to R3 now that F0/0 is back up.  An increased metric received does not cause holddown to occur as we saw earlier, so when R3 receives an update from R4, a single circle of updates occurs with the metric increasing by 5 each time (4 routers + 1 from the offset) until it reaches 16:

R2#debug ip routing
R2#debug ip rip

Mar 1 04:11:08.355: RIP: received v2 update from 10.0.23.3 on Serial0/1
Mar 1 04:11:08.355: 4.4.4.0/24 via 0.0.0.0 in 8 hops
Mar 1 04:11:08.359: RT: rip's 4.4.4.0/24 (via 10.0.23.3) metric changed from distance/metric [120/3] to [120/8]
Mar 1 04:11:08.359: RT: NET-RED 4.4.4.0/24
Mar 1 04:11:10.363: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 04:11:10.363: RIP: build flash update entries
Mar 1 04:11:10.363: 4.4.4.0/24 via 0.0.0.0, metric 9, tag 0
Mar 1 04:11:10.367: RIP: sending v2 flash update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 04:11:10.367: RIP: build flash update entries - suppressing null update
Mar 1 04:11:16.475: RIP: received v2 update from 10.0.23.3 on Serial0/1
Mar 1 04:11:16.479: 4.4.4.0/24 via 0.0.0.0 in 13 hops
Mar 1 04:11:16.479: RT: rip's 4.4.4.0/24 (via 10.0.23.3) metric changed from distance/metric [120/8] to [120/13]
Mar 1 04:11:16.479: RT: NET-RED 4.4.4.0/24
Mar 1 04:11:18.483: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 04:11:18.483: RIP: build flash update entries
Mar 1 04:11:18.483: 4.4.4.0/24 via 0.0.0.0, metric 14, tag 0
Mar 1 04:11:18.487: RIP: sending v2 flash update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 04:11:18.487: RIP: build flash update entries - suppressing null update
Mar 1 04:11:24.703: RIP: received v2 update from 10.0.23.3 on Serial0/1
Mar 1 04:11:24.703: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 04:11:24.703: RT: del 4.4.4.0/24 via 10.0.23.3, rip metric [120/13]
Mar 1 04:11:24.703: RT: delete subnet route to 4.4.4.0/24
Mar 1 04:11:24.703: RT: NET-RED 4.4.4.0/24
Mar 1 04:11:24.707: RT: delete network route to 4.0.0.0
Mar 1 04:11:24.707: RT: NET-RED 4.0.0.0/8
Mar 1 04:11:26.707: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 04:11:26.707: RIP: build flash update entries
Mar 1 04:11:26.707: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:11:26.707: RIP: sending v2 flash update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 04:11:26.707: RIP: build flash update entries
Mar 1 04:11:26.707: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0

 

 

So what exactly causes holddown to occur?  Earlier when we looked at the invalid timer, we saw the route placed into holddown when the invalid timer expired.  As it turns out, this is the only time that the holddown timer is used.  Let’s look at an example where we can see this being used.  We will shut down R4 F0/0.  The last update is received at 04:36:16.207.  After 180 seconds, the invalid expires and we see the message about the route entering holddown:

R3#debug ip rip
Mar 1 04:36:16.207: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 04:36:16.211: 4.4.4.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:36:16.211: 10.0.12.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:36:16.211: 10.0.14.0/24 via 0.0.0.0 in 1 hops

R4:
interface FastEthernet0/0
 shutdown

R3#debug ip routing
R3#debug ip rip
Mar 1 04:39:19.843: RT: delete route to 4.4.4.0 via 10.0.34.4, rip metric [120/2]
Mar 1 04:39:19.843: RT: SET_LAST_RDB for 4.4.4.0/24
OLD rdb: via 11.13.11.13
Mar 1 04:39:19.843: RT: no routes to 4.4.4.0, entering holddown
Mar 1 04:39:19.843: RT: NET-RED 4.4.4.0/24
Mar 1 04:39:19.843: RT: delete route to 10.0.14.0 via 10.0.34.4, rip metric [120/1]
Mar 1 04:39:19.843: RT: SET_LAST_RDB for 10.0.14.0/24
OLD rdb: via 11.13.11.13
Mar 1 04:39:19.843: RT: no routes to 10.0.14.0, entering holddown
Mar 1 04:39:19.843: RT: NET-RED 10.0.14.0/24
Mar 1 04:39:21.843: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 04:39:21.843: RIP: build flash update entries
Mar 1 04:39:21.843: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:39:21.843: 10.0.14.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:39:21.843: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 04:39:21.843: RIP: build flash update entries
Mar 1 04:39:21.843: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:39:21.843: 10.0.14.0/24 via 0.0.0.0, metric 16, tag 0

R3 receives an update from R2 advertising 4.4.4.0/24 with hop-count 3 a few seconds later, but the update is ignored because the route is in holddown:

R3#debug ip routing
Mar 1 04:39:38.135: RIP: received v2 update from 10.0.23.2 on Serial0/0
Mar 1 04:39:38.135: 4.4.4.0/24 via 0.0.0.0 in 3 hops
Mar 1 04:39:38.139: 10.0.12.0/24 via 0.0.0.0 in 1 hops
Mar 1 04:39:38.139: 10.0.14.0/24 via 0.0.0.0 in 2 hops

Let’s bring R4 F0/0 back up and see if R3 accepts the update from the original source:

R4:
interface FastEthernet0/0
 no shutdown

R3#debug ip rip
Mar 1 04:40:01.583: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 04:40:01.583: 4.4.4.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:40:01.587: 10.0.12.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:40:01.587: 10.0.14.0/24 via 0.0.0.0 in 1 hops

R3 ignores the update from the original source as well during the holddown period and continues advertising the route as unreachable out both interfaces:

R3#debug ip rip
Mar 1 04:40:05.363: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 04:40:05.363: RIP: build update entries
Mar 1 04:40:05.363: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:40:05.367: 10.0.14.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:40:05.367: 10.0.34.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 04:40:13.039: RIP: sending v2 update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 04:40:13.039: RIP: build update entries
Mar 1 04:40:13.039: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:40:13.043: 10.0.12.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 04:40:13.043: 10.0.14.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:40:13.043: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0

60 seconds after the invalid expired, the flush timer expires and the route is deleted:

R3#debug ip routing
Mar 1 04:40:19.843: RT: delete subnet route to 4.4.4.0/24
Mar 1 04:40:19.843: RT: NET-RED 4.4.4.0/24
Mar 1 04:40:19.843: RT: delete network route to 4.0.0.0
Mar 1 04:40:19.843: RT: NET-RED 4.0.0.0/8
Mar 1 04:40:19.843: RT: delete subnet route to 10.0.14.0/24
Mar 1 04:40:19.843: RT: NET-RED 10.0.14.0/24

When R3 receives the next periodic update from R4 a few seconds later, 4.4.4.0/24 and 10.0.14.0/24 are added back to the routing table and RIP database:

R3#debug ip routing
R3#debug ip rip
Mar 1 04:40:30.083: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 04:40:30.083: 4.4.4.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:40:30.087: RT: SET_LAST_RDB for 4.4.4.0/24
NEW rdb: via 10.0.34.4
Mar 1 04:40:30.087: RT: add 4.4.4.0/24 via 10.0.34.4, rip metric [120/2]
Mar 1 04:40:30.087: RT: NET-RED 4.4.4.0/24
Mar 1 04:40:30.091: 10.0.12.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:40:30.091: 10.0.14.0/24 via 0.0.0.0 in 1 hops
Mar 1 04:40:30.095: RT: SET_LAST_RDB for 10.0.14.0/24
NEW rdb: via 10.0.34.4
Mar 1 04:40:30.095: RT: add 10.0.14.0/24 via 10.0.34.4, rip metric [120/1]
Mar 1 04:40:30.095: RT: NET-RED 10.0.14.0/24

Wait a minute, if the holddown timer is 180 seconds by default shouldn’t updates be ignored for another 120 seconds?  If the flush timer expires before the holddown timer does, the route no longer exists in either the RIP database or routing table so any updates will be accepted for it.  Therefore, the effective holddown period is the lesser of the configured holddown timer and the flush minus the invalid timer.  Let’s repeat this with a holddown timer of 30 seconds to demonstrate this:

R3:
router rip
 timers basic 30 180 30 240

R3#debug ip rip
Mar 1 04:50:25.167: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 04:50:25.167: 4.4.4.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:50:25.171: 10.0.12.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:50:25.171: 10.0.14.0/24 via 0.0.0.0 in 1 hops

R4:
interface FastEthernet0/0
 shutdown

The routes enter holddown at 04:53:27.827:

R3#debug ip routing
R3#debug ip rip

Mar 1 04:53:27.823: RT: delete route to 4.4.4.0 via 10.0.34.4, rip metric [120/2]
Mar 1 04:53:27.823: RT: SET_LAST_RDB for 4.4.4.0/24
OLD rdb: via 11.13.11.13
Mar 1 04:53:27.827: RT: no routes to 4.4.4.0, entering holddown
Mar 1 04:53:27.827: RT: NET-RED 4.4.4.0/24
Mar 1 04:53:27.827: RT: delete route to 10.0.14.0 via 10.0.34.4, rip metric [120/1]
Mar 1 04:53:27.831: RT: SET_LAST_RDB for 10.0.14.0/24
OLD rdb: via 11.13.11.13
Mar 1 04:53:27.831: RT: no routes to 10.0.14.0, entering holddown
Mar 1 04:53:27.831: RT: NET-RED 10.0.14.0/24
Mar 1 04:53:29.827: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 04:53:29.827: RIP: build flash update entries
Mar 1 04:53:29.827: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:53:29.831: 10.0.14.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:53:29.831: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 04:53:29.831: RIP: build flash update entries
Mar 1 04:53:29.831: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 04:53:29.835: 10.0.14.0/24 via 0.0.0.0, metric 16, tag 0

After bringing R4 F0/0 back up, R3 receives a periodic update from R4 a little over 30 seconds after the routes entered holddown.  We see a log message stating that the routes have come out of holddown and the new routing information has been accepted:

R3#debug ip routing
R3#debug ip rip

Mar 1 04:53:59.203: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 04:53:59.203: 4.4.4.0/24 via 0.0.0.0 in 2 hops
Mar 1 04:53:59.203: RT: 4.4.4.0 came out of holddown
Mar 1 04:53:59.203: RT: SET_LAST_RDB for 4.4.4.0/24
NEW rdb: via 10.0.34.4
Mar 1 04:53:59.203: RT: add 4.4.4.0/24 via 10.0.34.4, rip metric [120/2]
Mar 1 04:53:59.203: RT: NET-RED 4.4.4.0/24
Mar 1 04:53:59.203: 10.0.12.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 04:53:59.207: 10.0.14.0/24 via 0.0.0.0 in 1 hops
Mar 1 04:53:59.207: RT: 10.0.14.0 came out of holddown
Mar 1 04:53:59.207: RT: SET_LAST_RDB for 10.0.14.0/24
NEW rdb: via 10.0.34.4
Mar 1 04:53:59.207: RT: add 10.0.14.0/24 via 10.0.34.4, rip metric [120/1]
Mar 1 04:53:59.211: RT: NET-RED 10.0.14.0/24
Mar 1 04:54:01.203: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 04:54:01.203: RIP: build flash update entries - suppressing null update
Mar 1 04:54:01.203: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 04:54:01.207: RIP: build flash update entries
Mar 1 04:54:01.207: 4.4.4.0/24 via 0.0.0.0, metric 3, tag 0
Mar 1 04:54:01.207: 10.0.14.0/24 via 0.0.0.0, metric 2, tag 0

 

So now we’ve seen how the holddown timer actually works, but this brings up another question:  If the route isn’t being placed in holddown when an unreachable update is received, what exactly is happening and how does the router know how long to pass the unreachable advertisement along?  The behavior is similar to when the invalid timer first expires on a router, with 2 exceptions:

1.  The route is not placed in holddown

2.  The route is maintained only in the RIP database.  It is removed from the routing table immediately and therefore not used to forward packets.

A router receiving an unreachable advertisement keeps the route in the RIP database for (flush – invalid) seconds and continues including it in updates as long as it is there.  This means that when an unreachable route is received, the actual values of the flush and invalid are not important for controlling how long the route continues to be advertised, only the difference between them.  To demonstrate this, we will change the flush and invalid timers on R1, R2, and R3.  The flush timer on R1 will be lowered to 180, the same as the invalid.  The invalid timer on R2 will be lowered to 60 while keeping the default flush of 240.  The invalid and flush will both be set to very high values on R3 while maintaining the difference of 60 between the two:

R1:
router rip
 timers basic 30 180 180 180

R2:
router rip
 timers basic 30 60 180 240

R3:
router rip
 timers basic 30 10000 180 10060

We will then shut down R4’s loopback.  All other interfaces are up, so the other 3 routers will learn of the failed route by an unreachable advertisement rather than by their invalid timer expiring:

R4:
interface Loopback0
 shutdown

Each of the routers hears of the failed route at approximately 05:34:33.  R1, whose (flush – invalid) is 0 seconds, keeps the failed route in the RIP database just long enough to send a flash update out all interfaces.  There is no log message showing when a route is removed from the RIP database, but we can see that at the first periodic update the route is no longer included:

R1#debug ip routing
R1#debug ip rip

Mar 1 05:34:32.799: RIP: received v2 update from 10.0.14.4 on Serial0/1
Mar 1 05:34:32.799: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 05:34:32.799: RT: del 4.4.4.0/24 via 10.0.14.4, rip metric [120/1]
Mar 1 05:34:32.803: RT: delete subnet route to 4.4.4.0/24
Mar 1 05:34:32.803: RT: NET-RED 4.4.4.0/24
Mar 1 05:34:32.803: RT: delete network route to 4.0.0.0
Mar 1 05:34:32.807: RT: NET-RED 4.0.0.0/8
Mar 1 05:34:32.807: 10.0.23.0/24 via 0.0.0.0 in 2 hops
Mar 1 05:34:32.807: 10.0.34.0/24 via 0.0.0.0 in 1 hops
Mar 1 05:34:34.807: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.12.1)
Mar 1 05:34:34.807: RIP: build flash update entries
Mar 1 05:34:34.807: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 05:34:34.811: RIP: sending v2 flash update to 224.0.0.9 via Serial0/1 (10.0.14.1)
Mar 1 05:34:34.811: RIP: build flash update entries
Mar 1 05:34:34.811: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 05:34:46.087: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.14.1)
Mar 1 05:34:46.087: RIP: build update entries
Mar 1 05:34:46.087: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0

Mar 1 05:34:46.091: 10.0.23.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 05:34:48.039: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.12.1)
Mar 1 05:34:48.039: RIP: build update entries
Mar 1 05:34:48.039: 10.0.14.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 05:34:48.043: 10.0.34.0/24 via 0.0.0.0, metric 2, tag 0

R2’s flush – invalid is 180 seconds, which is approximately how long the route continues to be advertised for.  Only the last of it’s periodic updates that include 4.4.4.0/24 and the first of it’s periodic updates that exclude it are shown to keep the output shorter:

R2#debug ip routing
R2#debug ip rip
Mar 1 05:34:35.691: RIP: received v2 update from 10.0.12.1 on Serial0/0
Mar 1 05:34:35.691: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 05:34:35.691: RT: del 4.4.4.0/24 via 10.0.12.1, rip metric [120/2]
Mar 1 05:34:35.695: RT: delete subnet route to 4.4.4.0/24
Mar 1 05:34:35.695: RT: NET-RED 4.4.4.0/24
Mar 1 05:34:35.695: RT: delete network route to 4.0.0.0
Mar 1 05:34:35.695: RT: NET-RED 4.0.0.0/8
Mar 1 05:34:37.699: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 05:34:37.699: RIP: build flash update entries
Mar 1 05:34:37.699: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 05:34:37.703: RIP: sending v2 flash update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 05:34:37.703: RIP: build flash update entries
Mar 1 05:34:37.703: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0

15-r2-show-ip-route

15-r2-rip-database

R2#debug ip rip
R2#debug ip routing

Mar 1 05:37:11.683: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 05:37:11.683: RIP: build update entries
Mar 1 05:37:11.683: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 05:37:11.687: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 05:37:11.687: 10.0.14.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 05:37:13.375: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 05:37:13.375: RIP: build update entries
Mar 1 05:37:13.375: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 05:37:13.379: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 05:37:13.379: 10.0.34.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 05:37:39.963: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.12.2)
Mar 1 05:37:39.963: RIP: build update entries
Mar 1 05:37:39.963: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 05:37:39.967: 10.0.34.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 05:37:40.167: RIP: sending v2 update to 224.0.0.9 via Serial0/1 (10.0.23.2)
Mar 1 05:37:40.167: RIP: build update entries
Mar 1 05:37:40.167: 10.0.12.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 05:37:40.167: 10.0.14.0/24 via 0.0.0.0, metric 2, tag 0

16-r2-rip-database

R3’s flush – invalid is 60 seconds, and even though we set them to very high values, we can see that the failed route is advertised for 60 seconds just like the default.  Again, only the last periodic update including 4.4.4.0/24 and first periodic update excluding it are shown:

R3#debug ip routing
R3#debug ip rip

Mar 1 05:34:35.407: RIP: received v2 update from 10.0.34.4 on FastEthernet0/0
Mar 1 05:34:35.407: 4.4.4.0/24 via 0.0.0.0 in 16 hops (inaccessible)
Mar 1 05:34:35.411: RT: del 4.4.4.0/24 via 10.0.34.4, rip metric [120/2]
Mar 1 05:34:35.411: RT: delete subnet route to 4.4.4.0/24
Mar 1 05:34:35.411: RT: NET-RED 4.4.4.0/24
Mar 1 05:34:35.415: RT: delete network route to 4.0.0.0
Mar 1 05:34:35.415: RT: NET-RED 4.0.0.0/8
Mar 1 05:34:37.415: RIP: sending v2 flash update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 05:34:37.415: RIP: build flash update entries
Mar 1 05:34:37.415: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 05:34:37.419: RIP: sending v2 flash update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 05:34:37.419: RIP: build flash update entries
Mar 1 05:34:37.419: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 05:35:35.875: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 05:35:35.875: RIP: build update entries
Mar 1 05:35:35.875: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 05:35:35.879: 10.0.14.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 05:35:35.879: 10.0.34.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 05:35:37.163: RIP: sending v2 update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 05:35:37.163: RIP: build update entries
Mar 1 05:35:37.163: 4.4.4.0/24 via 0.0.0.0, metric 16, tag 0
Mar 1 05:35:37.167: 10.0.12.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 05:35:37.167: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 05:36:02.035: RIP: sending v2 update to 224.0.0.9 via Serial0/0 (10.0.23.3)
Mar 1 05:36:02.035: RIP: build update entries
Mar 1 05:36:02.035: 10.0.14.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 05:36:02.039: 10.0.34.0/24 via 0.0.0.0, metric 1, tag 0
Mar 1 05:36:05.587: RIP: sending v2 update to 224.0.0.9 via FastEthernet0/0 (10.0.34.3)
Mar 1 05:36:05.587: RIP: build update entries
Mar 1 05:36:05.587: 10.0.12.0/24 via 0.0.0.0, metric 2, tag 0
Mar 1 05:36:05.591: 10.0.23.0/24 via 0.0.0.0, metric 1, tag 0

 

 

Next, we will look at the holddown timer in RIPng.  The holddown timer in RIPng is quite a bit different than in RIPv1/v2.  The default setting for the holddown timer is 0 seconds, so it is not even used in RIPng unless explicitly configured:

17-r3-ripng

If it is enabled, the holddown timer in RIPng works similarly to how the holddown timer in RIPv1/v2 is supposed to work.  Holddown in RIPng is activated by either of the following:

1.  The invalid timer expiring (same as RIPv1/v2)

2.  An unreachable route advertisement being received from the best route source 

We’ve already seen a route placed in holddown when the invalid expired in RIPv2, so let’s try it with an unreachable route advertisement in RIPng.  We will set a holddown timer of 60 seconds on R3 to test this out and keep the other timers at their defaults:

R3:
ipv6 router rip test
 timers 30 180 60 120

Next we will shutdown R4’s loopback:

R4:
interface Loopback0
 shutdown

R3 deletes the route to 4.4.4.0/24 right away after receiving an update from R4.  In the RIP database, we see that the holddown timer has begun counting down:

R3#debug ipv6 routing
R3#debug ipv6 rip

Mar 1 01:39:28.967: RIPng: response received from FE80::4 on FastEthernet0/0 for test
Mar 1 01:39:28.967: src=FE80::4 (FastEthernet0/0)
Mar 1 01:39:28.967: dst=FF02::9
Mar 1 01:39:28.971: sport=521, dport=521, length=92
Mar 1 01:39:28.971: command=2, version=1, mbz=0, #rte=4
Mar 1 01:39:28.971: tag=0, metric=1, prefix=2001:DB8:0:14::/64
Mar 1 01:39:28.971: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 01:39:28.971: tag=0, metric=2, prefix=2001:DB8:0:12::/64
Mar 1 01:39:28.971: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 01:39:28.975: RIPng: 2001:DB8:0:4444::/64, path FE80::4/FastEthernet0/0 unreachable
Mar 1 01:39:28.975: IPv6RT0: rip test, Delete 2001:DB8:0:4444::/64 from table
Mar 1 01:39:28.975: RIPng: 2001:DB8:0:4444::/64, expired, ttg is 60
Mar 1 01:39:28.979: RIPng: Triggered update requested
Mar 1 01:39:28.979: IPv6RT0: Event: 2001:DB8:0:4444::/64, Del, owner rip, previous None
Mar 1 01:39:29.979: RIPng: generating triggered update for test
Mar 1 01:39:29.979: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 01:39:29.979: src=FE80::3
Mar 1 01:39:29.979: dst=FF02::9 (Serial0/0)
Mar 1 01:39:29.979: sport=521, dport=521, length=32
Mar 1 01:39:29.979: command=2, version=1, mbz=0, #rte=1
Mar 1 01:39:29.979: tag=0, metric=16, prefix=2001:DB8:0:4444::/64
Mar 1 01:39:29.979: RIPng: Suppressed null multicast update on FastEthernet0/0 for test

17-r3-ripng-database

If we bring R4’s loopback back up before the holddown expires, R3 receives a flash update from R4.  R3 also receives a flash update from R2 since R1 and R2 are using default timers and therefore did not place the route into holddown.  R3 ignores the flash updates from both routers, and even generates log messages showing that the updates were ignored because of holddown:

R3#debug ipv6 rip
Mar 1 01:39:43.867: RIPng: response received from FE80::4 on FastEthernet0/0 for test
Mar 1 01:39:43.867: src=FE80::4 (FastEthernet0/0)
Mar 1 01:39:43.871: dst=FF02::9
Mar 1 01:39:43.871: sport=521, dport=521, length=32
Mar 1 01:39:43.871: command=2, version=1, mbz=0, #rte=1
Mar 1 01:39:43.871: tag=0, metric=1, prefix=2001:DB8:0:4444::/64
Mar 1 01:39:43.871: RIPng: 2001:DB8:0:4444::/64, held-down, ignoring update
Mar 1 01:39:47.815: RIPng: response received from FE80::2 on Serial0/0 for test
Mar 1 01:39:47.815: src=FE80::2 (Serial0/0)
Mar 1 01:39:47.819: dst=FF02::9
Mar 1 01:39:47.819: sport=521, dport=521, length=32
Mar 1 01:39:47.819: command=2, version=1, mbz=0, #rte=1
Mar 1 01:39:47.819: tag=0, metric=3, prefix=2001:DB8:0:4444::/64
Mar 1 01:39:47.819: RIPng: 2001:DB8:0:4444::/64, held-down, ignoring update

The next periodic update is ignored as well.  The first periodic update that arrives after the holddown timer has expired is accepted and the route is added back to the routing table (R2’s update arrives earlier so the metric changes when R4’s update arrives):

R3#debug ipv6 routing
R3#debug ipv6 rip

Mar 1 01:40:37.131: RIPng: response received from FE80::2 on Serial0/0 for test
Mar 1 01:40:37.131: src=FE80::2 (Serial0/0)
Mar 1 01:40:37.131: dst=FF02::9
Mar 1 01:40:37.131: sport=521, dport=521, length=92
Mar 1 01:40:37.135: command=2, version=1, mbz=0, #rte=4
Mar 1 01:40:37.135: tag=0, metric=1, prefix=2001:DB8:0:12::/64
Mar 1 01:40:37.135: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 01:40:37.135: tag=0, metric=2, prefix=2001:DB8:0:14::/64
Mar 1 01:40:37.135: tag=0, metric=3, prefix=2001:DB8:0:4444::/64
Mar 1 01:40:37.139: RIPng: 2001:DB8:0:4444::/64, metric changed to 4
Mar 1 01:40:37.139: RIPng: 2001:DB8:0:4444::/64, added path FE80::2/Serial0/0
Mar 1 01:40:37.139: IPv6RT0: rip test, Route add 2001:DB8:0:4444::/64 [new]
Mar 1 01:40:37.143: IPv6RT0: rip test, Add 2001:DB8:0:4444::/64 to table
Mar 1 01:40:37.143: IPv6RT0: rip test, Adding next-hop FE80::2 over Serial0/0 for 2001:DB8:0:4444::/64, [120/4]
Mar 1 01:40:37.143: RIPng: Triggered update requested
Mar 1 01:40:37.147: IPv6RT0: Event: 2001:DB8:0:4444::/64, Add, owner rip, previous None
Mar 1 01:40:37.779: RIPng: response received from FE80::4 on FastEthernet0/0 for test
Mar 1 01:40:37.779: src=FE80::4 (FastEthernet0/0)
Mar 1 01:40:37.783: dst=FF02::9
Mar 1 01:40:37.783: sport=521, dport=521, length=92
Mar 1 01:40:37.783: command=2, version=1, mbz=0, #rte=4
Mar 1 01:40:37.783: tag=0, metric=1, prefix=2001:DB8:0:14::/64
Mar 1 01:40:37.783: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 01:40:37.787: tag=0, metric=1, prefix=2001:DB8:0:4444::/64
Mar 1 01:40:37.787: tag=0, metric=2, prefix=2001:DB8:0:12::/64
Mar 1 01:40:37.787: RIPng: 2001:DB8:0:4444::/64, metric changed to 2
Mar 1 01:40:37.787: RIPng: 2001:DB8:0:4444::/64, added path FE80::4/FastEthernet0/0
Mar 1 01:40:37.791: IPv6RT0: rip test, Route add 2001:DB8:0:4444::/64 [better metric 2, 4]
Mar 1 01:40:37.791: IPv6RT0: rip test, Adding next-hop FE80::4 over FastEthernet0/0 for 2001:DB8:0:4444::/64, [120/2]
Mar 1 01:40:37.791: RIPng: Triggered update requested, delaying
Mar 1 01:40:37.795: IPv6RT0: Event: 2001:DB8:0:4444::/64, Mod, owner rip, previous None
Mar 1 01:40:38.143: RIPng: generating triggered update for test
Mar 1 01:40:38.143: RIPng: Sending multicast update on Serial0/0 for test
Mar 1 01:40:38.143: src=FE80::3
Mar 1 01:40:38.143: dst=FF02::9 (Serial0/0)
Mar 1 01:40:38.147: sport=521, dport=521, length=32
Mar 1 01:40:38.147: command=2, version=1, mbz=0, #rte=1
Mar 1 01:40:38.147: tag=0, metric=2, prefix=2001:DB8:0:4444::/64
Mar 1 01:40:38.151: RIPng: Suppressed null multicast update on FastEthernet0/0 for test

This partially agrees with what the last two sources had to say about how the holddown timer was supposed to work in RIPv1/v2 (however the route does not continue to be used for forwarding during the holddown and information from the original source is not accepted prior to the holddown expiring, as they say).  The Routing TCP/IP Volume 1 description of the holddown timer, which said that when a metric increases the route should be placed in holddown, still does not happen in RIPng.  R3’s current routing table looks like this:

18-r3-show-ipv6-route

R3’s best route to 2001:db8:0:14::/64 is 2 hops through R4.  We will change the hop-count added to routes received on R3 F0/0 from 1 to 7:

R3:
interface FastEthernet0/0
 ipv6 rip test metric-offset 7

When the next periodic update arrives from R4 on F0/0, R3 immediately updates the metric for the route and continues to keep it in the routing table:

R3#debug ipv6 routing
R3#debug ipv6 rip

Mar 1 01:55:46.315: RIPng: response received from FE80::4 on FastEthernet0/0 for test
Mar 1 01:55:46.315: src=FE80::4 (FastEthernet0/0)
Mar 1 01:55:46.319: dst=FF02::9
Mar 1 01:55:46.319: sport=521, dport=521, length=92
Mar 1 01:55:46.319: command=2, version=1, mbz=0, #rte=4
Mar 1 01:55:46.319: tag=0, metric=1, prefix=2001:DB8:0:34::/64
Mar 1 01:55:46.319: tag=0, metric=1, prefix=2001:DB8:0:14::/64
Mar 1 01:55:46.319: tag=0, metric=1, prefix=2001:DB8:0:4444::/64
Mar 1 01:55:46.323: tag=0, metric=2, prefix=2001:DB8:0:12::/64
Mar 1 01:55:46.323: RIPng: 2001:DB8:0:34::/64, metric changed to 8
Mar 1 01:55:46.323: RIPng: 2001:DB8:0:14::/64, metric changed to 8
Mar 1 01:55:46.323: IPv6RT0: rip test, Route add 2001:DB8:0:14::/64 [worse metric 8, 2]
Mar 1 01:55:46.327: RIPng: 2001:DB8:0:4444::/64, metric changed to 8
Mar 1 01:55:46.327: IPv6RT0: rip test, Route add 2001:DB8:0:4444::/64 [worse metric 8, 2]
Mar 1 01:55:46.327: RIPng: Triggered update requested
Mar 1 01:55:46.331: IPv6RT0: Event: 2001:DB8:0:14::/64, Mod, owner rip, previous None
Mar 1 01:55:46.331: IPv6RT0: Event: 2001:DB8:0:4444::/64, Mod, owner rip, previous None

A periodic update arrives just after this from R2, advertising the route as metric 2 (3 after R3 adds 1 to it).  R3 replaces the route from R4 with this one immediately:

R3#debug ipv6 routing
R3#debug ipv6 rip
Mar 1 01:55:47.003: RIPng: response received from FE80::2 on Serial0/0 for test
Mar 1 01:55:47.003: src=FE80::2 (Serial0/0)
Mar 1 01:55:47.007: dst=FF02::9
Mar 1 01:55:47.007: sport=521, dport=521, length=72
Mar 1 01:55:47.007: command=2, version=1, mbz=0, #rte=3
Mar 1 01:55:47.007: tag=0, metric=1, prefix=2001:DB8:0:12::/64
Mar 1 01:55:47.007: tag=0, metric=1, prefix=2001:DB8:0:23::/64
Mar 1 01:55:47.007: tag=0, metric=2, prefix=2001:DB8:0:14::/64
Mar 1 01:55:47.011: RIPng: 2001:DB8:0:14::/64, metric changed to 3
Mar 1 01:55:47.011: RIPng: 2001:DB8:0:14::/64, added path FE80::2/Serial0/0
Mar 1 01:55:47.011: IPv6RT0: rip test, Route add 2001:DB8:0:14::/64 [better metric 3, 8]
Mar 1 01:55:47.015: IPv6RT0: rip test, Adding next-hop FE80::2 over Serial0/0 for 2001:DB8:0:14::/64, [120/3]
Mar 1 01:55:47.015: RIPng: Triggered update requested, delaying
Mar 1 01:55:47.019: IPv6RT0: Event: 2001:DB8:0:14::/64, Mod, owner rip, previous None

Posted in IPv6, RIP | Leave a Comment »

VLSM Usage and Mismatched Subnet Masks in RIPv1

Posted by Andy on April 12, 2009

In this post we will look at what happens when a router using VLSM attempts to advertise the variably subnetted address space with RIPv1.  We will also look at what happens when opposite ends of a link are configured with different subnet masks in RIPv1.  The topology and configurations are shown below:

ripv1-vlsm

R1:
interface Loopback1
 ip address 10.1.1.1 255.255.255.0
!
interface Loopback2
 ip address 10.1.2.1 255.255.255.0
!
interface Loopback3
 ip address 10.1.3.1 255.255.255.0
!
interface Loopback4
 ip address 10.1.4.1 255.255.255.0
!
interface Loopback5
 ip address 10.1.5.1 255.255.255.192
!
interface Loopback6
 ip address 10.1.6.65 255.255.255.192
!
interface Loopback7
 ip address 10.1.7.129 255.255.255.192
!
interface Loopback8
 ip address 10.1.8.193 255.255.255.192
!
interface Serial0/0
 ip address 10.0.12.1 255.255.255.0

R2:
interface Loopback1
 ip address 10.2.1.2 255.255.255.0
!
interface Loopback2
 ip address 10.2.2.2 255.255.255.0
!
interface Loopback3
 ip address 10.2.3.2 255.255.255.0
!
interface Loopback4
 ip address 10.2.4.2 255.255.255.0
!
interface Loopback5
 ip address 10.2.5.2 255.255.255.192
!
interface Loopback6
 ip address 10.2.6.65 255.255.255.192
!
interface Loopback7
 ip address 10.2.7.129 255.255.255.192
!
interface Loopback8
 ip address 10.2.8.193 255.255.255.192
!
interface Serial0/0
 ip address 10.0.12.2 255.255.255.0

We will enable RIPv1 for the 10.0.0.0 network on each router.  We will also configure all loopback interfaces as passive interfaces so that there isn’t so much debug output:

R1:
router rip
 passive-interface default
 no passive-interface Serial0/0
 network 10.0.0.0

R2:
router rip
 passive-interface default
 no passive-interface Serial0/0
 network 10.0.0.0

R1 and R2 send only routes that have the same mask as the outgoing interface.  All /24 networks are sent and added to each other’s routing tables, and neither has knowledge of the other /26 networks:

R1#debug ip rip
*Mar 1 00:26:03.619: RIP: sending v1 update to 10.0.12.2 via Serial0/0 (10.0.12.1)
*Mar 1 00:26:03.623: RIP: build update entries
*Mar 1 00:26:03.623: subnet 10.1.1.0 metric 1
*Mar 1 00:26:03.623: subnet 10.1.2.0 metric 1
*Mar 1 00:26:03.623: subnet 10.1.3.0 metric 1
*Mar 1 00:26:03.627: subnet 10.1.4.0 metric 1
*Mar 1 00:26:05.643: RIP: received v1 update from 10.0.12.2 on Serial0/0
*Mar 1 00:26:05.643: 10.2.1.0 in 1 hops
*Mar 1 00:26:05.647: 10.2.2.0 in 1 hops
*Mar 1 00:26:05.651: 10.2.3.0 in 1 hops
*Mar 1 00:26:05.651: 10.2.4.0 in 1 hops

1-r1-route-table

1-r2-route-table

 

Next, we will change R2 to use a /26 mask on S0/0:

R2:
interface Serial0/0
 ip address 10.0.12.2 255.255.255.192

R2 stops sending the /24 routes in updates and begins sending the /26 routes:

R2#debug ip rip
*Mar 1 00:36:36.751: RIP: received v1 update from 10.0.12.1 on Serial0/0
*Mar 1 00:36:36.751: 10.1.1.0 in 1 hops
*Mar 1 00:36:36.751: 10.1.2.0 in 1 hops
*Mar 1 00:36:36.751: 10.1.3.0 in 1 hops
*Mar 1 00:36:36.751: 10.1.4.0 in 1 hops
*Mar 1 00:36:58.327: RIP: sending v1 update to 255.255.255.255 via Serial0/0 (10.0.12.2)
*Mar 1 00:36:58.327: RIP: build update entries
*Mar 1 00:36:58.331: subnet 10.2.5.0 metric 1
*Mar 1 00:36:58.331: subnet 10.2.6.64 metric 1
*Mar 1 00:36:58.331: subnet 10.2.7.128 metric 1
*Mar 1 00:36:58.331: subnet 10.2.8.192 metric 1

Because mask information is not carried in routing updates in RIPv1, the mask of the receiving interface is also used for determining the mask of received routes.  R2 interprets R1’s routes as all having /26 masks.  As a result, only the first 1/4 of the address space of each route is reachable from R2.  Once the flush timer expires for the old routes after changing the mask, R2’s route table now looks like this:

2-r2-route-table

R1 interprets all the routes received from R2 as having /24 masks.  Of the 4 routes received from R2, only 10.2.5.0 is a valid subnet address using a /24 mask.  Since the other 3 are invalid /24 subnets, they are instead interpreted as host routes and added with a /32 mask:

2-r1-route-table

The result is that R1 will attempt to route traffic in the range 10.2.5.64 – 10.2.5.255 to R2 when it should not, and will not route any traffic to the other 3 /26 networks when it should.

Posted in RIP | Leave a Comment »

Some Strange Static Routing Issues

Posted by Andy on April 8, 2009

In this post we will look at two static routing issues that I have yet to find an explanation for.  R1 and R2 are connected by 3 serial interfaces, one using a subnet of a class A network, one a class B, and one a class C:

static-routing-topology2

R1:
interface Serial0/0
 ip address 10.0.12.1 255.255.255.252
interface Serial0/1
 ip address 172.16.12.1 255.255.255.252
interface Serial0/2
 ip address 192.168.12.1 255.255.255.252

R2:
interface Serial0/0
 ip address 10.0.12.2 255.255.255.252
interface Serial0/1
 ip address 172.16.12.2 255.255.255.252
interface Serial0/2
 ip address 192.168.12.2 255.255.255.252

The first issue occurs when all of the following are true:

 

  • The static route is configured with a next-hop address

 

  • At least 1 subnet of the major network specified by the next-hop address in the static route statement is present in the routing table, but no subnets that match the specific IP address

 

  • The best match for the IP address specified in the static route is the default route

 

  • The default route is configured with an exit interface

 

Static routes matching all of these conditions are not entered in the routing table even though there is a match for the next-hop address using the default route.  If no subnets of the major network exist in the routing table, or if the best match is anything but the default route and is configured with an exit interface, the static route will be installed.  Let’s look at a few examples.  First we will add the default route using an exit interface:

R1:
ip route 0.0.0.0 0.0.0.0 Serial0/0

1-show-ip-route

Next we will add a couple static routes with random next-hop addresses:

R1:
ip route 1.0.0.0 255.0.0.0 21.1.1.1
ip route 2.0.0.0 255.0.0.0 22.1.1.1

The next-hop for both routes resolves to the default route.  No subnets of 21.0.0.0/8 or 22.0.0.0/8 exist in the routing table.  Both routes are installed:

R1#debug ip routing
Mar 1 00:25:16.899: RT: SET_LAST_RDB for 1.0.0.0/8
NEW rdb: via 21.1.1.1
Mar 1 00:25:16.899: RT: add 1.0.0.0/8 via 21.1.1.1, static metric [1/0]
Mar 1 00:25:16.903: RT: NET-RED 1.0.0.0/8
Mar 1 00:25:19.275: RT: SET_LAST_RDB for 2.0.0.0/8
NEW rdb: via 22.1.1.1
Mar 1 00:25:19.275: RT: add 2.0.0.0/8 via 22.1.1.1, static metric [1/0]
Mar 1 00:25:19.275: RT: NET-RED 2.0.0.0/8

Next we will try to add static routes with next-hop addresses in the same major networks as the directly connected subnets used on the serial links:

R1:
ip route 3.0.0.0 255.0.0.0 10.255.255.50
ip route 4.0.0.0 255.0.0.0 172.16.255.50
ip route 5.0.0.0 255.0.0.0 192.168.12.50

One subnet of each classful network exists, but none of them match the next-hop address.  The best match on all 3 next-hop addresses should be the default route.  However, none of these 3 routes are installed in the routing table:

2-show-ip-route

If we add a static route to 21.21.21.0/24 with a next-hop of another random address, the route is added just like the first 2 routes because no subnets of the major network exist.  However, this also causes the 1.0.0.0 network to be removed after several seconds when the router realizes it now has a subnet of 21.0.0.0/8, but no specific subnet of the classful network to reach 21.1.1.1 – the next-hop for 1.0.0.0:

R1:
ip route 21.21.21.0 255.255.255.0 23.1.1.1

R1#debug ip routing
Mar 1 00:38:03.331: RT: SET_LAST_RDB for 21.21.21.0/24
NEW rdb: via 23.1.1.1
Mar 1 00:38:03.331: RT: add 21.21.21.0/24 via 23.1.1.1, static metric [1/0]
Mar 1 00:38:03.335: RT: NET-RED 21.21.21.0/24
Mar 1 00:38:55.619: RT: del 1.0.0.0 via 21.1.1.1, static metric [1/0]
Mar 1 00:38:55.619: RT: delete network route to 1.0.0.0
Mar 1 00:38:55.619: RT: NET-RED 1.0.0.0/8
Mar 1 00:38:55.623: RT: NET-RED 0.0.0.0/0

3-show-ip-route

This classful behavior only occurs when the best match is the default route.  If we add two /1 networks to cover the entire range covered by the default route and configure them with exit interfaces just like the default route, all of the static routes we configured match one of the two /1 static routes and are added to the routing table:

R1:
ip route 0.0.0.0 128.0.0.0 Serial0/0
ip route 128.0.0.0 128.0.0.0 Serial0/0

4-show-ip-route

 

 

 

 

The second issue occurs when all of the following things are true:

 

  • The static route is configured with a next-hop address

 

  • The best match for the IP address specified in the static route is another static route configured with a next-hop address or a route learned from a routing protocol

 

  • The best match route uses a less specific mask than the route being configured

 

  • The range of the best match route includes the range of the route being configured

 

Static routes meeting all of these conditions are not installed in the routing table, even though the next-hop address may resolve to a valid route.  Let’s look at a couple examples of this.  First we will remove all of the static route statements from the previous example:

R1:
no ip route 0.0.0.0 0.0.0.0 Serial0/0
no ip route 0.0.0.0 128.0.0.0 Serial0/0
no ip route 1.0.0.0 255.0.0.0 21.1.1.1
no ip route 2.0.0.0 255.0.0.0 22.1.1.1
no ip route 3.0.0.0 255.0.0.0 10.255.255.50
no ip route 4.0.0.0 255.0.0.0 172.16.255.50
no ip route 5.0.0.0 255.0.0.0 192.168.12.50
no ip route 21.21.21.0 255.255.255.0 23.1.1.1
no ip route 128.0.0.0 128.0.0.0 Serial0/0

We will enable RIP between R1 and R2 on S0/0 and create a loopback interface on R2 to be advertised with RIP. We will also create a static route with a next-hop of R2’s S0/0 interface IP address:

R1:
router rip
 network 10.0.0.0
!
ip route 4.0.0.0 255.0.0.0 10.0.12.2

R2:
interface Loopback0
 ip address 2.2.2.2 255.0.0.0
!
router rip
 network 2.0.0.0
 network 10.0.0.0

R1 adds both routes with a next-hop of 10.0.12.2:

5-show-ip-route

Next we will create some static routes with next-hop addresses that match these 2 routes:

R1:
ip route 2.0.0.0 254.0.0.0 2.255.255.1
ip route 2.0.0.0 255.128.0.0 2.255.255.1
ip route 4.0.0.0 254.0.0.0 4.255.255.1
ip route 4.0.0.0 255.128.0.0 4.255.255.1
ip route 4.0.0.0 255.128.0.0 4.1.1.1

Only the 1st and 3rd routes are installed in the routing table.  These two routes both use a less specific mask than the best match for their next-hop addresses:

6-show-ip-route

The three /9 routes, which use a more specific mask than the best match for their next-hop, are not installed.  There is the risk that a route could be self-recursive if, after being installed, the best route to it’s next hop is itself.  We can see that this is true for the 4.0.0.0/9 route with a next-hop of 4.1.1.1.  If installed, the best route to it’s next-hop address would be itself.  However the other two /9 routes do not have this problem since their next-hop addresses are both outside of their own range.  If installed, their next-hop would resolve to the two /8 routes, both of which are valid. 

This issue only occurs when the matching route uses a next-hop address.  If we change 4.0.0.0/8 to use an exit interface rather than a next-hop address, R1 installs the route to 4.0.0.0/9 via 4.255.255.1 several seconds later after it’s next scan of the routing table.  The other, self-recursive route to 4.0.0.0/9 via 4.1.1.1 remains uninstalled, as it should:

R1:
no ip route 4.0.0.0 255.0.0.0 10.0.12.2
ip route 4.0.0.0 255.0.0.0 Serial0/0

R1#debug ip routing
Mar 1 01:24:57.171: RT: SET_LAST_RDB for 4.0.0.0/8
NEW rdb: is directly connected
Mar 1 01:24:57.171: RT: add 4.0.0.0/8 via 0.0.0.0, static metric [1/0]
Mar 1 01:24:57.171: RT: NET-RED 4.0.0.0/8
Mar 1 01:25:34.571: RT: network 4.0.0.0 is now variably masked
Mar 1 01:25:34.571: RT: SET_LAST_RDB for 4.0.0.0/9
NEW rdb: via 4.255.255.1
Mar 1 01:25:34.575: RT: add 4.0.0.0/9 via 4.255.255.1, static metric [1/0]
Mar 1 01:25:34.575: RT: NET-RED 4.0.0.0/9

7-show-ip-route

Posted in Static Routing | Leave a Comment »