On Mon, Jun 03, 2013 at 03:43:21PM +0300, Kapetanakis Giannis wrote:
> On 01/06/13 18:44, Claudio Jeker wrote:
> >Can you give this diff a spin? Not much tested but the current way we
> >define an area as active (having at least one active neighbor) is wrong.
> >This changes the decision to have at least one active interface
> >(not IF_STA_DOWN). Not sure if that will cause troubles with passive
> >interfaces since those are not considered active.  At least it seems that
> >RFC 3509 uses this to define active areas.
> >
> >Thanks
> 
> Just tested this diff and it does not work in my case for passive
> interfaces (either carp or loopback).
> 
> area 0.0.0.7 {
>    stub
>    interface carp8 {passive}
>    interface lo1 {passive}
> }
> 
> If I add carp8 or lo1 in area 0.0.0.0 then the routes are announced.
> 

Yeah, while the diff fixed the B flag it did not solve the problem that we
skipped our own networks. This version should solve that (at least it does
in my quick test).

Needs lots of testing since this changes core parts of the route calculation.
-- 
:wq Claudio

Index: area.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/area.c,v
retrieving revision 1.9
diff -u -p -r1.9 area.c
--- area.c      7 Jan 2009 21:16:36 -0000       1.9
+++ area.c      4 Jun 2013 20:58:05 -0000
@@ -94,19 +94,24 @@ area_find(struct ospfd_conf *conf, struc
 }
 
 void
-area_track(struct area *area, int state)
+area_track(struct area *area)
 {
-       int     old = area->active;
+       int             old = area->active;
+       struct iface    *iface;
 
-       if (state & NBR_STA_FULL)
-               area->active++;
-       else if (area->active == 0)
-               fatalx("area_track: area already inactive");
-       else
-               area->active--;
+       area->active = 0;
+       LIST_FOREACH(iface, &area->iface_list, entry) {
+               if (iface->state & IF_STA_DOWN)
+                       continue;
+               area->active = 1;
+               break;
+       }
 
-       if (area->active == 0 || old == 0)
+       if (area->active != old) {
+               ospfe_imsg_compose_rde(IMSG_AREA_CHANGE, area->id.s_addr, 0,
+                   &area->active, sizeof(area->active));
                ospfe_demote_area(area, old == 0);
+       }
 }
 
 int
@@ -116,7 +121,7 @@ area_border_router(struct ospfd_conf *co
        int              active = 0;
 
        LIST_FOREACH(area, &conf->area_list, entry)
-               if (area->active > 0)
+               if (area->active)
                        active++;
 
        return (active > 1);
Index: interface.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/interface.c,v
retrieving revision 1.75
diff -u -p -r1.75 interface.c
--- interface.c 14 May 2012 10:17:21 -0000      1.75
+++ interface.c 4 Jun 2013 20:58:05 -0000
@@ -136,8 +136,10 @@ if_fsm(struct iface *iface, enum iface_e
        if (new_state != 0)
                iface->state = new_state;
 
-       if (iface->state != old_state)
+       if (iface->state != old_state) {
+               area_track(iface->area);
                orig_rtr_lsa(iface->area);
+       }
 
        if (old_state & (IF_STA_MULTI | IF_STA_POINTTOPOINT) &&
            (iface->state & (IF_STA_MULTI | IF_STA_POINTTOPOINT)) == 0)
Index: neighbor.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/neighbor.c,v
retrieving revision 1.46
diff -u -p -r1.46 neighbor.c
--- neighbor.c  17 Jan 2013 10:07:56 -0000      1.46
+++ neighbor.c  4 Jun 2013 20:58:05 -0000
@@ -204,7 +204,6 @@ nbr_fsm(struct nbr *nbr, enum nbr_event 
                         * neighbor changed from/to FULL
                         * originate new rtr and net LSA
                         */
-                       area_track(nbr->iface->area, nbr->state);
                        orig_rtr_lsa(nbr->iface->area);
                        if (nbr->iface->state & IF_STA_DR)
                                orig_net_lsa(nbr->iface);
Index: ospfd.h
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/ospfd.h,v
retrieving revision 1.91
diff -u -p -r1.91 ospfd.h
--- ospfd.h     17 Jan 2013 10:07:56 -0000      1.91
+++ ospfd.h     4 Jun 2013 20:58:05 -0000
@@ -104,6 +104,7 @@ enum imsg_type {
        IMSG_NEIGHBOR_CAPA,
        IMSG_NETWORK_ADD,
        IMSG_NETWORK_DEL,
+       IMSG_AREA_CHANGE,
        IMSG_DD,
        IMSG_DD_END,
        IMSG_DD_BADLSA,
@@ -530,7 +531,7 @@ struct demote_msg {
 struct area    *area_new(void);
 int             area_del(struct area *);
 struct area    *area_find(struct ospfd_conf *, struct in_addr);
-void            area_track(struct area *, int);
+void            area_track(struct area *);
 int             area_border_router(struct ospfd_conf *);
 u_int8_t        area_ospf_options(struct area *);
 
Index: ospfe.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/ospfe.c,v
retrieving revision 1.86
diff -u -p -r1.86 ospfe.c
--- ospfe.c     22 Mar 2013 08:42:55 -0000      1.86
+++ ospfe.c     4 Jun 2013 20:58:05 -0000
@@ -992,9 +992,9 @@ orig_rtr_lsa(struct area *area)
                oeconf->border = border;
                orig_rtr_lsa_all(area);
        }
-
        if (oeconf->border)
                lsa_rtr.flags |= OSPF_RTR_B;
+
        /* TODO set V flag if a active virtual link ends here and the
         * area is the transit area for this link. */
        if (virtual)
Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/rde.c,v
retrieving revision 1.94
diff -u -p -r1.94 rde.c
--- rde.c       9 May 2011 12:24:41 -0000       1.94
+++ rde.c       4 Jun 2013 21:57:47 -0000
@@ -296,11 +296,6 @@ rde_dispatch_imsg(int fd, short event, v
                        if (nbr == NULL)
                                break;
 
-                       if (state != nbr->state &&
-                           (nbr->state & NBR_STA_FULL ||
-                           state & NBR_STA_FULL))
-                               area_track(nbr->area, state);
-
                        nbr->state = state;
                        if (nbr->state & NBR_STA_FULL)
                                rde_req_list_free(nbr);
@@ -313,6 +308,19 @@ rde_dispatch_imsg(int fd, short event, v
                                break;
                        nbr->capa_options = *(u_int8_t *)imsg.data;
                        break;
+               case IMSG_AREA_CHANGE:
+                       if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state))
+                               fatalx("invalid size of OE request");
+
+                       LIST_FOREACH(area, &rdeconf->area_list, entry) {
+                               if (area->id.s_addr == imsg.hdr.peerid)
+                                       break;
+                       }
+                       if (area == NULL)
+                               break;
+                       memcpy(&state, imsg.data, sizeof(state));
+                       area->active = state;
+                       break;
                case IMSG_DB_SNAPSHOT:
                        nbr = rde_nbr_find(imsg.hdr.peerid);
                        if (nbr == NULL)
@@ -776,8 +784,11 @@ rde_send_change_kroute(struct rt_node *r
                kr.ext_tag = r->ext_tag;
                imsg_add(wbuf, &kr, sizeof(kr));
        }
-       if (krcount == 0)
-               fatalx("rde_send_change_kroute: no valid nexthop found");
+       if (krcount == 0) {
+               /* ignore self originated networks */
+               ibuf_free(wbuf);
+               return;
+       }
        imsg_close(&iev_main->ibuf, wbuf);
        imsg_event_add(iev_main);
 }
@@ -1341,14 +1352,18 @@ rde_summary_update(struct rt_node *rte, 
        /* no need to originate inter-area routes to the backbone */
        if (rte->p_type == PT_INTER_AREA && area->id.s_addr == INADDR_ANY)
                return;
-       /* nexthop check, nexthop part of area -> no summary */
+       /*
+        * nexthop check, nexthop part of area -> no summary
+        * but exclude self originated networks (empty nexthop list)
+        */
        TAILQ_FOREACH(rn, &rte->nexthop, entry) {
                nr = rt_lookup(DT_NET, rn->nexthop.s_addr);
                if (nr && nr->area.s_addr == area->id.s_addr)
                        continue;
                break;
        }
-       if (rn == NULL) /* all nexthops belong to this area */
+       if (rn == NULL && !TAILQ_EMPTY(&rte->nexthop))
+               /* all nexthops belong to this area */
                return;
 
        if (rte->cost >= LS_INFINITY)
Index: rde_spf.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/rde_spf.c,v
retrieving revision 1.75
diff -u -p -r1.75 rde_spf.c
--- rde_spf.c   18 Sep 2012 18:58:56 -0000      1.75
+++ rde_spf.c   4 Jun 2013 22:01:23 -0000
@@ -22,6 +22,7 @@
 #include <arpa/inet.h>
 #include <err.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "ospfd.h"
 #include "ospf.h"
@@ -182,7 +183,7 @@ rt_calc(struct vertex *v, struct area *a
        switch (v->type) {
        case LSA_TYPE_ROUTER:
                /* stub networks */
-               if (v->cost >= LS_INFINITY || TAILQ_EMPTY(&v->nexthop))
+               if (v->cost >= LS_INFINITY)
                        return;
 
                for (i = 0; i < lsa_num_links(v); i++) {
@@ -211,7 +212,7 @@ rt_calc(struct vertex *v, struct area *a
                    adv_rtr, PT_INTRA_AREA, DT_RTR, v->lsa->data.rtr.flags, 0);
                break;
        case LSA_TYPE_NETWORK:
-               if (v->cost >= LS_INFINITY || TAILQ_EMPTY(&v->nexthop))
+               if (v->cost >= LS_INFINITY)
                        return;
 
                addr.s_addr = htonl(v->ls_id) & v->lsa->data.net.mask;
@@ -245,7 +246,7 @@ rt_calc(struct vertex *v, struct area *a
                v->cost = w->cost +
                    (ntohl(v->lsa->data.sum.metric) & LSA_METRIC_MASK);
 
-               if (v->cost >= LS_INFINITY || TAILQ_EMPTY(&v->nexthop))
+               if (v->cost >= LS_INFINITY)
                        return;
 
                adv_rtr.s_addr = htonl(v->adv_rtr);
@@ -823,20 +824,26 @@ rt_dump(struct in_addr area, pid_t pid, 
                        fatalx("rt_dump: invalid RIB type");
                }
 
+               bzero(&rtctl, sizeof(rtctl));
+               rtctl.prefix.s_addr = r->prefix.s_addr;
+               rtctl.area.s_addr = r->area.s_addr;
+               rtctl.cost = r->cost;
+               rtctl.cost2 = r->cost2;
+               rtctl.p_type = r->p_type;
+               rtctl.d_type = r->d_type;
+               rtctl.flags = r->flags;
+               rtctl.prefixlen = r->prefixlen;
+
+               if (TAILQ_EMPTY(&r->nexthop)) {
+                       rde_imsg_compose_ospfe(IMSG_CTL_SHOW_RIB, 0, pid,
+                           &rtctl, sizeof(rtctl));
+               }
                TAILQ_FOREACH(rn, &r->nexthop, entry) {
                        if (rn->invalid)
                                continue;
 
-                       rtctl.prefix.s_addr = r->prefix.s_addr;
                        rtctl.nexthop.s_addr = rn->nexthop.s_addr;
-                       rtctl.area.s_addr = r->area.s_addr;
                        rtctl.adv_rtr.s_addr = rn->adv_rtr.s_addr;
-                       rtctl.cost = r->cost;
-                       rtctl.cost2 = r->cost2;
-                       rtctl.p_type = r->p_type;
-                       rtctl.d_type = r->d_type;
-                       rtctl.flags = r->flags;
-                       rtctl.prefixlen = r->prefixlen;
                        rtctl.uptime = now.tv_sec - rn->uptime;
 
                        rde_imsg_compose_ospfe(IMSG_CTL_SHOW_RIB, 0, pid,
@@ -854,9 +861,6 @@ rt_update(struct in_addr prefix, u_int8_
        struct rt_node          *rte;
        struct rt_nexthop       *rn;
        int                      better = 0, equal = 0;
-
-       if (vnh == NULL || TAILQ_EMPTY(vnh))    /* XXX remove */
-               fatalx("rt_update: invalid nexthop");
 
        if ((rte = rt_find(prefix.s_addr, prefixlen, d_type)) == NULL) {
                if ((rte = calloc(1, sizeof(struct rt_node))) == NULL)

Reply via email to