summaryrefslogtreecommitdiffstats
path: root/proto/ospf
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2009-10-07 22:10:29 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2009-10-07 22:10:29 +0200
commitd82fc18d75e4ebf615657cb5d98f000c728b13e4 (patch)
treef2629862f96c5e5ad82a40a292f88b3e5c0b671e /proto/ospf
parent9f0ba7b1c7a0754c473b8ab202f572c9c8363285 (diff)
downloadbird-d82fc18d75e4ebf615657cb5d98f000c728b13e4.tar
bird-d82fc18d75e4ebf615657cb5d98f000c728b13e4.zip
Implement proper LSA ID generation.
Diffstat (limited to 'proto/ospf')
-rw-r--r--proto/ospf/ospf.c4
-rw-r--r--proto/ospf/rt.c2
-rw-r--r--proto/ospf/topology.c71
3 files changed, 66 insertions, 11 deletions
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index dafb607..0c4d673 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -605,7 +605,9 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
struct area_net_config *anc;
struct area_net *an;
- po->rfc1583 = new->rfc1583;
+ if (po->rfc1583 != new->rfc1583)
+ return 0;
+
schedule_rtcalc(po);
po->tick = new->tick;
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 416223f..68b6c82 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -18,7 +18,7 @@ static void ospf_ext_spf(struct proto_ospf *po);
static void rt_sync(struct proto_ospf *po);
/* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
- as index, so we need to encapsulate RID to IP addresss */
+ as index, so we need to encapsulate RID to IP address */
#ifdef OSPFv2
#define ipa_from_rid(x) _MI(x)
#else /* OSPFv3 */
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 182f644..6f7905b 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -30,11 +30,64 @@ void flush_prefix_net_lsa(struct ospf_iface *ifa);
#define ipa_to_rid(x) _I3(x)
#endif
-/* FIXME very ugly hack */
+
#ifdef OSPFv2
-#define ipa_to_lsaid(x) _I(x)
+static inline u32
+fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
+{
+ /* We have to map IP prefixes to u32 in such manner that resulting
+ u32 interpreted as IP address is a member of given
+ prefix. Therefore, /32 prefix have to be mapped on itself.
+ All received prefixes have to be mapped on different u32s.
+
+ We have an assumption that if there is nontrivial (non-/32)
+ network prefix, then there is not /32 prefix for the first
+ and the last IP address of the network (these are usually
+ reserved, therefore it is not an important restriction).
+ The network prefix is mapped to the first or the last
+ IP address in the manner that disallow collisions - we
+ use IP address that cannot be used by parent prefix.
+
+ For example:
+ 192.168.0.0/24 maps to 192.168.0.255
+ 192.168.1.0/24 maps to 192.168.1.0
+ because 192.168.0.0 and 192.168.1.255 might be used by
+ 192.168.0.0/23 .
+
+ This is not compatible with older RFC 1583, so we have an option
+ to the RFC 1583 compatible assignment (that always uses the first
+ address) which disallows subnetting.
+
+ Appendig E of RFC 2328 suggests different algorithm, that tries
+ to maximize both compatibility and subnetting. But as it is not
+ possible to have both reliably and the suggested algorithm was
+ unnecessary complicated and it does crazy things like changing
+ LSA ID for a network because different network appeared, we
+ choose a different way. */
+
+ u32 id = _I(fn->prefix);
+
+ if ((po->rfc1583) || (fn->pxlen == 0) || (fn->pxlen == 32))
+ return id;
+
+ if (id & (1 << (32 - fn->pxlen)))
+ return id;
+ else
+ return id | ~u32_mkmask(fn->pxlen);
+}
+
#else /* OSPFv3 */
-#define ipa_to_lsaid(x) _I0(x) ^ _I1(x) ^ _I2(x) ^ _I3(x)
+
+static inline u32
+fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
+{
+ /* In OSPFv3, it is simpler. There is not a requirement
+ for membership of the result in input network, so we
+ just use hash-based unique ID. */
+
+ return fn->uid;
+}
+
#endif
@@ -660,8 +713,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
if (type == ORT_NET)
{
- /* FIXME proper handling of LSA IDs and check for the same network */
- lsa.id = ipa_to_lsaid(fn->prefix);
+ lsa.id = fibnode_to_lsaid(po, fn);
lsa.type = LSA_T_SUM_NET;
}
else
@@ -710,8 +762,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
lsa.rt = rid;
if (type == ORT_NET)
{
- /* FIXME proper handling of LSA IDs and check for the same network */
- lsa.id = ipa_to_lsaid(fn->prefix);
+ lsa.id = fibnode_to_lsaid(po, fn);
lsa.type = LSA_T_SUM_NET;
}
else
@@ -721,6 +772,8 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
lsa.type = LSA_T_SUM_RT;
}
+ /* FIXME check for the same network */
+
if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
{
struct ospf_lsa_sum *sum = en->lsa_body;
@@ -892,7 +945,7 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
#endif
/* FIXME proper handling of LSA IDs and check for the same network */
- lsa.id = ipa_to_lsaid(n->n.prefix);
+ lsa.id = fibnode_to_lsaid(po, &n->n);
if ((en = ospf_hash_find_header(po->gr, 0, &lsa)) != NULL)
{
@@ -927,7 +980,7 @@ flush_ext_lsa(net *n, struct proto_ospf *po)
n->n.prefix, n->n.pxlen);
/* FIXME proper handling of LSA IDs and check for the same network */
- u32 lsaid = ipa_to_lsaid(n->n.prefix);
+ u32 lsaid = fibnode_to_lsaid(po, &n->n);
if (en = ospf_hash_find(po->gr, 0, lsaid, rid, LSA_T_EXT))
{