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:
Ondrej Filip 2004-06-25 16:39:53 +00:00
parent 5ed68e46d7
commit 98ac61766d
23 changed files with 1116 additions and 452 deletions

2
TODO
View file

@ -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

View file

@ -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 &lt;name&gt; {
<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.
@ -1163,7 +1177,7 @@ protocol ospf MyOSPF {
ospf_metric1 = 100;
accept;
}
reject;
reject;
};
area 0.0.0.0 {
tick 8;
@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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" };

View file

@ -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);

View file

@ -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,8 +78,46 @@ 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:
COST expr { OSPF_PATT->cost = $2 ; if (($2<=0) || ($2>65535)) cf_error("Cost must be in range 1-65535"); }
| HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); }
@ -95,8 +133,8 @@ ospf_iface_item:
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
| STUB bool { OSPF_PATT->stub = $2 ; }
| NEIGHBORS '{' ipa_list '}'
| AUTHENTICATION NONE { OSPF_PATT->autype=AU_NONE ; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype=AU_SIMPLE ; }
| AUTHENTICATION NONE { OSPF_PATT->autype = AU_NONE ; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = AU_SIMPLE ; }
| PASSWORD TEXT { memcpy(OSPF_PATT->password, $2, 8); }
;
@ -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;
@ -172,7 +210,7 @@ ospf_iface_start:
OSPF_PATT->strictnbma = 0;
OSPF_PATT->stub = 0;
init_list(&OSPF_PATT->nbma_list);
OSPF_PATT->autype=AU_NONE;
OSPF_PATT->autype = AU_NONE;
}
;

View file

@ -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;
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);
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? */
}
{
i--;
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))

View file

@ -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,56 +228,55 @@ 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;
if (timer == NULL) /* Response to received hello */
{
sk_send_to(ifa->ip_sk, length, dirn->ip, OSPF_PROTO);
}
else
{
int toall = 0;
int meeli = 0;
if (ifa->state > OSPF_IS_DROTHER)
toall = 1;
if (ifa->priority > 0)
meeli = 1;
WALK_LIST(nb, ifa->nbma_list)
case OSPF_IT_NBMA:
if (timer == NULL) /* Response to received hello */
{
send = 1;
WALK_LIST(n1, ifa->neigh_list)
{
if (ipa_compare(nb->ip, n1->ip) == 0)
{
send = 0;
break;
}
}
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, dirn->ip);
}
if (poll == 0)
else
{
WALK_LIST(n1, ifa->neigh_list)
{
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);
}
int toall = 0;
int meeli = 0;
if (ifa->state > OSPF_IS_DROTHER)
toall = 1;
if (ifa->priority > 0)
meeli = 1;
WALK_LIST(nb, ifa->nbma_list)
{
send = 1;
WALK_LIST(n1, ifa->neigh_list)
{
if (ipa_compare(nb->ip, n1->ip) == 0)
{
send = 0;
break;
}
}
if ((poll == 1) && (send))
{
if (toall || (meeli && nb->eligible))
ospf_send_to(ifa->ip_sk, length, nb->ip);
}
}
if (poll == 0)
{
WALK_LIST(n1, ifa->neigh_list)
{
if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
(meeli && (n1->priority > 0)))
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);
}

View file

@ -117,24 +117,34 @@ 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);
rfree(ifa->wait_timer);
rfree(ifa->hello_timer);
rfree(ifa->poll_timer);
rfree(ifa->lock);
mb_free(ifa);
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? */
}
/**
@ -142,7 +152,7 @@ ospf_iface_down(struct ospf_iface *ifa)
* @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,12 +343,113 @@ 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_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;
struct nbma_node *nbma, *nb;
struct object_lock *lock;
struct ospf_area *oa;
ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
ifa->proto = po;
ifa->iface = iface;
ifa->an = ac->areaid;
ifa->cost = ip->cost;
ifa->rxmtint = ip->rxmtint;
ifa->inftransdelay = ip->inftransdelay;
ifa->priority = ip->priority;
ifa->helloint = ip->helloint;
ifa->pollint = ip->pollint;
ifa->strictnbma = ip->strictnbma;
ifa->waitint = ip->waitint;
ifa->deadc = ip->deadc;
ifa->stub = ip->stub;
ifa->autype = ip->autype;
memcpy(ifa->aukey, ip->password, 8);
ifa->options = 2; /* FIXME what options? */
if (ip->type == OSPF_IT_UNDEF)
ifa->type = ospf_iface_clasify(ifa->iface);
else
ifa->type = ip->type;
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));
nbma->ip = nb->ip;
nbma->eligible = nb->eligible;
add_tail(&ifa->nbma_list, NODE nbma);
}
/* Add hello timer */
ifa->hello_timer = tm_new(p->pool);
ifa->hello_timer->data = ifa;
ifa->hello_timer->randomize = 0;
ifa->hello_timer->hook = hello_timer_hook;
ifa->hello_timer->recurrent = ifa->helloint;
DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
if (ifa->type == OSPF_IT_NBMA)
{
ifa->poll_timer = tm_new(p->pool);
ifa->poll_timer->data = ifa;
ifa->poll_timer->randomize = 0;
ifa->poll_timer->hook = poll_timer_hook;
ifa->poll_timer->recurrent = ifa->pollint;
DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
}
else
ifa->poll_timer = NULL;
ifa->wait_timer = tm_new(p->pool);
ifa->wait_timer->data = ifa;
ifa->wait_timer->randomize = 0;
ifa->wait_timer->hook = wait_timer_hook;
ifa->wait_timer->recurrent = 0;
DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
ifa->state = OSPF_IS_DOWN;
WALK_LIST(oa, po->area_list)
{
if (oa->areaid == ifa->an)
break;
}
if (EMPTY_LIST(po->area_list) || (oa->areaid != ifa->an)) /* New area */
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 */
}
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)
{
@ -344,8 +458,6 @@ ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
struct ospf_area_config *ac;
struct ospf_iface_patt *ip = NULL;
struct ospf_iface *ifa;
struct object_lock *lock;
struct nbma_node *nbma, *nb;
struct ospf_area *oa;
DBG("%s: If notify called\n", p->name);
@ -364,90 +476,7 @@ ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
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;
ifa->an = ac->areaid;
ifa->cost = ip->cost;
ifa->rxmtint = ip->rxmtint;
ifa->inftransdelay = ip->inftransdelay;
ifa->priority = ip->priority;
ifa->helloint = ip->helloint;
ifa->pollint = ip->pollint;
ifa->strictnbma = ip->strictnbma;
ifa->waitint = ip->waitint;
ifa->deadc = ip->deadc;
ifa->stub = ip->stub;
ifa->autype = ip->autype;
memcpy(ifa->aukey, ip->password, 8);
ifa->options = 2; /* FIXME what options? */
if (ip->type == OSPF_IT_UNDEF)
ifa->type = ospf_iface_clasify(ifa->iface);
else
ifa->type = ip->type;
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));
nbma->ip = nb->ip;
nbma->eligible = nb->eligible;
add_tail(&ifa->nbma_list, NODE nbma);
}
/* Add hello timer */
ifa->hello_timer = tm_new(p->pool);
ifa->hello_timer->data = ifa;
ifa->hello_timer->randomize = 0;
ifa->hello_timer->hook = hello_timer_hook;
ifa->hello_timer->recurrent = ifa->helloint;
DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
if (ifa->type == OSPF_IT_NBMA)
{
ifa->poll_timer = tm_new(p->pool);
ifa->poll_timer->data = ifa;
ifa->poll_timer->randomize = 0;
ifa->poll_timer->hook = poll_timer_hook;
ifa->poll_timer->recurrent = ifa->pollint;
DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
}
else
ifa->poll_timer = NULL;
ifa->wait_timer = tm_new(p->pool);
ifa->wait_timer->data = ifa;
ifa->wait_timer->randomize = 0;
ifa->wait_timer->hook = wait_timer_hook;
ifa->wait_timer->recurrent = 0;
DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
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)
{
if (oa->areaid == ifa->an)
break;
}
if (EMPTY_LIST(po->area_list) || (oa->areaid != ifa->an)) /* New area */
bug("Cannot add any area to accepted Interface");
else
ifa->oa = oa;
olock_acquire(lock);
ospf_iface_new(po, iface, ac, ip);
}
}

View file

@ -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_ */

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -1,7 +1,7 @@
/*
* BIRD -- OSPF
*
* (c) 1999 - 2000 Ondrej Filip <feela@network.cz>
* (c) 1999--2004 Ondrej Filip <feela@network.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@ -75,6 +75,31 @@ static int ospf_rte_same(struct rte *new, struct rte *old);
static void area_disp(timer *timer);
static void ospf_disp(timer *timer);
static void
ospf_area_initfib(struct fib_node *fn)
{
struct area_net *an = (struct area_net *) fn;
an->hidden = 0;
an->active = -1; /* Force to regenerate summary lsa */
/* ac->oldactive will be rewritten by ospf_rt_spf() */
}
static void
add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac)
{
struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
struct area_net_config *anet;
struct area_net *antmp;
fib_init(&oa->net_fib, p->pool, sizeof(struct area_net), 16, ospf_area_initfib);
WALK_LIST(anet, ac->net_list)
{
antmp = (struct area_net *) fib_get(&oa->net_fib, &anet->px.addr, anet->px.len);
antmp->hidden = anet->hidden;
}
}
static int
ospf_start(struct proto *p)
@ -83,13 +108,12 @@ ospf_start(struct proto *p)
struct ospf_config *c = (struct ospf_config *) (p->cf);
struct ospf_area_config *ac;
struct ospf_area *oa;
struct area_net *anet, *antmp;
po->rfc1583 = c->rfc1583;
po->ebit = 0;
po->tick = c->tick;
po->disp_timer = tm_new(po->proto.pool);
po->disp_timer = tm_new(p->pool);
po->disp_timer->data = po;
po->disp_timer->randomize = 0;
po->disp_timer->hook = ospf_disp;
@ -97,8 +121,7 @@ ospf_start(struct proto *p)
tm_start(po->disp_timer, 1);
init_list(&(po->iface_list));
init_list(&(po->area_list));
fib_init(&po->rtf[0], p->pool, sizeof(ort), 16, ospf_rt_initort);
fib_init(&po->rtf[1], p->pool, sizeof(ort), 16, ospf_rt_initort);
fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort);
po->areano = 0;
if (EMPTY_LIST(c->area_list))
{
@ -108,7 +131,7 @@ ospf_start(struct proto *p)
WALK_LIST(ac, c->area_list)
{
oa = mb_allocz(po->proto.pool, sizeof(struct ospf_area));
oa = mb_allocz(p->pool, sizeof(struct ospf_area));
add_tail(&po->area_list, NODE oa);
po->areano++;
oa->stub = ac->stub;
@ -118,20 +141,27 @@ ospf_start(struct proto *p)
s_init_list(&(oa->lsal));
oa->rt = NULL;
oa->po = po;
oa->disp_timer = tm_new(po->proto.pool);
oa->disp_timer = tm_new(p->pool);
oa->disp_timer->data = oa;
oa->disp_timer->randomize = 0;
oa->disp_timer->hook = area_disp;
oa->disp_timer->recurrent = oa->tick;
tm_start(oa->disp_timer, 2);
init_list(&oa->net_list);
WALK_LIST(anet, ac->net_list)
add_area_nets(oa, ac);
fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
if (oa->areaid == 0) po->backbone = oa;
}
/* Add all virtual links as interfaces */
if(po->backbone)
{
struct ospf_iface_patt *ipatt;
WALK_LIST(ac, c->area_list)
{
antmp = mb_allocz(po->proto.pool, sizeof(struct area_net));
antmp->px.addr = anet->px.addr;
antmp->px.len = anet->px.len;
antmp->hidden = anet->hidden;
add_tail(&oa->net_list, NODE antmp);
WALK_LIST(ipatt, ac->patt_list)
{
if (ipatt->type == OSPF_IT_VLINK) ospf_iface_new(po, NULL, ac, ipatt);
}
}
}
return PS_UP;
@ -189,42 +219,21 @@ ospf_init(struct proto_config *c)
static int
ospf_rte_better(struct rte *new, struct rte *old)
{
/* FIXME this is wrong */
if (new->u.ospf.metric1 == LSINFINITY)
return 0;
/* External paths are always longer that internal */
if (((new->attrs->source == RTS_OSPF)
|| (new->attrs->source == RTS_OSPF_IA))
&& (old->attrs->source == RTS_OSPF_EXT))
return 1;
if (((old->attrs->source == RTS_OSPF)
|| (old->attrs->source == RTS_OSPF_IA))
&& (new->attrs->source == RTS_OSPF_EXT))
return 0;
if(new->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)
{
struct area_net *anet;
cli_msg(-1014, "\t\tArea networks:");
WALK_LIST(anet, oa->net_list)
anet = (struct area_net *) nftmp;
if(firstfib)
{
cli_msg(-1014, "\t\t\t%1I/%u\t%s", anet->px.addr, anet->px.len,
anet->hidden ? "Hidden" : "Advertise");
cli_msg(-1014, "\t\tArea networks:");
firstfib = 0;
}
cli_msg(-1014, "\t\t\t%1I/%u\t%s\t%s", anet->fn.prefix, anet->fn.pxlen,
anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
}
FIB_WALK_END;
}
cli_msg(0, "");
}

View file

@ -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_ */

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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)
{
memcpy(&old->n, new, sizeof(orta));
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)
WALK_LIST(oa, po->area_list)
{
if (oa->trcap && (oa->areaid != 0))
{
//if (oa->trcap == 1) ospf_rt_sum(oa);
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,17 +931,59 @@ again:
a0.iface = nf->n.ifa;
a0.gw = nf->n.nh;
ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
e = rte_get_temp(&a0);
e->u.ospf.metric1 = nf->n.metric1;
e->u.ospf.metric2 = nf->n.metric2;
e->u.ospf.tag = nf->n.tag;
e->pflags = 0;
e->net = ne;
e->pref = p->preference;
DBG("Modifying rt entry %I\n (IP: %I, GW: %I)\n",
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;
e->u.ospf.tag = nf->n.tag;
e->pflags = 0;
e->net = ne;
e->pref = p->preference;
DBG("Modifying rt entry %I\n (IP: %I, GW: %I)\n",
nf->fn.prefix, ip, nf->nh);
rte_update(p->table, ne, p, e);
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;
}
}

View file

@ -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;

View file

@ -1,8 +1,8 @@
/*
* BIRD -- OSPF Topological Database
*
* (c) 1999 Martin Mares <mj@ucw.cz>
* (c) 1999 - 2004 Ondrej Filip <feela@network.cz>
* (c) 1999 Martin Mares <mj@ucw.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,9 +94,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
ln->data = 0xffffffff;
}
else
{
i--; /* No link added */
}
}
break;
case OSPF_IT_BCAST:
@ -140,14 +135,21 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
}
}
break;
case OSPF_IT_VLINK: /* FIXME Add virtual links! */
i--;
break;
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);
@ -440,9 +613,12 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
lsasum_calculate(&lsa, body);
WALK_LIST(oa, po->area_list)
{
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);
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);
@ -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;

View file

@ -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_ */