]>
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.
11 static void add_cand(list
* l
, struct top_hash_entry
*en
,
12 struct top_hash_entry
*par
, u32 dist
,
13 struct ospf_area
*oa
, int i
);
14 static void rt_sync(struct proto_ospf
*po
);
16 /* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
17 as index, so we need to encapsulate RID to IP address */
19 #define ipa_from_rid(x) _MI(x)
21 #define ipa_from_rid(x) _MI(0,0,0,x)
25 static inline void reset_ri(ort
*ort
)
27 bzero(&ort
->n
, sizeof(orta
));
31 ospf_rt_initort(struct fib_node
*fn
)
36 ri
->fn
.x0
= ri
->fn
.x1
= 0;
40 unresolved_vlink(struct mpnh
*nhs
)
42 return nhs
&& !nhs
->iface
;
45 static inline struct mpnh
*
46 new_nexthop(struct proto_ospf
*po
, ip_addr gw
, struct iface
*iface
, unsigned char weight
)
48 struct mpnh
*nh
= lp_alloc(po
->nhpool
, sizeof(struct mpnh
));
56 static inline struct mpnh
*
57 copy_nexthop(struct proto_ospf
*po
, struct mpnh
*src
)
59 struct mpnh
*nh
= lp_alloc(po
->nhpool
, sizeof(struct mpnh
));
61 nh
->iface
= src
->iface
;
63 nh
->weight
= src
->weight
;
68 /* If new is better return 1 */
70 ri_better(struct proto_ospf
*po
, orta
*new, orta
*old
)
72 if (old
->type
== RTS_DUMMY
)
75 if (new->type
< old
->type
)
78 if (new->type
> old
->type
)
81 if (new->metric1
< old
->metric1
)
84 if (new->metric1
> old
->metric1
)
91 /* Whether the ASBR or the forward address destination is preferred
92 in AS external route selection according to 16.4.1. */
94 epath_preferred(orta
*ep
)
96 return (ep
->type
== RTS_OSPF
) && (ep
->oa
->areaid
!= 0);
99 /* 16.4. (3), return 1 if new is better */
101 ri_better_asbr(struct proto_ospf
*po
, orta
*new, orta
*old
)
103 if (old
->type
== RTS_DUMMY
)
108 int new_pref
= epath_preferred(new);
109 int old_pref
= epath_preferred(old
);
111 if (new_pref
> old_pref
)
114 if (new_pref
< old_pref
)
118 if (new->metric1
< old
->metric1
)
121 if (new->metric1
> old
->metric1
)
124 /* Larger area ID is preferred */
125 if (new->oa
->areaid
> old
->oa
->areaid
)
134 /* RFC 3103 2.5 (6e) priorities */
135 u32 opts
= nf
->options
& (ORTA_NSSA
| ORTA_PROP
);
137 /* A Type-7 LSA with the P-bit set */
138 if (opts
== (ORTA_NSSA
| ORTA_PROP
))
148 /* 16.4. (6), return 1 if new is better */
150 ri_better_ext(struct proto_ospf
*po
, orta
*new, orta
*old
)
152 if (old
->type
== RTS_DUMMY
)
156 if (new->type
< old
->type
)
159 if (new->type
> old
->type
)
162 /* 16.4. (6b), same type */
163 if (new->type
== RTS_OSPF_EXT2
)
165 if (new->metric2
< old
->metric2
)
168 if (new->metric2
> old
->metric2
)
175 u32 new_pref
= new->options
& ORTA_PREF
;
176 u32 old_pref
= old
->options
& ORTA_PREF
;
178 if (new_pref
> old_pref
)
181 if (new_pref
< old_pref
)
186 if (new->metric1
< old
->metric1
)
189 if (new->metric1
> old
->metric1
)
192 /* RFC 3103, 2.5. (6e) */
193 int new_prio
= orta_prio(new);
194 int old_prio
= orta_prio(old
);
196 if (new_prio
> old_prio
)
199 if (old_prio
> new_prio
)
202 /* make it more deterministic */
203 if (new->rid
> old
->rid
)
210 ri_install_net(struct proto_ospf
*po
, ip_addr prefix
, int pxlen
, orta
*new)
212 ort
*old
= (ort
*) fib_get(&po
->rtf
, &prefix
, pxlen
);
213 if (ri_better(po
, new, &old
->n
))
214 memcpy(&old
->n
, new, sizeof(orta
));
218 ri_install_rt(struct ospf_area
*oa
, u32 rid
, orta
*new)
220 ip_addr addr
= ipa_from_rid(rid
);
221 ort
*old
= (ort
*) fib_get(&oa
->rtr
, &addr
, MAX_PREFIX_LENGTH
);
222 if (ri_better(oa
->po
, new, &old
->n
))
223 memcpy(&old
->n
, new, sizeof(orta
));
227 ri_install_asbr(struct proto_ospf
*po
, ip_addr
*addr
, orta
*new)
229 ort
*old
= (ort
*) fib_get(&po
->backbone
->rtr
, addr
, MAX_PREFIX_LENGTH
);
230 if (ri_better_asbr(po
, new, &old
->n
))
231 memcpy(&old
->n
, new, sizeof(orta
));
235 ri_install_ext(struct proto_ospf
*po
, ip_addr prefix
, int pxlen
, orta
*new)
237 ort
*old
= (ort
*) fib_get(&po
->rtf
, &prefix
, pxlen
);
238 if (ri_better_ext(po
, new, &old
->n
))
239 memcpy(&old
->n
, new, sizeof(orta
));
242 static inline struct ospf_iface
*
243 rt_pos_to_ifa(struct ospf_area
*oa
, int pos
)
245 struct ospf_iface
*ifa
;
246 WALK_LIST(ifa
, oa
->po
->iface_list
)
247 if (ifa
->oa
== oa
&& pos
>= ifa
->rt_pos_beg
&& pos
< ifa
->rt_pos_end
)
253 static inline struct ospf_iface
*
254 px_pos_to_ifa(struct ospf_area
*oa
, int pos
)
256 struct ospf_iface
*ifa
;
257 WALK_LIST(ifa
, oa
->po
->iface_list
)
258 if (ifa
->oa
== oa
&& pos
>= ifa
->px_pos_beg
&& pos
< ifa
->px_pos_end
)
266 add_network(struct ospf_area
*oa
, ip_addr px
, int pxlen
, int metric
, struct top_hash_entry
*en
, int pos
)
272 .metric2
= LSINFINITY
,
279 if (pxlen
< 0 || pxlen
> MAX_PREFIX_LENGTH
)
281 log(L_WARN
"%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
282 oa
->po
->proto
.name
, en
->lsa
.type
, en
->lsa
.id
, en
->lsa
.rt
);
289 * Local stub networks does not have proper iface in en->nhi
290 * (because they all have common top_hash_entry en).
291 * We have to find iface responsible for that stub network.
292 * Configured stubnets does not have any iface. They will
293 * be removed in rt_sync().
296 struct ospf_iface
*ifa
;
298 ifa
= rt_pos_to_ifa(oa
, pos
);
300 ifa
= px_pos_to_ifa(oa
, pos
);
303 nf
.nhs
= ifa
? new_nexthop(oa
->po
, IPA_NONE
, ifa
->iface
, ifa
->ecmp_weight
) : NULL
;
306 ri_install_net(oa
->po
, px
, pxlen
, &nf
);
311 process_prefixes(struct ospf_area
*oa
)
313 struct proto_ospf
*po
= oa
->po
;
314 // struct proto *p = &po->proto;
315 struct top_hash_entry
*en
, *src
;
316 struct ospf_lsa_prefix
*px
;
324 WALK_SLIST(en
, po
->lsal
)
326 if (en
->lsa
.type
!= LSA_T_PREFIX
)
329 if (en
->domain
!= oa
->areaid
)
332 if (en
->lsa
.age
== LSA_MAXAGE
)
337 /* For router prefix-LSA, we would like to find the first router-LSA */
338 if (px
->ref_type
== LSA_T_RT
)
339 src
= ospf_hash_find_rt(po
->gr
, oa
->areaid
, px
->ref_rt
);
341 src
= ospf_hash_find(po
->gr
, oa
->areaid
, px
->ref_id
, px
->ref_rt
, px
->ref_type
);
346 /* Reachable in SPF */
347 if (src
->color
!= INSPF
)
350 if ((src
->lsa
.type
!= LSA_T_RT
) && (src
->lsa
.type
!= LSA_T_NET
))
354 for (i
= 0; i
< px
->pxcount
; i
++)
356 buf
= lsa_get_ipv6_prefix(buf
, &pxa
, &pxlen
, &pxopts
, &metric
);
358 if (pxopts
& OPT_PX_NU
)
361 /* Store the first global address to use it later as a vlink endpoint */
362 if ((pxopts
& OPT_PX_LA
) && ipa_zero(src
->lb
))
365 add_network(oa
, pxa
, pxlen
, src
->dist
+ metric
, src
, i
);
373 ospf_rt_spfa_rtlinks(struct ospf_area
*oa
, struct top_hash_entry
*act
, struct top_hash_entry
*en
)
375 // struct proto *p = &oa->po->proto;
376 struct proto_ospf
*po
= oa
->po
;
377 ip_addr prefix UNUSED
;
380 struct ospf_lsa_rt
*rt
= en
->lsa_body
;
381 struct ospf_lsa_rt_link
*rr
= (struct ospf_lsa_rt_link
*) (rt
+ 1);
383 for (i
= 0; i
< lsa_rt_count(&en
->lsa
); i
++)
385 struct ospf_lsa_rt_link
*rtl
= rr
+ i
;
386 struct top_hash_entry
*tmp
= NULL
;
388 DBG(" Working on link: %R (type: %u) ", rtl
->id
, rtl
->type
);
394 * RFC 2328 in 16.1. (2a) says to handle stub networks in an
395 * second phase after the SPF for an area is calculated. We get
396 * the same result by handing them here because add_network()
397 * will keep the best (not the first) found route.
399 prefix
= ipa_from_u32(rtl
->id
& rtl
->data
);
400 pxlen
= ipa_mklen(ipa_from_u32(rtl
->data
));
401 add_network(oa
, prefix
, pxlen
, act
->dist
+ rtl
->metric
, act
, i
);
407 /* In OSPFv2, rtl->id is IP addres of DR, Router ID is not known */
408 tmp
= ospf_hash_find_net(po
->gr
, oa
->areaid
, rtl
->id
);
410 tmp
= ospf_hash_find(po
->gr
, oa
->areaid
, rtl
->nif
, rtl
->id
, LSA_T_NET
);
416 tmp
= ospf_hash_find_rt(po
->gr
, oa
->areaid
, rtl
->id
);
420 log("Unknown link type in router lsa. (rid = %R)", act
->lsa
.id
);
425 DBG("Going to add cand, Mydist: %u, Req: %u\n",
426 tmp
->dist
, act
->dist
+ rtl
->metric
);
427 add_cand(&oa
->cand
, tmp
, act
, act
->dist
+ rtl
->metric
, oa
, i
);
431 /* RFC 2328 16.1. calculating shortest paths for an area */
433 ospf_rt_spfa(struct ospf_area
*oa
)
435 struct proto
*p
= &oa
->po
->proto
;
436 struct proto_ospf
*po
= oa
->po
;
437 struct ospf_lsa_rt
*rt
;
438 struct ospf_lsa_net
*ln
;
439 struct top_hash_entry
*act
, *tmp
;
440 ip_addr prefix UNUSED
;
448 OSPF_TRACE(D_EVENTS
, "Starting routing table calculation for area %R", oa
->areaid
);
451 init_list(&oa
->cand
); /* Empty list of candidates */
454 DBG("LSA db prepared, adding me into candidate list.\n");
457 oa
->rt
->color
= CANDIDATE
;
458 add_head(&oa
->cand
, &oa
->rt
->cn
);
459 DBG("RT LSA: rt: %R, id: %R, type: %u\n",
460 oa
->rt
->lsa
.rt
, oa
->rt
->lsa
.id
, oa
->rt
->lsa
.type
);
462 while (!EMPTY_LIST(oa
->cand
))
465 act
= SKIP_BACK(struct top_hash_entry
, cn
, n
);
468 DBG("Working on LSA: rt: %R, id: %R, type: %u\n",
469 act
->lsa
.rt
, act
->lsa
.id
, act
->lsa
.type
);
472 switch (act
->lsa
.type
)
475 rt
= (struct ospf_lsa_rt
*) act
->lsa_body
;
476 if (rt
->options
& OPT_RT_V
)
480 * In OSPFv3, all routers are added to per-area routing
481 * tables. But we use it just for ASBRs and ABRs. For the
482 * purpose of the last step in SPF - prefix-LSA processing in
483 * process_prefixes(), we use information stored in LSA db.
485 if (((rt
->options
& OPT_RT_E
) || (rt
->options
& OPT_RT_B
))
486 && (act
->lsa
.rt
!= po
->router_id
))
490 .options
= rt
->options
,
491 .metric1
= act
->dist
,
492 .metric2
= LSINFINITY
,
498 ri_install_rt(oa
, act
->lsa
.rt
, &nf
);
502 ospf_rt_spfa_rtlinks(oa
, act
, act
);
504 /* Errata 2078 to RFC 5340 4.8.1 - skip links from non-routing nodes */
505 if ((act
!= oa
->rt
) && !(rt
->options
& OPT_R
))
508 for (tmp
= ospf_hash_find_rt_first(po
->gr
, act
->domain
, act
->lsa
.rt
);
509 tmp
; tmp
= ospf_hash_find_rt_next(tmp
))
510 ospf_rt_spfa_rtlinks(oa
, act
, tmp
);
518 prefix
= ipa_and(ipa_from_u32(act
->lsa
.id
), ln
->netmask
);
519 pxlen
= ipa_mklen(ln
->netmask
);
520 add_network(oa
, prefix
, pxlen
, act
->dist
, act
, -1);
523 rts
= (u32
*) (ln
+ 1);
524 for (i
= 0; i
< lsa_net_count(&act
->lsa
); i
++)
526 DBG(" Working on router %R ", rts
[i
]);
527 tmp
= ospf_hash_find_rt(po
->gr
, oa
->areaid
, rts
[i
]);
532 add_cand(&oa
->cand
, tmp
, act
, act
->dist
, oa
, -1);
539 process_prefixes(oa
);
544 link_back(struct ospf_area
*oa
, struct top_hash_entry
*en
, struct top_hash_entry
*par
)
547 struct ospf_lsa_net
*ln
;
548 struct ospf_lsa_rt
*rt
;
549 struct ospf_lsa_rt_link
*rtl
, *rr
;
550 struct top_hash_entry
*tmp
;
551 struct proto_ospf
*po
= oa
->po
;
553 if (!en
|| !par
) return 0;
555 /* We should check whether there is a link back from en to par,
556 this is used in SPF calc (RFC 2328 16.1. (2b)). According to RFC 2328
557 note 23, we don't have to find the same link that is used for par
558 to en, any link is enough. This we do for ptp links. For net-rt
559 links, we have to find the same link to compute proper lb/lb_id,
560 which may be later used as the next hop. */
562 /* In OSPFv2, en->lb is set here. In OSPFv3, en->lb is just cleared here,
563 it is set in process_prefixes() to any global addres in the area */
569 switch (en
->lsa
.type
)
572 rt
= (struct ospf_lsa_rt
*) en
->lsa_body
;
573 rr
= (struct ospf_lsa_rt_link
*) (rt
+ 1);
574 for (i
= 0; i
< lsa_rt_count(&en
->lsa
); i
++)
583 /* In OSPFv2, rtl->id is IP addres of DR, Router ID is not known */
584 tmp
= ospf_hash_find_net(po
->gr
, oa
->areaid
, rtl
->id
);
586 tmp
= ospf_hash_find(po
->gr
, oa
->areaid
, rtl
->nif
, rtl
->id
, LSA_T_NET
);
591 en
->lb
= ipa_from_u32(rtl
->data
);
593 en
->lb_id
= rtl
->lif
;
601 /* Not necessary the same link, see RFC 2328 [23] */
602 tmp
= ospf_hash_find_rt(po
->gr
, oa
->areaid
, rtl
->id
);
608 log(L_WARN
"Unknown link type in router lsa. (rid = %R)", en
->lsa
.rt
);
615 rts
= (u32
*) (ln
+ 1);
616 for (i
= 0; i
< lsa_net_count(&en
->lsa
); i
++)
618 tmp
= ospf_hash_find_rt(po
->gr
, oa
->areaid
, rts
[i
]);
624 bug("Unknown lsa type %x.", en
->lsa
.type
);
630 /* RFC 2328 16.2. calculating inter-area routes */
632 ospf_rt_sum(struct ospf_area
*oa
)
634 struct proto_ospf
*po
= oa
->po
;
635 struct proto
*p
= &po
->proto
;
636 struct top_hash_entry
*en
;
637 ip_addr ip
= IPA_NONE
;
641 int pxlen
= -1, type
= -1;
643 OSPF_TRACE(D_EVENTS
, "Starting routing table calculation for inter-area (area %R)", oa
->areaid
);
645 WALK_SLIST(en
, po
->lsal
)
647 if ((en
->lsa
.type
!= LSA_T_SUM_RT
) && (en
->lsa
.type
!= LSA_T_SUM_NET
))
650 if (en
->domain
!= oa
->areaid
)
654 if (en
->lsa
.age
== LSA_MAXAGE
)
658 if (en
->lsa
.rt
== po
->router_id
)
661 /* 16.2. (3) is handled later in ospf_rt_abr() by resetting such rt entry */
663 if (en
->lsa
.type
== LSA_T_SUM_NET
)
666 struct ospf_lsa_sum
*ls
= en
->lsa_body
;
667 ip
= ipa_and(ipa_from_u32(en
->lsa
.id
), ls
->netmask
);
668 pxlen
= ipa_mklen(ls
->netmask
);
672 struct ospf_lsa_sum_net
*ls
= en
->lsa_body
;
673 lsa_get_ipv6_prefix(ls
->prefix
, &ip
, &pxlen
, &pxopts
, &rest
);
675 if (pxopts
& OPT_PX_NU
)
679 if (pxlen
< 0 || pxlen
> MAX_PREFIX_LENGTH
)
681 log(L_WARN
"%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
682 p
->name
, en
->lsa
.type
, en
->lsa
.id
, en
->lsa
.rt
);
686 metric
= ls
->metric
& METRIC_MASK
;
690 else /* LSA_T_SUM_RT */
693 struct ospf_lsa_sum
*ls
= en
->lsa_body
;
694 dst_rid
= en
->lsa
.id
;
697 struct ospf_lsa_sum_rt
*ls
= en
->lsa_body
;
699 options
= ls
->options
& OPTIONS_MASK
;
702 /* We don't want local router in ASBR routing table */
703 if (dst_rid
== po
->router_id
)
706 metric
= ls
->metric
& METRIC_MASK
;
707 options
|= ORTA_ASBR
;
712 if (metric
== LSINFINITY
)
716 ip_addr abrip
= ipa_from_rid(en
->lsa
.rt
);
717 abr
= (ort
*) fib_find(&oa
->rtr
, &abrip
, MAX_PREFIX_LENGTH
);
718 if (!abr
|| !abr
->n
.type
)
721 if (!(abr
->n
.options
& ORTA_ABR
))
724 /* This check is not mentioned in RFC 2328 */
725 if (abr
->n
.type
!= RTS_OSPF
)
732 .metric1
= abr
->n
.metric1
+ metric
,
733 .metric2
= LSINFINITY
,
735 .rid
= en
->lsa
.rt
, /* ABR ID */
741 ri_install_net(po
, ip
, pxlen
, &nf
);
743 ri_install_rt(oa
, dst_rid
, &nf
);
747 /* RFC 2328 16.3. examining summary-LSAs in transit areas */
749 ospf_rt_sum_tr(struct ospf_area
*oa
)
751 struct proto
*p
= &oa
->po
->proto
;
752 struct proto_ospf
*po
= oa
->po
;
753 struct ospf_area
*bb
= po
->backbone
;
755 struct top_hash_entry
*en
;
757 ort
*re
= NULL
, *abr
;
762 WALK_SLIST(en
, po
->lsal
)
764 if ((en
->lsa
.type
!= LSA_T_SUM_RT
) && (en
->lsa
.type
!= LSA_T_SUM_NET
))
767 if (en
->domain
!= oa
->areaid
)
771 if (en
->lsa
.age
== LSA_MAXAGE
)
775 if (en
->lsa
.rt
== po
->router_id
)
778 if (en
->lsa
.type
== LSA_T_SUM_NET
)
783 struct ospf_lsa_sum
*ls
= en
->lsa_body
;
784 ip
= ipa_and(ipa_from_u32(en
->lsa
.id
), ls
->netmask
);
785 pxlen
= ipa_mklen(ls
->netmask
);
789 struct ospf_lsa_sum_net
*ls
= en
->lsa_body
;
790 lsa_get_ipv6_prefix(ls
->prefix
, &ip
, &pxlen
, &pxopts
, &rest
);
792 if (pxopts
& OPT_PX_NU
)
796 if (pxlen
< 0 || pxlen
> MAX_PREFIX_LENGTH
)
798 log(L_WARN
"%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
799 p
->name
, en
->lsa
.type
, en
->lsa
.id
, en
->lsa
.rt
);
803 metric
= ls
->metric
& METRIC_MASK
;
804 re
= fib_find(&po
->rtf
, &ip
, pxlen
);
806 else // en->lsa.type == LSA_T_SUM_RT
809 struct ospf_lsa_sum
*ls
= en
->lsa_body
;
810 dst_rid
= en
->lsa
.id
;
812 struct ospf_lsa_sum_rt
*ls
= en
->lsa_body
;
816 metric
= ls
->metric
& METRIC_MASK
;
817 ip_addr ip
= ipa_from_rid(dst_rid
);
818 re
= fib_find(&bb
->rtr
, &ip
, MAX_PREFIX_LENGTH
);
822 if (metric
== LSINFINITY
)
826 if (!re
|| !re
->n
.type
)
829 if (re
->n
.oa
->areaid
!= 0)
832 if ((re
->n
.type
!= RTS_OSPF
) && (re
->n
.type
!= RTS_OSPF_IA
))
836 abrip
= ipa_from_rid(en
->lsa
.rt
);
837 abr
= fib_find(&oa
->rtr
, &abrip
, MAX_PREFIX_LENGTH
);
838 if (!abr
|| !abr
->n
.type
)
841 metric
= abr
->n
.metric1
+ metric
; /* IAC */
844 if ((metric
< re
->n
.metric1
) ||
845 ((metric
== re
->n
.metric1
) && unresolved_vlink(re
->n
.nhs
)))
847 /* We want to replace the next-hop even if the metric is equal
848 to replace a virtual next-hop through vlink with a real one.
849 Proper ECMP would merge nexthops here, but we do not do that.
850 We restrict nexthops to fit one area to simplify check
851 12.4.3 p4 in decide_sum_lsa() */
853 re
->n
.metric1
= metric
;
855 re
->n
.nhs
= abr
->n
.nhs
;
860 /* Decide about originating or flushing summary LSAs for condended area networks */
862 decide_anet_lsa(struct ospf_area
*oa
, struct area_net
*anet
, struct ospf_area
*anet_oa
)
864 /* 12.4.3.1. - for stub/NSSA areas, originating summary routes is configurable */
865 if (!oa_is_ext(oa
) && !oa
->ac
->summary
)
871 /* Do not condense routing info when exporting from backbone to the transit area */
872 if ((anet_oa
== oa
->po
->backbone
) && oa
->trcap
)
875 return (anet
->active
&& !anet
->hidden
);
878 /* Decide about originating or flushing summary LSAs (12.4.3) */
880 decide_sum_lsa(struct ospf_area
*oa
, ort
*nf
, int dest
)
882 /* 12.4.3.1. - for stub/NSSA areas, originating summary routes is configurable */
883 if (!oa_is_ext(oa
) && !oa
->ac
->summary
)
886 /* Invalid field - no route */
891 if (nf
->n
.type
> RTS_OSPF_IA
)
895 if ((nf
->n
.oa
->areaid
== oa
->areaid
))
899 if (nf
->n
.voa
&& (nf
->n
.voa
->areaid
== oa
->areaid
))
903 if (nf
->n
.metric1
>= LSINFINITY
)
906 /* 12.4.3 p6 - AS boundary router */
907 if (dest
== ORT_ROUTER
)
909 /* We call decide_sum_lsa() on preferred ASBR entries, no need for 16.4. (3) */
911 return oa_is_ext(oa
) && (nf
->n
.options
& ORTA_ASBR
);
914 /* 12.4.3 p7 - inter-area route */
915 if (nf
->n
.type
== RTS_OSPF_IA
)
917 /* Inter-area routes are not repropagated into the backbone */
918 return (oa
!= oa
->po
->backbone
);
921 /* 12.4.3 p8 - intra-area route */
923 /* Do not condense routing info when exporting from backbone to the transit area */
924 if ((nf
->n
.oa
== oa
->po
->backbone
) && oa
->trcap
)
927 struct area_net
*anet
= (struct area_net
*)
928 fib_route(&nf
->n
.oa
->net_fib
, nf
->fn
.prefix
, nf
->fn
.pxlen
);
930 /* Condensed area network found */
937 /* RFC 2328 16.7. p1 - originate or flush summary LSAs */
939 check_sum_net_lsa(struct proto_ospf
*po
, ort
*nf
)
941 struct area_net
*anet
= NULL
;
942 struct ospf_area
*anet_oa
= NULL
;
944 /* RT entry marked as area network */
947 /* It is a default route for stub areas, handled entirely in ospf_rt_abr() */
948 if (nf
->fn
.pxlen
== 0)
951 /* Find that area network */
952 WALK_LIST(anet_oa
, po
->area_list
)
954 anet
= (struct area_net
*) fib_find(&anet_oa
->net_fib
, &nf
->fn
.prefix
, nf
->fn
.pxlen
);
960 struct ospf_area
*oa
;
961 WALK_LIST(oa
, po
->area_list
)
963 if (anet
&& decide_anet_lsa(oa
, anet
, anet_oa
))
964 originate_sum_net_lsa(oa
, &nf
->fn
, anet
->metric
);
965 else if (decide_sum_lsa(oa
, nf
, ORT_NET
))
966 originate_sum_net_lsa(oa
, &nf
->fn
, nf
->n
.metric1
);
968 flush_sum_lsa(oa
, &nf
->fn
, ORT_NET
);
973 check_sum_rt_lsa(struct proto_ospf
*po
, ort
*nf
)
975 struct ospf_area
*oa
;
976 WALK_LIST(oa
, po
->area_list
)
978 if (decide_sum_lsa(oa
, nf
, ORT_ROUTER
))
979 originate_sum_rt_lsa(oa
, &nf
->fn
, nf
->n
.metric1
, nf
->n
.options
);
981 flush_sum_lsa(oa
, &nf
->fn
, ORT_ROUTER
);
986 decide_nssa_lsa(ort
*nf
, u32
*rt_metric
, ip_addr
*rt_fwaddr
, u32
*rt_tag
)
988 struct ospf_area
*oa
= nf
->n
.oa
;
989 struct top_hash_entry
*en
= nf
->n
.en
;
992 if (!rt_is_nssa(nf
) || !oa
->translate
)
995 /* Condensed area network found */
996 if (fib_route(&oa
->enet_fib
, nf
->fn
.prefix
, nf
->fn
.pxlen
))
999 if (!en
|| (en
->lsa
.type
!= LSA_T_NSSA
))
1002 /* We do not store needed data in struct orta, we have to parse the LSA */
1003 struct ospf_lsa_ext
*le
= en
->lsa_body
;
1006 *rt_fwaddr
= le
->fwaddr
;
1008 propagate
= en
->lsa
.options
& OPT_P
;
1010 u32
*buf
= le
->rest
;
1011 u8 pxlen
= (*buf
>> 24);
1012 u8 pxopts
= (*buf
>> 16);
1013 buf
+= IPV6_PREFIX_WORDS(pxlen
); /* Skip the IP prefix */
1015 if (pxopts
& OPT_PX_NU
)
1018 if (le
->metric
& LSA_EXT_FBIT
)
1019 buf
= lsa_get_ipv6_addr(buf
, rt_fwaddr
);
1021 *rt_fwaddr
= IPA_NONE
;
1023 if (le
->metric
& LSA_EXT_TBIT
)
1028 propagate
= pxopts
& OPT_PX_P
;
1031 if (!propagate
|| ipa_zero(*rt_fwaddr
))
1034 *rt_metric
= le
->metric
& (METRIC_MASK
| LSA_EXT_EBIT
);
1038 /* RFC 3103 3.2 - translating Type-7 LSAs into Type-5 LSAs */
1040 check_nssa_lsa(struct proto_ospf
*po
, ort
*nf
)
1042 struct fib_node
*fn
= &nf
->fn
;
1043 struct area_net
*anet
= NULL
;
1044 struct ospf_area
*oa
= NULL
;
1045 u32 rt_metric
, rt_tag
;
1048 /* Do not translate LSA if there is already the external LSA from route export */
1049 if (fn
->x1
== EXT_EXPORT
)
1052 /* RT entry marked as area network */
1055 /* Find that area network */
1056 WALK_LIST(oa
, po
->area_list
)
1058 anet
= (struct area_net
*) fib_find(&oa
->enet_fib
, &fn
->prefix
, fn
->pxlen
);
1064 /* RFC 3103 3.2 (3) - originate the aggregated address range */
1065 if (anet
&& anet
->active
&& !anet
->hidden
&& oa
->translate
)
1066 originate_ext_lsa(po
->backbone
, fn
, EXT_NSSA
, anet
->metric
, IPA_NONE
, anet
->tag
, 0);
1068 /* RFC 3103 3.2 (2) - originate the same network */
1069 else if (decide_nssa_lsa(nf
, &rt_metric
, &rt_fwaddr
, &rt_tag
))
1070 originate_ext_lsa(po
->backbone
, fn
, EXT_NSSA
, rt_metric
, rt_fwaddr
, rt_tag
, 0);
1072 else if (fn
->x1
== EXT_NSSA
)
1073 flush_ext_lsa(po
->backbone
, fn
, 0);
1076 /* RFC 2328 16.7. p2 - find new/lost vlink endpoints */
1078 ospf_check_vlinks(struct proto_ospf
*po
)
1080 struct proto
*p
= &po
->proto
;
1082 struct ospf_iface
*iface
;
1083 WALK_LIST(iface
, po
->iface_list
)
1085 if (iface
->type
== OSPF_IT_VLINK
)
1087 struct top_hash_entry
*tmp
;
1088 tmp
= ospf_hash_find_rt(po
->gr
, iface
->voa
->areaid
, iface
->vid
);
1090 if (tmp
&& (tmp
->color
== INSPF
) && ipa_nonzero(tmp
->lb
) && tmp
->nhs
)
1092 struct ospf_iface
*nhi
= ospf_iface_find(po
, tmp
->nhs
->iface
);
1094 if ((iface
->state
!= OSPF_IS_PTP
)
1095 || (iface
->vifa
!= nhi
)
1096 || !ipa_equal(iface
->vip
, tmp
->lb
))
1098 OSPF_TRACE(D_EVENTS
, "Vlink peer %R found", tmp
->lsa
.id
);
1099 ospf_iface_sm(iface
, ISM_DOWN
);
1101 iface
->iface
= nhi
->iface
;
1102 iface
->addr
= nhi
->addr
;
1103 iface
->sk
= nhi
->sk
;
1104 iface
->cost
= tmp
->dist
;
1105 iface
->vip
= tmp
->lb
;
1106 ospf_iface_sm(iface
, ISM_UP
);
1108 else if ((iface
->state
== OSPF_IS_PTP
) && (iface
->cost
!= tmp
->dist
))
1110 iface
->cost
= tmp
->dist
;
1111 schedule_rt_lsa(po
->backbone
);
1116 if (iface
->state
> OSPF_IS_DOWN
)
1118 OSPF_TRACE(D_EVENTS
, "Vlink peer %R lost", iface
->vid
);
1119 ospf_iface_sm(iface
, ISM_DOWN
);
1127 /* Miscellaneous route processing that needs to be done by ABRs */
1129 ospf_rt_abr1(struct proto_ospf
*po
)
1131 struct area_net
*anet
;
1132 ort
*nf
, *default_nf
;
1134 FIB_WALK(&po
->rtf
, nftmp
)
1139 /* RFC 2328 G.3 - incomplete resolution of virtual next hops */
1140 if (nf
->n
.type
&& unresolved_vlink(nf
->n
.nhs
))
1144 /* Compute condensed area networks */
1145 if (nf
->n
.type
== RTS_OSPF
)
1147 anet
= (struct area_net
*) fib_route(&nf
->n
.oa
->net_fib
, nf
->fn
.prefix
, nf
->fn
.pxlen
);
1154 /* Get a RT entry and mark it to know that it is an area network */
1155 ort
*nfi
= (ort
*) fib_get(&po
->rtf
, &anet
->fn
.prefix
, anet
->fn
.pxlen
);
1156 nfi
->fn
.x0
= 1; /* mark and keep persistent, to have stable UID */
1159 if (nfi
->n
.type
== RTS_OSPF_IA
)
1163 if (anet
->metric
< nf
->n
.metric1
)
1164 anet
->metric
= nf
->n
.metric1
;
1170 ip_addr addr
= IPA_NONE
;
1171 default_nf
= (ort
*) fib_get(&po
->rtf
, &addr
, 0);
1172 default_nf
->fn
.x0
= 1; /* keep persistent */
1174 struct ospf_area
*oa
;
1175 WALK_LIST(oa
, po
->area_list
)
1178 /* 12.4.3.1. - originate or flush default route for stub/NSSA areas */
1179 if (oa_is_stub(oa
) || (oa_is_nssa(oa
) && !oa
->ac
->summary
))
1180 originate_sum_net_lsa(oa
, &default_nf
->fn
, oa
->ac
->default_cost
);
1182 flush_sum_lsa(oa
, &default_nf
->fn
, ORT_NET
);
1185 * Originate type-7 default route for NSSA areas
1187 * Because type-7 default LSAs are originated by ABRs, they do not
1188 * collide with other type-7 LSAs (as ABRs generate type-5 LSAs
1189 * for both external route export or external-NSSA translation),
1190 * so we use 0 for the src arg.
1193 if (oa_is_nssa(oa
) && oa
->ac
->default_nssa
)
1194 originate_ext_lsa(oa
, &default_nf
->fn
, 0, oa
->ac
->default_cost
, IPA_NONE
, 0, 0);
1196 flush_ext_lsa(oa
, &default_nf
->fn
, 1);
1199 /* RFC 2328 16.4. (3) - precompute preferred ASBR entries */
1202 FIB_WALK(&oa
->rtr
, nftmp
)
1205 if (nf
->n
.options
& ORTA_ASBR
)
1206 ri_install_asbr(po
, &nf
->fn
.prefix
, &nf
->n
);
1213 /* Originate or flush ASBR summary LSAs */
1214 FIB_WALK(&po
->backbone
->rtr
, nftmp
)
1216 check_sum_rt_lsa(po
, (ort
*) nftmp
);
1221 /* RFC 2328 16.7. p2 - find new/lost vlink endpoints */
1222 ospf_check_vlinks(po
);
1227 translator_timer_hook(timer
*timer
)
1229 struct ospf_area
*oa
= timer
->data
;
1231 if (oa
->translate
!= TRANS_WAIT
)
1234 oa
->translate
= TRANS_OFF
;
1235 schedule_rtcalc(oa
->po
);
1239 ospf_rt_abr2(struct proto_ospf
*po
)
1241 struct ospf_area
*oa
;
1242 struct top_hash_entry
*en
;
1246 /* RFC 3103 3.1 - type-7 translator election */
1247 struct ospf_area
*bb
= po
->backbone
;
1248 WALK_LIST(oa
, po
->area_list
)
1253 if (oa
->ac
->translator
)
1256 FIB_WALK(&oa
->rtr
, nftmp
)
1259 if (!nf
->n
.type
|| !(nf
->n
.options
& ORTA_ABR
))
1262 nf2
= fib_find(&bb
->rtr
, &nf
->fn
.prefix
, MAX_PREFIX_LENGTH
);
1263 if (!nf2
|| !nf2
->n
.type
|| !(nf2
->n
.options
& ORTA_ABR
))
1266 en
= ospf_hash_find_rt(po
->gr
, oa
->areaid
, nf
->n
.rid
);
1267 if (!en
|| (en
->color
!= INSPF
))
1270 struct ospf_lsa_rt
*rt
= en
->lsa_body
;
1271 /* There is better candidate - Nt-bit or higher Router ID */
1272 if ((rt
->options
& OPT_RT_NT
) || (po
->router_id
< nf
->n
.rid
))
1281 if (translate
&& (oa
->translate
!= TRANS_ON
))
1283 if (oa
->translate
== TRANS_WAIT
)
1284 tm_stop(oa
->translator_timer
);
1286 oa
->translate
= TRANS_ON
;
1289 if (!translate
&& (oa
->translate
== TRANS_ON
))
1291 if (oa
->translator_timer
== NULL
)
1292 oa
->translator_timer
= tm_new_set(po
->proto
.pool
, translator_timer_hook
, oa
, 0, 0);
1294 /* Schedule the end of translation */
1295 tm_start(oa
->translator_timer
, oa
->ac
->transint
);
1296 oa
->translate
= TRANS_WAIT
;
1301 /* Compute condensed external networks */
1302 FIB_WALK(&po
->rtf
, nftmp
)
1305 if (rt_is_nssa(nf
) && (nf
->n
.options
& ORTA_PROP
))
1307 struct area_net
*anet
= (struct area_net
*)
1308 fib_route(&nf
->n
.oa
->enet_fib
, nf
->fn
.prefix
, nf
->fn
.pxlen
);
1316 /* Get a RT entry and mark it to know that it is an area network */
1317 nf2
= (ort
*) fib_get(&po
->rtf
, &anet
->fn
.prefix
, anet
->fn
.pxlen
);
1321 u32 metric
= (nf
->n
.type
== RTS_OSPF_EXT1
) ?
1322 nf
->n
.metric1
: ((nf
->n
.metric2
+ 1) | LSA_EXT_EBIT
);
1324 if (anet
->metric
< metric
)
1325 anet
->metric
= metric
;
1332 FIB_WALK(&po
->rtf
, nftmp
)
1336 check_sum_net_lsa(po
, nf
);
1337 check_nssa_lsa(po
, nf
);
1343 /* Like fib_route(), but ignores dummy rt entries */
1345 ospf_fib_route(struct fib
*f
, ip_addr a
, int len
)
1352 a0
= ipa_and(a
, ipa_mkmask(len
));
1353 nf
= fib_find(f
, &a0
, len
);
1354 if (nf
&& nf
->n
.type
)
1361 /* RFC 2328 16.4. calculating external routes */
1363 ospf_ext_spf(struct proto_ospf
*po
)
1367 struct top_hash_entry
*en
;
1368 struct proto
*p
= &po
->proto
;
1369 struct ospf_lsa_ext
*le
;
1370 int pxlen
, ebit
, rt_fwaddr_valid
, rt_propagate
;
1371 ip_addr ip
, rtid
, rt_fwaddr
;
1372 u32 br_metric
, rt_metric
, rt_tag
;
1373 struct ospf_area
*atmp
;
1374 struct mpnh
* nhs
= NULL
;
1376 OSPF_TRACE(D_EVENTS
, "Starting routing table calculation for ext routes");
1378 WALK_SLIST(en
, po
->lsal
)
1381 if ((en
->lsa
.type
!= LSA_T_EXT
) && (en
->lsa
.type
!= LSA_T_NSSA
))
1384 if (en
->lsa
.age
== LSA_MAXAGE
)
1388 if (en
->lsa
.rt
== po
->router_id
)
1391 DBG("%s: Working on LSA. ID: %R, RT: %R, Type: %u\n",
1392 p
->name
, en
->lsa
.id
, en
->lsa
.rt
, en
->lsa
.type
);
1396 rt_metric
= le
->metric
& METRIC_MASK
;
1397 ebit
= le
->metric
& LSA_EXT_EBIT
;
1399 if (rt_metric
== LSINFINITY
)
1403 ip
= ipa_and(ipa_from_u32(en
->lsa
.id
), le
->netmask
);
1404 pxlen
= ipa_mklen(le
->netmask
);
1405 rt_fwaddr
= le
->fwaddr
;
1406 rt_fwaddr_valid
= !ipa_equal(rt_fwaddr
, IPA_NONE
);
1408 rt_propagate
= en
->lsa
.options
& OPT_P
;
1412 u32
*buf
= le
->rest
;
1413 buf
= lsa_get_ipv6_prefix(buf
, &ip
, &pxlen
, &pxopts
, &rest
);
1415 if (pxopts
& OPT_PX_NU
)
1418 rt_fwaddr_valid
= le
->metric
& LSA_EXT_FBIT
;
1419 if (rt_fwaddr_valid
)
1420 buf
= lsa_get_ipv6_addr(buf
, &rt_fwaddr
);
1422 rt_fwaddr
= IPA_NONE
;
1424 if (le
->metric
& LSA_EXT_TBIT
)
1429 rt_propagate
= pxopts
& OPT_PX_P
;
1432 if (pxlen
< 0 || pxlen
> MAX_PREFIX_LENGTH
)
1434 log(L_WARN
"%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
1435 p
->name
, en
->lsa
.type
, en
->lsa
.id
, en
->lsa
.rt
);
1441 /* If there are more areas, we already precomputed preferred ASBR
1442 entries in ospf_rt_abr1() and stored them in the backbone
1443 table. For NSSA, we examine the area to which the LSA is assigned */
1444 if (en
->lsa
.type
== LSA_T_EXT
)
1445 atmp
= ospf_main_area(po
);
1447 atmp
= ospf_find_area(po
, en
->domain
);
1450 continue; /* Should not happen */
1452 rtid
= ipa_from_rid(en
->lsa
.rt
);
1453 nf1
= fib_find(&atmp
->rtr
, &rtid
, MAX_PREFIX_LENGTH
);
1455 if (!nf1
|| !nf1
->n
.type
)
1456 continue; /* No AS boundary router found */
1458 if (!(nf1
->n
.options
& ORTA_ASBR
))
1459 continue; /* It is not ASBR */
1461 /* 16.4. (3) NSSA - special rule for default routes */
1462 /* ABR should use default only if P-bit is set and summaries are active */
1463 if ((en
->lsa
.type
== LSA_T_NSSA
) && ipa_zero(ip
) && (pxlen
== 0) &&
1464 (po
->areano
> 1) && !(rt_propagate
&& atmp
->ac
->summary
))
1467 if (!rt_fwaddr_valid
)
1471 br_metric
= nf1
->n
.metric1
;
1475 nf2
= ospf_fib_route(&po
->rtf
, rt_fwaddr
, MAX_PREFIX_LENGTH
);
1479 if (en
->lsa
.type
== LSA_T_EXT
)
1481 /* For ext routes, we accept intra-area or inter-area routes */
1482 if ((nf2
->n
.type
!= RTS_OSPF
) && (nf2
->n
.type
!= RTS_OSPF_IA
))
1487 /* For NSSA routes, we accept just intra-area in the same area */
1488 if ((nf2
->n
.type
!= RTS_OSPF
) || (nf2
->n
.oa
!= atmp
))
1492 /* Next-hop is a part of a configured stubnet */
1497 /* If gw is zero, it is a device route */
1498 if (ipa_zero(nhs
->gw
))
1499 nhs
= new_nexthop(po
, rt_fwaddr
, nhs
->iface
, nhs
->weight
);
1500 br_metric
= nf2
->n
.metric1
;
1505 nfa
.type
= RTS_OSPF_EXT2
;
1506 nfa
.metric1
= br_metric
;
1507 nfa
.metric2
= rt_metric
;
1511 nfa
.type
= RTS_OSPF_EXT1
;
1512 nfa
.metric1
= br_metric
+ rt_metric
;
1513 nfa
.metric2
= LSINFINITY
;
1516 /* Mark the LSA as reachable */
1519 /* Whether the route is preferred in route selection according to 16.4.1 */
1520 nfa
.options
= epath_preferred(&nf2
->n
) ? ORTA_PREF
: 0;
1521 if (en
->lsa
.type
== LSA_T_NSSA
)
1523 nfa
.options
|= ORTA_NSSA
;
1525 nfa
.options
|= ORTA_PROP
;
1529 nfa
.rid
= en
->lsa
.rt
;
1530 nfa
.oa
= atmp
; /* undefined in RFC 2328 */
1533 nfa
.en
= en
; /* store LSA for later (NSSA processing) */
1535 ri_install_ext(po
, ip
, pxlen
, &nfa
);
1539 /* Cleanup of routing tables and data */
1541 ospf_rt_reset(struct proto_ospf
*po
)
1543 struct ospf_area
*oa
;
1544 struct top_hash_entry
*en
;
1545 struct area_net
*anet
;
1548 /* Reset old routing table */
1549 FIB_WALK(&po
->rtf
, nftmp
)
1557 /* Reset SPF data in LSA db */
1558 WALK_SLIST(en
, po
->lsal
)
1561 en
->dist
= LSINFINITY
;
1566 WALK_LIST(oa
, po
->area_list
)
1568 /* Reset ASBR routing tables */
1569 FIB_WALK(&oa
->rtr
, nftmp
)
1576 /* Reset condensed area networks */
1579 FIB_WALK(&oa
->net_fib
, nftmp
)
1581 anet
= (struct area_net
*) nftmp
;
1587 FIB_WALK(&oa
->enet_fib
, nftmp
)
1589 anet
= (struct area_net
*) nftmp
;
1599 * ospf_rt_spf - calculate internal routes
1600 * @po: OSPF protocol
1602 * Calculation of internal paths in an area is described in 16.1 of RFC 2328.
1603 * It's based on Dijkstra's shortest path tree algorithms.
1604 * This function is invoked from ospf_disp().
1607 ospf_rt_spf(struct proto_ospf
*po
)
1609 struct proto
*p
= &po
->proto
;
1610 struct ospf_area
*oa
;
1612 if (po
->areano
== 0)
1615 OSPF_TRACE(D_EVENTS
, "Starting routing table calculation");
1621 WALK_LIST(oa
, po
->area_list
)
1625 ospf_rt_sum(ospf_main_area(po
));
1628 WALK_LIST(oa
, po
->area_list
)
1629 if (oa
->trcap
&& (oa
->areaid
!= 0))
1642 lp_flush(po
->nhpool
);
1649 inherit_nexthops(struct mpnh
*pn
)
1651 /* Proper nexthops (with defined GW) or dummy vlink nexthops (without iface) */
1652 return pn
&& (ipa_nonzero(pn
->gw
) || !pn
->iface
);
1655 static struct mpnh
*
1656 calc_next_hop(struct ospf_area
*oa
, struct top_hash_entry
*en
,
1657 struct top_hash_entry
*par
, int pos
)
1659 // struct proto *p = &oa->po->proto;
1660 struct proto_ospf
*po
= oa
->po
;
1661 struct mpnh
*pn
= par
->nhs
;
1662 struct ospf_iface
*ifa
;
1663 u32 rid
= en
->lsa
.rt
;
1665 /* 16.1.1. The next hop calculation */
1666 DBG(" Next hop calculating for id: %R rt: %R type: %u\n",
1667 en
->lsa
.id
, en
->lsa
.rt
, en
->lsa
.type
);
1669 /* Usually, we inherit parent nexthops */
1670 if (inherit_nexthops(pn
))
1674 * There are three cases:
1675 * 1) en is a local network (and par is root)
1676 * 2) en is a ptp or ptmp neighbor (and par is root)
1677 * 3) en is a bcast or nbma neighbor (and par is local network)
1680 /* The first case - local network */
1681 if ((en
->lsa
.type
== LSA_T_NET
) && (par
== oa
->rt
))
1683 ifa
= rt_pos_to_ifa(oa
, pos
);
1687 return new_nexthop(po
, IPA_NONE
, ifa
->iface
, ifa
->ecmp_weight
);
1690 /* The second case - ptp or ptmp neighbor */
1691 if ((en
->lsa
.type
== LSA_T_RT
) && (par
== oa
->rt
))
1693 ifa
= rt_pos_to_ifa(oa
, pos
);
1697 if (ifa
->type
== OSPF_IT_VLINK
)
1698 return new_nexthop(po
, IPA_NONE
, NULL
, 0);
1700 struct ospf_neighbor
*m
= find_neigh(ifa
, rid
);
1701 if (!m
|| (m
->state
!= NEIGHBOR_FULL
))
1704 return new_nexthop(po
, m
->ip
, ifa
->iface
, ifa
->ecmp_weight
);
1707 /* The third case - bcast or nbma neighbor */
1708 if ((en
->lsa
.type
== LSA_T_RT
) && (par
->lsa
.type
== LSA_T_NET
))
1710 /* par->nhi should be defined from parent's calc_next_hop() */
1716 * In this case, next-hop is the same as link-back, which is
1717 * already computed in link_back().
1719 if (ipa_zero(en
->lb
))
1722 return new_nexthop(po
, en
->lb
, pn
->iface
, pn
->weight
);
1726 * Next-hop is taken from lladdr field of Link-LSA, en->lb_id
1727 * is computed in link_back().
1729 struct top_hash_entry
*lhe
;
1730 lhe
= ospf_hash_find(po
->gr
, pn
->iface
->index
, en
->lb_id
, rid
, LSA_T_LINK
);
1735 struct ospf_lsa_link
*llsa
= lhe
->lsa_body
;
1737 if (ipa_zero(llsa
->lladdr
))
1740 return new_nexthop(po
, llsa
->lladdr
, pn
->iface
, pn
->weight
);
1745 /* Probably bug or some race condition, we log it */
1746 log(L_ERR
"Unexpected case in next hop calculation");
1750 /* Compare nexthops during merge.
1751 We need to maintain nhs sorted to eliminate duplicities */
1753 cmp_nhs(struct mpnh
*s1
, struct mpnh
*s2
)
1763 r
= ((int) s2
->weight
) - ((int) s1
->weight
);
1767 r
= ipa_compare(s1
->gw
, s2
->gw
);
1771 return ((int) s1
->iface
->index
) - ((int) s2
->iface
->index
);
1775 merge_nexthops(struct proto_ospf
*po
, struct top_hash_entry
*en
,
1776 struct top_hash_entry
*par
, struct mpnh
*new)
1781 int r1
= en
->nhs_reuse
;
1782 int r2
= (par
->nhs
!= new);
1783 int count
= po
->ecmp
;
1784 struct mpnh
*s1
= en
->nhs
;
1785 struct mpnh
*s2
= new;
1786 struct mpnh
**n
= &(en
->nhs
);
1789 * r1, r2 signalize whether we can reuse nexthops from s1, s2.
1790 * New nexthops (s2, new) can be reused if they are not inherited
1791 * from the parent (i.e. it is allocated in calc_next_hop()).
1792 * Current nexthops (s1, en->nhs) can be reused if they weren't
1793 * inherited in previous steps (that is stored in nhs_reuse,
1794 * i.e. created by merging or allocalted in calc_next_hop()).
1796 * Generally, a node first inherits shared nexthops from its
1797 * parent and later possibly gets reusable copy during merging.
1800 while ((s1
|| s2
) && count
--)
1802 int cmp
= cmp_nhs(s1
, s2
);
1805 *n
= r1
? s1
: copy_nexthop(po
, s1
);
1810 *n
= r2
? s2
: copy_nexthop(po
, s2
);
1815 *n
= r1
? s1
: (r2
? s2
: copy_nexthop(po
, s1
));
1826 /* Add LSA into list of candidates in Dijkstra's algorithm */
1828 add_cand(list
* l
, struct top_hash_entry
*en
, struct top_hash_entry
*par
,
1829 u32 dist
, struct ospf_area
*oa
, int pos
)
1831 struct proto_ospf
*po
= oa
->po
;
1834 struct top_hash_entry
*act
;
1839 if (en
->lsa
.age
== LSA_MAXAGE
)
1843 if (en
->lsa
.type
== LSA_T_RT
)
1845 struct ospf_lsa_rt
*rt
= en
->lsa_body
;
1846 if (!(rt
->options
& OPT_V6
))
1852 if (en
->color
== INSPF
)
1855 /* 16.1. (2d), also checks that dist < LSINFINITY */
1856 if (dist
> en
->dist
)
1859 /* We should check whether there is a reverse link from en to par, */
1860 if (!link_back(oa
, en
, par
))
1863 struct mpnh
*nhs
= calc_next_hop(oa
, en
, par
, pos
);
1866 log(L_WARN
"Cannot find next hop for LSA (Type: %04x, Id: %R, Rt: %R)",
1867 en
->lsa
.type
, en
->lsa
.id
, en
->lsa
.rt
);
1871 if (dist
== en
->dist
)
1874 * For multipath, we should merge nexthops. We do not mix dummy
1875 * vlink nexthops, device nexthops and gateway nexthops. We merge
1876 * gateway nexthops only. We prefer device nexthops over gateway
1877 * nexthops and gateway nexthops over vlink nexthops. We either
1878 * keep old nexthops, merge old and new, or replace old with new.
1880 * We know that en->color == CANDIDATE and en->nhs is defined.
1882 struct mpnh
*onhs
= en
->nhs
;
1885 if (!po
->ecmp
|| !nhs
->iface
|| (onhs
->iface
&& ipa_zero(onhs
->gw
)))
1888 /* Merge old and new */
1889 if (ipa_nonzero(nhs
->gw
) && ipa_nonzero(onhs
->gw
))
1891 merge_nexthops(po
, en
, par
, nhs
);
1895 /* Fallback to replace old ones */
1898 DBG(" Adding candidate: rt: %R, id: %R, type: %u\n",
1899 en
->lsa
.rt
, en
->lsa
.id
, en
->lsa
.type
);
1901 if (en
->color
== CANDIDATE
)
1902 { /* We found a shorter path */
1907 en
->color
= CANDIDATE
;
1908 en
->nhs_reuse
= (par
->nhs
!= nhs
);
1914 add_head(l
, &en
->cn
);
1920 act
= SKIP_BACK(struct top_hash_entry
, cn
, n
);
1921 if ((act
->dist
> dist
) ||
1922 ((act
->dist
== dist
) && (act
->lsa
.type
== LSA_T_RT
)))
1925 add_head(l
, &en
->cn
);
1927 insert_node(&en
->cn
, prev
);
1936 add_tail(l
, &en
->cn
);
1942 ort_changed(ort
*nf
, rta
*nr
)
1944 rta
*or = nf
->old_rta
;
1946 (nf
->n
.metric1
!= nf
->old_metric1
) || (nf
->n
.metric2
!= nf
->old_metric2
) ||
1947 (nf
->n
.tag
!= nf
->old_tag
) || (nf
->n
.rid
!= nf
->old_rid
) ||
1948 (nr
->source
!= or->source
) || (nr
->dest
!= or->dest
) ||
1949 (nr
->iface
!= or->iface
) || !ipa_equal(nr
->gw
, or->gw
) ||
1950 !mpnh_same(nr
->nexthops
, or->nexthops
);
1954 rt_sync(struct proto_ospf
*po
)
1956 struct proto
*p
= &po
->proto
;
1957 struct fib_iterator fit
;
1958 struct fib
*fib
= &po
->rtf
;
1960 struct ospf_area
*oa
;
1962 /* This is used for forced reload of routes */
1963 int reload
= (po
->calcrt
== 2);
1965 OSPF_TRACE(D_EVENTS
, "Starting routing table synchronisation");
1967 DBG("Now syncing my rt table with nest's\n");
1968 FIB_ITERATE_INIT(&fit
, fib
);
1970 FIB_ITERATE_START(fib
, &fit
, nftmp
)
1974 /* Sanity check of next-hop addresses, failure should not happen */
1978 for (nh
= nf
->n
.nhs
; nh
; nh
= nh
->next
)
1979 if (ipa_nonzero(nh
->gw
))
1981 neighbor
*ng
= neigh_find2(p
, &nh
->gw
, nh
->iface
, 0);
1982 if (!ng
|| (ng
->scope
== SCOPE_HOST
))
1983 { reset_ri(nf
); break; }
1987 /* Remove configured stubnets */
1991 if (nf
->n
.type
) /* Add the route */
1995 .source
= nf
->n
.type
,
1996 .scope
= SCOPE_UNIVERSE
,
1997 .cast
= RTC_UNICAST
,
2000 if (nf
->n
.nhs
->next
)
2002 a0
.dest
= RTD_MULTIPATH
;
2003 a0
.nexthops
= nf
->n
.nhs
;
2005 else if (ipa_nonzero(nf
->n
.nhs
->gw
))
2007 a0
.dest
= RTD_ROUTER
;
2008 a0
.iface
= nf
->n
.nhs
->iface
;
2009 a0
.gw
= nf
->n
.nhs
->gw
;
2013 a0
.dest
= RTD_DEVICE
;
2014 a0
.iface
= nf
->n
.nhs
->iface
;
2017 if (reload
|| ort_changed(nf
, &a0
))
2019 net
*ne
= net_get(p
->table
, nf
->fn
.prefix
, nf
->fn
.pxlen
);
2020 rta
*a
= rta_lookup(&a0
);
2021 rte
*e
= rte_get_temp(a
);
2023 rta_free(nf
->old_rta
);
2024 nf
->old_rta
= rta_clone(a
);
2025 e
->u
.ospf
.metric1
= nf
->old_metric1
= nf
->n
.metric1
;
2026 e
->u
.ospf
.metric2
= nf
->old_metric2
= nf
->n
.metric2
;
2027 e
->u
.ospf
.tag
= nf
->old_tag
= nf
->n
.tag
;
2028 e
->u
.ospf
.router_id
= nf
->old_rid
= nf
->n
.rid
;
2031 e
->pref
= p
->preference
;
2033 DBG("Mod rte type %d - %I/%d via %I on iface %s, met %d\n",
2034 a0
.source
, nf
->fn
.prefix
, nf
->fn
.pxlen
, a0
.gw
, a0
.iface
? a0
.iface
->name
: "(none)", nf
->n
.metric1
);
2035 rte_update(p
->table
, ne
, p
, p
, e
);
2038 else if (nf
->old_rta
)
2040 /* Remove the route */
2041 rta_free(nf
->old_rta
);
2044 net
*ne
= net_get(p
->table
, nf
->fn
.prefix
, nf
->fn
.pxlen
);
2045 rte_update(p
->table
, ne
, p
, p
, NULL
);
2048 /* Remove unused rt entry. Entries with fn.x0 == 1 are persistent. */
2049 if (!nf
->n
.type
&& !nf
->fn
.x0
&& !nf
->fn
.x1
)
2051 FIB_ITERATE_PUT(&fit
, nftmp
);
2052 fib_delete(fib
, nftmp
);
2056 FIB_ITERATE_END(nftmp
);
2059 WALK_LIST(oa
, po
->area_list
)
2061 /* Cleanup ASBR hash tables */
2062 FIB_ITERATE_INIT(&fit
, &oa
->rtr
);
2064 FIB_ITERATE_START(&oa
->rtr
, &fit
, nftmp
)
2070 FIB_ITERATE_PUT(&fit
, nftmp
);
2071 fib_delete(&oa
->rtr
, nftmp
);
2075 FIB_ITERATE_END(nftmp
);