1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

Temporary OSPFv3 development commit

This commit is contained in:
Ondrej Zajicek
2009-08-21 09:27:52 +02:00
parent 3aab39f589
commit c3226991a0
24 changed files with 1911 additions and 1000 deletions

View File

@@ -9,6 +9,13 @@
#include "ospf.h"
struct ospf_lsupd_packet
{
struct ospf_packet ospf_packet;
u32 lsano; /* Number of LSA's */
};
void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n)
{
struct ospf_lsa_header lsa;
@@ -51,27 +58,79 @@ static void ospf_dump_lsupd(struct proto *p, struct ospf_lsupd_packet *pkt)
}
}
#ifdef OSPFv2
int
ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
{
if (lsa->type == LSA_T_EXT)
{
if (ifa->type == OSPF_IT_VLINK)
return 0;
if (ifa->oa->stub)
return 0;
return 1
}
else
return ifa->oa->areaid == domain;
}
#else /* OSPFv3 */
int
ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
{
u32 scope = LSA_SCOPE(lsa);
/* 4.5.2 (Case 2) */
if (unknown_type(lsa) && !(lsa->type & LSA_UBIT))
scope = LSA_SCOPE_LINK;
switch (scope)
{
case LSA_SCOPE_LINK:
return ifa->iface->index == domain;
case LSA_SCOPE_AREA:
return ifa->oa->areaid == domain;
case LSA_SCOPE_AS:
if (ifa->type == OSPF_IT_VLINK)
return 0;
if (ifa->oa->stub)
return 0;
return 1;
default:
log(L_ERR "LSA with invalid scope");
return 0;
}
}
#endif
/**
* ospf_lsupd_flood - send received or generated lsa to the neighbors
* @po: OSPF protocol
* @n: neighbor than sent this lsa (or NULL if generated)
* @hn: LSA header followed by lsa body in network endianity (may be NULL)
* @hh: LSA header in host endianity (must be filled)
* @iff: interface which received this LSA (or NULL if LSA is generated)
* @oa: ospf_area which is the LSA generated for
* @domain: domain of LSA (must be filled)
* @rtl: add this LSA into retransmission list
*
*
* return value - was the LSA flooded back?
*/
int
ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
struct ospf_lsa_header *hh, struct ospf_iface *iff,
struct ospf_area *oa, int rtl)
ospf_lsupd_flood(struct proto_ospf *po,
struct ospf_neighbor *n, struct ospf_lsa_header *hn,
struct ospf_lsa_header *hh, u32 domain, int rtl)
{
struct ospf_iface *ifa;
struct ospf_neighbor *nn;
struct top_hash_entry *en;
struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
int ret, retval = 0;
@@ -81,18 +140,8 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
if (ifa->stub)
continue;
if (hh->type == LSA_T_EXT)
{
if (ifa->type == OSPF_IT_VLINK)
continue;
if (ifa->oa->stub)
continue;
}
else
{
if (ifa->oa != oa)
continue;
}
if (! ospf_lsa_flooding_allowed(hh, domain, ifa))
continue;
DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
hh->type, hh->id, hh->rt, hh->sn, hh->age);
@@ -100,11 +149,14 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
ret = 0;
WALK_LIST(nn, ifa->neigh_list)
{
/* 13.3 (1a) */
if (nn->state < NEIGHBOR_EXCHANGE)
continue;
/* 13.3 (1b) */
if (nn->state < NEIGHBOR_FULL)
{
if ((en = ospf_hash_find_header(nn->lsrqh, nn->ifa->oa->areaid, hh)) != NULL)
if ((en = ospfxx_hash_find_header(nn->lsrqh, domain, hh)) != NULL)
{
DBG("That LSA found in lsreq list for neigh %R\n", nn->rid);
@@ -140,14 +192,20 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
}
}
/* 13.3 (1c) */
if (nn == n)
continue;
/* 13.3 (1d) */
if (rtl)
{
if ((en = ospf_hash_find_header(nn->lsrth, nn->ifa->oa->areaid, hh)) == NULL)
/* In OSPFv3, there should be check whether receiving router understand
that type of LSA (for LSA types with U-bit == 0). But as we does not support
any optional LSA types, this is not needed yet */
if ((en = ospfxx_hash_find_header(nn->lsrth, domain, hh)) == NULL)
{
en = ospf_hash_get_header(nn->lsrth, nn->ifa->oa, hh);
en = ospfxx_hash_get_header(nn->lsrth, domain, hh);
}
else
{
@@ -159,7 +217,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
}
else
{
if ((en = ospf_hash_find_header(nn->lsrth, nn->ifa->oa->areaid, hh)) != NULL)
if ((en = ospfxx_hash_find_header(nn->lsrth, domain, hh)) != NULL)
{
s_rem_node(SNODE en);
if (en->lsa_body != NULL)
@@ -175,11 +233,11 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
if (ret == 0)
continue; /* pg 150 (2) */
if (ifa == iff)
if (n && (n->ifa == ifa))
{
if ((n->rid == iff->drid) || n->rid == iff->bdrid)
if ((n->rid == ifa->drid) || n->rid == ifa->bdrid)
continue; /* pg 150 (3) */
if (iff->state == OSPF_IS_BACKUP)
if (ifa->state == OSPF_IS_BACKUP)
continue; /* pg 150 (4) */
retval = 1;
}
@@ -216,7 +274,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
htonlsah(hh, lh);
help = (u8 *) (lh + 1);
en = ospf_hash_find_header(po->gr, oa->areaid, hh);
en = ospfxx_hash_find_header(po->gr, domain, hh);
htonlsab(en->lsa_body, help, hh->type, hh->length
- sizeof(struct ospf_lsa_header));
}
@@ -288,8 +346,9 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
WALK_LIST(llsh, *l)
{
if ((en = ospf_hash_find(po->gr, oa->areaid, llsh->lsh.id, llsh->lsh.rt,
llsh->lsh.type)) == NULL)
u32 domain = ospf_lsa_domain(llsh->lsh.type, n->ifa);
if ((en = ospfxx_hash_find(po->gr, domain, llsh->lsh.id,
llsh->lsh.rt, llsh->lsh.type)) == NULL)
continue; /* Probably flushed LSA */
/* FIXME This is a bug! I cannot flush LSA that is in lsrt */
@@ -330,13 +389,12 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
}
void
ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
struct ospf_iface *ifa, struct ospf_neighbor *n)
ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
u32 area;
struct ospf_lsupd_packet *ps = (void *) ps_i;
struct ospf_neighbor *ntmp;
struct ospf_lsa_header *lsa;
struct ospf_area *oa;
struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto;
unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length);
@@ -359,8 +417,6 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
ospf_neigh_sm(n, INM_HELLOREC); /* Questionable */
lsa = (struct ospf_lsa_header *) (ps + 1);
area = htonl(ps->ospf_packet.areaid);
oa = ospf_find_area((struct proto_ospf *) p, area);
for (i = 0; i < ntohl(ps->lsano); i++,
lsa = (struct ospf_lsa_header *) (((u8 *) lsa) + ntohs(lsa->length)))
@@ -394,6 +450,8 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
continue;
}
#ifdef OSPFv2
/* pg 143 (2) */
if ((lsa->type < LSA_T_RT) || (lsa->type > LSA_T_EXT))
{
@@ -402,18 +460,34 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
}
/* pg 143 (3) */
if ((lsa->type == LSA_T_EXT) && oa->stub)
if ((lsa->type == LSA_T_EXT) && ifa->oa->stub)
{
log(L_WARN "Received External LSA in stub area from %I", n->ip);
continue;
}
#else /* OSPFv3 */
/* 4.5.1 (2) */
if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && ifa->oa->stub)
{
log(L_WARN "Received LSA with AS scope in stub area from %I", n->ip);
continue;
}
/* 4.5.1 (3) */
if ((LSA_SCOPE(lsa) == LSA_SCOPE_RES))
{
log(L_WARN "Received LSA with invalid scope from %I", n->ip);
continue;
}
#endif
ntohlsah(lsa, &lsatmp);
DBG("Update Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
lsadb = ospf_hash_find_header(po->gr, oa->areaid, &lsatmp);
u32 domain = ospf_lsa_domain(lsatmp.type, ifa);
lsadb = ospfxx_hash_find_header(po->gr, domain, &lsatmp);
#ifdef LOCAL_DEBUG
if (lsadb)
@@ -439,7 +513,8 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
DBG("PG143(5): Received LSA is newer\n");
/* pg 145 (5f) - premature aging of self originated lsa */
#ifdef OSPFv2
/* 13.4 - check self-originated LSAs of NET type */
if ((!self) && (lsatmp.type == LSA_T_NET))
{
WALK_LIST(nifa, po->iface_list)
@@ -453,7 +528,9 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
}
}
}
#endif
/* pg 145 (5f) - premature aging of self originated lsa */
if (self)
{
struct top_hash_entry *en;
@@ -473,10 +550,10 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
lsatmp.type, lsatmp.id, lsatmp.rt);
lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */
lsatmp.checksum = ntohs(lsa->checksum);
ospf_lsupd_flood(NULL, lsa, &lsatmp, NULL, oa, 0);
if (en = ospf_hash_find_header(po->gr, oa->areaid, &lsatmp))
{
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
ospf_lsupd_flood(po, NULL, lsa, &lsatmp, domain, 0);
if (en = ospfxx_hash_find_header(po->gr, domain, &lsatmp))
{ /* FIXME verify hacks */
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, domain, 1);
}
continue;
}
@@ -489,7 +566,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
continue;
}
if (ospf_lsupd_flood(n, lsa, &lsatmp, ifa, ifa->oa, 1) == 0)
if (ospf_lsupd_flood(po, n, lsa, &lsatmp, domain, 1) == 0)
{
DBG("Wasn't flooded back\n"); /* ps 144(5e), pg 153 */
if (ifa->state == OSPF_IS_BACKUP)
@@ -509,7 +586,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
{
struct top_hash_entry *en;
if (ntmp->state > NEIGHBOR_EXSTART)
if ((en = ospf_hash_find_header(ntmp->lsrth, ntmp->ifa->oa->areaid, &lsadb->lsa)) != NULL)
if ((en = ospfxx_hash_find_header(ntmp->lsrth, domain, &lsadb->lsa)) != NULL)
{
s_rem_node(SNODE en);
if (en->lsa_body != NULL)
@@ -532,7 +609,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header));
ntohlsab(lsa + 1, body, lsatmp.type,
lsatmp.length - sizeof(struct ospf_lsa_header));
lsadb = lsa_install_new(&lsatmp, body, oa);
lsadb = lsa_install_new(po, &lsatmp, domain, body);
DBG("New LSA installed in DB\n");
continue;
@@ -545,7 +622,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
{
struct top_hash_entry *en;
DBG("PG145(7) Got the same LSA\n");
if ((en = ospf_hash_find_header(n->lsrth, n->ifa->oa->areaid, &lsadb->lsa)) != NULL)
if ((en = ospfxx_hash_find_header(n->lsrth, lsadb->domain, &lsadb->lsa)) != NULL)
{
/* pg145 (7a) */
s_rem_node(SNODE en);
@@ -596,10 +673,9 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
}
void
ospf_lsupd_flush_nlsa(struct top_hash_entry *en, struct ospf_area *oa)
ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en)
{
struct ospf_lsa_header *lsa = &en->lsa;
struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
lsa->age = LSA_MAXAGE;
@@ -607,5 +683,5 @@ ospf_lsupd_flush_nlsa(struct top_hash_entry *en, struct ospf_area *oa)
lsasum_calculate(lsa, en->lsa_body);
OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa!");
OSPF_TRACE(D_EVENTS, "Type: %d, Id: %R, Rt: %R", lsa->type, lsa->id, lsa->rt);
ospf_lsupd_flood(NULL, NULL, lsa, NULL, oa, 0);
ospf_lsupd_flood(po, NULL, NULL, lsa, en->domain, 0);
}