On Thu, Aug 04, 2005 at 06:49:58PM +0800, Lars Hansson wrote:
> Running a recent snapshot (a few days ago) ospfd seems to have a problem
> with correctly joining an ospf area unless it's router-priority is 0
> or higher than the current BDR. Ospfd is here connected to our ospf backbone
> wich is a mix of openbsd boxes running gated, Huawei 1760's and Cisco's
> running various versions of IOS.
> The first output below is after ospfd has been running with a router-priority
> of 1 for a couple of minutes, the second one is after a very quick restart (ie
> less than the dead time).
> It seems it get stuck in a state and doesnt proceed until it has been 
> restarded.
> It's notable that on the other routers in the backbone the ospfd box appears
> as a full 2way/drother member while ospfd itself seems to think it's still in
> exstart. The output also states that the BDR is in FULL/DROTHER but sometimes
> it's the DR that shows up in that state. It's never both at the same time
> though.
> 
> # ospfctl sh n 
> ID              Pri State             DeadTime  Address         Interface
> 203.65.245.3    1   EXSTART/DROTHER   00:00:32  203.65.245.3    sis0
> 203.65.245.6    10  FULL/DR           00:00:31  203.65.245.6    sis0
> 203.65.245.5    1   EXSTART/DROTHER   00:00:39  203.65.245.5    sis0
> 203.65.245.4    0   EXSTART/DROTHER   00:00:35  203.65.245.4    sis0
> 203.65.245.2    9   FULL/DROTHER      00:00:36  203.65.245.2    sis0
> 203.65.245.12   0   EXSTART/DROTHER   00:00:32  203.65.245.12   sis0
> 203.65.245.9    1   EXSTART/DROTHER   00:00:35  203.65.245.9    sis0
> 203.65.245.7    0   EXSTART/DROTHER   00:00:33  203.65.245.7    sis0
> 203.65.245.1    5   EXSTART/DROTHER   00:00:33  203.65.245.1    sis0
> 
> # ospfctl sh n 
> ID              Pri State             DeadTime  Address         Interface
> 203.65.245.2    9   FULL/BACKUP       00:00:31  203.65.245.2    sis0
> 203.65.245.9    1   2-WAY/DROTHER     00:00:30  203.65.245.9    sis0
> 203.65.245.12   0   2-WAY/DROTHER     00:00:39  203.65.245.12   sis0
> 203.65.245.7    0   2-WAY/DROTHER     00:00:39  203.65.245.7    sis0
> 203.65.245.1    5   2-WAY/DROTHER     00:00:39  203.65.245.1    sis0
> 203.65.245.3    1   2-WAY/DROTHER     00:00:37  203.65.245.3    sis0
> 203.65.245.6    10  FULL/DR           00:00:36  203.65.245.6    sis0
> 203.65.245.5    1   2-WAY/DROTHER     00:00:34  203.65.245.5    sis0
> 203.65.245.4    0   2-WAY/DROTHER     00:00:32  203.65.245.4    sis0
> 

Could you test the following diff and see if this fixes the problem.
It looks like the RFC is busted and we need to find out how to fix it
without generating more troubles.

-- 
:wq Claudio

Index: hello.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/hello.c,v
retrieving revision 1.8
diff -u -p -r1.8 hello.c
--- hello.c     13 Jun 2005 08:22:39 -0000      1.8
+++ hello.c     30 Jun 2005 13:09:20 -0000
@@ -117,9 +117,9 @@ recv_hello(struct iface *iface, struct i
     u_int16_t len)
 {
        struct hello_hdr         hello;
-       struct nbr              *nbr = NULL;
+       struct nbr              *nbr = NULL, *dr;
        u_int32_t                nbr_id;
-       int                      twoway = 0, nbr_change = 0;
+       int                      nbr_change = 0;
 
        if (len < sizeof(hello) && (len & 0x03)) {
                log_warnx("recv_hello: bad packet size, interface %s",
@@ -186,8 +186,13 @@ recv_hello(struct iface *iface, struct i
                fatalx("recv_hello: unknown interface type");
        }
 
-       if (!nbr)
+       if (!nbr) {
                nbr = nbr_new(rtr_id, iface, 0);
+               /* set neighbor parameters */
+               nbr->dr.s_addr = hello.d_rtr;
+               nbr->bdr.s_addr = hello.bd_rtr;
+               nbr->priority = hello.rtr_priority;
+       }
 
        /* actually the neighbor address shouldn't be stored on virtual links */
        nbr->addr.s_addr = src.s_addr;
@@ -199,8 +204,8 @@ recv_hello(struct iface *iface, struct i
                memcpy(&nbr_id, buf, sizeof(nbr_id));
                if (nbr_id == iface->rtr_id.s_addr) {
                        /* seen myself */
-                       if (nbr->state < NBR_STA_XSTRT)
-                               twoway = 1;
+                       if (nbr->state & NBR_STA_PRELIM)
+                               nbr_fsm(nbr, NBR_EVT_2_WAY_RCVD);
                        break;
                }
                buf += sizeof(nbr_id);
@@ -222,9 +227,25 @@ recv_hello(struct iface *iface, struct i
        }
 
        if (iface->state & IF_STA_WAITING &&
-           ((hello.d_rtr == nbr->addr.s_addr && hello.bd_rtr == 0) ||
-           hello.bd_rtr == nbr->addr.s_addr))
+           hello.d_rtr == nbr->addr.s_addr && hello.bd_rtr == 0) {
+               log_debug("hello: DR seen with NO BDR");
                if_fsm(iface, IF_EVT_BACKUP_SEEN);
+       }
+
+       if (iface->state & IF_STA_WAITING && hello.bd_rtr == nbr->addr.s_addr) {
+               /*
+                * In case we see the BDR make sure that the DR is around
+                * with a bidirectional (2_WAY or better) connection
+                */
+               log_debug("hello: BDR seen");
+               LIST_FOREACH(dr, &iface->nbr_list, entry)
+                       if (hello.d_rtr == dr->addr.s_addr &&
+                           dr->state & NBR_STA_BIDIR) {
+                               log_debug("hello: BDR seen & DR %s is BIDIR",
+                                   inet_ntoa(dr->addr));
+                               if_fsm(iface, IF_EVT_BACKUP_SEEN);
+                       }
+       }
 
        if ((nbr->addr.s_addr == nbr->dr.s_addr &&
            nbr->addr.s_addr != hello.d_rtr) ||
@@ -241,15 +262,6 @@ recv_hello(struct iface *iface, struct i
 
        nbr->dr.s_addr = hello.d_rtr;
        nbr->bdr.s_addr = hello.bd_rtr;
-
-       if (twoway) {
-               /*
-                * event 2 way received needs to be delayed after the
-                * interface neighbor change check else the DR and BDR
-                * may not be set correctly.
-                */
-               nbr_fsm(nbr, NBR_EVT_2_WAY_RCVD);
-       }
 
        if (nbr_change)
                if_fsm(iface, IF_EVT_NBR_CHNG);

Reply via email to