Fixes next hop handling.

This commit is contained in:
Ondrej Zajicek 2009-12-04 22:20:13 +01:00
parent 9895502392
commit b76aeb8234

View file

@ -11,9 +11,9 @@
static void add_cand(list * l, struct top_hash_entry *en, static void add_cand(list * l, struct top_hash_entry *en,
struct top_hash_entry *par, u32 dist, struct top_hash_entry *par, u32 dist,
struct ospf_area *oa); struct ospf_area *oa);
static void calc_next_hop(struct ospf_area *oa, static int calc_next_hop(struct ospf_area *oa,
struct top_hash_entry *en, struct top_hash_entry *en,
struct top_hash_entry *par); struct top_hash_entry *par);
static void ospf_ext_spf(struct proto_ospf *po); static void ospf_ext_spf(struct proto_ospf *po);
static void rt_sync(struct proto_ospf *po); static void rt_sync(struct proto_ospf *po);
@ -987,18 +987,23 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
*/ */
/* FIXME - fix link_back() /* FIXME - fix link_back()
* NOTE - we should not change link_back when
* it is already computed with different way and calc_next_hop()
* for current would fail
if (!link_back(oa, en, par)) if (!link_back(oa, en, par))
return; return;
*/ */
if (!calc_next_hop(oa, en, par))
{
log(L_WARN "Cannot find next hop for LSA (Type: %04x, Id: %R, Rt: %R)",
en->lsa.type, en->lsa.id, en->lsa.rt);
return;
}
DBG(" Adding candidate: rt: %R, id: %R, type: %u\n", DBG(" Adding candidate: rt: %R, id: %R, type: %u\n",
en->lsa.rt, en->lsa.id, en->lsa.type); en->lsa.rt, en->lsa.id, en->lsa.type);
calc_next_hop(oa, en, par);
if (!en->nhi)
return; /* We cannot find next hop, ignore it */
if (en->color == CANDIDATE) if (en->color == CANDIDATE)
{ /* We found a shorter path */ { /* We found a shorter path */
rem_node(&en->cn); rem_node(&en->cn);
@ -1049,7 +1054,7 @@ match_dr(struct ospf_iface *ifa, struct top_hash_entry *en)
#endif #endif
} }
static void static int
calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en, calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
struct top_hash_entry *par) struct top_hash_entry *par)
{ {
@ -1058,9 +1063,6 @@ calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
struct proto_ospf *po = oa->po; struct proto_ospf *po = oa->po;
struct ospf_iface *ifa; struct ospf_iface *ifa;
en->nhi = NULL;
en->nh = IPA_NONE;
/* 16.1.1. The next hop calculation */ /* 16.1.1. The next hop calculation */
DBG(" Next hop called.\n"); DBG(" Next hop called.\n");
if (ipa_equal(par->nh, IPA_NONE)) if (ipa_equal(par->nh, IPA_NONE))
@ -1068,57 +1070,58 @@ calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
DBG(" Next hop calculating for id: %R rt: %R type: %u\n", DBG(" Next hop calculating for id: %R rt: %R type: %u\n",
en->lsa.id, en->lsa.rt, en->lsa.type); en->lsa.id, en->lsa.rt, en->lsa.type);
/* The parent vertex is the root */ /*
if (par == oa->rt) * There are three cases:
* 1) en is a local network (and par is root)
* 2) en is a ptp or ptmp neighbor (and par is root)
* 3) en is a bcast or nbma neighbor (and par is local network)
*/
/* The first case - local network */
if ((en->lsa.type == LSA_T_NET) && (par == oa->rt))
{ {
if (en->lsa.type == LSA_T_NET) WALK_LIST(ifa, po->iface_list)
{ if (match_dr(ifa, en))
WALK_LIST(ifa, po->iface_list)
if (match_dr(ifa, en))
{ {
en->nhi = ifa; en->nh = IPA_NONE;
return; en->nhi = ifa;
return 1;
} }
return; return 0;
}
else
{
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 */
return;
}
} }
/* The parent vertex is a network that directly connects the /*
calculating router to the destination router. */ * Remaining cases - local neighbours.
if (par->lsa.type == LSA_T_NET) * There are two problems with this code:
* 1) we use IP address from HELLO packet
* and not the one from LSA (router or link).
* This may break NBMA networks
* 2) we use find_neigh_noifa() and does not
* take into account associated iface.
* This breaks neighbors connected by more links.
*/
if ((en->lsa.type == LSA_T_RT) &&
((par == oa->rt) || (par->lsa.type == LSA_T_NET)))
{ {
if (en->lsa.type == LSA_T_NET) if ((neigh = find_neigh_noifa(po, en->lsa.rt)) != NULL)
bug("Parent for net is net?"); {
if ((en->nhi = par->nhi) == NULL) en->nh = neigh->ip;
bug("Did not find next hop interface for INSPF lsa!"); en->nhi = neigh->ifa;
return 1;
}
return 0;
}
if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL) /* Probably bug or some race condition, we log it */
return; log(L_ERR "Unexpected case in next hop calculation");
en->nhi = neigh->ifa;
en->nh = neigh->ip; return 0;
/* Yes, neighbor is it's own next hop */
return;
}
else
{ /* Parent is some RT neighbor */
log(L_ERR "Router's parent has no next hop. (EN=%R, PAR=%R)",
en->lsa.id, par->lsa.id);
/* I hope this would never happen */
return;
}
} }
en->nhi = par->nhi;
en->nh = par->nh; en->nh = par->nh;
DBG(" Next hop calculated: %I.\n", en->nh); en->nhi = par->nhi;
return 1;
} }
static void static void