summaryrefslogtreecommitdiff
path: root/proto/ospf
diff options
context:
space:
mode:
Diffstat (limited to 'proto/ospf')
-rw-r--r--proto/ospf/ospf.c3
-rw-r--r--proto/ospf/topology.c32
-rw-r--r--proto/ospf/topology.h1
3 files changed, 31 insertions, 5 deletions
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index ebea9519..8229d096 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -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))
{
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 733719ab..87509979 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -355,6 +355,28 @@ originate_ext_lsa_body(net *n, rte *e, struct proto_ospf *po, struct ea_list *at
}
/**
+ * 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
* @e: rte
@@ -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;
}
diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h
index c4bbc9e5..d85173fa 100644
--- a/proto/ospf/topology.h
+++ b/proto/ospf/topology.h
@@ -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_ */