summaryrefslogtreecommitdiffstats
path: root/proto/ospf/ospf.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/ospf/ospf.c')
-rw-r--r--proto/ospf/ospf.c162
1 files changed, 82 insertions, 80 deletions
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index aca74cb..a1049e1 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -1,7 +1,7 @@
/*
* BIRD -- OSPF
*
- * (c) 1999 - 2000 Ondrej Filip <feela@network.cz>
+ * (c) 1999--2004 Ondrej Filip <feela@network.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -75,6 +75,31 @@ static int ospf_rte_same(struct rte *new, struct rte *old);
static void area_disp(timer *timer);
static void ospf_disp(timer *timer);
+static void
+ospf_area_initfib(struct fib_node *fn)
+{
+ struct area_net *an = (struct area_net *) fn;
+ an->hidden = 0;
+ an->active = -1; /* Force to regenerate summary lsa */
+ /* ac->oldactive will be rewritten by ospf_rt_spf() */
+}
+
+static void
+add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac)
+{
+ struct proto_ospf *po = oa->po;
+ struct proto *p = &po->proto;
+ struct area_net_config *anet;
+ struct area_net *antmp;
+
+ fib_init(&oa->net_fib, p->pool, sizeof(struct area_net), 16, ospf_area_initfib);
+
+ WALK_LIST(anet, ac->net_list)
+ {
+ antmp = (struct area_net *) fib_get(&oa->net_fib, &anet->px.addr, anet->px.len);
+ antmp->hidden = anet->hidden;
+ }
+}
static int
ospf_start(struct proto *p)
@@ -83,13 +108,12 @@ ospf_start(struct proto *p)
struct ospf_config *c = (struct ospf_config *) (p->cf);
struct ospf_area_config *ac;
struct ospf_area *oa;
- struct area_net *anet, *antmp;
po->rfc1583 = c->rfc1583;
po->ebit = 0;
po->tick = c->tick;
- po->disp_timer = tm_new(po->proto.pool);
+ po->disp_timer = tm_new(p->pool);
po->disp_timer->data = po;
po->disp_timer->randomize = 0;
po->disp_timer->hook = ospf_disp;
@@ -97,8 +121,7 @@ ospf_start(struct proto *p)
tm_start(po->disp_timer, 1);
init_list(&(po->iface_list));
init_list(&(po->area_list));
- fib_init(&po->rtf[0], p->pool, sizeof(ort), 16, ospf_rt_initort);
- fib_init(&po->rtf[1], p->pool, sizeof(ort), 16, ospf_rt_initort);
+ fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort);
po->areano = 0;
if (EMPTY_LIST(c->area_list))
{
@@ -108,7 +131,7 @@ ospf_start(struct proto *p)
WALK_LIST(ac, c->area_list)
{
- oa = mb_allocz(po->proto.pool, sizeof(struct ospf_area));
+ oa = mb_allocz(p->pool, sizeof(struct ospf_area));
add_tail(&po->area_list, NODE oa);
po->areano++;
oa->stub = ac->stub;
@@ -118,20 +141,27 @@ ospf_start(struct proto *p)
s_init_list(&(oa->lsal));
oa->rt = NULL;
oa->po = po;
- oa->disp_timer = tm_new(po->proto.pool);
+ oa->disp_timer = tm_new(p->pool);
oa->disp_timer->data = oa;
oa->disp_timer->randomize = 0;
oa->disp_timer->hook = area_disp;
oa->disp_timer->recurrent = oa->tick;
tm_start(oa->disp_timer, 2);
- init_list(&oa->net_list);
- WALK_LIST(anet, ac->net_list)
+ add_area_nets(oa, ac);
+ fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
+ if (oa->areaid == 0) po->backbone = oa;
+ }
+
+ /* Add all virtual links as interfaces */
+ if(po->backbone)
+ {
+ struct ospf_iface_patt *ipatt;
+ WALK_LIST(ac, c->area_list)
{
- antmp = mb_allocz(po->proto.pool, sizeof(struct area_net));
- antmp->px.addr = anet->px.addr;
- antmp->px.len = anet->px.len;
- antmp->hidden = anet->hidden;
- add_tail(&oa->net_list, NODE antmp);
+ WALK_LIST(ipatt, ac->patt_list)
+ {
+ if (ipatt->type == OSPF_IT_VLINK) ospf_iface_new(po, NULL, ac, ipatt);
+ }
}
}
return PS_UP;
@@ -189,42 +219,21 @@ ospf_init(struct proto_config *c)
static int
ospf_rte_better(struct rte *new, struct rte *old)
{
- /* FIXME this is wrong */
if (new->u.ospf.metric1 == LSINFINITY)
return 0;
- /* External paths are always longer that internal */
- if (((new->attrs->source == RTS_OSPF)
- || (new->attrs->source == RTS_OSPF_IA))
- && (old->attrs->source == RTS_OSPF_EXT))
- return 1;
- if (((old->attrs->source == RTS_OSPF)
- || (old->attrs->source == RTS_OSPF_IA))
- && (new->attrs->source == RTS_OSPF_EXT))
- return 0;
-
- if (new->u.ospf.metric2 < old->u.ospf.metric2)
- {
- if (old->u.ospf.metric2 == LSINFINITY)
- return 0; /* Old is E1, new is E2 */
- return 1; /* Both are E2 */
- }
+ if(new->attrs->source < old->attrs->source) return 1;
+ if(new->attrs->source > old->attrs->source) return 0;
- if (new->u.ospf.metric2 > old->u.ospf.metric2)
+ if(new->attrs->source == RTS_OSPF_EXT2)
{
- if (new->u.ospf.metric2 == LSINFINITY)
- return 1; /* New is E1, old is E2 */
- return 0; /* Both are E2 */
+ if(new->u.ospf.metric2 < old->u.ospf.metric2) return 1;
+ if(new->u.ospf.metric2 > old->u.ospf.metric2) return 0;
}
- /*
- * E2 metrics are the same. It means that:
- * 1) Paths are E2 with same metric
- * 2) Paths are E1.
- */
-
if (new->u.ospf.metric1 < old->u.ospf.metric1)
return 1;
+
return 0; /* Old is shorter or same */
}
@@ -466,29 +475,30 @@ ospf_get_status(struct proto *p, byte * buf)
static void
ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED)
{
- char met = ' ';
- char type = ' ';
+ char *type = "<bug>";
- if (rte->attrs->source == RTS_OSPF_EXT)
+ switch(rte->attrs->source)
{
- met = '1';
- type = 'E';
-
+ case RTS_OSPF:
+ type = "I";
+ break;
+ case RTS_OSPF_IA:
+ type = "IA";
+ break;
+ case RTS_OSPF_EXT1:
+ type = "E1";
+ break;
+ case RTS_OSPF_EXT2:
+ type = "E2";
+ break;
}
- if (rte->u.ospf.metric2 != LSINFINITY)
- met = '2';
- if (rte->attrs->source == RTS_OSPF_IA)
- type = 'A';
- if (rte->attrs->source == RTS_OSPF)
- type = 'I';
- buf += bsprintf(buf, " %c", type);
- if (met != ' ')
- buf += bsprintf(buf, "%c", met);
+
+ buf += bsprintf(buf, " %s", type);
buf += bsprintf(buf, " (%d/%d", rte->pref, rte->u.ospf.metric1);
- if (rte->u.ospf.metric2 != LSINFINITY)
+ if (rte->attrs->source == RTS_OSPF_EXT2)
buf += bsprintf(buf, "/%d", rte->u.ospf.metric2);
buf += bsprintf(buf, ")");
- if (rte->attrs->source == RTS_OSPF_EXT && rte->u.ospf.tag)
+ if ((rte->attrs->source == RTS_OSPF_EXT2 || rte->attrs->source == RTS_OSPF_EXT1) && rte->u.ospf.tag)
{
buf += bsprintf(buf, " [%x]", rte->u.ospf.tag);
}
@@ -578,19 +588,8 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
}
/* Change net_list */
- WALK_LIST_DELSAFE(anet, antmp, oa->net_list)
- {
- rem_node(NODE anet);
- mb_free(anet);
- }
- WALK_LIST(anet, ac2->net_list)
- {
- antmp = mb_alloc(p->pool, sizeof(struct area_net));
- antmp->px.addr = anet->px.addr;
- antmp->px.len = anet->px.len;
- antmp->hidden = anet->hidden;
- add_tail(&oa->net_list, NODE antmp);
- }
+ fib_free(&oa->net_fib);
+ add_area_nets(oa, ac2);
if (!iface_patts_equal(&ac1->patt_list, &ac2->patt_list,
(void *) ospf_patt_compare))
@@ -833,9 +832,8 @@ ospf_sh(struct proto *p)
struct proto_ospf *po = (struct proto_ospf *) p;
struct ospf_iface *ifa;
struct ospf_neighbor *n;
- int ifano;
- int nno;
- int adjno;
+ int ifano, nno, adjno, firstfib;
+ struct area_net *anet;
if (p->proto_state != PS_UP)
{
@@ -871,16 +869,20 @@ ospf_sh(struct proto *p)
cli_msg(-1014, "\t\tNumber of LSAs in DB:\t%u", oa->gr->hash_entries);
cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);
cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno);
- if (!EMPTY_LIST(oa->net_list))
+
+ firstfib = 1;
+ FIB_WALK(&oa->net_fib, nftmp)
{
- struct area_net *anet;
- cli_msg(-1014, "\t\tArea networks:");
- WALK_LIST(anet, oa->net_list)
+ anet = (struct area_net *) nftmp;
+ if(firstfib)
{
- cli_msg(-1014, "\t\t\t%1I/%u\t%s", anet->px.addr, anet->px.len,
- anet->hidden ? "Hidden" : "Advertise");
+ cli_msg(-1014, "\t\tArea networks:");
+ firstfib = 0;
}
+ cli_msg(-1014, "\t\t\t%1I/%u\t%s\t%s", anet->fn.prefix, anet->fn.pxlen,
+ anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
}
+ FIB_WALK_END;
}
cli_msg(0, "");
}