A lot of changes:
- metric is 3 byte long now - summary lsa originating - more OSPF areas possible - virtual links - better E1/E2 routes handling - some bug fixes.. I have to do: - md5 auth (last mandatory item from rfc2328) - !!!!DEBUG!!!!! (mainly virtual link system has probably a lot of bugs) - 2328 appendig E
This commit is contained in:
parent
5ed68e46d7
commit
98ac61766d
23 changed files with 1116 additions and 452 deletions
2
TODO
2
TODO
|
@ -51,7 +51,5 @@ OSPF
|
|||
- automatic generation of external route tags (RFC1403)
|
||||
- RFC1587 NSSA areas
|
||||
- RFC2370 opaque LSA's
|
||||
- respect interface MTU and try not to create larger packets unless unavoidable
|
||||
- AS external LSAs are in topology database of every OSPF Area
|
||||
- Limit export rate of external LSAs (like Gated does)
|
||||
- Maximal distance is just 0xffff, but 2328 requires 0xffffff
|
||||
|
|
|
@ -1034,6 +1034,16 @@ protocol ospf <name> {
|
|||
<ip> eligible;
|
||||
};
|
||||
};
|
||||
virtual link <id>
|
||||
{
|
||||
hello <num>;
|
||||
poll <num>;
|
||||
retransmit <num>;
|
||||
wait <num>;
|
||||
dead count <num>;
|
||||
authentication [none|simple];
|
||||
password "<text>";
|
||||
};
|
||||
};
|
||||
}
|
||||
</code>
|
||||
|
@ -1068,6 +1078,10 @@ protocol ospf <name> {
|
|||
<tag>interface <M>pattern</M></tag>
|
||||
Defines that the specified interfaces belong to the area being defined.
|
||||
|
||||
<tag>virtual link <M>id</M></tag>
|
||||
Virtual link to router with the router id. This item cannot be in the
|
||||
backbone area (ID 0).
|
||||
|
||||
<tag>cost <M>num</M></tag>
|
||||
Specifies output cost (metric) of an interface. Default value is 10.
|
||||
|
||||
|
@ -1185,6 +1199,10 @@ protocol ospf MyOSPF {
|
|||
};
|
||||
area 120 {
|
||||
stub yes;
|
||||
networks {
|
||||
172.16.1.0/24;
|
||||
172.16.2.0/24 hidden;
|
||||
}
|
||||
interface "-arc0" , "arc*" {
|
||||
type nonbroadcast;
|
||||
authentication none;
|
||||
|
|
|
@ -25,7 +25,7 @@ CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFA
|
|||
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREIMPORT)
|
||||
|
||||
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
|
||||
RIP, OSPF, OSPF_EXT, OSPF_IA, BGP, PIPE)
|
||||
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
|
||||
CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE)
|
||||
CF_ENUM(T_ENUM_RTC, RTC_, UNICAST, BROADCAST, MULTICAST, ANYCAST)
|
||||
CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT)
|
||||
|
|
|
@ -253,9 +253,10 @@ typedef struct rta {
|
|||
#define RTS_RIP 6 /* RIP route */
|
||||
#define RTS_OSPF 7 /* OSPF route */
|
||||
#define RTS_OSPF_IA 8 /* OSPF inter-area route */
|
||||
#define RTS_OSPF_EXT 9 /* OSPF external route */
|
||||
#define RTS_BGP 10 /* BGP route */
|
||||
#define RTS_PIPE 11 /* Inter-table wormhole */
|
||||
#define RTS_OSPF_EXT1 9 /* OSPF external route type 1 */
|
||||
#define RTS_OSPF_EXT2 10 /* OSPF external route type 2 */
|
||||
#define RTS_BGP 11 /* BGP route */
|
||||
#define RTS_PIPE 12 /* Inter-table wormhole */
|
||||
|
||||
#define RTC_UNICAST 0
|
||||
#define RTC_BROADCAST 1
|
||||
|
|
|
@ -705,7 +705,8 @@ rta_dump(rta *a)
|
|||
{
|
||||
static char *rts[] = { "RTS_DUMMY", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE",
|
||||
"RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP",
|
||||
"RTS_OSPF", "RTS_OSPF_EXT", "RTS_OSPF_IA", "RTS_BGP" };
|
||||
"RTS_OSPF", "RTS_OSPF_IA", "RTS_OSPF_EXT1",
|
||||
"RTS_OSPF_EXT2", "RTS_BGP" };
|
||||
static char *rtc[] = { "", " BC", " MC", " AC" };
|
||||
static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" };
|
||||
|
||||
|
|
|
@ -560,7 +560,7 @@ bgp_create_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p
|
|||
ea->count = 4;
|
||||
|
||||
bgp_set_attr(ea->attrs, pool, BA_ORIGIN,
|
||||
(rta->source == RTS_OSPF_EXT) ? ORIGIN_INCOMPLETE : ORIGIN_IGP);
|
||||
((rta->source == RTS_OSPF_EXT1) || (rta->source == RTS_OSPF_EXT2)) ? ORIGIN_INCOMPLETE : ORIGIN_IGP);
|
||||
|
||||
if (p->is_internal)
|
||||
bgp_set_attr(ea->attrs+1, pool, BA_AS_PATH, 0);
|
||||
|
|
|
@ -17,7 +17,7 @@ static struct ospf_area_config *this_area;
|
|||
static struct iface_patt *this_ipatt;
|
||||
#define OSPF_PATT ((struct ospf_iface_patt *) this_ipatt)
|
||||
static struct nbma_node *this_nbma;
|
||||
static struct area_net *this_pref;
|
||||
static struct area_net_config *this_pref;
|
||||
|
||||
CF_DECLS
|
||||
|
||||
|
@ -25,7 +25,7 @@ CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG)
|
|||
CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
|
||||
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE)
|
||||
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, PASSWORD, STRICT)
|
||||
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN)
|
||||
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, LINK)
|
||||
|
||||
%type <t> opttext
|
||||
|
||||
|
@ -78,6 +78,44 @@ ospf_area_item:
|
|||
| 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_start ospf_vlink_opts
|
||||
;
|
||||
|
||||
ospf_vlink_opts:
|
||||
/* empty */
|
||||
| ospf_vlink_opts ospf_vlink_item ';'
|
||||
;
|
||||
|
||||
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"); }
|
||||
| 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 ; }
|
||||
| DEAD COUNT expr { OSPF_PATT->deadc = $3 ; if ($3<=1) cf_error("Dead count must be greater than one"); }
|
||||
| AUTHENTICATION NONE { OSPF_PATT->autype = AU_NONE ; }
|
||||
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = AU_SIMPLE ; }
|
||||
| PASSWORD TEXT { memcpy(OSPF_PATT->password, $2, 8); }
|
||||
;
|
||||
|
||||
ospf_vlink_start: VIRTUAL LINK '{'
|
||||
{
|
||||
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);
|
||||
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;
|
||||
OSPF_PATT->autype = AU_NONE;
|
||||
}
|
||||
;
|
||||
|
||||
ospf_iface_item:
|
||||
|
@ -111,7 +149,7 @@ pref_item:
|
|||
|
||||
pref_el: prefix ';'
|
||||
{
|
||||
this_pref = cfg_allocz(sizeof(struct area_net));
|
||||
this_pref = cfg_allocz(sizeof(struct area_net_config));
|
||||
add_tail(&this_area->net_list, NODE this_pref);
|
||||
this_pref->px.addr = $1.addr;
|
||||
this_pref->px.len = $1.len;
|
||||
|
@ -120,7 +158,7 @@ pref_el: prefix ';'
|
|||
|
||||
pref_hid: prefix HIDDEN ';'
|
||||
{
|
||||
this_pref = cfg_allocz(sizeof(struct area_net));
|
||||
this_pref = cfg_allocz(sizeof(struct area_net_config));
|
||||
add_tail(&this_area->net_list, NODE this_pref);
|
||||
this_pref->px.addr = $1.addr;
|
||||
this_pref->px.len = $1.len;
|
||||
|
|
|
@ -39,14 +39,14 @@ ospf_dbdes_send(struct ospf_neighbor *n)
|
|||
pkt = (struct ospf_dbdes_packet *) (ifa->ip_sk->tbuf);
|
||||
op = (struct ospf_packet *) pkt;
|
||||
fill_ospf_pkt_hdr(ifa, pkt, DBDES_P);
|
||||
pkt->iface_mtu = htons(ifa->iface->mtu); /* FIXME NOT for VLINK! */
|
||||
pkt->iface_mtu = htons(ifa->iface->mtu);
|
||||
pkt->options = ifa->options;
|
||||
pkt->imms = n->myimms;
|
||||
pkt->ddseq = htonl(n->dds);
|
||||
length = sizeof(struct ospf_dbdes_packet);
|
||||
op->length = htons(length);
|
||||
ospf_pkt_finalize(ifa, op);
|
||||
sk_send_to(ifa->ip_sk, length, n->ip, OSPF_PROTO);
|
||||
ospf_send_to(ifa->ip_sk, length, n->ip);
|
||||
OSPF_TRACE(D_PACKETS, "DB_DES (I) sent to %I via %s.", n->ip,
|
||||
ifa->iface->name);
|
||||
break;
|
||||
|
@ -79,20 +79,26 @@ ospf_dbdes_send(struct ospf_neighbor *n)
|
|||
for (; i > 0; i--)
|
||||
{
|
||||
struct top_hash_entry *en;
|
||||
|
||||
en = (struct top_hash_entry *) sn;
|
||||
|
||||
if ((n->ifa->type != OSPF_IT_VLINK) && (en->lsa.type != LSA_T_EXT))
|
||||
{
|
||||
htonlsah(&(en->lsa), lsa);
|
||||
DBG("Working on: %d\n", i);
|
||||
DBG("\tX%01x %-1I %-1I %p\n", en->lsa.type, en->lsa.id,
|
||||
en->lsa.rt, en->lsa_body);
|
||||
|
||||
lsa++;
|
||||
}
|
||||
else i++; /* No lsa added */
|
||||
|
||||
if (sn == STAIL(n->ifa->oa->lsal))
|
||||
{
|
||||
i--;
|
||||
break; /* Should set some flag? */
|
||||
break;
|
||||
}
|
||||
|
||||
sn = sn->next;
|
||||
lsa++;
|
||||
}
|
||||
|
||||
if (sn == STAIL(n->ifa->oa->lsal))
|
||||
|
@ -130,7 +136,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
|
|||
memcpy(ifa->ip_sk->tbuf, n->ldbdes, length);
|
||||
/* Copy last sent packet again */
|
||||
|
||||
sk_send_to(ifa->ip_sk, length, n->ip, OSPF_PROTO);
|
||||
ospf_send_to(ifa->ip_sk, length, n->ip);
|
||||
|
||||
if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
|
||||
|
||||
|
@ -245,8 +251,6 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
|||
ps->imms.byte);
|
||||
break;
|
||||
}
|
||||
if(ps->imms.bit.i) log("FUCK");
|
||||
|
||||
case NEIGHBOR_EXCHANGE:
|
||||
if ((ps->imms.byte == n->imms.byte) && (ps->options == n->options) &&
|
||||
(ntohl(ps->ddseq) == n->ddr))
|
||||
|
|
|
@ -166,16 +166,20 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
|
|||
struct ospf_hello_packet *pkt;
|
||||
struct ospf_packet *op;
|
||||
struct proto *p;
|
||||
struct ospf_neighbor *neigh;
|
||||
struct ospf_neighbor *neigh, *n1;
|
||||
u16 length;
|
||||
u32 *pp;
|
||||
int i;
|
||||
int i, send;
|
||||
struct nbma_node *nb;
|
||||
|
||||
if (timer == NULL)
|
||||
ifa = dirn->ifa;
|
||||
else
|
||||
ifa = (struct ospf_iface *) timer->data;
|
||||
|
||||
if (ifa->state == OSPF_IS_DOWN)
|
||||
return;
|
||||
|
||||
if (ifa->stub)
|
||||
return; /* Don't send any packet on stub iface */
|
||||
|
||||
|
@ -184,13 +188,13 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
|
|||
p->name, ifa->iface->name);
|
||||
/* Now we should send a hello packet */
|
||||
/* First a common packet header */
|
||||
if (ifa->type != OSPF_IT_NBMA)
|
||||
if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
|
||||
{
|
||||
pkt = (struct ospf_hello_packet *) (ifa->hello_sk->tbuf);
|
||||
pkt = (struct ospf_hello_packet *) (ifa->ip_sk->tbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt = (struct ospf_hello_packet *) (ifa->ip_sk->tbuf);
|
||||
pkt = (struct ospf_hello_packet *) (ifa->hello_sk->tbuf);
|
||||
}
|
||||
|
||||
/* Now fill ospf_hello header */
|
||||
|
@ -224,19 +228,12 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
|
|||
ospf_pkt_finalize(ifa, op);
|
||||
|
||||
/* And finally send it :-) */
|
||||
if (ifa->type != OSPF_IT_NBMA)
|
||||
switch(ifa->type)
|
||||
{
|
||||
sk_send(ifa->hello_sk, length);
|
||||
}
|
||||
else /* NBMA */
|
||||
{
|
||||
struct ospf_neighbor *n1;
|
||||
struct nbma_node *nb;
|
||||
int send;
|
||||
|
||||
case OSPF_IT_NBMA:
|
||||
if (timer == NULL) /* Response to received hello */
|
||||
{
|
||||
sk_send_to(ifa->ip_sk, length, dirn->ip, OSPF_PROTO);
|
||||
ospf_send_to(ifa->ip_sk, length, dirn->ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -261,7 +258,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
|
|||
if ((poll == 1) && (send))
|
||||
{
|
||||
if (toall || (meeli && nb->eligible))
|
||||
sk_send_to(ifa->ip_sk, length, nb->ip, OSPF_PROTO);
|
||||
ospf_send_to(ifa->ip_sk, length, nb->ip);
|
||||
}
|
||||
}
|
||||
if (poll == 0)
|
||||
|
@ -270,10 +267,16 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
|
|||
{
|
||||
if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
|
||||
(meeli && (n1->priority > 0)))
|
||||
sk_send_to(ifa->ip_sk, length, n1->ip, OSPF_PROTO);
|
||||
ospf_send_to(ifa->ip_sk, length, n1->ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OSPF_IT_VLINK:
|
||||
ospf_send_to(ifa->ip_sk, length, ifa->vip);
|
||||
break;
|
||||
default:
|
||||
sk_send(ifa->hello_sk, length);
|
||||
}
|
||||
OSPF_TRACE(D_PACKETS, "Hello sent via %s", ifa->iface->name);
|
||||
}
|
||||
|
|
|
@ -117,32 +117,42 @@ ospf_iface_down(struct ospf_iface *ifa)
|
|||
{
|
||||
struct ospf_neighbor *n, *nx;
|
||||
struct proto *p = &ifa->proto->proto;
|
||||
struct proto_ospf *po = ifa->proto;
|
||||
struct ospf_iface *iff;
|
||||
|
||||
WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
|
||||
ospf_neigh_remove(n);
|
||||
}
|
||||
rem_node(NODE ifa);
|
||||
|
||||
rfree(ifa->hello_sk);
|
||||
rfree(ifa->dr_sk);
|
||||
rfree(ifa->ip_sk);
|
||||
|
||||
if(ifa->type == OSPF_IT_VLINK)
|
||||
{
|
||||
ifa->ip_sk = NULL;
|
||||
ifa->iface = NULL;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
rfree(ifa->wait_timer);
|
||||
rfree(ifa->hello_timer);
|
||||
rfree(ifa->poll_timer);
|
||||
|
||||
rfree(ifa->lock);
|
||||
rem_node(NODE ifa);
|
||||
mb_free(ifa);
|
||||
}
|
||||
/* FIXME: Should I down related VLINK also? */
|
||||
}
|
||||
|
||||
/**
|
||||
* ospf_iface_sm - OSPF interface state machine
|
||||
* @ifa: OSPF interface
|
||||
* @event: event comming to state machine
|
||||
*
|
||||
* This fully respect 9.3 of RFC 2328 except we don't use %LOOP state of
|
||||
* This fully respects 9.3 of RFC 2328 except we don't use %LOOP state of
|
||||
* interface.
|
||||
*/
|
||||
void
|
||||
|
@ -260,6 +270,7 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
|
|||
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;
|
||||
|
@ -307,6 +318,8 @@ ospf_iface_add(struct object_lock *lock)
|
|||
struct iface *iface = lock->iface;
|
||||
struct proto *p = &po->proto;
|
||||
|
||||
ifa->lock = lock;
|
||||
|
||||
ifa->ioprob = OSPF_I_OK;
|
||||
|
||||
if (ifa->type != OSPF_IT_NBMA)
|
||||
|
@ -330,41 +343,20 @@ ospf_iface_add(struct object_lock *lock)
|
|||
ifa->stub = 1;
|
||||
ifa->ioprob += OSPF_I_IP;
|
||||
}
|
||||
ifa->lock = lock;
|
||||
|
||||
ifa->state = OSPF_IS_DOWN;
|
||||
ospf_iface_sm(ifa, ISM_UP);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
|
||||
ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_config *ac, struct ospf_iface_patt *ip)
|
||||
{
|
||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||
struct ospf_config *c = (struct ospf_config *) (p->cf);
|
||||
struct ospf_area_config *ac;
|
||||
struct ospf_iface_patt *ip = NULL;
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_iface *ifa;
|
||||
struct object_lock *lock;
|
||||
struct nbma_node *nbma, *nb;
|
||||
struct object_lock *lock;
|
||||
struct ospf_area *oa;
|
||||
|
||||
DBG("%s: If notify called\n", p->name);
|
||||
if (iface->flags & IF_IGNORE)
|
||||
return;
|
||||
|
||||
if (flags & IF_CHANGE_UP)
|
||||
{
|
||||
WALK_LIST(ac, c->area_list)
|
||||
{
|
||||
if (ip = (struct ospf_iface_patt *)
|
||||
iface_patt_match(&ac->patt_list, iface))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ip)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Using interface %s.", iface->name);
|
||||
|
||||
ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
|
||||
ifa->proto = po;
|
||||
ifa->iface = iface;
|
||||
|
@ -428,15 +420,7 @@ ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
|
|||
add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
|
||||
ifa->state = OSPF_IS_DOWN;
|
||||
|
||||
lock = olock_new(p->pool);
|
||||
lock->addr = AllSPFRouters;
|
||||
lock->type = OBJLOCK_IP;
|
||||
lock->port = OSPF_PROTO;
|
||||
lock->iface = iface;
|
||||
lock->data = ifa;
|
||||
lock->hook = ospf_iface_add;
|
||||
|
||||
WALK_LIST(NODE oa, po->area_list)
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
if (oa->areaid == ifa->an)
|
||||
break;
|
||||
|
@ -447,8 +431,53 @@ ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
|
|||
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 */
|
||||
}
|
||||
|
||||
lock = olock_new(p->pool);
|
||||
lock->addr = AllSPFRouters;
|
||||
lock->type = OBJLOCK_IP;
|
||||
lock->port = OSPF_PROTO;
|
||||
lock->iface = iface;
|
||||
lock->data = ifa;
|
||||
lock->hook = ospf_iface_add;
|
||||
|
||||
olock_acquire(lock);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
|
||||
{
|
||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||
struct ospf_config *c = (struct ospf_config *) (p->cf);
|
||||
struct ospf_area_config *ac;
|
||||
struct ospf_iface_patt *ip = NULL;
|
||||
struct ospf_iface *ifa;
|
||||
struct ospf_area *oa;
|
||||
|
||||
DBG("%s: If notify called\n", p->name);
|
||||
if (iface->flags & IF_IGNORE)
|
||||
return;
|
||||
|
||||
if (flags & IF_CHANGE_UP)
|
||||
{
|
||||
WALK_LIST(ac, c->area_list)
|
||||
{
|
||||
if (ip = (struct ospf_iface_patt *)
|
||||
iface_patt_match(&ac->patt_list, iface))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ip)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Using interface %s.", iface->name);
|
||||
ospf_iface_new(po, iface, ac, ip);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & IF_CHANGE_DOWN)
|
||||
|
|
|
@ -16,5 +16,6 @@ struct ospf_iface *ospf_iface_find(struct proto_ospf *p, struct iface *what);
|
|||
void ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface);
|
||||
void ospf_iface_info(struct ospf_iface *ifa);
|
||||
void ospf_iface_shutdown(struct ospf_iface *ifa);
|
||||
void ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_config *ac, struct ospf_iface_patt *ip);
|
||||
|
||||
#endif /* _BIRD_OSPF_IFACE_H_ */
|
||||
|
|
|
@ -78,16 +78,16 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
|||
if (ifa->type == OSPF_IT_BCAST)
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
sk_send_to(sk, len, AllSPFRouters, OSPF_PROTO);
|
||||
ospf_send_to(sk, len, AllSPFRouters);
|
||||
else
|
||||
sk_send_to(sk, len, AllDRouters, OSPF_PROTO);
|
||||
ospf_send_to(sk, len, AllDRouters);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
|
||||
ospf_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
|
||||
else
|
||||
sk_send_to_bdr(sk, len, ifa);
|
||||
ospf_send_to_bdr(sk, len, ifa);
|
||||
}
|
||||
|
||||
fill_ospf_pkt_hdr(n->ifa, pk, LSACK_P);
|
||||
|
@ -104,16 +104,16 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
|||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
{
|
||||
sk_send_to(sk, len, AllSPFRouters, OSPF_PROTO);
|
||||
ospf_send_to(sk, len, AllSPFRouters);
|
||||
}
|
||||
else
|
||||
{
|
||||
sk_send_to(sk, len, AllDRouters, OSPF_PROTO);
|
||||
ospf_send_to(sk, len, AllDRouters);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
|
||||
ospf_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ flush_lsa(struct top_hash_entry *en, struct ospf_area *oa)
|
|||
{
|
||||
struct proto *p = &oa->po->proto;
|
||||
OSPF_TRACE(D_EVENTS,
|
||||
"Going to remove node Type: %u, Id: %I, Rt: %I, Age: %u",
|
||||
en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age);
|
||||
"Going to remove node Type: %u, Id: %I, Rt: %I, Age: %u, SN: 0x%x",
|
||||
en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn);
|
||||
s_rem_node(SNODE en);
|
||||
if (en->lsa_body != NULL)
|
||||
mb_free(en->lsa_body);
|
||||
|
@ -56,6 +56,7 @@ ospf_age(struct ospf_area *oa)
|
|||
en->dist = LSINFINITY;
|
||||
en->nhi = NULL;
|
||||
en->nh = ipa_from_u32(0);
|
||||
en->lb = ipa_from_u32(0);
|
||||
DBG("Infinitying Type: %u, Id: %I, Rt: %I\n", en->lsa.type, en->lsa.id,
|
||||
en->lsa.rt);
|
||||
}
|
||||
|
@ -164,8 +165,8 @@ htonlsab(void *h, void *n, u8 type, u16 len)
|
|||
case LSA_T_SUM_NET:
|
||||
case LSA_T_SUM_RT:
|
||||
{
|
||||
struct ospf_lsa_summ *hs, *ns;
|
||||
struct ospf_lsa_summ_net *hn, *nn;
|
||||
struct ospf_lsa_sum *hs, *ns;
|
||||
union ospf_lsa_sum_tm *hn, *nn;
|
||||
|
||||
hs = h;
|
||||
ns = n;
|
||||
|
@ -173,15 +174,16 @@ htonlsab(void *h, void *n, u8 type, u16 len)
|
|||
ns->netmask = hs->netmask;
|
||||
ipa_hton(ns->netmask);
|
||||
|
||||
hn = (struct ospf_lsa_summ_net *) (hs + 1);
|
||||
nn = (struct ospf_lsa_summ_net *) (ns + 1);
|
||||
hn = (union ospf_lsa_sum_tm *) (hs + 1);
|
||||
nn = (union ospf_lsa_sum_tm *) (ns + 1);
|
||||
|
||||
for (i = 0; i < ((len - sizeof(struct ospf_lsa_summ)) /
|
||||
sizeof(struct ospf_lsa_summ_net)); i++)
|
||||
for (i = 0; i < ((len - sizeof(struct ospf_lsa_sum)) /
|
||||
sizeof(union ospf_lsa_sum_tm)); i++)
|
||||
{
|
||||
(nn + i)->tos = (hn + i)->tos;
|
||||
(nn + i)->metric = htons((hn + i)->metric);
|
||||
(nn + i)->padding = 0;
|
||||
(nn + i)->metric = htonl((hn + i)->metric);
|
||||
//(nn + i)->tos = (hn + i)->tos;
|
||||
//(nn + i)->metric = htons((hn + i)->metric);
|
||||
//(nn + i)->padding = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -202,9 +204,10 @@ htonlsab(void *h, void *n, u8 type, u16 len)
|
|||
for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) /
|
||||
sizeof(struct ospf_lsa_ext_tos)); i++)
|
||||
{
|
||||
(nt + i)->etos = (ht + i)->etos;
|
||||
(nt + i)->padding = 0;
|
||||
(nt + i)->metric = htons((ht + i)->metric);
|
||||
(nt + i)->etm.metric = htonl((ht + i)->etm.metric);
|
||||
//(nt + i)->tos = (ht + i)->tos;
|
||||
//(nt + i)->padding = 0;
|
||||
//(nt + i)->metric = htons((ht + i)->metric);
|
||||
(nt + i)->fwaddr = (ht + i)->fwaddr;
|
||||
ipa_hton((nt + i)->fwaddr);
|
||||
(nt + i)->tag = htonl((ht + i)->tag);
|
||||
|
@ -262,8 +265,8 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
|
|||
case LSA_T_SUM_NET:
|
||||
case LSA_T_SUM_RT:
|
||||
{
|
||||
struct ospf_lsa_summ *hs, *ns;
|
||||
struct ospf_lsa_summ_net *hn, *nn;
|
||||
struct ospf_lsa_sum *hs, *ns;
|
||||
union ospf_lsa_sum_tm *hn, *nn;
|
||||
|
||||
hs = h;
|
||||
ns = n;
|
||||
|
@ -271,15 +274,16 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
|
|||
hs->netmask = ns->netmask;
|
||||
ipa_ntoh(hs->netmask);
|
||||
|
||||
hn = (struct ospf_lsa_summ_net *) (hs + 1);
|
||||
nn = (struct ospf_lsa_summ_net *) (ns + 1);
|
||||
hn = (union ospf_lsa_sum_tm *) (hs + 1);
|
||||
nn = (union ospf_lsa_sum_tm *) (ns + 1);
|
||||
|
||||
for (i = 0; i < ((len - sizeof(struct ospf_lsa_summ)) /
|
||||
sizeof(struct ospf_lsa_summ_net)); i++)
|
||||
for (i = 0; i < ((len - sizeof(struct ospf_lsa_sum)) /
|
||||
sizeof(union ospf_lsa_sum_tm)); i++)
|
||||
{
|
||||
(hn + i)->tos = (nn + i)->tos;
|
||||
(hn + i)->metric = ntohs((nn + i)->metric);
|
||||
(hn + i)->padding = 0;
|
||||
(hn + i)->metric = ntohl((nn + i)->metric);
|
||||
//(hn + i)->tos = (nn + i)->tos;
|
||||
//(hn + i)->metric = ntohs((nn + i)->metric);
|
||||
//(hn + i)->padding = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -300,9 +304,10 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
|
|||
for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) /
|
||||
sizeof(struct ospf_lsa_ext_tos)); i++)
|
||||
{
|
||||
(ht + i)->etos = (nt + i)->etos;
|
||||
(ht + i)->padding = 0;
|
||||
(ht + i)->metric = ntohs((nt + i)->metric);
|
||||
(ht + i)->etm.metric = ntohl((nt + i)->etm.metric);
|
||||
//(ht + i)->etos = (nt + i)->etos;
|
||||
//(ht + i)->padding = 0;
|
||||
//(ht + i)->metric = ntohs((nt + i)->metric);
|
||||
(ht + i)->fwaddr = (nt + i)->fwaddr;
|
||||
ipa_ntoh((ht + i)->fwaddr);
|
||||
(ht + i)->tag = ntohl((nt + i)->tag);
|
||||
|
|
|
@ -60,7 +60,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
|
|||
i) * sizeof(struct ospf_lsreq_header);
|
||||
op->length = htons(length);
|
||||
ospf_pkt_finalize(n->ifa, op);
|
||||
sk_send_to(n->ifa->ip_sk, length, n->ip, OSPF_PROTO);
|
||||
ospf_send_to(n->ifa->ip_sk, length, n->ip);
|
||||
OSPF_TRACE(D_PACKETS, "LS request sent to: %I", n->rid);
|
||||
}
|
||||
|
||||
|
|
|
@ -197,17 +197,17 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
|||
if (ifa->type == OSPF_IT_NBMA)
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
|
||||
sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
|
||||
ospf_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
|
||||
else
|
||||
sk_send_to_bdr(sk, len, ifa);
|
||||
ospf_send_to_bdr(sk, len, ifa);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
|
||||
(ifa->type == OSPF_IT_PTP))
|
||||
sk_send_to(sk, len, AllSPFRouters, OSPF_PROTO);
|
||||
ospf_send_to(sk, len, AllSPFRouters);
|
||||
else
|
||||
sk_send_to(sk, len, AllDRouters, OSPF_PROTO);
|
||||
ospf_send_to(sk, len, AllDRouters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
|
|||
op->length = htons(len - SIPH);
|
||||
ospf_pkt_finalize(n->ifa, op);
|
||||
|
||||
sk_send_to(n->ifa->ip_sk, len - SIPH, n->ip, OSPF_PROTO);
|
||||
ospf_send_to(n->ifa->ip_sk, len - SIPH, n->ip);
|
||||
OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano);
|
||||
|
||||
DBG("LSupd: next packet\n");
|
||||
|
@ -277,7 +277,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
|
|||
ospf_pkt_finalize(n->ifa, op);
|
||||
|
||||
OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano);
|
||||
sk_send_to(n->ifa->ip_sk, len - SIPH, n->ip, OSPF_PROTO);
|
||||
ospf_send_to(n->ifa->ip_sk, len - SIPH, n->ip);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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->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 (old->u.ospf.metric2 == LSINFINITY)
|
||||
return 0; /* Old is E1, new is E2 */
|
||||
return 1; /* 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;
|
||||
}
|
||||
|
||||
if (new->u.ospf.metric2 > old->u.ospf.metric2)
|
||||
{
|
||||
if (new->u.ospf.metric2 == LSINFINITY)
|
||||
return 1; /* New is E1, old is E2 */
|
||||
return 0; /* Both are E2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
anet = (struct area_net *) nftmp;
|
||||
if(firstfib)
|
||||
{
|
||||
struct area_net *anet;
|
||||
cli_msg(-1014, "\t\tArea networks:");
|
||||
WALK_LIST(anet, oa->net_list)
|
||||
{
|
||||
cli_msg(-1014, "\t\t\t%1I/%u\t%s", anet->px.addr, anet->px.len,
|
||||
anet->hidden ? "Hidden" : "Advertise");
|
||||
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, "");
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
@ -50,7 +50,7 @@
|
|||
#define LSREFRESHTIME 1800 /* 30 minutes */
|
||||
#define MINLSINTERVAL 5
|
||||
#define MINLSARRIVAL 1
|
||||
#define LSINFINITY 0xffff /* RFC says 0xffffff ??? */
|
||||
#define LSINFINITY 0xffffff
|
||||
|
||||
#define DEFAULT_OSPFTICK 5
|
||||
#define DEFAULT_AREATICK 4
|
||||
|
@ -72,13 +72,18 @@ struct nbma_node
|
|||
int eligible;
|
||||
};
|
||||
|
||||
struct area_net
|
||||
struct area_net_config
|
||||
{
|
||||
node n;
|
||||
struct prefix px;
|
||||
int hidden;
|
||||
};
|
||||
|
||||
struct area_net
|
||||
{
|
||||
struct fib_node fn;
|
||||
int hidden;
|
||||
int active;
|
||||
int oldactive;
|
||||
};
|
||||
|
||||
struct ospf_area_config
|
||||
|
@ -113,6 +118,9 @@ struct ospf_iface
|
|||
u32 rxmtint; /* number of seconds between LSA retransmissions */
|
||||
u32 pollint; /* Poll interval */
|
||||
u32 deadc; /* after "deadint" missing hellos is router dead */
|
||||
u32 vid; /* Id of peer of virtual link */
|
||||
ip_addr vip; /* IP of peer of virtual link */
|
||||
struct ospf_area *voa; /* Area wich the vlink goes through */
|
||||
u16 autype;
|
||||
u8 aukey[8];
|
||||
u8 options;
|
||||
|
@ -299,28 +307,61 @@ struct ospf_lsa_net
|
|||
ip_addr netmask;
|
||||
};
|
||||
|
||||
struct ospf_lsa_summ
|
||||
struct ospf_lsa_sum
|
||||
{
|
||||
ip_addr netmask;
|
||||
};
|
||||
|
||||
struct ospf_lsa_summ_net
|
||||
{
|
||||
u8 tos;
|
||||
u8 padding;
|
||||
u16 metric;
|
||||
};
|
||||
|
||||
struct ospf_lsa_ext
|
||||
{
|
||||
ip_addr netmask;
|
||||
};
|
||||
|
||||
struct ospf_lsa_ext_etos
|
||||
{
|
||||
#ifdef _BIG_ENDIAN
|
||||
u8 ebit:1;
|
||||
u8 tos:7;
|
||||
u8 padding1;
|
||||
u16 padding2;
|
||||
#else
|
||||
u16 padding2;
|
||||
u8 padding1;
|
||||
u8 tos:7;
|
||||
u8 ebit:1;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define METRIC_MASK 0x00FFFFFF
|
||||
struct ospf_lsa_sum_tos
|
||||
{
|
||||
#ifdef _BIG_ENDIAN
|
||||
u8 tos;
|
||||
u8 padding1;
|
||||
u16 padding2;
|
||||
#else
|
||||
u16 padding2;
|
||||
u8 padding1;
|
||||
u8 tos;
|
||||
#endif
|
||||
};
|
||||
|
||||
union ospf_lsa_sum_tm
|
||||
{
|
||||
struct ospf_lsa_sum_tos tos;
|
||||
u32 metric;
|
||||
};
|
||||
|
||||
union ospf_lsa_ext_etm
|
||||
{
|
||||
struct ospf_lsa_ext_etos etos;
|
||||
u32 metric;
|
||||
};
|
||||
|
||||
struct ospf_lsa_ext_tos
|
||||
{
|
||||
u8 etos;
|
||||
u8 padding;
|
||||
u16 metric;
|
||||
union ospf_lsa_ext_etm etm;
|
||||
ip_addr fwaddr;
|
||||
u32 tag;
|
||||
};
|
||||
|
@ -432,11 +473,12 @@ struct ospf_area
|
|||
slist lsal; /* List of all LSA's */
|
||||
struct top_hash_entry *rt; /* My own router LSA */
|
||||
list cand; /* List of candidates for RT calc. */
|
||||
list net_list; /* Networks to advertise or not */
|
||||
struct fib net_fib; /* Networks to advertise or not */
|
||||
int stub;
|
||||
int trcap; /* Transit capability? */
|
||||
struct proto_ospf *po;
|
||||
unsigned tick;
|
||||
struct fib rtr; /* Routing tables for routers */
|
||||
};
|
||||
|
||||
struct proto_ospf
|
||||
|
@ -448,9 +490,10 @@ struct proto_ospf
|
|||
list iface_list; /* Interfaces we really use */
|
||||
list area_list;
|
||||
int areano; /* Number of area I belong to */
|
||||
struct fib rtf[2]; /* Routing tables */
|
||||
struct fib rtf; /* Routing table */
|
||||
int rfc1583; /* RFC1583 compatibility */
|
||||
int ebit; /* Did I originate any ext lsa? */
|
||||
struct ospf_area *backbone; /* If exists */
|
||||
};
|
||||
|
||||
struct ospf_iface_patt
|
||||
|
@ -468,6 +511,7 @@ struct ospf_iface_patt
|
|||
u32 autype;
|
||||
u32 strictnbma;
|
||||
u32 stub;
|
||||
u32 vid;
|
||||
/* must be in network byte order */
|
||||
#define AU_NONE htons(0)
|
||||
#define AU_SIMPLE htons(1)
|
||||
|
@ -493,6 +537,7 @@ void ospf_sh_iface(struct proto *p, char *iff);
|
|||
#define EA_OSPF_METRIC2 EA_CODE(EAP_OSPF, 1)
|
||||
#define EA_OSPF_TAG EA_CODE(EAP_OSPF, 2)
|
||||
|
||||
#include "proto/ospf/rt.h"
|
||||
#include "proto/ospf/hello.h"
|
||||
#include "proto/ospf/packet.h"
|
||||
#include "proto/ospf/iface.h"
|
||||
|
@ -503,6 +548,5 @@ void ospf_sh_iface(struct proto *p, char *iff);
|
|||
#include "proto/ospf/lsupd.h"
|
||||
#include "proto/ospf/lsack.h"
|
||||
#include "proto/ospf/lsalib.h"
|
||||
#include "proto/ospf/rt.h"
|
||||
|
||||
#endif /* _BIRD_OSPF_H_ */
|
||||
|
|
|
@ -226,19 +226,26 @@ ospf_err_hook(sock * sk, int err UNUSED)
|
|||
}
|
||||
|
||||
void
|
||||
sk_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state)
|
||||
ospf_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state)
|
||||
{
|
||||
struct ospf_neighbor *n;
|
||||
|
||||
WALK_LIST(NODE n, ifa->neigh_list) if (n->state >= state)
|
||||
sk_send_to(sk, len, n->ip, OSPF_PROTO);
|
||||
ospf_send_to(sk, len, n->ip);
|
||||
}
|
||||
|
||||
void
|
||||
sk_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa)
|
||||
ospf_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa)
|
||||
{
|
||||
if (ipa_compare(ifa->drip, ipa_from_u32(0)) != 0)
|
||||
sk_send_to(sk, len, ifa->drip, OSPF_PROTO);
|
||||
ospf_send_to(sk, len, ifa->drip);
|
||||
if (ipa_compare(ifa->bdrip, ipa_from_u32(0)) != 0)
|
||||
sk_send_to(sk, len, ifa->bdrip, OSPF_PROTO);
|
||||
ospf_send_to(sk, len, ifa->bdrip);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_send_to(sock *sk, u16 len, ip_addr ip)
|
||||
{
|
||||
sk_send_to(sk, len, ip, OSPF_PROTO);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,9 @@ void ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt);
|
|||
int ospf_rx_hook(sock * sk, int size);
|
||||
void ospf_tx_hook(sock * sk);
|
||||
void ospf_err_hook(sock * sk, int err);
|
||||
void sk_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state);
|
||||
void sk_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa);
|
||||
void ospf_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state);
|
||||
void ospf_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa);
|
||||
void ospf_send_to(sock *sk, u16 len, ip_addr ip);
|
||||
|
||||
|
||||
#endif /* _BIRD_OSPF_PACKET_H_ */
|
||||
|
|
497
proto/ospf/rt.c
497
proto/ospf/rt.c
|
@ -21,8 +21,6 @@ fill_ri(orta * orta)
|
|||
{
|
||||
orta->type = RTS_DUMMY;
|
||||
orta->capa = 0;
|
||||
#define ORTA_ASBR 1
|
||||
#define ORTA_ABR 2
|
||||
orta->oa = NULL;
|
||||
orta->metric1 = LSINFINITY;
|
||||
orta->metric2 = LSINFINITY;
|
||||
|
@ -37,13 +35,20 @@ ospf_rt_initort(struct fib_node *fn)
|
|||
{
|
||||
ort *ri = (ort *) fn;
|
||||
fill_ri(&ri->n);
|
||||
ri->dest = ORT_UNDEF;
|
||||
memcpy(&ri->o, &ri->n, sizeof(orta));
|
||||
ri->efn = NULL;
|
||||
}
|
||||
|
||||
/* If new is better return 1 */
|
||||
|
||||
/*
|
||||
* This is hard to understand:
|
||||
* If rfc1583 is set to 1, it work likes normal route_better()
|
||||
* But if it is set to 0, it prunes number of AS bondary
|
||||
* routes before it starts the router decision
|
||||
*/
|
||||
static int
|
||||
ri_better(struct proto_ospf *po, orta * new, orta * old)
|
||||
ri_better(struct proto_ospf *po, orta * new, ort *nefn, orta * old, ort *oefn, int rfc1583)
|
||||
{
|
||||
int newtype = new->type;
|
||||
int oldtype = old->type;
|
||||
|
@ -54,41 +59,44 @@ ri_better(struct proto_ospf *po, orta * new, orta * old)
|
|||
if (old->metric1 == LSINFINITY)
|
||||
return 1;
|
||||
|
||||
if (po->rfc1583)
|
||||
if(!rfc1583)
|
||||
{
|
||||
if ((newtype == RTS_OSPF) && (new->oa->areaid == 0)) newtype = RTS_OSPF_IA;
|
||||
if ((oldtype == RTS_OSPF) && (old->oa->areaid == 0)) oldtype = RTS_OSPF_IA;
|
||||
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;
|
||||
|
||||
if (new->metric2 < old->metric2)
|
||||
{
|
||||
if (old->metric2 == LSINFINITY)
|
||||
return 0; /* Old is E1, new is E2 */
|
||||
if (new->type > old->type)
|
||||
return 0;
|
||||
|
||||
return 1; /* Both are E2 */
|
||||
}
|
||||
if (new->metric2 > old->metric2)
|
||||
/* Same type */
|
||||
if(new->type == RTS_OSPF_EXT2)
|
||||
{
|
||||
if (new->metric2 == LSINFINITY)
|
||||
return 1; /* New is E1, old is E2 */
|
||||
|
||||
return 0; /* Both are E2 */
|
||||
if (new->metric2 < old->metric2) return 1;
|
||||
if (new->metric2 > old->metric2) return 0;
|
||||
}
|
||||
|
||||
if(((new->type == RTS_OSPF_EXT2) || (new->type == RTS_OSPF_EXT1)) && (!po->rfc1583))
|
||||
{
|
||||
int newtype = nefn->n.type;
|
||||
int oldtype = oefn->n.type;
|
||||
|
||||
if(nefn->n.oa->areaid == 0) newtype = RTS_OSPF_IA;
|
||||
if(oefn->n.oa->areaid == 0) oldtype = RTS_OSPF_IA;
|
||||
|
||||
if(newtype < oldtype) return 1;
|
||||
if(newtype > oldtype) return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* E2 metrics are the same. It means that: 1) Paths are E2 with same
|
||||
* metric 2) Paths are E1.
|
||||
*/
|
||||
if (new->metric1 < old->metric1)
|
||||
return 1;
|
||||
|
||||
if (new->metric1 > old->metric1)
|
||||
return 0;
|
||||
|
||||
/* Metric 1 are the same */
|
||||
if (new->oa->areaid > old->oa->areaid) return 1; /* Larger AREAID is preffered */
|
||||
|
||||
return 0; /* Old is shorter or same */
|
||||
|
@ -96,26 +104,35 @@ ri_better(struct proto_ospf *po, orta * new, orta * old)
|
|||
|
||||
static void
|
||||
ri_install(struct proto_ospf *po, ip_addr prefix, int pxlen, int dest,
|
||||
orta * new)
|
||||
orta * new, ort * ipath)
|
||||
{
|
||||
ort *old = (ort *) fib_get(&po->rtf[dest], &prefix, pxlen);
|
||||
struct ospf_area *oa = new->oa;
|
||||
ort *old;
|
||||
|
||||
if (ri_better(po, new, &old->n))
|
||||
if (dest == ORT_NET)
|
||||
{
|
||||
struct area_net *anet;
|
||||
old = (ort *) fib_get(&po->rtf, &prefix, pxlen);
|
||||
if (ri_better(po, new, ipath, &old->n, old->efn, 1))
|
||||
{
|
||||
memcpy(&old->n, new, sizeof(orta));
|
||||
old->efn = ipath;
|
||||
}
|
||||
if ((new->type == RTS_OSPF) && (anet = (struct area_net *)fib_route(&oa->net_fib, prefix, pxlen)))
|
||||
anet->active = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
old = (ort *) fib_get(&oa->rtr, &prefix, pxlen);
|
||||
|
||||
if (ri_better(po, new, ipath, &old->n, old->efn, 1))
|
||||
{
|
||||
memcpy(&old->n, new, sizeof(orta));
|
||||
old->efn = ipath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ospf_rt_spf - calculate internal routes
|
||||
* @po: OSPF protocol
|
||||
*
|
||||
* Calculation of internal paths in an area is described in 16.1 of RFC 2328.
|
||||
* It's based on Dijkstra's shortest path tree algorithms.
|
||||
* RFC recommends to add ASBR routers into routing table. I don't do this
|
||||
* and latter parts of routing table calculation look directly into LSA
|
||||
* Database. This function is invoked from ospf_disp().
|
||||
*/
|
||||
static void
|
||||
ospf_rt_spfa(struct ospf_area *oa)
|
||||
{
|
||||
|
@ -126,6 +143,10 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
struct proto_ospf *po = oa->po;
|
||||
struct ospf_lsa_net *ln;
|
||||
orta nf;
|
||||
struct ospf_iface *iface;
|
||||
struct top_hash_entry *act, *tmp;
|
||||
node *n;
|
||||
|
||||
|
||||
if (oa->rt == NULL)
|
||||
return;
|
||||
|
@ -149,9 +170,6 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
|
||||
while (!EMPTY_LIST(oa->cand))
|
||||
{
|
||||
struct top_hash_entry *act, *tmp;
|
||||
node *n;
|
||||
|
||||
n = HEAD(oa->cand);
|
||||
act = SKIP_BACK(struct top_hash_entry, cn, n);
|
||||
rem_node(n);
|
||||
|
@ -178,7 +196,7 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
nf.ar = act;
|
||||
nf.nh = act->nh;
|
||||
nf.ifa = act->nhi;
|
||||
ri_install(po, ipa_from_u32(act->lsa.id), 32, ORT_ROUTER, &nf);
|
||||
ri_install(po, ipa_from_u32(act->lsa.id), 32, ORT_ROUTER, &nf, NULL);
|
||||
}
|
||||
rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||
DBG(" Number of links: %u\n", rt->links);
|
||||
|
@ -208,13 +226,9 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
nf.nh = act->nh;
|
||||
nf.ifa = act->nhi;
|
||||
ri_install(po, ipa_from_u32(rtl->id),
|
||||
ipa_mklen(ipa_from_u32(rtl->data)), ORT_NET, &nf);
|
||||
ipa_mklen(ipa_from_u32(rtl->data)), ORT_NET, &nf, NULL);
|
||||
break;
|
||||
|
||||
case LSART_VLNK: /* FIXME !!!!!!!! */
|
||||
DBG("Ignoring\n");
|
||||
continue;
|
||||
break;
|
||||
case LSART_NET:
|
||||
tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET);
|
||||
if (tmp == NULL)
|
||||
|
@ -222,6 +236,8 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
else
|
||||
DBG("Found. :-)\n");
|
||||
break;
|
||||
|
||||
case LSART_VLNK:
|
||||
case LSART_PTP:
|
||||
tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT);
|
||||
DBG("PTP found.\n");
|
||||
|
@ -247,7 +263,7 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
nf.nh = act->nh;
|
||||
nf.ifa = act->nhi;
|
||||
ri_install(po, ipa_and(ipa_from_u32(act->lsa.id), ln->netmask),
|
||||
ipa_mklen(ln->netmask), ORT_NET, &nf);
|
||||
ipa_mklen(ln->netmask), ORT_NET, &nf, NULL);
|
||||
|
||||
rts = (u32 *) (ln + 1);
|
||||
for (i = 0; i < (act->lsa.length - sizeof(struct ospf_lsa_header) -
|
||||
|
@ -264,9 +280,244 @@ ospf_rt_spfa(struct ospf_area *oa)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find new/lost VLINK peers */
|
||||
WALK_LIST(iface, po->iface_list)
|
||||
{
|
||||
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))
|
||||
{
|
||||
DBG("Vlink peer found\n");
|
||||
ospf_iface_sm(iface, ISM_UP); /* FIXME: Add slave iface! */
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG("Vlink peer not found\n");
|
||||
ospf_iface_sm(iface, ISM_DOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entry *pre)
|
||||
{
|
||||
u32 i, *rts;
|
||||
struct ospf_lsa_net *ln;
|
||||
struct ospf_lsa_rt *rt;
|
||||
struct ospf_lsa_rt_link *rtl, *rr;
|
||||
|
||||
if(!pre) return 0;
|
||||
if(!fol) return 0;
|
||||
switch (fol->lsa.type)
|
||||
{
|
||||
case LSA_T_RT:
|
||||
rt = (struct ospf_lsa_rt *) fol->lsa_body;
|
||||
rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||
for (i = 0; i < rt->links; i++)
|
||||
{
|
||||
rtl = (rr + i);
|
||||
switch (rtl->type)
|
||||
{
|
||||
case LSART_STUB:
|
||||
break;
|
||||
case LSART_NET:
|
||||
if (ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET) == pre)
|
||||
{
|
||||
fol->lb = ipa_from_u32(rtl->data);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case LSART_VLNK:
|
||||
case LSART_PTP:
|
||||
if (ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT) == pre)
|
||||
{
|
||||
fol->lb = ipa_from_u32(rtl->data);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log("Unknown link type in router lsa.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LSA_T_NET:
|
||||
ln = fol->lsa_body;
|
||||
rts = (u32 *) (ln + 1);
|
||||
for (i = 0; i < (fol->lsa.length - sizeof(struct ospf_lsa_header) -
|
||||
sizeof(struct ospf_lsa_net)) / sizeof(u32); i++)
|
||||
{
|
||||
if (ospf_hash_find(oa->gr, *(rts + i), *(rts + i), LSA_T_RT) == pre)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log("Unknown link type in router lsa.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
ip_addr *mask, ip, abrip;
|
||||
struct top_hash_entry *en;
|
||||
int mlen = -1, type = -1;
|
||||
union ospf_lsa_sum_tm *tm;
|
||||
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)
|
||||
{
|
||||
if (en->lsa.age == LSA_MAXAGE)
|
||||
continue;
|
||||
if (en->dist == LSINFINITY)
|
||||
continue;
|
||||
|
||||
if (en->lsa.rt == p->cf->global->router_id)
|
||||
continue;
|
||||
|
||||
if((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
|
||||
continue;
|
||||
|
||||
mask = (ip_addr *)en->lsa_body;
|
||||
|
||||
if (en->lsa.type == LSA_T_SUM_NET)
|
||||
{
|
||||
mlen = ipa_mklen(*mask);
|
||||
ip = ipa_and(ipa_from_u32(en->lsa.id), *mask);
|
||||
type = ORT_NET;
|
||||
re = (ort *) fib_find(&po->rtf, &ip, 32);
|
||||
}
|
||||
|
||||
if (en->lsa.type == LSA_T_SUM_RT)
|
||||
{
|
||||
ip = ipa_from_u32(en->lsa.id);
|
||||
mlen = 32;
|
||||
type = ORT_ROUTER;
|
||||
re = (ort *) fib_find(&bb->rtr, &ip, 32);
|
||||
}
|
||||
if(!re) continue;
|
||||
if(re->n.oa->areaid != 0) continue;
|
||||
if((re->n.type != RTS_OSPF) && (re->n.type != RTS_OSPF_IA)) continue;
|
||||
|
||||
abrip = ipa_from_u32(en->lsa.rt);
|
||||
|
||||
abr = fib_find(&oa->rtr, &abrip, 32);
|
||||
if(!abr) continue;
|
||||
|
||||
tm = (union ospf_lsa_sum_tm *)(mask + 1);
|
||||
|
||||
nf.type = re->n.type;
|
||||
nf.capa = ORTA_ABR;
|
||||
nf.metric1 = abr->n.metric1 + (tm->metric & METRIC_MASK);
|
||||
nf.metric2 = LSINFINITY;
|
||||
nf.oa = oa;
|
||||
nf.ar = abr->n.ar;
|
||||
nf.nh = abr->n.nh;
|
||||
nf.ifa = abr->n.ifa;
|
||||
ri_install(po, ip, mlen, type, &nf, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ospf_rt_sum(struct ospf_area *oa)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
struct top_hash_entry *en;
|
||||
ip_addr *mask, ip, abrip;
|
||||
struct area_net *anet;
|
||||
orta nf;
|
||||
ort *re, *abr;
|
||||
int mlen = -1, type = -1;
|
||||
union ospf_lsa_sum_tm *tm;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area routes");
|
||||
|
||||
WALK_SLIST(en, oa->lsal)
|
||||
{
|
||||
/* Page 169 (1) */
|
||||
if (en->lsa.age == LSA_MAXAGE)
|
||||
continue;
|
||||
if (en->dist == LSINFINITY)
|
||||
continue;
|
||||
|
||||
/* Page 169 (2) */
|
||||
if (en->lsa.rt == p->cf->global->router_id)
|
||||
continue;
|
||||
|
||||
if((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
|
||||
continue;
|
||||
|
||||
mask = (ip_addr *)en->lsa_body;
|
||||
|
||||
if (en->lsa.type == LSA_T_SUM_NET)
|
||||
{
|
||||
mlen = ipa_mklen(*mask);
|
||||
ip = ipa_and(ipa_from_u32(en->lsa.id), *mask);
|
||||
/* Page 169 (3) */
|
||||
if ((anet = fib_route(&oa->net_fib, ip, mlen)) && anet->active)
|
||||
continue;
|
||||
type = ORT_NET;
|
||||
}
|
||||
|
||||
if (en->lsa.type == LSA_T_SUM_RT)
|
||||
{
|
||||
ip = ipa_from_u32(en->lsa.id);
|
||||
mlen = 32;
|
||||
type = ORT_ROUTER;
|
||||
}
|
||||
abrip = ipa_from_u32(en->lsa.rt);
|
||||
|
||||
if (!(abr = (ort *) fib_find(&oa->rtr, &abrip, 32))) continue;
|
||||
if (abr->n.metric1 == LSINFINITY) continue;
|
||||
if (!(abr->n.capa & ORTA_ABR)) continue;
|
||||
|
||||
tm = (union ospf_lsa_sum_tm *)(mask + 1);
|
||||
|
||||
nf.type = RTS_OSPF_IA;
|
||||
nf.capa = ORTA_ABR;
|
||||
nf.metric1 = abr->n.metric1 + (tm->metric & METRIC_MASK);
|
||||
nf.metric2 = LSINFINITY;
|
||||
nf.oa = oa;
|
||||
nf.ar = abr->n.ar;
|
||||
nf.nh = abr->n.nh;
|
||||
nf.ifa = abr->n.ifa;
|
||||
ri_install(po, ip, mlen, type, &nf, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ospf_rt_spf - calculate internal routes
|
||||
* @po: OSPF protocol
|
||||
*
|
||||
* Calculation of internal paths in an area is described in 16.1 of RFC 2328.
|
||||
* It's based on Dijkstra's shortest path tree algorithms.
|
||||
* This function is invoked from ospf_disp().
|
||||
*/
|
||||
void
|
||||
ospf_rt_spf(struct proto_ospf *po)
|
||||
{
|
||||
|
@ -274,12 +525,14 @@ ospf_rt_spf(struct proto_ospf *po)
|
|||
struct ospf_area *oa;
|
||||
int i;
|
||||
ort *ri;
|
||||
struct area_net *anet;
|
||||
|
||||
if (po->areano == 0) return;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
|
||||
|
||||
/* Invalidate old routing table */
|
||||
for (i = 0; i < 2; i++)
|
||||
FIB_WALK(&po->rtf[i], nftmp)
|
||||
FIB_WALK(&po->rtf, nftmp)
|
||||
{
|
||||
ri = (ort *) nftmp;
|
||||
memcpy(&ri->o, &ri->n, sizeof(orta)); /* Backup old data */
|
||||
|
@ -290,25 +543,44 @@ ospf_rt_spf(struct proto_ospf *po)
|
|||
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
FIB_WALK(&oa->rtr, nftmp)
|
||||
{
|
||||
ri = (ort *) nftmp;
|
||||
memcpy(&ri->o, &ri->n, sizeof(orta)); /* Backup old data */
|
||||
fill_ri(&ri->n);
|
||||
}
|
||||
FIB_WALK_END;
|
||||
|
||||
fib_free(&oa->rtr);
|
||||
fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
|
||||
|
||||
FIB_WALK(&oa->net_fib, nftmp)
|
||||
{
|
||||
anet = (struct area_net *) nftmp;
|
||||
anet->active = 0;
|
||||
}
|
||||
FIB_WALK_END;
|
||||
ospf_rt_spfa(oa);
|
||||
}
|
||||
|
||||
if (po->areano > 1)
|
||||
if (po->areano == 1)
|
||||
{
|
||||
//ospf_rt_sum(oa);
|
||||
ospf_rt_sum(HEAD(po->area_list));
|
||||
}
|
||||
else
|
||||
{
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
//if (oa->id == 0) ospf_rt_sum(oa);
|
||||
if (po->backbone) ospf_rt_sum(po->backbone); /* And if backbone is not connected? */
|
||||
}
|
||||
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
//if (oa->trcap == 1) ospf_rt_sum(oa);
|
||||
if (oa->trcap && (oa->areaid != 0))
|
||||
{
|
||||
ospf_rt_sum_tr(oa);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
if (!oa->stub)
|
||||
|
@ -333,7 +605,7 @@ static void
|
|||
ospf_ext_spfa(struct ospf_area *oa)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
ort *nf1, *nf2;
|
||||
ort *nf1, *nf2, *nfh;
|
||||
orta nfa;
|
||||
struct top_hash_entry *en;
|
||||
struct proto *p = &po->proto;
|
||||
|
@ -345,6 +617,7 @@ ospf_ext_spfa(struct ospf_area *oa)
|
|||
int met1, met2;
|
||||
neighbor *nn;
|
||||
struct ospf_lsa_rt *rt;
|
||||
struct ospf_area *atmp;
|
||||
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Starting routing table calculation for ext routes");
|
||||
|
@ -364,7 +637,7 @@ ospf_ext_spfa(struct ospf_area *oa)
|
|||
DBG("%s: Working on LSA. ID: %I, RT: %I, Type: %u, Mask %I\n",
|
||||
p->name, en->lsa.id, en->lsa.rt, en->lsa.type, le->netmask);
|
||||
|
||||
if (lt->metric == LSINFINITY)
|
||||
if ((lt->etm.metric & METRIC_MASK) == LSINFINITY)
|
||||
continue;
|
||||
ip = ipa_and(ipa_from_u32(en->lsa.id), le->netmask);
|
||||
mlen = ipa_mklen(le->netmask);
|
||||
|
@ -382,7 +655,16 @@ ospf_ext_spfa(struct ospf_area *oa)
|
|||
|
||||
rtid = ipa_from_u32(en->lsa.rt);
|
||||
|
||||
if (!(nf1 = fib_find(&po->rtf[ORT_ROUTER], &rtid, 32)))
|
||||
nf1 = NULL;
|
||||
WALK_LIST(atmp, po->area_list)
|
||||
{
|
||||
nfh = fib_find(&atmp->rtr, &rtid, 32);
|
||||
if(nfh == NULL) continue;
|
||||
if(nf1 == NULL) nf1 = nfh;
|
||||
else if(ri_better(po, &nfh->n, NULL, &nf1->n, NULL, po->rfc1583)) nf1 = nfh;
|
||||
}
|
||||
|
||||
if (!nf1)
|
||||
continue; /* No AS boundary router found */
|
||||
|
||||
if (nf1->n.metric1 == LSINFINITY)
|
||||
|
@ -393,34 +675,39 @@ ospf_ext_spfa(struct ospf_area *oa)
|
|||
|
||||
if (ipa_compare(lt->fwaddr, ipa_from_u32(0)) == 0)
|
||||
{
|
||||
if (lt->etos > 0)
|
||||
if (lt->etm.etos.ebit)
|
||||
{ /* FW address == 0 */
|
||||
met1 = nf1->n.metric1;
|
||||
met2 = lt->metric;
|
||||
met2 = (lt->etm.metric & METRIC_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
met1 = nf1->n.metric1 + lt->metric;
|
||||
met1 = nf1->n.metric1 + (lt->etm.metric & METRIC_MASK);
|
||||
met2 = LSINFINITY;
|
||||
}
|
||||
|
||||
nh = nf1->n.nh;
|
||||
nhi = nf1->n.ifa;
|
||||
nfh = nf1;
|
||||
}
|
||||
else
|
||||
{ /* FW address !=0 */
|
||||
if (!(nf2 = fib_route(&po->rtf[ORT_NET], lt->fwaddr, 32)))
|
||||
nf2 = fib_route(&po->rtf, lt->fwaddr, 32);
|
||||
|
||||
if (!nf2)
|
||||
{
|
||||
DBG("Cannot find network route (GW=%I)\n", lt->fwaddr);
|
||||
continue;
|
||||
}
|
||||
if (lt->etos > 0)
|
||||
|
||||
if (lt->etm.etos.ebit)
|
||||
{
|
||||
met1 = nf2->n.metric1;
|
||||
met2 = lt->metric;
|
||||
met2 = (lt->etm.metric & METRIC_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
met1 = nf2->n.metric1 + lt->metric;
|
||||
met1 = nf2->n.metric1 + (lt->etm.metric & METRIC_MASK);
|
||||
met2 = LSINFINITY;
|
||||
}
|
||||
|
||||
|
@ -434,9 +721,12 @@ ospf_ext_spfa(struct ospf_area *oa)
|
|||
nh = nf2->n.nh;
|
||||
nhi = nf2->n.ifa;
|
||||
}
|
||||
|
||||
nfh = nf2;
|
||||
}
|
||||
|
||||
nfa.type = RTS_OSPF_EXT;
|
||||
nfa.type = RTS_OSPF_EXT2;
|
||||
if(met2 == LSINFINITY) nfa.type = RTS_OSPF_EXT1;
|
||||
nfa.capa = 0;
|
||||
nfa.metric1 = met1;
|
||||
nfa.metric2 = met2;
|
||||
|
@ -445,7 +735,7 @@ ospf_ext_spfa(struct ospf_area *oa)
|
|||
nfa.nh = nh;
|
||||
nfa.ifa = nhi;
|
||||
nfa.tag = lt->tag;
|
||||
ri_install(po, ip, mlen, ORT_NET, &nfa);
|
||||
ri_install(po, ip, mlen, ORT_NET, &nfa, nfh);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -463,16 +753,20 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
|
|||
return;
|
||||
if (en->lsa.age == LSA_MAXAGE)
|
||||
return;
|
||||
/* FIXME Does it have link back? Test it! */
|
||||
|
||||
if (en->color == INSPF)
|
||||
return;
|
||||
|
||||
if (dist >= en->dist)
|
||||
return;
|
||||
/*
|
||||
* FIXME The line above is not a bug, but we don't support multiple
|
||||
* FIXME The line above (=) is not a bug, but we don't support multiple
|
||||
* next hops. I'll start as soon as nest will
|
||||
*/
|
||||
|
||||
if (!link_back(oa, en, par))
|
||||
return;
|
||||
|
||||
DBG(" Adding candidate: rt: %I, id: %I, type: %u\n", en->lsa.rt,
|
||||
en->lsa.id, en->lsa.type);
|
||||
|
||||
|
@ -520,7 +814,6 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
|
|||
add_tail(l, &en->cn);
|
||||
}
|
||||
}
|
||||
/* FIXME Some VLINK stuff should be here */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -607,30 +900,20 @@ rt_sync(struct proto_ospf *po)
|
|||
{
|
||||
struct proto *p = &po->proto;
|
||||
struct fib_iterator fit;
|
||||
struct fib *fib = &po->rtf[ORT_NET];
|
||||
struct fib *fib = &po->rtf;
|
||||
ort *nf;
|
||||
struct ospf_area *oa;
|
||||
struct area_net *anet;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Starting routing table synchronisation");
|
||||
|
||||
DBG("Now syncing my rt table with nest's\n");
|
||||
FIB_ITERATE_INIT(&fit, fib);
|
||||
again:
|
||||
again1:
|
||||
FIB_ITERATE_START(fib, &fit, nftmp)
|
||||
{
|
||||
nf = (ort *) nftmp;
|
||||
if (nf->n.metric1 == LSINFINITY)
|
||||
{
|
||||
net *ne;
|
||||
|
||||
ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
|
||||
DBG("Deleting rt entry %I\n (IP: %I, GW: %I)\n",
|
||||
nf->fn.prefix, ip, nf->nh);
|
||||
rte_update(p->table, ne, p, NULL);
|
||||
|
||||
/* Now delete my fib */
|
||||
FIB_ITERATE_PUT(&fit, nftmp);
|
||||
fib_delete(fib, nftmp);
|
||||
goto again;
|
||||
}
|
||||
else if (memcmp(&nf->n, &nf->o, sizeof(orta)))
|
||||
if (memcmp(&nf->n, &nf->o, sizeof(orta)))
|
||||
{ /* Some difference */
|
||||
net *ne;
|
||||
rta a0;
|
||||
|
@ -648,6 +931,9 @@ again:
|
|||
a0.iface = nf->n.ifa;
|
||||
a0.gw = nf->n.nh;
|
||||
ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
|
||||
check_sum_lsa(po, nf, ORT_NET);
|
||||
if (nf->n.metric1 < LSINFINITY)
|
||||
{
|
||||
e = rte_get_temp(&a0);
|
||||
e->u.ospf.metric1 = nf->n.metric1;
|
||||
e->u.ospf.metric2 = nf->n.metric2;
|
||||
|
@ -659,6 +945,45 @@ again:
|
|||
nf->fn.prefix, ip, nf->nh);
|
||||
rte_update(p->table, ne, p, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
rte_update(p->table, ne, p, NULL);
|
||||
FIB_ITERATE_PUT(&fit, nftmp);
|
||||
fib_delete(fib, nftmp);
|
||||
goto again1;
|
||||
}
|
||||
}
|
||||
}
|
||||
FIB_ITERATE_END(nftmp);
|
||||
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
FIB_ITERATE_INIT(&fit, &oa->rtr);
|
||||
again2:
|
||||
FIB_ITERATE_START(&oa->rtr, &fit, nftmp)
|
||||
{
|
||||
nf = (ort *) nftmp;
|
||||
if (memcmp(&nf->n, &nf->o, sizeof(orta)))
|
||||
{ /* Some difference */
|
||||
check_sum_lsa(po, nf, ORT_ROUTER);
|
||||
if(nf->n.metric1 >= LSINFINITY)
|
||||
{
|
||||
FIB_ITERATE_PUT(&fit, nftmp);
|
||||
fib_delete(&oa->rtr, nftmp);
|
||||
goto again2;
|
||||
}
|
||||
}
|
||||
}
|
||||
FIB_ITERATE_END(nftmp);
|
||||
|
||||
/* Check condensed summary LSAs */
|
||||
FIB_WALK(&oa->net_fib, nftmp)
|
||||
{
|
||||
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);
|
||||
}
|
||||
FIB_WALK_END;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,16 @@
|
|||
#ifndef _BIRD_OSPF_RT_H_
|
||||
#define _BIRD_OSPF_RT_H_
|
||||
|
||||
#define ORT_UNDEF -1
|
||||
#define ORT_ROUTER 1
|
||||
#define ORT_NET 0
|
||||
|
||||
typedef struct orta
|
||||
{
|
||||
int type;
|
||||
int capa;
|
||||
#define ORTA_ASBR 1
|
||||
#define ORTA_ABR 2
|
||||
struct ospf_area *oa;
|
||||
int metric1;
|
||||
int metric2;
|
||||
|
@ -27,12 +33,9 @@ orta;
|
|||
typedef struct ort
|
||||
{
|
||||
struct fib_node fn;
|
||||
int dest;
|
||||
#define ORT_UNDEF -1
|
||||
#define ORT_ROUTER 1
|
||||
#define ORT_NET 0
|
||||
orta n;
|
||||
orta o;
|
||||
struct ort *efn; /* For RFC1583 */
|
||||
}
|
||||
ort;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* BIRD -- OSPF Topological Database
|
||||
*
|
||||
* (c) 1999 Martin Mares <mj@ucw.cz>
|
||||
* (c) 1999 - 2004 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.
|
||||
*/
|
||||
|
@ -25,7 +25,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
|
|||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct ospf_iface *ifa;
|
||||
int j = 0, k = 0, v = 0;
|
||||
int j = 0, k = 0;
|
||||
u16 i = 0;
|
||||
struct ospf_lsa_rt *rt;
|
||||
struct ospf_lsa_rt_link *ln;
|
||||
|
@ -39,8 +39,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
|
|||
if ((ifa->an == oa->areaid) && (ifa->state != OSPF_IS_DOWN))
|
||||
{
|
||||
i++;
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
v = 1;
|
||||
}
|
||||
}
|
||||
rt = mb_allocz(po->proto.pool, sizeof(struct ospf_lsa_rt) +
|
||||
|
@ -49,7 +47,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
|
|||
rt->veb.bit.b = 1;
|
||||
if ((po->ebit) && (!oa->stub))
|
||||
rt->veb.bit.e = 1;
|
||||
rt->veb.bit.v = v;
|
||||
ln = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
|
@ -83,7 +80,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
|
|||
}
|
||||
else
|
||||
{
|
||||
ln->id = ipa_to_u32(ifa->iface->addr->ip);
|
||||
ln->data = ipa_to_u32(ifa->iface->addr->ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -97,10 +94,8 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
|
|||
ln->data = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
i--; /* No link added */
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OSPF_IT_BCAST:
|
||||
case OSPF_IT_NBMA:
|
||||
|
@ -140,14 +135,21 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case OSPF_IT_VLINK: /* FIXME Add virtual links! */
|
||||
i--;
|
||||
case OSPF_IT_VLINK:
|
||||
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
|
||||
if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
|
||||
{
|
||||
ln->type = LSART_VLNK;
|
||||
ln->id = neigh->rid;
|
||||
ln->metric = ifa->cost;
|
||||
ln->notos = 0;
|
||||
rt->veb.bit.v = 1;
|
||||
}
|
||||
else
|
||||
i--; /* No link added */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
v = 1;
|
||||
ln = (ln + 1);
|
||||
}
|
||||
rt->links = i;
|
||||
*length = i * sizeof(struct ospf_lsa_rt_link) + sizeof(struct ospf_lsa_rt) +
|
||||
|
@ -305,6 +307,7 @@ originate_net_lsa(struct ospf_iface *ifa)
|
|||
ifa->orignet = 0;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po,
|
||||
struct ea_list *attrs)
|
||||
|
@ -325,15 +328,16 @@ originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po,
|
|||
|
||||
if (m1 != LSINFINITY)
|
||||
{
|
||||
et->etos = 0;
|
||||
et->metric = m1;
|
||||
et->etm.metric = m1;
|
||||
et->etm.etos.tos = 0;
|
||||
et->etm.etos.ebit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
et->etos = 0x80;
|
||||
et->metric = m2;
|
||||
et->etm.metric = m2;
|
||||
et->etm.etos.tos = 0;
|
||||
et->etm.etos.ebit = 1;
|
||||
}
|
||||
et->padding = 0;
|
||||
et->tag = tag;
|
||||
if (ipa_compare(e->attrs->gw, ipa_from_u32(0)) != 0)
|
||||
{
|
||||
|
@ -371,6 +375,175 @@ max_ext_lsa(unsigned pxlen)
|
|||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
struct top_hash_entry *en;
|
||||
u32 rtid = po->proto.cf->global->router_id;
|
||||
struct ospf_lsa_header lsa;
|
||||
int max, i;
|
||||
struct ospf_lsa_sum *sum = NULL;
|
||||
union ospf_lsa_sum_tm *tm;
|
||||
|
||||
lsa.rt = rtid;
|
||||
lsa.type = LSA_T_SUM_NET;
|
||||
if (type == ORT_ROUTER)
|
||||
lsa.type = LSA_T_SUM_RT;
|
||||
|
||||
max = max_ext_lsa(fn->pxlen);
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
lsa.id = ipa_to_u32(fn->prefix) + i;
|
||||
if ((en = ospf_hash_find_header(oa->gr, &lsa)) != NULL)
|
||||
{
|
||||
sum = en->lsa_body;
|
||||
if (fn->pxlen == ipa_mklen(sum->netmask))
|
||||
{
|
||||
en->lsa.age = LSA_MAXAGE;
|
||||
en->lsa.sn = LSA_MAXSEQNO;
|
||||
OSPF_TRACE(D_EVENTS, "Flushing summary lsa.");
|
||||
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
|
||||
if (can_flush_lsa(oa)) flush_lsa(en, oa);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
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;
|
||||
struct ospf_lsa_sum *sum = NULL;
|
||||
union ospf_lsa_sum_tm *tm;
|
||||
lsa.type = LSA_T_SUM_NET;
|
||||
|
||||
if (type == ORT_ROUTER)
|
||||
{
|
||||
lsa.type = LSA_T_SUM_RT;
|
||||
mlen = 0;
|
||||
}
|
||||
|
||||
lsa.age = 0;
|
||||
lsa.rt = rtid;
|
||||
lsa.sn = LSA_INITSEQNO;
|
||||
lsa.length = sizeof(struct ospf_lsa_sum) + sizeof(union ospf_lsa_sum_tm) +
|
||||
sizeof(struct ospf_lsa_header);
|
||||
|
||||
max = max_ext_lsa(fn->pxlen);
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
lsa.id = ipa_to_u32(fn->prefix) + i;
|
||||
if ((en = ospf_hash_find_header(oa->gr, &lsa)) == NULL)
|
||||
{
|
||||
if (free < 0) free = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
sum = en->lsa_body;
|
||||
if (mlen == ipa_mklen(sum->netmask))
|
||||
{
|
||||
tm = (union ospf_lsa_sum_tm *) (sum + 1);
|
||||
if (tm->metric == (unsigned)metric) return; /* No reason for origination */
|
||||
lsa.sn = en->lsa.sn + 1;
|
||||
free = en->lsa.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(free < 0)
|
||||
{
|
||||
log("%s: got more routes for one /%d network then %d, ignoring", p->name,
|
||||
fn->pxlen, max);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
|
||||
sum = mb_alloc(p->pool, sizeof(struct ospf_lsa_sum) + sizeof(union ospf_lsa_sum_tm));
|
||||
sum->netmask = ipa_mkmask(mlen);
|
||||
tm = (union ospf_lsa_sum_tm *) (sum + 1);
|
||||
tm->metric = metric;
|
||||
tm->tos.tos = 0;
|
||||
|
||||
lsasum_calculate(&lsa, body);
|
||||
en = lsa_install_new(&lsa, body, oa);
|
||||
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
|
||||
}
|
||||
|
||||
void
|
||||
check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
|
||||
{
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_area *oa;
|
||||
struct area_net *anet;
|
||||
int flush, mlen;
|
||||
ip_addr ip;
|
||||
|
||||
if (po->areano < 2) return;
|
||||
|
||||
if ((nf->n.type > RTS_OSPF_IA) && (nf->o.type > RTS_OSPF_IA)) return;
|
||||
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
flush = 0;
|
||||
if ((nf->n.metric1 >= LSINFINITY) || (nf->n.type > RTS_OSPF_IA))
|
||||
flush = 1;
|
||||
if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR)))
|
||||
flush = 1;
|
||||
if (nf->n.oa->areaid == oa->areaid)
|
||||
flush = 1;
|
||||
/* FIXME: Test next hop - is it in actual area? */
|
||||
if ((dest == ORT_ROUTER) && oa->stub)
|
||||
flush = 1;
|
||||
/* FIXME stub for networks? */
|
||||
|
||||
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 */
|
||||
flush = 1;
|
||||
|
||||
if(flush) /* FIXME Go on... */
|
||||
{
|
||||
flush_sum_lsa(oa, &nf->fn, dest);
|
||||
continue;
|
||||
}
|
||||
originate_sum_lsa(oa, &nf->fn, dest, nf->n.metric1);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -397,8 +570,7 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
|||
struct proto *p = &po->proto;
|
||||
struct ospf_area *oa;
|
||||
struct ospf_lsa_ext *ext1, *ext2;
|
||||
int i;
|
||||
int max;
|
||||
int i, max;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Originating Ext lsa for %I/%d.", n->n.prefix,
|
||||
n->n.pxlen);
|
||||
|
@ -408,6 +580,7 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
|||
lsa.type = LSA_T_EXT;
|
||||
lsa.rt = rtid;
|
||||
lsa.sn = LSA_INITSEQNO;
|
||||
|
||||
body = originate_ext_lsa_body(n, e, po, attrs);
|
||||
lsa.length = sizeof(struct ospf_lsa_ext) + sizeof(struct ospf_lsa_ext_tos) +
|
||||
sizeof(struct ospf_lsa_header);
|
||||
|
@ -439,11 +612,14 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
|||
}
|
||||
lsasum_calculate(&lsa, body);
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
if (!oa->stub)
|
||||
{
|
||||
en = lsa_install_new(&lsa, body, oa);
|
||||
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
|
||||
body = originate_ext_lsa_body(n, e, po, attrs);
|
||||
}
|
||||
}
|
||||
mb_free(body);
|
||||
|
||||
if (po->ebit == 0)
|
||||
|
@ -617,6 +793,7 @@ ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type)
|
|||
e->dist = LSINFINITY;
|
||||
e->nhi = NULL;
|
||||
e->nh = ipa_from_u32(0);
|
||||
e->lb = ipa_from_u32(0);
|
||||
e->lsa.id = lsa;
|
||||
e->lsa.rt = rtr;
|
||||
e->lsa.type = type;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* BIRD -- OSPF
|
||||
*
|
||||
* (c) 1999 - 2004 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.
|
||||
*/
|
||||
|
@ -21,15 +21,15 @@ struct top_hash_entry
|
|||
void *lsa_body;
|
||||
bird_clock_t inst_t; /* Time of installation into DB */
|
||||
ip_addr nh; /* Next hop */
|
||||
ip_addr lb; /* Link back */
|
||||
struct iface *nhi;
|
||||
u16 dist; /* Distance from the root */
|
||||
u32 dist; /* Distance from the root */
|
||||
u16 ini_age;
|
||||
u8 color;
|
||||
#define OUTSPF 0
|
||||
#define CANDIDATE 1
|
||||
#define INSPF 2
|
||||
u8 padding;
|
||||
u16 padding2;
|
||||
};
|
||||
|
||||
struct top_graph
|
||||
|
@ -62,5 +62,11 @@ int can_flush_lsa(struct ospf_area *oa);
|
|||
int max_ext_lsa(unsigned pxlen);
|
||||
void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
||||
struct ea_list *attrs);
|
||||
void check_sum_lsa(struct proto_ospf *po, ort *nf, int);
|
||||
void originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric);
|
||||
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* _BIRD_OSPF_TOPOLOGY_H_ */
|
||||
|
|
Loading…
Reference in a new issue