Mailing List Archive

fix for UNH failure (OSPF_CONF.3.22)
Hi,

I have the fix for *one* of the UNH failures. Analysis and patch
attached below. I tested on Solaris, using a raw socket program
to generate the 7FFFFFFF packet.

Analysis:
--------
It seems like there's no check to make sure that the seq number does not
wrap around. Since rfc2328 says, in section 14.1, that the Premature
Aging process is the same, regardless of whether it is being used
to flush an lsa out of the area or whether it is being used when the
seqnum naturally wraps around, the correct place to fix this problem
is some function that is called by all the lsa_output functions.
The right place for the fix seems to be ospf_lsa_install().

We'll also have to introduce some new lsa_flag so that, after the
lsa is prematurely aged and all acks are received, a new lsa is
originated for the area. Currently ospf_maxage_lsa_remover() does
not have any hooks for this.

The specific fixes are:

- ospfd/ospf_lsa.c
fix for UNH OSPF_CONF.3.22 failure
- added better debug comments (print ls_seqnum)
- check sequence number in ospf_lsa_install
- ospf_maxage_lsa_remover() checks for OSPF_LSA_PREMATURE_AGE
and re-originates the lsa after ls_acks are received.

- ospfd/ospf_lsa.h
- added OSPF_LSA_PREMATURE_AGE (UNH OSPF_CONF.3.22 failure)

- ospfd/ospf_flood.c
- improve debug statement- print ls_seqnum


===================================================================
RCS file: ospf_lsa.c,v
retrieving revision 1.22
diff -uwb -r1.22 ospf_lsa.c
--- ospf_lsa.c 2003/07/13 01:36:06 1.22
+++ ospf_lsa.c 2003/10/10 14:20:33
@@ -2380,8 +2380,9 @@
area->router_lsa_self = ospf_lsa_lock (new);

if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
- zlog_info("LSA[Type%d]: ID %s is self-originated",
- new->data->type, inet_ntoa (new->data->id));
+ zlog_info("LSA[Type%d]: ID %s seq 0x%x is self-originated",
+ new->data->type, inet_ntoa (new->data->id),
+ new->data->ls_seqnum);
}

return new;
@@ -2641,6 +2642,44 @@
if ( old == NULL || ospf_lsa_different(old, lsa))
rt_recalc = 1;

+ /*
+ Sequence number check (Section 14.1 of rfc 2328)
+ "Premature aging is used when it is time for a self-originated
+ LSA's sequence number field to wrap. At this point, the current
+ LSA instance (having LS sequence number MaxSequenceNumber) must
+ be prematurely aged and flushed from the routing domain before a
+ new instance with sequence number equal to InitialSequenceNumber
+ can be originated. "
+ */
+
+ if (lsa->data->ls_seqnum - 1 == htonl(OSPF_MAX_SEQUENCE_NUMBER))
+ {
+ if (ospf_lsa_is_self_originated(ospf, lsa))
+ {
+ lsa->data->ls_seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER);
+ if (!IS_LSA_MAXAGE(lsa))
+ lsa->flags |= OSPF_LSA_PREMATURE_AGE;
+ lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+
+ if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
+ {
+ zlog_info ("ospf_lsa_install() Premature Aging "
+ "lsa 0x%lx", (u_long)lsa);
+ ospf_lsa_header_dump (lsa->data);
+ }
+ }
+ else
+ {
+ if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+ {
+ zlog_info ("ospf_lsa_install() got an lsa with seq 0x80000000 "
+ "that was not self originated. Ignoring\n");
+ ospf_lsa_header_dump (lsa->data);
+ }
+ return old;
+ }
+ }
+
/* discard old LSA from LSDB */
if (old != NULL)
ospf_discard_from_db (ospf, lsdb, lsa);
@@ -2722,12 +2761,16 @@
}
}

- /* If received LSA' ls_age is MaxAge, set LSA on MaxAge LSA list. */
- if (IS_LSA_MAXAGE (new) && !IS_LSA_SELF (new))
+ /*
+ If received LSA' ls_age is MaxAge, or lsa is being prematurely aged
+ (it's getting flushed out of the area), set LSA on MaxAge LSA list.
+ */
+ if ((lsa->flags & OSPF_LSA_PREMATURE_AGE) ||
+ (IS_LSA_MAXAGE (new) && !IS_LSA_SELF (new)))
{
- if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
- zlog_info ("LSA[Type%d:%s]: Install LSA, MaxAge",
- new->data->type, inet_ntoa (new->data->id));
+ if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
+ zlog_info ("LSA[Type%d:%s]: Install LSA 0x%lx, MaxAge",
+ new->data->type, inet_ntoa (new->data->id), (u_long)lsa);
ospf_lsa_maxage (ospf, lsa);
}

@@ -2822,8 +2865,8 @@
/* Remove LSA from the LSDB */
if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF))
if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
- zlog_info ("LSA[Type%d:%s]: This LSA is self-originated: ",
- lsa->data->type, inet_ntoa (lsa->data->id));
+ zlog_info ("LSA[Type%d:%s]: LSA 0x%lx is self-oririnated: ",
+ lsa->data->type, inet_ntoa (lsa->data->id), (u_long)lsa);

if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
zlog_info ("LSA[Type%d:%s]: MaxAge LSA removed from list",
@@ -2836,6 +2879,14 @@
ospf_flood_through (ospf, NULL, lsa);
#endif /* ORIGINAL_CODING */

+ if (lsa->flags & OSPF_LSA_PREMATURE_AGE)
+ {
+ if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+ zlog_info ("originating new router lsa for lsa 0x%lx \n",
+ (u_long)lsa);
+ ospf_router_lsa_originate(lsa->area);
+ }
+
/* Remove from lsdb. */
ospf_discard_from_db (ospf, lsa->lsdb, lsa);
ospf_lsdb_delete (lsa->lsdb, lsa);
===================================================================
RCS file: ospf_lsa.h,v
retrieving revision 1.6
diff -uwb -r1.6 ospf_lsa.h
--- ospf_lsa.h 2003/07/12 21:30:57 1.6
+++ ospf_lsa.h 2003/10/10 14:13:31
@@ -80,6 +80,7 @@
#ifdef HAVE_NSSA
#define OSPF_LSA_LOCAL_XLT 0x20
#endif /* HAVE_NSSA */
+#define OSPF_LSA_PREMATURE_AGE 0x40

/* LSA data. */
struct lsa_header *data;
===================================================================
RCS file: ospf_flood.c,v
retrieving revision 1.5
diff -uwb -r1.5 ospf_flood.c
--- ospf_flood.c 2003/07/12 21:30:57 1.5
+++ ospf_flood.c 2003/10/10 14:21:50
@@ -119,8 +119,9 @@
listnode node;

if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("LSA[Type%d:%s]: Process self-originated LSA",
- new->data->type, inet_ntoa (new->data->id));
+ zlog_info ("LSA[Type%d:%s]: Process self-originated LSA seq 0x%lx",
+ new->data->type, inet_ntoa (new->data->id),
+ (u_long)new->data->ls_seqnum);

/* If we're here, we installed a self-originated LSA that we received
from a neighbor, i.e. it's more recent. We must see whether we want