Fixes several bugs related to OSPFv3 vlinks.

This commit is contained in:
Ondrej Zajicek 2012-10-29 20:29:31 +01:00
parent 0343d066da
commit e4404cef0b
3 changed files with 53 additions and 26 deletions

View file

@ -92,6 +92,7 @@ ospf_proto_finish(void)
if (cf->abr && !backbone) if (cf->abr && !backbone)
{ {
struct ospf_area_config *ac = cfg_allocz(sizeof(struct ospf_area_config)); struct ospf_area_config *ac = cfg_allocz(sizeof(struct ospf_area_config));
ac->type = OPT_E; /* Backbone is non-stub */
add_head(&cf->area_list, NODE ac); add_head(&cf->area_list, NODE ac);
init_list(&ac->patt_list); init_list(&ac->patt_list);
init_list(&ac->net_list); init_list(&ac->net_list);

View file

@ -112,6 +112,10 @@ ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_i
{ {
u32 scope = LSA_SCOPE(lsa); u32 scope = LSA_SCOPE(lsa);
/* Handle inactive vlinks */
if (ifa->state == OSPF_IS_DOWN)
return 0;
/* 4.5.2 (Case 2) */ /* 4.5.2 (Case 2) */
if (unknown_lsa_type(lsa) && !(lsa->type & LSA_UBIT)) if (unknown_lsa_type(lsa) && !(lsa->type & LSA_UBIT))
scope = LSA_SCOPE_LINK; scope = LSA_SCOPE_LINK;

View file

@ -1249,7 +1249,6 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
struct ospf_config *cf = (struct ospf_config *) (po->proto.cf); struct ospf_config *cf = (struct ospf_config *) (po->proto.cf);
struct ospf_iface *ifa; struct ospf_iface *ifa;
struct ospf_lsa_prefix *lp; struct ospf_lsa_prefix *lp;
struct ifa *vlink_addr = NULL;
int host_addr = 0; int host_addr = 0;
int net_lsa; int net_lsa;
int i = 0; int i = 0;
@ -1263,7 +1262,7 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
WALK_LIST(ifa, po->iface_list) WALK_LIST(ifa, po->iface_list)
{ {
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN)) if ((ifa->oa != oa) || (ifa->type == OSPF_IT_VLINK) || (ifa->state == OSPF_IS_DOWN))
continue; continue;
ifa->px_pos_beg = i; ifa->px_pos_beg = i;
@ -1282,9 +1281,6 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
(a->scope <= SCOPE_LINK)) (a->scope <= SCOPE_LINK))
continue; continue;
if (!vlink_addr)
vlink_addr = a;
if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) || if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) ||
configured_stubnet(oa, a)) configured_stubnet(oa, a))
continue; continue;
@ -1304,23 +1300,41 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
ifa->px_pos_end = i; ifa->px_pos_end = i;
} }
/* If there are some configured vlinks, add some global address,
which will be used as a vlink endpoint. */
if (!EMPTY_LIST(cf->vlink_list) && !host_addr && vlink_addr)
{
lsa_put_prefix(po, vlink_addr->ip, MAX_PREFIX_LENGTH, 0);
i++;
}
struct ospf_stubnet_config *sn; struct ospf_stubnet_config *sn;
if (oa->ac) if (oa->ac)
WALK_LIST(sn, oa->ac->stubnet_list) WALK_LIST(sn, oa->ac->stubnet_list)
if (!sn->hidden) if (!sn->hidden)
{ {
lsa_put_prefix(po, sn->px.addr, sn->px.len, sn->cost); lsa_put_prefix(po, sn->px.addr, sn->px.len, sn->cost);
if (sn->px.len == MAX_PREFIX_LENGTH)
host_addr = 1;
i++; i++;
} }
/* If there are some configured vlinks, find some global address
(even from another area), which will be used as a vlink endpoint. */
if (!EMPTY_LIST(cf->vlink_list) && !host_addr)
{
WALK_LIST(ifa, po->iface_list)
{
if ((ifa->type == OSPF_IT_VLINK) || (ifa->state == OSPF_IS_DOWN))
continue;
struct ifa *a;
WALK_LIST(a, ifa->iface->addrs)
{
if ((a->flags & IA_SECONDARY) || (a->scope <= SCOPE_LINK))
continue;
/* Found some IP */
lsa_put_prefix(po, a->ip, MAX_PREFIX_LENGTH, 0);
i++;
goto done;
}
}
}
done:
lp = po->lsab; lp = po->lsab;
lp->pxcount = i; lp->pxcount = i;
*length = po->lsab_used + sizeof(struct ospf_lsa_header); *length = po->lsab_used + sizeof(struct ospf_lsa_header);
@ -1389,15 +1403,12 @@ add_prefix(struct proto_ospf *po, u32 *px, int offset, int *pxc)
{ {
u32 *pxl = lsab_offset(po, offset); u32 *pxl = lsab_offset(po, offset);
int i; int i;
for (i = 0; i < *pxc; i++) for (i = 0; i < *pxc; pxl = prefix_advance(pxl), i++)
if (prefix_same(px, pxl))
{ {
if (prefix_same(px, pxl)) /* Options should be logically OR'ed together */
{ *pxl |= (*px & 0x00FF0000);
/* Options should be logically OR'ed together */ return;
*pxl |= *px;
return;
}
pxl = prefix_advance(pxl);
} }
ASSERT(pxl == lsab_end(po)); ASSERT(pxl == lsab_end(po));
@ -1405,6 +1416,7 @@ add_prefix(struct proto_ospf *po, u32 *px, int offset, int *pxc)
int pxspace = prefix_space(px); int pxspace = prefix_space(px);
pxl = lsab_alloc(po, pxspace); pxl = lsab_alloc(po, pxspace);
memcpy(pxl, px, pxspace); memcpy(pxl, px, pxspace);
*pxl &= 0xFFFF0000; /* Set metric to zero */
(*pxc)++; (*pxc)++;
} }
@ -1415,11 +1427,21 @@ add_link_lsa(struct proto_ospf *po, struct top_hash_entry *en, int offset, int *
u32 *pxb = ll->rest; u32 *pxb = ll->rest;
int j; int j;
for (j = 0; j < ll->pxcount; j++) for (j = 0; j < ll->pxcount; pxb = prefix_advance(pxb), j++)
{ {
add_prefix(po, pxb, offset, pxc); u8 pxlen = (pxb[0] >> 24);
pxb = prefix_advance(pxb); u8 pxopts = (pxb[0] >> 16);
}
/* Skip NU or LA prefixes */
if (pxopts & (OPT_PX_NU | OPT_PX_LA))
continue;
/* Skip link-local prefixes */
if ((pxlen >= 10) && ((pxb[1] & 0xffc00000) == 0xfe800000))
continue;
add_prefix(po, pxb, offset, pxc);
}
} }