diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index d3145b9f..5711ac5f 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -24,7 +24,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps, mask = ps->netmask; ipa_ntoh(mask); - if (((ifa->type != OSPF_IT_VLINK) || (ifa->type != OSPF_IT_PTP)) && + if (((ifa->type != OSPF_IT_VLINK) && (ifa->type != OSPF_IT_PTP)) && ((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen)) { log(L_ERR "%s%I%sbad netmask %I.", beg, faddr, rec, mask); diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index af6b8534..0339ec2d 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -115,6 +115,7 @@ neigh_chstate(struct ospf_neighbor *n, u8 state) { ifa->fadj--; schedule_rt_lsa(ifa->oa); + if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa); schedule_net_lsa(ifa); } @@ -507,7 +508,7 @@ find_neigh(struct ospf_iface *ifa, u32 rid) } -/* Find a closest neighbor which is at leas 2-Way */ +/* Find a closest neighbor which is at least 2-Way */ struct ospf_neighbor * find_neigh_noifa(struct proto_ospf *po, u32 rid) { diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index e9e45d76..c753503b 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -153,13 +153,29 @@ ospf_start(struct proto *p) } /* Add all virtual links as interfaces */ - if(po->backbone) { struct ospf_iface_patt *ipatt; WALK_LIST(ac, c->area_list) { WALK_LIST(ipatt, ac->vlink_list) + { + if(!po->backbone) + { + oa = mb_allocz(p->pool, sizeof(struct ospf_area)); + add_tail(&po->area_list, NODE oa); + po->areano++; + oa->stub = 0; + oa->areaid = 0; + oa->rt = NULL; + oa->po = po; + fib_init(&oa->net_fib, p->pool, sizeof(struct area_net), 16, ospf_area_initfib); + fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort); + po->backbone = oa; + oa->opt.byte = 0; + oa->opt.bit.e = 1; + } ospf_iface_new(po, NULL, ac, ipatt); + } } } return PS_UP; diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index f6b68fd4..6a334d0d 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -149,7 +149,8 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_ } if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE != size) { - OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch"); + OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %s)", + ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE, size); return 0; } @@ -356,7 +357,7 @@ ospf_tx_hook(sock * sk) { struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); struct proto *p = (struct proto *) (ifa->oa->po); - DBG("%s: TX_Hook called on interface %s\n", p->name, sk->iface->name); + log(L_ERR "%s: TX_Hook called on interface %s\n", p->name, sk->iface->name); } void @@ -364,7 +365,7 @@ ospf_err_hook(sock * sk, int err UNUSED) { struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); struct proto *p = (struct proto *) (ifa->oa->po); - DBG("%s: Err_Hook called on interface %s\n", p->name, sk->iface->name); + log(L_ERR "%s: Err_Hook called on interface %s\n", p->name, sk->iface->name); } void diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index ca1f58d1..77627f91 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -7,9 +7,10 @@ */ #include "ospf.h" + static void add_cand(list * l, struct top_hash_entry *en, - struct top_hash_entry *par, u16 dist, struct ospf_area *oa, int vlink); + struct top_hash_entry *par, u16 dist, struct ospf_area *oa); static void calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par, struct ospf_area *oa); @@ -145,7 +146,6 @@ ospf_rt_spfa(struct ospf_area *oa) struct ospf_iface *iface; struct top_hash_entry *act, *tmp; node *n; - int vlink; if (oa->rt == NULL) @@ -202,7 +202,6 @@ ospf_rt_spfa(struct ospf_area *oa) DBG(" Number of links: %u\n", rt->links); for (i = 0; i < rt->links; i++) { - vlink = 0; tmp = NULL; rtl = (rr + i); DBG(" Working on link: %I (type: %u) ", rtl->id, rtl->type); @@ -230,10 +229,10 @@ ospf_rt_spfa(struct ospf_area *oa) WALK_LIST(iff, po->iface_list) { - if (rtl->id == (ipa_to_u32(ipa_mkmask(iff->iface->addr->pxlen)) - & ipa_to_u32(iff->iface->addr->prefix))) + if (iff->iface && (rtl->id == (ipa_to_u32(ipa_mkmask(iff->iface->addr->pxlen)) + & ipa_to_u32(iff->iface->addr->prefix)))) { - nf.ifa = iff->iface; + nf.ifa = iff; break; } } @@ -256,7 +255,6 @@ ospf_rt_spfa(struct ospf_area *oa) break; case LSART_VLNK: - vlink = 1; case LSART_PTP: tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT); DBG("PTP found.\n"); @@ -268,7 +266,7 @@ ospf_rt_spfa(struct ospf_area *oa) if (tmp) DBG("Going to add cand, Mydist: %u, Req: %u\n", tmp->dist, act->dist + rtl->metric); - add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa, vlink); + add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa); } break; case LSA_T_NET: @@ -294,7 +292,7 @@ ospf_rt_spfa(struct ospf_area *oa) DBG("Found :-)\n"); else DBG("Not found!\n"); - add_cand(&oa->cand, tmp, act, act->dist, oa, 0); + add_cand(&oa->cand, tmp, act, act->dist, oa); } break; } @@ -308,11 +306,11 @@ ospf_rt_spfa(struct ospf_area *oa) 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) || (!ipa_equal(iface->vip, tmp->lb))) + if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi->iface) || (!ipa_equal(iface->vip, tmp->lb))) { OSPF_TRACE(D_EVENTS, "Vlink peer %I found", tmp->lsa.id); ospf_iface_sm(iface, ISM_DOWN); - iface->iface = tmp->nhi; + iface->iface = tmp->nhi->iface; iface->vip = tmp->lb; ospf_iface_sm(iface, ISM_UP); } @@ -499,11 +497,21 @@ ospf_rt_sum(struct ospf_area *oa) if (en->lsa.type == LSA_T_SUM_NET) { + struct ospf_area *oaa; + int skip = 0; mlen = ipa_mklen(*mask); ip = ipa_and(ipa_from_u32(en->lsa.id), *mask); /* Page 169 (3) */ - if ((anet = fib_route(&oa->net_fib, ip, mlen)) && anet->active) - continue; + WALK_LIST(oaa, po->area_list) + { + if ((anet = fib_find(&oaa->net_fib, &ip, mlen)) && anet->active) + { + skip = 1; + break; + } + } + if (skip) continue; + type = ORT_NET; } else @@ -573,9 +581,6 @@ ospf_rt_spf(struct proto_ospf *po) } FIB_WALK_END; - fib_free(&oa->rtr); - fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort); - FIB_WALK(&oa->net_fib, nftmp) { anet = (struct area_net *) nftmp; @@ -585,13 +590,13 @@ ospf_rt_spf(struct proto_ospf *po) ospf_rt_spfa(oa); } - if (po->areano == 1) + if ((po->areano == 1) || (!po->backbone)) { ospf_rt_sum(HEAD(po->area_list)); } else { - if (po->backbone) ospf_rt_sum(po->backbone); /* And if backbone is not connected? */ + ospf_rt_sum(po->backbone); } WALK_LIST(oa, po->area_list) @@ -630,7 +635,7 @@ ospf_ext_spf(struct proto_ospf *po) struct ospf_lsa_ext_tos *lt; int mlen; ip_addr ip, nh, rtid; - struct iface *nhi = NULL; + struct ospf_iface *nhi = NULL; int met1, met2; neighbor *nn; struct ospf_lsa_rt *rt; @@ -731,7 +736,7 @@ ospf_ext_spf(struct proto_ospf *po) if ((nn = neigh_find(p, <->fwaddr, 0)) != NULL) { nh = lt->fwaddr; - nhi = nn->iface; + nhi = ospf_iface_find(po, nn->iface); } else { @@ -760,7 +765,7 @@ ospf_ext_spf(struct proto_ospf *po) /* Add LSA into list of candidates in Dijkstra's algorithm */ static void add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par, - u16 dist, struct ospf_area *oa, int vlink) + u16 dist, struct ospf_area *oa) { node *prev, *n; int added = 0; @@ -791,7 +796,6 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par, en->nh = IPA_NONE; calc_next_hop(en, par, oa); - //if (vlink) en->nh = IPA_NONE; if (!en->nhi) return; /* We cannot find next hop, ignore it */ @@ -861,7 +865,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par, if (ifa->iface && (ipa_compare (ifa->iface->addr->ip, ipa_from_u32(en->lsa.id)) == 0)) { - en->nhi = ifa->iface; + en->nhi = ifa; return; } log(L_ERR "I didn't find interface for my self originated LSA!\n"); @@ -873,7 +877,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par, ip_addr ip = ipa_from_u32(en->lsa.id); nn = neigh_find(p, &ip, 0); if (nn) - en->nhi = nn->iface; + en->nhi = ospf_iface_find(po, nn->iface); return; } } @@ -881,7 +885,8 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par, { if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL) return; - en->nhi = neigh->ifa->iface; + en->nhi = neigh->ifa; + if (neigh->ifa->type == OSPF_IT_VLINK) en->nh = neigh->ip; /* Yes, neighbor is it's * own next hop */ return; @@ -895,7 +900,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par, 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->iface; + en->nhi = neigh->ifa; en->nh = neigh->ip; /* Yes, neighbor is it's own * next hop */ return; @@ -932,6 +937,7 @@ again1: FIB_ITERATE_START(fib, &fit, nftmp) { nf = (ort *) nftmp; + check_sum_lsa(po, nf, ORT_NET); if (memcmp(&nf->n, &nf->o, sizeof(orta))) { /* Some difference */ net *ne; @@ -947,7 +953,8 @@ again1: a0.dest = RTD_ROUTER; a0.flags = 0; a0.aflags = 0; - a0.iface = nf->n.ifa; + a0.iface = NULL; + if (nf->n.ifa) a0.iface = nf->n.ifa->iface; a0.gw = nf->n.nh; if (ipa_equal(nf->n.nh, IPA_NONE)) a0.dest = RTD_DEVICE; @@ -974,7 +981,6 @@ again1: if (!found) nf->n.metric1 = LSINFINITY; /* Delete it */ } ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen); - check_sum_lsa(po, nf, ORT_NET); if (nf->n.metric1 < LSINFINITY) { e = rte_get_temp(&a0); @@ -1024,13 +1030,18 @@ again2: { flush = 1; anet = (struct area_net *) nftmp; - if((!anet->hidden) && anet->active && (!oa->trcap)) + if((!anet->hidden) && anet->active) flush = 0; WALK_LIST(oaa, po->area_list) { + int fl = flush; + if (oaa == oa) continue; - if(flush) flush_sum_lsa(oaa, &anet->fn, ORT_NET); + + if ((oa == po->backbone) && oaa->trcap) fl = 1; + + if(fl) flush_sum_lsa(oaa, &anet->fn, ORT_NET); else originate_sum_lsa(oaa, &anet->fn, ORT_NET, 1); } } diff --git a/proto/ospf/rt.h b/proto/ospf/rt.h index f7b33303..ea2f28f5 100644 --- a/proto/ospf/rt.h +++ b/proto/ospf/rt.h @@ -24,7 +24,7 @@ typedef struct orta int metric1; int metric2; ip_addr nh; /* Next hop */ - struct iface *ifa; /* Outgoing interface */ + struct ospf_iface *ifa; /* Outgoing interface */ struct top_hash_entry *ar; /* Advertising router */ u32 tag; } diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 5ba41e83..43dbc7d6 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -24,6 +24,7 @@ static void * originate_rt_lsa_body(struct ospf_area *oa, u16 * length) { struct proto_ospf *po = oa->po; + struct proto *p = &po->proto; struct ospf_iface *ifa; int j = 0, k = 0; u16 i = 0; @@ -51,8 +52,12 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length) WALK_LIST(ifa, po->iface_list) { - if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (ifa->state > OSPF_IS_DOWN)) - rt->veb.bit.v = 1; + if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (!EMPTY_LIST(ifa->neigh_list))) + { + neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list); + if ((neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff)) + rt->veb.bit.v = 1; + } if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN)) continue; @@ -413,7 +418,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type) if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL) { sum = en->lsa_body; - if (fn->pxlen == ipa_mklen(sum->netmask)) + if ((type == ORT_ROUTER) || (fn->pxlen == ipa_mklen(sum->netmask))) { en->lsa.age = LSA_MAXAGE; en->lsa.sn = LSA_MAXSEQNO; @@ -521,27 +526,36 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest) flush = 0; if ((nf->n.metric1 >= LSINFINITY) || (nf->n.type > RTS_OSPF_IA)) flush = 1; - if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR))) + if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ASBR))) flush = 1; if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid)) flush = 1; - /* FIXME: Test next hop - is it in actual area? */ + + if (nf->n.ifa) { + if (nf->n.ifa->oa->areaid == oa->areaid) + flush = 1; + } + else flush = 1; + if ((dest == ORT_ROUTER) && oa->stub) flush = 1; /* FIXME stub for networks? */ mlen = nf->fn.pxlen; ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen)); - if ((!flush) && (!nf->n.oa->trcap) && - fib_route(&nf->n.oa->net_fib, ip, mlen)) /* The route fits into area networks */ - flush = 1; - if(flush) /* FIXME Go on... */ + 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 */ { - flush_sum_lsa(oa, &nf->fn, dest); - continue; + flush = 1; + if ((nf->n.oa == po->backbone) && (oa->trcap)) flush = 0; } - originate_sum_lsa(oa, &nf->fn, dest, nf->n.metric1); + + if(flush) + flush_sum_lsa(oa, &nf->fn, dest); + else + originate_sum_lsa(oa, &nf->fn, dest, nf->n.metric1); } } diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h index bccff056..21e545e7 100644 --- a/proto/ospf/topology.h +++ b/proto/ospf/topology.h @@ -23,7 +23,7 @@ struct top_hash_entry bird_clock_t inst_t; /* Time of installation into DB */ ip_addr nh; /* Next hop */ ip_addr lb; /* Link back */ - struct iface *nhi; + struct ospf_iface *nhi; /* Next hop interface */ u32 dist; /* Distance from the root */ u16 ini_age; u8 color;