]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/rt.c
4 * (c) 2000--2004 Ondrej Filip <feela@network.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 add_cand(list
* l
, struct top_hash_entry
*en
,
13 struct top_hash_entry
*par
, u32 dist
, struct ospf_area
*oa
);
15 calc_next_hop(struct top_hash_entry
*en
,
16 struct top_hash_entry
*par
, struct ospf_area
*oa
);
17 static void ospf_ext_spf(struct proto_ospf
*po
);
18 static void rt_sync(struct proto_ospf
*po
);
20 /* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
21 as index, so we need to encapsulate RID to IP addresss */
23 #define ipa_from_rid(x) _MI(x)
25 #define ipa_from_rid(x) _MI(0,0,0,x)
30 get_ipv6_prefix(u32
*buf
, ip_addr
*addr
, int *pxlen
, u8
*pxopts
)
32 u8 pxl
= (*buf
>> 24);
33 *pxopts
= (*buf
>> 16);
52 get_ipv6_addr(u32
*buf
, ip_addr
*addr
)
54 *addr
= *(ip_addr
*) buf
;
61 orta
->type
= RTS_DUMMY
;
64 orta
->metric1
= LSINFINITY
;
65 orta
->metric2
= LSINFINITY
;
73 ospf_rt_initort(struct fib_node
*fn
)
77 memcpy(&ri
->o
, &ri
->n
, sizeof(orta
));
81 /* If new is better return 1 */
84 * This is hard to understand:
85 * If rfc1583 is set to 1, it work likes normal route_better()
86 * But if it is set to 0, it prunes number of AS boundary
87 * routes before it starts the router decision
90 ri_better(struct proto_ospf
*po
, orta
* new, ort
*nefn
, orta
* old
, ort
*oefn
, int rfc1583
)
92 int newtype
= new->type
;
93 int oldtype
= old
->type
;
95 if (old
->type
== RTS_DUMMY
)
98 if (old
->metric1
== LSINFINITY
)
103 if ((new->type
< RTS_OSPF_EXT1
) && (new->oa
->areaid
== 0)) newtype
= RTS_OSPF_IA
;
104 if ((old
->type
< RTS_OSPF_EXT2
) && (old
->oa
->areaid
== 0)) oldtype
= RTS_OSPF_IA
;
107 if (newtype
< oldtype
)
110 if (newtype
> oldtype
)
114 if (new->type
== RTS_OSPF_EXT2
)
116 if (new->metric2
< old
->metric2
) return 1;
117 if (new->metric2
> old
->metric2
) return 0;
120 if (((new->type
== RTS_OSPF_EXT2
) || (new->type
== RTS_OSPF_EXT1
)) && (!po
->rfc1583
))
122 newtype
= nefn
->n
.type
;
123 oldtype
= oefn
->n
.type
;
125 if (nefn
->n
.oa
->areaid
== 0) newtype
= RTS_OSPF_IA
;
126 if (oefn
->n
.oa
->areaid
== 0) oldtype
= RTS_OSPF_IA
;
128 if (newtype
< oldtype
) return 1;
129 if (newtype
> oldtype
) return 0;
132 if (new->metric1
< old
->metric1
)
135 if (new->metric1
> old
->metric1
)
138 if (new->oa
->areaid
> old
->oa
->areaid
) return 1; /* Larger AREAID is preffered */
140 return 0; /* Old is shorter or same */
144 ri_install(struct proto_ospf
*po
, ip_addr prefix
, int pxlen
, int dest
,
145 orta
* new, ort
* ipath
)
147 struct ospf_area
*oa
= new->oa
;
152 struct area_net
*anet
;
153 old
= (ort
*) fib_get(&po
->rtf
, &prefix
, pxlen
);
154 if (ri_better(po
, new, ipath
, &old
->n
, old
->efn
, 1))
156 memcpy(&old
->n
, new, sizeof(orta
));
158 if ((new->type
== RTS_OSPF
) && (anet
= (struct area_net
*)fib_route(&oa
->net_fib
, prefix
, pxlen
)))
161 if (new->metric1
> anet
->metric
) anet
->metric
= new->metric1
;
167 old
= (ort
*) fib_get(&oa
->rtr
, &prefix
, pxlen
);
169 if (ri_better(po
, new, ipath
, &old
->n
, old
->efn
, 1))
171 memcpy(&old
->n
, new, sizeof(orta
));
178 ospf_rt_spfa(struct ospf_area
*oa
)
181 struct ospf_lsa_rt
*rt
;
182 struct ospf_lsa_rt_link
*rtl
, *rr
;
183 struct proto
*p
= &oa
->po
->proto
;
184 struct proto_ospf
*po
= oa
->po
;
185 struct ospf_lsa_net
*ln
;
187 struct ospf_iface
*iface
;
188 struct top_hash_entry
*act
, *tmp
;
195 OSPF_TRACE(D_EVENTS
, "Starting routing table calculation for area %R", oa
->areaid
);
197 if (oa
->rt
->dist
!= LSINFINITY
)
198 bug("Aging was not processed.");
201 init_list(&oa
->cand
); /* Empty list of candidates */
204 DBG("LSA db prepared, adding me into candidate list.\n");
207 oa
->rt
->color
= CANDIDATE
;
208 add_head(&oa
->cand
, &oa
->rt
->cn
);
209 DBG("RT LSA: rt: %R, id: %R, type: %u\n",
210 oa
->rt
->lsa
.rt
, oa
->rt
->lsa
.id
, oa
->rt
->lsa
.type
);
212 while (!EMPTY_LIST(oa
->cand
))
215 act
= SKIP_BACK(struct top_hash_entry
, cn
, n
);
218 DBG("Working on LSA: rt: %R, id: %R, type: %u\n",
219 act
->lsa
.rt
, act
->lsa
.id
, act
->lsa
.type
);
222 switch (act
->lsa
.type
)
225 /* FIXME - in OSPFv3 we should process all RT LSAs from that router */
226 rt
= (struct ospf_lsa_rt
*) act
->lsa_body
;
227 if (rt
->options
& OPT_RT_V
)
229 /* FIXME - in OSPFv3, should we add all routers, or just ABRs an ASBRs? */
230 if ((rt
->options
& OPT_RT_V
) || (rt
->options
& OPT_RT_E
))
233 nf
.options
= rt
->options
;
234 nf
.metric1
= act
->dist
;
235 nf
.metric2
= LSINFINITY
;
241 ri_install(po
, ipa_from_rid(act
->lsa
.rt
), 32, ORT_ROUTER
, &nf
, NULL
);
243 rr
= (struct ospf_lsa_rt_link
*) (rt
+ 1);
244 DBG(" Number of links: %u\n", rt
->links
);
245 for (i
= 0; i
< lsa_rt_count(&act
->lsa
); i
++)
249 DBG(" Working on link: %R (type: %u) ", rtl
->id
, rtl
->type
);
255 * This violates rfc2328! But it is mostly harmless.
256 * But it causes that the cost of the stub is ignored.
262 nf
.metric1
= act
->dist
+ rtl
->metric
;
263 nf
.metric2
= LSINFINITY
;
272 struct ospf_iface
*iff
;
274 WALK_LIST(iff
, po
->iface_list
) /* Try to find corresponding interface */
276 if (iff
->iface
&& (iff
->type
!= OSPF_IT_VLINK
) &&
277 (rtl
->id
== (ipa_to_u32(ipa_mkmask(iff
->iface
->addr
->pxlen
))
278 & ipa_to_u32(iff
->iface
->addr
->prefix
)))) /* No VLINK and IP must match */
289 ri_install(po
, ipa_from_u32(rtl
->id
),
290 ipa_mklen(ipa_from_u32(rtl
->data
)), ORT_NET
, &nf
, NULL
);
295 /* In OSPFv2, rtl->id is IP addres of DR, router ID is not known */
296 tmp
= ospfxx_hash_find(po
->gr
, oa
->areaid
, rtl
->id
, 0, LSA_T_NET
);
298 tmp
= ospfxx_hash_find(po
->gr
, oa
->areaid
, rtl
->nif
, rtl
->id
, LSA_T_NET
);
308 /* FIXME - in OSPFv3, find any LSA ID */
309 tmp
= ospfxx_hash_find(po
->gr
, oa
->areaid
, rtl
->id
, rtl
->id
, LSA_T_RT
);
313 log("Unknown link type in router lsa. (rid = %R)", act
->lsa
.id
);
317 DBG("Going to add cand, Mydist: %u, Req: %u\n",
318 tmp
->dist
, act
->dist
+ rtl
->metric
);
319 add_cand(&oa
->cand
, tmp
, act
, act
->dist
+ rtl
->metric
, oa
);
326 nf
.metric1
= act
->dist
;
327 nf
.metric2
= LSINFINITY
;
333 ri_install(po
, ipa_and(ipa_from_u32(act
->lsa
.id
), ln
->netmask
),
334 ipa_mklen(ln
->netmask
), ORT_NET
, &nf
, NULL
);
336 rts
= (u32
*) (ln
+ 1);
337 for (i
= 0; i
< lsa_net_count(&act
->lsa
); i
++)
339 DBG(" Working on router %R ", rts
[i
]);
340 /* FIXME - in OSPFv3, find any LSA ID */
341 tmp
= ospfxx_hash_find(po
->gr
, oa
->areaid
, rts
[i
], rts
[i
], LSA_T_RT
);
346 add_cand(&oa
->cand
, tmp
, act
, act
->dist
, oa
);
352 /* Find new/lost VLINK peers */
353 WALK_LIST(iface
, po
->iface_list
)
355 if ((iface
->type
== OSPF_IT_VLINK
) && (iface
->voa
== oa
))
357 /* FIXME in OSPFv3, different LSAID */
358 if ((tmp
= ospfxx_hash_find(po
->gr
, oa
->areaid
, iface
->vid
, iface
->vid
, LSA_T_RT
)) &&
359 (!ipa_equal(tmp
->lb
, IPA_NONE
)))
361 if ((iface
->state
!= OSPF_IS_PTP
) || (iface
->iface
!= tmp
->nhi
->iface
) || (!ipa_equal(iface
->vip
, tmp
->lb
)))
363 OSPF_TRACE(D_EVENTS
, "Vlink peer %R found", tmp
->lsa
.id
);
364 ospf_iface_sm(iface
, ISM_DOWN
);
365 iface
->iface
= tmp
->nhi
->iface
;
366 iface
->vip
= tmp
->lb
;
367 ospf_iface_sm(iface
, ISM_UP
);
372 if (iface
->state
> OSPF_IS_DOWN
)
374 OSPF_TRACE(D_EVENTS
, "Vlink peer %R lost", iface
->vid
);
375 ospf_iface_sm(iface
, ISM_DOWN
);
383 link_back(struct ospf_area
*oa
, struct top_hash_entry
*fol
, struct top_hash_entry
*pre
)
386 struct ospf_lsa_net
*ln
;
387 struct ospf_lsa_rt
*rt
;
388 struct ospf_lsa_rt_link
*rtl
, *rr
;
389 struct proto_ospf
*po
= oa
->po
;
393 switch (fol
->lsa
.type
)
396 rt
= (struct ospf_lsa_rt
*) fol
->lsa_body
;
397 rr
= (struct ospf_lsa_rt_link
*) (rt
+ 1);
398 for (i
= 0; i
< lsa_rt_count(&fol
->lsa
); i
++)
406 if (ospfxx_hash_find(po
->gr
, oa
->areaid
, rtl
->id
, rtl
->id
, LSA_T_NET
) == pre
)
408 fol
->lb
= ipa_from_u32(rtl
->data
);
414 if (ospfxx_hash_find(po
->gr
, oa
->areaid
, rtl
->id
, rtl
->id
, LSA_T_RT
) == pre
)
416 fol
->lb
= ipa_from_u32(rtl
->data
);
421 log("Unknown link type in router lsa. (rid = %R)", fol
->lsa
.id
);
428 rts
= (u32
*) (ln
+ 1);
429 for (i
= 0; i
< lsa_net_count(&fol
->lsa
); i
++)
431 if (ospfxx_hash_find(po
->gr
, oa
->areaid
, *(rts
+ i
), *(rts
+ i
), LSA_T_RT
) == pre
)
438 bug("Unknown lsa type. (id = %R)", fol
->lsa
.id
);
444 ospf_rt_sum_tr(struct ospf_area
*oa
)
446 struct proto
*p
= &oa
->po
->proto
;
447 struct proto_ospf
*po
= oa
->po
;
448 struct ospf_area
*bb
= po
->backbone
;
450 struct top_hash_entry
*en
;
451 u32 dst_rid
, metric
, options
;
452 int pxlen
= -1, type
= -1;
453 ort
*re
= NULL
, *abr
;
458 WALK_SLIST(en
, po
->lsal
)
460 if ((en
->lsa
.type
!= LSA_T_SUM_RT
) && (en
->lsa
.type
!= LSA_T_SUM_NET
))
463 if (en
->domain
!= oa
->areaid
)
466 if (en
->lsa
.age
== LSA_MAXAGE
)
469 if (en
->dist
== LSINFINITY
)
472 if (en
->lsa
.rt
== p
->cf
->global
->router_id
)
476 if (en
->lsa
.type
== LSA_T_SUM_NET
)
479 struct ospf_lsa_sum
*ls
= en
->lsa_body
;
480 pxlen
= ipa_mklen(ls
->netmask
);
481 ip
= ipa_and(ipa_from_u32(en
->lsa
.id
), ls
->netmask
);
484 struct ospf_lsa_sum_net
*ls
= en
->lsa_body
;
485 get_ipv6_prefix(ls
->prefix
, &ip
, &pxlen
, &pxopts
);
486 if (pxopts
& OPT_PX_NU
)
490 metric
= ls
->metric
& METRIC_MASK
;
493 re
= (ort
*) fib_find(&po
->rtf
, &ip
, pxlen
);
495 else if (en
->lsa
.type
== LSA_T_SUM_RT
)
498 struct ospf_lsa_sum
*ls
= en
->lsa_body
;
499 dst_rid
= en
->lsa
.id
;
502 struct ospf_lsa_sum_rt
*ls
= en
->lsa_body
;
504 options
= ls
->options
& OPTIONS_MASK
;
507 ip
= ipa_from_rid(dst_rid
);
509 metric
= ls
->metric
& METRIC_MASK
;
510 options
|= ORTA_ASBR
;
512 re
= (ort
*) fib_find(&bb
->rtr
, &ip
, pxlen
);
516 if (re
->n
.oa
->areaid
!= 0) continue;
517 if ((re
->n
.type
!= RTS_OSPF
) && (re
->n
.type
!= RTS_OSPF_IA
)) continue;
519 abrip
= ipa_from_rid(en
->lsa
.rt
);
521 abr
= fib_find(&oa
->rtr
, &abrip
, 32);
524 nf
.type
= re
->n
.type
;
525 nf
.options
= options
;
526 nf
.metric1
= abr
->n
.metric1
+ metric
;
527 nf
.metric2
= LSINFINITY
;
533 ri_install(po
, ip
, pxlen
, type
, &nf
, NULL
);
539 ospf_rt_sum(struct ospf_area
*oa
)
541 struct proto_ospf
*po
= oa
->po
;
542 struct proto
*p
= &po
->proto
;
543 struct top_hash_entry
*en
;
544 ip_addr ip
, abrip
; /* abrIP is actually ID */
545 u32 dst_rid
, metric
, options
;
546 struct area_net
*anet
;
549 int pxlen
= -1, type
= -1;
551 OSPF_TRACE(D_EVENTS
, "Starting routing table calculation for inter-area (area %R)", oa
->areaid
);
553 WALK_SLIST(en
, po
->lsal
)
555 if ((en
->lsa
.type
!= LSA_T_SUM_RT
) && (en
->lsa
.type
!= LSA_T_SUM_NET
))
558 if (en
->domain
!= oa
->areaid
)
562 if (en
->lsa
.age
== LSA_MAXAGE
)
566 if (en
->lsa
.rt
== p
->cf
->global
->router_id
)
570 if (en
->lsa
.type
== LSA_T_SUM_NET
)
572 struct ospf_area
*oaa
;
576 struct ospf_lsa_sum
*ls
= en
->lsa_body
;
577 pxlen
= ipa_mklen(ls
->netmask
);
578 ip
= ipa_and(ipa_from_u32(en
->lsa
.id
), ls
->netmask
);
581 struct ospf_lsa_sum_net
*ls
= en
->lsa_body
;
582 get_ipv6_prefix(ls
->prefix
, &ip
, &pxlen
, &pxopts
);
583 if (pxopts
& OPT_PX_NU
)
587 metric
= ls
->metric
& METRIC_MASK
;
592 WALK_LIST(oaa
, po
->area_list
)
594 if ((anet
= fib_find(&oaa
->net_fib
, &ip
, pxlen
)) && anet
->active
)
605 struct ospf_lsa_sum
*ls
= en
->lsa_body
;
606 dst_rid
= en
->lsa
.id
;
609 struct ospf_lsa_sum_rt
*ls
= en
->lsa_body
;
611 options
= ls
->options
& OPTIONS_MASK
;
614 ip
= ipa_from_rid(dst_rid
);
616 metric
= ls
->metric
& METRIC_MASK
;
617 options
|= ORTA_ASBR
;
622 if (metric
== LSINFINITY
)
626 abrip
= ipa_from_rid(en
->lsa
.rt
);
627 if (!(abr
= (ort
*) fib_find(&oa
->rtr
, &abrip
, 32))) continue;
628 if (abr
->n
.metric1
== LSINFINITY
) continue;
629 if (!(abr
->n
.options
& ORTA_ABR
)) continue;
631 nf
.type
= RTS_OSPF_IA
;
632 nf
.options
= options
;
633 nf
.metric1
= abr
->n
.metric1
+ metric
;
634 nf
.metric2
= LSINFINITY
;
640 ri_install(po
, ip
, pxlen
, type
, &nf
, NULL
);
645 * ospf_rt_spf - calculate internal routes
648 * Calculation of internal paths in an area is described in 16.1 of RFC 2328.
649 * It's based on Dijkstra's shortest path tree algorithms.
650 * This function is invoked from ospf_disp().
653 ospf_rt_spf(struct proto_ospf
*po
)
655 struct proto
*p
= &po
->proto
;
656 struct ospf_area
*oa
;
658 struct area_net
*anet
;
660 if (po
->areano
== 0) return;
664 OSPF_TRACE(D_EVENTS
, "Starting routing table calculation");
666 /* 16. (1) - Invalidate old routing table */
667 FIB_WALK(&po
->rtf
, nftmp
)
670 memcpy(&ri
->o
, &ri
->n
, sizeof(orta
)); /* Backup old data */
676 WALK_LIST(oa
, po
->area_list
)
678 FIB_WALK(&oa
->rtr
, nftmp
)
681 memcpy(&ri
->o
, &ri
->n
, sizeof(orta
)); /* Backup old data */
686 FIB_WALK(&oa
->net_fib
, nftmp
)
688 anet
= (struct area_net
*) nftmp
;
699 if ((po
->areano
== 1) || (!po
->backbone
))
701 ospf_rt_sum(HEAD(po
->area_list
));
705 ospf_rt_sum(po
->backbone
);
709 WALK_LIST(oa
, po
->area_list
)
711 if (oa
->trcap
&& (oa
->areaid
!= 0))
727 * ospf_ext_spf - calculate external paths
730 * After routing table for any area is calculated, calculation of external
731 * path is invoked. This process is described in 16.4 of RFC 2328.
732 * Inter- and Intra-area paths are always prefered over externals.
735 ospf_ext_spf(struct proto_ospf
*po
)
737 ort
*nf1
, *nf2
, *nfh
;
739 struct top_hash_entry
*en
;
740 struct proto
*p
= &po
->proto
;
741 struct ospf_lsa_ext
*le
;
742 int pxlen
, ebit
, rt_fwaddr_valid
;
743 ip_addr ip
, nh
, rtid
, rt_fwaddr
;
744 struct ospf_iface
*nhi
= NULL
;
745 u32 br_metric
, rt_metric
, rt_tag
;
747 struct ospf_area
*atmp
;
749 OSPF_TRACE(D_EVENTS
, "Starting routing table calculation for ext routes");
751 WALK_SLIST(en
, po
->lsal
)
754 if (en
->lsa
.type
!= LSA_T_EXT
)
756 if (en
->lsa
.age
== LSA_MAXAGE
)
760 if (en
->lsa
.rt
== p
->cf
->global
->router_id
)
763 DBG("%s: Working on LSA. ID: %R, RT: %R, Type: %u, Mask %I\n",
764 p
->name
, en
->lsa
.id
, en
->lsa
.rt
, en
->lsa
.type
, le
->netmask
);
768 rt_metric
= le
->metric
& METRIC_MASK
;
769 ebit
= le
->metric
& LSA_EXT_EBIT
;
771 if (rt_metric
== LSINFINITY
)
775 ip
= ipa_and(ipa_from_u32(en
->lsa
.id
), le
->netmask
);
776 pxlen
= ipa_mklen(le
->netmask
);
777 rt_fwaddr
= le
->fwaddr
;
778 rt_fwaddr_valid
= !ipa_equal(rt_fwaddr
, IPA_NONE
);
783 buf
= get_ipv6_prefix(buf
, &ip
, &pxlen
, &pxopts
);
785 if (pxopts
& OPT_PX_NU
)
788 rt_fwaddr_valid
= le
->metric
& LSA_EXT_FBIT
;
790 buf
= get_ipv6_addr(buf
, &rt_fwaddr
);
792 rt_fwaddr
= IPA_NONE
;
794 if (le
->metric
& LSA_EXT_TBIT
)
802 log("%s: Invalid mask in LSA. ID: %R, RT: %R, Type: %u",
803 p
->name
, en
->lsa
.id
, en
->lsa
.rt
, en
->lsa
.type
);
810 rtid
= ipa_from_rid(en
->lsa
.rt
);
812 WALK_LIST(atmp
, po
->area_list
)
814 nfh
= fib_find(&atmp
->rtr
, &rtid
, 32);
815 if (nfh
== NULL
) continue;
816 if (nf1
== NULL
) nf1
= nfh
;
817 else if (ri_better(po
, &nfh
->n
, NULL
, &nf1
->n
, NULL
, po
->rfc1583
)) nf1
= nfh
;
821 continue; /* No AS boundary router found */
823 if (nf1
->n
.metric1
== LSINFINITY
)
824 continue; /* distance is INF */
826 if (!(nf1
->n
.options
& ORTA_ASBR
))
827 continue; /* It is not ASBR */
829 if (!rt_fwaddr_valid
)
834 br_metric
= nf1
->n
.metric1
;
838 nf2
= fib_route(&po
->rtf
, rt_fwaddr
, 32);
842 DBG("Cannot find network route (GW=%I)\n", rt_fwaddr
);
847 if ((nn
= neigh_find(p
, &rt_fwaddr
, 0)) != NULL
)
850 nhi
= ospf_iface_find(po
, nn
->iface
);
858 br_metric
= nf2
->n
.metric1
;
859 if (br_metric
== LSINFINITY
)
860 continue; /* distance is INF */
865 nfa
.type
= RTS_OSPF_EXT2
;
866 nfa
.metric1
= br_metric
;
867 nfa
.metric2
= rt_metric
;
871 nfa
.type
= RTS_OSPF_EXT1
;
872 nfa
.metric1
= br_metric
+ rt_metric
;
873 nfa
.metric2
= LSINFINITY
;
878 nfa
.oa
= (po
->backbone
== NULL
) ? HEAD(po
->area_list
) : po
->backbone
;
882 ri_install(po
, ip
, pxlen
, ORT_NET
, &nfa
, nfh
);
887 /* Add LSA into list of candidates in Dijkstra's algorithm */
889 add_cand(list
* l
, struct top_hash_entry
*en
, struct top_hash_entry
*par
,
890 u32 dist
, struct ospf_area
*oa
)
894 struct top_hash_entry
*act
;
898 if (en
->lsa
.age
== LSA_MAXAGE
)
902 if (en
->color
== INSPF
)
906 if (dist
>= en
->dist
)
909 * FIXME The line above (=) is not a bug, but we don't support multiple
910 * next hops. I'll start as soon as nest will
913 if (!link_back(oa
, en
, par
))
916 DBG(" Adding candidate: rt: %R, id: %R, type: %u\n",
917 en
->lsa
.rt
, en
->lsa
.id
, en
->lsa
.type
);
922 calc_next_hop(en
, par
, oa
);
925 return; /* We cannot find next hop, ignore it */
927 if (en
->color
== CANDIDATE
)
928 { /* We found a shorter path */
932 en
->color
= CANDIDATE
;
938 add_head(l
, &en
->cn
);
944 act
= SKIP_BACK(struct top_hash_entry
, cn
, n
);
945 if ((act
->dist
> dist
) ||
946 ((act
->dist
== dist
) && (act
->lsa
.type
== LSA_T_NET
)))
947 /* FIXME - shouldn't be here LSA_T_RT ??? */
950 add_head(l
, &en
->cn
);
952 insert_node(&en
->cn
, prev
);
961 add_tail(l
, &en
->cn
);
967 calc_next_hop(struct top_hash_entry
*en
, struct top_hash_entry
*par
,
968 struct ospf_area
*oa
)
970 struct ospf_neighbor
*neigh
;
971 struct proto
*p
= &oa
->po
->proto
;
972 struct proto_ospf
*po
= oa
->po
;
973 struct ospf_iface
*ifa
;
974 u32 myrid
= p
->cf
->global
->router_id
;
976 /* 16.1.1. The next hop calculation */
977 DBG(" Next hop called.\n");
978 if (ipa_equal(par
->nh
, IPA_NONE
))
981 DBG(" Next hop calculating for id: %R rt: %R type: %u\n",
982 en
->lsa
.id
, en
->lsa
.rt
, en
->lsa
.type
);
984 /* The parent vertex is the root */
987 if (en
->lsa
.type
== LSA_T_NET
)
989 if (en
->lsa
.rt
== myrid
)
991 WALK_LIST(ifa
, po
->iface_list
)
992 if (ifa
->iface
&& (ipa_compare
993 (ifa
->iface
->addr
->ip
, ipa_from_u32(en
->lsa
.id
)) == 0))
998 log(L_ERR
"I didn't find interface for my self originated LSA!\n");
999 /* This could sometimes happen */
1004 ip_addr ip
= ipa_from_u32(en
->lsa
.id
);
1005 nn
= neigh_find(p
, &ip
, 0);
1007 en
->nhi
= ospf_iface_find(po
, nn
->iface
);
1013 if ((neigh
= find_neigh_noifa(po
, en
->lsa
.rt
)) == NULL
)
1015 en
->nhi
= neigh
->ifa
;
1016 if (ipa_equal(en
->nh
, IPA_NONE
))
1017 en
->nh
= neigh
->ip
; /* Yes, neighbor is it's
1023 /* The parent vertex is a network that directly connects the
1024 calculating router to the destination router. */
1025 if (par
->lsa
.type
== LSA_T_NET
)
1027 if (en
->lsa
.type
== LSA_T_NET
)
1028 bug("Parent for net is net?");
1029 if ((en
->nhi
= par
->nhi
) == NULL
)
1030 bug("Did not find next hop interface for INSPF lsa!");
1031 if ((neigh
= find_neigh_noifa(po
, en
->lsa
.rt
)) == NULL
)
1033 en
->nhi
= neigh
->ifa
;
1034 en
->nh
= neigh
->ip
; /* Yes, neighbor is it's own
1039 { /* Parent is some RT neighbor */
1040 log(L_ERR
"Router's parent has no next hop. (EN=%R, PAR=%R)",
1041 en
->lsa
.id
, par
->lsa
.id
);
1042 /* I hope this would never happen */
1048 DBG(" Next hop calculated: %I.\n", en
->nh
);
1052 rt_sync(struct proto_ospf
*po
)
1054 struct proto
*p
= &po
->proto
;
1055 struct fib_iterator fit
;
1056 struct fib
*fib
= &po
->rtf
;
1058 struct ospf_area
*oa
, *oaa
;
1059 struct area_net
*anet
;
1062 OSPF_TRACE(D_EVENTS
, "Starting routing table synchronisation");
1064 DBG("Now syncing my rt table with nest's\n");
1065 FIB_ITERATE_INIT(&fit
, fib
);
1067 FIB_ITERATE_START(fib
, &fit
, nftmp
)
1070 check_sum_lsa(po
, nf
, ORT_NET
);
1071 if (memcmp(&nf
->n
, &nf
->o
, sizeof(orta
)))
1072 { /* Some difference */
1077 bzero(&a0
, sizeof(a0
));
1080 a0
.source
= nf
->n
.type
;
1081 a0
.scope
= SCOPE_UNIVERSE
;
1082 a0
.cast
= RTC_UNICAST
;
1083 a0
.dest
= RTD_ROUTER
;
1087 if (nf
->n
.ifa
) a0
.iface
= nf
->n
.ifa
->iface
;
1090 if ((!ipa_equal(nf
->n
.nh
, IPA_NONE
)) && (!neigh_find(p
, &nf
->n
.nh
, 0)))
1093 struct ospf_iface
*ifa
;
1094 struct top_hash_entry
*en
;
1095 OSPF_TRACE(D_EVENTS
, "Trying to find correct next hop");
1096 WALK_LIST(ifa
, po
->iface_list
)
1098 if ((ifa
->type
== OSPF_IT_VLINK
) && ipa_equal(ifa
->vip
, nf
->n
.nh
))
1100 /* FIXME in OSPFv3, may be different LSA ID */
1101 if ((en
= ospfxx_hash_find(po
->gr
, ifa
->voa
->areaid
, ifa
->vid
, ifa
->vid
, LSA_T_RT
))
1102 && (!ipa_equal(en
->nh
, IPA_NONE
)))
1110 if (!found
) nf
->n
.metric1
= LSINFINITY
; /* Delete it */
1113 if (ipa_equal(nf
->n
.nh
, IPA_NONE
)) a0
.dest
= RTD_DEVICE
;
1115 if (!a0
.iface
) /* Still no match? Can this really happen? */
1116 nf
->n
.metric1
= LSINFINITY
;
1118 ne
= net_get(p
->table
, nf
->fn
.prefix
, nf
->fn
.pxlen
);
1119 if (nf
->n
.metric1
< LSINFINITY
)
1121 e
= rte_get_temp(&a0
);
1122 e
->u
.ospf
.metric1
= nf
->n
.metric1
;
1123 e
->u
.ospf
.metric2
= nf
->n
.metric2
;
1124 e
->u
.ospf
.tag
= nf
->n
.tag
;
1127 e
->pref
= p
->preference
;
1128 DBG("Mod rte type %d - %I/%d via %I on iface %s, met %d\n",
1129 a0
.source
, nf
->fn
.prefix
, nf
->fn
.pxlen
, a0
.gw
, a0
.iface
? a0
.iface
->name
: "(none)", nf
->n
.metric1
);
1130 rte_update(p
->table
, ne
, p
, p
, e
);
1134 rte_update(p
->table
, ne
, p
, p
, NULL
);
1135 FIB_ITERATE_PUT(&fit
, nftmp
);
1136 fib_delete(fib
, nftmp
);
1141 FIB_ITERATE_END(nftmp
);
1143 WALK_LIST(oa
, po
->area_list
)
1145 FIB_ITERATE_INIT(&fit
, &oa
->rtr
);
1147 FIB_ITERATE_START(&oa
->rtr
, &fit
, nftmp
)
1150 if (memcmp(&nf
->n
, &nf
->o
, sizeof(orta
)))
1151 { /* Some difference */
1152 check_sum_lsa(po
, nf
, ORT_ROUTER
);
1153 if (nf
->n
.metric1
>= LSINFINITY
)
1155 FIB_ITERATE_PUT(&fit
, nftmp
);
1156 fib_delete(&oa
->rtr
, nftmp
);
1161 FIB_ITERATE_END(nftmp
);
1163 /* Check condensed summary LSAs */
1164 FIB_WALK(&oa
->net_fib
, nftmp
)
1167 anet
= (struct area_net
*) nftmp
;
1168 if ((!anet
->hidden
) && anet
->active
)
1171 WALK_LIST(oaa
, po
->area_list
)
1175 if (oaa
== oa
) continue;
1177 if ((oa
== po
->backbone
) && oaa
->trcap
) fl
= 1;
1179 if (oaa
->stub
) fl
= 1;
1181 if (fl
) flush_sum_lsa(oaa
, &anet
->fn
, ORT_NET
);
1182 else originate_sum_lsa(oaa
, &anet
->fn
, ORT_NET
, anet
->metric
, 0);
1187 /* Check default summary LSA for stub areas
1188 * just for router connected to backbone */
1191 struct fib_node fnn
;
1193 fnn
.prefix
= IPA_NONE
;
1195 if (oa
->stub
) originate_sum_lsa(oa
, &fnn
, ORT_NET
, oa
->stub
, 0);
1196 else flush_sum_lsa(oa
, &fnn
, ORT_NET
);