Temporary OSPFv3 development commit
This commit is contained in:
parent
c3226991a0
commit
b49e6f5a65
23 changed files with 449 additions and 214 deletions
|
@ -86,6 +86,7 @@ int filter_same(struct filter *new, struct filter *old);
|
|||
|
||||
int i_same(struct f_inst *f1, struct f_inst *f2);
|
||||
|
||||
void f_prefix_get_bounds(struct f_prefix *px, int *l, int *h);
|
||||
int val_compare(struct f_val v1, struct f_val v2);
|
||||
void val_print(struct f_val v);
|
||||
|
||||
|
|
|
@ -272,7 +272,7 @@ static int
|
|||
trie_node_print(struct f_trie_node *t, char *buf, int blen)
|
||||
{
|
||||
if (t == NULL)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
int old_blen = blen;
|
||||
int wb = 0; // bsnprintf(buf, blen, "%I/%d accept %I\n", t->addr, t->plen, t->accept);
|
||||
|
|
54
lib/ipv6.c
54
lib/ipv6.c
|
@ -136,6 +136,60 @@ ipv6_compare(ip_addr X, ip_addr Y)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* From Linux include/net/ipv6.h */
|
||||
#define NEXTHDR_HOP 0 /* Hop-by-hop option header. */
|
||||
#define NEXTHDR_ROUTING 43 /* Routing header. */
|
||||
#define NEXTHDR_FRAGMENT 44 /* Fragmentation/reassembly header. */
|
||||
#define NEXTHDR_DEST 60 /* Destination options header. */
|
||||
#define NEXTHDR_NONE 59 /* No next header */
|
||||
|
||||
#define NEXTHDR_ESP 50 /* Encapsulating security payload. */
|
||||
#define NEXTHDR_AUTH 51 /* Authentication header. */
|
||||
|
||||
|
||||
byte *
|
||||
ipv6_skip_header(byte *pkt, int *len)
|
||||
{
|
||||
int l = *len;
|
||||
int q;
|
||||
u8 nh;
|
||||
|
||||
if (l < 40 || (*pkt & 0xf0) != 0x60)
|
||||
return NULL;
|
||||
|
||||
/* Skip IPv6 header */
|
||||
nh = pkt[6];
|
||||
pkt += 40;
|
||||
|
||||
while ()
|
||||
{
|
||||
switch (nw)
|
||||
{
|
||||
case NEXTHDR_FRAGMENT:
|
||||
|
||||
case NEXTHDR_HOP:
|
||||
case NEXTHDR_ROUTING:
|
||||
case NEXTHDR_DEST:
|
||||
|
||||
case NEXTHDR_AUTH:
|
||||
break;
|
||||
|
||||
case NEXTHDR_NONE:
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
return pkt;
|
||||
}
|
||||
}
|
||||
|
||||
q = (*pkt & 0x0f) * 4;
|
||||
if (q > l)
|
||||
return NULL;
|
||||
*len -= q;
|
||||
return pkt + q;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Conversion of IPv6 address to presentation format and vice versa.
|
||||
* Heavily inspired by routines written by Paul Vixie for the BIND project
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/*
|
||||
* BIRD -- IP Addresses et Cetera for IPv6
|
||||
*
|
||||
|
|
|
@ -298,7 +298,7 @@ parse_path(struct adata *path, struct pm_pos *pos)
|
|||
u8 *p = path->data;
|
||||
u8 *q = p + path->length;
|
||||
struct pm_pos *opos = pos;
|
||||
int i, j, len;
|
||||
int i, len;
|
||||
|
||||
|
||||
while (p < q)
|
||||
|
|
|
@ -71,7 +71,6 @@ ea__find(ea_list *e, unsigned id)
|
|||
|
||||
while (e)
|
||||
{
|
||||
/*
|
||||
if (e->flags & EALF_BISECT)
|
||||
{
|
||||
l = 0;
|
||||
|
@ -89,7 +88,6 @@ ea__find(ea_list *e, unsigned id)
|
|||
}
|
||||
}
|
||||
else
|
||||
*/
|
||||
for(m=0; m<e->count; m++)
|
||||
if (e->attrs[m].id == id)
|
||||
return &e->attrs[m];
|
||||
|
|
|
@ -1131,6 +1131,8 @@ as4_aggregator_valid(struct adata *aggr)
|
|||
|
||||
if ((a[0] == 0) || (a[1] == 0))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -488,7 +488,6 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
|
|||
{
|
||||
struct bgp_proto *p = conn->bgp;
|
||||
int cl;
|
||||
u32 as;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
|
|
|
@ -85,8 +85,9 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
|||
struct proto *p = &po->proto;
|
||||
u16 length, i, j;
|
||||
|
||||
/* FIXME ??? */
|
||||
if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal)))
|
||||
originate_rt_lsa(oa);
|
||||
update_rt_lsa(oa);
|
||||
|
||||
switch (n->state)
|
||||
{
|
||||
|
@ -227,13 +228,14 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
|
|||
for (i = 0; i < j; i++)
|
||||
{
|
||||
ntohlsah(plsa + i, &lsa);
|
||||
if (((he = ospfxx_hash_find_smart(gr, n->ifa, &lsa)) == NULL) ||
|
||||
u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
|
||||
if (((he = ospf_hash_find_header(gr, dom, &lsa)) == NULL) ||
|
||||
(lsa_comp(&lsa, &(he->lsa)) == 1))
|
||||
{
|
||||
/* Is this condition necessary? */
|
||||
if (ospfxx_hash_find_smart(n->lsrqh, n->ifa, &lsa) == NULL)
|
||||
if (ospf_hash_find_header(n->lsrqh, dom, &lsa) == NULL)
|
||||
{
|
||||
sn = ospfxx_hash_get_smart(n->lsrqh, n->ifa, &lsa);
|
||||
sn = ospf_hash_get_header(n->lsrqh, dom, &lsa);
|
||||
ntohlsah(plsa + i, &(sn->lsa));
|
||||
s_add_tail(&(n->lsrql), SNODE sn);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
struct ospf_hello_packet *ps = (void *) ps_i;
|
||||
u32 *pnrid;
|
||||
u32 olddr, oldbdr, oldiface_id, tmp;
|
||||
ip_addr mask;
|
||||
char *beg = "Bad OSPF hello packet from ", *rec = " received: ";
|
||||
struct proto *p = (struct proto *) ifa->oa->po;
|
||||
unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers;
|
||||
|
|
|
@ -420,6 +420,23 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface,
|
|||
|
||||
#ifdef OSPFv3
|
||||
ifa->instance_id = ip->instance_id;
|
||||
|
||||
ifa->lladdr = IPA_NONE;
|
||||
|
||||
/* Find link-local address */
|
||||
if (ifa->type != OSPF_IT_VLINK)
|
||||
{
|
||||
struct ifa *a;
|
||||
WALK_LIST(a, iface->addrs)
|
||||
if (a->scope == SCOPE_LINK)
|
||||
{
|
||||
ifa->lladdr = a->ip;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! ipa_nonzero(ifa->lladdr))
|
||||
log(L_WARN "%s: Missing link local address on interface %s", p->name, iface->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
ifa->rxbuf = ip->rxbuf;
|
||||
|
|
|
@ -177,7 +177,8 @@ ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
for (i = 0; i < nolsa; i++)
|
||||
{
|
||||
ntohlsah(ps->lsh + i, &lsa);
|
||||
if ((en = ospfxx_hash_find_smart(n->lsrth, n->ifa, &lsa)) == NULL)
|
||||
u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
|
||||
if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL)
|
||||
continue; /* pg 155 */
|
||||
|
||||
if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */
|
||||
|
|
|
@ -384,12 +384,11 @@ lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain,
|
|||
{
|
||||
/* LSA can be temporarrily, but body must be mb_allocated. */
|
||||
int change = 0;
|
||||
unsigned i;
|
||||
struct top_hash_entry *en;
|
||||
|
||||
if ((en = ospfxx_hash_find_header(po->gr, domain, lsa)) == NULL)
|
||||
if ((en = ospf_hash_find_header(po->gr, domain, lsa)) == NULL)
|
||||
{
|
||||
en = ospfxx_hash_get_header(po->gr, domain, lsa);
|
||||
en = ospf_hash_get_header(po->gr, domain, lsa);
|
||||
change = 1;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -127,7 +127,7 @@ ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
llsh->lsh.rt = hrt;
|
||||
llsh->lsh.type = htype;
|
||||
add_tail(&uplist, NODE llsh);
|
||||
if (ospfxx_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
|
||||
if (ospf_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
|
||||
{
|
||||
log(L_WARN
|
||||
"Received bad LS req from: %I looking: Type: %u, ID: %R, RT: %R",
|
||||
|
|
|
@ -156,7 +156,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
|
|||
/* 13.3 (1b) */
|
||||
if (nn->state < NEIGHBOR_FULL)
|
||||
{
|
||||
if ((en = ospfxx_hash_find_header(nn->lsrqh, domain, hh)) != NULL)
|
||||
if ((en = ospf_hash_find_header(nn->lsrqh, domain, hh)) != NULL)
|
||||
{
|
||||
DBG("That LSA found in lsreq list for neigh %R\n", nn->rid);
|
||||
|
||||
|
@ -203,9 +203,9 @@ ospf_lsupd_flood(struct proto_ospf *po,
|
|||
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)
|
||||
if ((en = ospf_hash_find_header(nn->lsrth, domain, hh)) == NULL)
|
||||
{
|
||||
en = ospfxx_hash_get_header(nn->lsrth, domain, hh);
|
||||
en = ospf_hash_get_header(nn->lsrth, domain, hh);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -217,7 +217,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((en = ospfxx_hash_find_header(nn->lsrth, domain, hh)) != NULL)
|
||||
if ((en = ospf_hash_find_header(nn->lsrth, domain, hh)) != NULL)
|
||||
{
|
||||
s_rem_node(SNODE en);
|
||||
if (en->lsa_body != NULL)
|
||||
|
@ -274,7 +274,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
|
|||
|
||||
htonlsah(hh, lh);
|
||||
help = (u8 *) (lh + 1);
|
||||
en = ospfxx_hash_find_header(po->gr, domain, hh);
|
||||
en = ospf_hash_find_header(po->gr, domain, hh);
|
||||
htonlsab(en->lsa_body, help, hh->type, hh->length
|
||||
- sizeof(struct ospf_lsa_header));
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
|
|||
WALK_LIST(llsh, *l)
|
||||
{
|
||||
u32 domain = ospf_lsa_domain(llsh->lsh.type, n->ifa);
|
||||
if ((en = ospfxx_hash_find(po->gr, domain, llsh->lsh.id,
|
||||
if ((en = ospf_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 */
|
||||
|
@ -487,7 +487,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
|
||||
|
||||
u32 domain = ospf_lsa_domain(lsatmp.type, ifa);
|
||||
lsadb = ospfxx_hash_find_header(po->gr, domain, &lsatmp);
|
||||
lsadb = ospf_hash_find_header(po->gr, domain, &lsatmp);
|
||||
|
||||
#ifdef LOCAL_DEBUG
|
||||
if (lsadb)
|
||||
|
@ -508,7 +508,6 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
{
|
||||
struct ospf_iface *ift = NULL;
|
||||
void *body;
|
||||
struct ospf_iface *nifa;
|
||||
int self = (lsatmp.rt == p->cf->global->router_id);
|
||||
|
||||
DBG("PG143(5): Received LSA is newer\n");
|
||||
|
@ -517,6 +516,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
/* 13.4 - check self-originated LSAs of NET type */
|
||||
if ((!self) && (lsatmp.type == LSA_T_NET))
|
||||
{
|
||||
struct ospf_iface *nifa;
|
||||
WALK_LIST(nifa, po->iface_list)
|
||||
{
|
||||
if (!nifa->iface)
|
||||
|
@ -551,7 +551,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */
|
||||
lsatmp.checksum = ntohs(lsa->checksum);
|
||||
ospf_lsupd_flood(po, NULL, lsa, &lsatmp, domain, 0);
|
||||
if (en = ospfxx_hash_find_header(po->gr, domain, &lsatmp))
|
||||
if (en = ospf_hash_find_header(po->gr, domain, &lsatmp))
|
||||
{ /* FIXME verify hacks */
|
||||
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, domain, 1);
|
||||
}
|
||||
|
@ -586,7 +586,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
{
|
||||
struct top_hash_entry *en;
|
||||
if (ntmp->state > NEIGHBOR_EXSTART)
|
||||
if ((en = ospfxx_hash_find_header(ntmp->lsrth, domain, &lsadb->lsa)) != NULL)
|
||||
if ((en = ospf_hash_find_header(ntmp->lsrth, domain, &lsadb->lsa)) != NULL)
|
||||
{
|
||||
s_rem_node(SNODE en);
|
||||
if (en->lsa_body != NULL)
|
||||
|
@ -622,7 +622,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
{
|
||||
struct top_hash_entry *en;
|
||||
DBG("PG145(7) Got the same LSA\n");
|
||||
if ((en = ospfxx_hash_find_header(n->lsrth, lsadb->domain, &lsadb->lsa)) != NULL)
|
||||
if ((en = ospf_hash_find_header(n->lsrth, lsadb->domain, &lsadb->lsa)) != NULL)
|
||||
{
|
||||
/* pg145 (7a) */
|
||||
s_rem_node(SNODE en);
|
||||
|
|
|
@ -173,16 +173,16 @@ electbdr(list nl)
|
|||
struct ospf_neighbor *neigh, *n1, *n2;
|
||||
u32 nid;
|
||||
|
||||
n1 = NULL;
|
||||
n2 = NULL;
|
||||
WALK_LIST(neigh, nl) /* First try those decl. themselves */
|
||||
{
|
||||
#ifdef OSPFv2
|
||||
nid = ipa_to_u32(neigh->ip);
|
||||
#else /* OSPFv3 */
|
||||
nid = neigh->rid;
|
||||
#endif
|
||||
|
||||
n1 = NULL;
|
||||
n2 = NULL;
|
||||
WALK_LIST(neigh, nl) /* First try those decl. themselves */
|
||||
{
|
||||
if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
|
||||
if (neigh->priority > 0) /* Eligible */
|
||||
if (neigh->dr != nid) /* And not decl. itself DR */
|
||||
|
@ -231,15 +231,15 @@ electdr(list nl)
|
|||
struct ospf_neighbor *neigh, *n;
|
||||
u32 nid;
|
||||
|
||||
n = NULL;
|
||||
WALK_LIST(neigh, nl) /* And now DR */
|
||||
{
|
||||
#ifdef OSPFv2
|
||||
nid = ipa_to_u32(neigh->ip);
|
||||
#else /* OSPFv3 */
|
||||
nid = neigh->rid;
|
||||
#endif
|
||||
|
||||
n = NULL;
|
||||
WALK_LIST(neigh, nl) /* And now DR */
|
||||
{
|
||||
if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
|
||||
if (neigh->priority > 0) /* Eligible */
|
||||
if (neigh->dr == nid) /* And declaring itself DR */
|
||||
|
|
|
@ -337,7 +337,7 @@ schedule_rtcalc(struct proto_ospf *po)
|
|||
* @oa: ospf area
|
||||
*
|
||||
* It invokes aging and when @ospf_area->origrt is set to 1, start
|
||||
* function for origination of router LSA and network LSAs.
|
||||
* function for origination of router, network LSAs.
|
||||
*/
|
||||
void
|
||||
area_disp(struct ospf_area *oa)
|
||||
|
@ -347,13 +347,18 @@ area_disp(struct ospf_area *oa)
|
|||
|
||||
/* Now try to originage rt_lsa */
|
||||
if (oa->origrt)
|
||||
originate_rt_lsa(oa);
|
||||
update_rt_lsa(oa);
|
||||
|
||||
/* Now try to originate network LSA's */
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
{
|
||||
#ifdef OSPFv3
|
||||
if (ifa->origlink && (ifa->oa == oa))
|
||||
update_link_lsa(ifa);
|
||||
#endif
|
||||
|
||||
if (ifa->orignet && (ifa->oa == oa))
|
||||
originate_net_lsa(ifa);
|
||||
update_net_lsa(ifa);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,7 +381,7 @@ ospf_disp(timer * timer)
|
|||
|
||||
/* Calculate routing table */
|
||||
if (po->calcrt)
|
||||
ospf_rt_spf (po);
|
||||
ospf_rt_spf(po);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1019,6 +1024,7 @@ ospf_sh_iface(struct proto *p, char *iff)
|
|||
* according to originating router id (to get all LSA needed to represent one
|
||||
* router node together). Then, according to LSA type, ID and age.
|
||||
*/
|
||||
/*
|
||||
static int
|
||||
he_compare(const void *p1, const void *p2)
|
||||
{
|
||||
|
@ -1057,6 +1063,7 @@ he_compare(const void *p1, const void *p2)
|
|||
return lsa1->age - lsa2->age;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
static inline void
|
||||
show_lsa_router(struct top_hash_entry *he)
|
||||
|
@ -1074,7 +1081,7 @@ show_lsa_router(struct top_hash_entry *he)
|
|||
if (rr[i].type == LSART_NET)
|
||||
{
|
||||
struct proto_ospf *po = he->oa->po;
|
||||
struct top_hash_entry *net_he = ospfxx_hash_find(po->gr, he->oa->areaid, rr[i].id, rr[i].id, LSA_T_NET);
|
||||
struct top_hash_entry *net_he = ospf_hash_find(po->gr, he->oa->areaid, rr[i].id, rr[i].id, LSA_T_NET);
|
||||
if (net_he)
|
||||
{
|
||||
struct ospf_lsa_header *net_lsa = &(net_he->lsa);
|
||||
|
@ -1152,12 +1159,13 @@ show_lsa_external(struct top_hash_entry *he)
|
|||
void
|
||||
ospf_sh_state(struct proto *p, int verbose)
|
||||
{
|
||||
/*
|
||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||
struct top_graph *f = po->gr;
|
||||
unsigned int i, j;
|
||||
u32 last_rt = 0xFFFFFFFF;
|
||||
u32 last_area = 0xFFFFFFFF;
|
||||
/*
|
||||
|
||||
if (p->proto_state != PS_UP)
|
||||
{
|
||||
cli_msg(-1016, "%s: is not up", p->name);
|
||||
|
|
|
@ -194,6 +194,7 @@ struct ospf_iface
|
|||
u32 dr_iface_id; /* if drid is valid, this is iface_id of DR (for connecting network) */
|
||||
u8 instance_id; /* Used to differentiate between more OSPF
|
||||
instances on one interface */
|
||||
ip_addr lladdr; /* Used link-local addr */
|
||||
#endif
|
||||
|
||||
u8 type; /* OSPF view of type */
|
||||
|
@ -371,8 +372,8 @@ struct ospf_lsa_header
|
|||
u32 id;
|
||||
u32 rt; /* Advertising router */
|
||||
s32 sn; /* LS Sequence number */
|
||||
#define LSA_INITSEQNO 0x80000001
|
||||
#define LSA_MAXSEQNO 0x7fffffff
|
||||
#define LSA_INITSEQNO ((s32) 0x80000001)
|
||||
#define LSA_MAXSEQNO ((s32) 0x7fffffff)
|
||||
u16 checksum;
|
||||
u16 length;
|
||||
};
|
||||
|
|
|
@ -278,7 +278,7 @@ ospf_rx_hook(sock * sk, int size)
|
|||
if (ifa->stub)
|
||||
return (1);
|
||||
|
||||
ps = (struct ospf_packet *) ipv4_skip_header(sk->rbuf, &size);
|
||||
ps = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size);
|
||||
|
||||
if (ps == NULL)
|
||||
{
|
||||
|
|
211
proto/ospf/rt.c
211
proto/ospf/rt.c
|
@ -8,12 +8,12 @@
|
|||
|
||||
#include "ospf.h"
|
||||
|
||||
static void
|
||||
add_cand(list * l, struct top_hash_entry *en,
|
||||
struct top_hash_entry *par, u32 dist, struct ospf_area *oa);
|
||||
static void
|
||||
calc_next_hop(struct top_hash_entry *en,
|
||||
struct top_hash_entry *par, struct ospf_area *oa);
|
||||
static void add_cand(list * l, struct top_hash_entry *en,
|
||||
struct top_hash_entry *par, u32 dist,
|
||||
struct ospf_area *oa);
|
||||
static void calc_next_hop(struct ospf_area *oa,
|
||||
struct top_hash_entry *en,
|
||||
struct top_hash_entry *par);
|
||||
static void ospf_ext_spf(struct proto_ospf *po);
|
||||
static void rt_sync(struct proto_ospf *po);
|
||||
|
||||
|
@ -27,10 +27,11 @@ static void rt_sync(struct proto_ospf *po);
|
|||
|
||||
|
||||
static inline u32 *
|
||||
get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts)
|
||||
get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts, u16 *rest)
|
||||
{
|
||||
u8 pxl = (*buf >> 24);
|
||||
*pxopts = (*buf >> 16);
|
||||
*rest = *buf;
|
||||
*pxlen = pxl;
|
||||
buf++;
|
||||
|
||||
|
@ -174,6 +175,79 @@ ri_install(struct proto_ospf *po, ip_addr prefix, int pxlen, int dest,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_hash_entry *en)
|
||||
{
|
||||
orta nf;
|
||||
nf.type = RTS_OSPF;
|
||||
nf.options = 0;
|
||||
nf.metric1 = metric;
|
||||
nf.metric2 = LSINFINITY;
|
||||
nf.tag = 0;
|
||||
nf.oa = oa;
|
||||
nf.ar = en;
|
||||
nf.nh = en->nh;
|
||||
nf.ifa = en->nhi;
|
||||
|
||||
/* FIXME check nf.ifa on stubs */
|
||||
ri_install(oa->po, px, pxlen, ORT_NET, &nf, NULL);
|
||||
}
|
||||
|
||||
#ifdef OSPFv3
|
||||
static void
|
||||
process_prefixes(struct ospf_area *oa)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
struct top_hash_entry *en, *src;
|
||||
struct ospf_lsa_prefix *px;
|
||||
ip_addr pxa;
|
||||
int pxlen;
|
||||
u8 pxopts;
|
||||
u16 metric;
|
||||
u32 *buf;
|
||||
int i;
|
||||
|
||||
WALK_SLIST(en, po->lsal)
|
||||
{
|
||||
if (en->lsa.type != LSA_T_PREFIX)
|
||||
continue;
|
||||
|
||||
if (en->domain != oa->areaid)
|
||||
continue;
|
||||
|
||||
if (en->lsa.age == LSA_MAXAGE)
|
||||
continue;
|
||||
|
||||
px = en->lsa_body;
|
||||
/* FIXME: for router LSA, we should find the first one */
|
||||
src = ospf_hash_find(po->gr, oa->areaid,
|
||||
((px->ref_type == LSA_T_RT) ? px->ref_rt : px->ref_id),
|
||||
px->ref_rt, px->ref_type);
|
||||
|
||||
if (!src)
|
||||
continue;
|
||||
|
||||
if (src->lsa.age == LSA_MAXAGE)
|
||||
continue;
|
||||
|
||||
if ((src->lsa.type != LSA_T_RT) && (src->lsa.type != LSA_T_NET))
|
||||
continue;
|
||||
|
||||
buf = px->rest;
|
||||
for (i = 0; i < px->pxcount; i++)
|
||||
{
|
||||
buf = get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric);
|
||||
|
||||
if (pxopts & OPT_PX_NU)
|
||||
continue;
|
||||
|
||||
add_network(oa, pxa, pxlen, src->dist + metric, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ospf_rt_spfa(struct ospf_area *oa)
|
||||
{
|
||||
|
@ -188,7 +262,6 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
struct top_hash_entry *act, *tmp;
|
||||
node *n;
|
||||
|
||||
|
||||
if (oa->rt == NULL)
|
||||
return;
|
||||
|
||||
|
@ -226,6 +299,7 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
rt = (struct ospf_lsa_rt *) act->lsa_body;
|
||||
if (rt->options & OPT_RT_V)
|
||||
oa->trcap = 1;
|
||||
|
||||
/* FIXME - in OSPFv3, should we add all routers, or just ABRs an ASBRs? */
|
||||
if ((rt->options & OPT_RT_V) || (rt->options & OPT_RT_E))
|
||||
{
|
||||
|
@ -240,6 +314,7 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
nf.ifa = act->nhi;
|
||||
ri_install(po, ipa_from_rid(act->lsa.rt), 32, ORT_ROUTER, &nf, NULL);
|
||||
}
|
||||
|
||||
rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||
DBG(" Number of links: %u\n", rt->links);
|
||||
for (i = 0; i < lsa_rt_count(&act->lsa); i++)
|
||||
|
@ -253,7 +328,6 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
case LSART_STUB:
|
||||
/*
|
||||
* This violates rfc2328! But it is mostly harmless.
|
||||
* But it causes that the cost of the stub is ignored.
|
||||
*/
|
||||
DBG("\n");
|
||||
|
||||
|
@ -293,9 +367,9 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
case LSART_NET:
|
||||
#ifdef OSPFv2
|
||||
/* In OSPFv2, rtl->id is IP addres of DR, router ID is not known */
|
||||
tmp = ospfxx_hash_find(po->gr, oa->areaid, rtl->id, 0, LSA_T_NET);
|
||||
tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, 0, LSA_T_NET);
|
||||
#else /* OSPFv3 */
|
||||
tmp = ospfxx_hash_find(po->gr, oa->areaid, rtl->nif, rtl->id, LSA_T_NET);
|
||||
tmp = ospf_hash_find(po->gr, oa->areaid, rtl->nif, rtl->id, LSA_T_NET);
|
||||
#endif
|
||||
if (tmp == NULL)
|
||||
DBG("Not found!\n");
|
||||
|
@ -305,8 +379,9 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
|
||||
case LSART_VLNK:
|
||||
case LSART_PTP:
|
||||
/* FIXME - in OSPFv3, find any LSA ID */
|
||||
tmp = ospfxx_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
|
||||
/* FIXME - in OSPFv3, find lowest LSA ID */
|
||||
tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
|
||||
|
||||
DBG("PTP found.\n");
|
||||
break;
|
||||
default:
|
||||
|
@ -321,24 +396,18 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
break;
|
||||
case LSA_T_NET:
|
||||
ln = act->lsa_body;
|
||||
nf.type = RTS_OSPF;
|
||||
nf.options = 0;
|
||||
nf.metric1 = act->dist;
|
||||
nf.metric2 = LSINFINITY;
|
||||
nf.tag = 0;
|
||||
nf.oa = oa;
|
||||
nf.ar = act;
|
||||
nf.nh = act->nh;
|
||||
nf.ifa = act->nhi;
|
||||
ri_install(po, ipa_and(ipa_from_u32(act->lsa.id), ln->netmask),
|
||||
ipa_mklen(ln->netmask), ORT_NET, &nf, NULL);
|
||||
|
||||
#ifdef OSPFv2
|
||||
add_network(oa, ipa_and(ipa_from_u32(act->lsa.id), ln->netmask),
|
||||
ipa_mklen(ln->netmask), act->dist, act);
|
||||
#endif
|
||||
|
||||
rts = (u32 *) (ln + 1);
|
||||
for (i = 0; i < lsa_net_count(&act->lsa); i++)
|
||||
{
|
||||
DBG(" Working on router %R ", rts[i]);
|
||||
/* FIXME - in OSPFv3, find any LSA ID */
|
||||
tmp = ospfxx_hash_find(po->gr, oa->areaid, rts[i], rts[i], LSA_T_RT);
|
||||
tmp = ospf_hash_find(po->gr, oa->areaid, rts[i], rts[i], LSA_T_RT);
|
||||
if (tmp != NULL)
|
||||
DBG("Found :-)\n");
|
||||
else
|
||||
|
@ -349,13 +418,17 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef OSPFv3
|
||||
process_prefixes(oa);
|
||||
#endif
|
||||
|
||||
/* Find new/lost VLINK peers */
|
||||
WALK_LIST(iface, po->iface_list)
|
||||
{
|
||||
if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa))
|
||||
{
|
||||
/* FIXME in OSPFv3, different LSAID */
|
||||
if ((tmp = ospfxx_hash_find(po->gr, oa->areaid, iface->vid, iface->vid, LSA_T_RT)) &&
|
||||
if ((tmp = ospf_hash_find(po->gr, oa->areaid, iface->vid, iface->vid, LSA_T_RT)) &&
|
||||
(!ipa_equal(tmp->lb, IPA_NONE)))
|
||||
{
|
||||
if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi->iface) || (!ipa_equal(iface->vip, tmp->lb)))
|
||||
|
@ -379,6 +452,7 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entry *pre)
|
||||
{
|
||||
|
@ -403,7 +477,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
|
|||
case LSART_STUB:
|
||||
break;
|
||||
case LSART_NET:
|
||||
if (ospfxx_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_NET) == pre)
|
||||
if (ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_NET) == pre)
|
||||
{
|
||||
fol->lb = ipa_from_u32(rtl->data);
|
||||
return 1;
|
||||
|
@ -411,7 +485,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
|
|||
break;
|
||||
case LSART_VLNK:
|
||||
case LSART_PTP:
|
||||
if (ospfxx_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT) == pre)
|
||||
if (ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT) == pre)
|
||||
{
|
||||
fol->lb = ipa_from_u32(rtl->data);
|
||||
return 1;
|
||||
|
@ -428,7 +502,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
|
|||
rts = (u32 *) (ln + 1);
|
||||
for (i = 0; i < lsa_net_count(&fol->lsa); i++)
|
||||
{
|
||||
if (ospfxx_hash_find(po->gr, oa->areaid, *(rts + i), *(rts + i), LSA_T_RT) == pre)
|
||||
if (ospf_hash_find(po->gr, oa->areaid, *(rts + i), *(rts + i), LSA_T_RT) == pre)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -439,6 +513,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ospf_rt_sum_tr(struct ospf_area *oa)
|
||||
|
@ -481,8 +556,10 @@ ospf_rt_sum_tr(struct ospf_area *oa)
|
|||
ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
|
||||
#else /* OSPFv3 */
|
||||
u8 pxopts;
|
||||
u16 rest;
|
||||
struct ospf_lsa_sum_net *ls = en->lsa_body;
|
||||
get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts);
|
||||
get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts, &rest);
|
||||
|
||||
if (pxopts & OPT_PX_NU)
|
||||
continue;
|
||||
#endif
|
||||
|
@ -578,8 +655,10 @@ ospf_rt_sum(struct ospf_area *oa)
|
|||
ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
|
||||
#else /* OSPFv3 */
|
||||
u8 pxopts;
|
||||
u16 rest;
|
||||
struct ospf_lsa_sum_net *ls = en->lsa_body;
|
||||
get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts);
|
||||
get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts, &rest);
|
||||
|
||||
if (pxopts & OPT_PX_NU)
|
||||
continue;
|
||||
#endif
|
||||
|
@ -779,8 +858,9 @@ ospf_ext_spf(struct proto_ospf *po)
|
|||
rt_tag = le->tag;
|
||||
#else /* OSPFv3 */
|
||||
u8 pxopts;
|
||||
u16 rest;
|
||||
u32 *buf = le->rest;
|
||||
buf = get_ipv6_prefix(buf, &ip, &pxlen, &pxopts);
|
||||
buf = get_ipv6_prefix(buf, &ip, &pxlen, &pxopts, &rest);
|
||||
|
||||
if (pxopts & OPT_PX_NU)
|
||||
continue;
|
||||
|
@ -893,11 +973,21 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
|
|||
int added = 0;
|
||||
struct top_hash_entry *act;
|
||||
|
||||
/* 16.1. (2b) */
|
||||
if (en == NULL)
|
||||
return;
|
||||
if (en->lsa.age == LSA_MAXAGE)
|
||||
return;
|
||||
|
||||
#ifdef OSPFv3
|
||||
if (en->lsa.type == LSA_T_RT)
|
||||
{
|
||||
struct ospf_lsa_rt *rt = en->lsa_body;
|
||||
if (!(rt->options & OPT_V6) || !(rt->options & OPT_R))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 16.1. (2c) */
|
||||
if (en->color == INSPF)
|
||||
return;
|
||||
|
@ -910,16 +1000,15 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
|
|||
* next hops. I'll start as soon as nest will
|
||||
*/
|
||||
|
||||
/* FIXME - fix link_back()
|
||||
if (!link_back(oa, en, par))
|
||||
return;
|
||||
*/
|
||||
|
||||
DBG(" Adding candidate: rt: %R, id: %R, type: %u\n",
|
||||
en->lsa.rt, en->lsa.id, en->lsa.type);
|
||||
|
||||
en->nhi = NULL;
|
||||
en->nh = IPA_NONE;
|
||||
|
||||
calc_next_hop(en, par, oa);
|
||||
calc_next_hop(oa, en, par);
|
||||
|
||||
if (!en->nhi)
|
||||
return; /* We cannot find next hop, ignore it */
|
||||
|
@ -963,21 +1052,33 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
match_dr(struct ospf_iface *ifa, struct top_hash_entry *en)
|
||||
{
|
||||
#ifdef OSPFv2
|
||||
return (ifa->drid == en->lsa.rt) && (ifa->drip == ipa_from_u32(en->lsa.id));
|
||||
#else /* OSPFv3 */
|
||||
return (ifa->drid == en->lsa.rt) && (ifa->dr_iface_id == en->lsa.id);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
|
||||
struct ospf_area *oa)
|
||||
calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
|
||||
struct top_hash_entry *par)
|
||||
{
|
||||
struct ospf_neighbor *neigh;
|
||||
struct proto *p = &oa->po->proto;
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct ospf_iface *ifa;
|
||||
u32 myrid = p->cf->global->router_id;
|
||||
|
||||
en->nhi = NULL;
|
||||
en->nh = IPA_NONE;
|
||||
|
||||
/* 16.1.1. The next hop calculation */
|
||||
DBG(" Next hop called.\n");
|
||||
if (ipa_equal(par->nh, IPA_NONE))
|
||||
{
|
||||
neighbor *nn;
|
||||
DBG(" Next hop calculating for id: %R rt: %R type: %u\n",
|
||||
en->lsa.id, en->lsa.rt, en->lsa.type);
|
||||
|
||||
|
@ -985,37 +1086,22 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
|
|||
if (par == oa->rt)
|
||||
{
|
||||
if (en->lsa.type == LSA_T_NET)
|
||||
{
|
||||
if (en->lsa.rt == myrid)
|
||||
{
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
if (ifa->iface && (ipa_compare
|
||||
(ifa->iface->addr->ip, ipa_from_u32(en->lsa.id)) == 0))
|
||||
if (match_dr(ifa, en))
|
||||
{
|
||||
en->nhi = ifa;
|
||||
return;
|
||||
}
|
||||
log(L_ERR "I didn't find interface for my self originated LSA!\n");
|
||||
/* This could sometimes happen */
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ip_addr ip = ipa_from_u32(en->lsa.id);
|
||||
nn = neigh_find(p, &ip, 0);
|
||||
if (nn)
|
||||
en->nhi = ospf_iface_find(po, nn->iface);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
|
||||
return;
|
||||
en->nhi = neigh->ifa;
|
||||
if (ipa_equal(en->nh, IPA_NONE))
|
||||
en->nh = neigh->ip; /* Yes, neighbor is it's
|
||||
* own next hop */
|
||||
en->nh = neigh->ip;
|
||||
/* Yes, neighbor is it's own next hop */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1028,11 +1114,12 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
|
|||
bug("Parent for net is net?");
|
||||
if ((en->nhi = par->nhi) == NULL)
|
||||
bug("Did not find next hop interface for INSPF lsa!");
|
||||
|
||||
if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
|
||||
return;
|
||||
en->nhi = neigh->ifa;
|
||||
en->nh = neigh->ip; /* Yes, neighbor is it's own
|
||||
* next hop */
|
||||
en->nh = neigh->ip;
|
||||
/* Yes, neighbor is it's own next hop */
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -1043,8 +1130,8 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
|
|||
return;
|
||||
}
|
||||
}
|
||||
en->nh = par->nh;
|
||||
en->nhi = par->nhi;
|
||||
en->nh = par->nh;
|
||||
DBG(" Next hop calculated: %I.\n", en->nh);
|
||||
}
|
||||
|
||||
|
@ -1098,7 +1185,7 @@ again1:
|
|||
if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh))
|
||||
{
|
||||
/* FIXME in OSPFv3, may be different LSA ID */
|
||||
if ((en = ospfxx_hash_find(po->gr, ifa->voa->areaid, ifa->vid, ifa->vid, LSA_T_RT))
|
||||
if ((en = ospf_hash_find(po->gr, ifa->voa->areaid, ifa->vid, ifa->vid, LSA_T_RT))
|
||||
&& (!ipa_equal(en->nh, IPA_NONE)))
|
||||
{
|
||||
a0.gw = en->nh;
|
||||
|
|
|
@ -20,6 +20,23 @@
|
|||
#define HASH_LO_STEP 2
|
||||
#define HASH_LO_MIN 8
|
||||
|
||||
void originate_prefix_rt_lsa(struct ospf_area *oa);
|
||||
void originate_prefix_net_lsa(struct ospf_iface *ifa);
|
||||
|
||||
#ifdef OSPFv2
|
||||
#define ipa_to_rid(x) _I(x)
|
||||
#else /* OSPFv3 */
|
||||
#define ipa_to_rid(x) _I3(x)
|
||||
#endif
|
||||
|
||||
/* FIXME very ugly hack */
|
||||
#ifdef OSPFv2
|
||||
#define ipa_to_lsaid(x) _I(x)
|
||||
#else /* OSPFv3 */
|
||||
#define ipa_to_lsaid(x) _I0(x) ^ _I1(x) ^ _I2(x) ^ _I3(x)
|
||||
#endif
|
||||
|
||||
|
||||
static void *
|
||||
lsab_alloc(struct proto_ospf *po, unsigned size)
|
||||
{
|
||||
|
@ -300,7 +317,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
|||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct ospf_iface *ifa;
|
||||
int i = 0, j = 0, k = 0, bitv = 0;
|
||||
int bitv = 0;
|
||||
struct ospf_lsa_rt *rt;
|
||||
struct ospf_neighbor *neigh;
|
||||
|
||||
|
@ -390,18 +407,9 @@ originate_rt_lsa(struct ospf_area *oa)
|
|||
struct ospf_lsa_header lsa;
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
u32 rtid = po->proto.cf->global->router_id;
|
||||
struct top_hash_entry *en;
|
||||
u32 rid = po->proto.cf->global->router_id;
|
||||
void *body;
|
||||
|
||||
if ((oa->rt) && ((oa->rt->inst_t + MINLSINTERVAL)) > now)
|
||||
return;
|
||||
/*
|
||||
* Tick is probably set to very low value. We cannot
|
||||
* originate new LSA before MINLSINTERVAL. We will
|
||||
* try to do it next tick.
|
||||
*/
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Originating RT_lsa for area %R.", oa->areaid);
|
||||
|
||||
lsa.age = 0;
|
||||
|
@ -411,16 +419,33 @@ originate_rt_lsa(struct ospf_area *oa)
|
|||
lsa.options = oa->options;
|
||||
#endif
|
||||
|
||||
lsa.id = rtid;
|
||||
lsa.rt = rtid;
|
||||
lsa.id = rid;
|
||||
lsa.rt = rid;
|
||||
lsa.sn = oa->rt ? (oa->rt->lsa.sn + 1) : LSA_INITSEQNO;
|
||||
u32 dom = oa->areaid;
|
||||
|
||||
body = originate_rt_lsa_body(oa, &lsa.length);
|
||||
lsasum_calculate(&lsa, body);
|
||||
en = lsa_install_new(po, &lsa, dom, body);
|
||||
oa->rt = en;
|
||||
ospf_lsupd_flood(po, NULL, NULL, &oa->rt->lsa, dom, 1);
|
||||
oa->rt = lsa_install_new(po, &lsa, dom, body);
|
||||
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
|
||||
}
|
||||
|
||||
void
|
||||
update_rt_lsa(struct ospf_area *oa)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
|
||||
if ((oa->rt) && ((oa->rt->inst_t + MINLSINTERVAL)) > now)
|
||||
return;
|
||||
/*
|
||||
* Tick is probably set to very low value. We cannot
|
||||
* originate new LSA before MINLSINTERVAL. We will
|
||||
* try to do it next tick.
|
||||
*/
|
||||
|
||||
originate_rt_lsa(oa);
|
||||
originate_prefix_rt_lsa(oa);
|
||||
|
||||
schedule_rtcalc(po);
|
||||
oa->origrt = 0;
|
||||
}
|
||||
|
@ -454,7 +479,7 @@ originate_net_lsa_body(struct ospf_iface *ifa, u16 *length,
|
|||
if (n->state == NEIGHBOR_FULL)
|
||||
{
|
||||
#ifdef OSPFv3
|
||||
en = ospfxx_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK);
|
||||
en = ospf_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK);
|
||||
if (en)
|
||||
options |= ((struct ospf_lsa_link *) en->lsa_body)->options;
|
||||
#endif
|
||||
|
@ -474,6 +499,7 @@ originate_net_lsa_body(struct ospf_iface *ifa, u16 *length,
|
|||
return net;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* originate_net_lsa - originates of deletes network LSA
|
||||
* @ifa: interface which is LSA originated for
|
||||
|
@ -488,39 +514,11 @@ originate_net_lsa(struct ospf_iface *ifa)
|
|||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct ospf_lsa_header lsa;
|
||||
u32 rtid = po->proto.cf->global->router_id;
|
||||
u32 rid = po->proto.cf->global->router_id;
|
||||
u32 dom = ifa->oa->areaid;
|
||||
struct proto *p = &po->proto;
|
||||
void *body;
|
||||
|
||||
if (ifa->net_lsa && ((ifa->net_lsa->inst_t + MINLSINTERVAL) > now))
|
||||
return;
|
||||
/*
|
||||
* It's too early to originate new network LSA. We will
|
||||
* try to do it next tick
|
||||
*/
|
||||
|
||||
if ((ifa->state != OSPF_IS_DR) || (ifa->fadj == 0))
|
||||
{
|
||||
if (ifa->net_lsa == NULL)
|
||||
return;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Deleting Net lsa for iface \"%s\".",
|
||||
ifa->iface->name);
|
||||
ifa->net_lsa->lsa.sn += 1;
|
||||
ifa->net_lsa->lsa.age = LSA_MAXAGE;
|
||||
lsasum_calculate(&ifa->net_lsa->lsa, ifa->net_lsa->lsa_body);
|
||||
ospf_lsupd_flood(po, NULL, NULL, &ifa->net_lsa->lsa, dom, 0);
|
||||
s_rem_node(SNODE ifa->net_lsa);
|
||||
if (ifa->net_lsa->lsa_body != NULL)
|
||||
mb_free(ifa->net_lsa->lsa_body);
|
||||
ifa->net_lsa->lsa_body = NULL;
|
||||
ospf_hash_delete(po->gr, ifa->net_lsa);
|
||||
schedule_rtcalc(po);
|
||||
ifa->net_lsa = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Originating Net lsa for iface \"%s\".",
|
||||
ifa->iface->name);
|
||||
|
||||
|
@ -534,16 +532,63 @@ originate_net_lsa(struct ospf_iface *ifa)
|
|||
lsa.id = ifa->iface->index;
|
||||
#endif
|
||||
|
||||
lsa.rt = rtid;
|
||||
lsa.rt = rid;
|
||||
lsa.sn = ifa->net_lsa ? (ifa->net_lsa->lsa.sn + 1) : LSA_INITSEQNO;
|
||||
|
||||
body = originate_net_lsa_body(ifa, &lsa.length, po);
|
||||
lsasum_calculate(&lsa, body);
|
||||
ifa->net_lsa = lsa_install_new(po, &lsa, dom, body);
|
||||
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
|
||||
ifa->orignet = 0;
|
||||
}
|
||||
|
||||
void
|
||||
flush_net_lsa(struct ospf_iface *ifa)
|
||||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
u32 dom = ifa->oa->areaid;
|
||||
|
||||
if (ifa->net_lsa == NULL)
|
||||
return;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Deleting Net lsa for iface \"%s\".",
|
||||
ifa->iface->name);
|
||||
ifa->net_lsa->lsa.sn += 1;
|
||||
ifa->net_lsa->lsa.age = LSA_MAXAGE;
|
||||
lsasum_calculate(&ifa->net_lsa->lsa, ifa->net_lsa->lsa_body);
|
||||
ospf_lsupd_flood(po, NULL, NULL, &ifa->net_lsa->lsa, dom, 0);
|
||||
|
||||
|
||||
flush_lsa(ifa->net_lsa, po);
|
||||
ifa->net_lsa = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
update_net_lsa(struct ospf_iface *ifa)
|
||||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
if (ifa->net_lsa && ((ifa->net_lsa->inst_t + MINLSINTERVAL) > now))
|
||||
return;
|
||||
/*
|
||||
* It's too early to originate new network LSA. We will
|
||||
* try to do it next tick
|
||||
*/
|
||||
|
||||
if ((ifa->state != OSPF_IS_DR) || (ifa->fadj == 0))
|
||||
{
|
||||
flush_net_lsa(ifa);
|
||||
flush_prefix_net_lsa(ifa);
|
||||
}
|
||||
else
|
||||
{
|
||||
originate_net_lsa(ifa);
|
||||
originate_prefix_net_lsa(ifa);
|
||||
}
|
||||
|
||||
schedule_rtcalc(po);
|
||||
ifa->orignet = 0;
|
||||
}
|
||||
|
||||
#ifdef OSPFv2
|
||||
|
||||
|
@ -630,7 +675,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
|
|||
u32 dom = oa->areaid;
|
||||
|
||||
/* FIXME check for the same LSA */
|
||||
if ((en = ospfxx_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
|
||||
if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
|
||||
lsa.sn = en->lsa.sn + 1;
|
||||
|
||||
if (type == ORT_NET)
|
||||
|
@ -677,7 +722,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
|
|||
lsa.type = LSA_T_SUM_RT;
|
||||
}
|
||||
|
||||
if ((en = ospfxx_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
|
||||
if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
|
||||
{
|
||||
struct ospf_lsa_sum *sum = en->lsa_body;
|
||||
en->lsa.age = LSA_MAXAGE;
|
||||
|
@ -733,10 +778,12 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
|
|||
mlen = nf->fn.pxlen;
|
||||
ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen));
|
||||
|
||||
if ((oa == po->backbone) && (nf->n.type == RTS_OSPF_IA)) flush = 1; /* Only intra-area can go to the backbone */
|
||||
if ((oa == po->backbone) && (nf->n.type == RTS_OSPF_IA))
|
||||
flush = 1; /* Only intra-area can go to the backbone */
|
||||
|
||||
if ((!flush) && (dest == ORT_NET) && fib_route(&nf->n.oa->net_fib, ip, mlen)) /* The route fits into area networks */
|
||||
if ((!flush) && (dest == ORT_NET) && fib_route(&nf->n.oa->net_fib, ip, mlen))
|
||||
{
|
||||
/* The route fits into area networks */
|
||||
flush = 1;
|
||||
if ((nf->n.oa == po->backbone) && (oa->trcap)) flush = 0;
|
||||
}
|
||||
|
@ -833,8 +880,6 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
|||
void *body;
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_area *oa;
|
||||
struct ospf_lsa_ext *ext1, *ext2;
|
||||
int i, max;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Originating Ext lsa for %I/%d.", n->n.prefix,
|
||||
n->n.pxlen);
|
||||
|
@ -850,7 +895,7 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
|||
/* FIXME proper handling of LSA IDs and check for the same network */
|
||||
lsa.id = ipa_to_lsaid(n->n.prefix);
|
||||
|
||||
if ((en = ospfxx_hash_find_header(po->gr, 0, &lsa)) != NULL)
|
||||
if ((en = ospf_hash_find_header(po->gr, 0, &lsa)) != NULL)
|
||||
{
|
||||
lsa.sn = en->lsa.sn + 1;
|
||||
}
|
||||
|
@ -877,13 +922,11 @@ flush_ext_lsa(net *n, struct proto_ospf *po)
|
|||
u32 rid = po->proto.cf->global->router_id;
|
||||
struct ospf_area *oa;
|
||||
struct top_hash_entry *en;
|
||||
struct ospf_lsa_ext *ext;
|
||||
int i;
|
||||
|
||||
/* FIXME proper handling of LSA IDs and check for the same network */
|
||||
u32 lsaid = ipa_to_lsaid(n->n.prefix);
|
||||
|
||||
if (en = ospfxx_hash_find(po->gr, 0, lsaid, rid, LSA_T_EXT))
|
||||
if (en = ospf_hash_find(po->gr, 0, lsaid, rid, LSA_T_EXT))
|
||||
{
|
||||
/* FIXME this is nonsense */
|
||||
WALK_LIST(oa, po->area_list)
|
||||
|
@ -907,7 +950,7 @@ originate_link_lsa_body(struct ospf_iface *ifa, u16 *length)
|
|||
ASSERT(po->lsab_used == 0);
|
||||
ll = lsab_allocz(po, sizeof(struct ospf_lsa_link));
|
||||
ll->options = ifa->oa->options | (ifa->priority << 24);
|
||||
ll->lladdr = FIX;
|
||||
ll->lladdr = ifa->lladdr;
|
||||
ll = NULL; /* buffer might be reallocated later */
|
||||
|
||||
struct ifa *a;
|
||||
|
@ -935,23 +978,16 @@ originate_link_lsa(struct ospf_iface *ifa)
|
|||
struct ospf_lsa_header lsa;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
u32 rtid = po->proto.cf->global->router_id;
|
||||
u32 rid = po->proto.cf->global->router_id;
|
||||
void *body;
|
||||
|
||||
if (ifa->link_lsa && ((ifa->link_lsa->inst_t + MINLSINTERVAL) > now))
|
||||
return;
|
||||
/*
|
||||
* It's too early to originate new link LSA. We will
|
||||
* try to do it next tick
|
||||
*/
|
||||
|
||||
/* FIXME check for vlink and skip that? */
|
||||
OSPF_TRACE(D_EVENTS, "Originating Link_lsa for iface %s.", ifa->iface->name);
|
||||
|
||||
lsa.age = 0;
|
||||
lsa.type = LSA_T_LINK;
|
||||
lsa.id = ifa->iface->index;
|
||||
lsa.rt = rtid;
|
||||
lsa.rt = rid;
|
||||
lsa.sn = ifa->link_lsa ? (ifa->link_lsa->lsa.sn + 1) : LSA_INITSEQNO;
|
||||
u32 dom = ifa->iface->index;
|
||||
|
||||
|
@ -959,9 +995,20 @@ originate_link_lsa(struct ospf_iface *ifa)
|
|||
lsasum_calculate(&lsa, body);
|
||||
ifa->link_lsa = lsa_install_new(po, &lsa, dom, body);
|
||||
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
|
||||
ifa->origlink = 0;
|
||||
}
|
||||
|
||||
void
|
||||
update_link_lsa(struct ospf_iface *ifa)
|
||||
{
|
||||
if (ifa->link_lsa && ((ifa->link_lsa->inst_t + MINLSINTERVAL) > now))
|
||||
return;
|
||||
/*
|
||||
* It's too early to originate new link LSA. We will
|
||||
* try to do it next tick
|
||||
*/
|
||||
originate_link_lsa(ifa);
|
||||
ifa->origlink = 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||
|
@ -1129,7 +1176,7 @@ originate_prefix_net_lsa_body(struct ospf_iface *ifa, u16 *length)
|
|||
/* Find all Link LSA associated with the link and merge their prefixes */
|
||||
WALK_LIST(n, ifa->neigh_list)
|
||||
if ((n->state == NEIGHBOR_FULL) &&
|
||||
(en = ospfxx_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK)))
|
||||
(en = ospf_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK)))
|
||||
{
|
||||
ll = en->lsa_body;
|
||||
pxb = ll->rest;
|
||||
|
@ -1170,6 +1217,7 @@ originate_prefix_net_lsa(struct ospf_iface *ifa)
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
ospf_top_ht_alloc(struct top_graph *f)
|
||||
{
|
||||
|
@ -1263,7 +1311,7 @@ ospf_top_rehash(struct top_graph *f, int step)
|
|||
|
||||
oldn = f->hash_size;
|
||||
oldt = f->hash_table;
|
||||
dbg("re-hashing topology hash from order %d to %d\n", f->hash_order,
|
||||
DBG("re-hashing topology hash from order %d to %d\n", f->hash_order,
|
||||
f->hash_order + step);
|
||||
f->hash_order += step;
|
||||
ospf_top_ht_alloc(f);
|
||||
|
@ -1284,20 +1332,37 @@ ospf_top_rehash(struct top_graph *f, int step)
|
|||
ospf_top_ht_free(oldt);
|
||||
}
|
||||
|
||||
struct top_hash_entry *
|
||||
ospfxx_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
|
||||
u32
|
||||
ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
|
||||
{
|
||||
return ospfxx_hash_find(f, domain, h->id, h->rt, h->type);
|
||||
switch (type & LSA_SCOPE_MASK)
|
||||
{
|
||||
case LSA_SCOPE_LINK:
|
||||
return ifa->iface->index;
|
||||
|
||||
case LSA_SCOPE_AREA:
|
||||
return ifa->oa->areaid;
|
||||
|
||||
case LSA_SCOPE_AS:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct top_hash_entry *
|
||||
ospfxx_hash_get_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
|
||||
ospf_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
|
||||
{
|
||||
return ospfxx_hash_get(f, domain, h->id, h->rt, h->type);
|
||||
return ospf_hash_find(f, domain, h->id, h->rt, h->type);
|
||||
}
|
||||
|
||||
struct top_hash_entry *
|
||||
ospfxx_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
||||
ospf_hash_get_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
|
||||
{
|
||||
return ospf_hash_get(f, domain, h->id, h->rt, h->type);
|
||||
}
|
||||
|
||||
struct top_hash_entry *
|
||||
ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
||||
{
|
||||
struct top_hash_entry *e;
|
||||
|
||||
|
@ -1322,7 +1387,7 @@ ospfxx_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
|||
}
|
||||
|
||||
struct top_hash_entry *
|
||||
ospfxx_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
||||
ospf_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
||||
{
|
||||
struct top_hash_entry **ee;
|
||||
struct top_hash_entry *e;
|
||||
|
@ -1379,6 +1444,7 @@ ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e)
|
|||
static void
|
||||
ospf_dump_lsa(struct top_hash_entry *he, struct proto *p)
|
||||
{
|
||||
/*
|
||||
struct ospf_lsa_rt *rt = NULL;
|
||||
struct ospf_lsa_rt_link *rr = NULL;
|
||||
struct ospf_lsa_net *ln = NULL;
|
||||
|
@ -1389,7 +1455,7 @@ ospf_dump_lsa(struct top_hash_entry *he, struct proto *p)
|
|||
he->lsa.type, he->lsa.id, he->lsa.rt, he->lsa.age, he->lsa.sn,
|
||||
he->lsa.checksum, he->domain);
|
||||
|
||||
/*
|
||||
|
||||
switch (he->lsa.type)
|
||||
{
|
||||
case LSA_T_RT:
|
||||
|
|
|
@ -47,27 +47,27 @@ struct top_graph
|
|||
struct top_graph *ospf_top_new(pool *);
|
||||
void ospf_top_free(struct top_graph *);
|
||||
void ospf_top_dump(struct top_graph *, struct proto *);
|
||||
struct top_hash_entry *ospfxx_hash_find_header(struct top_graph *f, u32 areaid,
|
||||
u32 ospf_lsa_domain(u32 type, struct ospf_iface *ifa);
|
||||
struct top_hash_entry *ospf_hash_find_header(struct top_graph *f, u32 domain,
|
||||
struct ospf_lsa_header *h);
|
||||
struct top_hash_entry *ospfxx_hash_get_header(struct top_graph *f, u32 domain,
|
||||
struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, u32 domain,
|
||||
struct ospf_lsa_header *h);
|
||||
|
||||
struct top_hash_entry *ospfxx_hash_find_smart(struct top_graph *f, struct ospf_iface *ifa,
|
||||
struct ospf_lsa_header *h);
|
||||
struct top_hash_entry *ospfxx_hash_get_smart(struct top_graph *f, struct ospf_iface *ifa,
|
||||
struct ospf_lsa_header *h);
|
||||
|
||||
struct top_hash_entry *ospfxx_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
|
||||
struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
|
||||
u32 type);
|
||||
struct top_hash_entry *ospfxx_hash_get(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
|
||||
struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
|
||||
u32 type);
|
||||
void ospf_hash_delete(struct top_graph *, struct top_hash_entry *);
|
||||
void originate_rt_lsa(struct ospf_area *oa);
|
||||
void update_rt_lsa(struct ospf_area *oa);
|
||||
void originate_net_lsa(struct ospf_iface *ifa);
|
||||
void update_net_lsa(struct ospf_iface *ifa);
|
||||
void update_link_lsa(struct ospf_iface *ifa);
|
||||
int can_flush_lsa(struct proto_ospf *po);
|
||||
int max_ext_lsa(unsigned pxlen);
|
||||
void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
||||
struct ea_list *attrs);
|
||||
void flush_ext_lsa(net *n, struct proto_ospf *po);
|
||||
void check_sum_lsa(struct proto_ospf *po, ort *nf, int);
|
||||
void originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric, u32 options);
|
||||
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
|
||||
|
|
|
@ -390,7 +390,6 @@ nl_parse_addr(struct nlmsghdr *h)
|
|||
else
|
||||
{
|
||||
ip_addr netmask = ipa_mkmask(ifa.pxlen);
|
||||
ip_addr xbrd;
|
||||
ifa.prefix = ipa_and(ifa.ip, netmask);
|
||||
ifa.brd = ipa_or(ifa.ip, ipa_not(netmask));
|
||||
#ifndef IPV6
|
||||
|
@ -398,6 +397,7 @@ nl_parse_addr(struct nlmsghdr *h)
|
|||
ifa.opposite = ipa_opposite(ifa.ip, i->ifa_prefixlen);
|
||||
if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
|
||||
{
|
||||
ip_addr xbrd;
|
||||
memcpy(&xbrd, RTA_DATA(a[IFA_BROADCAST]), sizeof(xbrd));
|
||||
ipa_ntoh(xbrd);
|
||||
if (ipa_equal(xbrd, ifa.prefix) || ipa_equal(xbrd, ifa.brd))
|
||||
|
|
Loading…
Reference in a new issue