From b49e6f5a65d437cb7e7bdefe8397e0f550496012 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Tue, 25 Aug 2009 16:42:14 +0200 Subject: [PATCH] Temporary OSPFv3 development commit --- filter/filter.h | 1 + filter/trie.c | 2 +- lib/ipv6.c | 54 ++++++++ lib/ipv6.h | 1 + nest/a-path.c | 2 +- nest/rt-attr.c | 2 - proto/bgp/attrs.c | 2 + proto/bgp/packets.c | 1 - proto/ospf/dbdes.c | 10 +- proto/ospf/hello.c | 1 - proto/ospf/iface.c | 17 +++ proto/ospf/lsack.c | 3 +- proto/ospf/lsalib.c | 5 +- proto/ospf/lsreq.c | 2 +- proto/ospf/lsupd.c | 22 +-- proto/ospf/neighbor.c | 24 ++-- proto/ospf/ospf.c | 20 ++- proto/ospf/ospf.h | 5 +- proto/ospf/packet.c | 2 +- proto/ospf/rt.c | 243 ++++++++++++++++++++++----------- proto/ospf/topology.c | 224 +++++++++++++++++++----------- proto/ospf/topology.h | 18 +-- sysdep/linux/netlink/netlink.c | 2 +- 23 files changed, 449 insertions(+), 214 deletions(-) diff --git a/filter/filter.h b/filter/filter.h index 2277f519..8e0d1793 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -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); diff --git a/filter/trie.c b/filter/trie.c index ffb9b99f..2257c8b6 100644 --- a/filter/trie.c +++ b/filter/trie.c @@ -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); diff --git a/lib/ipv6.c b/lib/ipv6.c index 88c54eb6..3334b976 100644 --- a/lib/ipv6.c +++ b/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 diff --git a/lib/ipv6.h b/lib/ipv6.h index 9cec86e7..d2b77c01 100644 --- a/lib/ipv6.h +++ b/lib/ipv6.h @@ -1,3 +1,4 @@ + /* * BIRD -- IP Addresses et Cetera for IPv6 * diff --git a/nest/a-path.c b/nest/a-path.c index dba214d2..5aacf8f2 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -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) diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 8daebae0..de63198e 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -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; mcount; m++) if (e->attrs[m].id == id) return &e->attrs[m]; diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 68f21b97..d0ec41f9 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1131,6 +1131,8 @@ as4_aggregator_valid(struct adata *aggr) if ((a[0] == 0) || (a[1] == 0)) return 0; + + return 1; } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index ae4906ee..ac697be1 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -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) { diff --git a/proto/ospf/dbdes.c b/proto/ospf/dbdes.c index 31075791..9be8e61f 100644 --- a/proto/ospf/dbdes.c +++ b/proto/ospf/dbdes.c @@ -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); } diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index 7eeee3b3..cce256fc 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -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; diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index ea3baa23..cae36ad3 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -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; diff --git a/proto/ospf/lsack.c b/proto/ospf/lsack.c index 7871b8f4..dc942197 100644 --- a/proto/ospf/lsack.c +++ b/proto/ospf/lsack.c @@ -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 */ diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index 7c4001d9..4cbabcc1 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -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 diff --git a/proto/ospf/lsreq.c b/proto/ospf/lsreq.c index cc5afa0f..aafc190e 100644 --- a/proto/ospf/lsreq.c +++ b/proto/ospf/lsreq.c @@ -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", diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c index 8c26f548..efaafe86 100644 --- a/proto/ospf/lsupd.c +++ b/proto/ospf/lsupd.c @@ -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); diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index d86895ed..374da636 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -173,16 +173,16 @@ electbdr(list nl) struct ospf_neighbor *neigh, *n1, *n2; u32 nid; -#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 */ { +#ifdef OSPFv2 + nid = ipa_to_u32(neigh->ip); +#else /* OSPFv3 */ + nid = neigh->rid; +#endif + 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; -#ifdef OSPFv2 - nid = ipa_to_u32(neigh->ip); -#else /* OSPFv3 */ - nid = neigh->rid; -#endif - n = NULL; WALK_LIST(neigh, nl) /* And now DR */ { +#ifdef OSPFv2 + nid = ipa_to_u32(neigh->ip); +#else /* OSPFv3 */ + nid = neigh->rid; +#endif + if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */ if (neigh->priority > 0) /* Eligible */ if (neigh->dr == nid) /* And declaring itself DR */ diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 2ee6e631..438e9a54 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -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); diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 1e46d3be..da0104de 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -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; }; diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index e3a3115b..200ef958 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -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) { diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index e64e68af..677ce5b4 100644 --- a/proto/ospf/rt.c +++ b/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,20 +299,22 @@ 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)) - { - nf.type = RTS_OSPF; - nf.options = rt->options; - 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_from_rid(act->lsa.rt), 32, ORT_ROUTER, &nf, NULL); - } + { + nf.type = RTS_OSPF; + nf.options = rt->options; + 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_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); @@ -986,36 +1087,21 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par, { 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)) + WALK_LIST(ifa, po->iface_list) + if (match_dr(ifa, en)) { - en->nhi = ifa; - return; + 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; - } + 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; diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 21627f05..360e3627 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -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: diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h index 4555bea2..5bb3397a 100644 --- a/proto/ospf/topology.h +++ b/proto/ospf/topology.h @@ -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); diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c index 2e85f54b..b7fd479b 100644 --- a/sysdep/linux/netlink/netlink.c +++ b/sysdep/linux/netlink/netlink.c @@ -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))