The code was broken for external /29 to /32 routes. Assuming that you
have one machine publishing a route to 10.1.1.3/32 and another one publishing a route to 10.1.1.4/32. If the first machine went down the route to 10.1.1.4/32 was wrongly killed by the old code, leading either to missing routes or worse to bug()s like "Router parent does not have next hop" or just segfaults. The patch fixes this but in the long term a redesign is required here. Note that the patch doesn't worse the situation, instead it prevents the problems stated. The redesign is required to handle multiple routes to small subnets properly. (by Andreas) Feela, I think that this is at least a good temporary fix, but it's of course up to you to decide.
This commit is contained in:
parent
4ef3dccfa1
commit
0077aab4f9
3 changed files with 31 additions and 5 deletions
|
@ -391,11 +391,12 @@ ospf_rt_notify(struct proto *p, net *n, rte *new, rte *old, ea_list *attrs)
|
|||
u32 pr=ipa_to_u32(n->n.prefix);
|
||||
struct ospf_lsa_ext *ext;
|
||||
int i;
|
||||
int max=max_ext_lsa(n->n.pxlen);
|
||||
|
||||
/* Flush old external LSA */
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
for(i=0;i<MAXNETS;i++,pr++)
|
||||
for(i=0;i<max;i++,pr++)
|
||||
{
|
||||
if(en=ospf_hash_find(oa->gr, pr, rtid, LSA_T_EXT))
|
||||
{
|
||||
|
|
|
@ -354,6 +354,28 @@ originate_ext_lsa_body(net *n, rte *e, struct proto_ospf *po, struct ea_list *at
|
|||
return ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* max_ext_lsa - calculate the maximum amount of external networks
|
||||
* possible for the given prefix length.
|
||||
*
|
||||
* This is a fix for the previous static use of MAXNETS which did
|
||||
* only work correct if MAXNETS < possible IPs for given prefix.
|
||||
* This solution is kind of a hack as there can now only be one
|
||||
* route for /32 type entries but this is better than the crashes
|
||||
* I did experience whith close together /32 routes originating
|
||||
* on different hosts.
|
||||
*/
|
||||
|
||||
int
|
||||
max_ext_lsa(unsigned pxlen)
|
||||
{
|
||||
int i;
|
||||
for(i=1;pxlen<BITS_PER_IP_ADDRESS;pxlen++,i<<=1)
|
||||
if(i>=MAXNETS)
|
||||
return MAXNETS;
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* originate_ext_lsa - new route received from nest and filters
|
||||
* @n: network prefix and mask
|
||||
|
@ -380,6 +402,7 @@ originate_ext_lsa(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs)
|
|||
struct ospf_area *oa;
|
||||
struct ospf_lsa_ext *ext1,*ext2;
|
||||
int i;
|
||||
int max;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Originating Ext lsa for %I/%d.", n->n.prefix,
|
||||
n->n.pxlen);
|
||||
|
@ -393,10 +416,11 @@ originate_ext_lsa(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs)
|
|||
lsa.length=sizeof(struct ospf_lsa_ext)+sizeof(struct ospf_lsa_ext_tos)+
|
||||
sizeof(struct ospf_lsa_header);
|
||||
ext1=body;
|
||||
max=max_ext_lsa(n->n.pxlen);
|
||||
|
||||
oa=HEAD(po->area_list);
|
||||
|
||||
for(i=0;i<MAXNETS;i++)
|
||||
for(i=0;i<max;i++)
|
||||
{
|
||||
if((en=ospf_hash_find_header(oa->gr, &lsa))!=NULL)
|
||||
{
|
||||
|
@ -407,10 +431,10 @@ originate_ext_lsa(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs)
|
|||
else break;
|
||||
}
|
||||
|
||||
if(i==MAXNETS)
|
||||
if(i==max)
|
||||
{
|
||||
log("%s: got more routes for one network then %d, ignoring",p->name,
|
||||
MAXNETS);
|
||||
log("%s: got more routes for one /%d network then %d, ignoring",p->name,
|
||||
n->n.pxlen,max);
|
||||
mb_free(body);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ void addifa_rtlsa(struct ospf_iface *ifa);
|
|||
void originate_rt_lsa(struct ospf_area *oa);
|
||||
void originate_net_lsa(struct ospf_iface *ifa);
|
||||
int can_flush_lsa(struct ospf_area *oa);
|
||||
int max_ext_lsa(unsigned pxlen);
|
||||
void originate_ext_lsa(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs);
|
||||
|
||||
#endif /* _BIRD_OSPF_TOPOLOGY_H_ */
|
||||
|
|
Loading…
Reference in a new issue