summaryrefslogtreecommitdiffstats
path: root/proto/ospf
diff options
context:
space:
mode:
authorOndrej Filip <feela@network.cz>2004-07-14 23:46:20 +0200
committerOndrej Filip <feela@network.cz>2004-07-14 23:46:20 +0200
commit3b16080c97a2d89c90f7df7a8fda0401ec9abe42 (patch)
treeef885699eaa72453b99f40dba181112d7e9540b7 /proto/ospf
parenta417ad13a117d2458702cbec4aa418ba99981611 (diff)
downloadbird-3b16080c97a2d89c90f7df7a8fda0401ec9abe42.tar
bird-3b16080c97a2d89c90f7df7a8fda0401ec9abe42.zip
Multiple OSPF areas can be attached.
Origination of summary LSA works. Routing table calculation works. Virtual links works. Well, I hope, OSPF is fully compatible with RFC2328!!!!
Diffstat (limited to 'proto/ospf')
-rw-r--r--proto/ospf/config.Y21
-rw-r--r--proto/ospf/hello.c14
-rw-r--r--proto/ospf/iface.c219
-rw-r--r--proto/ospf/lsalib.c4
-rw-r--r--proto/ospf/lsupd.c25
-rw-r--r--proto/ospf/neighbor.c18
-rw-r--r--proto/ospf/ospf.c63
-rw-r--r--proto/ospf/ospf.h7
-rw-r--r--proto/ospf/packet.c25
-rw-r--r--proto/ospf/rt.c88
-rw-r--r--proto/ospf/topology.c65
11 files changed, 314 insertions, 235 deletions
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index 87a97bc..bd3a2e5 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -58,9 +58,9 @@ ospf_area_start: AREA idval '{' {
this_area = cfg_allocz(sizeof(struct ospf_area_config));
add_tail(&OSPF_CFG->area_list, NODE this_area);
this_area->areaid = $2;
- this_area->tick = DEFAULT_AREATICK;
this_area->stub = 0;
init_list(&this_area->patt_list);
+ init_list(&this_area->vlink_list);
init_list(&this_area->net_list);
}
;
@@ -75,13 +75,14 @@ ospf_area_opts:
ospf_area_item:
STUB COST expr { this_area->stub = $3 ; if($3<=0) cf_error("Stub cost must be greater than zero"); }
- | TICK expr { this_area->tick = $2 ; if($2<=0) cf_error("Tick must be greater than zero"); }
| NETWORKS '{' pref_list '}'
| INTERFACE ospf_iface_list
- | ospf_vlink '}'
+ | ospf_vlink
;
-ospf_vlink: ospf_vlink_start ospf_vlink_opts
+ospf_vlink:
+ ospf_vlink_start '{' ospf_vlink_opts '}'
+ | ospf_vlink_start
;
ospf_vlink_opts:
@@ -90,8 +91,7 @@ ospf_vlink_opts:
;
ospf_vlink_item:
- HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); }
- | POLL expr { OSPF_PATT->pollint = $2 ; if ($2<=0) cf_error("Poll int must be greater than zero"); }
+ | HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); }
| RETRANSMIT expr { OSPF_PATT->rxmtint = $2 ; if ($2<=0) cf_error("Retransmit int must be greater than zero"); }
| TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
| WAIT expr { OSPF_PATT->waitint = $2 ; }
@@ -102,19 +102,21 @@ ospf_vlink_item:
| password_list {OSPF_PATT->passwords = $1; }
;
-ospf_vlink_start: VIRTUAL LINK '{'
+ospf_vlink_start: VIRTUAL LINK idval
{
+ log("Vlink start");
if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone");
this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
- add_tail(&this_area->patt_list, NODE this_ipatt);
+ add_tail(&this_area->vlink_list, NODE this_ipatt);
+ OSPF_PATT->vid = $3;
OSPF_PATT->cost = COST_D;
OSPF_PATT->helloint = HELLOINT_D;
- OSPF_PATT->pollint = POLLINT_D;
OSPF_PATT->rxmtint = RXMTINT_D;
OSPF_PATT->inftransdelay = INFTRANSDELAY_D;
OSPF_PATT->waitint = WAIT_DMH*HELLOINT_D;
OSPF_PATT->deadc = DEADC_D;
OSPF_PATT->type = OSPF_IT_VLINK;
+ init_list(&OSPF_PATT->nbma_list);
OSPF_PATT->autype = OSPF_AUTH_NONE;
}
;
@@ -198,6 +200,7 @@ ipa_ne: IPA ELIGIBLE ';'
ospf_iface_start:
{
+ log("Iface start");
this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
add_tail(&this_area->patt_list, NODE this_ipatt);
OSPF_PATT->cost = COST_D;
diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c
index 7820cf7..350bad7 100644
--- a/proto/ospf/hello.c
+++ b/proto/ospf/hello.c
@@ -19,12 +19,13 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
struct proto *p = (struct proto *) ifa->proto;
unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers;
- OSPF_TRACE(D_PACKETS, "Received hello from %I via %s", faddr,
- ifa->iface->name);
+ OSPF_TRACE(D_PACKETS, "Received hello from %I via %s%s", faddr,
+ (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
mask = ps->netmask;
ipa_ntoh(mask);
- if ((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen)
+ if ((ifa->type != OSPF_IT_VLINK) &&
+ ((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen))
{
log(L_ERR "%s%I%sbad netmask %I.", beg, faddr, rec, mask);
return;
@@ -151,7 +152,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
ospf_iface_sm(ifa, ISM_NEICH);
}
- if (ifa->type != OSPF_IT_NBMA)
+ if (ifa->type == OSPF_IT_NBMA)
{
if ((ifa->priority == 0) && (n->priority > 0))
ospf_hello_send(NULL, 0, n);
@@ -171,7 +172,6 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
u32 *pp;
int i, send;
struct nbma_node *nb;
-
if (timer == NULL)
ifa = dirn->ifa;
else
@@ -204,6 +204,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
ipa_hton(pkt->netmask);
+ if (ifa->type == OSPF_IT_VLINK) pkt->netmask = IPA_NONE;
pkt->helloint = ntohs(ifa->helloint);
pkt->options = ifa->oa->opt.byte;
pkt->priority = ifa->priority;
@@ -280,5 +281,6 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
default:
ospf_send_to(ifa->hello_sk, IPA_NONE, ifa);
}
- OSPF_TRACE(D_PACKETS, "Hello sent via %s", ifa->iface->name);
+ OSPF_TRACE(D_PACKETS, "Hello sent via %s%s",
+ (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
}
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 62b8899..5a10cde 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -21,6 +21,7 @@ char *ospf_it[] = { "broadcast", "nbma", "point-to-point", "virtual link" };
static void
poll_timer_hook(timer * timer)
{
+ log("POLL!");
ospf_hello_send(timer, 1, NULL);
}
@@ -40,6 +41,38 @@ wait_timer_hook(timer * timer)
ospf_iface_sm(ifa, ISM_WAITF);
}
+static sock *
+ospf_open_ip_socket(struct ospf_iface *ifa)
+{
+ sock *ipsk;
+ struct proto *p;
+
+ p = (struct proto *) (ifa->proto);
+
+ ipsk = sk_new(p->pool);
+ ipsk->type = SK_IP;
+ ipsk->dport = OSPF_PROTO;
+ ipsk->saddr = ifa->iface->addr->ip;
+ ipsk->tos = IP_PREC_INTERNET_CONTROL;
+ ipsk->ttl = 1;
+ if (ifa->type == OSPF_IT_VLINK)
+ ipsk->ttl = 255;
+ ipsk->rx_hook = ospf_rx_hook;
+ ipsk->tx_hook = ospf_tx_hook;
+ ipsk->err_hook = ospf_err_hook;
+ ipsk->iface = ifa->iface;
+ ipsk->rbsize = ifa->iface->mtu;
+ ipsk->tbsize = ifa->iface->mtu;
+ ipsk->data = (void *) ifa;
+ if (sk_open(ipsk) != 0)
+ {
+ DBG("%s: SK_OPEN: ip open failed.\n", p->name);
+ return (NULL);
+ }
+ DBG("%s: SK_OPEN: ip opened.\n", p->name);
+ return (ipsk);
+}
+
/**
* ospf_iface_chstate - handle changes of interface state
@@ -55,58 +88,71 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
{
struct proto_ospf *po = ifa->proto;
struct proto *p = &po->proto;
- u8 oldstate;
+ u8 oldstate = ifa->state;
- if (ifa->state != state)
+ if (oldstate != state)
{
- OSPF_TRACE(D_EVENTS,
- "Changing state of iface: %s from \"%s\" into \"%s\".",
- ifa->iface->name, ospf_is[ifa->state], ospf_is[state]);
- oldstate = ifa->state;
ifa->state = state;
- if (ifa->iface->flags & IF_MULTICAST)
+
+ if (ifa->type == OSPF_IT_VLINK)
{
- if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
+ OSPF_TRACE(D_EVENTS,
+ "Changing state of virtual link %I from \"%s\" into \"%s\".",
+ ifa->vid, ospf_is[oldstate], ospf_is[state]);
+ if (state == OSPF_IS_PTP)
{
- if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA))
+ ifa->ip_sk = ospf_open_ip_socket(ifa);
+ }
+ }
+ else
+ {
+ OSPF_TRACE(D_EVENTS,
+ "Changing state of iface: %s from \"%s\" into \"%s\".",
+ ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
+ if (ifa->iface->flags & IF_MULTICAST)
+ {
+ if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
{
- DBG("%s: Adding new multicast socket for (B)DR\n", p->name);
- ifa->dr_sk = sk_new(p->pool);
- ifa->dr_sk->type = SK_IP_MC;
- ifa->dr_sk->sport = 0;
- ifa->dr_sk->dport = OSPF_PROTO;
- ifa->dr_sk->saddr = AllDRouters;
- ifa->dr_sk->daddr = AllDRouters;
- ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL;
- ifa->dr_sk->ttl = 1;
- ifa->dr_sk->rx_hook = ospf_rx_hook;
- ifa->dr_sk->tx_hook = ospf_tx_hook;
- ifa->dr_sk->err_hook = ospf_err_hook;
- ifa->dr_sk->iface = ifa->iface;
- ifa->dr_sk->rbsize = ifa->iface->mtu;
- ifa->dr_sk->tbsize = ifa->iface->mtu;
- ifa->dr_sk->data = (void *) ifa;
- if (sk_open(ifa->dr_sk) != 0)
+ if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA))
{
- DBG("%s: SK_OPEN: new? mc open failed.\n", p->name);
+ DBG("%s: Adding new multicast socket for (B)DR\n", p->name);
+ ifa->dr_sk = sk_new(p->pool);
+ ifa->dr_sk->type = SK_IP_MC;
+ ifa->dr_sk->sport = 0;
+ ifa->dr_sk->dport = OSPF_PROTO;
+ ifa->dr_sk->saddr = AllDRouters;
+ ifa->dr_sk->daddr = AllDRouters;
+ ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL;
+ ifa->dr_sk->ttl = 1;
+ ifa->dr_sk->rx_hook = ospf_rx_hook;
+ ifa->dr_sk->tx_hook = ospf_tx_hook;
+ ifa->dr_sk->err_hook = ospf_err_hook;
+ ifa->dr_sk->iface = ifa->iface;
+ ifa->dr_sk->rbsize = ifa->iface->mtu;
+ ifa->dr_sk->tbsize = ifa->iface->mtu;
+ ifa->dr_sk->data = (void *) ifa;
+ if (sk_open(ifa->dr_sk) != 0)
+ {
+ DBG("%s: SK_OPEN: new? mc open failed.\n", p->name);
+ }
}
}
- }
- else
- {
- rfree(ifa->dr_sk);
- ifa->dr_sk = NULL;
- }
- if ((oldstate == OSPF_IS_DR) && (ifa->nlsa != NULL))
- {
- ifa->nlsa->lsa.age = LSA_MAXAGE;
- if (state >= OSPF_IS_WAITING)
+ else
{
- ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa);
+ rfree(ifa->dr_sk);
+ ifa->dr_sk = NULL;
+ }
+ if ((oldstate == OSPF_IS_DR) && (ifa->nlsa != NULL))
+ {
+ ifa->nlsa->lsa.age = LSA_MAXAGE;
+ if (state >= OSPF_IS_WAITING)
+ {
+ ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa);
+ }
+ if (can_flush_lsa(ifa->oa))
+ flush_lsa(ifa->nlsa, ifa->oa);
+ ifa->nlsa = NULL;
}
- if (can_flush_lsa(ifa->oa))
- flush_lsa(ifa->nlsa, ifa->oa);
- ifa->nlsa = NULL;
}
}
}
@@ -120,6 +166,16 @@ ospf_iface_down(struct ospf_iface *ifa)
struct proto_ospf *po = ifa->proto;
struct ospf_iface *iff;
+ /* First of all kill all the related vlinks */
+ if (ifa->type != OSPF_IT_VLINK)
+ {
+ WALK_LIST(iff, po->iface_list)
+ {
+ if ((iff->type == OSPF_IT_VLINK) && (iff->iface == ifa->iface))
+ ospf_iface_down(iff);
+ }
+ }
+
WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
{
OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
@@ -129,7 +185,7 @@ ospf_iface_down(struct ospf_iface *ifa)
rfree(ifa->dr_sk);
rfree(ifa->ip_sk);
- if(ifa->type == OSPF_IT_VLINK)
+ if (ifa->type == OSPF_IT_VLINK)
{
ifa->ip_sk = NULL;
ifa->iface = NULL;
@@ -144,7 +200,6 @@ ospf_iface_down(struct ospf_iface *ifa)
rem_node(NODE ifa);
mb_free(ifa);
}
- /* FIXME: Should I down related VLINK also? */
}
/**
@@ -168,13 +223,10 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
if (ifa->state == OSPF_IS_DOWN)
{
/* Now, nothing should be adjacent */
- tm_start(ifa->hello_timer, ifa->helloint);
-
- if (ifa->poll_timer)
- tm_start(ifa->poll_timer, ifa->pollint);
-
if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK))
+ {
ospf_iface_chstate(ifa, OSPF_IS_PTP);
+ }
else
{
if (ifa->priority == 0)
@@ -185,6 +237,12 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
tm_start(ifa->wait_timer, ifa->waitint);
}
}
+
+ tm_start(ifa->hello_timer, ifa->helloint);
+
+ if (ifa->poll_timer)
+ tm_start(ifa->poll_timer, ifa->pollint);
+
hello_timer_hook(ifa->hello_timer);
}
schedule_rt_lsa(ifa->oa);
@@ -257,37 +315,6 @@ ospf_open_mc_socket(struct ospf_iface *ifa)
return (mcsk);
}
-static sock *
-ospf_open_ip_socket(struct ospf_iface *ifa)
-{
- sock *ipsk;
- struct proto *p;
-
- p = (struct proto *) (ifa->proto);
-
- ipsk = sk_new(p->pool);
- ipsk->type = SK_IP;
- ipsk->dport = OSPF_PROTO;
- ipsk->saddr = ifa->iface->addr->ip;
- ipsk->tos = IP_PREC_INTERNET_CONTROL;
- ipsk->ttl = 1;
- if (ifa->type == OSPF_IT_VLINK) ipsk->ttl = 255;
- ipsk->rx_hook = ospf_rx_hook;
- ipsk->tx_hook = ospf_tx_hook;
- ipsk->err_hook = ospf_err_hook;
- ipsk->iface = ifa->iface;
- ipsk->rbsize = ifa->iface->mtu;
- ipsk->tbsize = ifa->iface->mtu;
- ipsk->data = (void *) ifa;
- if (sk_open(ipsk) != 0)
- {
- DBG("%s: SK_OPEN: ip open failed.\n", p->name);
- return (NULL);
- }
- DBG("%s: SK_OPEN: ip opened.\n", p->name);
- return (ipsk);
-}
-
u8
ospf_iface_clasify(struct iface * ifa)
{
@@ -306,7 +333,7 @@ ospf_iface_find(struct proto_ospf *p, struct iface *what)
{
struct ospf_iface *i;
- WALK_LIST(i, p->iface_list) if ((i)->iface == what)
+ WALK_LIST(i, p->iface_list) if ((i->iface == what) && (i->type != OSPF_IT_VLINK))
return i;
return NULL;
}
@@ -350,7 +377,8 @@ ospf_iface_add(struct object_lock *lock)
}
void
-ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_config *ac, struct ospf_iface_patt *ip)
+ospf_iface_new(struct proto_ospf *po, struct iface *iface,
+ struct ospf_area_config *ac, struct ospf_iface_patt *ip)
{
struct proto *p = &po->proto;
struct ospf_iface *ifa;
@@ -362,7 +390,6 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf
ifa->proto = po;
ifa->iface = iface;
- ifa->an = ac->areaid;
ifa->cost = ip->cost;
ifa->rxmtint = ip->rxmtint;
ifa->inftransdelay = ip->inftransdelay;
@@ -383,6 +410,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf
init_list(&ifa->neigh_list);
init_list(&ifa->nbma_list);
+
WALK_LIST(nb, ip->nbma_list)
{
nbma = mb_alloc(p->pool, sizeof(struct nbma_node));
@@ -420,23 +448,26 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf
add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
ifa->state = OSPF_IS_DOWN;
+ ifa->oa = NULL;
WALK_LIST(oa, po->area_list)
{
- if (oa->areaid == ifa->an)
+ if (oa->areaid == ac->areaid)
+ {
+ ifa->oa = oa;
break;
+ }
}
- if (EMPTY_LIST(po->area_list) || (oa->areaid != ifa->an)) /* New area */
+ if (!ifa->oa)
bug("Cannot add any area to accepted Interface");
else
- ifa->oa = oa;
if (ifa->type == OSPF_IT_VLINK)
{
ifa->oa = po->backbone;
ifa->voa = oa;
ifa->vid = ip->vid;
- return; /* Don't lock, don't add sockets */
+ return; /* Don't lock, don't add sockets */
}
lock = olock_new(p->pool);
@@ -536,9 +567,19 @@ ospf_iface_info(struct ospf_iface *ifa)
if ((ifa->type != OSPF_IT_NBMA) || (ifa->strictnbma == 0))
strict = "";
- cli_msg(-1015, "Interface \"%s\":", ifa->iface->name);
- cli_msg(-1015, "\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid);
- cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict);
+ if (ifa->type == OSPF_IT_VLINK)
+ {
+ cli_msg(-1015, "Virtual link to %I:", ifa->vid);
+ cli_msg(-1015, "\tTransit area: %I (%u)", ifa->voa->areaid,
+ ifa->voa->areaid);
+ }
+ else
+ {
+ cli_msg(-1015, "Interface \"%s\":",
+ (ifa->iface ? ifa->iface->name : "(none)"));
+ cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict);
+ cli_msg(-1015, "\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid);
+ }
cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state],
ifa->stub ? "(stub)" : "");
cli_msg(-1015, "\tPriority: %u", ifa->priority);
diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c
index 7ea8304..b244c3f 100644
--- a/proto/ospf/lsalib.c
+++ b/proto/ospf/lsalib.c
@@ -55,8 +55,8 @@ ospf_age(struct ospf_area *oa)
en->color = OUTSPF;
en->dist = LSINFINITY;
en->nhi = NULL;
- en->nh = ipa_from_u32(0);
- en->lb = ipa_from_u32(0);
+ en->nh = IPA_NONE;
+ en->lb = IPA_NONE;
DBG("Infinitying Type: %u, Id: %I, Rt: %I\n", en->lsa.type, en->lsa.id,
en->lsa.rt);
}
diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c
index 44d35d9..51b38af 100644
--- a/proto/ospf/lsupd.c
+++ b/proto/ospf/lsupd.c
@@ -152,10 +152,10 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
struct ospf_packet *op;
struct ospf_lsa_header *lh;
- if (ifa->type == OSPF_IT_NBMA)
+ if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
sk = ifa->ip_sk;
else
- sk = ifa->hello_sk; /* FIXME is this true for PTP? */
+ sk = ifa->hello_sk;
pk = (struct ospf_lsupd_packet *) sk->tbuf;
op = (struct ospf_packet *) sk->tbuf;
@@ -192,16 +192,23 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
op->length = htons(len);
OSPF_TRACE(D_PACKETS, "LS upd flooded via %s", ifa->iface->name);
+ DBG("ID=%I, AGE=%d, SEQ=%x", ntohl(lh->id), ntohs(lh->age),
+ ntohl(lh->sn));
- if (ifa->type == OSPF_IT_NBMA)
+ switch (ifa->type)
{
+ case OSPF_IT_NBMA:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
else
ospf_send_to_bdr(sk, ifa);
- }
- else
- {
+ break;
+
+ case OSPF_IT_VLINK:
+ ospf_send_to(sk, ifa->vip, ifa);
+ break;
+
+ default:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
(ifa->type == OSPF_IT_PTP))
ospf_send_to(sk, AllSPFRouters, ifa);
@@ -243,6 +250,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
if ((en = ospf_hash_find(n->ifa->oa->gr, llsh->lsh.id, llsh->lsh.rt,
llsh->lsh.type)) == NULL)
continue; /* Probably flushed LSA */
+ /* FIXME This is a bug! I cannot flush LSA that is in lsrt */
DBG("Sending ID=%I, Type=%u, RT=%I Sn: 0x%x Age: %u\n",
llsh->lsh.id, llsh->lsh.type, llsh->lsh.rt, en->lsa.sn, en->lsa.age);
@@ -395,8 +403,9 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
{
WALK_LIST(nifa, po->iface_list)
{
- if (ipa_compare(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)) ==
- 0)
+ if (!nifa->iface)
+ continue;
+ if (ipa_equal(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)))
{
self = 1;
break;
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c
index e9ef476..869db2b 100644
--- a/proto/ospf/neighbor.c
+++ b/proto/ospf/neighbor.c
@@ -122,6 +122,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);
}
if (state == NEIGHBOR_EXSTART)
@@ -422,12 +423,12 @@ bdr_election(struct ospf_iface *ifa)
|| ((ifa->bdrid != myid) && (nbdr == &me)))
{
if (ndr == NULL)
- ifa->drip = me.dr = ipa_from_u32(0);
+ ifa->drip = me.dr = IPA_NONE;
else
ifa->drip = me.dr = ndr->ip;
if (nbdr == NULL)
- ifa->bdrip = me.bdr = ipa_from_u32(0);
+ ifa->bdrip = me.bdr = IPA_NONE;
else
ifa->bdrip = me.bdr = nbdr->ip;
@@ -436,12 +437,12 @@ bdr_election(struct ospf_iface *ifa)
}
if (ndr == NULL)
- ndrip = ipa_from_u32(0);
+ ndrip = IPA_NONE;
else
ndrip = ndr->ip;
if (nbdr == NULL)
- nbdrip = ipa_from_u32(0);
+ nbdrip = IPA_NONE;
else
nbdrip = nbdr->ip;
@@ -453,7 +454,7 @@ bdr_election(struct ospf_iface *ifa)
if (ndr == NULL)
{
ifa->drid = 0;
- ifa->drip = ipa_from_u32(0);
+ ifa->drip = IPA_NONE;
}
else
{
@@ -464,7 +465,7 @@ bdr_election(struct ospf_iface *ifa)
if (nbdr == NULL)
{
ifa->bdrid = 0;
- ifa->bdrip = ipa_from_u32(0);
+ ifa->bdrip = IPA_NONE;
}
else
{
@@ -591,11 +592,12 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
pos = "dr ";
if (n->rid == ifa->bdrid)
pos = "bdr ";
- if (n->ifa->type == OSPF_IT_PTP)
+ if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_VLINK))
pos = "ptp ";
cli_msg(-1013, "%-1I\t%3u\t%s/%s\t%-5s\t%-1I\t%-10s", n->rid, n->priority,
- ospf_ns[n->state], pos, etime, n->ip, ifa->iface->name);
+ ospf_ns[n->state], pos, etime, n->ip,
+ (ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name));
}
void
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index ccdc502..8f6b217 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -45,7 +45,7 @@
* Every area has its own area_disp() which is
* responsible for late originating of router LSA, calculating
* of the routing table and it also ages and flushes the LSAs. This
- * function is called in regular intervals.
+ * function is called in regular intervals from ospf_disp()
* To every &ospf_iface, we connect one or more
* &ospf_neighbor's -- a structure containing many timers and queues
* for building adjacency and for exchange of routing messages.
@@ -72,7 +72,6 @@
static int ospf_rte_better(struct rte *new, struct rte *old);
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
@@ -135,18 +134,11 @@ ospf_start(struct proto *p)
add_tail(&po->area_list, NODE oa);
po->areano++;
oa->stub = ac->stub;
- oa->tick = ac->tick;
oa->areaid = ac->areaid;
oa->gr = ospf_top_new(p->pool);
s_init_list(&(oa->lsal));
oa->rt = NULL;
oa->po = po;
- 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);
add_area_nets(oa, ac);
fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
if (oa->areaid == 0) po->backbone = oa;
@@ -160,10 +152,8 @@ ospf_start(struct proto *p)
struct ospf_iface_patt *ipatt;
WALK_LIST(ac, c->area_list)
{
- WALK_LIST(ipatt, ac->patt_list)
- {
- if (ipatt->type == OSPF_IT_VLINK) ospf_iface_new(po, NULL, ac, ipatt);
- }
+ WALK_LIST(ipatt, ac->vlink_list)
+ ospf_iface_new(po, NULL, ac, ipatt);
}
}
return PS_UP;
@@ -181,7 +171,7 @@ ospf_dump(struct proto *p)
WALK_LIST(ifa, po->iface_list)
{
- OSPF_TRACE(D_EVENTS, "Interface: %s", ifa->iface->name);
+ OSPF_TRACE(D_EVENTS, "Interface: %s", (ifa->iface ? ifa->iface->name : "(null)"));
OSPF_TRACE(D_EVENTS, "state: %u", ifa->state);
OSPF_TRACE(D_EVENTS, "DR: %I", ifa->drid);
OSPF_TRACE(D_EVENTS, "BDR: %I", ifa->bdrid);
@@ -311,9 +301,8 @@ schedule_rtcalc(struct proto_ospf *po)
* function for origination of router LSA and network LSAs.
*/
void
-area_disp(timer * timer)
+area_disp(struct ospf_area *oa)
{
- struct ospf_area *oa = timer->data;
struct proto_ospf *po = oa->po;
struct ospf_iface *ifa;
@@ -324,7 +313,7 @@ area_disp(timer * timer)
/* Now try to originate network LSA's */
WALK_LIST(ifa, po->iface_list)
{
- if (ifa->orignet && (ifa->an == oa->areaid))
+ if (ifa->orignet && (ifa->oa == oa))
originate_net_lsa(ifa);
}
@@ -336,6 +325,10 @@ void
ospf_disp(timer * timer)
{
struct proto_ospf *po = timer->data;
+ struct ospf_area *oa;
+
+ WALK_LIST(oa, po->area_list)
+ area_disp(oa);
/* Calculate routing table */
if (po->calcrt)
@@ -555,6 +548,13 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
struct area_net *anet, *antmp;
int found;
+ /* FIXME Temporarily disabled */
+
+ return !memcmp(((byte *) old) + sizeof(struct proto_config),
+ ((byte *) new) + sizeof(struct proto_config),
+ sizeof(struct ospf_config) - sizeof(struct proto_config));
+
+
po->rfc1583 = new->rfc1583;
schedule_rtcalc(po);
@@ -576,19 +576,6 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
if (!oa)
return 0;
- if (ac1->tick != ac2->tick)
- {
- if (oa->areaid == ac2->areaid)
- {
- oa->tick = ac2->tick;
- tm_start(oa->disp_timer, oa->tick);
- OSPF_TRACE(D_EVENTS,
- "Changing tick interval on area %I from %d to %d",
- oa->areaid, ac1->tick, ac2->tick);
- break;
- }
- }
-
/* Change net_list */
fib_free(&oa->net_fib);
add_area_nets(oa, ac2);
@@ -840,6 +827,8 @@ ospf_sh(struct proto *p)
}
cli_msg(-1014, "%s:", p->name);
+ cli_msg(-1014, "RFC1583 compatibility: %s", (po->rfc1583 ? "enable" : "disabled"));
+ cli_msg(-1014, "RT scheduler tick: %d", po->tick);
cli_msg(-1014, "Number of areas: %u", po->areano);
WALK_LIST(oa, po->area_list)
@@ -852,16 +841,18 @@ ospf_sh(struct proto *p)
WALK_LIST(ifa, po->iface_list)
{
if (oa == ifa->oa)
- ifano++;
- WALK_LIST(n, ifa->neigh_list)
{
- nno++;
- if (n->state == NEIGHBOR_FULL)
- adjno++;
+ ifano++;
+ WALK_LIST(n, ifa->neigh_list)
+ {
+ nno++;
+ if (n->state == NEIGHBOR_FULL)
+ adjno++;
+ }
}
}
cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No");
- cli_msg(-1014, "\t\tRT scheduler tick:\t%u", oa->tick);
+ cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No");
cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano);
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);
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index 13a5f82..40452c2 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -52,8 +52,7 @@
#define LSINFINITY 0xffffff
#define DEFAULT_OSPFTICK 1
-#define DEFAULT_AREATICK 1
-#define DEFAULT_RFC1583 1 /* compatibility with rfc1583 */
+#define DEFAULT_RFC1583 0 /* compatibility with rfc1583 */
struct ospf_config
@@ -90,8 +89,8 @@ struct ospf_area_config
node n;
u32 areaid;
int stub;
- unsigned tick;
list patt_list;
+ list vlink_list;
list net_list;
};
@@ -130,7 +129,6 @@ struct ospf_iface
struct iface *iface; /* Nest's iface */
struct ospf_area *oa;
struct object_lock *lock;
- u32 an; /* Area number */
sock *hello_sk; /* Hello socket */
sock *dr_sk; /* For states DR or BACKUP */
sock *ip_sk; /* IP socket (for DD ...) */
@@ -519,7 +517,6 @@ struct ospf_area
int stub;
int trcap; /* Transit capability? */
struct proto_ospf *po;
- unsigned tick;
struct fib rtr; /* Routing tables for routers */
union options opt; /* RFC2328 - A.2 */
};
diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c
index 488a3a2..92e0522 100644
--- a/proto/ospf/packet.c
+++ b/proto/ospf/packet.c
@@ -25,7 +25,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
pkt->type = h_type;
pkt->routerid = htonl(p->cf->global->router_id);
- pkt->areaid = htonl(ifa->an);
+ pkt->areaid = htonl(ifa->oa->areaid);
pkt->autype = htons(ifa->autype);
pkt->checksum = 0;
}
@@ -219,17 +219,32 @@ ospf_rx_hook(sock * sk, int size)
{
struct ospf_packet *ps;
struct ospf_iface *ifa = (struct ospf_iface *) (sk->data);
+ struct proto_ospf *po = ifa->proto;
struct proto *p = (struct proto *) (ifa->proto);
struct ospf_neighbor *n;
int osize;
char *mesg = "Bad OSPF packet from ";
+ struct ospf_iface *iff;
if (ifa->stub)
return (1);
+ ps = (struct ospf_packet *) ipv4_skip_header(sk->rbuf, &size);
+
+ if ((ifa->oa->areaid != 0) && (ntohl(ps->areaid) == 0))
+ {
+ WALK_LIST(iff, po->iface_list)
+ {
+ if ((iff->type == OSPF_IT_VLINK) && (iff->iface == ifa->iface) &&
+ (iff->voa = ifa->oa) && ipa_equal(sk->faddr, iff->vip))
+ {
+ return 1; /* Packet is for VLINK */
+ }
+ }
+ }
+
DBG("%s: RX_Hook called on interface %s.\n", p->name, sk->iface->name);
- ps = (struct ospf_packet *) ipv4_skip_header(sk->rbuf, &size);
osize = ntohs(ps->length);
if (ps == NULL)
{
@@ -263,7 +278,7 @@ ospf_rx_hook(sock * sk, int size)
return 1;
}
- if (ntohl(ps->areaid) != ifa->an)
+ if (ntohl(ps->areaid) != ifa->oa->areaid)
{
log(L_ERR "%s%I - other area %ld", mesg, sk->faddr, ps->areaid);
return 1;
@@ -374,9 +389,9 @@ ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state)
void
ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa)
{
- if (ipa_compare(ifa->drip, ipa_from_u32(0)) != 0)
+ if (!ipa_equal(ifa->drip, IPA_NONE))
ospf_send_to(sk, ifa->drip, ifa);
- if (ipa_compare(ifa->bdrip, ipa_from_u32(0)) != 0)
+ if (!ipa_equal(ifa->bdrip, IPA_NONE))
ospf_send_to(sk, ifa->bdrip, ifa);
}
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 3d2ee51..ef3d44d 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -9,7 +9,7 @@
#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);
+ struct top_hash_entry *par, u16 dist, struct ospf_area *oa, int vlink);
static void
calc_next_hop(struct top_hash_entry *en,
struct top_hash_entry *par, struct ospf_area *oa);
@@ -24,7 +24,7 @@ fill_ri(orta * orta)
orta->oa = NULL;
orta->metric1 = LSINFINITY;
orta->metric2 = LSINFINITY;
- orta->nh = ipa_from_u32(0);
+ orta->nh = IPA_NONE;
orta->ifa = NULL;
orta->ar = NULL;
orta->tag = 0;
@@ -63,8 +63,7 @@ ri_better(struct proto_ospf *po, orta * new, ort *nefn, orta * old, ort *oefn, i
{
if(new->oa->areaid == 0) newtype = RTS_OSPF_IA;
if(old->oa->areaid == 0) oldtype = RTS_OSPF_IA;
-
-}
+ }
if (new->type < old->type)
return 1;
@@ -146,6 +145,7 @@ 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)
@@ -155,7 +155,7 @@ ospf_rt_spfa(struct ospf_area *oa)
oa->areaid);
if (oa->rt->dist != LSINFINITY)
- ospf_age(oa);
+ bug("Aging was not processed.");
init_list(&oa->cand); /* Empty list of candidates */
oa->trcap = 0;
@@ -202,6 +202,7 @@ 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);
@@ -238,6 +239,7 @@ ospf_rt_spfa(struct ospf_area *oa)
break;
case LSART_VLNK:
+ vlink = 1;
case LSART_PTP:
tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT);
DBG("PTP found.\n");
@@ -249,7 +251,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);
+ add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa, vlink);
}
break;
case LSA_T_NET:
@@ -275,7 +277,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);
+ add_cand(&oa->cand, tmp, act, act->dist, oa, 0);
}
break;
}
@@ -287,15 +289,24 @@ ospf_rt_spfa(struct ospf_area *oa)
if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa))
{
if ((tmp = ospf_hash_find(oa->gr, iface->vid, iface->vid, LSA_T_RT)) &&
- ipa_equal(tmp->lb, IPA_NONE))
+ (!ipa_equal(tmp->lb, IPA_NONE)))
{
- DBG("Vlink peer found\n");
- ospf_iface_sm(iface, ISM_UP); /* FIXME: Add slave iface! */
+ if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi) || (!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->vip = tmp->lb;
+ ospf_iface_sm(iface, ISM_UP);
+ }
}
else
{
- DBG("Vlink peer not found\n");
- ospf_iface_sm(iface, ISM_DOWN);
+ if (iface->state > OSPF_IS_DOWN)
+ {
+ OSPF_TRACE(D_EVENTS, "Vlink peer %I lost", iface->vid);
+ ospf_iface_sm(iface, ISM_DOWN);
+ }
}
}
}
@@ -367,7 +378,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
{
struct proto *p = &oa->po->proto;
struct proto_ospf *po = oa->po;
- struct ospf_area *bb, *atmp;
+ struct ospf_area *bb = po->backbone;
ip_addr *mask, ip, abrip;
struct top_hash_entry *en;
int mlen = -1, type = -1;
@@ -375,17 +386,6 @@ ospf_rt_sum_tr(struct ospf_area *oa)
ort *re = NULL, *abr;
orta nf;
- bb = NULL;
-
- WALK_LIST(atmp, po->area_list)
- {
- if(atmp->areaid == 0)
- {
- bb = atmp;
- break;
- }
- }
-
if(!bb) return;
WALK_SLIST(en, oa->lsal)
@@ -672,7 +672,7 @@ ospf_ext_spfa(struct ospf_area *oa)
if (!(nf1->n.capa & ORTA_ASBR))
continue; /* It is not ASBR */
- if (ipa_compare(lt->fwaddr, ipa_from_u32(0)) == 0)
+ if (ipa_equal(lt->fwaddr, IPA_NONE))
{
if (lt->etm.etos.ebit)
{ /* FW address == 0 */
@@ -742,7 +742,7 @@ ospf_ext_spfa(struct ospf_area *oa)
/* 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)
+ u16 dist, struct ospf_area *oa, int vlink)
{
node *prev, *n;
int added = 0;
@@ -773,6 +773,7 @@ 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 */
@@ -901,8 +902,9 @@ rt_sync(struct proto_ospf *po)
struct fib_iterator fit;
struct fib *fib = &po->rtf;
ort *nf;
- struct ospf_area *oa;
+ struct ospf_area *oa, *oaa;
struct area_net *anet;
+ int flush;
OSPF_TRACE(D_EVENTS, "Starting routing table synchronisation");
@@ -929,6 +931,27 @@ again1:
a0.aflags = 0;
a0.iface = nf->n.ifa;
a0.gw = nf->n.nh;
+ if(!neigh_find(p, &nf->n.nh, 0))
+ {
+ int found = 0;
+ struct ospf_iface *ifa;
+ struct top_hash_entry *en;
+ DBG("Trying to find correct next hop");
+ WALK_LIST(ifa, po->iface_list)
+ {
+ if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh))
+ {
+ if ((en = ospf_hash_find(ifa->voa->gr, ifa->vid, ifa->vid, LSA_T_RT)) &&
+ (!ipa_equal(en->nh, IPA_NONE)))
+ {
+ a0.gw = en->nh;
+ found = 1;
+ }
+ break;
+ }
+ }
+ 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)
@@ -978,10 +1001,17 @@ again2:
/* Check condensed summary LSAs */
FIB_WALK(&oa->net_fib, nftmp)
{
+ flush = 1;
anet = (struct area_net *) nftmp;
if((!anet->hidden) && anet->active && (!oa->trcap))
- originate_sum_lsa(oa, &anet->fn, ORT_NET, 1);
- else flush_sum_lsa(oa, &anet->fn, ORT_NET);
+ flush = 0;
+
+ WALK_LIST(oaa, po->area_list)
+ {
+ if (oaa == oa) continue;
+ if(flush) flush_sum_lsa(oaa, &anet->fn, ORT_NET);
+ else originate_sum_lsa(oaa, &anet->fn, ORT_NET, 1);
+ }
}
FIB_WALK_END;
}
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 562ddb5..4854721 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -36,7 +36,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
WALK_LIST(ifa, po->iface_list)
{
- if ((ifa->an == oa->areaid) && (ifa->state != OSPF_IS_DOWN))
+ if ((ifa->oa == oa) && (ifa->state != OSPF_IS_DOWN))
{
i++;
}
@@ -51,7 +51,10 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
WALK_LIST(ifa, po->iface_list)
{
- if ((ifa->an != oa->areaid) || (ifa->state == OSPF_IS_DOWN))
+ if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (ifa->state > OSPF_IS_DOWN))
+ rt->veb.bit.v = 1;
+
+ if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
continue;
if (ifa->state == OSPF_IS_LOOP)
@@ -146,7 +149,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
ln->id = neigh->rid;
ln->metric = ifa->cost;
ln->notos = 0;
- rt->veb.bit.v = 1;
}
else
{
@@ -351,14 +353,14 @@ originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po,
et->etm.etos.ebit = 1;
}
et->tag = tag;
- if (ipa_compare(e->attrs->gw, ipa_from_u32(0)) != 0)
+ if (!ipa_equal(e->attrs->gw, IPA_NONE))
{
if (ospf_iface_find((struct proto_ospf *) p, e->attrs->iface) != NULL)
inas = 1;
}
if (!inas)
- et->fwaddr = ipa_from_u32(0);
+ et->fwaddr = IPA_NONE;
else
et->fwaddr = e->attrs->gw;
return ext;
@@ -416,7 +418,8 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
{
en->lsa.age = LSA_MAXAGE;
en->lsa.sn = LSA_MAXSEQNO;
- OSPF_TRACE(D_EVENTS, "Flushing summary lsa.");
+ lsasum_calculate(&en->lsa, sum);
+ OSPF_TRACE(D_EVENTS, "Flushing summary lsa. (id=%I, type=%d)", en->lsa.id, en->lsa.type);
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
if (can_flush_lsa(oa)) flush_lsa(en, oa);
break;
@@ -425,9 +428,6 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
}
}
-
-
-
void
originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric)
{
@@ -436,8 +436,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
struct top_hash_entry *en;
u32 rtid = po->proto.cf->global->router_id;
struct ospf_lsa_header lsa;
- void *body = NULL;
- int i, max, mlen = fn->pxlen, found = 0, free = -1;
+ int i, max, mlen = fn->pxlen, free = 0;
struct ospf_lsa_sum *sum = NULL;
union ospf_lsa_sum_tm *tm;
lsa.type = LSA_T_SUM_NET;
@@ -461,7 +460,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
lsa.id = ipa_to_u32(fn->prefix) + i;
if ((en = ospf_hash_find_header(oa->gr, &lsa)) == NULL)
{
- if (free < 0) free = i;
+ if (!free) free = lsa.id;
}
else
{
@@ -477,7 +476,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
}
}
- if(free < 0)
+ if(!free)
{
log("%s: got more routes for one /%d network then %d, ignoring", p->name,
fn->pxlen, max);
@@ -485,9 +484,6 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
}
lsa.id = free;
- sum = en->lsa_body;
- tm = (union ospf_lsa_sum_tm *) (sum + 1);
-
OSPF_TRACE(D_EVENTS, "Originating summary (type %d) lsa for %I/%d.", lsa.type, fn->prefix,
fn->pxlen);
@@ -497,8 +493,8 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
tm->metric = metric;
tm->tos.tos = 0;
- lsasum_calculate(&lsa, body);
- en = lsa_install_new(&lsa, body, oa);
+ lsasum_calculate(&lsa, sum);
+ en = lsa_install_new(&lsa, sum, oa);
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
}
@@ -515,6 +511,12 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
if ((nf->n.type > RTS_OSPF_IA) && (nf->o.type > RTS_OSPF_IA)) return;
+#ifdef LOCAL_DEBUG
+ DBG("Checking...dest = %d, %I/%d", dest, nf->fn.prefix, nf->fn.pxlen);
+ if (nf->n.oa) DBG("New: met=%d, oa=%d", nf->n.metric1, nf->n.oa->areaid);
+ if (nf->o.oa) DBG("Old: met=%d, oa=%d", nf->o.metric1, nf->o.oa->areaid);
+#endif
+
WALK_LIST(oa, po->area_list)
{
flush = 0;
@@ -522,7 +524,7 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
flush = 1;
if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR)))
flush = 1;
- if (nf->n.oa->areaid == oa->areaid)
+ if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid))
flush = 1;
/* FIXME: Test next hop - is it in actual area? */
if ((dest == ORT_ROUTER) && oa->stub)
@@ -531,7 +533,8 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
mlen = nf->fn.pxlen;
ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen));
- if((!oa->trcap) && fib_route(&oa->net_fib, ip, mlen)) /* The route fits into some area */
+ 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... */
@@ -543,20 +546,6 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
}
}
-void
-check_sum_areas(struct proto_ospf *po)
-{
- struct proto *p = &po->proto;
- struct ospf_area *oa;
- struct area_net *anet;
-
- WALK_LIST(oa, po->area_list)
- {
- ; /* FIXME */
- }
-}
-
-
/**
* originate_ext_lsa - new route received from nest and filters
* @n: network prefix and mask
@@ -806,8 +795,8 @@ ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type)
e->color = OUTSPF;
e->dist = LSINFINITY;
e->nhi = NULL;
- e->nh = ipa_from_u32(0);
- e->lb = ipa_from_u32(0);
+ e->nh = IPA_NONE;
+ e->lb = IPA_NONE;
e->lsa.id = lsa;
e->lsa.rt = rtr;
e->lsa.type = type;
@@ -852,8 +841,8 @@ ospf_top_dump(struct top_graph *f, struct proto *p)
struct top_hash_entry *e = f->hash_table[i];
while (e)
{
- OSPF_TRACE(D_EVENTS, "\t%1x %-1I %-1I %4u 0x%08x",
- e->lsa.type, e->lsa.id, e->lsa.rt, e->lsa.age, e->lsa.sn);
+ OSPF_TRACE(D_EVENTS, "\t%1x %-1I %-1I %4u 0x%08x 0x%04x",
+ e->lsa.type, e->lsa.id, e->lsa.rt, e->lsa.age, e->lsa.sn, e->lsa.checksum);
e = e->next;
}
}