Fixes next hop calculation on NBMA and parallel PTP links.
This commit is contained in:
parent
7969ea3b41
commit
6e80676096
4 changed files with 71 additions and 43 deletions
|
@ -536,27 +536,6 @@ find_neigh(struct ospf_iface *ifa, u32 rid)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Find a closest neighbor which is at least 2-Way */
|
|
||||||
struct ospf_neighbor *
|
|
||||||
find_neigh_noifa(struct proto_ospf *po, u32 rid)
|
|
||||||
{
|
|
||||||
struct ospf_neighbor *n = NULL, *m;
|
|
||||||
struct ospf_iface *ifa;
|
|
||||||
|
|
||||||
WALK_LIST(ifa, po->iface_list) if ((m = find_neigh(ifa, rid)) != NULL)
|
|
||||||
{
|
|
||||||
if (m->state >= NEIGHBOR_2WAY)
|
|
||||||
{
|
|
||||||
if (n == NULL)
|
|
||||||
n = m;
|
|
||||||
else if (m->ifa->cost < n->ifa->cost)
|
|
||||||
n = m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ospf_area *
|
struct ospf_area *
|
||||||
ospf_find_area(struct proto_ospf *po, u32 aid)
|
ospf_find_area(struct proto_ospf *po, u32 aid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,6 @@ struct ospf_neighbor *ospf_neighbor_new(struct ospf_iface *ifa);
|
||||||
void ospf_neigh_sm(struct ospf_neighbor *n, int event);
|
void ospf_neigh_sm(struct ospf_neighbor *n, int event);
|
||||||
void bdr_election(struct ospf_iface *ifa);
|
void bdr_election(struct ospf_iface *ifa);
|
||||||
struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid);
|
struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid);
|
||||||
struct ospf_neighbor *find_neigh_noifa(struct proto_ospf *po, u32 rid);
|
|
||||||
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
|
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
|
||||||
void ospf_neigh_remove(struct ospf_neighbor *n);
|
void ospf_neigh_remove(struct ospf_neighbor *n);
|
||||||
void ospf_sh_neigh_info(struct ospf_neighbor *n);
|
void ospf_sh_neigh_info(struct ospf_neighbor *n);
|
||||||
|
|
|
@ -477,6 +477,9 @@ link_back(struct ospf_area *oa, struct top_hash_entry *en, struct top_hash_entry
|
||||||
|
|
||||||
// FIXME lb should be properly set for vlinks */
|
// FIXME lb should be properly set for vlinks */
|
||||||
en->lb = IPA_NONE;
|
en->lb = IPA_NONE;
|
||||||
|
#ifdef OSPFv3
|
||||||
|
en->lb_id = 0;
|
||||||
|
#endif
|
||||||
switch (en->lsa.type)
|
switch (en->lsa.type)
|
||||||
{
|
{
|
||||||
case LSA_T_RT:
|
case LSA_T_RT:
|
||||||
|
@ -500,6 +503,8 @@ link_back(struct ospf_area *oa, struct top_hash_entry *en, struct top_hash_entry
|
||||||
{
|
{
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
en->lb = ipa_from_u32(rtl->data);
|
en->lb = ipa_from_u32(rtl->data);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
en->lb_id = rtl->lif;
|
||||||
#endif
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1099,14 +1104,15 @@ calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
|
||||||
struct top_hash_entry *par)
|
struct top_hash_entry *par)
|
||||||
{
|
{
|
||||||
// struct proto *p = &oa->po->proto;
|
// struct proto *p = &oa->po->proto;
|
||||||
struct ospf_neighbor *neigh;
|
struct ospf_neighbor *neigh, *m;
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
struct ospf_iface *ifa;
|
struct ospf_iface *ifa;
|
||||||
|
|
||||||
/* 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_zero(par->nh))
|
||||||
{
|
{
|
||||||
|
u32 rid = en->lsa.rt;
|
||||||
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);
|
||||||
|
|
||||||
|
@ -1130,32 +1136,73 @@ calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* The second case - ptp or ptmp neighbor */
|
||||||
* Remaining cases - local neighbours.
|
if ((en->lsa.type == LSA_T_RT) && (par == oa->rt))
|
||||||
* 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 ((neigh = find_neigh_noifa(po, en->lsa.rt)) != NULL)
|
/*
|
||||||
|
* We don't know which iface was used to reach this neighbor
|
||||||
|
* (there might be more parallel ifaces) so we will find
|
||||||
|
* the best PTP iface with given fully adjacent neighbor.
|
||||||
|
*/
|
||||||
|
neigh = NULL;
|
||||||
|
WALK_LIST(ifa, po->iface_list)
|
||||||
|
if (ifa->type == OSPF_IT_PTP)
|
||||||
{
|
{
|
||||||
en->nh = neigh->ip;
|
m = find_neigh(ifa, rid);
|
||||||
en->nhi = neigh->ifa;
|
if (m && (m->state == NEIGHBOR_FULL))
|
||||||
return 1;
|
{
|
||||||
|
if (!neigh || (m->ifa->cost < neigh->ifa->cost))
|
||||||
|
neigh = m;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
if (!neigh)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
en->nh = neigh->ip;
|
||||||
|
en->nhi = neigh->ifa;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The third case - bcast or nbma neighbor */
|
||||||
|
if ((en->lsa.type == LSA_T_RT) && (par->lsa.type == LSA_T_NET))
|
||||||
|
{
|
||||||
|
/* par->nhi should be defined from parent's calc_next_hop() */
|
||||||
|
if (!par->nhi)
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
/*
|
||||||
|
* In this case, next-hop is the same as link-back, which is
|
||||||
|
* already computed in link_back().
|
||||||
|
*/
|
||||||
|
if (ipa_zero(en->lb))
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
en->nh = en->lb;
|
||||||
|
en->nhi = par->nhi;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
/*
|
||||||
|
* Next-hop is taken from lladdr field of Link-LSA, en->lb_id
|
||||||
|
* is computed in link_back().
|
||||||
|
*/
|
||||||
|
struct top_hash_entry *llsa;
|
||||||
|
llsa = ospf_hash_find(po->gr, par->nhi->iface->index, en->lb_id, rid, LSA_T_LINK);
|
||||||
|
|
||||||
|
if (!llsa)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
en->nh = llsa->lladdr;
|
||||||
|
en->nhi = par->nhi;
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bad:
|
||||||
/* Probably bug or some race condition, we log it */
|
/* Probably bug or some race condition, we log it */
|
||||||
log(L_ERR "Unexpected case in next hop calculation");
|
log(L_ERR "Unexpected case in next hop calculation");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@ struct top_hash_entry
|
||||||
ip_addr nh; /* Next hop */
|
ip_addr nh; /* Next hop */
|
||||||
ip_addr lb; /* Link back */
|
ip_addr lb; /* Link back */
|
||||||
struct ospf_iface *nhi; /* Next hop interface */
|
struct ospf_iface *nhi; /* Next hop interface */
|
||||||
|
#ifdef OSPFv3
|
||||||
|
u32 lb_id; /* Interface ID of link back iface (for bcast or NBMA networks) */
|
||||||
|
#endif
|
||||||
u32 dist; /* Distance from the root */
|
u32 dist; /* Distance from the root */
|
||||||
u16 ini_age;
|
u16 ini_age;
|
||||||
u8 color;
|
u8 color;
|
||||||
|
|
Loading…
Reference in a new issue