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) - automatic generation of external route tags (RFC1403)
- RFC1587 NSSA areas - RFC1587 NSSA areas
- RFC2370 opaque LSA's - 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 - AS external LSAs are in topology database of every OSPF Area
- Limit export rate of external LSAs (like Gated does) - 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; <ip> eligible;
}; };
}; };
virtual link <id>
{
hello <num>;
poll <num>;
retransmit <num>;
wait <num>;
dead count <num>;
authentication [none|simple];
password "<text>";
};
}; };
} }
</code> </code>
@ -1068,6 +1078,10 @@ protocol ospf &lt;name&gt; {
<tag>interface <M>pattern</M></tag> <tag>interface <M>pattern</M></tag>
Defines that the specified interfaces belong to the area being defined. 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> <tag>cost <M>num</M></tag>
Specifies output cost (metric) of an interface. Default value is 10. Specifies output cost (metric) of an interface. Default value is 10.
@ -1185,6 +1199,10 @@ protocol ospf MyOSPF {
}; };
area 120 { area 120 {
stub yes; stub yes;
networks {
172.16.1.0/24;
172.16.2.0/24 hidden;
}
interface "-arc0" , "arc*" { interface "-arc0" , "arc*" {
type nonbroadcast; type nonbroadcast;
authentication none; 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_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREIMPORT)
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, 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_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE)
CF_ENUM(T_ENUM_RTC, RTC_, UNICAST, BROADCAST, MULTICAST, ANYCAST) CF_ENUM(T_ENUM_RTC, RTC_, UNICAST, BROADCAST, MULTICAST, ANYCAST)
CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT) 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_RIP 6 /* RIP route */
#define RTS_OSPF 7 /* OSPF route */ #define RTS_OSPF 7 /* OSPF route */
#define RTS_OSPF_IA 8 /* OSPF inter-area route */ #define RTS_OSPF_IA 8 /* OSPF inter-area route */
#define RTS_OSPF_EXT 9 /* OSPF external route */ #define RTS_OSPF_EXT1 9 /* OSPF external route type 1 */
#define RTS_BGP 10 /* BGP route */ #define RTS_OSPF_EXT2 10 /* OSPF external route type 2 */
#define RTS_PIPE 11 /* Inter-table wormhole */ #define RTS_BGP 11 /* BGP route */
#define RTS_PIPE 12 /* Inter-table wormhole */
#define RTC_UNICAST 0 #define RTC_UNICAST 0
#define RTC_BROADCAST 1 #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", static char *rts[] = { "RTS_DUMMY", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE",
"RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP", "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 *rtc[] = { "", " BC", " MC", " AC" };
static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" }; 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; ea->count = 4;
bgp_set_attr(ea->attrs, pool, BA_ORIGIN, 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) if (p->is_internal)
bgp_set_attr(ea->attrs+1, pool, BA_AS_PATH, 0); 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; static struct iface_patt *this_ipatt;
#define OSPF_PATT ((struct ospf_iface_patt *) this_ipatt) #define OSPF_PATT ((struct ospf_iface_patt *) this_ipatt)
static struct nbma_node *this_nbma; static struct nbma_node *this_nbma;
static struct area_net *this_pref; static struct area_net_config *this_pref;
CF_DECLS 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(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE) CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE)
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, PASSWORD, STRICT) CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, PASSWORD, STRICT)
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN) CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, LINK)
%type <t> opttext %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"); } | TICK expr { this_area->tick = $2 ; if($2<=0) cf_error("Tick must be greater than zero"); }
| NETWORKS '{' pref_list '}' | NETWORKS '{' pref_list '}'
| INTERFACE ospf_iface_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: ospf_iface_item:
COST expr { OSPF_PATT->cost = $2 ; if (($2<=0) || ($2>65535)) cf_error("Cost must be in range 1-65535"); } 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"); } | 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 ; } | STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
| STUB bool { OSPF_PATT->stub = $2 ; } | STUB bool { OSPF_PATT->stub = $2 ; }
| NEIGHBORS '{' ipa_list '}' | NEIGHBORS '{' ipa_list '}'
| AUTHENTICATION NONE { OSPF_PATT->autype=AU_NONE ; } | AUTHENTICATION NONE { OSPF_PATT->autype = AU_NONE ; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype=AU_SIMPLE ; } | AUTHENTICATION SIMPLE { OSPF_PATT->autype = AU_SIMPLE ; }
| PASSWORD TEXT { memcpy(OSPF_PATT->password, $2, 8); } | PASSWORD TEXT { memcpy(OSPF_PATT->password, $2, 8); }
; ;
@ -111,7 +149,7 @@ pref_item:
pref_el: prefix ';' 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); add_tail(&this_area->net_list, NODE this_pref);
this_pref->px.addr = $1.addr; this_pref->px.addr = $1.addr;
this_pref->px.len = $1.len; this_pref->px.len = $1.len;
@ -120,7 +158,7 @@ pref_el: prefix ';'
pref_hid: prefix HIDDEN ';' 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); add_tail(&this_area->net_list, NODE this_pref);
this_pref->px.addr = $1.addr; this_pref->px.addr = $1.addr;
this_pref->px.len = $1.len; this_pref->px.len = $1.len;
@ -172,7 +210,7 @@ ospf_iface_start:
OSPF_PATT->strictnbma = 0; OSPF_PATT->strictnbma = 0;
OSPF_PATT->stub = 0; OSPF_PATT->stub = 0;
init_list(&OSPF_PATT->nbma_list); 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); pkt = (struct ospf_dbdes_packet *) (ifa->ip_sk->tbuf);
op = (struct ospf_packet *) pkt; op = (struct ospf_packet *) pkt;
fill_ospf_pkt_hdr(ifa, pkt, DBDES_P); 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->options = ifa->options;
pkt->imms = n->myimms; pkt->imms = n->myimms;
pkt->ddseq = htonl(n->dds); pkt->ddseq = htonl(n->dds);
length = sizeof(struct ospf_dbdes_packet); length = sizeof(struct ospf_dbdes_packet);
op->length = htons(length); op->length = htons(length);
ospf_pkt_finalize(ifa, op); 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, OSPF_TRACE(D_PACKETS, "DB_DES (I) sent to %I via %s.", n->ip,
ifa->iface->name); ifa->iface->name);
break; break;
@ -79,20 +79,26 @@ ospf_dbdes_send(struct ospf_neighbor *n)
for (; i > 0; i--) for (; i > 0; i--)
{ {
struct top_hash_entry *en; struct top_hash_entry *en;
en = (struct top_hash_entry *) sn; en = (struct top_hash_entry *) sn;
if ((n->ifa->type != OSPF_IT_VLINK) && (en->lsa.type != LSA_T_EXT))
{
htonlsah(&(en->lsa), lsa); htonlsah(&(en->lsa), lsa);
DBG("Working on: %d\n", i); DBG("Working on: %d\n", i);
DBG("\tX%01x %-1I %-1I %p\n", en->lsa.type, en->lsa.id, DBG("\tX%01x %-1I %-1I %p\n", en->lsa.type, en->lsa.id,
en->lsa.rt, en->lsa_body); en->lsa.rt, en->lsa_body);
lsa++;
}
else i++; /* No lsa added */
if (sn == STAIL(n->ifa->oa->lsal)) if (sn == STAIL(n->ifa->oa->lsal))
{ {
i--; i--;
break; /* Should set some flag? */ break;
} }
sn = sn->next; sn = sn->next;
lsa++;
} }
if (sn == STAIL(n->ifa->oa->lsal)) 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); memcpy(ifa->ip_sk->tbuf, n->ldbdes, length);
/* Copy last sent packet again */ /* 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 */ 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); ps->imms.byte);
break; break;
} }
if(ps->imms.bit.i) log("FUCK");
case NEIGHBOR_EXCHANGE: case NEIGHBOR_EXCHANGE:
if ((ps->imms.byte == n->imms.byte) && (ps->options == n->options) && if ((ps->imms.byte == n->imms.byte) && (ps->options == n->options) &&
(ntohl(ps->ddseq) == n->ddr)) (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_hello_packet *pkt;
struct ospf_packet *op; struct ospf_packet *op;
struct proto *p; struct proto *p;
struct ospf_neighbor *neigh; struct ospf_neighbor *neigh, *n1;
u16 length; u16 length;
u32 *pp; u32 *pp;
int i; int i, send;
struct nbma_node *nb;
if (timer == NULL) if (timer == NULL)
ifa = dirn->ifa; ifa = dirn->ifa;
else else
ifa = (struct ospf_iface *) timer->data; ifa = (struct ospf_iface *) timer->data;
if (ifa->state == OSPF_IS_DOWN)
return;
if (ifa->stub) if (ifa->stub)
return; /* Don't send any packet on stub iface */ 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); p->name, ifa->iface->name);
/* Now we should send a hello packet */ /* Now we should send a hello packet */
/* First a common packet header */ /* 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 else
{ {
pkt = (struct ospf_hello_packet *) (ifa->ip_sk->tbuf); pkt = (struct ospf_hello_packet *) (ifa->hello_sk->tbuf);
} }
/* Now fill ospf_hello header */ /* 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); ospf_pkt_finalize(ifa, op);
/* And finally send it :-) */ /* And finally send it :-) */
if (ifa->type != OSPF_IT_NBMA) switch(ifa->type)
{ {
sk_send(ifa->hello_sk, length); case OSPF_IT_NBMA:
}
else /* NBMA */
{
struct ospf_neighbor *n1;
struct nbma_node *nb;
int send;
if (timer == NULL) /* Response to received hello */ 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 else
{ {
@ -261,7 +258,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
if ((poll == 1) && (send)) if ((poll == 1) && (send))
{ {
if (toall || (meeli && nb->eligible)) 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) 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) || if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
(meeli && (n1->priority > 0))) (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); 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 ospf_neighbor *n, *nx;
struct proto *p = &ifa->proto->proto; struct proto *p = &ifa->proto->proto;
struct proto_ospf *po = ifa->proto;
struct ospf_iface *iff;
WALK_LIST_DELSAFE(n, nx, ifa->neigh_list) WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
{ {
OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip); OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
ospf_neigh_remove(n); ospf_neigh_remove(n);
} }
rem_node(NODE ifa);
rfree(ifa->hello_sk); rfree(ifa->hello_sk);
rfree(ifa->dr_sk); rfree(ifa->dr_sk);
rfree(ifa->ip_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->wait_timer);
rfree(ifa->hello_timer); rfree(ifa->hello_timer);
rfree(ifa->poll_timer); rfree(ifa->poll_timer);
rfree(ifa->lock); rfree(ifa->lock);
rem_node(NODE ifa);
mb_free(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 * @ifa: OSPF interface
* @event: event comming to state machine * @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. * interface.
*/ */
void void
@ -260,6 +270,7 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
ipsk->saddr = ifa->iface->addr->ip; ipsk->saddr = ifa->iface->addr->ip;
ipsk->tos = IP_PREC_INTERNET_CONTROL; ipsk->tos = IP_PREC_INTERNET_CONTROL;
ipsk->ttl = 1; ipsk->ttl = 1;
if (ifa->type == OSPF_IT_VLINK) ipsk->ttl = 255;
ipsk->rx_hook = ospf_rx_hook; ipsk->rx_hook = ospf_rx_hook;
ipsk->tx_hook = ospf_tx_hook; ipsk->tx_hook = ospf_tx_hook;
ipsk->err_hook = ospf_err_hook; ipsk->err_hook = ospf_err_hook;
@ -307,6 +318,8 @@ ospf_iface_add(struct object_lock *lock)
struct iface *iface = lock->iface; struct iface *iface = lock->iface;
struct proto *p = &po->proto; struct proto *p = &po->proto;
ifa->lock = lock;
ifa->ioprob = OSPF_I_OK; ifa->ioprob = OSPF_I_OK;
if (ifa->type != OSPF_IT_NBMA) if (ifa->type != OSPF_IT_NBMA)
@ -330,41 +343,20 @@ ospf_iface_add(struct object_lock *lock)
ifa->stub = 1; ifa->stub = 1;
ifa->ioprob += OSPF_I_IP; ifa->ioprob += OSPF_I_IP;
} }
ifa->lock = lock;
ifa->state = OSPF_IS_DOWN; ifa->state = OSPF_IS_DOWN;
ospf_iface_sm(ifa, ISM_UP); ospf_iface_sm(ifa, ISM_UP);
} }
void 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 proto *p = &po->proto;
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_iface *ifa;
struct object_lock *lock;
struct nbma_node *nbma, *nb; struct nbma_node *nbma, *nb;
struct object_lock *lock;
struct ospf_area *oa; 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 = mb_allocz(p->pool, sizeof(struct ospf_iface));
ifa->proto = po; ifa->proto = po;
ifa->iface = iface; 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); add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
ifa->state = OSPF_IS_DOWN; ifa->state = OSPF_IS_DOWN;
lock = olock_new(p->pool); WALK_LIST(oa, po->area_list)
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) if (oa->areaid == ifa->an)
break; break;
@ -447,7 +431,52 @@ ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
else else
ifa->oa = oa; 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); 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);
} }
} }

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_notify(struct proto *p, unsigned flags, struct iface *iface);
void ospf_iface_info(struct ospf_iface *ifa); void ospf_iface_info(struct ospf_iface *ifa);
void ospf_iface_shutdown(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_ */ #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->type == OSPF_IT_BCAST)
{ {
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) 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 else
sk_send_to(sk, len, AllDRouters, OSPF_PROTO); ospf_send_to(sk, len, AllDRouters);
} }
else else
{ {
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) 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 else
sk_send_to_bdr(sk, len, ifa); ospf_send_to_bdr(sk, len, ifa);
} }
fill_ospf_pkt_hdr(n->ifa, pk, LSACK_P); 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)) 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 else
{ {
sk_send_to(sk, len, AllDRouters, OSPF_PROTO); ospf_send_to(sk, len, AllDRouters);
} }
} }
else 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; struct proto *p = &oa->po->proto;
OSPF_TRACE(D_EVENTS, OSPF_TRACE(D_EVENTS,
"Going to remove node Type: %u, Id: %I, Rt: %I, Age: %u", "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.type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn);
s_rem_node(SNODE en); s_rem_node(SNODE en);
if (en->lsa_body != NULL) if (en->lsa_body != NULL)
mb_free(en->lsa_body); mb_free(en->lsa_body);
@ -56,6 +56,7 @@ ospf_age(struct ospf_area *oa)
en->dist = LSINFINITY; en->dist = LSINFINITY;
en->nhi = NULL; en->nhi = NULL;
en->nh = ipa_from_u32(0); 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, DBG("Infinitying Type: %u, Id: %I, Rt: %I\n", en->lsa.type, en->lsa.id,
en->lsa.rt); 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_NET:
case LSA_T_SUM_RT: case LSA_T_SUM_RT:
{ {
struct ospf_lsa_summ *hs, *ns; struct ospf_lsa_sum *hs, *ns;
struct ospf_lsa_summ_net *hn, *nn; union ospf_lsa_sum_tm *hn, *nn;
hs = h; hs = h;
ns = n; ns = n;
@ -173,15 +174,16 @@ htonlsab(void *h, void *n, u8 type, u16 len)
ns->netmask = hs->netmask; ns->netmask = hs->netmask;
ipa_hton(ns->netmask); ipa_hton(ns->netmask);
hn = (struct ospf_lsa_summ_net *) (hs + 1); hn = (union ospf_lsa_sum_tm *) (hs + 1);
nn = (struct ospf_lsa_summ_net *) (ns + 1); nn = (union ospf_lsa_sum_tm *) (ns + 1);
for (i = 0; i < ((len - sizeof(struct ospf_lsa_summ)) / for (i = 0; i < ((len - sizeof(struct ospf_lsa_sum)) /
sizeof(struct ospf_lsa_summ_net)); i++) sizeof(union ospf_lsa_sum_tm)); i++)
{ {
(nn + i)->tos = (hn + i)->tos; (nn + i)->metric = htonl((hn + i)->metric);
(nn + i)->metric = htons((hn + i)->metric); //(nn + i)->tos = (hn + i)->tos;
(nn + i)->padding = 0; //(nn + i)->metric = htons((hn + i)->metric);
//(nn + i)->padding = 0;
} }
break; break;
} }
@ -202,9 +204,10 @@ htonlsab(void *h, void *n, u8 type, u16 len)
for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) / for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) /
sizeof(struct ospf_lsa_ext_tos)); i++) sizeof(struct ospf_lsa_ext_tos)); i++)
{ {
(nt + i)->etos = (ht + i)->etos; (nt + i)->etm.metric = htonl((ht + i)->etm.metric);
(nt + i)->padding = 0; //(nt + i)->tos = (ht + i)->tos;
(nt + i)->metric = htons((ht + i)->metric); //(nt + i)->padding = 0;
//(nt + i)->metric = htons((ht + i)->metric);
(nt + i)->fwaddr = (ht + i)->fwaddr; (nt + i)->fwaddr = (ht + i)->fwaddr;
ipa_hton((nt + i)->fwaddr); ipa_hton((nt + i)->fwaddr);
(nt + i)->tag = htonl((ht + i)->tag); (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_NET:
case LSA_T_SUM_RT: case LSA_T_SUM_RT:
{ {
struct ospf_lsa_summ *hs, *ns; struct ospf_lsa_sum *hs, *ns;
struct ospf_lsa_summ_net *hn, *nn; union ospf_lsa_sum_tm *hn, *nn;
hs = h; hs = h;
ns = n; ns = n;
@ -271,15 +274,16 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
hs->netmask = ns->netmask; hs->netmask = ns->netmask;
ipa_ntoh(hs->netmask); ipa_ntoh(hs->netmask);
hn = (struct ospf_lsa_summ_net *) (hs + 1); hn = (union ospf_lsa_sum_tm *) (hs + 1);
nn = (struct ospf_lsa_summ_net *) (ns + 1); nn = (union ospf_lsa_sum_tm *) (ns + 1);
for (i = 0; i < ((len - sizeof(struct ospf_lsa_summ)) / for (i = 0; i < ((len - sizeof(struct ospf_lsa_sum)) /
sizeof(struct ospf_lsa_summ_net)); i++) sizeof(union ospf_lsa_sum_tm)); i++)
{ {
(hn + i)->tos = (nn + i)->tos; (hn + i)->metric = ntohl((nn + i)->metric);
(hn + i)->metric = ntohs((nn + i)->metric); //(hn + i)->tos = (nn + i)->tos;
(hn + i)->padding = 0; //(hn + i)->metric = ntohs((nn + i)->metric);
//(hn + i)->padding = 0;
} }
break; break;
} }
@ -300,9 +304,10 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) / for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) /
sizeof(struct ospf_lsa_ext_tos)); i++) sizeof(struct ospf_lsa_ext_tos)); i++)
{ {
(ht + i)->etos = (nt + i)->etos; (ht + i)->etm.metric = ntohl((nt + i)->etm.metric);
(ht + i)->padding = 0; //(ht + i)->etos = (nt + i)->etos;
(ht + i)->metric = ntohs((nt + i)->metric); //(ht + i)->padding = 0;
//(ht + i)->metric = ntohs((nt + i)->metric);
(ht + i)->fwaddr = (nt + i)->fwaddr; (ht + i)->fwaddr = (nt + i)->fwaddr;
ipa_ntoh((ht + i)->fwaddr); ipa_ntoh((ht + i)->fwaddr);
(ht + i)->tag = ntohl((nt + i)->tag); (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); i) * sizeof(struct ospf_lsreq_header);
op->length = htons(length); op->length = htons(length);
ospf_pkt_finalize(n->ifa, op); 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); 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->type == OSPF_IT_NBMA)
{ {
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR)) 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 else
sk_send_to_bdr(sk, len, ifa); ospf_send_to_bdr(sk, len, ifa);
} }
else else
{ {
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) || if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
(ifa->type == OSPF_IT_PTP)) (ifa->type == OSPF_IT_PTP))
sk_send_to(sk, len, AllSPFRouters, OSPF_PROTO); ospf_send_to(sk, len, AllSPFRouters);
else 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); op->length = htons(len - SIPH);
ospf_pkt_finalize(n->ifa, op); 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); OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano);
DBG("LSupd: next packet\n"); 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_pkt_finalize(n->ifa, op);
OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano); 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 * 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. * 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 area_disp(timer *timer);
static void ospf_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 static int
ospf_start(struct proto *p) 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_config *c = (struct ospf_config *) (p->cf);
struct ospf_area_config *ac; struct ospf_area_config *ac;
struct ospf_area *oa; struct ospf_area *oa;
struct area_net *anet, *antmp;
po->rfc1583 = c->rfc1583; po->rfc1583 = c->rfc1583;
po->ebit = 0; po->ebit = 0;
po->tick = c->tick; 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->data = po;
po->disp_timer->randomize = 0; po->disp_timer->randomize = 0;
po->disp_timer->hook = ospf_disp; po->disp_timer->hook = ospf_disp;
@ -97,8 +121,7 @@ ospf_start(struct proto *p)
tm_start(po->disp_timer, 1); tm_start(po->disp_timer, 1);
init_list(&(po->iface_list)); init_list(&(po->iface_list));
init_list(&(po->area_list)); init_list(&(po->area_list));
fib_init(&po->rtf[0], p->pool, sizeof(ort), 16, ospf_rt_initort); fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort);
fib_init(&po->rtf[1], p->pool, sizeof(ort), 16, ospf_rt_initort);
po->areano = 0; po->areano = 0;
if (EMPTY_LIST(c->area_list)) if (EMPTY_LIST(c->area_list))
{ {
@ -108,7 +131,7 @@ ospf_start(struct proto *p)
WALK_LIST(ac, c->area_list) 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); add_tail(&po->area_list, NODE oa);
po->areano++; po->areano++;
oa->stub = ac->stub; oa->stub = ac->stub;
@ -118,20 +141,27 @@ ospf_start(struct proto *p)
s_init_list(&(oa->lsal)); s_init_list(&(oa->lsal));
oa->rt = NULL; oa->rt = NULL;
oa->po = po; 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->data = oa;
oa->disp_timer->randomize = 0; oa->disp_timer->randomize = 0;
oa->disp_timer->hook = area_disp; oa->disp_timer->hook = area_disp;
oa->disp_timer->recurrent = oa->tick; oa->disp_timer->recurrent = oa->tick;
tm_start(oa->disp_timer, 2); tm_start(oa->disp_timer, 2);
init_list(&oa->net_list); add_area_nets(oa, ac);
WALK_LIST(anet, ac->net_list) 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)); struct ospf_iface_patt *ipatt;
antmp->px.addr = anet->px.addr; WALK_LIST(ac, c->area_list)
antmp->px.len = anet->px.len; {
antmp->hidden = anet->hidden; WALK_LIST(ipatt, ac->patt_list)
add_tail(&oa->net_list, NODE antmp); {
if (ipatt->type == OSPF_IT_VLINK) ospf_iface_new(po, NULL, ac, ipatt);
}
} }
} }
return PS_UP; return PS_UP;
@ -189,42 +219,21 @@ ospf_init(struct proto_config *c)
static int static int
ospf_rte_better(struct rte *new, struct rte *old) ospf_rte_better(struct rte *new, struct rte *old)
{ {
/* FIXME this is wrong */
if (new->u.ospf.metric1 == LSINFINITY) if (new->u.ospf.metric1 == LSINFINITY)
return 0; return 0;
/* External paths are always longer that internal */ if(new->attrs->source < old->attrs->source) return 1;
if (((new->attrs->source == RTS_OSPF) if(new->attrs->source > old->attrs->source) return 0;
|| (new->attrs->source == RTS_OSPF_IA))
&& (old->attrs->source == RTS_OSPF_EXT))
return 1;
if (((old->attrs->source == RTS_OSPF)
|| (old->attrs->source == RTS_OSPF_IA))
&& (new->attrs->source == RTS_OSPF_EXT))
return 0;
if (new->u.ospf.metric2 < old->u.ospf.metric2) if(new->attrs->source == RTS_OSPF_EXT2)
{ {
if (old->u.ospf.metric2 == LSINFINITY) if(new->u.ospf.metric2 < old->u.ospf.metric2) return 1;
return 0; /* Old is E1, new is E2 */ if(new->u.ospf.metric2 > old->u.ospf.metric2) return 0;
return 1; /* Both are E2 */
} }
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) if (new->u.ospf.metric1 < old->u.ospf.metric1)
return 1; return 1;
return 0; /* Old is shorter or same */ return 0; /* Old is shorter or same */
} }
@ -466,29 +475,30 @@ ospf_get_status(struct proto *p, byte * buf)
static void static void
ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED) ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED)
{ {
char met = ' '; char *type = "<bug>";
char type = ' ';
if (rte->attrs->source == RTS_OSPF_EXT) switch(rte->attrs->source)
{ {
met = '1'; case RTS_OSPF:
type = 'E'; 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'; buf += bsprintf(buf, " %s", type);
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, " (%d/%d", rte->pref, rte->u.ospf.metric1); 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, "/%d", rte->u.ospf.metric2);
buf += bsprintf(buf, ")"); 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); buf += bsprintf(buf, " [%x]", rte->u.ospf.tag);
} }
@ -578,19 +588,8 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
} }
/* Change net_list */ /* Change net_list */
WALK_LIST_DELSAFE(anet, antmp, oa->net_list) fib_free(&oa->net_fib);
{ add_area_nets(oa, ac2);
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);
}
if (!iface_patts_equal(&ac1->patt_list, &ac2->patt_list, if (!iface_patts_equal(&ac1->patt_list, &ac2->patt_list,
(void *) ospf_patt_compare)) (void *) ospf_patt_compare))
@ -833,9 +832,8 @@ ospf_sh(struct proto *p)
struct proto_ospf *po = (struct proto_ospf *) p; struct proto_ospf *po = (struct proto_ospf *) p;
struct ospf_iface *ifa; struct ospf_iface *ifa;
struct ospf_neighbor *n; struct ospf_neighbor *n;
int ifano; int ifano, nno, adjno, firstfib;
int nno; struct area_net *anet;
int adjno;
if (p->proto_state != PS_UP) 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 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 neighbors:\t%u", nno);
cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno); 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:"); cli_msg(-1014, "\t\tArea networks:");
WALK_LIST(anet, oa->net_list) firstfib = 0;
{
cli_msg(-1014, "\t\t\t%1I/%u\t%s", anet->px.addr, anet->px.len,
anet->hidden ? "Hidden" : "Advertise");
} }
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, ""); cli_msg(0, "");
} }

View file

@ -1,7 +1,7 @@
/* /*
* BIRD -- OSPF * 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. * Can be freely distributed and used under the terms of the GNU GPL.
*/ */
@ -50,7 +50,7 @@
#define LSREFRESHTIME 1800 /* 30 minutes */ #define LSREFRESHTIME 1800 /* 30 minutes */
#define MINLSINTERVAL 5 #define MINLSINTERVAL 5
#define MINLSARRIVAL 1 #define MINLSARRIVAL 1
#define LSINFINITY 0xffff /* RFC says 0xffffff ??? */ #define LSINFINITY 0xffffff
#define DEFAULT_OSPFTICK 5 #define DEFAULT_OSPFTICK 5
#define DEFAULT_AREATICK 4 #define DEFAULT_AREATICK 4
@ -72,13 +72,18 @@ struct nbma_node
int eligible; int eligible;
}; };
struct area_net struct area_net_config
{ {
node n; node n;
struct prefix px; struct prefix px;
int hidden; int hidden;
};
struct area_net
{
struct fib_node fn;
int hidden;
int active; int active;
int oldactive;
}; };
struct ospf_area_config struct ospf_area_config
@ -113,6 +118,9 @@ struct ospf_iface
u32 rxmtint; /* number of seconds between LSA retransmissions */ u32 rxmtint; /* number of seconds between LSA retransmissions */
u32 pollint; /* Poll interval */ u32 pollint; /* Poll interval */
u32 deadc; /* after "deadint" missing hellos is router dead */ 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; u16 autype;
u8 aukey[8]; u8 aukey[8];
u8 options; u8 options;
@ -299,28 +307,61 @@ struct ospf_lsa_net
ip_addr netmask; ip_addr netmask;
}; };
struct ospf_lsa_summ struct ospf_lsa_sum
{ {
ip_addr netmask; ip_addr netmask;
}; };
struct ospf_lsa_summ_net
{
u8 tos;
u8 padding;
u16 metric;
};
struct ospf_lsa_ext struct ospf_lsa_ext
{ {
ip_addr netmask; 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 struct ospf_lsa_ext_tos
{ {
u8 etos; union ospf_lsa_ext_etm etm;
u8 padding;
u16 metric;
ip_addr fwaddr; ip_addr fwaddr;
u32 tag; u32 tag;
}; };
@ -432,11 +473,12 @@ struct ospf_area
slist lsal; /* List of all LSA's */ slist lsal; /* List of all LSA's */
struct top_hash_entry *rt; /* My own router LSA */ struct top_hash_entry *rt; /* My own router LSA */
list cand; /* List of candidates for RT calc. */ 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 stub;
int trcap; /* Transit capability? */ int trcap; /* Transit capability? */
struct proto_ospf *po; struct proto_ospf *po;
unsigned tick; unsigned tick;
struct fib rtr; /* Routing tables for routers */
}; };
struct proto_ospf struct proto_ospf
@ -448,9 +490,10 @@ struct proto_ospf
list iface_list; /* Interfaces we really use */ list iface_list; /* Interfaces we really use */
list area_list; list area_list;
int areano; /* Number of area I belong to */ int areano; /* Number of area I belong to */
struct fib rtf[2]; /* Routing tables */ struct fib rtf; /* Routing table */
int rfc1583; /* RFC1583 compatibility */ int rfc1583; /* RFC1583 compatibility */
int ebit; /* Did I originate any ext lsa? */ int ebit; /* Did I originate any ext lsa? */
struct ospf_area *backbone; /* If exists */
}; };
struct ospf_iface_patt struct ospf_iface_patt
@ -468,6 +511,7 @@ struct ospf_iface_patt
u32 autype; u32 autype;
u32 strictnbma; u32 strictnbma;
u32 stub; u32 stub;
u32 vid;
/* must be in network byte order */ /* must be in network byte order */
#define AU_NONE htons(0) #define AU_NONE htons(0)
#define AU_SIMPLE htons(1) #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_METRIC2 EA_CODE(EAP_OSPF, 1)
#define EA_OSPF_TAG EA_CODE(EAP_OSPF, 2) #define EA_OSPF_TAG EA_CODE(EAP_OSPF, 2)
#include "proto/ospf/rt.h"
#include "proto/ospf/hello.h" #include "proto/ospf/hello.h"
#include "proto/ospf/packet.h" #include "proto/ospf/packet.h"
#include "proto/ospf/iface.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/lsupd.h"
#include "proto/ospf/lsack.h" #include "proto/ospf/lsack.h"
#include "proto/ospf/lsalib.h" #include "proto/ospf/lsalib.h"
#include "proto/ospf/rt.h"
#endif /* _BIRD_OSPF_H_ */ #endif /* _BIRD_OSPF_H_ */

View file

@ -226,19 +226,26 @@ ospf_err_hook(sock * sk, int err UNUSED)
} }
void 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; struct ospf_neighbor *n;
WALK_LIST(NODE n, ifa->neigh_list) if (n->state >= state) 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 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) 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) 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); int ospf_rx_hook(sock * sk, int size);
void ospf_tx_hook(sock * sk); void ospf_tx_hook(sock * sk);
void ospf_err_hook(sock * sk, int err); void ospf_err_hook(sock * sk, int err);
void sk_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state); void ospf_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_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_ */ #endif /* _BIRD_OSPF_PACKET_H_ */

View file

@ -21,8 +21,6 @@ fill_ri(orta * orta)
{ {
orta->type = RTS_DUMMY; orta->type = RTS_DUMMY;
orta->capa = 0; orta->capa = 0;
#define ORTA_ASBR 1
#define ORTA_ABR 2
orta->oa = NULL; orta->oa = NULL;
orta->metric1 = LSINFINITY; orta->metric1 = LSINFINITY;
orta->metric2 = LSINFINITY; orta->metric2 = LSINFINITY;
@ -37,13 +35,20 @@ ospf_rt_initort(struct fib_node *fn)
{ {
ort *ri = (ort *) fn; ort *ri = (ort *) fn;
fill_ri(&ri->n); fill_ri(&ri->n);
ri->dest = ORT_UNDEF;
memcpy(&ri->o, &ri->n, sizeof(orta)); memcpy(&ri->o, &ri->n, sizeof(orta));
ri->efn = NULL;
} }
/* If new is better return 1 */ /* 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 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 newtype = new->type;
int oldtype = old->type; int oldtype = old->type;
@ -54,41 +59,44 @@ ri_better(struct proto_ospf *po, orta * new, orta * old)
if (old->metric1 == LSINFINITY) if (old->metric1 == LSINFINITY)
return 1; return 1;
if (po->rfc1583) if(!rfc1583)
{ {
if ((newtype == RTS_OSPF) && (new->oa->areaid == 0)) newtype = RTS_OSPF_IA; if(new->oa->areaid == 0) newtype = RTS_OSPF_IA;
if ((oldtype == RTS_OSPF) && (old->oa->areaid == 0)) oldtype = RTS_OSPF_IA; if(old->oa->areaid == 0) oldtype = RTS_OSPF_IA;
}
}
if (new->type < old->type) if (new->type < old->type)
return 1; return 1;
if (new->metric2 < old->metric2) if (new->type > old->type)
{ return 0;
if (old->metric2 == LSINFINITY)
return 0; /* Old is E1, new is E2 */
return 1; /* Both are E2 */ /* Same type */
} if(new->type == RTS_OSPF_EXT2)
if (new->metric2 > old->metric2)
{ {
if (new->metric2 == LSINFINITY) if (new->metric2 < old->metric2) return 1;
return 1; /* New is E1, old is E2 */ if (new->metric2 > old->metric2) return 0;
}
return 0; /* Both are E2 */
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) if (new->metric1 < old->metric1)
return 1; return 1;
if (new->metric1 > old->metric1) if (new->metric1 > old->metric1)
return 0; return 0;
/* Metric 1 are the same */
if (new->oa->areaid > old->oa->areaid) return 1; /* Larger AREAID is preffered */ if (new->oa->areaid > old->oa->areaid) return 1; /* Larger AREAID is preffered */
return 0; /* Old is shorter or same */ return 0; /* Old is shorter or same */
@ -96,26 +104,35 @@ ri_better(struct proto_ospf *po, orta * new, orta * old)
static void static void
ri_install(struct proto_ospf *po, ip_addr prefix, int pxlen, int dest, 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)); 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 static void
ospf_rt_spfa(struct ospf_area *oa) 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 proto_ospf *po = oa->po;
struct ospf_lsa_net *ln; struct ospf_lsa_net *ln;
orta nf; orta nf;
struct ospf_iface *iface;
struct top_hash_entry *act, *tmp;
node *n;
if (oa->rt == NULL) if (oa->rt == NULL)
return; return;
@ -149,9 +170,6 @@ ospf_rt_spfa(struct ospf_area *oa)
while (!EMPTY_LIST(oa->cand)) while (!EMPTY_LIST(oa->cand))
{ {
struct top_hash_entry *act, *tmp;
node *n;
n = HEAD(oa->cand); n = HEAD(oa->cand);
act = SKIP_BACK(struct top_hash_entry, cn, n); act = SKIP_BACK(struct top_hash_entry, cn, n);
rem_node(n); rem_node(n);
@ -178,7 +196,7 @@ ospf_rt_spfa(struct ospf_area *oa)
nf.ar = act; nf.ar = act;
nf.nh = act->nh; nf.nh = act->nh;
nf.ifa = act->nhi; 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); rr = (struct ospf_lsa_rt_link *) (rt + 1);
DBG(" Number of links: %u\n", rt->links); DBG(" Number of links: %u\n", rt->links);
@ -208,13 +226,9 @@ ospf_rt_spfa(struct ospf_area *oa)
nf.nh = act->nh; nf.nh = act->nh;
nf.ifa = act->nhi; nf.ifa = act->nhi;
ri_install(po, ipa_from_u32(rtl->id), 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; break;
case LSART_VLNK: /* FIXME !!!!!!!! */
DBG("Ignoring\n");
continue;
break;
case LSART_NET: case LSART_NET:
tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET); tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET);
if (tmp == NULL) if (tmp == NULL)
@ -222,6 +236,8 @@ ospf_rt_spfa(struct ospf_area *oa)
else else
DBG("Found. :-)\n"); DBG("Found. :-)\n");
break; break;
case LSART_VLNK:
case LSART_PTP: case LSART_PTP:
tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT); tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT);
DBG("PTP found.\n"); DBG("PTP found.\n");
@ -247,7 +263,7 @@ ospf_rt_spfa(struct ospf_area *oa)
nf.nh = act->nh; nf.nh = act->nh;
nf.ifa = act->nhi; nf.ifa = act->nhi;
ri_install(po, ipa_and(ipa_from_u32(act->lsa.id), ln->netmask), 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); rts = (u32 *) (ln + 1);
for (i = 0; i < (act->lsa.length - sizeof(struct ospf_lsa_header) - for (i = 0; i < (act->lsa.length - sizeof(struct ospf_lsa_header) -
@ -264,9 +280,244 @@ ospf_rt_spfa(struct ospf_area *oa)
break; 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 void
ospf_rt_spf(struct proto_ospf *po) ospf_rt_spf(struct proto_ospf *po)
{ {
@ -274,12 +525,14 @@ ospf_rt_spf(struct proto_ospf *po)
struct ospf_area *oa; struct ospf_area *oa;
int i; int i;
ort *ri; ort *ri;
struct area_net *anet;
if (po->areano == 0) return;
OSPF_TRACE(D_EVENTS, "Starting routing table calculation"); OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
/* Invalidate old routing table */ /* Invalidate old routing table */
for (i = 0; i < 2; i++) FIB_WALK(&po->rtf, nftmp)
FIB_WALK(&po->rtf[i], nftmp)
{ {
ri = (ort *) nftmp; ri = (ort *) nftmp;
memcpy(&ri->o, &ri->n, sizeof(orta)); /* Backup old data */ 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) 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); ospf_rt_spfa(oa);
} }
if (po->areano > 1) if (po->areano == 1)
{ {
//ospf_rt_sum(oa); ospf_rt_sum(HEAD(po->area_list));
} }
else else
{ {
WALK_LIST(oa, po->area_list) if (po->backbone) ospf_rt_sum(po->backbone); /* And if backbone is not connected? */
{
//if (oa->id == 0) ospf_rt_sum(oa);
} }
WALK_LIST(oa, po->area_list) 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) WALK_LIST(oa, po->area_list)
{ {
if (!oa->stub) if (!oa->stub)
@ -333,7 +605,7 @@ static void
ospf_ext_spfa(struct ospf_area *oa) ospf_ext_spfa(struct ospf_area *oa)
{ {
struct proto_ospf *po = oa->po; struct proto_ospf *po = oa->po;
ort *nf1, *nf2; ort *nf1, *nf2, *nfh;
orta nfa; orta nfa;
struct top_hash_entry *en; struct top_hash_entry *en;
struct proto *p = &po->proto; struct proto *p = &po->proto;
@ -345,6 +617,7 @@ ospf_ext_spfa(struct ospf_area *oa)
int met1, met2; int met1, met2;
neighbor *nn; neighbor *nn;
struct ospf_lsa_rt *rt; struct ospf_lsa_rt *rt;
struct ospf_area *atmp;
OSPF_TRACE(D_EVENTS, "Starting routing table calculation for ext routes"); 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", 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); 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; continue;
ip = ipa_and(ipa_from_u32(en->lsa.id), le->netmask); ip = ipa_and(ipa_from_u32(en->lsa.id), le->netmask);
mlen = ipa_mklen(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); 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 */ continue; /* No AS boundary router found */
if (nf1->n.metric1 == LSINFINITY) 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 (ipa_compare(lt->fwaddr, ipa_from_u32(0)) == 0)
{ {
if (lt->etos > 0) if (lt->etm.etos.ebit)
{ /* FW address == 0 */ { /* FW address == 0 */
met1 = nf1->n.metric1; met1 = nf1->n.metric1;
met2 = lt->metric; met2 = (lt->etm.metric & METRIC_MASK);
} }
else else
{ {
met1 = nf1->n.metric1 + lt->metric; met1 = nf1->n.metric1 + (lt->etm.metric & METRIC_MASK);
met2 = LSINFINITY; met2 = LSINFINITY;
} }
nh = nf1->n.nh; nh = nf1->n.nh;
nhi = nf1->n.ifa; nhi = nf1->n.ifa;
nfh = nf1;
} }
else else
{ /* FW address !=0 */ { /* 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); DBG("Cannot find network route (GW=%I)\n", lt->fwaddr);
continue; continue;
} }
if (lt->etos > 0)
if (lt->etm.etos.ebit)
{ {
met1 = nf2->n.metric1; met1 = nf2->n.metric1;
met2 = lt->metric; met2 = (lt->etm.metric & METRIC_MASK);
} }
else else
{ {
met1 = nf2->n.metric1 + lt->metric; met1 = nf2->n.metric1 + (lt->etm.metric & METRIC_MASK);
met2 = LSINFINITY; met2 = LSINFINITY;
} }
@ -434,9 +721,12 @@ ospf_ext_spfa(struct ospf_area *oa)
nh = nf2->n.nh; nh = nf2->n.nh;
nhi = nf2->n.ifa; 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.capa = 0;
nfa.metric1 = met1; nfa.metric1 = met1;
nfa.metric2 = met2; nfa.metric2 = met2;
@ -445,7 +735,7 @@ ospf_ext_spfa(struct ospf_area *oa)
nfa.nh = nh; nfa.nh = nh;
nfa.ifa = nhi; nfa.ifa = nhi;
nfa.tag = lt->tag; 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; return;
if (en->lsa.age == LSA_MAXAGE) if (en->lsa.age == LSA_MAXAGE)
return; return;
/* FIXME Does it have link back? Test it! */
if (en->color == INSPF) if (en->color == INSPF)
return; return;
if (dist >= en->dist) if (dist >= en->dist)
return; 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 * 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, DBG(" Adding candidate: rt: %I, id: %I, type: %u\n", en->lsa.rt,
en->lsa.id, en->lsa.type); 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); add_tail(l, &en->cn);
} }
} }
/* FIXME Some VLINK stuff should be here */
} }
static void static void
@ -607,30 +900,20 @@ rt_sync(struct proto_ospf *po)
{ {
struct proto *p = &po->proto; struct proto *p = &po->proto;
struct fib_iterator fit; struct fib_iterator fit;
struct fib *fib = &po->rtf[ORT_NET]; struct fib *fib = &po->rtf;
ort *nf; 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"); DBG("Now syncing my rt table with nest's\n");
FIB_ITERATE_INIT(&fit, fib); FIB_ITERATE_INIT(&fit, fib);
again: again1:
FIB_ITERATE_START(fib, &fit, nftmp) FIB_ITERATE_START(fib, &fit, nftmp)
{ {
nf = (ort *) nftmp; nf = (ort *) nftmp;
if (nf->n.metric1 == LSINFINITY) if (memcmp(&nf->n, &nf->o, sizeof(orta)))
{
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)))
{ /* Some difference */ { /* Some difference */
net *ne; net *ne;
rta a0; rta a0;
@ -648,6 +931,9 @@ again:
a0.iface = nf->n.ifa; a0.iface = nf->n.ifa;
a0.gw = nf->n.nh; a0.gw = nf->n.nh;
ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen); 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 = rte_get_temp(&a0);
e->u.ospf.metric1 = nf->n.metric1; e->u.ospf.metric1 = nf->n.metric1;
e->u.ospf.metric2 = nf->n.metric2; e->u.ospf.metric2 = nf->n.metric2;
@ -659,6 +945,45 @@ again:
nf->fn.prefix, ip, nf->nh); 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); 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_ #ifndef _BIRD_OSPF_RT_H_
#define _BIRD_OSPF_RT_H_ #define _BIRD_OSPF_RT_H_
#define ORT_UNDEF -1
#define ORT_ROUTER 1
#define ORT_NET 0
typedef struct orta typedef struct orta
{ {
int type; int type;
int capa; int capa;
#define ORTA_ASBR 1
#define ORTA_ABR 2
struct ospf_area *oa; struct ospf_area *oa;
int metric1; int metric1;
int metric2; int metric2;
@ -27,12 +33,9 @@ orta;
typedef struct ort typedef struct ort
{ {
struct fib_node fn; struct fib_node fn;
int dest;
#define ORT_UNDEF -1
#define ORT_ROUTER 1
#define ORT_NET 0
orta n; orta n;
orta o; orta o;
struct ort *efn; /* For RFC1583 */
} }
ort; ort;

View file

@ -2,7 +2,7 @@
* BIRD -- OSPF Topological Database * BIRD -- OSPF Topological Database
* *
* (c) 1999 Martin Mares <mj@ucw.cz> * (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. * 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 proto_ospf *po = oa->po;
struct ospf_iface *ifa; struct ospf_iface *ifa;
int j = 0, k = 0, v = 0; int j = 0, k = 0;
u16 i = 0; u16 i = 0;
struct ospf_lsa_rt *rt; struct ospf_lsa_rt *rt;
struct ospf_lsa_rt_link *ln; 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)) if ((ifa->an == oa->areaid) && (ifa->state != OSPF_IS_DOWN))
{ {
i++; i++;
if (ifa->type == OSPF_IT_VLINK)
v = 1;
} }
} }
rt = mb_allocz(po->proto.pool, sizeof(struct ospf_lsa_rt) + 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; rt->veb.bit.b = 1;
if ((po->ebit) && (!oa->stub)) if ((po->ebit) && (!oa->stub))
rt->veb.bit.e = 1; rt->veb.bit.e = 1;
rt->veb.bit.v = v;
ln = (struct ospf_lsa_rt_link *) (rt + 1); ln = (struct ospf_lsa_rt_link *) (rt + 1);
WALK_LIST(ifa, po->iface_list) WALK_LIST(ifa, po->iface_list)
@ -83,7 +80,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
} }
else else
{ {
ln->id = ipa_to_u32(ifa->iface->addr->ip); ln->data = ipa_to_u32(ifa->iface->addr->ip);
} }
} }
else else
@ -97,10 +94,8 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
ln->data = 0xffffffff; ln->data = 0xffffffff;
} }
else else
{
i--; /* No link added */ i--; /* No link added */
} }
}
break; break;
case OSPF_IT_BCAST: case OSPF_IT_BCAST:
case OSPF_IT_NBMA: case OSPF_IT_NBMA:
@ -140,14 +135,21 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
} }
} }
break; break;
case OSPF_IT_VLINK: /* FIXME Add virtual links! */ case OSPF_IT_VLINK:
i--; 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; break;
} }
} }
if (ifa->type == OSPF_IT_VLINK)
v = 1;
ln = (ln + 1);
} }
rt->links = i; rt->links = i;
*length = i * sizeof(struct ospf_lsa_rt_link) + sizeof(struct ospf_lsa_rt) + *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; ifa->orignet = 0;
} }
static void * static void *
originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po, originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po,
struct ea_list *attrs) struct ea_list *attrs)
@ -325,15 +328,16 @@ originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po,
if (m1 != LSINFINITY) if (m1 != LSINFINITY)
{ {
et->etos = 0; et->etm.metric = m1;
et->metric = m1; et->etm.etos.tos = 0;
et->etm.etos.ebit = 0;
} }
else else
{ {
et->etos = 0x80; et->etm.metric = m2;
et->metric = m2; et->etm.etos.tos = 0;
et->etm.etos.ebit = 1;
} }
et->padding = 0;
et->tag = tag; et->tag = tag;
if (ipa_compare(e->attrs->gw, ipa_from_u32(0)) != 0) if (ipa_compare(e->attrs->gw, ipa_from_u32(0)) != 0)
{ {
@ -371,6 +375,175 @@ max_ext_lsa(unsigned pxlen)
return i; 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 * originate_ext_lsa - new route received from nest and filters
* @n: network prefix and mask * @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 proto *p = &po->proto;
struct ospf_area *oa; struct ospf_area *oa;
struct ospf_lsa_ext *ext1, *ext2; struct ospf_lsa_ext *ext1, *ext2;
int i; int i, max;
int max;
OSPF_TRACE(D_EVENTS, "Originating Ext lsa for %I/%d.", n->n.prefix, OSPF_TRACE(D_EVENTS, "Originating Ext lsa for %I/%d.", n->n.prefix,
n->n.pxlen); n->n.pxlen);
@ -408,6 +580,7 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
lsa.type = LSA_T_EXT; lsa.type = LSA_T_EXT;
lsa.rt = rtid; lsa.rt = rtid;
lsa.sn = LSA_INITSEQNO; lsa.sn = LSA_INITSEQNO;
body = originate_ext_lsa_body(n, e, po, attrs); body = originate_ext_lsa_body(n, e, po, attrs);
lsa.length = sizeof(struct ospf_lsa_ext) + sizeof(struct ospf_lsa_ext_tos) + lsa.length = sizeof(struct ospf_lsa_ext) + sizeof(struct ospf_lsa_ext_tos) +
sizeof(struct ospf_lsa_header); sizeof(struct ospf_lsa_header);
@ -439,11 +612,14 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
} }
lsasum_calculate(&lsa, body); lsasum_calculate(&lsa, body);
WALK_LIST(oa, po->area_list) WALK_LIST(oa, po->area_list)
{
if (!oa->stub)
{ {
en = lsa_install_new(&lsa, body, oa); en = lsa_install_new(&lsa, body, oa);
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1); ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
body = originate_ext_lsa_body(n, e, po, attrs); body = originate_ext_lsa_body(n, e, po, attrs);
} }
}
mb_free(body); mb_free(body);
if (po->ebit == 0) 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->dist = LSINFINITY;
e->nhi = NULL; e->nhi = NULL;
e->nh = ipa_from_u32(0); e->nh = ipa_from_u32(0);
e->lb = ipa_from_u32(0);
e->lsa.id = lsa; e->lsa.id = lsa;
e->lsa.rt = rtr; e->lsa.rt = rtr;
e->lsa.type = type; e->lsa.type = type;

View file

@ -1,7 +1,7 @@
/* /*
* BIRD -- OSPF * 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. * Can be freely distributed and used under the terms of the GNU GPL.
*/ */
@ -21,15 +21,15 @@ struct top_hash_entry
void *lsa_body; void *lsa_body;
bird_clock_t inst_t; /* Time of installation into DB */ bird_clock_t inst_t; /* Time of installation into DB */
ip_addr nh; /* Next hop */ ip_addr nh; /* Next hop */
ip_addr lb; /* Link back */
struct iface *nhi; struct iface *nhi;
u16 dist; /* Distance from the root */ u32 dist; /* Distance from the root */
u16 ini_age; u16 ini_age;
u8 color; u8 color;
#define OUTSPF 0 #define OUTSPF 0
#define CANDIDATE 1 #define CANDIDATE 1
#define INSPF 2 #define INSPF 2
u8 padding; u8 padding;
u16 padding2;
}; };
struct top_graph struct top_graph
@ -62,5 +62,11 @@ int can_flush_lsa(struct ospf_area *oa);
int max_ext_lsa(unsigned pxlen); int max_ext_lsa(unsigned pxlen);
void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po, void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
struct ea_list *attrs); 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_ */ #endif /* _BIRD_OSPF_TOPOLOGY_H_ */