Temporary OSPFv3 development commit
This commit is contained in:
parent
3aab39f589
commit
c3226991a0
24 changed files with 1911 additions and 1000 deletions
10
configure.in
10
configure.in
|
@ -43,15 +43,13 @@ AC_SUBST(srcdir_rel_mf)
|
||||||
if test "$enable_ipv6" = yes ; then
|
if test "$enable_ipv6" = yes ; then
|
||||||
ip=ipv6
|
ip=ipv6
|
||||||
SUFFIX6=6
|
SUFFIX6=6
|
||||||
if test "$with_protocols" = all ; then
|
|
||||||
with_protocols=bgp,pipe,rip,static
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
ip=ipv4
|
ip=ipv4
|
||||||
SUFFIX6=""
|
SUFFIX6=""
|
||||||
if test "$with_protocols" = all ; then
|
fi
|
||||||
with_protocols=bgp,ospf,pipe,rip,static
|
|
||||||
fi
|
if test "$with_protocols" = all ; then
|
||||||
|
with_protocols=bgp,ospf,pipe,rip,static
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SEARCH_LIBS(clock_gettime,[c rt posix4])
|
AC_SEARCH_LIBS(clock_gettime,[c rt posix4])
|
||||||
|
|
|
@ -71,6 +71,7 @@ ea__find(ea_list *e, unsigned id)
|
||||||
|
|
||||||
while (e)
|
while (e)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (e->flags & EALF_BISECT)
|
if (e->flags & EALF_BISECT)
|
||||||
{
|
{
|
||||||
l = 0;
|
l = 0;
|
||||||
|
@ -88,6 +89,7 @@ ea__find(ea_list *e, unsigned id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
*/
|
||||||
for(m=0; m<e->count; m++)
|
for(m=0; m<e->count; m++)
|
||||||
if (e->attrs[m].id == id)
|
if (e->attrs[m].id == id)
|
||||||
return &e->attrs[m];
|
return &e->attrs[m];
|
||||||
|
|
|
@ -20,6 +20,7 @@ static struct nbma_node *this_nbma;
|
||||||
static struct area_net_config *this_pref;
|
static struct area_net_config *this_pref;
|
||||||
static struct ospf_stubnet_config *this_stubnet;
|
static struct ospf_stubnet_config *this_stubnet;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
static void
|
static void
|
||||||
finish_iface_config(struct ospf_iface_patt *ip)
|
finish_iface_config(struct ospf_iface_patt *ip)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +32,16 @@ finish_iface_config(struct ospf_iface_patt *ip)
|
||||||
if ((ip->autype == OSPF_AUTH_NONE) && (ip->passwords != NULL))
|
if ((ip->autype == OSPF_AUTH_NONE) && (ip->passwords != NULL))
|
||||||
log(L_WARN "Password option without authentication option does not make sense");
|
log(L_WARN "Password option without authentication option does not make sense");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
static void
|
||||||
|
finish_iface_config(struct ospf_iface_patt *ip)
|
||||||
|
{
|
||||||
|
if ((ip->autype != OSPF_AUTH_NONE) || (get_passwords() != NULL))
|
||||||
|
log(L_WARN "Authentication not supported in OSPFv3");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,37 @@
|
||||||
#include "ospf.h"
|
#include "ospf.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
struct ospf_dbdes_packet
|
||||||
|
{
|
||||||
|
struct ospf_packet ospf_packet;
|
||||||
|
u16 iface_mtu;
|
||||||
|
u8 options;
|
||||||
|
union imms imms; /* I, M, MS bits */
|
||||||
|
u32 ddseq;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define hton_opt(X) X
|
||||||
|
#define ntoh_opt(X) X
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
struct ospf_dbdes_packet
|
||||||
|
{
|
||||||
|
struct ospf_packet ospf_packet;
|
||||||
|
u32 options;
|
||||||
|
u16 iface_mtu;
|
||||||
|
u8 padding;
|
||||||
|
union imms imms; /* I, M, MS bits */
|
||||||
|
u32 ddseq;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define hton_opt(X) htonl(X)
|
||||||
|
#define ntoh_opt(X) ntohl(X)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
|
static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
|
||||||
{
|
{
|
||||||
struct ospf_packet *op = &pkt->ospf_packet;
|
struct ospf_packet *op = &pkt->ospf_packet;
|
||||||
|
@ -37,7 +68,7 @@ static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
|
||||||
* @n: neighbor
|
* @n: neighbor
|
||||||
* @next: whether to send a next packet in a sequence (1) or to retransmit the old one (0)
|
* @next: whether to send a next packet in a sequence (1) or to retransmit the old one (0)
|
||||||
*
|
*
|
||||||
* Sending of a database description packet is described in 10.6 of RFC 2328.
|
* Sending of a database description packet is described in 10.8 of RFC 2328.
|
||||||
* Reception of each packet is acknowledged in the sequence number of another.
|
* Reception of each packet is acknowledged in the sequence number of another.
|
||||||
* When I send a packet to a neighbor I keep a copy in a buffer. If the neighbor
|
* When I send a packet to a neighbor I keep a copy in a buffer. If the neighbor
|
||||||
* does not reply, I don't create a new packet but just send the content
|
* does not reply, I don't create a new packet but just send the content
|
||||||
|
@ -65,7 +96,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||||
op = (struct ospf_packet *) pkt;
|
op = (struct ospf_packet *) pkt;
|
||||||
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
|
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
|
||||||
pkt->iface_mtu = htons(ifa->iface->mtu);
|
pkt->iface_mtu = htons(ifa->iface->mtu);
|
||||||
pkt->options = oa->opt.byte;
|
pkt->options = hton_opt(oa->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);
|
||||||
|
@ -88,8 +119,8 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||||
|
|
||||||
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
|
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
|
||||||
pkt->iface_mtu = htons(ifa->iface->mtu);
|
pkt->iface_mtu = htons(ifa->iface->mtu);
|
||||||
pkt->options = oa->opt.byte;
|
|
||||||
pkt->ddseq = htonl(n->dds);
|
pkt->ddseq = htonl(n->dds);
|
||||||
|
pkt->options = hton_opt(oa->options);
|
||||||
|
|
||||||
j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header); /* Number of possible lsaheaders to send */
|
j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header); /* Number of possible lsaheaders to send */
|
||||||
lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet));
|
lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet));
|
||||||
|
@ -102,16 +133,8 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||||
for (; i > 0; i--)
|
for (; i > 0; i--)
|
||||||
{
|
{
|
||||||
struct top_hash_entry *en= (struct top_hash_entry *) sn;
|
struct top_hash_entry *en= (struct top_hash_entry *) sn;
|
||||||
int send = 1;
|
|
||||||
|
|
||||||
/* Don't send ext LSA into stub areas */
|
if (ospf_lsa_flooding_allowed(&en->lsa, en->domain, ifa))
|
||||||
if (oa->stub && (en->lsa.type == LSA_T_EXT)) send = 0;
|
|
||||||
/* Don't send ext LSAs through VLINK */
|
|
||||||
if ((ifa->type == OSPF_IT_VLINK) && (en->lsa.type == LSA_T_EXT)) send = 0;;
|
|
||||||
/* Don't send LSA of other areas */
|
|
||||||
if ((en->lsa.type != LSA_T_EXT) && (en->oa != oa)) send = 0;
|
|
||||||
|
|
||||||
if (send)
|
|
||||||
{
|
{
|
||||||
htonlsah(&(en->lsa), lsa);
|
htonlsah(&(en->lsa), lsa);
|
||||||
DBG("Working on: %d\n", i);
|
DBG("Working on: %d\n", i);
|
||||||
|
@ -204,13 +227,13 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
|
||||||
for (i = 0; i < j; i++)
|
for (i = 0; i < j; i++)
|
||||||
{
|
{
|
||||||
ntohlsah(plsa + i, &lsa);
|
ntohlsah(plsa + i, &lsa);
|
||||||
if (((he = ospf_hash_find(gr, oa->areaid, lsa.id, lsa.rt, lsa.type)) == NULL) ||
|
if (((he = ospfxx_hash_find_smart(gr, n->ifa, &lsa)) == NULL) ||
|
||||||
(lsa_comp(&lsa, &(he->lsa)) == 1))
|
(lsa_comp(&lsa, &(he->lsa)) == 1))
|
||||||
{
|
{
|
||||||
/* Is this condition necessary? */
|
/* Is this condition necessary? */
|
||||||
if (ospf_hash_find(n->lsrqh, oa->areaid, lsa.id, lsa.rt, lsa.type) == NULL)
|
if (ospfxx_hash_find_smart(n->lsrqh, n->ifa, &lsa) == NULL)
|
||||||
{
|
{
|
||||||
sn = ospf_hash_get(n->lsrqh, oa, lsa.id, lsa.rt, lsa.type);
|
sn = ospfxx_hash_get_smart(n->lsrqh, n->ifa, &lsa);
|
||||||
ntohlsah(plsa + i, &(sn->lsa));
|
ntohlsah(plsa + i, &(sn->lsa));
|
||||||
s_add_tail(&(n->lsrql), SNODE sn);
|
s_add_tail(&(n->lsrql), SNODE sn);
|
||||||
}
|
}
|
||||||
|
@ -219,13 +242,17 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n)
|
struct ospf_neighbor *n)
|
||||||
{
|
{
|
||||||
|
struct ospf_dbdes_packet *ps = (void *) ps_i;
|
||||||
struct proto *p = &ifa->oa->po->proto;
|
struct proto *p = &ifa->oa->po->proto;
|
||||||
u32 myrid = p->cf->global->router_id;
|
u32 myrid = p->cf->global->router_id;
|
||||||
unsigned int size = ntohs(ps->ospf_packet.length);
|
unsigned int size = ntohs(ps->ospf_packet.length);
|
||||||
|
|
||||||
|
u32 ps_ddseq = ntohl(ps->ddseq);
|
||||||
|
u32 ps_options = ntoh_opt(ps->options);
|
||||||
|
|
||||||
OSPF_PACKET(ospf_dump_dbdes, ps, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
|
OSPF_PACKET(ospf_dump_dbdes, ps, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
|
||||||
|
|
||||||
ospf_neigh_sm(n, INM_HELLOREC);
|
ospf_neigh_sm(n, INM_HELLOREC);
|
||||||
|
@ -246,9 +273,9 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
||||||
&& (n->rid > myrid) && (size == sizeof(struct ospf_dbdes_packet)))
|
&& (n->rid > myrid) && (size == sizeof(struct ospf_dbdes_packet)))
|
||||||
{
|
{
|
||||||
/* I'm slave! */
|
/* I'm slave! */
|
||||||
n->dds = ntohl(ps->ddseq);
|
n->dds = ps_ddseq;
|
||||||
n->ddr = ntohl(ps->ddseq);
|
n->ddr = ps_ddseq;
|
||||||
n->options = ps->options;
|
n->options = ps_options;
|
||||||
n->myimms.bit.ms = 0;
|
n->myimms.bit.ms = 0;
|
||||||
n->imms.byte = ps->imms.byte;
|
n->imms.byte = ps->imms.byte;
|
||||||
OSPF_TRACE(D_PACKETS, "I'm slave to %I.", n->ip);
|
OSPF_TRACE(D_PACKETS, "I'm slave to %I.", n->ip);
|
||||||
|
@ -258,11 +285,11 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((ps->imms.bit.i == 0) && (ps->imms.bit.ms == 0)) &&
|
if (((ps->imms.bit.i == 0) && (ps->imms.bit.ms == 0)) &&
|
||||||
(n->rid < myrid) && (n->dds == ntohl(ps->ddseq)))
|
(n->rid < myrid) && (n->dds == ps_ddseq))
|
||||||
{
|
{
|
||||||
/* I'm master! */
|
/* I'm master! */
|
||||||
n->options = ps->options;
|
n->options = ps_options;
|
||||||
n->ddr = ntohl(ps->ddseq) - 1; /* It will be set corectly a few lines down */
|
n->ddr = ps_ddseq - 1; /* It will be set corectly a few lines down */
|
||||||
n->imms.byte = ps->imms.byte;
|
n->imms.byte = ps->imms.byte;
|
||||||
OSPF_TRACE(D_PACKETS, "I'm master to %I.", n->ip);
|
OSPF_TRACE(D_PACKETS, "I'm master to %I.", n->ip);
|
||||||
ospf_neigh_sm(n, INM_NEGDONE);
|
ospf_neigh_sm(n, INM_NEGDONE);
|
||||||
|
@ -274,8 +301,8 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
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))
|
(ps_ddseq == n->ddr))
|
||||||
{
|
{
|
||||||
/* Duplicate packet */
|
/* Duplicate packet */
|
||||||
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
|
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
|
||||||
|
@ -287,7 +314,7 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
n->ddr = ntohl(ps->ddseq);
|
n->ddr = ps_ddseq;
|
||||||
|
|
||||||
if (ps->imms.bit.ms != n->imms.bit.ms) /* M/S bit differs */
|
if (ps->imms.bit.ms != n->imms.bit.ms) /* M/S bit differs */
|
||||||
{
|
{
|
||||||
|
@ -307,7 +334,7 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
||||||
|
|
||||||
n->imms.byte = ps->imms.byte;
|
n->imms.byte = ps->imms.byte;
|
||||||
|
|
||||||
if (ps->options != n->options) /* Options differs */
|
if (ps_options != n->options) /* Options differs */
|
||||||
{
|
{
|
||||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)",
|
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)",
|
||||||
n->ip);
|
n->ip);
|
||||||
|
@ -317,7 +344,7 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
||||||
|
|
||||||
if (n->myimms.bit.ms)
|
if (n->myimms.bit.ms)
|
||||||
{
|
{
|
||||||
if (ntohl(ps->ddseq) != n->dds) /* MASTER */
|
if (ps_ddseq != n->dds) /* MASTER */
|
||||||
{
|
{
|
||||||
OSPF_TRACE(D_PACKETS,
|
OSPF_TRACE(D_PACKETS,
|
||||||
"dbdes - sequence mismatch neighbor %I (master)", n->ip);
|
"dbdes - sequence mismatch neighbor %I (master)", n->ip);
|
||||||
|
@ -339,15 +366,15 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ntohl(ps->ddseq) != (n->dds + 1)) /* SLAVE */
|
if (ps_ddseq != (n->dds + 1)) /* SLAVE */
|
||||||
{
|
{
|
||||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)",
|
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)",
|
||||||
n->ip);
|
n->ip);
|
||||||
ospf_neigh_sm(n, INM_SEQMIS);
|
ospf_neigh_sm(n, INM_SEQMIS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
n->ddr = ntohl(ps->ddseq);
|
n->ddr = ps_ddseq;
|
||||||
n->dds = ntohl(ps->ddseq);
|
n->dds = ps_ddseq;
|
||||||
ospf_dbdes_reqladd(ps, n);
|
ospf_dbdes_reqladd(ps, n);
|
||||||
ospf_dbdes_send(n, 1);
|
ospf_dbdes_send(n, 1);
|
||||||
}
|
}
|
||||||
|
@ -355,8 +382,8 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
||||||
break;
|
break;
|
||||||
case NEIGHBOR_LOADING:
|
case NEIGHBOR_LOADING:
|
||||||
case NEIGHBOR_FULL:
|
case NEIGHBOR_FULL:
|
||||||
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))
|
&& (ps_ddseq == n->ddr))
|
||||||
/* Only duplicate are accepted */
|
/* Only duplicate are accepted */
|
||||||
{
|
{
|
||||||
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
|
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
|
||||||
|
@ -371,7 +398,7 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
||||||
{
|
{
|
||||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)",
|
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)",
|
||||||
n->ip);
|
n->ip);
|
||||||
DBG("PS=%u, DDR=%u, DDS=%u\n", ntohl(ps->ddseq), n->ddr, n->dds);
|
DBG("PS=%u, DDR=%u, DDS=%u\n", ps_ddseq, n->ddr, n->dds);
|
||||||
ospf_neigh_sm(n, INM_SEQMIS);
|
ospf_neigh_sm(n, INM_SEQMIS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#define _BIRD_OSPF_DBDES_H_
|
#define _BIRD_OSPF_DBDES_H_
|
||||||
|
|
||||||
void ospf_dbdes_send(struct ospf_neighbor *n, int next);
|
void ospf_dbdes_send(struct ospf_neighbor *n, int next);
|
||||||
void ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
|
void ospf_dbdes_receive(struct ospf_packet *ps, struct ospf_iface *ifa,
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n);
|
struct ospf_neighbor *n);
|
||||||
|
|
||||||
#endif /* _BIRD_OSPF_DBDES_H_ */
|
#endif /* _BIRD_OSPF_DBDES_H_ */
|
||||||
|
|
|
@ -8,12 +8,46 @@
|
||||||
|
|
||||||
#include "ospf.h"
|
#include "ospf.h"
|
||||||
|
|
||||||
void
|
|
||||||
ospf_hello_receive(struct ospf_hello_packet *ps,
|
#ifdef OSPFv2
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n, ip_addr faddr)
|
struct ospf_hello_packet
|
||||||
{
|
{
|
||||||
|
struct ospf_packet ospf_packet;
|
||||||
|
ip_addr netmask;
|
||||||
|
u16 helloint;
|
||||||
|
u8 options;
|
||||||
|
u8 priority;
|
||||||
|
u32 deadint;
|
||||||
|
u32 dr;
|
||||||
|
u32 bdr;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
struct ospf_hello_packet
|
||||||
|
{
|
||||||
|
struct ospf_packet ospf_packet;
|
||||||
|
u32 iface_id;
|
||||||
|
u8 priority;
|
||||||
|
u8 options3;
|
||||||
|
u8 options2;
|
||||||
|
u8 options;
|
||||||
|
u16 helloint;
|
||||||
|
u16 deadint;
|
||||||
|
u32 dr;
|
||||||
|
u32 bdr;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||||
|
struct ospf_neighbor *n, ip_addr faddr)
|
||||||
|
{
|
||||||
|
struct ospf_hello_packet *ps = (void *) ps_i;
|
||||||
u32 *pnrid;
|
u32 *pnrid;
|
||||||
ip_addr olddr, oldbdr;
|
u32 olddr, oldbdr, oldiface_id, tmp;
|
||||||
ip_addr mask;
|
ip_addr mask;
|
||||||
char *beg = "Bad OSPF hello packet from ", *rec = " received: ";
|
char *beg = "Bad OSPF hello packet from ", *rec = " received: ";
|
||||||
struct proto *p = (struct proto *) ifa->oa->po;
|
struct proto *p = (struct proto *) ifa->oa->po;
|
||||||
|
@ -21,9 +55,10 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
|
||||||
|
|
||||||
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s%s", faddr,
|
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s%s", faddr,
|
||||||
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
|
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
mask = ps->netmask;
|
mask = ps->netmask;
|
||||||
ipa_ntoh(mask);
|
ipa_ntoh(mask);
|
||||||
|
|
||||||
if (ifa->type != OSPF_IT_VLINK)
|
if (ifa->type != OSPF_IT_VLINK)
|
||||||
{
|
{
|
||||||
char *msg = L_WARN "Received HELLO packet %s (%I) is inconsistent "
|
char *msg = L_WARN "Received HELLO packet %s (%I) is inconsistent "
|
||||||
|
@ -50,24 +85,30 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ntohs(ps->helloint) != ifa->helloint)
|
tmp = ntohs(ps->helloint);
|
||||||
|
if (tmp != ifa->helloint)
|
||||||
{
|
{
|
||||||
log(L_ERR "%s%I%shello interval mismatch (%d).", beg, faddr, rec,
|
log(L_ERR "%s%I%shello interval mismatch (%d).", beg, faddr, rec, tmp);
|
||||||
ntohs(ps->helloint));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntohl(ps->deadint) != ifa->dead)
|
#ifdef OSPFv2
|
||||||
|
tmp = ntohl(ps->deadint);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
tmp = ntohs(ps->deadint);
|
||||||
|
#endif
|
||||||
|
if (tmp != ifa->dead)
|
||||||
{
|
{
|
||||||
log(L_ERR "%s%I%sdead interval mismatch (%d).", beg, faddr, rec,
|
log(L_ERR "%s%I%sdead interval mismatch (%d).", beg, faddr, rec, tmp);
|
||||||
ntohl(ps->deadint));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps->options != ifa->oa->opt.byte)
|
tmp = !(ps->options & OPT_E);
|
||||||
|
if (tmp != ifa->oa->stub)
|
||||||
{
|
{
|
||||||
log(L_ERR "%s%I%soptions mismatch (0x%x).", beg, faddr, rec, ps->options);
|
log(L_ERR "%s%I%sstub area flag mismatch (%d).", beg, faddr, rec, tmp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,12 +152,12 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
|
||||||
|
|
||||||
n->rid = ntohl(((struct ospf_packet *) ps)->routerid);
|
n->rid = ntohl(((struct ospf_packet *) ps)->routerid);
|
||||||
n->ip = faddr;
|
n->ip = faddr;
|
||||||
n->dr = ps->dr;
|
n->dr = ntohl(ps->dr);
|
||||||
ipa_ntoh(n->dr);
|
n->bdr = ntohl(ps->bdr);
|
||||||
n->bdr = ps->bdr;
|
|
||||||
ipa_ntoh(n->bdr);
|
|
||||||
n->priority = ps->priority;
|
n->priority = ps->priority;
|
||||||
n->options = ps->options;
|
#ifdef OSPFv3
|
||||||
|
n->iface_id = ntohl(ps->iface_id);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
ospf_neigh_sm(n, INM_HELLOREC);
|
ospf_neigh_sm(n, INM_HELLOREC);
|
||||||
|
|
||||||
|
@ -140,35 +181,54 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
|
||||||
ospf_neigh_sm(n, INM_1WAYREC);
|
ospf_neigh_sm(n, INM_1WAYREC);
|
||||||
|
|
||||||
olddr = n->dr;
|
olddr = n->dr;
|
||||||
n->dr = ipa_ntoh(ps->dr);
|
|
||||||
oldbdr = n->bdr;
|
oldbdr = n->bdr;
|
||||||
n->bdr = ipa_ntoh(ps->bdr);
|
|
||||||
oldpriority = n->priority;
|
oldpriority = n->priority;
|
||||||
|
#ifdef OSPFv3
|
||||||
|
oldiface_id = n->iface_id;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
n->dr = ntohl(ps->dr);
|
||||||
|
n->bdr = ntohl(ps->bdr);
|
||||||
n->priority = ps->priority;
|
n->priority = ps->priority;
|
||||||
|
#ifdef OSPFv3
|
||||||
|
n->iface_id = ntohl(ps->iface_id);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Check priority change */
|
/* Check priority change */
|
||||||
if (n->state >= NEIGHBOR_2WAY)
|
if (n->state >= NEIGHBOR_2WAY)
|
||||||
{
|
{
|
||||||
|
#ifdef OSPFv2
|
||||||
|
u32 rid = n->ip;
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
u32 rid = p->cf->global->router_id;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (n->priority != oldpriority)
|
if (n->priority != oldpriority)
|
||||||
ospf_iface_sm(ifa, ISM_NEICH);
|
ospf_iface_sm(ifa, ISM_NEICH);
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
if (n->iface_id != oldiface_id)
|
||||||
|
ospf_iface_sm(ifa, ISM_NEICH);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Router is declaring itself ad DR and there is no BDR */
|
/* Router is declaring itself ad DR and there is no BDR */
|
||||||
if (ipa_equal(n->ip, n->dr) && (ipa_to_u32(n->bdr) == 0)
|
if ((rid == n->dr) && (n->bdr == 0)
|
||||||
&& (n->state != NEIGHBOR_FULL))
|
&& (n->state != NEIGHBOR_FULL))
|
||||||
ospf_iface_sm(ifa, ISM_BACKS);
|
ospf_iface_sm(ifa, ISM_BACKS);
|
||||||
|
|
||||||
/* Neighbor is declaring itself as BDR */
|
/* Neighbor is declaring itself as BDR */
|
||||||
if (ipa_equal(n->ip, n->bdr) && (n->state != NEIGHBOR_FULL))
|
if ((rid == n->bdr) && (n->state != NEIGHBOR_FULL))
|
||||||
ospf_iface_sm(ifa, ISM_BACKS);
|
ospf_iface_sm(ifa, ISM_BACKS);
|
||||||
|
|
||||||
/* Neighbor is newly declaring itself as DR or BDR */
|
/* Neighbor is newly declaring itself as DR or BDR */
|
||||||
if ((ipa_equal(n->ip, n->dr) && (!ipa_equal(n->dr, olddr)))
|
if (((rid == n->dr) && (n->dr != olddr))
|
||||||
|| (ipa_equal(n->ip, n->bdr) && (!ipa_equal(n->bdr, oldbdr))))
|
|| ((rid == n->bdr) && (n->bdr != oldbdr)))
|
||||||
ospf_iface_sm(ifa, ISM_NEICH);
|
ospf_iface_sm(ifa, ISM_NEICH);
|
||||||
|
|
||||||
/* Neighbor is no more declaring itself as DR or BDR */
|
/* Neighbor is no more declaring itself as DR or BDR */
|
||||||
if ((ipa_equal(n->ip, olddr) && (!ipa_equal(n->dr, olddr)))
|
if (((rid == olddr) && (n->dr != olddr))
|
||||||
|| (ipa_equal(n->ip, oldbdr) && (!ipa_equal(n->bdr, oldbdr))))
|
|| ((rid == oldbdr) && (n->bdr != oldbdr)))
|
||||||
ospf_iface_sm(ifa, ISM_NEICH);
|
ospf_iface_sm(ifa, ISM_NEICH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +241,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
|
ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
|
||||||
{
|
{
|
||||||
struct ospf_iface *ifa;
|
struct ospf_iface *ifa;
|
||||||
struct ospf_hello_packet *pkt;
|
struct ospf_hello_packet *pkt;
|
||||||
|
@ -223,18 +283,33 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
|
||||||
|
|
||||||
ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
|
ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
|
pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
|
||||||
ipa_hton(pkt->netmask);
|
ipa_hton(pkt->netmask);
|
||||||
if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
|
if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
|
||||||
pkt->netmask = IPA_NONE;
|
pkt->netmask = IPA_NONE;
|
||||||
|
#endif
|
||||||
|
|
||||||
pkt->helloint = ntohs(ifa->helloint);
|
pkt->helloint = ntohs(ifa->helloint);
|
||||||
pkt->options = ifa->oa->opt.byte;
|
|
||||||
pkt->priority = ifa->priority;
|
pkt->priority = ifa->priority;
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
pkt->iface_id = htonl(ifa->iface->index);
|
||||||
|
|
||||||
|
pkt->options3 = ifa->oa->options >> 16;
|
||||||
|
pkt->options2 = ifa->oa->options >> 8;
|
||||||
|
#endif
|
||||||
|
pkt->options = ifa->oa->options;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
pkt->deadint = htonl(ifa->dead);
|
pkt->deadint = htonl(ifa->dead);
|
||||||
pkt->dr = ifa->drip;
|
pkt->dr = htonl(ipa_to_u32(ifa->drip));
|
||||||
ipa_hton(pkt->dr);
|
pkt->bdr = htonl(ipa_to_u32(ifa->bdrip));
|
||||||
pkt->bdr = ifa->bdrip;
|
#else /* OSPFv3 */
|
||||||
ipa_hton(pkt->bdr);
|
pkt->deadint = htons(ifa->dead);
|
||||||
|
pkt->dr = htonl(ifa->drid);
|
||||||
|
pkt->bdr = htonl(ifa->bdrid);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Fill all neighbors */
|
/* Fill all neighbors */
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
#ifndef _BIRD_OSPF_HELLO_H_
|
#ifndef _BIRD_OSPF_HELLO_H_
|
||||||
#define _BIRD_OSPF_HELLO_H_
|
#define _BIRD_OSPF_HELLO_H_
|
||||||
|
|
||||||
void ospf_hello_receive(struct ospf_hello_packet *ps,
|
void ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n, ip_addr faddr);
|
struct ospf_neighbor *n, ip_addr faddr);
|
||||||
void ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn);
|
void ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn);
|
||||||
|
|
||||||
#endif /* _BIRD_OSPF_HELLO_H_ */
|
#endif /* _BIRD_OSPF_HELLO_H_ */
|
||||||
|
|
|
@ -157,16 +157,16 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
|
||||||
rfree(ifa->dr_sk);
|
rfree(ifa->dr_sk);
|
||||||
ifa->dr_sk = NULL;
|
ifa->dr_sk = NULL;
|
||||||
}
|
}
|
||||||
if ((oldstate == OSPF_IS_DR) && (ifa->nlsa != NULL))
|
if ((oldstate == OSPF_IS_DR) && (ifa->net_lsa != NULL))
|
||||||
{
|
{
|
||||||
ifa->nlsa->lsa.age = LSA_MAXAGE;
|
ifa->net_lsa->lsa.age = LSA_MAXAGE;
|
||||||
if (state >= OSPF_IS_WAITING)
|
if (state >= OSPF_IS_WAITING)
|
||||||
{
|
{
|
||||||
ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa);
|
ospf_lsupd_flush_nlsa(po, ifa->net_lsa);
|
||||||
}
|
}
|
||||||
if (can_flush_lsa(po))
|
if (can_flush_lsa(po))
|
||||||
flush_lsa(ifa->nlsa, po);
|
flush_lsa(ifa->net_lsa, po);
|
||||||
ifa->nlsa = NULL;
|
ifa->net_lsa = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,8 +412,16 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface,
|
||||||
ifa->waitint = ip->waitint;
|
ifa->waitint = ip->waitint;
|
||||||
ifa->dead = (ip->dead == 0) ? ip->deadc * ifa->helloint : ip->dead;
|
ifa->dead = (ip->dead == 0) ? ip->deadc * ifa->helloint : ip->dead;
|
||||||
ifa->stub = ip->stub;
|
ifa->stub = ip->stub;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
ifa->autype = ip->autype;
|
ifa->autype = ip->autype;
|
||||||
ifa->passwords = ip->passwords;
|
ifa->passwords = ip->passwords;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
ifa->instance_id = ip->instance_id;
|
||||||
|
#endif
|
||||||
|
|
||||||
ifa->rxbuf = ip->rxbuf;
|
ifa->rxbuf = ip->rxbuf;
|
||||||
|
|
||||||
if (ip->type == OSPF_IT_UNDEF)
|
if (ip->type == OSPF_IT_UNDEF)
|
||||||
|
|
|
@ -8,6 +8,14 @@
|
||||||
|
|
||||||
#include "ospf.h"
|
#include "ospf.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct ospf_lsack_packet
|
||||||
|
{
|
||||||
|
struct ospf_packet ospf_packet;
|
||||||
|
struct ospf_lsa_header lsh[];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
char *s_queue[] = { "direct", "delayed" };
|
char *s_queue[] = { "direct", "delayed" };
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,14 +26,12 @@ static void ospf_dump_lsack(struct proto *p, struct ospf_lsack_packet *pkt)
|
||||||
ASSERT(op->type == LSACK_P);
|
ASSERT(op->type == LSACK_P);
|
||||||
ospf_dump_common(p, op);
|
ospf_dump_common(p, op);
|
||||||
|
|
||||||
struct ospf_lsa_header *plsa = (void *) (pkt + 1);
|
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) /
|
j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) /
|
||||||
sizeof(struct ospf_lsa_header);
|
sizeof(struct ospf_lsa_header);
|
||||||
|
|
||||||
for (i = 0; i < j; i++)
|
for (i = 0; i < j; i++)
|
||||||
ospf_dump_lsahdr(p, plsa + i);
|
ospf_dump_lsahdr(p, pkt->lsh + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,7 +76,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
||||||
op = (struct ospf_packet *) sk->tbuf;
|
op = (struct ospf_packet *) sk->tbuf;
|
||||||
|
|
||||||
ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
|
ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
|
||||||
h = (struct ospf_lsa_header *) (pk + 1);
|
h = pk->lsh;
|
||||||
|
|
||||||
while (!EMPTY_LIST(n->ackl[queue]))
|
while (!EMPTY_LIST(n->ackl[queue]))
|
||||||
{
|
{
|
||||||
|
@ -141,10 +147,11 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_lsack_receive(struct ospf_lsack_packet *ps,
|
ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n)
|
struct ospf_neighbor *n)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header lsa, *plsa;
|
struct ospf_lsack_packet *ps = (void *) ps_i;
|
||||||
|
struct ospf_lsa_header lsa;
|
||||||
u16 nolsa;
|
u16 nolsa;
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
struct proto *p = &ifa->oa->po->proto;
|
struct proto *p = &ifa->oa->po->proto;
|
||||||
|
@ -167,12 +174,10 @@ ospf_lsack_receive(struct ospf_lsack_packet *ps,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plsa = (struct ospf_lsa_header *) (ps + 1);
|
|
||||||
|
|
||||||
for (i = 0; i < nolsa; i++)
|
for (i = 0; i < nolsa; i++)
|
||||||
{
|
{
|
||||||
ntohlsah(plsa + i, &lsa);
|
ntohlsah(ps->lsh + i, &lsa);
|
||||||
if ((en = ospf_hash_find_header(n->lsrth, n->ifa->oa->areaid, &lsa)) == NULL)
|
if ((en = ospfxx_hash_find_smart(n->lsrth, n->ifa, &lsa)) == NULL)
|
||||||
continue; /* pg 155 */
|
continue; /* pg 155 */
|
||||||
|
|
||||||
if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */
|
if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */
|
||||||
|
|
|
@ -16,8 +16,8 @@ struct lsah_n
|
||||||
struct ospf_lsa_header lsa;
|
struct ospf_lsa_header lsa;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ospf_lsack_receive(struct ospf_lsack_packet *ps,
|
void ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n);
|
struct ospf_neighbor *n);
|
||||||
void ospf_lsack_send(struct ospf_neighbor *n, int queue);
|
void ospf_lsack_send(struct ospf_neighbor *n, int queue);
|
||||||
void ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h,
|
void ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h,
|
||||||
int queue);
|
int queue);
|
||||||
|
|
|
@ -65,8 +65,8 @@ ospf_age(struct proto_ospf *po)
|
||||||
flush_lsa(en, po);
|
flush_lsa(en, po);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((en->lsa.rt == p->cf->global->router_id) &&(en->lsa.age >=
|
if ((en->lsa.rt == p->cf->global->router_id) &&
|
||||||
LSREFRESHTIME))
|
(en->lsa.age >= LSREFRESHTIME))
|
||||||
{
|
{
|
||||||
OSPF_TRACE(D_EVENTS, "Refreshing my LSA: Type: %u, Id: %R, Rt: %R",
|
OSPF_TRACE(D_EVENTS, "Refreshing my LSA: Type: %u, Id: %R, Rt: %R",
|
||||||
en->lsa.type, en->lsa.id, en->lsa.rt);
|
en->lsa.type, en->lsa.id, en->lsa.rt);
|
||||||
|
@ -75,7 +75,7 @@ ospf_age(struct proto_ospf *po)
|
||||||
en->inst_t = now;
|
en->inst_t = now;
|
||||||
en->ini_age = 0;
|
en->ini_age = 0;
|
||||||
lsasum_calculate(&en->lsa, en->lsa_body);
|
lsasum_calculate(&en->lsa, en->lsa_body);
|
||||||
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, en->oa, 1);
|
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, en->domain, 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((en->lsa.age = (en->ini_age + (now - en->inst_t))) >= LSA_MAXAGE)
|
if ((en->lsa.age = (en->ini_age + (now - en->inst_t))) >= LSA_MAXAGE)
|
||||||
|
@ -96,7 +96,9 @@ void
|
||||||
htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
|
htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
|
||||||
{
|
{
|
||||||
n->age = htons(h->age);
|
n->age = htons(h->age);
|
||||||
|
#ifdef OSPFv2
|
||||||
n->options = h->options;
|
n->options = h->options;
|
||||||
|
#endif
|
||||||
n->type = h->type;
|
n->type = h->type;
|
||||||
n->id = htonl(h->id);
|
n->id = htonl(h->id);
|
||||||
n->rt = htonl(h->rt);
|
n->rt = htonl(h->rt);
|
||||||
|
@ -109,7 +111,9 @@ void
|
||||||
ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
|
ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
|
||||||
{
|
{
|
||||||
h->age = ntohs(n->age);
|
h->age = ntohs(n->age);
|
||||||
|
#ifdef OSPFv2
|
||||||
h->options = n->options;
|
h->options = n->options;
|
||||||
|
#endif
|
||||||
h->type = n->type;
|
h->type = n->type;
|
||||||
h->id = ntohl(n->id);
|
h->id = ntohl(n->id);
|
||||||
h->rt = ntohl(n->rt);
|
h->rt = ntohl(n->rt);
|
||||||
|
@ -119,7 +123,7 @@ ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
htonlsab(void *h, void *n, u8 type, u16 len)
|
htonlsab(void *h, void *n, u16 type, u16 len)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -132,24 +136,43 @@ htonlsab(void *h, void *n, u8 type, u16 len)
|
||||||
|
|
||||||
nrt = n;
|
nrt = n;
|
||||||
hrt = h;
|
hrt = h;
|
||||||
links = hrt->links;
|
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
nrt->veb.byte = hrt->veb.byte;
|
nrt->veb.byte = hrt->veb.byte;
|
||||||
nrt->padding = 0;
|
nrt->padding = 0;
|
||||||
nrt->links = htons(hrt->links);
|
nrt->links = htons(hrt->links);
|
||||||
|
links = hrt->links;
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
hrt->options = htonl(nrt->options);
|
||||||
|
links = (len - sizeof(struct ospf_lsa_rt)) /
|
||||||
|
sizeof(struct ospf_lsa_rt_link);
|
||||||
|
#endif
|
||||||
|
|
||||||
nrtl = (struct ospf_lsa_rt_link *) (nrt + 1);
|
nrtl = (struct ospf_lsa_rt_link *) (nrt + 1);
|
||||||
hrtl = (struct ospf_lsa_rt_link *) (hrt + 1);
|
hrtl = (struct ospf_lsa_rt_link *) (hrt + 1);
|
||||||
for (i = 0; i < links; i++)
|
for (i = 0; i < links; i++)
|
||||||
{
|
{
|
||||||
(nrtl + i)->id = htonl((hrtl + i)->id);
|
#ifdef OSPFv2
|
||||||
(nrtl + i)->data = htonl((hrtl + i)->data);
|
nrtl[i].id = htonl(hrtl[i].id);
|
||||||
(nrtl + i)->type = (hrtl + i)->type;
|
nrtl[i].data = htonl(hrtl[i].data);
|
||||||
(nrtl + i)->notos = (hrtl + i)->notos;
|
nrtl[i].type = hrtl[i].type;
|
||||||
(nrtl + i)->metric = htons((hrtl + i)->metric);
|
nrtl[i].notos = hrtl[i].notos;
|
||||||
|
nrtl[i].metric = htons(hrtl[i].metric);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
nrtl[i].type = hrtl[i].type;
|
||||||
|
nrtl[i].padding = 0;
|
||||||
|
nrtl[i].metric = htons(hrtl[i].metric);
|
||||||
|
nrtl[i].lif = htonl(hrtl[i].lif);
|
||||||
|
nrtl[i].nif = htonl(hrtl[i].nif);
|
||||||
|
nrtl[i].id = htonl(hrtl[i].id);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LSA_T_NET:
|
case LSA_T_NET:
|
||||||
|
case LSA_T_SUM_NET:
|
||||||
|
case LSA_T_SUM_RT:
|
||||||
|
case LSA_T_EXT:
|
||||||
{
|
{
|
||||||
u32 *hid, *nid;
|
u32 *hid, *nid;
|
||||||
|
|
||||||
|
@ -162,59 +185,14 @@ htonlsab(void *h, void *n, u8 type, u16 len)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LSA_T_SUM_NET:
|
|
||||||
case LSA_T_SUM_RT:
|
|
||||||
{
|
|
||||||
struct ospf_lsa_sum *hs, *ns;
|
|
||||||
union ospf_lsa_sum_tm *hn, *nn;
|
|
||||||
|
|
||||||
hs = h;
|
|
||||||
ns = n;
|
|
||||||
|
|
||||||
ns->netmask = hs->netmask;
|
|
||||||
ipa_hton(ns->netmask);
|
|
||||||
|
|
||||||
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_sum)) /
|
|
||||||
sizeof(union ospf_lsa_sum_tm)); i++)
|
|
||||||
{
|
|
||||||
(nn + i)->metric = htonl((hn + i)->metric);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LSA_T_EXT:
|
|
||||||
{
|
|
||||||
struct ospf_lsa_ext *he, *ne;
|
|
||||||
struct ospf_lsa_ext_tos *ht, *nt;
|
|
||||||
|
|
||||||
he = h;
|
|
||||||
ne = n;
|
|
||||||
|
|
||||||
ne->netmask = he->netmask;
|
|
||||||
ipa_hton(ne->netmask);
|
|
||||||
|
|
||||||
ht = (struct ospf_lsa_ext_tos *) (he + 1);
|
|
||||||
nt = (struct ospf_lsa_ext_tos *) (ne + 1);
|
|
||||||
|
|
||||||
for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) /
|
|
||||||
sizeof(struct ospf_lsa_ext_tos)); i++)
|
|
||||||
{
|
|
||||||
(nt + i)->etm.metric = htonl((ht + i)->etm.metric);
|
|
||||||
(nt + i)->fwaddr = (ht + i)->fwaddr;
|
|
||||||
ipa_hton((nt + i)->fwaddr);
|
|
||||||
(nt + i)->tag = htonl((ht + i)->tag);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
bug("(hton): Unknown LSA");
|
bug("(hton): Unknown LSA");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
ntohlsab(void *n, void *h, u8 type, u16 len)
|
ntohlsab(void *n, void *h, u16 type, u16 len)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -228,22 +206,41 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
|
||||||
nrt = n;
|
nrt = n;
|
||||||
hrt = h;
|
hrt = h;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
hrt->veb.byte = nrt->veb.byte;
|
hrt->veb.byte = nrt->veb.byte;
|
||||||
hrt->padding = 0;
|
hrt->padding = 0;
|
||||||
links = hrt->links = ntohs(nrt->links);
|
links = hrt->links = ntohs(nrt->links);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
hrt->options = ntohl(nrt->options);
|
||||||
|
links = (len - sizeof(struct ospf_lsa_rt)) /
|
||||||
|
sizeof(struct ospf_lsa_rt_link);
|
||||||
|
#endif
|
||||||
|
|
||||||
nrtl = (struct ospf_lsa_rt_link *) (nrt + 1);
|
nrtl = (struct ospf_lsa_rt_link *) (nrt + 1);
|
||||||
hrtl = (struct ospf_lsa_rt_link *) (hrt + 1);
|
hrtl = (struct ospf_lsa_rt_link *) (hrt + 1);
|
||||||
for (i = 0; i < links; i++)
|
for (i = 0; i < links; i++)
|
||||||
{
|
{
|
||||||
(hrtl + i)->id = ntohl((nrtl + i)->id);
|
#ifdef OSPFv2
|
||||||
(hrtl + i)->data = ntohl((nrtl + i)->data);
|
hrtl[i].id = ntohl(nrtl[i].id);
|
||||||
(hrtl + i)->type = (nrtl + i)->type;
|
hrtl[i].data = ntohl(nrtl[i].data);
|
||||||
(hrtl + i)->notos = (nrtl + i)->notos;
|
hrtl[i].type = nrtl[i].type;
|
||||||
(hrtl + i)->metric = ntohs((nrtl + i)->metric);
|
hrtl[i].notos = nrtl[i].notos;
|
||||||
|
hrtl[i].metric = ntohs(nrtl[i].metric);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
hrtl[i].type = nrtl[i].type;
|
||||||
|
hrtl[i].padding = 0;
|
||||||
|
hrtl[i].metric = ntohs(nrtl[i].metric);
|
||||||
|
hrtl[i].lif = ntohl(nrtl[i].lif);
|
||||||
|
hrtl[i].nif = ntohl(nrtl[i].nif);
|
||||||
|
hrtl[i].id = ntohl(nrtl[i].id);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LSA_T_NET:
|
case LSA_T_NET:
|
||||||
|
case LSA_T_SUM_NET:
|
||||||
|
case LSA_T_SUM_RT:
|
||||||
|
case LSA_T_EXT:
|
||||||
{
|
{
|
||||||
u32 *hid, *nid;
|
u32 *hid, *nid;
|
||||||
|
|
||||||
|
@ -252,53 +249,7 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
|
||||||
|
|
||||||
for (i = 0; i < (len / sizeof(u32)); i++)
|
for (i = 0; i < (len / sizeof(u32)); i++)
|
||||||
{
|
{
|
||||||
*(hid + i) = ntohl(*(nid + i));
|
hid[i] = ntohl(nid[i]);
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LSA_T_SUM_NET:
|
|
||||||
case LSA_T_SUM_RT:
|
|
||||||
{
|
|
||||||
struct ospf_lsa_sum *hs, *ns;
|
|
||||||
union ospf_lsa_sum_tm *hn, *nn;
|
|
||||||
|
|
||||||
hs = h;
|
|
||||||
ns = n;
|
|
||||||
|
|
||||||
hs->netmask = ns->netmask;
|
|
||||||
ipa_ntoh(hs->netmask);
|
|
||||||
|
|
||||||
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_sum)) /
|
|
||||||
sizeof(union ospf_lsa_sum_tm)); i++)
|
|
||||||
{
|
|
||||||
(hn + i)->metric = ntohl((nn + i)->metric);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LSA_T_EXT:
|
|
||||||
{
|
|
||||||
struct ospf_lsa_ext *he, *ne;
|
|
||||||
struct ospf_lsa_ext_tos *ht, *nt;
|
|
||||||
|
|
||||||
he = h;
|
|
||||||
ne = n;
|
|
||||||
|
|
||||||
he->netmask = ne->netmask;
|
|
||||||
ipa_ntoh(he->netmask);
|
|
||||||
|
|
||||||
ht = (struct ospf_lsa_ext_tos *) (he + 1);
|
|
||||||
nt = (struct ospf_lsa_ext_tos *) (ne + 1);
|
|
||||||
|
|
||||||
for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) /
|
|
||||||
sizeof(struct ospf_lsa_ext_tos)); i++)
|
|
||||||
{
|
|
||||||
(ht + i)->etm.metric = ntohl((nt + i)->etm.metric);
|
|
||||||
(ht + i)->fwaddr = (nt + i)->fwaddr;
|
|
||||||
ipa_ntoh((ht + i)->fwaddr);
|
|
||||||
(ht + i)->tag = ntohl((nt + i)->tag);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -343,7 +294,8 @@ lsasum_check(struct ospf_lsa_header *h, void *body)
|
||||||
u16 length;
|
u16 length;
|
||||||
|
|
||||||
b = body;
|
b = body;
|
||||||
sp = (char *) &h->options;
|
sp = (char *) &h;
|
||||||
|
sp += 2; /* Skip Age field */
|
||||||
length = ntohs(h->length) - 2;
|
length = ntohs(h->length) - 2;
|
||||||
h->checksum = 0;
|
h->checksum = 0;
|
||||||
|
|
||||||
|
@ -417,45 +369,40 @@ lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lsa_install_new - install new LSA into database
|
* lsa_install_new - install new LSA into database
|
||||||
|
* @po: OSPF protocol
|
||||||
* @lsa: LSA header
|
* @lsa: LSA header
|
||||||
|
* @domain: domain of LSA
|
||||||
* @body: pointer to LSA body
|
* @body: pointer to LSA body
|
||||||
* @oa: current ospf_area
|
|
||||||
*
|
*
|
||||||
* This function ensures installing new LSA into LSA database. Old instance is
|
* This function ensures installing new LSA into LSA database. Old instance is
|
||||||
* replaced. Several actions are taken to detect if new routing table
|
* replaced. Several actions are taken to detect if new routing table
|
||||||
* calculation is necessary. This is described in 13.2 of RFC 2328.
|
* calculation is necessary. This is described in 13.2 of RFC 2328.
|
||||||
*/
|
*/
|
||||||
struct top_hash_entry *
|
struct top_hash_entry *
|
||||||
lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa)
|
lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain, void *body)
|
||||||
{
|
{
|
||||||
/* LSA can be temporarrily, but body must be mb_allocated. */
|
/* LSA can be temporarrily, but body must be mb_allocated. */
|
||||||
int change = 0;
|
int change = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
struct proto_ospf *po = oa->po;
|
|
||||||
|
|
||||||
if ((en = ospf_hash_find_header(po->gr, oa->areaid, lsa)) == NULL)
|
if ((en = ospfxx_hash_find_header(po->gr, domain, lsa)) == NULL)
|
||||||
{
|
{
|
||||||
en = ospf_hash_get_header(po->gr, oa, lsa);
|
en = ospfxx_hash_get_header(po->gr, domain, lsa);
|
||||||
change = 1;
|
change = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((en->lsa.length != lsa->length) || (en->lsa.options != lsa->options)
|
if ((en->lsa.length != lsa->length)
|
||||||
|| ((en->lsa.age == LSA_MAXAGE) || (lsa->age == LSA_MAXAGE)))
|
#ifdef OSPFv2
|
||||||
|
|| (en->lsa.options != lsa->options)
|
||||||
|
#endif
|
||||||
|
|| (en->lsa.age == LSA_MAXAGE)
|
||||||
|
|| (lsa->age == LSA_MAXAGE)
|
||||||
|
|| memcmp(en->lsa_body, body, lsa->length - sizeof(struct ospf_lsa_header)))
|
||||||
change = 1;
|
change = 1;
|
||||||
else
|
|
||||||
{
|
|
||||||
u8 *k = en->lsa_body, *l = body;
|
|
||||||
for (i = 0; i < (lsa->length - sizeof(struct ospf_lsa_header)); i++)
|
|
||||||
{
|
|
||||||
if (*(k + i) != *(l + i))
|
|
||||||
{
|
|
||||||
change = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s_rem_node(SNODE en);
|
s_rem_node(SNODE en);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,15 @@
|
||||||
|
|
||||||
void htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n);
|
void htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n);
|
||||||
void ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h);
|
void ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h);
|
||||||
void htonlsab(void *h, void *n, u8 type, u16 len);
|
void htonlsab(void *h, void *n, u16 type, u16 len);
|
||||||
void ntohlsab(void *n, void *h, u8 type, u16 len);
|
void ntohlsab(void *n, void *h, u16 type, u16 len);
|
||||||
void lsasum_calculate(struct ospf_lsa_header *header, void *body);
|
void lsasum_calculate(struct ospf_lsa_header *header, void *body);
|
||||||
u16 lsasum_check(struct ospf_lsa_header *h, void *body);
|
u16 lsasum_check(struct ospf_lsa_header *h, void *body);
|
||||||
#define CMP_NEWER 1
|
#define CMP_NEWER 1
|
||||||
#define CMP_SAME 0
|
#define CMP_SAME 0
|
||||||
#define CMP_OLDER -1
|
#define CMP_OLDER -1
|
||||||
int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2);
|
int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2);
|
||||||
struct top_hash_entry *lsa_install_new(struct ospf_lsa_header *lsa,
|
struct top_hash_entry * lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain, void *body);
|
||||||
void *body, struct ospf_area *oa);
|
|
||||||
void ospf_age(struct proto_ospf *po);
|
void ospf_age(struct proto_ospf *po);
|
||||||
void flush_lsa(struct top_hash_entry *en, struct proto_ospf *po);
|
void flush_lsa(struct top_hash_entry *en, struct proto_ospf *po);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,14 @@
|
||||||
|
|
||||||
#include "ospf.h"
|
#include "ospf.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct ospf_lsreq_packet
|
||||||
|
{
|
||||||
|
struct ospf_packet ospf_packet;
|
||||||
|
struct ospf_lsreq_header lsh[];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void ospf_dump_lsreq(struct proto *p, struct ospf_lsreq_packet *pkt)
|
static void ospf_dump_lsreq(struct proto *p, struct ospf_lsreq_packet *pkt)
|
||||||
{
|
{
|
||||||
struct ospf_packet *op = &pkt->ospf_packet;
|
struct ospf_packet *op = &pkt->ospf_packet;
|
||||||
|
@ -15,15 +23,13 @@ static void ospf_dump_lsreq(struct proto *p, struct ospf_lsreq_packet *pkt)
|
||||||
ASSERT(op->type == LSREQ_P);
|
ASSERT(op->type == LSREQ_P);
|
||||||
ospf_dump_common(p, op);
|
ospf_dump_common(p, op);
|
||||||
|
|
||||||
struct ospf_lsreq_header *plsr = (void *) (pkt + 1);
|
|
||||||
int i, j;
|
int i, j;
|
||||||
|
j = (ntohs(op->length) - sizeof(struct ospf_lsreq_packet)) /
|
||||||
j = (ntohs(op->length) - sizeof(struct ospf_dbdes_packet)) /
|
|
||||||
sizeof(struct ospf_lsreq_header);
|
sizeof(struct ospf_lsreq_header);
|
||||||
|
|
||||||
for (i = 0; i < j; i++)
|
for (i = 0; i < j; i++)
|
||||||
log(L_TRACE "%s: LSR Id: %R, Rt: %R, Type: %u",
|
log(L_TRACE "%s: LSR Id: %R, Rt: %R, Type: %u", p->name,
|
||||||
p->name, htonl(plsr[i].id), htonl(plsr[i].rt), plsr[i].type);
|
htonl(pkt->lsh[i].id), htonl(pkt->lsh[i].rt), pkt->lsh[i].type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -53,14 +59,12 @@ ospf_lsreq_send(struct ospf_neighbor *n)
|
||||||
|
|
||||||
i = j = (ospf_pkt_maxsize(n->ifa) - sizeof(struct ospf_lsreq_packet)) /
|
i = j = (ospf_pkt_maxsize(n->ifa) - sizeof(struct ospf_lsreq_packet)) /
|
||||||
sizeof(struct ospf_lsreq_header);
|
sizeof(struct ospf_lsreq_header);
|
||||||
lsh = (struct ospf_lsreq_header *) (pk + 1);
|
lsh = pk->lsh;
|
||||||
|
|
||||||
for (; i > 0; i--)
|
for (; i > 0; i--)
|
||||||
{
|
{
|
||||||
en = (struct top_hash_entry *) sn;
|
en = (struct top_hash_entry *) sn;
|
||||||
lsh->padd1 = 0;
|
lsh->type = htonl(en->lsa.type);
|
||||||
lsh->padd2 = 0;
|
|
||||||
lsh->type = en->lsa.type;
|
|
||||||
lsh->rt = htonl(en->lsa.rt);
|
lsh->rt = htonl(en->lsa.rt);
|
||||||
lsh->id = htonl(en->lsa.id);
|
lsh->id = htonl(en->lsa.id);
|
||||||
DBG("Requesting %uth LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
|
DBG("Requesting %uth LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
|
||||||
|
@ -84,9 +88,10 @@ ospf_lsreq_send(struct ospf_neighbor *n)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_lsreq_receive(struct ospf_lsreq_packet *ps,
|
ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n)
|
struct ospf_neighbor *n)
|
||||||
{
|
{
|
||||||
|
struct ospf_lsreq_packet *ps = (void *) ps_i;
|
||||||
struct ospf_lsreq_header *lsh;
|
struct ospf_lsreq_header *lsh;
|
||||||
struct l_lsr_head *llsh;
|
struct l_lsr_head *llsh;
|
||||||
list uplist;
|
list uplist;
|
||||||
|
@ -104,7 +109,7 @@ ospf_lsreq_receive(struct ospf_lsreq_packet *ps,
|
||||||
|
|
||||||
ospf_neigh_sm(n, INM_HELLOREC);
|
ospf_neigh_sm(n, INM_HELLOREC);
|
||||||
|
|
||||||
lsh = (void *) (ps + 1);
|
lsh = ps->lsh;
|
||||||
init_list(&uplist);
|
init_list(&uplist);
|
||||||
upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
|
upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
|
||||||
|
|
||||||
|
@ -114,18 +119,19 @@ ospf_lsreq_receive(struct ospf_lsreq_packet *ps,
|
||||||
{
|
{
|
||||||
u32 hid = ntohl(lsh->id);
|
u32 hid = ntohl(lsh->id);
|
||||||
u32 hrt = ntohl(lsh->rt);
|
u32 hrt = ntohl(lsh->rt);
|
||||||
|
u32 htype = ntohl(lsh->type);
|
||||||
|
u32 dom = ospf_lsa_domain(htype, ifa);
|
||||||
DBG("Processing requested LSA: Type: %u, ID: %R, RT: %R\n", lsh->type, hid, hrt);
|
DBG("Processing requested LSA: Type: %u, ID: %R, RT: %R\n", lsh->type, hid, hrt);
|
||||||
llsh = sl_alloc(upslab);
|
llsh = sl_alloc(upslab);
|
||||||
llsh->lsh.id = hid;
|
llsh->lsh.id = hid;
|
||||||
llsh->lsh.rt = hrt;
|
llsh->lsh.rt = hrt;
|
||||||
llsh->lsh.type = lsh->type;
|
llsh->lsh.type = htype;
|
||||||
add_tail(&uplist, NODE llsh);
|
add_tail(&uplist, NODE llsh);
|
||||||
if (ospf_hash_find(po->gr, oa->areaid, llsh->lsh.id, llsh->lsh.rt,
|
if (ospfxx_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
|
||||||
llsh->lsh.type) == NULL)
|
|
||||||
{
|
{
|
||||||
log(L_WARN
|
log(L_WARN
|
||||||
"Received bad LS req from: %I looking: Type: %u, ID: %R, RT: %R",
|
"Received bad LS req from: %I looking: Type: %u, ID: %R, RT: %R",
|
||||||
n->ip, lsh->type, hid, hrt);
|
n->ip, htype, hid, hrt);
|
||||||
ospf_neigh_sm(n, INM_BADLSREQ);
|
ospf_neigh_sm(n, INM_BADLSREQ);
|
||||||
rfree(upslab);
|
rfree(upslab);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#define _BIRD_OSPF_LSREQ_H_
|
#define _BIRD_OSPF_LSREQ_H_
|
||||||
|
|
||||||
void ospf_lsreq_send(struct ospf_neighbor *n);
|
void ospf_lsreq_send(struct ospf_neighbor *n);
|
||||||
void ospf_lsreq_receive(struct ospf_lsreq_packet *ps,
|
void ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n);
|
struct ospf_neighbor *n);
|
||||||
|
|
||||||
#endif /* _BIRD_OSPF_LSREQ_H_ */
|
#endif /* _BIRD_OSPF_LSREQ_H_ */
|
||||||
|
|
|
@ -9,6 +9,13 @@
|
||||||
#include "ospf.h"
|
#include "ospf.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct ospf_lsupd_packet
|
||||||
|
{
|
||||||
|
struct ospf_packet ospf_packet;
|
||||||
|
u32 lsano; /* Number of LSA's */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n)
|
void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header lsa;
|
struct ospf_lsa_header lsa;
|
||||||
|
@ -51,27 +58,79 @@ static void ospf_dump_lsupd(struct proto *p, struct ospf_lsupd_packet *pkt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
|
||||||
|
int
|
||||||
|
ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
|
||||||
|
{
|
||||||
|
if (lsa->type == LSA_T_EXT)
|
||||||
|
{
|
||||||
|
if (ifa->type == OSPF_IT_VLINK)
|
||||||
|
return 0;
|
||||||
|
if (ifa->oa->stub)
|
||||||
|
return 0;
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ifa->oa->areaid == domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
|
||||||
|
int
|
||||||
|
ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
|
||||||
|
{
|
||||||
|
u32 scope = LSA_SCOPE(lsa);
|
||||||
|
|
||||||
|
/* 4.5.2 (Case 2) */
|
||||||
|
if (unknown_type(lsa) && !(lsa->type & LSA_UBIT))
|
||||||
|
scope = LSA_SCOPE_LINK;
|
||||||
|
|
||||||
|
switch (scope)
|
||||||
|
{
|
||||||
|
case LSA_SCOPE_LINK:
|
||||||
|
return ifa->iface->index == domain;
|
||||||
|
|
||||||
|
case LSA_SCOPE_AREA:
|
||||||
|
return ifa->oa->areaid == domain;
|
||||||
|
|
||||||
|
case LSA_SCOPE_AS:
|
||||||
|
if (ifa->type == OSPF_IT_VLINK)
|
||||||
|
return 0;
|
||||||
|
if (ifa->oa->stub)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log(L_ERR "LSA with invalid scope");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ospf_lsupd_flood - send received or generated lsa to the neighbors
|
* ospf_lsupd_flood - send received or generated lsa to the neighbors
|
||||||
|
* @po: OSPF protocol
|
||||||
* @n: neighbor than sent this lsa (or NULL if generated)
|
* @n: neighbor than sent this lsa (or NULL if generated)
|
||||||
* @hn: LSA header followed by lsa body in network endianity (may be NULL)
|
* @hn: LSA header followed by lsa body in network endianity (may be NULL)
|
||||||
* @hh: LSA header in host endianity (must be filled)
|
* @hh: LSA header in host endianity (must be filled)
|
||||||
* @iff: interface which received this LSA (or NULL if LSA is generated)
|
* @domain: domain of LSA (must be filled)
|
||||||
* @oa: ospf_area which is the LSA generated for
|
|
||||||
* @rtl: add this LSA into retransmission list
|
* @rtl: add this LSA into retransmission list
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* return value - was the LSA flooded back?
|
* return value - was the LSA flooded back?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
ospf_lsupd_flood(struct proto_ospf *po,
|
||||||
struct ospf_lsa_header *hh, struct ospf_iface *iff,
|
struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
||||||
struct ospf_area *oa, int rtl)
|
struct ospf_lsa_header *hh, u32 domain, int rtl)
|
||||||
{
|
{
|
||||||
struct ospf_iface *ifa;
|
struct ospf_iface *ifa;
|
||||||
struct ospf_neighbor *nn;
|
struct ospf_neighbor *nn;
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
struct proto_ospf *po = oa->po;
|
|
||||||
struct proto *p = &po->proto;
|
struct proto *p = &po->proto;
|
||||||
int ret, retval = 0;
|
int ret, retval = 0;
|
||||||
|
|
||||||
|
@ -81,18 +140,8 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
||||||
if (ifa->stub)
|
if (ifa->stub)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (hh->type == LSA_T_EXT)
|
if (! ospf_lsa_flooding_allowed(hh, domain, ifa))
|
||||||
{
|
continue;
|
||||||
if (ifa->type == OSPF_IT_VLINK)
|
|
||||||
continue;
|
|
||||||
if (ifa->oa->stub)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ifa->oa != oa)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
|
DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
|
||||||
hh->type, hh->id, hh->rt, hh->sn, hh->age);
|
hh->type, hh->id, hh->rt, hh->sn, hh->age);
|
||||||
|
@ -100,11 +149,14 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
||||||
ret = 0;
|
ret = 0;
|
||||||
WALK_LIST(nn, ifa->neigh_list)
|
WALK_LIST(nn, ifa->neigh_list)
|
||||||
{
|
{
|
||||||
|
/* 13.3 (1a) */
|
||||||
if (nn->state < NEIGHBOR_EXCHANGE)
|
if (nn->state < NEIGHBOR_EXCHANGE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* 13.3 (1b) */
|
||||||
if (nn->state < NEIGHBOR_FULL)
|
if (nn->state < NEIGHBOR_FULL)
|
||||||
{
|
{
|
||||||
if ((en = ospf_hash_find_header(nn->lsrqh, nn->ifa->oa->areaid, hh)) != NULL)
|
if ((en = ospfxx_hash_find_header(nn->lsrqh, domain, hh)) != NULL)
|
||||||
{
|
{
|
||||||
DBG("That LSA found in lsreq list for neigh %R\n", nn->rid);
|
DBG("That LSA found in lsreq list for neigh %R\n", nn->rid);
|
||||||
|
|
||||||
|
@ -140,14 +192,20 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 13.3 (1c) */
|
||||||
if (nn == n)
|
if (nn == n)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* 13.3 (1d) */
|
||||||
if (rtl)
|
if (rtl)
|
||||||
{
|
{
|
||||||
if ((en = ospf_hash_find_header(nn->lsrth, nn->ifa->oa->areaid, hh)) == NULL)
|
/* In OSPFv3, there should be check whether receiving router understand
|
||||||
|
that type of LSA (for LSA types with U-bit == 0). But as we does not support
|
||||||
|
any optional LSA types, this is not needed yet */
|
||||||
|
|
||||||
|
if ((en = ospfxx_hash_find_header(nn->lsrth, domain, hh)) == NULL)
|
||||||
{
|
{
|
||||||
en = ospf_hash_get_header(nn->lsrth, nn->ifa->oa, hh);
|
en = ospfxx_hash_get_header(nn->lsrth, domain, hh);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -159,7 +217,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((en = ospf_hash_find_header(nn->lsrth, nn->ifa->oa->areaid, hh)) != NULL)
|
if ((en = ospfxx_hash_find_header(nn->lsrth, domain, hh)) != NULL)
|
||||||
{
|
{
|
||||||
s_rem_node(SNODE en);
|
s_rem_node(SNODE en);
|
||||||
if (en->lsa_body != NULL)
|
if (en->lsa_body != NULL)
|
||||||
|
@ -175,11 +233,11 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
continue; /* pg 150 (2) */
|
continue; /* pg 150 (2) */
|
||||||
|
|
||||||
if (ifa == iff)
|
if (n && (n->ifa == ifa))
|
||||||
{
|
{
|
||||||
if ((n->rid == iff->drid) || n->rid == iff->bdrid)
|
if ((n->rid == ifa->drid) || n->rid == ifa->bdrid)
|
||||||
continue; /* pg 150 (3) */
|
continue; /* pg 150 (3) */
|
||||||
if (iff->state == OSPF_IS_BACKUP)
|
if (ifa->state == OSPF_IS_BACKUP)
|
||||||
continue; /* pg 150 (4) */
|
continue; /* pg 150 (4) */
|
||||||
retval = 1;
|
retval = 1;
|
||||||
}
|
}
|
||||||
|
@ -216,7 +274,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
||||||
|
|
||||||
htonlsah(hh, lh);
|
htonlsah(hh, lh);
|
||||||
help = (u8 *) (lh + 1);
|
help = (u8 *) (lh + 1);
|
||||||
en = ospf_hash_find_header(po->gr, oa->areaid, hh);
|
en = ospfxx_hash_find_header(po->gr, domain, hh);
|
||||||
htonlsab(en->lsa_body, help, hh->type, hh->length
|
htonlsab(en->lsa_body, help, hh->type, hh->length
|
||||||
- sizeof(struct ospf_lsa_header));
|
- sizeof(struct ospf_lsa_header));
|
||||||
}
|
}
|
||||||
|
@ -288,8 +346,9 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
|
||||||
|
|
||||||
WALK_LIST(llsh, *l)
|
WALK_LIST(llsh, *l)
|
||||||
{
|
{
|
||||||
if ((en = ospf_hash_find(po->gr, oa->areaid, llsh->lsh.id, llsh->lsh.rt,
|
u32 domain = ospf_lsa_domain(llsh->lsh.type, n->ifa);
|
||||||
llsh->lsh.type)) == NULL)
|
if ((en = ospfxx_hash_find(po->gr, domain, llsh->lsh.id,
|
||||||
|
llsh->lsh.rt, llsh->lsh.type)) == NULL)
|
||||||
continue; /* Probably flushed LSA */
|
continue; /* Probably flushed LSA */
|
||||||
/* FIXME This is a bug! I cannot flush LSA that is in lsrt */
|
/* FIXME This is a bug! I cannot flush LSA that is in lsrt */
|
||||||
|
|
||||||
|
@ -330,13 +389,12 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n)
|
struct ospf_neighbor *n)
|
||||||
{
|
{
|
||||||
u32 area;
|
struct ospf_lsupd_packet *ps = (void *) ps_i;
|
||||||
struct ospf_neighbor *ntmp;
|
struct ospf_neighbor *ntmp;
|
||||||
struct ospf_lsa_header *lsa;
|
struct ospf_lsa_header *lsa;
|
||||||
struct ospf_area *oa;
|
|
||||||
struct proto_ospf *po = ifa->oa->po;
|
struct proto_ospf *po = ifa->oa->po;
|
||||||
struct proto *p = &po->proto;
|
struct proto *p = &po->proto;
|
||||||
unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length);
|
unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length);
|
||||||
|
@ -359,8 +417,6 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
ospf_neigh_sm(n, INM_HELLOREC); /* Questionable */
|
ospf_neigh_sm(n, INM_HELLOREC); /* Questionable */
|
||||||
|
|
||||||
lsa = (struct ospf_lsa_header *) (ps + 1);
|
lsa = (struct ospf_lsa_header *) (ps + 1);
|
||||||
area = htonl(ps->ospf_packet.areaid);
|
|
||||||
oa = ospf_find_area((struct proto_ospf *) p, area);
|
|
||||||
|
|
||||||
for (i = 0; i < ntohl(ps->lsano); i++,
|
for (i = 0; i < ntohl(ps->lsano); i++,
|
||||||
lsa = (struct ospf_lsa_header *) (((u8 *) lsa) + ntohs(lsa->length)))
|
lsa = (struct ospf_lsa_header *) (((u8 *) lsa) + ntohs(lsa->length)))
|
||||||
|
@ -394,6 +450,8 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
/* pg 143 (2) */
|
/* pg 143 (2) */
|
||||||
if ((lsa->type < LSA_T_RT) || (lsa->type > LSA_T_EXT))
|
if ((lsa->type < LSA_T_RT) || (lsa->type > LSA_T_EXT))
|
||||||
{
|
{
|
||||||
|
@ -402,18 +460,34 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pg 143 (3) */
|
/* pg 143 (3) */
|
||||||
if ((lsa->type == LSA_T_EXT) && oa->stub)
|
if ((lsa->type == LSA_T_EXT) && ifa->oa->stub)
|
||||||
{
|
{
|
||||||
log(L_WARN "Received External LSA in stub area from %I", n->ip);
|
log(L_WARN "Received External LSA in stub area from %I", n->ip);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
/* 4.5.1 (2) */
|
||||||
|
if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && ifa->oa->stub)
|
||||||
|
{
|
||||||
|
log(L_WARN "Received LSA with AS scope in stub area from %I", n->ip);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4.5.1 (3) */
|
||||||
|
if ((LSA_SCOPE(lsa) == LSA_SCOPE_RES))
|
||||||
|
{
|
||||||
|
log(L_WARN "Received LSA with invalid scope from %I", n->ip);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ntohlsah(lsa, &lsatmp);
|
ntohlsah(lsa, &lsatmp);
|
||||||
|
|
||||||
DBG("Update Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
|
DBG("Update Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
|
||||||
lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
|
lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
|
||||||
|
|
||||||
lsadb = ospf_hash_find_header(po->gr, oa->areaid, &lsatmp);
|
u32 domain = ospf_lsa_domain(lsatmp.type, ifa);
|
||||||
|
lsadb = ospfxx_hash_find_header(po->gr, domain, &lsatmp);
|
||||||
|
|
||||||
#ifdef LOCAL_DEBUG
|
#ifdef LOCAL_DEBUG
|
||||||
if (lsadb)
|
if (lsadb)
|
||||||
|
@ -439,7 +513,8 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
|
|
||||||
DBG("PG143(5): Received LSA is newer\n");
|
DBG("PG143(5): Received LSA is newer\n");
|
||||||
|
|
||||||
/* pg 145 (5f) - premature aging of self originated lsa */
|
#ifdef OSPFv2
|
||||||
|
/* 13.4 - check self-originated LSAs of NET type */
|
||||||
if ((!self) && (lsatmp.type == LSA_T_NET))
|
if ((!self) && (lsatmp.type == LSA_T_NET))
|
||||||
{
|
{
|
||||||
WALK_LIST(nifa, po->iface_list)
|
WALK_LIST(nifa, po->iface_list)
|
||||||
|
@ -453,7 +528,9 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* pg 145 (5f) - premature aging of self originated lsa */
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
|
@ -473,10 +550,10 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
lsatmp.type, lsatmp.id, lsatmp.rt);
|
lsatmp.type, lsatmp.id, lsatmp.rt);
|
||||||
lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */
|
lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */
|
||||||
lsatmp.checksum = ntohs(lsa->checksum);
|
lsatmp.checksum = ntohs(lsa->checksum);
|
||||||
ospf_lsupd_flood(NULL, lsa, &lsatmp, NULL, oa, 0);
|
ospf_lsupd_flood(po, NULL, lsa, &lsatmp, domain, 0);
|
||||||
if (en = ospf_hash_find_header(po->gr, oa->areaid, &lsatmp))
|
if (en = ospfxx_hash_find_header(po->gr, domain, &lsatmp))
|
||||||
{
|
{ /* FIXME verify hacks */
|
||||||
ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
|
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, domain, 1);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -489,7 +566,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ospf_lsupd_flood(n, lsa, &lsatmp, ifa, ifa->oa, 1) == 0)
|
if (ospf_lsupd_flood(po, n, lsa, &lsatmp, domain, 1) == 0)
|
||||||
{
|
{
|
||||||
DBG("Wasn't flooded back\n"); /* ps 144(5e), pg 153 */
|
DBG("Wasn't flooded back\n"); /* ps 144(5e), pg 153 */
|
||||||
if (ifa->state == OSPF_IS_BACKUP)
|
if (ifa->state == OSPF_IS_BACKUP)
|
||||||
|
@ -509,7 +586,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
{
|
{
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
if (ntmp->state > NEIGHBOR_EXSTART)
|
if (ntmp->state > NEIGHBOR_EXSTART)
|
||||||
if ((en = ospf_hash_find_header(ntmp->lsrth, ntmp->ifa->oa->areaid, &lsadb->lsa)) != NULL)
|
if ((en = ospfxx_hash_find_header(ntmp->lsrth, domain, &lsadb->lsa)) != NULL)
|
||||||
{
|
{
|
||||||
s_rem_node(SNODE en);
|
s_rem_node(SNODE en);
|
||||||
if (en->lsa_body != NULL)
|
if (en->lsa_body != NULL)
|
||||||
|
@ -532,7 +609,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header));
|
mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header));
|
||||||
ntohlsab(lsa + 1, body, lsatmp.type,
|
ntohlsab(lsa + 1, body, lsatmp.type,
|
||||||
lsatmp.length - sizeof(struct ospf_lsa_header));
|
lsatmp.length - sizeof(struct ospf_lsa_header));
|
||||||
lsadb = lsa_install_new(&lsatmp, body, oa);
|
lsadb = lsa_install_new(po, &lsatmp, domain, body);
|
||||||
DBG("New LSA installed in DB\n");
|
DBG("New LSA installed in DB\n");
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -545,7 +622,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
{
|
{
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
DBG("PG145(7) Got the same LSA\n");
|
DBG("PG145(7) Got the same LSA\n");
|
||||||
if ((en = ospf_hash_find_header(n->lsrth, n->ifa->oa->areaid, &lsadb->lsa)) != NULL)
|
if ((en = ospfxx_hash_find_header(n->lsrth, lsadb->domain, &lsadb->lsa)) != NULL)
|
||||||
{
|
{
|
||||||
/* pg145 (7a) */
|
/* pg145 (7a) */
|
||||||
s_rem_node(SNODE en);
|
s_rem_node(SNODE en);
|
||||||
|
@ -596,10 +673,9 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_lsupd_flush_nlsa(struct top_hash_entry *en, struct ospf_area *oa)
|
ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header *lsa = &en->lsa;
|
struct ospf_lsa_header *lsa = &en->lsa;
|
||||||
struct proto_ospf *po = oa->po;
|
|
||||||
struct proto *p = &po->proto;
|
struct proto *p = &po->proto;
|
||||||
|
|
||||||
lsa->age = LSA_MAXAGE;
|
lsa->age = LSA_MAXAGE;
|
||||||
|
@ -607,5 +683,5 @@ ospf_lsupd_flush_nlsa(struct top_hash_entry *en, struct ospf_area *oa)
|
||||||
lsasum_calculate(lsa, en->lsa_body);
|
lsasum_calculate(lsa, en->lsa_body);
|
||||||
OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa!");
|
OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa!");
|
||||||
OSPF_TRACE(D_EVENTS, "Type: %d, Id: %R, Rt: %R", lsa->type, lsa->id, lsa->rt);
|
OSPF_TRACE(D_EVENTS, "Type: %d, Id: %R, Rt: %R", lsa->type, lsa->id, lsa->rt);
|
||||||
ospf_lsupd_flood(NULL, NULL, lsa, NULL, oa, 0);
|
ospf_lsupd_flood(po, NULL, NULL, lsa, en->domain, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,13 @@
|
||||||
void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n);
|
void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n);
|
||||||
void ospf_dump_common(struct proto *p, struct ospf_packet *op);
|
void ospf_dump_common(struct proto *p, struct ospf_packet *op);
|
||||||
void ospf_lsupd_send_list(struct ospf_neighbor *n, list * l);
|
void ospf_lsupd_send_list(struct ospf_neighbor *n, list * l);
|
||||||
void ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
|
void ospf_lsupd_receive(struct ospf_packet *ps_i,
|
||||||
struct ospf_iface *ifa, struct ospf_neighbor *n);
|
struct ospf_iface *ifa, struct ospf_neighbor *n);
|
||||||
int ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
int ospf_lsupd_flood(struct proto_ospf *po,
|
||||||
struct ospf_lsa_header *hh, struct ospf_iface *iff,
|
struct ospf_neighbor *n, struct ospf_lsa_header *hn,
|
||||||
struct ospf_area *oa, int rtl);
|
struct ospf_lsa_header *hh, u32 domain, int rtl);
|
||||||
void ospf_lsupd_flush_nlsa(struct top_hash_entry *en, struct ospf_area *oa);
|
void ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en);
|
||||||
|
int ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _BIRD_OSPF_LSUPD_H_ */
|
#endif /* _BIRD_OSPF_LSUPD_H_ */
|
||||||
|
|
|
@ -171,16 +171,23 @@ static struct ospf_neighbor *
|
||||||
electbdr(list nl)
|
electbdr(list nl)
|
||||||
{
|
{
|
||||||
struct ospf_neighbor *neigh, *n1, *n2;
|
struct ospf_neighbor *neigh, *n1, *n2;
|
||||||
|
u32 nid;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
nid = ipa_to_u32(neigh->ip);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
nid = neigh->rid;
|
||||||
|
#endif
|
||||||
|
|
||||||
n1 = NULL;
|
n1 = NULL;
|
||||||
n2 = NULL;
|
n2 = NULL;
|
||||||
WALK_LIST(neigh, nl) /* First try those decl. themselves */
|
WALK_LIST(neigh, nl) /* First try those decl. themselves */
|
||||||
{
|
{
|
||||||
if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
|
if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
|
||||||
if (neigh->priority > 0) /* Eligible */
|
if (neigh->priority > 0) /* Eligible */
|
||||||
if (ipa_compare(neigh->ip, neigh->dr) != 0) /* And not decl. itself DR */
|
if (neigh->dr != nid) /* And not decl. itself DR */
|
||||||
{
|
{
|
||||||
if (ipa_compare(neigh->ip, neigh->bdr) == 0) /* Declaring BDR */
|
if (neigh->bdr == nid) /* Declaring BDR */
|
||||||
{
|
{
|
||||||
if (n1 != NULL)
|
if (n1 != NULL)
|
||||||
{
|
{
|
||||||
|
@ -222,13 +229,20 @@ static struct ospf_neighbor *
|
||||||
electdr(list nl)
|
electdr(list nl)
|
||||||
{
|
{
|
||||||
struct ospf_neighbor *neigh, *n;
|
struct ospf_neighbor *neigh, *n;
|
||||||
|
u32 nid;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
nid = ipa_to_u32(neigh->ip);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
nid = neigh->rid;
|
||||||
|
#endif
|
||||||
|
|
||||||
n = NULL;
|
n = NULL;
|
||||||
WALK_LIST(neigh, nl) /* And now DR */
|
WALK_LIST(neigh, nl) /* And now DR */
|
||||||
{
|
{
|
||||||
if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
|
if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
|
||||||
if (neigh->priority > 0) /* Eligible */
|
if (neigh->priority > 0) /* Eligible */
|
||||||
if (ipa_compare(neigh->ip, neigh->dr) == 0) /* And declaring itself DR */
|
if (neigh->dr == nid) /* And declaring itself DR */
|
||||||
{
|
{
|
||||||
if (n != NULL)
|
if (n != NULL)
|
||||||
{
|
{
|
||||||
|
@ -427,7 +441,6 @@ bdr_election(struct ospf_iface *ifa)
|
||||||
{
|
{
|
||||||
struct ospf_neighbor *neigh, *ndr, *nbdr, me;
|
struct ospf_neighbor *neigh, *ndr, *nbdr, me;
|
||||||
u32 myid;
|
u32 myid;
|
||||||
ip_addr ndrip, nbdrip;
|
|
||||||
int doadj;
|
int doadj;
|
||||||
struct proto *p = &ifa->oa->po->proto;
|
struct proto *p = &ifa->oa->po->proto;
|
||||||
|
|
||||||
|
@ -438,10 +451,17 @@ bdr_election(struct ospf_iface *ifa)
|
||||||
me.state = NEIGHBOR_2WAY;
|
me.state = NEIGHBOR_2WAY;
|
||||||
me.rid = myid;
|
me.rid = myid;
|
||||||
me.priority = ifa->priority;
|
me.priority = ifa->priority;
|
||||||
me.dr = ifa->drip;
|
|
||||||
me.bdr = ifa->bdrip;
|
|
||||||
me.ip = ifa->iface->addr->ip;
|
me.ip = ifa->iface->addr->ip;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
me.dr = ipa_to_u32(ifa->drip);
|
||||||
|
me.bdr = ipa_to_u32(ifa->bdrip);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
me.dr = ifa->drid;
|
||||||
|
me.bdr = ifa->bdrid;
|
||||||
|
me.iface_id = ifa->iface->index;
|
||||||
|
#endif
|
||||||
|
|
||||||
add_tail(&ifa->neigh_list, NODE & me);
|
add_tail(&ifa->neigh_list, NODE & me);
|
||||||
|
|
||||||
nbdr = electbdr(ifa->neigh_list);
|
nbdr = electbdr(ifa->neigh_list);
|
||||||
|
@ -450,64 +470,43 @@ bdr_election(struct ospf_iface *ifa)
|
||||||
if (ndr == NULL)
|
if (ndr == NULL)
|
||||||
ndr = nbdr;
|
ndr = nbdr;
|
||||||
|
|
||||||
|
/* 9.4. (4) */
|
||||||
if (((ifa->drid == myid) && (ndr != &me))
|
if (((ifa->drid == myid) && (ndr != &me))
|
||||||
|| ((ifa->drid != myid) && (ndr == &me))
|
|| ((ifa->drid != myid) && (ndr == &me))
|
||||||
|| ((ifa->bdrid == myid) && (nbdr != &me))
|
|| ((ifa->bdrid == myid) && (nbdr != &me))
|
||||||
|| ((ifa->bdrid != myid) && (nbdr == &me)))
|
|| ((ifa->bdrid != myid) && (nbdr == &me)))
|
||||||
{
|
{
|
||||||
if (ndr == NULL)
|
#ifdef OSPFv2
|
||||||
ifa->drip = me.dr = IPA_NONE;
|
me.dr = ndr ? ipa_to_u32(ndr->ip) : IPA_NONE;
|
||||||
else
|
me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : IPA_NONE;
|
||||||
ifa->drip = me.dr = ndr->ip;
|
#else /* OSPFv3 */
|
||||||
|
me.dr = ndr ? ndr->rid : 0;
|
||||||
if (nbdr == NULL)
|
me.bdr = nbdr ? nbdr->rid : 0;
|
||||||
ifa->bdrip = me.bdr = IPA_NONE;
|
#endif
|
||||||
else
|
|
||||||
ifa->bdrip = me.bdr = nbdr->ip;
|
|
||||||
|
|
||||||
nbdr = electbdr(ifa->neigh_list);
|
nbdr = electbdr(ifa->neigh_list);
|
||||||
ndr = electdr(ifa->neigh_list);
|
ndr = electdr(ifa->neigh_list);
|
||||||
|
|
||||||
|
if (ndr == NULL)
|
||||||
|
ndr = nbdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ndr == NULL)
|
u32 odrid = ifa->drid;
|
||||||
ndrip = IPA_NONE;
|
u32 obdrid = ifa->bdrid;
|
||||||
else
|
|
||||||
ndrip = ndr->ip;
|
|
||||||
|
|
||||||
if (nbdr == NULL)
|
ifa->drid = ndr ? ndr->rid : 0;
|
||||||
nbdrip = IPA_NONE;
|
ifa->drip = ndr ? ndr->ip : IPA_NONE;
|
||||||
else
|
ifa->bdrid = nbdr ? nbdr->rid : 0;
|
||||||
nbdrip = nbdr->ip;
|
ifa->bdrip = nbdr ? nbdr->ip : IPA_NONE;
|
||||||
|
|
||||||
doadj = 0;
|
#ifdef OSPFv3
|
||||||
if ((ipa_compare(ifa->drip, ndrip) != 0)
|
ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
|
||||||
|| (ipa_compare(ifa->bdrip, nbdrip) != 0))
|
#endif
|
||||||
doadj = 1;
|
|
||||||
|
|
||||||
if (ndr == NULL)
|
|
||||||
{
|
|
||||||
ifa->drid = 0;
|
|
||||||
ifa->drip = IPA_NONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ifa->drid = ndr->rid;
|
|
||||||
ifa->drip = ndr->ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nbdr == NULL)
|
|
||||||
{
|
|
||||||
ifa->bdrid = 0;
|
|
||||||
ifa->bdrip = IPA_NONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ifa->bdrid = nbdr->rid;
|
|
||||||
ifa->bdrip = nbdr->ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
|
DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
|
||||||
|
|
||||||
|
doadj = ((ifa->drid != odrid) || (ifa->bdrid != obdrid));
|
||||||
|
|
||||||
if (myid == ifa->drid)
|
if (myid == ifa->drid)
|
||||||
ospf_iface_chstate(ifa, OSPF_IS_DR);
|
ospf_iface_chstate(ifa, OSPF_IS_DR);
|
||||||
else
|
else
|
||||||
|
|
|
@ -163,8 +163,11 @@ ospf_start(struct proto *p)
|
||||||
oa->stub = 0;
|
oa->stub = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
oa->opt.byte = 0;
|
#ifdef OSPFv2
|
||||||
if(!oa->stub) oa->opt.bit.e = 1;
|
oa->options = (oa->stub ? 0 : OPT_E);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
oa->options = OPT_R | (oa->stub ? 0 : OPT_E) | OPT_V6;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add all virtual links as interfaces */
|
/* Add all virtual links as interfaces */
|
||||||
|
@ -186,8 +189,11 @@ ospf_start(struct proto *p)
|
||||||
fib_init(&oa->net_fib, p->pool, sizeof(struct area_net), 16, ospf_area_initfib);
|
fib_init(&oa->net_fib, p->pool, sizeof(struct area_net), 16, ospf_area_initfib);
|
||||||
fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
|
fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
|
||||||
po->backbone = oa;
|
po->backbone = oa;
|
||||||
oa->opt.byte = 0;
|
#ifdef OSPFv2
|
||||||
oa->opt.bit.e = 1;
|
oa->options = OPT_E;
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
oa->options = OPT_R | OPT_E | OPT_V6;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
ospf_iface_new(po, NULL, ac, ipatt);
|
ospf_iface_new(po, NULL, ac, ipatt);
|
||||||
}
|
}
|
||||||
|
@ -448,36 +454,9 @@ ospf_rt_notify(struct proto *p, net * n, rte * new, rte * old UNUSED,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (new) /* Got some new route */
|
if (new) /* Got some new route */
|
||||||
{
|
|
||||||
originate_ext_lsa(n, new, po, attrs);
|
originate_ext_lsa(n, new, po, attrs);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
flush_ext_lsa(n, po);
|
||||||
u32 rtid = po->proto.cf->global->router_id;
|
|
||||||
struct ospf_area *oa;
|
|
||||||
struct top_hash_entry *en;
|
|
||||||
u32 pr = ipa_to_u32(n->n.prefix);
|
|
||||||
struct ospf_lsa_ext *ext;
|
|
||||||
int i;
|
|
||||||
int max = max_ext_lsa(n->n.pxlen);
|
|
||||||
|
|
||||||
/* Flush old external LSA */
|
|
||||||
for (i = 0; i < max; i++, pr++)
|
|
||||||
{
|
|
||||||
if (en = ospf_hash_find(po->gr, 0, pr, rtid, LSA_T_EXT))
|
|
||||||
{
|
|
||||||
ext = en->lsa_body;
|
|
||||||
if (ipa_compare(ext->netmask, ipa_mkmask(n->n.pxlen)) == 0)
|
|
||||||
{
|
|
||||||
WALK_LIST(oa, po->area_list)
|
|
||||||
{
|
|
||||||
ospf_lsupd_flush_nlsa(en, oa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -762,6 +741,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
|
||||||
"Interface %s is no longer stub.", ifa->iface->name);
|
"Interface %s is no longer stub.", ifa->iface->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
/* AUTHENTICATION */
|
/* AUTHENTICATION */
|
||||||
if (oldip->autype != newip->autype)
|
if (oldip->autype != newip->autype)
|
||||||
{
|
{
|
||||||
|
@ -772,6 +752,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
|
||||||
}
|
}
|
||||||
/* Add *passwords */
|
/* Add *passwords */
|
||||||
ifa->passwords = newip->passwords;
|
ifa->passwords = newip->passwords;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* priority */
|
/* priority */
|
||||||
if (oldip->priority != newip->priority)
|
if (oldip->priority != newip->priority)
|
||||||
|
@ -1076,24 +1057,24 @@ he_compare(const void *p1, const void *p2)
|
||||||
return lsa1->age - lsa2->age;
|
return lsa1->age - lsa2->age;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
static inline void
|
static inline void
|
||||||
show_lsa_router(struct top_hash_entry *he)
|
show_lsa_router(struct top_hash_entry *he)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header *lsa = &(he->lsa);
|
struct ospf_lsa_header *lsa = &(he->lsa);
|
||||||
struct ospf_lsa_rt *rt = he->lsa_body;
|
struct ospf_lsa_rt *rt = he->lsa_body;
|
||||||
struct ospf_lsa_rt_link *rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
struct ospf_lsa_rt_link *rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||||
u32 i;
|
int max = lsa_rt_count(lsa);
|
||||||
|
|
||||||
for (i = 0; i < rt->links; i++)
|
for (i = 0; i < max; i++)
|
||||||
if (rr[i].type == LSART_PTP)
|
if (rr[i].type == LSART_PTP)
|
||||||
cli_msg(-1016, "\t\trouter %R metric %u ", rr[i].id, rr[i].metric);
|
cli_msg(-1016, "\t\trouter %R metric %u ", rr[i].id, rr[i].metric);
|
||||||
|
|
||||||
for (i = 0; i < rt->links; i++)
|
for (i = 0; i < max; i++)
|
||||||
if (rr[i].type == LSART_NET)
|
if (rr[i].type == LSART_NET)
|
||||||
{
|
{
|
||||||
struct proto_ospf *po = he->oa->po;
|
struct proto_ospf *po = he->oa->po;
|
||||||
struct top_hash_entry *net_he = ospf_hash_find(po->gr, he->oa->areaid, rr[i].id, rr[i].id, LSA_T_NET);
|
struct top_hash_entry *net_he = ospfxx_hash_find(po->gr, he->oa->areaid, rr[i].id, rr[i].id, LSA_T_NET);
|
||||||
if (net_he)
|
if (net_he)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header *net_lsa = &(net_he->lsa);
|
struct ospf_lsa_header *net_lsa = &(net_he->lsa);
|
||||||
|
@ -1104,11 +1085,11 @@ show_lsa_router(struct top_hash_entry *he)
|
||||||
cli_msg(-1016, "\t\tnetwork ??? metric %u ", rr[i].metric);
|
cli_msg(-1016, "\t\tnetwork ??? metric %u ", rr[i].metric);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < rt->links; i++)
|
for (i = 0; i < max; i++)
|
||||||
if (rr[i].type == LSART_STUB)
|
if (rr[i].type == LSART_STUB)
|
||||||
cli_msg(-1016, "\t\tstubnet %I/%d metric %u ", ipa_from_u32(rr[i].id), ipa_mklen(ipa_from_u32(rr[i].data)), rr[i].metric);
|
cli_msg(-1016, "\t\tstubnet %I/%d metric %u ", ipa_from_u32(rr[i].id), ipa_mklen(ipa_from_u32(rr[i].data)), rr[i].metric);
|
||||||
|
|
||||||
for (i = 0; i < rt->links; i++)
|
for (i = 0; i < max; i++)
|
||||||
if (rr[i].type == LSART_VLNK)
|
if (rr[i].type == LSART_VLNK)
|
||||||
cli_msg(-1016, "\t\tvlink %I metric %u ", ipa_from_u32(rr[i].id), rr[i].metric);
|
cli_msg(-1016, "\t\tvlink %I metric %u ", ipa_from_u32(rr[i].id), rr[i].metric);
|
||||||
}
|
}
|
||||||
|
@ -1119,14 +1100,13 @@ show_lsa_network(struct top_hash_entry *he)
|
||||||
struct ospf_lsa_header *lsa = &(he->lsa);
|
struct ospf_lsa_header *lsa = &(he->lsa);
|
||||||
struct ospf_lsa_net *ln = he->lsa_body;
|
struct ospf_lsa_net *ln = he->lsa_body;
|
||||||
u32 *rts = (u32 *) (ln + 1);
|
u32 *rts = (u32 *) (ln + 1);
|
||||||
u32 max = (lsa->length - sizeof(struct ospf_lsa_header) - sizeof(struct ospf_lsa_net)) / sizeof(u32);
|
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
cli_msg(-1016, "");
|
cli_msg(-1016, "");
|
||||||
cli_msg(-1016, "\tnetwork %I/%d", ipa_and(ipa_from_u32(lsa->id), ln->netmask), ipa_mklen(ln->netmask));
|
cli_msg(-1016, "\tnetwork %I/%d", ipa_and(ipa_from_u32(lsa->id), ln->netmask), ipa_mklen(ln->netmask));
|
||||||
cli_msg(-1016, "\t\tdr %R", lsa->rt);
|
cli_msg(-1016, "\t\tdr %R", lsa->rt);
|
||||||
|
|
||||||
for (i = 0; i < max; i++)
|
for (i = 0; i < lsa_net_count(lsa); i++)
|
||||||
cli_msg(-1016, "\t\trouter %R", rts[i]);
|
cli_msg(-1016, "\t\trouter %R", rts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,7 +1148,7 @@ show_lsa_external(struct top_hash_entry *he)
|
||||||
et->etm.metric & METRIC_MASK, str_via, str_tag);
|
et->etm.metric & METRIC_MASK, str_via, str_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
ospf_sh_state(struct proto *p, int verbose)
|
ospf_sh_state(struct proto *p, int verbose)
|
||||||
{
|
{
|
||||||
|
@ -1177,7 +1157,7 @@ ospf_sh_state(struct proto *p, int verbose)
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
u32 last_rt = 0xFFFFFFFF;
|
u32 last_rt = 0xFFFFFFFF;
|
||||||
u32 last_area = 0xFFFFFFFF;
|
u32 last_area = 0xFFFFFFFF;
|
||||||
|
/*
|
||||||
if (p->proto_state != PS_UP)
|
if (p->proto_state != PS_UP)
|
||||||
{
|
{
|
||||||
cli_msg(-1016, "%s: is not up", p->name);
|
cli_msg(-1016, "%s: is not up", p->name);
|
||||||
|
@ -1240,7 +1220,7 @@ ospf_sh_state(struct proto *p, int verbose)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
cli_msg(0, "");
|
cli_msg(0, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,13 +49,17 @@ do { if ((p->debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
|
||||||
#define OSPF_PROTO 89
|
#define OSPF_PROTO 89
|
||||||
|
|
||||||
#ifndef IPV6
|
#ifndef IPV6
|
||||||
|
#define OSPFv2 1
|
||||||
#define OSPF_VERSION 2
|
#define OSPF_VERSION 2
|
||||||
#define AllSPFRouters ipa_from_u32(0xe0000005) /* 224.0.0.5 */
|
#define AllSPFRouters ipa_from_u32(0xe0000005) /* 224.0.0.5 */
|
||||||
#define AllDRouters ipa_from_u32(0xe0000006) /* 224.0.0.6 */
|
#define AllDRouters ipa_from_u32(0xe0000006) /* 224.0.0.6 */
|
||||||
#define DEFAULTDES ipa_from_u32(0)
|
|
||||||
#else
|
#else
|
||||||
#error OSPF for IPv6 is not implemented (mail to Feela <feela@network.cz>)
|
#define OSPFv3 1
|
||||||
|
#define OSPF_VERSION 3
|
||||||
|
#define AllSPFRouters _MI(0xFF020000, 0, 0, 5) /* FF02::5 */
|
||||||
|
#define AllDRouters _MI(0xFF020000, 0, 0, 6) /* FF02::6 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,32 +122,37 @@ struct ospf_area_config
|
||||||
list stubnet_list;
|
list stubnet_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct obits
|
|
||||||
{
|
|
||||||
#ifdef CPU_BIG_ENDIAN
|
|
||||||
u8 unused2:2;
|
|
||||||
u8 dc:1;
|
|
||||||
u8 ea:1;
|
|
||||||
u8 np:1;
|
|
||||||
u8 mc:1;
|
|
||||||
u8 e:1;
|
|
||||||
u8 unused1:1;
|
|
||||||
#else
|
|
||||||
u8 unused1:1;
|
|
||||||
u8 e:1;
|
|
||||||
u8 mc:1;
|
|
||||||
u8 np:1;
|
|
||||||
u8 ea:1;
|
|
||||||
u8 dc:1;
|
|
||||||
u8 unused2:2;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
union options
|
/* Option flags */
|
||||||
{
|
|
||||||
u8 byte;
|
#define OPT_E 0x02
|
||||||
struct obits bit;
|
#define OPT_N 0x08
|
||||||
};
|
#define OPT_DC 0x20
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
#define OPT_EA 0x10
|
||||||
|
|
||||||
|
/* VEB flags are are stored independently in 'u16 options' */
|
||||||
|
#define OPT_RT_B (0x01 << 8)
|
||||||
|
#define OPT_RT_E (0x02 << 8)
|
||||||
|
#define OPT_RT_V (0x04 << 8)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
#define OPT_V6 0x01
|
||||||
|
#define OPT_R 0x10
|
||||||
|
|
||||||
|
/* VEB flags are are stored together with options in 'u32 options' */
|
||||||
|
#define OPT_RT_B (0x01 << 24)
|
||||||
|
#define OPT_RT_E (0x02 << 24)
|
||||||
|
#define OPT_RT_V (0x04 << 24)
|
||||||
|
#define OPT_RT_NT (0x10 << 24)
|
||||||
|
|
||||||
|
#define OPT_PX_NU 0x01
|
||||||
|
#define OPT_PX_LA 0x02
|
||||||
|
#define OPT_PX_P 0x08
|
||||||
|
#define OPT_PX_DN 0x10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct ospf_iface
|
struct ospf_iface
|
||||||
|
@ -167,15 +176,26 @@ struct ospf_iface
|
||||||
u16 inftransdelay; /* The estimated number of seconds it takes to
|
u16 inftransdelay; /* The estimated number of seconds it takes to
|
||||||
transmit a Link State Update Packet over this
|
transmit a Link State Update Packet over this
|
||||||
interface. LSAs contained in the update */
|
interface. LSAs contained in the update */
|
||||||
u16 autype;
|
|
||||||
u16 helloint; /* number of seconds between hello sending */
|
u16 helloint; /* number of seconds between hello sending */
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
list *passwords;
|
list *passwords;
|
||||||
|
u16 autype;
|
||||||
u32 csn; /* Last used crypt seq number */
|
u32 csn; /* Last used crypt seq number */
|
||||||
bird_clock_t csn_use; /* Last time when packet with that CSN was sent */
|
bird_clock_t csn_use; /* Last time when packet with that CSN was sent */
|
||||||
|
#endif
|
||||||
|
|
||||||
ip_addr drip; /* Designated router */
|
ip_addr drip; /* Designated router */
|
||||||
u32 drid;
|
u32 drid;
|
||||||
ip_addr bdrip; /* Backup DR */
|
ip_addr bdrip; /* Backup DR */
|
||||||
u32 bdrid;
|
u32 bdrid;
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
u32 dr_iface_id; /* if drid is valid, this is iface_id of DR (for connecting network) */
|
||||||
|
u8 instance_id; /* Used to differentiate between more OSPF
|
||||||
|
instances on one interface */
|
||||||
|
#endif
|
||||||
|
|
||||||
u8 type; /* OSPF view of type */
|
u8 type; /* OSPF view of type */
|
||||||
#define OSPF_IT_BCAST 0
|
#define OSPF_IT_BCAST 0
|
||||||
#define OSPF_IT_NBMA 1
|
#define OSPF_IT_NBMA 1
|
||||||
|
@ -206,14 +226,19 @@ struct ospf_iface
|
||||||
#define HELLOINT_D 10
|
#define HELLOINT_D 10
|
||||||
#define POLLINT_D 20
|
#define POLLINT_D 20
|
||||||
#define DEADC_D 4
|
#define DEADC_D 4
|
||||||
#define WAIT_DMH 4 /* Value of Wait timer - not found it in RFC
|
#define WAIT_DMH 4
|
||||||
* - using 4*HELLO
|
/* Value of Wait timer - not found it in RFC * - using 4*HELLO */
|
||||||
*/
|
|
||||||
struct top_hash_entry *nlsa; /* Originated net lsa */
|
struct top_hash_entry *net_lsa; /* Originated network LSA */
|
||||||
int orignet; /* Schedule network LSA origination */
|
int orignet; /* Schedule network LSA origination */
|
||||||
int fadj; /* Number of full adjacent neigh */
|
#ifdef OSPFv3
|
||||||
|
struct top_hash_entry *link_lsa; /* Originated link LSA */
|
||||||
|
int origlink; /* Schedule link LSA origination */
|
||||||
|
struct top_hash_entry *pxn_lsa; /* Originated prefix LSA */
|
||||||
|
#endif
|
||||||
|
int fadj; /* Number of full adjacent neigh */
|
||||||
list nbma_list;
|
list nbma_list;
|
||||||
u8 priority; /* A router priority for DR election */
|
u8 priority; /* A router priority for DR election */
|
||||||
u8 ioprob;
|
u8 ioprob;
|
||||||
u32 rxbuf;
|
u32 rxbuf;
|
||||||
};
|
};
|
||||||
|
@ -232,35 +257,17 @@ union ospf_auth
|
||||||
struct ospf_md5 md5;
|
struct ospf_md5 md5;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ospf_packet
|
|
||||||
{
|
/* Packet types */
|
||||||
u8 version;
|
|
||||||
u8 type;
|
|
||||||
#define HELLO_P 1 /* Hello */
|
#define HELLO_P 1 /* Hello */
|
||||||
#define DBDES_P 2 /* Database description */
|
#define DBDES_P 2 /* Database description */
|
||||||
#define LSREQ_P 3 /* Link state request */
|
#define LSREQ_P 3 /* Link state request */
|
||||||
#define LSUPD_P 4 /* Link state update */
|
#define LSUPD_P 4 /* Link state update */
|
||||||
#define LSACK_P 5 /* Link state acknowledgement */
|
#define LSACK_P 5 /* Link state acknowledgement */
|
||||||
u16 length;
|
|
||||||
u32 routerid;
|
|
||||||
u32 areaid;
|
|
||||||
#define BACKBONE 0
|
|
||||||
u16 checksum;
|
|
||||||
u16 autype;
|
|
||||||
union ospf_auth u;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ospf_hello_packet
|
/* Area IDs */
|
||||||
{
|
#define BACKBONE 0
|
||||||
struct ospf_packet ospf_packet;
|
|
||||||
ip_addr netmask;
|
|
||||||
u16 helloint;
|
|
||||||
u8 options;
|
|
||||||
u8 priority;
|
|
||||||
u32 deadint;
|
|
||||||
ip_addr dr;
|
|
||||||
ip_addr bdr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct immsb
|
struct immsb
|
||||||
{
|
{
|
||||||
|
@ -282,34 +289,86 @@ union imms
|
||||||
u8 byte;
|
u8 byte;
|
||||||
struct immsb bit;
|
struct immsb bit;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ospf_dbdes_packet
|
|
||||||
{
|
|
||||||
struct ospf_packet ospf_packet;
|
|
||||||
u16 iface_mtu;
|
|
||||||
u8 options;
|
|
||||||
union imms imms; /* I, M, MS bits */
|
|
||||||
#define DBDES_MS 1
|
#define DBDES_MS 1
|
||||||
#define DBDES_M 2
|
#define DBDES_M 2
|
||||||
#define DBDES_I 4
|
#define DBDES_I 4
|
||||||
u32 ddseq;
|
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
|
||||||
|
struct ospf_packet
|
||||||
|
{
|
||||||
|
u8 version;
|
||||||
|
u8 type;
|
||||||
|
u16 length;
|
||||||
|
u32 routerid;
|
||||||
|
u32 areaid;
|
||||||
|
u16 checksum;
|
||||||
|
u16 autype;
|
||||||
|
union ospf_auth u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#else /* OSPFv3 packet descriptions */
|
||||||
|
|
||||||
|
struct ospf_packet
|
||||||
|
{
|
||||||
|
u8 version;
|
||||||
|
u8 type;
|
||||||
|
u16 length;
|
||||||
|
u32 routerid;
|
||||||
|
u32 areaid;
|
||||||
|
u16 checksum;
|
||||||
|
u8 instance_id;
|
||||||
|
u8 zero;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ospf_lsa_header
|
struct ospf_lsa_header
|
||||||
{
|
{
|
||||||
u16 age; /* LS Age */
|
u16 age; /* LS Age */
|
||||||
#define LSA_MAXAGE 3600 /* 1 hour */
|
#define LSA_MAXAGE 3600 /* 1 hour */
|
||||||
#define LSA_CHECKAGE 300 /* 5 minutes */
|
#define LSA_CHECKAGE 300 /* 5 minutes */
|
||||||
#define LSA_MAXAGEDIFF 900 /* 15 minutes */
|
#define LSA_MAXAGEDIFF 900 /* 15 minutes */
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
u8 options;
|
u8 options;
|
||||||
u8 type;
|
u8 type;
|
||||||
|
|
||||||
|
#define LSA_T_RT 1
|
||||||
|
#define LSA_T_NET 2
|
||||||
|
#define LSA_T_SUM_NET 3
|
||||||
|
#define LSA_T_SUM_RT 4
|
||||||
|
#define LSA_T_EXT 5
|
||||||
|
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
u16 type;
|
||||||
|
|
||||||
|
#define LSA_T_RT 0x2001
|
||||||
|
#define LSA_T_NET 0x2002
|
||||||
|
#define LSA_T_SUM_NET 0x2003
|
||||||
|
#define LSA_T_SUM_RT 0x2004
|
||||||
|
#define LSA_T_EXT 0x4005
|
||||||
|
#define LSA_T_LINK 0x0008
|
||||||
|
#define LSA_T_PREFIX 0x2009
|
||||||
|
|
||||||
|
#define LSA_UBIT 0x8000
|
||||||
|
|
||||||
|
#define LSA_SCOPE_LINK 0x0000
|
||||||
|
#define LSA_SCOPE_AREA 0x2000
|
||||||
|
#define LSA_SCOPE_AS 0x4000
|
||||||
|
#define LSA_SCOPE_RES 0x6000
|
||||||
|
#define LSA_SCOPE_MASK 0x6000
|
||||||
|
|
||||||
|
#define LSA_SCOPE(lsa) ((lsa)->type & LSA_SCOPE_MASK)
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 id;
|
u32 id;
|
||||||
#define LSA_T_RT 1
|
|
||||||
#define LSA_T_NET 2
|
|
||||||
#define LSA_T_SUM_NET 3
|
|
||||||
#define LSA_T_SUM_RT 4
|
|
||||||
#define LSA_T_EXT 5
|
|
||||||
u32 rt; /* Advertising router */
|
u32 rt; /* Advertising router */
|
||||||
s32 sn; /* LS Sequence number */
|
s32 sn; /* LS Sequence number */
|
||||||
#define LSA_INITSEQNO 0x80000001
|
#define LSA_INITSEQNO 0x80000001
|
||||||
|
@ -318,31 +377,18 @@ struct ospf_lsa_header
|
||||||
u16 length;
|
u16 length;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vebb
|
|
||||||
{
|
|
||||||
#ifdef CPU_BIG_ENDIAN
|
|
||||||
u8 padding:5;
|
|
||||||
u8 v:1;
|
|
||||||
u8 e:1;
|
|
||||||
u8 b:1;
|
|
||||||
#else
|
|
||||||
u8 b:1;
|
|
||||||
u8 e:1;
|
|
||||||
u8 v:1;
|
|
||||||
u8 padding:5;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
union veb
|
#define LSART_PTP 1
|
||||||
{
|
#define LSART_NET 2
|
||||||
u8 byte;
|
#define LSART_STUB 3
|
||||||
struct vebb bit;
|
#define LSART_VLNK 4
|
||||||
};
|
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
|
||||||
struct ospf_lsa_rt
|
struct ospf_lsa_rt
|
||||||
{
|
{
|
||||||
union veb veb;
|
u16 options; /* VEB flags only */
|
||||||
u8 padding;
|
|
||||||
u16 links;
|
u16 links;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -351,37 +397,115 @@ struct ospf_lsa_rt_link
|
||||||
u32 id;
|
u32 id;
|
||||||
u32 data;
|
u32 data;
|
||||||
u8 type;
|
u8 type;
|
||||||
#define LSART_PTP 1
|
|
||||||
#define LSART_NET 2
|
|
||||||
#define LSART_STUB 3
|
|
||||||
#define LSART_VLNK 4
|
|
||||||
u8 notos;
|
u8 notos;
|
||||||
u16 metric;
|
u16 metric;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ospf_lsa_rt_link_tos
|
|
||||||
{ /* Actually we ignore TOS. This is useless */
|
|
||||||
u8 tos;
|
|
||||||
u8 padding;
|
|
||||||
u16 metric;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ospf_lsa_net
|
struct ospf_lsa_net
|
||||||
{
|
{
|
||||||
ip_addr netmask;
|
ip_addr netmask;
|
||||||
|
u32 routers[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ospf_lsa_sum
|
struct ospf_lsa_sum
|
||||||
{
|
{
|
||||||
ip_addr netmask;
|
ip_addr netmask;
|
||||||
|
u32 metric;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ospf_lsa_ext
|
struct ospf_lsa_ext
|
||||||
{
|
{
|
||||||
ip_addr netmask;
|
ip_addr netmask;
|
||||||
|
u32 metric;
|
||||||
|
ip_addr fwaddr;
|
||||||
|
u32 tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define LSA_EXT_EBIT 0x80000000
|
||||||
|
|
||||||
|
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
|
||||||
|
struct ospf_lsa_rt
|
||||||
|
{
|
||||||
|
u32 options;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ospf_lsa_rt_link
|
||||||
|
{
|
||||||
|
u8 type;
|
||||||
|
u8 padding;
|
||||||
|
u16 metric;
|
||||||
|
u32 lif; /* Local interface ID */
|
||||||
|
u32 nif; /* Neighbor interface ID */
|
||||||
|
u32 id; /* Neighbor router ID */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ospf_lsa_net
|
||||||
|
{
|
||||||
|
u32 options;
|
||||||
|
u32 routers[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ospf_lsa_sum_net
|
||||||
|
{
|
||||||
|
u32 metric;
|
||||||
|
u32 prefix[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ospf_lsa_sum_rt
|
||||||
|
{
|
||||||
|
u32 options;
|
||||||
|
u32 metric;
|
||||||
|
u32 drid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ospf_lsa_ext
|
||||||
|
{
|
||||||
|
u32 metric;
|
||||||
|
u32 rest[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ospf_lsa_link
|
||||||
|
{
|
||||||
|
u32 options;
|
||||||
|
ip_addr lladdr;
|
||||||
|
u32 pxcount;
|
||||||
|
u32 rest[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ospf_lsa_prefix
|
||||||
|
{
|
||||||
|
u16 pxcount;
|
||||||
|
u16 ref_type;
|
||||||
|
u32 ref_id;
|
||||||
|
u32 ref_rt;
|
||||||
|
u32 rest[];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LSA_EXT_EBIT 0x4000000
|
||||||
|
#define LSA_EXT_FBIT 0x2000000
|
||||||
|
#define LSA_EXT_TBIT 0x1000000
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define METRIC_MASK 0x00FFFFFF
|
||||||
|
#define OPTIONS_MASK 0x00FFFFFF
|
||||||
|
|
||||||
|
static inline unsigned lsa_rt_count(struct ospf_lsa_header *lsa)
|
||||||
|
{
|
||||||
|
return (lsa->length - sizeof(struct ospf_lsa_header) - sizeof(struct ospf_lsa_rt))
|
||||||
|
/ sizeof(struct ospf_lsa_rt_link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned lsa_net_count(struct ospf_lsa_header *lsa)
|
||||||
|
{
|
||||||
|
return (lsa->length - sizeof(struct ospf_lsa_header) - sizeof(struct ospf_lsa_net))
|
||||||
|
/ sizeof(u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
struct ospf_lsa_ext_etos
|
struct ospf_lsa_ext_etos
|
||||||
{
|
{
|
||||||
#ifdef CPU_BIG_ENDIAN
|
#ifdef CPU_BIG_ENDIAN
|
||||||
|
@ -397,7 +521,7 @@ struct ospf_lsa_ext_etos
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define METRIC_MASK 0x00FFFFFF
|
|
||||||
struct ospf_lsa_sum_tos
|
struct ospf_lsa_sum_tos
|
||||||
{
|
{
|
||||||
#ifdef CPU_BIG_ENDIAN
|
#ifdef CPU_BIG_ENDIAN
|
||||||
|
@ -430,16 +554,11 @@ struct ospf_lsa_ext_tos
|
||||||
u32 tag;
|
u32 tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ospf_lsreq_packet
|
*/
|
||||||
{
|
|
||||||
struct ospf_packet ospf_packet;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ospf_lsreq_header
|
struct ospf_lsreq_header
|
||||||
{
|
{
|
||||||
u16 padd1;
|
u32 type;
|
||||||
u8 padd2;
|
|
||||||
u8 type;
|
|
||||||
u32 id;
|
u32 id;
|
||||||
u32 rt; /* Advertising router */
|
u32 rt; /* Advertising router */
|
||||||
};
|
};
|
||||||
|
@ -450,17 +569,6 @@ struct l_lsr_head
|
||||||
struct ospf_lsreq_header lsh;
|
struct ospf_lsreq_header lsh;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ospf_lsupd_packet
|
|
||||||
{
|
|
||||||
struct ospf_packet ospf_packet;
|
|
||||||
u32 lsano; /* Number of LSA's */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ospf_lsack_packet
|
|
||||||
{
|
|
||||||
struct ospf_packet ospf_packet;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct ospf_neighbor
|
struct ospf_neighbor
|
||||||
{
|
{
|
||||||
|
@ -484,10 +592,18 @@ struct ospf_neighbor
|
||||||
u32 rid; /* Router ID */
|
u32 rid; /* Router ID */
|
||||||
ip_addr ip; /* IP of it's interface */
|
ip_addr ip; /* IP of it's interface */
|
||||||
u8 priority; /* Priority */
|
u8 priority; /* Priority */
|
||||||
u8 options; /* Options received */
|
|
||||||
ip_addr dr; /* Neigbour's idea of DR */
|
|
||||||
ip_addr bdr; /* Neigbour's idea of BDR */
|
|
||||||
u8 adj; /* built adjacency? */
|
u8 adj; /* built adjacency? */
|
||||||
|
u32 options; /* Options received */
|
||||||
|
|
||||||
|
/* dr and bdr store IP address in OSPFv2 and router ID in OSPFv3,
|
||||||
|
we use the same type to simplify handling */
|
||||||
|
u32 dr; /* Neigbour's idea of DR */
|
||||||
|
u32 bdr; /* Neigbour's idea of BDR */
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
u32 iface_id; /* ID of Neighbour's iface connected to common network */
|
||||||
|
#endif
|
||||||
|
|
||||||
siterator dbsi; /* Database summary list iterator */
|
siterator dbsi; /* Database summary list iterator */
|
||||||
slist lsrql; /* Link state request */
|
slist lsrql; /* Link state request */
|
||||||
struct top_graph *lsrqh; /* LSA graph */
|
struct top_graph *lsrqh; /* LSA graph */
|
||||||
|
@ -535,13 +651,14 @@ struct ospf_area
|
||||||
struct ospf_area_config *ac; /* Related area config */
|
struct ospf_area_config *ac; /* Related area config */
|
||||||
int origrt; /* Rt lsa origination scheduled? */
|
int origrt; /* Rt lsa origination scheduled? */
|
||||||
struct top_hash_entry *rt; /* My own router LSA */
|
struct top_hash_entry *rt; /* My own router LSA */
|
||||||
|
struct top_hash_entry *pxr_lsa; /* Originated prefix LSA */
|
||||||
list cand; /* List of candidates for RT calc. */
|
list cand; /* List of candidates for RT calc. */
|
||||||
struct fib net_fib; /* 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? */
|
||||||
|
u32 options; /* Optional features */
|
||||||
struct proto_ospf *po;
|
struct proto_ospf *po;
|
||||||
struct fib rtr; /* Routing tables for routers */
|
struct fib rtr; /* Routing tables for routers */
|
||||||
union options opt; /* RFC2328 - A.2 */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct proto_ospf
|
struct proto_ospf
|
||||||
|
@ -577,20 +694,28 @@ struct ospf_iface_patt
|
||||||
u32 deadc;
|
u32 deadc;
|
||||||
u32 dead;
|
u32 dead;
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 autype;
|
|
||||||
u32 strictnbma;
|
u32 strictnbma;
|
||||||
u32 stub;
|
u32 stub;
|
||||||
u32 vid;
|
u32 vid;
|
||||||
#define OSPF_AUTH_NONE 0
|
|
||||||
#define OSPF_AUTH_SIMPLE 1
|
|
||||||
#define OSPF_AUTH_CRYPT 2
|
|
||||||
#define OSPF_AUTH_CRYPT_SIZE 16
|
|
||||||
u32 rxbuf;
|
u32 rxbuf;
|
||||||
#define OSPF_RXBUF_NORMAL 0
|
#define OSPF_RXBUF_NORMAL 0
|
||||||
#define OSPF_RXBUF_LARGE 1
|
#define OSPF_RXBUF_LARGE 1
|
||||||
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
|
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
|
||||||
list *passwords;
|
|
||||||
list nbma_list;
|
list nbma_list;
|
||||||
|
|
||||||
|
u32 autype; /* Not really used in OSPFv3 */
|
||||||
|
#define OSPF_AUTH_NONE 0
|
||||||
|
#define OSPF_AUTH_SIMPLE 1
|
||||||
|
#define OSPF_AUTH_CRYPT 2
|
||||||
|
#define OSPF_AUTH_CRYPT_SIZE 16
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
list *passwords;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
u8 instance_id;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
|
int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
|
||||||
|
|
|
@ -24,21 +24,37 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
|
||||||
|
|
||||||
pkt->routerid = htonl(p->cf->global->router_id);
|
pkt->routerid = htonl(p->cf->global->router_id);
|
||||||
pkt->areaid = htonl(ifa->oa->areaid);
|
pkt->areaid = htonl(ifa->oa->areaid);
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
pkt->instance_id = ifa->instance_id;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
pkt->autype = htons(ifa->autype);
|
pkt->autype = htons(ifa->autype);
|
||||||
|
#endif
|
||||||
|
|
||||||
pkt->checksum = 0;
|
pkt->checksum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
ospf_pkt_maxsize(struct ospf_iface *ifa)
|
ospf_pkt_maxsize(struct ospf_iface *ifa)
|
||||||
{
|
{
|
||||||
|
/* For virtual links use mtu=576, can be mtu < 576? */
|
||||||
unsigned mtu = (ifa->type == OSPF_IT_VLINK) ? OSPF_VLINK_MTU : ifa->iface->mtu;
|
unsigned mtu = (ifa->type == OSPF_IT_VLINK) ? OSPF_VLINK_MTU : ifa->iface->mtu;
|
||||||
/* Can be mtu < 576? */
|
unsigned add = 0;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
add = ((ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return ((mtu <= ifa->iface->mtu) ? mtu : ifa->iface->mtu) -
|
return ((mtu <= ifa->iface->mtu) ? mtu : ifa->iface->mtu) -
|
||||||
SIZE_OF_IP_HEADER - ((ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0);
|
SIZE_OF_IP_HEADER - add;
|
||||||
/* For virtual links use mtu=576 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
|
||||||
|
static void
|
||||||
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
|
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
|
||||||
{
|
{
|
||||||
struct password_item *passwd = NULL;
|
struct password_item *passwd = NULL;
|
||||||
|
@ -224,6 +240,20 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* OSPFv3 authentication not yet supported */
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
static int
|
||||||
|
ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
|
||||||
|
{ return 1; }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ospf_rx_hook
|
* ospf_rx_hook
|
||||||
* @sk: socket we received the packet. Its ignored.
|
* @sk: socket we received the packet. Its ignored.
|
||||||
|
@ -290,6 +320,8 @@ ospf_rx_hook(sock * sk, int size)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME - handle checksums in OSPFv3 */
|
||||||
|
#ifdef OSPFv2
|
||||||
if ((ps->autype != htons(OSPF_AUTH_CRYPT)) &&
|
if ((ps->autype != htons(OSPF_AUTH_CRYPT)) &&
|
||||||
(!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
|
(!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
|
||||||
ntohs(ps->length) - sizeof(struct ospf_packet), NULL)))
|
ntohs(ps->length) - sizeof(struct ospf_packet), NULL)))
|
||||||
|
@ -297,13 +329,23 @@ ospf_rx_hook(sock * sk, int size)
|
||||||
log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
|
log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ntohl(ps->areaid) != ifa->oa->areaid)
|
if (ntohl(ps->areaid) != ifa->oa->areaid)
|
||||||
{
|
{
|
||||||
log(L_ERR "%s%I - different area %ld", mesg, sk->faddr, ntohl(ps->areaid));
|
log(L_ERR "%s%I - different area (%u)", mesg, sk->faddr, ntohl(ps->areaid));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME - handling of instance id should be better */
|
||||||
|
#ifdef OSPFv3
|
||||||
|
if (ps->instance_id != ifa->instance_id)
|
||||||
|
{
|
||||||
|
log(L_ERR "%s%I - different instance (%u)", mesg, sk->faddr, ps->instance_id);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ntohl(ps->routerid) == p->cf->global->router_id)
|
if (ntohl(ps->routerid) == p->cf->global->router_id)
|
||||||
{
|
{
|
||||||
log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr);
|
log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr);
|
||||||
|
@ -352,23 +394,23 @@ ospf_rx_hook(sock * sk, int size)
|
||||||
{
|
{
|
||||||
case HELLO_P:
|
case HELLO_P:
|
||||||
DBG("%s: Hello received.\n", p->name);
|
DBG("%s: Hello received.\n", p->name);
|
||||||
ospf_hello_receive((struct ospf_hello_packet *) ps, ifa, n, sk->faddr);
|
ospf_hello_receive(ps, ifa, n, sk->faddr);
|
||||||
break;
|
break;
|
||||||
case DBDES_P:
|
case DBDES_P:
|
||||||
DBG("%s: Database description received.\n", p->name);
|
DBG("%s: Database description received.\n", p->name);
|
||||||
ospf_dbdes_receive((struct ospf_dbdes_packet *) ps, ifa, n);
|
ospf_dbdes_receive(ps, ifa, n);
|
||||||
break;
|
break;
|
||||||
case LSREQ_P:
|
case LSREQ_P:
|
||||||
DBG("%s: Link state request received.\n", p->name);
|
DBG("%s: Link state request received.\n", p->name);
|
||||||
ospf_lsreq_receive((struct ospf_lsreq_packet *) ps, ifa, n);
|
ospf_lsreq_receive(ps, ifa, n);
|
||||||
break;
|
break;
|
||||||
case LSUPD_P:
|
case LSUPD_P:
|
||||||
DBG("%s: Link state update received.\n", p->name);
|
DBG("%s: Link state update received.\n", p->name);
|
||||||
ospf_lsupd_receive((struct ospf_lsupd_packet *) ps, ifa, n);
|
ospf_lsupd_receive(ps, ifa, n);
|
||||||
break;
|
break;
|
||||||
case LSACK_P:
|
case LSACK_P:
|
||||||
DBG("%s: Link state ack received.\n", p->name);
|
DBG("%s: Link state ack received.\n", p->name);
|
||||||
ospf_lsack_receive((struct ospf_lsack_packet *) ps, ifa, n);
|
ospf_lsack_receive(ps, ifa, n);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, ps->type);
|
log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, ps->type);
|
||||||
|
@ -416,9 +458,14 @@ void
|
||||||
ospf_send_to(sock *sk, ip_addr ip, struct ospf_iface *ifa)
|
ospf_send_to(sock *sk, ip_addr ip, struct ospf_iface *ifa)
|
||||||
{
|
{
|
||||||
struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
|
struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
|
||||||
int len = ntohs(pkt->length) + ((ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0);
|
int len = ntohs(pkt->length);
|
||||||
ospf_pkt_finalize(ifa, pkt);
|
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
if (ifa->autype == OSPF_AUTH_CRYPT)
|
||||||
|
len += OSPF_AUTH_CRYPT_SIZE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ospf_pkt_finalize(ifa, pkt);
|
||||||
if (sk->tbuf != sk->tpos)
|
if (sk->tbuf != sk->tpos)
|
||||||
log(L_ERR "Aiee, old packet was overwritted in TX buffer");
|
log(L_ERR "Aiee, old packet was overwritted in TX buffer");
|
||||||
|
|
||||||
|
|
393
proto/ospf/rt.c
393
proto/ospf/rt.c
|
@ -10,18 +10,56 @@
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_cand(list * l, struct top_hash_entry *en,
|
add_cand(list * l, struct top_hash_entry *en,
|
||||||
struct top_hash_entry *par, u16 dist, struct ospf_area *oa);
|
struct top_hash_entry *par, u32 dist, struct ospf_area *oa);
|
||||||
static void
|
static void
|
||||||
calc_next_hop(struct top_hash_entry *en,
|
calc_next_hop(struct top_hash_entry *en,
|
||||||
struct top_hash_entry *par, struct ospf_area *oa);
|
struct top_hash_entry *par, struct ospf_area *oa);
|
||||||
static void ospf_ext_spf(struct proto_ospf *po);
|
static void ospf_ext_spf(struct proto_ospf *po);
|
||||||
static void rt_sync(struct proto_ospf *po);
|
static void rt_sync(struct proto_ospf *po);
|
||||||
|
|
||||||
|
/* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
|
||||||
|
as index, so we need to encapsulate RID to IP addresss */
|
||||||
|
#ifdef OSPFv2
|
||||||
|
#define ipa_from_rid(x) _MI(x)
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
#define ipa_from_rid(x) _MI(0,0,0,x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static inline u32 *
|
||||||
|
get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts)
|
||||||
|
{
|
||||||
|
u8 pxl = (*buf >> 24);
|
||||||
|
*pxopts = (*buf >> 16);
|
||||||
|
*pxlen = pxl;
|
||||||
|
buf++;
|
||||||
|
|
||||||
|
*addr = IPA_NONE;
|
||||||
|
|
||||||
|
if (pxl > 0)
|
||||||
|
_I0(*addr) = *buf++;
|
||||||
|
if (pxl > 32)
|
||||||
|
_I1(*addr) = *buf++;
|
||||||
|
if (pxl > 64)
|
||||||
|
_I2(*addr) = *buf++;
|
||||||
|
if (pxl > 96)
|
||||||
|
_I3(*addr) = *buf++;
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 *
|
||||||
|
get_ipv6_addr(u32 *buf, ip_addr *addr)
|
||||||
|
{
|
||||||
|
*addr = *(ip_addr *) buf;
|
||||||
|
return buf + 4;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_ri(orta * orta)
|
fill_ri(orta * orta)
|
||||||
{
|
{
|
||||||
orta->type = RTS_DUMMY;
|
orta->type = RTS_DUMMY;
|
||||||
orta->capa = 0;
|
orta->options = 0;
|
||||||
orta->oa = NULL;
|
orta->oa = NULL;
|
||||||
orta->metric1 = LSINFINITY;
|
orta->metric1 = LSINFINITY;
|
||||||
orta->metric2 = LSINFINITY;
|
orta->metric2 = LSINFINITY;
|
||||||
|
@ -159,6 +197,7 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
if (oa->rt->dist != LSINFINITY)
|
if (oa->rt->dist != LSINFINITY)
|
||||||
bug("Aging was not processed.");
|
bug("Aging was not processed.");
|
||||||
|
|
||||||
|
/* 16.1. (1) */
|
||||||
init_list(&oa->cand); /* Empty list of candidates */
|
init_list(&oa->cand); /* Empty list of candidates */
|
||||||
oa->trcap = 0;
|
oa->trcap = 0;
|
||||||
|
|
||||||
|
@ -183,15 +222,15 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
switch (act->lsa.type)
|
switch (act->lsa.type)
|
||||||
{
|
{
|
||||||
case LSA_T_RT:
|
case LSA_T_RT:
|
||||||
|
/* FIXME - in OSPFv3 we should process all RT LSAs from that router */
|
||||||
rt = (struct ospf_lsa_rt *) act->lsa_body;
|
rt = (struct ospf_lsa_rt *) act->lsa_body;
|
||||||
if (rt->veb.bit.v)
|
if (rt->options & OPT_RT_V)
|
||||||
oa->trcap = 1;
|
oa->trcap = 1;
|
||||||
if (rt->veb.bit.b || rt->veb.bit.e)
|
/* FIXME - in OSPFv3, should we add all routers, or just ABRs an ASBRs? */
|
||||||
|
if ((rt->options & OPT_RT_V) || (rt->options & OPT_RT_E))
|
||||||
{
|
{
|
||||||
nf.type = RTS_OSPF;
|
nf.type = RTS_OSPF;
|
||||||
nf.capa = 0;
|
nf.options = rt->options;
|
||||||
if (rt->veb.bit.b) nf.capa |= ORTA_ABR;
|
|
||||||
if (rt->veb.bit.e) nf.capa |= ORTA_ASBR;
|
|
||||||
nf.metric1 = act->dist;
|
nf.metric1 = act->dist;
|
||||||
nf.metric2 = LSINFINITY;
|
nf.metric2 = LSINFINITY;
|
||||||
nf.tag = 0;
|
nf.tag = 0;
|
||||||
|
@ -199,26 +238,27 @@ 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, NULL);
|
ri_install(po, ipa_from_rid(act->lsa.rt), 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);
|
||||||
for (i = 0; i < rt->links; i++)
|
for (i = 0; i < lsa_rt_count(&act->lsa); i++)
|
||||||
{
|
{
|
||||||
tmp = NULL;
|
tmp = NULL;
|
||||||
rtl = (rr + i);
|
rtl = (rr + i);
|
||||||
DBG(" Working on link: %R (type: %u) ", rtl->id, rtl->type);
|
DBG(" Working on link: %R (type: %u) ", rtl->id, rtl->type);
|
||||||
switch (rtl->type)
|
switch (rtl->type)
|
||||||
{
|
{
|
||||||
|
#ifdef OSPFv2
|
||||||
case LSART_STUB:
|
case LSART_STUB:
|
||||||
/*
|
/*
|
||||||
* This violates rfc2328! but I hope
|
* This violates rfc2328! But it is mostly harmless.
|
||||||
* it's also correct.
|
* But it causes that the cost of the stub is ignored.
|
||||||
*/
|
*/
|
||||||
DBG("\n");
|
DBG("\n");
|
||||||
|
|
||||||
nf.type = RTS_OSPF;
|
nf.type = RTS_OSPF;
|
||||||
nf.capa = 0;
|
nf.options = 0;
|
||||||
nf.metric1 = act->dist + rtl->metric;
|
nf.metric1 = act->dist + rtl->metric;
|
||||||
nf.metric2 = LSINFINITY;
|
nf.metric2 = LSINFINITY;
|
||||||
nf.tag = 0;
|
nf.tag = 0;
|
||||||
|
@ -249,9 +289,14 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
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, NULL);
|
ipa_mklen(ipa_from_u32(rtl->data)), ORT_NET, &nf, NULL);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case LSART_NET:
|
case LSART_NET:
|
||||||
tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_NET);
|
#ifdef OSPFv2
|
||||||
|
/* In OSPFv2, rtl->id is IP addres of DR, router ID is not known */
|
||||||
|
tmp = ospfxx_hash_find(po->gr, oa->areaid, rtl->id, 0, LSA_T_NET);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
tmp = ospfxx_hash_find(po->gr, oa->areaid, rtl->nif, rtl->id, LSA_T_NET);
|
||||||
|
#endif
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
DBG("Not found!\n");
|
DBG("Not found!\n");
|
||||||
else
|
else
|
||||||
|
@ -260,7 +305,8 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
|
|
||||||
case LSART_VLNK:
|
case LSART_VLNK:
|
||||||
case LSART_PTP:
|
case LSART_PTP:
|
||||||
tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
|
/* FIXME - in OSPFv3, find any LSA ID */
|
||||||
|
tmp = ospfxx_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
|
||||||
DBG("PTP found.\n");
|
DBG("PTP found.\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -276,7 +322,7 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
case LSA_T_NET:
|
case LSA_T_NET:
|
||||||
ln = act->lsa_body;
|
ln = act->lsa_body;
|
||||||
nf.type = RTS_OSPF;
|
nf.type = RTS_OSPF;
|
||||||
nf.capa = 0;
|
nf.options = 0;
|
||||||
nf.metric1 = act->dist;
|
nf.metric1 = act->dist;
|
||||||
nf.metric2 = LSINFINITY;
|
nf.metric2 = LSINFINITY;
|
||||||
nf.tag = 0;
|
nf.tag = 0;
|
||||||
|
@ -288,11 +334,11 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
ipa_mklen(ln->netmask), ORT_NET, &nf, NULL);
|
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 < lsa_net_count(&act->lsa); i++)
|
||||||
sizeof(struct ospf_lsa_net)) / sizeof(u32); i++)
|
|
||||||
{
|
{
|
||||||
DBG(" Working on router %R ", rts[i]);
|
DBG(" Working on router %R ", rts[i]);
|
||||||
tmp = ospf_hash_find(po->gr, oa->areaid, rts[i], rts[i], LSA_T_RT);
|
/* FIXME - in OSPFv3, find any LSA ID */
|
||||||
|
tmp = ospfxx_hash_find(po->gr, oa->areaid, rts[i], rts[i], LSA_T_RT);
|
||||||
if (tmp != NULL)
|
if (tmp != NULL)
|
||||||
DBG("Found :-)\n");
|
DBG("Found :-)\n");
|
||||||
else
|
else
|
||||||
|
@ -308,7 +354,8 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
{
|
{
|
||||||
if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa))
|
if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa))
|
||||||
{
|
{
|
||||||
if ((tmp = ospf_hash_find(po->gr, oa->areaid, iface->vid, iface->vid, LSA_T_RT)) &&
|
/* FIXME in OSPFv3, different LSAID */
|
||||||
|
if ((tmp = ospfxx_hash_find(po->gr, oa->areaid, iface->vid, iface->vid, LSA_T_RT)) &&
|
||||||
(!ipa_equal(tmp->lb, IPA_NONE)))
|
(!ipa_equal(tmp->lb, IPA_NONE)))
|
||||||
{
|
{
|
||||||
if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi->iface) || (!ipa_equal(iface->vip, tmp->lb)))
|
if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi->iface) || (!ipa_equal(iface->vip, tmp->lb)))
|
||||||
|
@ -348,7 +395,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
|
||||||
case LSA_T_RT:
|
case LSA_T_RT:
|
||||||
rt = (struct ospf_lsa_rt *) fol->lsa_body;
|
rt = (struct ospf_lsa_rt *) fol->lsa_body;
|
||||||
rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||||
for (i = 0; i < rt->links; i++)
|
for (i = 0; i < lsa_rt_count(&fol->lsa); i++)
|
||||||
{
|
{
|
||||||
rtl = (rr + i);
|
rtl = (rr + i);
|
||||||
switch (rtl->type)
|
switch (rtl->type)
|
||||||
|
@ -356,7 +403,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
|
||||||
case LSART_STUB:
|
case LSART_STUB:
|
||||||
break;
|
break;
|
||||||
case LSART_NET:
|
case LSART_NET:
|
||||||
if (ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_NET) == pre)
|
if (ospfxx_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_NET) == pre)
|
||||||
{
|
{
|
||||||
fol->lb = ipa_from_u32(rtl->data);
|
fol->lb = ipa_from_u32(rtl->data);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -364,7 +411,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
|
||||||
break;
|
break;
|
||||||
case LSART_VLNK:
|
case LSART_VLNK:
|
||||||
case LSART_PTP:
|
case LSART_PTP:
|
||||||
if (ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT) == pre)
|
if (ospfxx_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT) == pre)
|
||||||
{
|
{
|
||||||
fol->lb = ipa_from_u32(rtl->data);
|
fol->lb = ipa_from_u32(rtl->data);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -379,10 +426,9 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
|
||||||
case LSA_T_NET:
|
case LSA_T_NET:
|
||||||
ln = fol->lsa_body;
|
ln = fol->lsa_body;
|
||||||
rts = (u32 *) (ln + 1);
|
rts = (u32 *) (ln + 1);
|
||||||
for (i = 0; i < (fol->lsa.length - sizeof(struct ospf_lsa_header) -
|
for (i = 0; i < lsa_net_count(&fol->lsa); i++)
|
||||||
sizeof(struct ospf_lsa_net)) / sizeof(u32); i++)
|
|
||||||
{
|
{
|
||||||
if (ospf_hash_find(po->gr, oa->areaid, *(rts + i), *(rts + i), LSA_T_RT) == pre)
|
if (ospfxx_hash_find(po->gr, oa->areaid, *(rts + i), *(rts + i), LSA_T_RT) == pre)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -400,10 +446,10 @@ ospf_rt_sum_tr(struct ospf_area *oa)
|
||||||
struct proto *p = &oa->po->proto;
|
struct proto *p = &oa->po->proto;
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
struct ospf_area *bb = po->backbone;
|
struct ospf_area *bb = po->backbone;
|
||||||
ip_addr *mask, ip, abrip;
|
ip_addr ip, abrip;
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
int mlen = -1, type = -1;
|
u32 dst_rid, metric, options;
|
||||||
union ospf_lsa_sum_tm *tm;
|
int pxlen = -1, type = -1;
|
||||||
ort *re = NULL, *abr;
|
ort *re = NULL, *abr;
|
||||||
orta nf;
|
orta nf;
|
||||||
|
|
||||||
|
@ -411,57 +457,80 @@ ospf_rt_sum_tr(struct ospf_area *oa)
|
||||||
|
|
||||||
WALK_SLIST(en, po->lsal)
|
WALK_SLIST(en, po->lsal)
|
||||||
{
|
{
|
||||||
if (en->oa != oa)
|
if ((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (en->domain != oa->areaid)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (en->lsa.age == LSA_MAXAGE)
|
if (en->lsa.age == LSA_MAXAGE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (en->dist == LSINFINITY)
|
if (en->dist == LSINFINITY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (en->lsa.rt == p->cf->global->router_id)
|
if (en->lsa.rt == p->cf->global->router_id)
|
||||||
continue;
|
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)
|
if (en->lsa.type == LSA_T_SUM_NET)
|
||||||
{
|
{
|
||||||
mlen = ipa_mklen(*mask);
|
#ifdef OSPFv2
|
||||||
ip = ipa_and(ipa_from_u32(en->lsa.id), *mask);
|
struct ospf_lsa_sum *ls = en->lsa_body;
|
||||||
|
pxlen = ipa_mklen(ls->netmask);
|
||||||
|
ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
u8 pxopts;
|
||||||
|
struct ospf_lsa_sum_net *ls = en->lsa_body;
|
||||||
|
get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts);
|
||||||
|
if (pxopts & OPT_PX_NU)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
metric = ls->metric & METRIC_MASK;
|
||||||
|
options = 0;
|
||||||
type = ORT_NET;
|
type = ORT_NET;
|
||||||
re = (ort *) fib_find(&po->rtf, &ip, 32);
|
re = (ort *) fib_find(&po->rtf, &ip, pxlen);
|
||||||
|
}
|
||||||
|
else if (en->lsa.type == LSA_T_SUM_RT)
|
||||||
|
{
|
||||||
|
#ifdef OSPFv2
|
||||||
|
struct ospf_lsa_sum *ls = en->lsa_body;
|
||||||
|
dst_rid = en->lsa.id;
|
||||||
|
options = 0;
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
struct ospf_lsa_sum_rt *ls = en->lsa_body;
|
||||||
|
dst_rid = ls->drid;
|
||||||
|
options = ls->options & OPTIONS_MASK;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ip = ipa_from_rid(dst_rid);
|
||||||
|
pxlen = 32;
|
||||||
|
metric = ls->metric & METRIC_MASK;
|
||||||
|
options |= ORTA_ASBR;
|
||||||
|
type = ORT_ROUTER;
|
||||||
|
re = (ort *) fib_find(&bb->rtr, &ip, pxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) continue;
|
||||||
if (re->n.oa->areaid != 0) continue;
|
if (re->n.oa->areaid != 0) continue;
|
||||||
if ((re->n.type != RTS_OSPF) && (re->n.type != RTS_OSPF_IA)) continue;
|
if ((re->n.type != RTS_OSPF) && (re->n.type != RTS_OSPF_IA)) continue;
|
||||||
|
|
||||||
abrip = ipa_from_u32(en->lsa.rt);
|
abrip = ipa_from_rid(en->lsa.rt);
|
||||||
|
|
||||||
abr = fib_find(&oa->rtr, &abrip, 32);
|
abr = fib_find(&oa->rtr, &abrip, 32);
|
||||||
if (!abr) continue;
|
if (!abr) continue;
|
||||||
|
|
||||||
tm = (union ospf_lsa_sum_tm *)(mask + 1);
|
|
||||||
|
|
||||||
nf.type = re->n.type;
|
nf.type = re->n.type;
|
||||||
nf.capa = ORTA_ASBR;
|
nf.options = options;
|
||||||
nf.metric1 = abr->n.metric1 + (tm->metric & METRIC_MASK);
|
nf.metric1 = abr->n.metric1 + metric;
|
||||||
nf.metric2 = LSINFINITY;
|
nf.metric2 = LSINFINITY;
|
||||||
nf.tag = 0;
|
nf.tag = 0;
|
||||||
nf.oa = oa;
|
nf.oa = oa;
|
||||||
nf.ar = abr->n.ar;
|
nf.ar = abr->n.ar;
|
||||||
nf.nh = abr->n.nh;
|
nf.nh = abr->n.nh;
|
||||||
nf.ifa = abr->n.ifa;
|
nf.ifa = abr->n.ifa;
|
||||||
ri_install(po, ip, mlen, type, &nf, NULL);
|
ri_install(po, ip, pxlen, type, &nf, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,76 +541,103 @@ ospf_rt_sum(struct ospf_area *oa)
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
struct proto *p = &po->proto;
|
struct proto *p = &po->proto;
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
ip_addr *mask, ip, abrip; /* abrIP is actually ID */
|
ip_addr ip, abrip; /* abrIP is actually ID */
|
||||||
|
u32 dst_rid, metric, options;
|
||||||
struct area_net *anet;
|
struct area_net *anet;
|
||||||
orta nf;
|
orta nf;
|
||||||
ort *abr;
|
ort *abr;
|
||||||
int mlen = -1, type = -1;
|
int pxlen = -1, type = -1;
|
||||||
union ospf_lsa_sum_tm *tm;
|
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area (area %R)", oa->areaid);
|
OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area (area %R)", oa->areaid);
|
||||||
|
|
||||||
WALK_SLIST(en, po->lsal)
|
WALK_SLIST(en, po->lsal)
|
||||||
{
|
{
|
||||||
if (en->oa != oa)
|
if ((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (en->domain != oa->areaid)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Page 169 (1) */
|
/* Page 169 (1) */
|
||||||
if (en->lsa.age == LSA_MAXAGE)
|
if (en->lsa.age == LSA_MAXAGE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Page 169 (2) */
|
/* Page 169 (2) */
|
||||||
if (en->lsa.rt == p->cf->global->router_id)
|
if (en->lsa.rt == p->cf->global->router_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mask = (ip_addr *)en->lsa_body;
|
|
||||||
tm = (union ospf_lsa_sum_tm *)(mask + 1);
|
|
||||||
|
|
||||||
if ((tm->metric & METRIC_MASK) == LSINFINITY)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (en->lsa.type == LSA_T_SUM_NET)
|
if (en->lsa.type == LSA_T_SUM_NET)
|
||||||
{
|
{
|
||||||
struct ospf_area *oaa;
|
struct ospf_area *oaa;
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
mlen = ipa_mklen(*mask);
|
|
||||||
ip = ipa_and(ipa_from_u32(en->lsa.id), *mask);
|
#ifdef OSPFv2
|
||||||
|
struct ospf_lsa_sum *ls = en->lsa_body;
|
||||||
|
pxlen = ipa_mklen(ls->netmask);
|
||||||
|
ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
u8 pxopts;
|
||||||
|
struct ospf_lsa_sum_net *ls = en->lsa_body;
|
||||||
|
get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts);
|
||||||
|
if (pxopts & OPT_PX_NU)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
metric = ls->metric & METRIC_MASK;
|
||||||
|
options = 0;
|
||||||
|
type = ORT_NET;
|
||||||
|
|
||||||
/* Page 169 (3) */
|
/* Page 169 (3) */
|
||||||
WALK_LIST(oaa, po->area_list)
|
WALK_LIST(oaa, po->area_list)
|
||||||
{
|
{
|
||||||
if ((anet = fib_find(&oaa->net_fib, &ip, mlen)) && anet->active)
|
if ((anet = fib_find(&oaa->net_fib, &ip, pxlen)) && anet->active)
|
||||||
{
|
{
|
||||||
skip = 1;
|
skip = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (skip) continue;
|
if (skip) continue;
|
||||||
|
|
||||||
type = ORT_NET;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ip = ipa_from_u32(en->lsa.id);
|
#ifdef OSPFv2
|
||||||
mlen = 32;
|
struct ospf_lsa_sum *ls = en->lsa_body;
|
||||||
|
dst_rid = en->lsa.id;
|
||||||
|
options = 0;
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
struct ospf_lsa_sum_rt *ls = en->lsa_body;
|
||||||
|
dst_rid = ls->drid;
|
||||||
|
options = ls->options & OPTIONS_MASK;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ip = ipa_from_rid(dst_rid);
|
||||||
|
pxlen = 32;
|
||||||
|
metric = ls->metric & METRIC_MASK;
|
||||||
|
options |= ORTA_ASBR;
|
||||||
type = ORT_ROUTER;
|
type = ORT_ROUTER;
|
||||||
}
|
}
|
||||||
abrip = ipa_from_u32(en->lsa.rt);
|
|
||||||
|
|
||||||
|
/* Page 169 (1) */
|
||||||
|
if (metric == LSINFINITY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Page 169 (4) */
|
||||||
|
abrip = ipa_from_rid(en->lsa.rt);
|
||||||
if (!(abr = (ort *) fib_find(&oa->rtr, &abrip, 32))) continue;
|
if (!(abr = (ort *) fib_find(&oa->rtr, &abrip, 32))) continue;
|
||||||
if (abr->n.metric1 == LSINFINITY) continue;
|
if (abr->n.metric1 == LSINFINITY) continue;
|
||||||
if (!(abr->n.capa & ORTA_ABR)) continue;
|
if (!(abr->n.options & ORTA_ABR)) continue;
|
||||||
|
|
||||||
nf.type = RTS_OSPF_IA;
|
nf.type = RTS_OSPF_IA;
|
||||||
nf.capa = ORTA_ASBR;
|
nf.options = options;
|
||||||
nf.metric1 = abr->n.metric1 + (tm->metric & METRIC_MASK);
|
nf.metric1 = abr->n.metric1 + metric;
|
||||||
nf.metric2 = LSINFINITY;
|
nf.metric2 = LSINFINITY;
|
||||||
nf.tag = 0;
|
nf.tag = 0;
|
||||||
nf.oa = oa;
|
nf.oa = oa;
|
||||||
nf.ar = abr->n.ar;
|
nf.ar = abr->n.ar;
|
||||||
nf.nh = abr->n.nh;
|
nf.nh = abr->n.nh;
|
||||||
nf.ifa = abr->n.ifa;
|
nf.ifa = abr->n.ifa;
|
||||||
ri_install(po, ip, mlen, type, &nf, NULL);
|
ri_install(po, ip, pxlen, type, &nf, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,7 +663,7 @@ ospf_rt_spf(struct proto_ospf *po)
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
|
OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
|
||||||
|
|
||||||
/* Invalidate old routing table */
|
/* 16. (1) - Invalidate old routing table */
|
||||||
FIB_WALK(&po->rtf, nftmp)
|
FIB_WALK(&po->rtf, nftmp)
|
||||||
{
|
{
|
||||||
ri = (ort *) nftmp;
|
ri = (ort *) nftmp;
|
||||||
|
@ -594,9 +690,12 @@ ospf_rt_spf(struct proto_ospf *po)
|
||||||
anet->metric = 1;
|
anet->metric = 1;
|
||||||
}
|
}
|
||||||
FIB_WALK_END;
|
FIB_WALK_END;
|
||||||
|
|
||||||
|
/* 16. (2) */
|
||||||
ospf_rt_spfa(oa);
|
ospf_rt_spfa(oa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 16. (3) */
|
||||||
if ((po->areano == 1) || (!po->backbone))
|
if ((po->areano == 1) || (!po->backbone))
|
||||||
{
|
{
|
||||||
ospf_rt_sum(HEAD(po->area_list));
|
ospf_rt_sum(HEAD(po->area_list));
|
||||||
|
@ -606,6 +705,7 @@ ospf_rt_spf(struct proto_ospf *po)
|
||||||
ospf_rt_sum(po->backbone);
|
ospf_rt_sum(po->backbone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 16. (4) */
|
||||||
WALK_LIST(oa, po->area_list)
|
WALK_LIST(oa, po->area_list)
|
||||||
{
|
{
|
||||||
if (oa->trcap && (oa->areaid != 0))
|
if (oa->trcap && (oa->areaid != 0))
|
||||||
|
@ -615,6 +715,7 @@ ospf_rt_spf(struct proto_ospf *po)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 16. (5) */
|
||||||
ospf_ext_spf(po);
|
ospf_ext_spf(po);
|
||||||
|
|
||||||
rt_sync(po);
|
rt_sync(po);
|
||||||
|
@ -622,13 +723,12 @@ ospf_rt_spf(struct proto_ospf *po)
|
||||||
po->calcrt = 0;
|
po->calcrt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ospf_ext_spf - calculate external paths
|
* ospf_ext_spf - calculate external paths
|
||||||
* @po: protocol
|
* @po: protocol
|
||||||
*
|
*
|
||||||
* After routing table for any area is calculated, calculation of external
|
* After routing table for any area is calculated, calculation of external
|
||||||
* path is invoked. This process is described in 16.6 of RFC 2328.
|
* path is invoked. This process is described in 16.4 of RFC 2328.
|
||||||
* Inter- and Intra-area paths are always prefered over externals.
|
* Inter- and Intra-area paths are always prefered over externals.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
|
@ -639,50 +739,75 @@ ospf_ext_spf(struct proto_ospf *po)
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
struct proto *p = &po->proto;
|
struct proto *p = &po->proto;
|
||||||
struct ospf_lsa_ext *le;
|
struct ospf_lsa_ext *le;
|
||||||
struct ospf_lsa_ext_tos *lt;
|
int pxlen, ebit, rt_fwaddr_valid;
|
||||||
int mlen;
|
ip_addr ip, nh, rtid, rt_fwaddr;
|
||||||
ip_addr ip, nh, rtid;
|
|
||||||
struct ospf_iface *nhi = NULL;
|
struct ospf_iface *nhi = NULL;
|
||||||
int met1, met2;
|
u32 br_metric, rt_metric, rt_tag;
|
||||||
neighbor *nn;
|
neighbor *nn;
|
||||||
struct ospf_area *atmp;
|
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");
|
||||||
|
|
||||||
WALK_SLIST(en, po->lsal)
|
WALK_SLIST(en, po->lsal)
|
||||||
{
|
{
|
||||||
|
/* 16.4. (1) */
|
||||||
if (en->lsa.type != LSA_T_EXT)
|
if (en->lsa.type != LSA_T_EXT)
|
||||||
continue;
|
continue;
|
||||||
if (en->lsa.age == LSA_MAXAGE)
|
if (en->lsa.age == LSA_MAXAGE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* 16.4. (2) */
|
||||||
if (en->lsa.rt == p->cf->global->router_id)
|
if (en->lsa.rt == p->cf->global->router_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
le = en->lsa_body;
|
|
||||||
lt = (struct ospf_lsa_ext_tos *) (le + 1);
|
|
||||||
|
|
||||||
DBG("%s: Working on LSA. ID: %R, RT: %R, Type: %u, Mask %I\n",
|
DBG("%s: Working on LSA. ID: %R, RT: %R, 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->etm.metric & METRIC_MASK) == LSINFINITY)
|
le = en->lsa_body;
|
||||||
|
|
||||||
|
rt_metric = le->metric & METRIC_MASK;
|
||||||
|
ebit = le->metric & LSA_EXT_EBIT;
|
||||||
|
|
||||||
|
if (rt_metric == LSINFINITY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
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);
|
pxlen = ipa_mklen(le->netmask);
|
||||||
if ((mlen < 0) || (mlen > 32))
|
rt_fwaddr = le->fwaddr;
|
||||||
|
rt_fwaddr_valid = !ipa_equal(rt_fwaddr, IPA_NONE);
|
||||||
|
rt_tag = le->tag;
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
u8 pxopts;
|
||||||
|
u32 *buf = le->rest;
|
||||||
|
buf = get_ipv6_prefix(buf, &ip, &pxlen, &pxopts);
|
||||||
|
|
||||||
|
if (pxopts & OPT_PX_NU)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rt_fwaddr_valid = le->metric & LSA_EXT_FBIT;
|
||||||
|
if (rt_fwaddr_valid)
|
||||||
|
buf = get_ipv6_addr(buf, &rt_fwaddr);
|
||||||
|
else
|
||||||
|
rt_fwaddr = IPA_NONE;
|
||||||
|
|
||||||
|
if (le->metric & LSA_EXT_TBIT)
|
||||||
|
rt_tag = *buf++;
|
||||||
|
else
|
||||||
|
rt_tag = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pxlen < 0)
|
||||||
{
|
{
|
||||||
log("%s: Invalid mask in LSA. ID: %R, RT: %R, Type: %u, Mask %I",
|
log("%s: Invalid mask in LSA. ID: %R, RT: %R, Type: %u",
|
||||||
p->name, en->lsa.id, en->lsa.rt, en->lsa.type, le->netmask);
|
p->name, en->lsa.id, en->lsa.rt, en->lsa.type);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nhi = NULL;
|
nhi = NULL;
|
||||||
nh = IPA_NONE;
|
nh = IPA_NONE;
|
||||||
|
|
||||||
met1 = LSINFINITY;
|
/* 16.4. (3) */
|
||||||
met2 = LSINFINITY;
|
rtid = ipa_from_rid(en->lsa.rt);
|
||||||
|
|
||||||
rtid = ipa_from_u32(en->lsa.rt);
|
|
||||||
|
|
||||||
nf1 = NULL;
|
nf1 = NULL;
|
||||||
WALK_LIST(atmp, po->area_list)
|
WALK_LIST(atmp, po->area_list)
|
||||||
{
|
{
|
||||||
|
@ -698,50 +823,30 @@ ospf_ext_spf(struct proto_ospf *po)
|
||||||
if (nf1->n.metric1 == LSINFINITY)
|
if (nf1->n.metric1 == LSINFINITY)
|
||||||
continue; /* distance is INF */
|
continue; /* distance is INF */
|
||||||
|
|
||||||
if (!(nf1->n.capa & ORTA_ASBR))
|
if (!(nf1->n.options & ORTA_ASBR))
|
||||||
continue; /* It is not ASBR */
|
continue; /* It is not ASBR */
|
||||||
|
|
||||||
if (ipa_equal(lt->fwaddr, IPA_NONE))
|
if (!rt_fwaddr_valid)
|
||||||
{
|
{
|
||||||
if (lt->etm.etos.ebit)
|
|
||||||
{ /* FW address == 0 */
|
|
||||||
met1 = nf1->n.metric1;
|
|
||||||
met2 = (lt->etm.metric & METRIC_MASK);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
met1 = nf1->n.metric1 + (lt->etm.metric & METRIC_MASK);
|
|
||||||
met2 = LSINFINITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
nh = nf1->n.nh;
|
nh = nf1->n.nh;
|
||||||
nhi = nf1->n.ifa;
|
nhi = nf1->n.ifa;
|
||||||
nfh = nf1;
|
nfh = nf1;
|
||||||
|
br_metric = nf1->n.metric1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* FW address !=0 */
|
{
|
||||||
nf2 = fib_route(&po->rtf, lt->fwaddr, 32);
|
nf2 = fib_route(&po->rtf, rt_fwaddr, 32);
|
||||||
|
|
||||||
if (!nf2)
|
if (!nf2)
|
||||||
{
|
{
|
||||||
DBG("Cannot find network route (GW=%I)\n", lt->fwaddr);
|
DBG("Cannot find network route (GW=%I)\n", rt_fwaddr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lt->etm.etos.ebit)
|
|
||||||
{
|
|
||||||
met1 = nf2->n.metric1;
|
|
||||||
met2 = (lt->etm.metric & METRIC_MASK);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
met1 = nf2->n.metric1 + (lt->etm.metric & METRIC_MASK);
|
|
||||||
met2 = LSINFINITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((nn = neigh_find(p, <->fwaddr, 0)) != NULL)
|
if ((nn = neigh_find(p, &rt_fwaddr, 0)) != NULL)
|
||||||
{
|
{
|
||||||
nh = lt->fwaddr;
|
nh = rt_fwaddr;
|
||||||
nhi = ospf_iface_find(po, nn->iface);
|
nhi = ospf_iface_find(po, nn->iface);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -750,20 +855,31 @@ ospf_ext_spf(struct proto_ospf *po)
|
||||||
nhi = nf2->n.ifa;
|
nhi = nf2->n.ifa;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nf2->n.metric1 == LSINFINITY)
|
br_metric = nf2->n.metric1;
|
||||||
|
if (br_metric == LSINFINITY)
|
||||||
continue; /* distance is INF */
|
continue; /* distance is INF */
|
||||||
}
|
}
|
||||||
|
|
||||||
nfa.type = (met2 == LSINFINITY) ? RTS_OSPF_EXT1 : RTS_OSPF_EXT2;
|
if (ebit)
|
||||||
nfa.capa = 0;
|
{
|
||||||
nfa.metric1 = met1;
|
nfa.type = RTS_OSPF_EXT2;
|
||||||
nfa.metric2 = met2;
|
nfa.metric1 = br_metric;
|
||||||
nfa.tag = lt->tag;
|
nfa.metric2 = rt_metric;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nfa.type = RTS_OSPF_EXT1;
|
||||||
|
nfa.metric1 = br_metric + rt_metric;
|
||||||
|
nfa.metric2 = LSINFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfa.options = 0;
|
||||||
|
nfa.tag = rt_tag;
|
||||||
nfa.oa = (po->backbone == NULL) ? HEAD(po->area_list) : po->backbone;
|
nfa.oa = (po->backbone == NULL) ? HEAD(po->area_list) : po->backbone;
|
||||||
nfa.ar = nf1->n.ar;
|
nfa.ar = nf1->n.ar;
|
||||||
nfa.nh = nh;
|
nfa.nh = nh;
|
||||||
nfa.ifa = nhi;
|
nfa.ifa = nhi;
|
||||||
ri_install(po, ip, mlen, ORT_NET, &nfa, nfh);
|
ri_install(po, ip, pxlen, ORT_NET, &nfa, nfh);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -771,7 +887,7 @@ ospf_ext_spf(struct proto_ospf *po)
|
||||||
/* Add LSA into list of candidates in Dijkstra's algorithm */
|
/* Add LSA into list of candidates in Dijkstra's algorithm */
|
||||||
static void
|
static void
|
||||||
add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
|
add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
|
||||||
u16 dist, struct ospf_area *oa)
|
u32 dist, struct ospf_area *oa)
|
||||||
{
|
{
|
||||||
node *prev, *n;
|
node *prev, *n;
|
||||||
int added = 0;
|
int added = 0;
|
||||||
|
@ -782,9 +898,11 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
|
||||||
if (en->lsa.age == LSA_MAXAGE)
|
if (en->lsa.age == LSA_MAXAGE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* 16.1. (2c) */
|
||||||
if (en->color == INSPF)
|
if (en->color == INSPF)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* 16.1. (2d) */
|
||||||
if (dist >= en->dist)
|
if (dist >= en->dist)
|
||||||
return;
|
return;
|
||||||
/*
|
/*
|
||||||
|
@ -826,6 +944,7 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
|
||||||
act = SKIP_BACK(struct top_hash_entry, cn, n);
|
act = SKIP_BACK(struct top_hash_entry, cn, n);
|
||||||
if ((act->dist > dist) ||
|
if ((act->dist > dist) ||
|
||||||
((act->dist == dist) && (act->lsa.type == LSA_T_NET)))
|
((act->dist == dist) && (act->lsa.type == LSA_T_NET)))
|
||||||
|
/* FIXME - shouldn't be here LSA_T_RT ??? */
|
||||||
{
|
{
|
||||||
if (prev == NULL)
|
if (prev == NULL)
|
||||||
add_head(l, &en->cn);
|
add_head(l, &en->cn);
|
||||||
|
@ -854,6 +973,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
|
||||||
struct ospf_iface *ifa;
|
struct ospf_iface *ifa;
|
||||||
u32 myrid = p->cf->global->router_id;
|
u32 myrid = p->cf->global->router_id;
|
||||||
|
|
||||||
|
/* 16.1.1. The next hop calculation */
|
||||||
DBG(" Next hop called.\n");
|
DBG(" Next hop called.\n");
|
||||||
if (ipa_equal(par->nh, IPA_NONE))
|
if (ipa_equal(par->nh, IPA_NONE))
|
||||||
{
|
{
|
||||||
|
@ -861,6 +981,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
|
||||||
DBG(" Next hop calculating for id: %R rt: %R type: %u\n",
|
DBG(" Next hop calculating for id: %R rt: %R type: %u\n",
|
||||||
en->lsa.id, en->lsa.rt, en->lsa.type);
|
en->lsa.id, en->lsa.rt, en->lsa.type);
|
||||||
|
|
||||||
|
/* The parent vertex is the root */
|
||||||
if (par == oa->rt)
|
if (par == oa->rt)
|
||||||
{
|
{
|
||||||
if (en->lsa.type == LSA_T_NET)
|
if (en->lsa.type == LSA_T_NET)
|
||||||
|
@ -898,6 +1019,9 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The parent vertex is a network that directly connects the
|
||||||
|
calculating router to the destination router. */
|
||||||
if (par->lsa.type == LSA_T_NET)
|
if (par->lsa.type == LSA_T_NET)
|
||||||
{
|
{
|
||||||
if (en->lsa.type == LSA_T_NET)
|
if (en->lsa.type == LSA_T_NET)
|
||||||
|
@ -973,7 +1097,8 @@ again1:
|
||||||
{
|
{
|
||||||
if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh))
|
if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh))
|
||||||
{
|
{
|
||||||
if ((en = ospf_hash_find(po->gr, ifa->voa->areaid, ifa->vid, ifa->vid, LSA_T_RT))
|
/* FIXME in OSPFv3, may be different LSA ID */
|
||||||
|
if ((en = ospfxx_hash_find(po->gr, ifa->voa->areaid, ifa->vid, ifa->vid, LSA_T_RT))
|
||||||
&& (!ipa_equal(en->nh, IPA_NONE)))
|
&& (!ipa_equal(en->nh, IPA_NONE)))
|
||||||
{
|
{
|
||||||
a0.gw = en->nh;
|
a0.gw = en->nh;
|
||||||
|
@ -1054,7 +1179,7 @@ again2:
|
||||||
if (oaa->stub) fl = 1;
|
if (oaa->stub) fl = 1;
|
||||||
|
|
||||||
if (fl) flush_sum_lsa(oaa, &anet->fn, ORT_NET);
|
if (fl) flush_sum_lsa(oaa, &anet->fn, ORT_NET);
|
||||||
else originate_sum_lsa(oaa, &anet->fn, ORT_NET, anet->metric);
|
else originate_sum_lsa(oaa, &anet->fn, ORT_NET, anet->metric, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FIB_WALK_END;
|
FIB_WALK_END;
|
||||||
|
@ -1067,7 +1192,7 @@ again2:
|
||||||
|
|
||||||
fnn.prefix = IPA_NONE;
|
fnn.prefix = IPA_NONE;
|
||||||
fnn.pxlen = 0;
|
fnn.pxlen = 0;
|
||||||
if (oa->stub) originate_sum_lsa(oa, &fnn, ORT_NET, oa->stub);
|
if (oa->stub) originate_sum_lsa(oa, &fnn, ORT_NET, oa->stub, 0);
|
||||||
else flush_sum_lsa(oa, &fnn, ORT_NET);
|
else flush_sum_lsa(oa, &fnn, ORT_NET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,12 @@
|
||||||
typedef struct orta
|
typedef struct orta
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
int capa;
|
u32 options;
|
||||||
#define ORTA_ASBR 1
|
/* router-LSA style options (for ORT_ROUTER), with V,E,B bits.
|
||||||
#define ORTA_ABR 2
|
In OSPFv2, ASBRs from another areas (that we know from rt-summary-lsa),
|
||||||
|
have just ORTA_ASBR in options, their real options are unknown */
|
||||||
|
#define ORTA_ASBR OPT_RT_E
|
||||||
|
#define ORTA_ABR OPT_RT_V
|
||||||
struct ospf_area *oa;
|
struct ospf_area *oa;
|
||||||
u32 metric1;
|
u32 metric1;
|
||||||
u32 metric2;
|
u32 metric2;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,12 +13,11 @@ struct top_hash_entry
|
||||||
{ /* Index for fast mapping (type,rtrid,LSid)->vertex */
|
{ /* Index for fast mapping (type,rtrid,LSid)->vertex */
|
||||||
snode n;
|
snode n;
|
||||||
node cn; /* For adding into list of candidates
|
node cn; /* For adding into list of candidates
|
||||||
* in intra-area routing table
|
in intra-area routing table calculation */
|
||||||
* calculation
|
|
||||||
*/
|
|
||||||
struct top_hash_entry *next; /* Next in hash chain */
|
struct top_hash_entry *next; /* Next in hash chain */
|
||||||
struct ospf_lsa_header lsa;
|
struct ospf_lsa_header lsa;
|
||||||
struct ospf_area *oa;
|
u32 domain; /* Area ID for area-wide LSAs, Iface ID for link-wide LSAs */
|
||||||
|
// struct ospf_area *oa;
|
||||||
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 */
|
||||||
|
@ -48,13 +47,19 @@ struct top_graph
|
||||||
struct top_graph *ospf_top_new(pool *);
|
struct top_graph *ospf_top_new(pool *);
|
||||||
void ospf_top_free(struct top_graph *);
|
void ospf_top_free(struct top_graph *);
|
||||||
void ospf_top_dump(struct top_graph *, struct proto *);
|
void ospf_top_dump(struct top_graph *, struct proto *);
|
||||||
struct top_hash_entry *ospf_hash_find_header(struct top_graph *f, u32 areaid,
|
struct top_hash_entry *ospfxx_hash_find_header(struct top_graph *f, u32 areaid,
|
||||||
struct ospf_lsa_header *h);
|
struct ospf_lsa_header *h);
|
||||||
struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, struct ospf_area *oa,
|
struct top_hash_entry *ospfxx_hash_get_header(struct top_graph *f, u32 domain,
|
||||||
struct ospf_lsa_header *h);
|
struct ospf_lsa_header *h);
|
||||||
struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 areaid, u32 lsa, u32 rtr,
|
|
||||||
|
struct top_hash_entry *ospfxx_hash_find_smart(struct top_graph *f, struct ospf_iface *ifa,
|
||||||
|
struct ospf_lsa_header *h);
|
||||||
|
struct top_hash_entry *ospfxx_hash_get_smart(struct top_graph *f, struct ospf_iface *ifa,
|
||||||
|
struct ospf_lsa_header *h);
|
||||||
|
|
||||||
|
struct top_hash_entry *ospfxx_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
|
||||||
u32 type);
|
u32 type);
|
||||||
struct top_hash_entry *ospf_hash_get(struct top_graph *, struct ospf_area *oa, u32 lsa, u32 rtr,
|
struct top_hash_entry *ospfxx_hash_get(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
|
||||||
u32 type);
|
u32 type);
|
||||||
void ospf_hash_delete(struct top_graph *, struct top_hash_entry *);
|
void ospf_hash_delete(struct top_graph *, struct top_hash_entry *);
|
||||||
void originate_rt_lsa(struct ospf_area *oa);
|
void originate_rt_lsa(struct ospf_area *oa);
|
||||||
|
@ -64,7 +69,7 @@ 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 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 originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric, u32 options);
|
||||||
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
|
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue