This diff solves the issue of PR6597 for me and should be commited.
If nobody screams I will commit it tomorrow evening.

-- 
:wq Claudio

Index: usr.sbin/ospfd/rde_spf.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/rde_spf.c,v
retrieving revision 1.72
diff -u -p -r1.72 rde_spf.c
--- usr.sbin/ospfd/rde_spf.c    9 May 2011 12:24:41 -0000       1.72
+++ usr.sbin/ospfd/rde_spf.c    20 May 2011 10:25:04 -0000
@@ -38,9 +38,9 @@ struct vertex                 *spf_root = NULL;
 void    calc_nexthop(struct vertex *, struct vertex *,
             struct area *, struct lsa_rtr_link *);
 void    rt_nexthop_clear(struct rt_node *);
-void    rt_nexthop_add(struct rt_node *, struct v_nexthead *,
+void    rt_nexthop_add(struct rt_node *, struct v_nexthead *, u_int8_t,
             struct in_addr);
-void    rt_update(struct in_addr, u_int8_t, struct v_nexthead *,
+void    rt_update(struct in_addr, u_int8_t, struct v_nexthead *, u_int8_t,
             u_int32_t, u_int32_t, struct in_addr, struct in_addr,
             enum path_type, enum dst_type, u_int8_t, u_int32_t);
 void    rt_invalidate(struct area *);
@@ -194,7 +194,8 @@ rt_calc(struct vertex *v, struct area *a
                        adv_rtr.s_addr = htonl(v->adv_rtr);
 
                        rt_update(addr, mask2prefixlen(rtr_link->data),
-                           &v->nexthop, v->cost + ntohs(rtr_link->metric), 0,
+                           &v->nexthop, v->type,
+                           v->cost + ntohs(rtr_link->metric), 0,
                            area->id, adv_rtr, PT_INTRA_AREA, DT_NET,
                            v->lsa->data.rtr.flags, 0);
                }
@@ -206,7 +207,7 @@ rt_calc(struct vertex *v, struct area *a
                addr.s_addr = htonl(v->ls_id);
                adv_rtr.s_addr = htonl(v->adv_rtr);
 
-               rt_update(addr, 32, &v->nexthop, v->cost, 0, area->id,
+               rt_update(addr, 32, &v->nexthop, v->type, v->cost, 0, area->id,
                    adv_rtr, PT_INTRA_AREA, DT_RTR, v->lsa->data.rtr.flags, 0);
                break;
        case LSA_TYPE_NETWORK:
@@ -216,8 +217,8 @@ rt_calc(struct vertex *v, struct area *a
                addr.s_addr = htonl(v->ls_id) & v->lsa->data.net.mask;
                adv_rtr.s_addr = htonl(v->adv_rtr);
                rt_update(addr, mask2prefixlen(v->lsa->data.net.mask),
-                   &v->nexthop, v->cost, 0, area->id, adv_rtr, PT_INTRA_AREA,
-                   DT_NET, 0, 0);
+                   &v->nexthop, v->type, v->cost, 0, area->id, adv_rtr,
+                   PT_INTRA_AREA, DT_NET, 0, 0);
                break;
        case LSA_TYPE_SUM_NETWORK:
        case LSA_TYPE_SUM_ROUTER:
@@ -251,12 +252,12 @@ rt_calc(struct vertex *v, struct area *a
                if (v->type == LSA_TYPE_SUM_NETWORK) {
                        addr.s_addr = htonl(v->ls_id) & v->lsa->data.sum.mask;
                        rt_update(addr, mask2prefixlen(v->lsa->data.sum.mask),
-                           &v->nexthop, v->cost, 0, area->id, adv_rtr,
+                           &v->nexthop, v->type, v->cost, 0, area->id, adv_rtr,
                            PT_INTER_AREA, DT_NET, 0, 0);
                } else {
                        addr.s_addr = htonl(v->ls_id);
-                       rt_update(addr, 32, &v->nexthop, v->cost, 0, area->id,
-                           adv_rtr, PT_INTER_AREA, DT_RTR,
+                       rt_update(addr, 32, &v->nexthop, v->type, v->cost, 0,
+                           area->id, adv_rtr, PT_INTER_AREA, DT_RTR,
                            v->lsa->data.rtr.flags, 0);
                }
 
@@ -322,19 +323,20 @@ asext_calc(struct vertex *v)
                        if (rn->invalid)
                                continue;
 
-                       if (rn->connected && r->d_type == DT_NET) {
-                               if (v->lsa->data.asext.fw_addr != 0)
-                                       vertex_nexthop_add(v, NULL,
-                                           v->lsa->data.asext.fw_addr);
-                               else
-                                       vertex_nexthop_add(v, NULL,
-                                           htonl(v->adv_rtr));
-                       } else
+                       /*
+                        * if a fw_addr is specified and the nexthop
+                        * is directly connected then it is possible to
+                        * send traffic directly to fw_addr.
+                        */
+                       if (v->lsa->data.asext.fw_addr != 0 && rn->connected)
+                               vertex_nexthop_add(v, NULL,
+                                   v->lsa->data.asext.fw_addr);
+                       else
                                vertex_nexthop_add(v, NULL, rn->nexthop.s_addr);
                }
 
                rt_update(addr, mask2prefixlen(v->lsa->data.asext.mask),
-                   &v->nexthop, v->cost, cost2, a, adv_rtr, type,
+                   &v->nexthop, v->type, v->cost, cost2, a, adv_rtr, type,
                    DT_NET, 0, ntohl(v->lsa->data.asext.ext_tag));
                break;
        default:
@@ -729,7 +731,7 @@ rt_nexthop_clear(struct rt_node *r)
 }
 
 void
-rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh,
+rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh, u_int8_t type,
     struct in_addr adv_rtr)
 {
        struct v_nexthop        *vn;
@@ -742,7 +744,8 @@ rt_nexthop_add(struct rt_node *r, struct
                                continue;
 
                        rn->adv_rtr.s_addr = adv_rtr.s_addr;
-                       rn->connected = vn->prev == spf_root;
+                       rn->connected = (type == LSA_TYPE_NETWORK &&
+                           vn->prev == spf_root);
                        rn->invalid = 0;
 
                        r->invalid = 0;
@@ -758,7 +761,8 @@ rt_nexthop_add(struct rt_node *r, struct
                rn->nexthop.s_addr = vn->nexthop.s_addr;
                rn->adv_rtr.s_addr = adv_rtr.s_addr;
                rn->uptime = now.tv_sec;
-               rn->connected = vn->prev == spf_root;
+               rn->connected = (type == LSA_TYPE_NETWORK &&
+                   vn->prev == spf_root);
                rn->invalid = 0;
 
                r->invalid = 0;
@@ -837,7 +841,7 @@ rt_dump(struct in_addr area, pid_t pid, 
 
 void
 rt_update(struct in_addr prefix, u_int8_t prefixlen, struct v_nexthead *vnh,
-     u_int32_t cost, u_int32_t cost2, struct in_addr area,
+     u_int8_t v_type, u_int32_t cost, u_int32_t cost2, struct in_addr area,
      struct in_addr adv_rtr, enum path_type p_type, enum dst_type d_type,
      u_int8_t flags, u_int32_t tag)
 {
@@ -863,7 +867,7 @@ rt_update(struct in_addr prefix, u_int8_
                rte->flags = flags;
                rte->ext_tag = tag;
 
-               rt_nexthop_add(rte, vnh, adv_rtr);
+               rt_nexthop_add(rte, vnh, v_type, adv_rtr);
 
                rt_insert(rte);
        } else {
@@ -923,7 +927,7 @@ rt_update(struct in_addr prefix, u_int8_
                }
 
                if (equal || better)
-                       rt_nexthop_add(rte, vnh, adv_rtr);
+                       rt_nexthop_add(rte, vnh, v_type, adv_rtr);
        }
 }

Reply via email to