#include "nest/route.h"
#include "nest/attrs.h"
+
+#define IPV6 1 // XXXX temporary
+
struct f_inst { /* Instruction */
struct f_inst *next; /* Structure is 16 bytes, anyway */
u16 code;
#include "lib/unaligned.h"
-#ifdef DEBUGGING
+
+#define IP4_MIN_MTU 576 /* RFC 2328 A.1 */
+#define IP6_MIN_MTU 1280 /* RFC 5340 A.1 */
+
+#define IP4_ALL_SPF_ROUTERS ipa_build4(224, 0, 0, 5)
+#define IP4_ALL_D_ROUTERS ipa_build4(224, 0, 0, 6)
+
+#define IP6_All_NODES ipa_build6(0xFF020000, 0, 0, 1)
+#define IP6_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 2)
+#define IP6_ALL_OSPF_ROUTERS ipa_build6(0xFF020000, 0, 0, 5)
+#define IP6_ALL_OSPF_D_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
+
+#define IP4_NONE _MI4(0)
+#define IP6_NONE _MI6(0,0,0,0)
+#define IPA_NONE IP6_NONE
+
/*
* Use the structural representation when you want to make sure
* nobody unauthorized attempts to handle ip_addr as number.
*/
+#ifdef DEBUGGING
+
typedef struct ip4_addr {
u32 addr;
} ip4_addr;
-#define IPA_NONE IP6_NONE
-#define IP4_NONE _MI4(0)
-#define IP6_NONE _MI6(0,0,0,0)
-
-
/*
* ip_classify() returns either a negative number for invalid addresses
* or scope OR'ed together with address type.
#define ipa_from_ip4(x) _MI6(0,0,0xffff,_I(x))
#define ipa_from_ip6(x) x
+#define ipa_from_u32(x) ipa_from_ip4(ip4_from_u32(x))
#define ipa_to_ip4(x) _I3(x)
#define ipa_to_ip6(x) x
+#define ipa_to_u32(x) ip4_to_u32(ipa_to_ip4(x))
#define ip4_from_u32(x) _MI4(x)
#define ip4_to_u32(x) _I(x)
break;
}
-#ifndef IPV6
- if ((i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd))
- log(L_ERR "Missing broadcast address for interface %s", i->name);
-#endif
+ if (ipa_is_ip4(a->ip) && (i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd))
+ log(L_WARN "Missing broadcast address for interface %s", i->name);
b = mb_alloc(if_pool, sizeof(struct ifa));
memcpy(b, a, sizeof(struct ifa));
}
}
+
static void
auto_router_id(void)
{
-#ifndef IPV6
+// XXXX check this
+#if 0
+
struct iface *i, *j;
j = NULL;
{
if (ipa_in_net(*a, b->prefix, b->pxlen))
{
-#ifndef IPV6
+ // XXXX what about this ?
if ((b->pxlen < (BITS_PER_IP_ADDRESS - 1)) &&
(ipa_equal(*a, b->prefix) || /* Network address */
ipa_equal(*a, b->brd))) /* Broadcast */
return -1;
-#endif
return b->scope;
}
ipa_el
| ipa_ne;
-ipa_el: IPA ';'
+ipa_el: ipa ';'
{
this_nbma = cfg_allocz(sizeof(struct nbma_node));
add_tail(&OSPF_PATT->nbma_list, NODE this_nbma);
}
;
-ipa_ne: IPA ELIGIBLE ';'
+ipa_ne: ipa ELIGIBLE ';'
{
this_nbma = cfg_allocz(sizeof(struct nbma_node));
add_tail(&OSPF_PATT->nbma_list, NODE this_nbma);
#include "ospf.h"
-#ifdef OSPFv2
-struct ospf_dbdes_packet
+struct ospf_dbdes2_packet
{
- struct ospf_packet ospf_packet;
+ struct ospf_packet hdr;
+ union ospf_auth auth;
+
u16 iface_mtu;
u8 options;
- union imms imms; /* I, M, MS bits */
+ u8 imms; /* I, M, MS bits */
u32 ddseq;
-};
-
-#define hton_opt(X) X
-#define ntoh_opt(X) X
-#endif
+ struct ospf_lsa_header lsas[];
+};
-#ifdef OSPFv3
-struct ospf_dbdes_packet
+struct ospf_dbdes3_packet
{
- struct ospf_packet ospf_packet;
+ struct ospf_packet hdr;
+
u32 options;
u16 iface_mtu;
u8 padding;
- union imms imms; /* I, M, MS bits */
+ u8 imms; /* I, M, MS bits */
u32 ddseq;
+
+ struct ospf_lsa_header lsas[];
};
+
+
+#ifdef OSPFv2
+
+#define hton_opt(X) X
+#define ntoh_opt(X) X
+#endif
+
+
+#ifdef OSPFv3
+
#define hton_opt(X) htonl(X)
#define ntoh_opt(X) ntohl(X)
#endif
+static inline unsigned
+ospf_dbdes_hdrlen(struct proto_ospf *po)
+{
+ return ospf_is_v2(po) ?
+ sizeof(struct ospf_dbdes2_packet) :
+ sizeof(struct ospf_dbdes3_packet);
+}
+
+static void
+ospf_dbdes_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
+ struct ospf_lsa_header **body, unsigned *count)
+{
+ unsigned hdrlen = ospf_dbdes_hdrlen(po);
+ *body = ((void *) pkt) + hdrlen;
+ *count = (plen - hdrlen) / sizeof(struct ospf_lsa_header);
+}
-static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
+static void ospf_dbdes_dump(struct proto_ospf *po, struct ospf_packet *pkt)
{
- struct ospf_packet *op = &pkt->ospf_packet;
-
- ASSERT(op->type == DBDES_P);
- ospf_dump_common(p, op);
- log(L_TRACE "%s: imms %s%s%s",
- p->name, pkt->imms.bit.ms ? "MS " : "",
- pkt->imms.bit.m ? "M " : "",
- pkt->imms.bit.i ? "I " : "" );
+ struct proto *p = &po->proto;
+ struct ospf_lsa_header *lsas;
+ unsigned i, lsa_count;
+
+ ASSERT(pkt->type == DBDES_P);
+ ospf_dump_common(po, pkt);
+
+ log(L_TRACE "%s: imms %s%s%s", p->name,
+ (imms & DBDES_I) ? "I " : "",
+ (imms & DBDES_M) ? "M " : "",
+ (imms & DBDES_MS) ? "MS" : "");
log(L_TRACE "%s: ddseq %u", p->name, ntohl(pkt->ddseq));
struct ospf_lsa_header *plsa = (void *) (pkt + 1);
sizeof(struct ospf_lsa_header);
for (i = 0; i < j; i++)
- ospf_dump_lsahdr(p, plsa + i);
+ ospf_dump_lsahdr(p, &lsas[i]);
}
void
ospf_dbdes_send(struct ospf_neighbor *n, int next)
{
- struct ospf_dbdes_packet *pkt;
- struct ospf_packet *op;
struct ospf_iface *ifa = n->ifa;
struct ospf_area *oa = ifa->oa;
struct proto_ospf *po = oa->po;
- struct proto *p = &po->proto;
+
+ struct ospf_dbdes_packet *pkt;
+ struct ospf_packet *op;
u16 length, i, j;
/* FIXME ??? */
switch (n->state)
{
case NEIGHBOR_EXSTART: /* Send empty packets */
- n->myimms.bit.i = 1;
+ n->myimms |= DBDES_I;
pkt = ospf_tx_buffer(ifa);
op = &pkt->ospf_packet;
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
break;
case NEIGHBOR_EXCHANGE:
- n->myimms.bit.i = 0;
+ n->myimms &= ~DBDES_I;
if (next)
{
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));
- if (n->myimms.bit.m)
+ if (n->myimms & DBDES_M)
{
sn = s_get(&(n->dbsi));
{
DBG("Number of LSA NOT sent: %d\n", i);
DBG("M bit unset.\n");
- n->myimms.bit.m = 0; /* Unset more bit */
+ n->myimms &= ~DBDES_M; /* Unset more bit */
}
s_put(&(n->dbsi), sn);
}
- pkt->imms.byte = n->myimms.byte;
+ pkt->imms = n->myimms;
length = (j - i) * sizeof(struct ospf_lsa_header) +
sizeof(struct ospf_dbdes_packet);
OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
ospf_send_to(ifa, n->ip);
- if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
+ if (n->myimms & DBDES_MS)
+ tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
- if (!n->myimms.bit.ms)
+ if (!(n->myimms & DBDES_MS))
{
- if ((n->myimms.bit.m == 0) && (n->imms.bit.m == 0) &&
+ if (!(n->myimms & DBDES_M) &&
+ !(n->imms & DBDES_M) &&
(n->state == NEIGHBOR_EXCHANGE))
{
ospf_neigh_sm(n, INM_EXDONE);
}
void
-ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
+ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
+
+ u32 rcv_ddseq, rcv_options;
+ u16 rcv_iface_mtu;
+ u8 rcv_imms;
+
unsigned int size = ntohs(ps_i->length);
if (size < sizeof(struct ospf_dbdes_packet))
return;
}
- struct ospf_dbdes_packet *ps = (void *) ps_i;
- u32 ps_ddseq = ntohl(ps->ddseq);
- u32 ps_options = ntoh_opt(ps->options);
- u16 ps_iface_mtu = ntohs(ps->iface_mtu);
+ if (ospf_is_v2(po))
+ {
+ struct ospf_dbdes2_packet *ps = (void *) pkt;
+ rcv_iface_mtu = ntohs(ps->iface_mtu);
+ rcv_options = ps->options;
+ rcv_imms = ps->imms;
+ rcv_ddseq = ntohl(ps->ddseq);
+ }
+ else /* OSPFv3 */
+ {
+ struct ospf_dbdes3_packet *ps = (void *) pkt;
+ rcv_options = ntohl(ps->options);
+ rcv_iface_mtu = ntohs(ps->iface_mtu);
+ rcv_imms = ps->imms;
+ rcv_ddseq = ntohl(ps->ddseq);
+ }
- OSPF_PACKET(ospf_dump_dbdes, ps, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
+ OSPF_PACKET(ospf_dbdes_dump, ps, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
ospf_neigh_sm(n, INM_HELLOREC);
case NEIGHBOR_ATTEMPT:
case NEIGHBOR_2WAY:
return;
- break;
+
case NEIGHBOR_INIT:
ospf_neigh_sm(n, INM_2WAYREC);
if (n->state != NEIGHBOR_EXSTART)
return;
- case NEIGHBOR_EXSTART:
- if ((ps_iface_mtu != ifa->iface->mtu) && (ifa->type != OSPF_IT_VLINK)
- && (ps_iface_mtu != 0) && (ifa->iface->mtu != 0))
+ case NEIGHBOR_EXSTART:
+ if ((rcv_iface_mtu != ifa->iface->mtu) &&
+ (rcv_iface_mtu != 0) &&
+ (ifa->iface->mtu != 0) &&
+ (ifa->type != OSPF_IT_VLINK))
log(L_WARN "OSPF: MTU mismatch with neighbour %I on interface %s (remote %d, local %d)",
- n->ip, ifa->iface->name, ps_iface_mtu, ifa->iface->mtu);
+ n->ip, ifa->iface->name, rcv_iface_mtu, ifa->iface->mtu);
- if ((ps->imms.bit.m && ps->imms.bit.ms && ps->imms.bit.i)
- && (n->rid > po->router_id) && (size == sizeof(struct ospf_dbdes_packet)))
+ if ((rcv_imms == DBDES_IMMS) &&
+ (n->rid > po->router_id) &&
+ (size == sizeof(struct ospf_dbdes_packet)))
{
/* I'm slave! */
- n->dds = ps_ddseq;
- n->ddr = ps_ddseq;
- n->options = ps_options;
- n->myimms.bit.ms = 0;
- n->imms.byte = ps->imms.byte;
- OSPF_TRACE(D_PACKETS, "I'm slave to %I.", n->ip);
+ n->dds = rcv_ddseq;
+ n->ddr = rcv_ddseq;
+ n->options = rcv_options;
+ n->myimms &= ~DBDES_MS;
+ n->imms = rcv_imms;
+ OSPF_TRACE(D_PACKETS, "I'm slave to %I", n->ip);
ospf_neigh_sm(n, INM_NEGDONE);
ospf_dbdes_send(n, 1);
break;
}
- if (((ps->imms.bit.i == 0) && (ps->imms.bit.ms == 0)) &&
- (n->rid < po->router_id) && (n->dds == ps_ddseq))
+ if (!(rcv_imms & DBDES_I) &&
+ !(rcv_imms & DBDES_MS) &&
+ (n->rid < po->router_id) &&
+ (n->dds == rcv_ddseq))
{
/* I'm master! */
- n->options = ps_options;
- n->ddr = ps_ddseq - 1; /* It will be set corectly a few lines down */
- n->imms.byte = ps->imms.byte;
- OSPF_TRACE(D_PACKETS, "I'm master to %I.", n->ip);
+ n->options = rcv_options;
+ n->ddr = rcv_ddseq - 1; /* It will be set corectly a few lines down */
+ n->imms = rcv_imms;
+ OSPF_TRACE(D_PACKETS, "I'm master to %I", n->ip);
ospf_neigh_sm(n, INM_NEGDONE);
}
else
{
- DBG("%s: Nothing happend to %I (imms=%u)\n", p->name, n->ip,
- ps->imms.byte);
+ DBG("%s: Nothing happend to %I (imms=%d)\n", p->name, n->ip, rcv_imms);
break;
}
+
case NEIGHBOR_EXCHANGE:
- if ((ps->imms.byte == n->imms.byte) && (ps_options == n->options) &&
- (ps_ddseq == n->ddr))
+ if ((rcv_imms == n->imms) &&
+ (rcv_options == n->options) &&
+ (rcv_ddseq == n->ddr))
{
/* Duplicate packet */
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
- if (n->myimms.bit.ms == 0)
+ if (!(n->myimms & DBDES_MS))
{
/* Slave should retransmit dbdes packet */
ospf_dbdes_send(n, 0);
return;
}
- n->ddr = ps_ddseq;
-
- if (ps->imms.bit.ms != n->imms.bit.ms) /* M/S bit differs */
+ if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS)) /* M/S bit differs */
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit MS)",
- n->ip);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit MS)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
- if (ps->imms.bit.i) /* I bit is set */
+ if (rcv_imms & DBDES_I) /* I bit is set */
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)",
- n->ip);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
- n->imms.byte = ps->imms.byte;
-
- if (ps_options != n->options) /* Options differs */
+ if (rcv_options != n->options) /* Options differs */
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)",
- n->ip);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
- if (n->myimms.bit.ms)
+ n->ddr = rcv_ddseq;
+ n->imms = rcv_imms;
+
+ if (n->myimms & DBDES_MS)
{
- if (ps_ddseq != n->dds) /* MASTER */
+ if (rcv_ddseq != n->dds) /* MASTER */
{
- OSPF_TRACE(D_PACKETS,
- "dbdes - sequence mismatch neighbor %I (master)", n->ip);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
n->dds++;
DBG("Incrementing dds\n");
ospf_dbdes_reqladd(ps, n);
- if ((n->myimms.bit.m == 0) && (ps->imms.bit.m == 0))
+ if (!(n->myimms & DBDES_M) &&
+ !(rcv_imms & DBDES_M))
{
ospf_neigh_sm(n, INM_EXDONE);
}
}
else
{
- if (ps_ddseq != (n->dds + 1)) /* SLAVE */
+ if (rcv_ddseq != (n->dds + 1)) /* SLAVE */
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)",
- n->ip);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
- n->ddr = ps_ddseq;
- n->dds = ps_ddseq;
+ n->ddr = rcv_ddseq;
+ n->dds = rcv_ddseq;
ospf_dbdes_reqladd(ps, n);
ospf_dbdes_send(n, 1);
}
-
break;
+
case NEIGHBOR_LOADING:
case NEIGHBOR_FULL:
- if ((ps->imms.byte == n->imms.byte) && (ps_options == n->options)
- && (ps_ddseq == n->ddr))
+ if ((rcv_imms == n->imms) &&
+ (rcv_options == n->options) &&
+ (rcv_ddseq == n->ddr))
/* Only duplicate are accepted */
{
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
- if (n->myimms.bit.ms == 0)
+ if (!(n->myimms & DBDES_MS))
{
/* Slave should retransmit dbdes packet */
ospf_dbdes_send(n, 0);
}
else
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)",
- n->ip);
- DBG("PS=%u, DDR=%u, DDS=%u\n", ps_ddseq, n->ddr, n->dds);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)", n->ip);
+ DBG("PS=%u, DDR=%u, DDS=%u\n", rcv_ddseq, n->ddr, n->dds);
ospf_neigh_sm(n, INM_SEQMIS);
}
break;
#include "ospf.h"
-#ifdef OSPFv2
-struct ospf_hello_packet
+struct ospf_hello2_packet
{
- struct ospf_packet ospf_packet;
- ip_addr netmask;
+ struct ospf_packet hdr;
+ union ospf_auth auth;
+
+ u32 netmask;
u16 helloint;
u8 options;
u8 priority;
u32 deadint;
u32 dr;
u32 bdr;
-};
-#endif
+ u32 neighbors[];
+};
-#ifdef OSPFv3
-struct ospf_hello_packet
+struct ospf_hello3_packet
{
- struct ospf_packet ospf_packet;
+ struct ospf_packet hdr;
+
u32 iface_id;
u8 priority;
u8 options3;
u16 deadint;
u32 dr;
u32 bdr;
+
+ u32 neighbors[];
};
-#endif
void
-ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
+ospf_hello_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n, ip_addr faddr)
{
struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto;
char *beg = "OSPF: Bad HELLO packet from ";
- unsigned int size, i, twoway, peers;
- u32 tmp;
- u32 *pnrid;
+ unsigned int size, i, two_way;
- size = ntohs(ps_i->length);
- if (size < sizeof(struct ospf_hello_packet))
- {
- log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
- return;
- }
+ u32 rcv_iface_id, rcv_helloint, rcv_deadint, rcv_dr, rcv_bdr;
+ u8 rcv_options, rcv_priority;
+
+ u32 *neighbors;
+ u32 neigh_count;
- struct ospf_hello_packet *ps = (void *) ps_i;
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s%s", faddr,
- (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
-
-#ifdef OSPFv2
- ip_addr mask = ps->netmask;
- ipa_ntoh(mask);
- if ((ifa->type != OSPF_IT_VLINK) &&
- (ifa->type != OSPF_IT_PTP) &&
- !ipa_equal(mask, ipa_mkmask(ifa->addr->pxlen)))
+ (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
+
+ size = ntohs(pkt->length);
+
+ if (ospf_is_v2(po))
{
- log(L_ERR "%s%I - netmask mismatch (%I)", beg, faddr, mask);
- return;
+ struct ospf_hello2_packet *ps = (void *) pkt;
+
+ if (size < sizeof(struct ospf_hello2_packet))
+ {
+ log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
+ return;
+ }
+
+ rcv_iface_id = 0;
+ rcv_helloint = ntohs(ps->helloint);
+ rcv_deadint = ntohl(ps->deadint);
+ rcv_dr = ntohl(ps->dr);
+ rcv_bdr = ntohl(ps->bdr);
+ rcv_options = ps->options;
+ rcv_priority = ps->priority;
+
+ int pxlen = u32_masklen(ntohl(ps->netmask));
+ if ((ifa->type != OSPF_IT_VLINK) &&
+ (ifa->type != OSPF_IT_PTP) &&
+ (pxlen != ifa->addr->pxlen))
+ {
+ log(L_ERR "%s%I - prefix length mismatch (%d)", beg, faddr, pxlen);
+ return;
+ }
+
+ neighbors = ps->neighbors;
+ neigh_count = (size - sizeof(struct ospf_hello2_packet)) / sizeof(u32);
+ }
+ else /* OSPFv3 */
+ {
+ struct ospf_hello3_packet *ps = (void *) pkt;
+
+ if (size < sizeof(struct ospf_hello3_packet))
+ {
+ log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
+ return;
+ }
+
+ rcv_iface_id = ntohl(ps->iface_id);
+ rcv_helloint = ntohs(ps->helloint);
+ rcv_deadint = ntohs(ps->deadint);
+ rcv_dr = ntohl(ps->dr);
+ rcv_bdr = ntohl(ps->bdr);
+ rcv_options = ps->options;
+ rcv_priority = ps->priority;
+
+ neighbors = ps->neighbors;
+ neigh_count = (size - sizeof(struct ospf_hello3_packet)) / sizeof(u32);
}
-#endif
- tmp = ntohs(ps->helloint);
- if (tmp != ifa->helloint)
+ if (rcv_helloint != ifa->helloint)
{
- log(L_ERR "%s%I - hello interval mismatch (%d)", beg, faddr, tmp);
+ log(L_ERR "%s%I - hello interval mismatch (%d)", beg, faddr, rcv_helloint);
return;
}
-#ifdef OSPFv2
- tmp = ntohl(ps->deadint);
-#else /* OSPFv3 */
- tmp = ntohs(ps->deadint);
-#endif
- if (tmp != ifa->deadint)
+ if (rcv_deadint != ifa->deadint)
{
- log(L_ERR "%s%I - dead interval mismatch (%d)", beg, faddr, tmp);
+ log(L_ERR "%s%I - dead interval mismatch (%d)", beg, faddr, rcv_deadint);
return;
}
/* Check whether bits E, N match */
- if ((ps->options ^ ifa->oa->options) & (OPT_E | OPT_N))
+ if ((rcv_options ^ ifa->oa->options) & (OPT_E | OPT_N))
{
- log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, ps->options);
+ log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, rcv_options);
return;
}
}
if (nn && (ifa->type == OSPF_IT_NBMA) &&
- (((ps->priority == 0) && nn->eligible) ||
- ((ps->priority > 0) && !nn->eligible)))
+ (((rcv_priority == 0) && nn->eligible) ||
+ ((rcv_priority > 0) && !nn->eligible)))
{
log(L_ERR "Eligibility mismatch for neighbor: %I on %s",
faddr, ifa->iface->name);
n = ospf_neighbor_new(ifa);
- n->rid = ntohl(((struct ospf_packet *) ps)->routerid);
+ n->rid = ntohl(pkt->routerid);
n->ip = faddr;
- n->dr = ntohl(ps->dr);
- n->bdr = ntohl(ps->bdr);
- n->priority = ps->priority;
-#ifdef OSPFv3
- n->iface_id = ntohl(ps->iface_id);
-#endif
+ n->dr = rcv_dr;
+ n->bdr = rcv_bdr;
+ n->priority = rcv_priority;
+ n->iface_id = rcv_iface_id;
}
ospf_neigh_sm(n, INM_HELLOREC);
- pnrid = (u32 *) ((struct ospf_hello_packet *) (ps + 1));
-
- peers = (size - sizeof(struct ospf_hello_packet))/ sizeof(u32);
-
- twoway = 0;
- for (i = 0; i < peers; i++)
+ two_way = 0;
+ for (i = 0; i < neigh_count; i++)
{
- if (ntohl(pnrid[i]) == po->router_id)
+ if (ntohl(neighbors[i]) == po->router_id)
{
DBG("%s: Twoway received from %I\n", p->name, faddr);
ospf_neigh_sm(n, INM_2WAYREC);
- twoway = 1;
+ two_way = 1;
break;
}
}
-
- if (!twoway)
+ if (!two_way)
ospf_neigh_sm(n, INM_1WAYREC);
- u32 olddr = n->dr;
- u32 oldbdr = n->bdr;
- u32 oldpriority = n->priority;
-#ifdef OSPFv3
- u32 oldiface_id = n->iface_id;
-#endif
-
- n->dr = ntohl(ps->dr);
- n->bdr = ntohl(ps->bdr);
- n->priority = ps->priority;
-#ifdef OSPFv3
- n->iface_id = ntohl(ps->iface_id);
-#endif
+ u32 old_dr = n->dr;
+ u32 old_bdr = n->bdr;
+ u32 old_priority = n->priority;
+ u32 old_iface_id = n->iface_id;
+ n->dr = rcv_dr;
+ n->bdr = rcv_bdr;
+ n->priority = rcv_priority;
+ n->iface_id = rcv_iface_id;
/* Check priority change */
if (n->state >= NEIGHBOR_2WAY)
{
-#ifdef OSPFv2
- u32 neigh = ipa_to_u32(n->ip);
-#else /* OSPFv3 */
- u32 neigh = n->rid;
-#endif
+ u32 n_id = ospf_is_v2(po) ? ipa_to_u32(n->ip) : n->rid;
- if (n->priority != oldpriority)
+ if (n->priority != old_priority)
ospf_iface_sm(ifa, ISM_NEICH);
-#ifdef OSPFv3
- if (n->iface_id != oldiface_id)
+ if (n->iface_id != old_iface_id)
ospf_iface_sm(ifa, ISM_NEICH);
-#endif
/* Neighbor is declaring itself ad DR and there is no BDR */
- if ((n->dr == neigh) && (n->bdr == 0)
+ if ((n->dr == n_id) && (n->bdr == 0)
&& (n->state != NEIGHBOR_FULL))
ospf_iface_sm(ifa, ISM_BACKS);
/* Neighbor is declaring itself as BDR */
- if ((n->bdr == neigh) && (n->state != NEIGHBOR_FULL))
+ if ((n->bdr == n_id) && (n->state != NEIGHBOR_FULL))
ospf_iface_sm(ifa, ISM_BACKS);
/* Neighbor is newly declaring itself as DR or BDR */
- if (((n->dr == neigh) && (n->dr != olddr))
- || ((n->bdr == neigh) && (n->bdr != oldbdr)))
+ if (((n->dr == n_id) && (n->dr != old_dr))
+ || ((n->bdr == n_id) && (n->bdr != old_bdr)))
ospf_iface_sm(ifa, ISM_NEICH);
/* Neighbor is no more declaring itself as DR or BDR */
- if (((olddr == neigh) && (n->dr != olddr))
- || ((oldbdr == neigh) && (n->bdr != oldbdr)))
+ if (((old_dr == n_id) && (n->dr != old_dr))
+ || ((old_bdr == n_id) && (n->bdr != old_bdr)))
ospf_iface_sm(ifa, ISM_NEICH);
}
void
ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
{
- struct ospf_hello_packet *pkt;
- struct ospf_packet *op;
- struct proto *p;
+ struct proto_ospf *po = ifa->oa->po;
+ struct proto *p = &po->proto;
+ struct ospf_packet *pkt;
struct ospf_neighbor *neigh, *n1;
- u16 length;
- int i;
struct nbma_node *nb;
+ u32 *neighbors;
+ u16 length;
+ int i, max;
if (ifa->state <= OSPF_IS_LOOP)
return;
if (ifa->stub)
return; /* Don't send any packet on stub iface */
- p = (struct proto *) (ifa->oa->po);
DBG("%s: Hello/Poll timer fired on interface %s with IP %I\n",
p->name, ifa->iface->name, ifa->addr->ip);
- /* Now we should send a hello packet */
pkt = ospf_tx_buffer(ifa);
- op = &pkt->ospf_packet;
-
- /* Now fill ospf_hello header */
ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
-#ifdef OSPFv2
- pkt->netmask = ipa_mkmask(ifa->addr->pxlen);
- ipa_hton(pkt->netmask);
- if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
- pkt->netmask = IPA_NONE;
-#endif
-
- pkt->helloint = ntohs(ifa->helloint);
- 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->deadint);
- pkt->dr = htonl(ipa_to_u32(ifa->drip));
- pkt->bdr = htonl(ipa_to_u32(ifa->bdrip));
-#else /* OSPFv3 */
- pkt->deadint = htons(ifa->deadint);
- pkt->dr = htonl(ifa->drid);
- pkt->bdr = htonl(ifa->bdrid);
-#endif
+ if (ospf_is_v2(po))
+ {
+ struct ospf_hello2_packet *ps = (void *) pkt;
+
+ ps->netmask = htonl(u32_mkmask(ifa->addr->pxlen));
+
+ if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
+ ps->netmask = 0;
+
+ ps->helloint = ntohs(ifa->helloint);
+ ps->options = ifa->oa->options;
+ ps->priority = ifa->priority;
+ ps->deadint = htonl(ifa->deadint);
+ ps->dr = htonl(ipa_to_u32(ifa->drip));
+ ps->bdr = htonl(ipa_to_u32(ifa->bdrip));
+
+ length = sizeof(struct ospf_hello2_packet);
+ neighbors = ps->neighbors;
+ }
+ else
+ {
+ struct ospf_hello3_packet *ps = (void *) pkt;
+
+ ps->iface_id = htonl(ifa->iface->index);
+ ps->priority = ifa->priority;
+ ps->options3 = ifa->oa->options >> 16;
+ ps->options2 = ifa->oa->options >> 8;
+ ps->options = ifa->oa->options;
+ ps->helloint = ntohs(ifa->helloint);
+ ps->deadint = htons(ifa->deadint);
+ ps->dr = htonl(ifa->drid);
+ ps->bdr = htonl(ifa->bdrid);
+
+ length = sizeof(struct ospf_hello3_packet);
+ neighbors = ps->neighbors;
+ }
- /* Fill all neighbors */
i = 0;
+ max = (ospf_pkt_bufsize(ifa) - length) / sizeof(u32);
+ /* Fill all neighbors */
if (kind != OHS_SHUTDOWN)
{
- u32 *pp = (u32 *) (((u8 *) pkt) + sizeof(struct ospf_hello_packet));
WALK_LIST(neigh, ifa->neigh_list)
{
- if ((i+1) * sizeof(u32) + sizeof(struct ospf_hello_packet) > ospf_pkt_bufsize(ifa))
+ if (i == max)
{
log(L_WARN "%s: Too many neighbors on interface %s", p->name, ifa->iface->name);
break;
}
- *(pp + i) = htonl(neigh->rid);
+ neighbors[i] = htonl(neigh->rid);
i++;
}
}
- length = sizeof(struct ospf_hello_packet) + i * sizeof(u32);
- op->length = htons(length);
+ length += i * sizeof(u32);
+ pkt->length = htons(length);
switch(ifa->type)
{
wait_timer_hook(timer * timer)
{
struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
- struct proto *p = &ifa->oa->po->proto;
+ struct proto_ospf *po = ifa->oa->po;
OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s.", ifa->iface->name);
ospf_iface_sm(ifa, ISM_WAITF);
static void
ospf_iface_down(struct ospf_iface *ifa)
{
- struct ospf_neighbor *n, *nx;
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
+ struct ospf_neighbor *n, *nx;
struct ospf_iface *iff;
if (ifa->type != OSPF_IT_VLINK)
void
ospf_iface_remove(struct ospf_iface *ifa)
{
- struct proto *p = &ifa->oa->po->proto;
+ struct proto_ospf *po = ifa->oa->po;
+
if (ifa->type == OSPF_IT_VLINK)
OSPF_TRACE(D_EVENTS, "Removing vlink to %R via area %R", ifa->vid, ifa->voa->areaid);
ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
{
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
u8 oldstate = ifa->state;
if (oldstate == state)
void
ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip)
{
- struct proto *p = &oa->po->proto;
+ struct proto_ospf *po = oa->po;
struct iface *iface = addr ? addr->iface : NULL;
struct pool *pool;
#endif
}
- pool = rp_new(p->pool, "OSPF Interface");
+ pool = rp_new(po->proto.pool, "OSPF Interface");
ifa = mb_allocz(pool, sizeof(struct ospf_iface));
ifa->iface = iface;
ifa->addr = addr;
int
ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
{
- struct proto *p = &ifa->oa->po->proto;
+ struct proto_ospf *po = ifa->oa->po;
struct nbma_node *nb, *nbx;
char *ifname = (ifa->type != OSPF_IT_VLINK) ? ifa->iface->name : "vlink";
static void
ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
{
- struct proto *p = &po->proto;
struct ospf_packet *op;
struct ospf_neighbor *n;
OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s", ifa->iface->name);
#include "ospf.h"
+/*
struct ospf_lsack_packet
{
- struct ospf_packet ospf_packet;
- struct ospf_lsa_header lsh[];
-};
+ struct ospf_packet hdr;
+ // union ospf_auth auth;
-
-char *s_queue[] = { "direct", "delayed" };
+ struct ospf_lsa_header lsas[];
+};
+*/
-static void ospf_dump_lsack(struct proto *p, struct ospf_lsack_packet *pkt)
+static void
+ospf_lsack_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
+ struct ospf_lsa_header **body, unsigned *count)
{
- struct ospf_packet *op = &pkt->ospf_packet;
+ unsigned hdrlen = ospf_pkt_hdrlen(po);
+ *body = ((void *) pkt) + hdrlen;
+ *count = (plen - hdrlen) / sizeof(struct ospf_lsa_header);
+}
- ASSERT(op->type == LSACK_P);
- ospf_dump_common(p, op);
+static void
+ospf_lsack_dump(struct proto_ospf *po, struct ospf_packet *pkt)
+{
+ struct ospf_lsa_header *lsas;
+ unsigned i, lsa_count;
- unsigned int i, j;
- j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) /
- sizeof(struct ospf_lsa_header);
+ ASSERT(pkt->type == LSACK_P);
+ ospf_dump_common(po, pkt);
- for (i = 0; i < j; i++)
- ospf_dump_lsahdr(p, pkt->lsh + i);
+ ospf_lsack_body(po, pkt, ntohs(pkt->length), &lsas, &lsa_count);
+ for (i = 0; i < lsa_count; i++)
+ ospf_dump_lsahdr(po, lsas + i);
}
*/
void
-ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h,
- int queue)
+ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h, int queue)
{
struct lsah_n *no = mb_alloc(n->pool, sizeof(struct lsah_n));
memcpy(&no->lsa, h, sizeof(struct ospf_lsa_header));
add_tail(&n->ackl[queue], NODE no);
- DBG("Adding (%s) ack for %R, ID: %R, RT: %R, Type: %u\n", s_queue[queue],
+ DBG("Adding (%s) ack for %R, ID: %R, RT: %R, Type: %u\n",
+ (queue == ACKL_DIRECT) ? "direct" : "delayed",
n->rid, ntohl(h->id), ntohl(h->rt), h->type);
}
-void
-ospf_lsack_send(struct ospf_neighbor *n, int queue)
+static inline void
+ospf_lsack_send_one(struct ospf_neighbor *n, int queue)
{
- struct ospf_packet *op;
- struct ospf_lsack_packet *pk;
- u16 len, i = 0;
- struct ospf_lsa_header *h;
- struct lsah_n *no;
struct ospf_iface *ifa = n->ifa;
- struct proto *p = &n->ifa->oa->po->proto;
-
- if (EMPTY_LIST(n->ackl[queue]))
- return;
+ struct proto_ospf *po = ifa->oa->po;
+ struct ospf_lsa_header *lsas;
+ struct ospf_packet *pkt;
+ struct lsah_n *no;
+ unsigned i, lsa_max, length;
- pk = ospf_tx_buffer(ifa);
- op = &pk->ospf_packet;
- ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
- h = pk->lsh;
+ pkt = ospf_tx_buffer(ifa);
+ ospf_pkt_fill_hdr(ifa, pkt, LSACK_P);
+ ospf_lsack_body(po, pkt, ospf_pkt_maxsize(ifa), &lsas, &lsa_max);
- while (!EMPTY_LIST(n->ackl[queue]))
+ for (i = 0; i < lsa_max && !EMPTY_LIST(n->ackl[queue]); i++)
{
no = (struct lsah_n *) HEAD(n->ackl[queue]);
- memcpy(h + i, &no->lsa, sizeof(struct ospf_lsa_header));
- DBG("Iter %u ID: %R, RT: %R, Type: %04x\n", i, ntohl((h + i)->id),
- ntohl((h + i)->rt), (h + i)->type);
- i++;
+ memcpy(&lsas[i], &no->lsa, sizeof(struct ospf_lsa_header));
+ DBG("Iter %u ID: %R, RT: %R, Type: %04x\n",
+ i, ntohl(lsas[i].id), ntohl(lsas[i].rt), lsas[i].type);
rem_node(NODE no);
mb_free(no);
- if ((i * sizeof(struct ospf_lsa_header) +
- sizeof(struct ospf_lsack_packet)) > ospf_pkt_maxsize(n->ifa))
- {
- if (!EMPTY_LIST(n->ackl[queue]))
- {
- len =
- sizeof(struct ospf_lsack_packet) +
- i * sizeof(struct ospf_lsa_header);
- op->length = htons(len);
- DBG("Sending and continuing! Len=%u\n", len);
-
- OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name);
-
- if (ifa->type == OSPF_IT_BCAST)
- {
- if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
- ospf_send_to_all(ifa);
- else if (ifa->cf->real_bcast)
- ospf_send_to_bdr(ifa);
- else
- ospf_send_to(ifa, AllDRouters);
- }
- else
- {
- if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
- ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
- else
- ospf_send_to_bdr(ifa);
- }
-
- ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
- i = 0;
- }
- }
}
- len = sizeof(struct ospf_lsack_packet) + i * sizeof(struct ospf_lsa_header);
- op->length = htons(len);
- DBG("Sending! Len=%u\n", len);
+ length = ospf_pkt_hdrlen(po) + i * sizeof(struct ospf_lsa_header);
+ pkt->length = htons(length);
- OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name);
+ OSPF_PACKET(ospf_lsack_dump, pkt, "LSACK packet sent via %s", ifa->iface->name);
+ /* XXXX this is very strange */
if (ifa->type == OSPF_IT_BCAST)
{
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
}
else
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
+
+ /*
+ if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
+ ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
+ else
+ ospf_send_to_bdr(ifa);
+ */
+}
+
+void
+ospf_lsack_send(struct ospf_neighbor *n, int queue)
+{
+ while (!EMPTY_LIST(n->ackl[queue]))
+ ospf_lsack_send_one(n, queue);
}
void
-ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
+ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
- struct proto *p = &ifa->oa->po->proto;
- struct ospf_lsa_header lsa;
+ struct proto_ospf *po = ifa->oa->po;
+ struct ospf_lsa_header lsa, *lsas;
struct top_hash_entry *en;
- unsigned int i, lsano;
+ unsigned i, lsa_count;
- unsigned int size = ntohs(ps_i->length);
- if (size < sizeof(struct ospf_lsack_packet))
- {
- log(L_ERR "Bad OSPF LSACK packet from %I - too short (%u B)", n->ip, size);
- return;
- }
- struct ospf_lsack_packet *ps = (void *) ps_i;
- OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->iface->name);
+ /* No need to check length, lsack has only basic header */
- ospf_neigh_sm(n, INM_HELLOREC);
+ OSPF_PACKET(ospf_lsack_dump, pkt, "LSACK packet received from %I via %s",
+ n->ip, ifa->iface->name);
if (n->state < NEIGHBOR_EXCHANGE)
return;
- lsano = (size - sizeof(struct ospf_lsack_packet)) /
- sizeof(struct ospf_lsa_header);
- for (i = 0; i < lsano; i++)
+ ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */
+
+ ospf_lsack_body(po, pkt, ntohs(pkt->length), &lsas, &lsa_count);
+ for (i = 0; i < lsa_count; i++)
{
- ntohlsah(ps->lsh + i, &lsa);
+ ntohlsah(&lsas[i], &lsa);
u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL)
continue; /* pg 155 */
void
flush_lsa(struct top_hash_entry *en, struct proto_ospf *po)
{
- struct proto *p = &po->proto;
-
OSPF_TRACE(D_EVENTS,
"Going to remove LSA Type: %04x, Id: %R, Rt: %R, Age: %u, Seqno: 0x%x",
- en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn);
+ en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn);
s_rem_node(SNODE en);
if (en->lsa_body != NULL)
mb_free(en->lsa_body);
WALK_SLIST_DELSAFE(en, nxt, po->lsal)
{
- if ((LSA_SCOPE(&en->lsa) == LSA_SCOPE_AREA) && (en->domain == areaid))
+ if ((LSA_SCOPE(en->lsa_type) == LSA_SCOPE_AREA) && (en->domain == areaid))
flush_lsa(en, po);
}
}
void
ospf_age(struct proto_ospf *po)
{
- struct proto *p = &po->proto;
struct top_hash_entry *en, *nxt;
int flush = can_flush_lsa(po);
if ((en->lsa.rt == po->router_id) && (en->lsa.age >= LSREFRESHTIME))
{
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);
en->lsa.sn++;
en->lsa.age = 0;
en->inst_t = now;
htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
{
n->age = htons(h->age);
-#ifdef OSPFv2
- n->options = h->options;
-#endif
- n->type = htont(h->type);
+ n->type_raw = htont(h->type_raw);
n->id = htonl(h->id);
n->rt = htonl(h->rt);
n->sn = htonl(h->sn);
ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
{
h->age = ntohs(n->age);
-#ifdef OSPFv2
- h->options = n->options;
-#endif
- h->type = ntoht(n->type);
+ h->type_raw = ntoht(n->type_raw);
h->id = ntohl(n->id);
h->rt = ntohl(n->rt);
h->sn = ntohl(n->sn);
return CMP_SAME;
}
+
+static inline int
+lsa_walk_rt2(struct ospf_lsa_rt_walk *rt)
+{
+ if (rt->buf >= rt->bufend)
+ return 0;
+
+ struct ospf_lsa_rt2_link *l = rt->buf;
+ rt->buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
+
+ rt->type = l->type;
+ rt->metric = l->metric;
+ rt->id = l->id;
+ rt->data = l->data;
+ return 1;
+}
+
+static inline int
+lsa_walk_rt3(struct ospf_lsa_rt_walk *rt)
+{
+ while (rt->buf >= rt->bufend)
+ {
+ rt->en = ospf_hash_find_rt_next(rt->en);
+ if (!rt->en)
+ return 0;
+
+ rt->buf = rt->en->lsa_body;
+ rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
+ rt->buf += sizeof(struct ospf_lsa_rt);
+ }
+
+ struct ospf_lsa_rt3_link *l = rt->buf;
+ rt->buf += sizeof(struct ospf_lsa_rt3_link);
+
+ rt->type = l->type;
+ rt->metric = l->metric;
+ rt->lif = l->lif;
+ rt->nif = l->nif;
+ rt->id = l->id;
+ return 1;
+}
+
+void
+lsa_walk_rt_init(struct proto_ospf *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt)
+{
+ rt->ospf2 = ospf_is_v2(po);
+ rt->id = rt->data = rt->lif = rt->nif = 0;
+
+ if (rt->ospf2)
+ rt->en = act;
+ else
+ rt->en = ospf_hash_find_rt_first(po->gr, act->domain, act->lsa.rt);
+
+ rt->buf = rt->en->lsa_body;
+ rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
+ rt->buf += sizeof(struct ospf_lsa_rt);
+}
+
+int
+lsa_walk_rt(struct ospf_lsa_rt_walk *rt)
+{
+ return rt->ospf2 ? lsa_walk_rt2(rt) : lsa_walk_rt3(rt);
+}
+
+
+void
+lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric)
+{
+ if (ospf2)
+ {
+ struct ospf_lsa_sum2 *ls = en->lsa_body;
+ *ip = ipa_from_u32(en->lsa.id & ls->netmask);
+ *pxlen = u32_masklen(ls->netmask);
+ *pxopts = 0;
+ *metric = ls->metric & METRIC_MASK;
+ }
+ else
+ {
+ struct ospf_lsa_sum3_net *ls = en->lsa_body;
+ u16 rest;
+ lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest);
+ *metric = ls->metric & METRIC_MASK;
+ }
+}
+
+void
+lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options)
+{
+ if (ospf2)
+ {
+ struct ospf_lsa_sum2 *ls = en->lsa_body;
+ *drid = en->lsa.id;
+ *metric = ls->metric & METRIC_MASK;
+ *options = 0;
+ }
+ else
+ {
+ struct ospf_lsa_sum3_rt *ls = en->lsa_body;
+ *drid = ls->drid;
+ *metric = ls->metric & METRIC_MASK;
+ *options = ls->options & OPTIONS_MASK;
+ }
+}
+
+void
+lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt)
+{
+ if (ospf2)
+ {
+ struct ospf_lsa_ext2 *ext = en->lsa_body;
+ rt->ip = ipa_from_u32(en->lsa.id & ext->netmask);
+ rt->pxlen = u32_masklen(ext->netmask);
+ rt->pxopts = 0;
+ rt->metric = ext->metric & METRIC_MASK;
+ rt->ebit = ext->metric & LSA_EXT2_EBIT;
+
+ rt->fbit = ip4_nonzero(ext->fwaddr);
+ rt->fwaddr = ipa_from_ip4(ext->fwaddr);
+
+ rt->tag = ext->tag;
+ rt->propagate = lsa_get_options(&en->lsa) & OPT_P;
+ }
+ else
+ {
+ struct ospf_lsa_ext3 *ext = en->lsa_body;
+ u16 rest;
+ u32 *buf = lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest);
+ rt->metric = ext->metric & METRIC_MASK;
+ rt->ebit = ext->metric & LSA_EXT3_EBIT;
+
+ rt->fbit = ext->metric & LSA_EXT3_FBIT;
+ if (rt->fbit)
+ buf = lsa_get_ipv6_addr(buf, &rt->fwaddr);
+ else
+ rt->fwaddr = IPA_NONE;
+
+ rt->tag = (ext->metric & LSA_EXT3_TBIT) ? *buf++ : 0;
+ rt->propagate = rt->pxopts & OPT_PX_P;
+ }
+}
+
#define HDRLEN sizeof(struct ospf_lsa_header)
static int
}
static int
-lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum_net *body)
+lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body)
{
- if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum_net) + 4))
+ if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + 4))
return 0;
u8 pxl = pxlen(body->prefix);
if (pxl > MAX_PREFIX_LENGTH)
return 0;
- if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum_net) +
+ if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) +
IPV6_PREFIX_SPACE(pxl)))
return 0;
static int
-lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum_rt *body)
+lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body)
{
- if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum_rt)))
+ if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt)))
return 0;
return 1;
}
static int
-lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext *body)
+lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
{
- if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext) + 4))
+ if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext3) + 4))
return 0;
u8 pxl = pxlen(body->rest);
return 0;
int len = IPV6_PREFIX_SPACE(pxl);
- if (body->metric & LSA_EXT_FBIT) // forwardinf address
+ if (body->metric & LSA_EXT3_FBIT) // forwardinf address
len += 16;
- if (body->metric & LSA_EXT_TBIT) // route tag
+ if (body->metric & LSA_EXT3_TBIT) // route tag
len += 4;
if (*body->rest & 0xFFFF) // referenced LS type field
len += 4;
- if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext) + len))
+ if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext3) + len))
return 0;
return 1;
case LSA_T_EXT:
case LSA_T_NSSA:
return lsa_validate_ext(lsa, body);
-#ifdef OSPFv3
case LSA_T_LINK:
return lsa_validate_link(lsa, body);
case LSA_T_PREFIX:
return lsa_validate_prefix(lsa, body);
-#endif
default:
/* In OSPFv3, unknown LSAs are OK,
In OSPFv2, unknown LSAs are already rejected
static inline void ntohlsab1(void *n, u16 len) { ntohlsab(n, n, len); };
#endif
+struct ospf_lsa_rt_walk {
+ struct top_hash_entry *en;
+ void *buf, *bufend;
+ int ospf2;
+ u16 type, metric;
+ u32 id, data, lif, nif;
+};
+
void lsasum_calculate(struct ospf_lsa_header *header, void *body);
u16 lsasum_check(struct ospf_lsa_header *h, void *body);
#define CMP_NEWER 1
#define CMP_SAME 0
#define CMP_OLDER -1
int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2);
+void lsa_walk_rt_init(struct proto_ospf *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt);
+int lsa_walk_rt(struct ospf_lsa_rt_walk *rt);
+void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric);
+void lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options);
+void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt);
int lsa_validate(struct ospf_lsa_header *lsa, void *body);
struct top_hash_entry * lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain, void *body);
void ospf_age(struct proto_ospf *po);
#include "ospf.h"
+/*
struct ospf_lsreq_packet
{
- struct ospf_packet ospf_packet;
- struct ospf_lsreq_header lsh[];
-};
+ struct ospf_packet hdr;
+ // union ospf_auth auth;
+ struct ospf_lsreq_header lsrs[];
+};
+*/
-static void ospf_dump_lsreq(struct proto *p, struct ospf_lsreq_packet *pkt)
+static void
+ospf_lsreq_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
+ struct ospf_lsreq_header **body, unsigned *count)
{
- struct ospf_packet *op = &pkt->ospf_packet;
+ unsigned hdrlen = ospf_pkt_hdrlen(po);
+ *body = ((void *) pkt) + hdrlen;
+ *count = (plen - hdrlen) / sizeof(struct ospf_lsreq_header);
+}
- ASSERT(op->type == LSREQ_P);
- ospf_dump_common(p, op);
+static void
+ospf_lsreq_dump(struct proto_ospf *po, struct ospf_packet *pkt)
+{
+ struct ospf_lsreq_header *lsrs;
+ unsigned i, lsr_count;
- unsigned int i, j;
- j = (ntohs(op->length) - sizeof(struct ospf_lsreq_packet)) /
- sizeof(struct ospf_lsreq_header);
+ ASSERT(pkt->type == LSREQ_P);
+ ospf_dump_common(po, pkt);
- for (i = 0; i < j; i++)
- log(L_TRACE "%s: LSR Type: %04x, Id: %R, Rt: %R", p->name,
- htonl(pkt->lsh[i].type), htonl(pkt->lsh[i].id), htonl(pkt->lsh[i].rt));
+ ospf_lsreq_body(po, pkt, ntohs(pkt->length), &lsrs, &lsr_count);
+ for (i = 0; i < lsr_count; i++)
+ log(L_TRACE "%s: LSR Type: %04x, Id: %R, Rt: %R", po->proto.name,
+ ntohl(lsrs[i].type), ntohl(lsrs[i].id), ntohl(lsrs[i].rt));
}
void
ospf_lsreq_send(struct ospf_neighbor *n)
{
- snode *sn;
+ struct ospf_iface *ifa = n->ifa;
+ struct proto_ospf *po = ifa->oa->po;
+ struct ospf_lsreq_header *lsrs;
struct top_hash_entry *en;
- struct ospf_lsreq_packet *pk;
- struct ospf_packet *op;
- struct ospf_lsreq_header *lsh;
- u16 length;
- int i, j;
- struct proto *p = &n->ifa->oa->po->proto;
-
- pk = ospf_tx_buffer(n->ifa);
- op = &pk->ospf_packet;
+ struct ospf_packet *pkt;
+ unsigned i, lsh_max, length;
+ snode *sn;
- ospf_pkt_fill_hdr(n->ifa, pk, LSREQ_P);
- sn = SHEAD(n->lsrql);
if (EMPTY_SLIST(n->lsrql))
{
if (n->state == NEIGHBOR_LOADING)
return;
}
- i = j = (ospf_pkt_maxsize(n->ifa) - sizeof(struct ospf_lsreq_packet)) /
- sizeof(struct ospf_lsreq_header);
- lsh = pk->lsh;
+ pkt = ospf_tx_buffer(ifa);
+ ospf_pkt_fill_hdr(ifa, pkt, LSREQ_P);
+ ospf_lsreq_body(po, pkt, ospf_pkt_maxsize(ifa), &lsrs, &lsh_max);
- for (; i > 0; i--)
+ sn = SHEAD(n->lsrql);
+ for (i = 0; i < lsh_max; i++)
{
en = (struct top_hash_entry *) sn;
- lsh->type = htonl(en->lsa.type);
- lsh->rt = htonl(en->lsa.rt);
- lsh->id = htonl(en->lsa.id);
DBG("Requesting %uth LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
i, en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
- lsh++;
+
+ lsrs[i].type = htonl(en->lsa.type);
+ lsrs[i].rt = htonl(en->lsa.rt);
+ lsrs[i].id = htonl(en->lsa.id);
+
if (sn == STAIL(n->lsrql))
break;
sn = sn->next;
}
- if (i != 0)
- i--;
- length =
- sizeof(struct ospf_lsreq_packet) + (j -
- i) * sizeof(struct ospf_lsreq_header);
- op->length = htons(length);
+ length = ospf_pkt_hdrlen(po) + i * sizeof(struct ospf_lsreq_header);
+ pkt->length = htons(length);
- OSPF_PACKET(ospf_dump_lsreq, pk, "LSREQ packet sent to %I via %s", n->ip, n->ifa->iface->name);
- ospf_send_to(n->ifa, n->ip);
+ OSPF_PACKET(ospf_lsreq_dump, pkt, "LSREQ packet sent to %I via %s",
+ n->ip, ifa->iface->name);
+ ospf_send_to(ifa, n->ip);
}
void
-ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
+ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
- struct ospf_area *oa = ifa->oa;
- struct proto_ospf *po = oa->po;
- struct proto *p = &po->proto;
- struct ospf_lsreq_header *lsh;
- struct l_lsr_head *llsh;
+ struct proto_ospf *po = ifa->oa->po;
+ struct ospf_lsreq_header *lsrs;
+ unsigned i, lsr_count;
list uplist;
slab *upslab;
- int i, lsano;
- unsigned int size = ntohs(ps_i->length);
- if (size < sizeof(struct ospf_lsreq_packet))
- {
- log(L_ERR "Bad OSPF LSREQ packet from %I - too short (%u B)", n->ip, size);
- return;
- }
- struct ospf_lsreq_packet *ps = (void *) ps_i;
- OSPF_PACKET(ospf_dump_lsreq, ps, "LSREQ packet received from %I via %s", n->ip, ifa->iface->name);
+ /* No need to check length, lsreq has only basic header */
+
+ OSPF_PACKET(ospf_lsreq_dump, pkt, "LSREQ packet received from %I via %s",
+ n->ip, ifa->iface->name);
if (n->state < NEIGHBOR_EXCHANGE)
return;
- ospf_neigh_sm(n, INM_HELLOREC);
+ ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */
- lsh = ps->lsh;
init_list(&uplist);
upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
- lsano = (size - sizeof(struct ospf_lsreq_packet)) /
- sizeof(struct ospf_lsreq_header);
- for (i = 0; i < lsano; lsh++, i++)
+ ospf_lsreq_body(po, pkt, ntohs(pkt->length), &lsrs, &lsr_count);
+ for (i = 0; i < lsr_count; i++)
{
- u32 hid = ntohl(lsh->id);
- u32 hrt = ntohl(lsh->rt);
- u32 htype = ntohl(lsh->type);
+ u32 hid = ntohl(lsrs[i].id);
+ u32 hrt = ntohl(lsrs[i].rt);
+ u32 htype = ntohl(lsrs[i].type);
u32 dom = ospf_lsa_domain(htype, ifa);
- DBG("Processing requested LSA: Type: %u, ID: %R, RT: %R\n", lsh->type, hid, hrt);
- llsh = sl_alloc(upslab);
- llsh->lsh.id = hid;
- llsh->lsh.rt = hrt;
- llsh->lsh.type = htype;
- add_tail(&uplist, NODE llsh);
+ // XXXX check
+ DBG("Processing requested LSA: Type: %u, ID: %R, RT: %R\n", htype, hid, hrt);
+
if (ospf_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
{
log(L_WARN "Received bad LSREQ from %I: Type: %04x, Id: %R, Rt: %R",
rfree(upslab);
return;
}
+
+ struct l_lsr_head *llsh = sl_alloc(upslab);
+ llsh->lsh.id = hid;
+ llsh->lsh.rt = hrt;
+ llsh->lsh.type = htype;
+ add_tail(&uplist, NODE llsh);
}
+
ospf_lsupd_send_list(n, &uplist);
rfree(upslab);
}
/* Beware of unaligned access */
-void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n)
+void ospf_dump_lsahdr(struct proto_ospf *po, struct ospf_lsa_header *lsa_n)
{
struct ospf_lsa_header lsa;
ntohlsah(lsa_n, &lsa);
log(L_TRACE "%s: LSA Type: %04x, Id: %R, Rt: %R, Age: %u, Seq: %08x, Sum: %04x",
- p->name, lsa.type, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
+ po->proto.name, lsa.type, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
}
-void ospf_dump_common(struct proto *p, struct ospf_packet *op)
+void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt)
{
- log(L_TRACE "%s: length %d", p->name, ntohs(op->length));
- log(L_TRACE "%s: router %R", p->name, ntohl(op->routerid));
+ struct proto *p = &po->proto;
+ log(L_TRACE "%s: length %d", p->name, ntohs(pkt->length));
+ log(L_TRACE "%s: router %R", p->name, ntohl(pkt->routerid));
}
-static void ospf_dump_lsupd(struct proto *p, struct ospf_lsupd_packet *pkt)
+static void ospf_dump_lsupd(struct proto_ospf *po, struct ospf_lsupd_packet *pkt)
{
+ struct proto *p = &po->proto;
struct ospf_packet *op = &pkt->ospf_packet;
ASSERT(op->type == LSUPD_P);
- ospf_dump_common(p, op);
+ ospf_dump_common(po, op);
/* We know that ntohs(op->length) >= sizeof(struct ospf_lsa_header) */
u8 *pbuf= (u8 *) pkt;
struct ospf_iface *ifa;
struct ospf_neighbor *nn;
struct top_hash_entry *en;
- struct proto *p = &po->proto;
int ret, retval = 0;
/* pg 148 */
ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
{
struct ospf_area *oa = n->ifa->oa;
- struct proto *p = &oa->po->proto;
+ struct proto_ospf *po = oa->po;
struct l_lsr_head *lsr;
struct top_hash_entry *en;
struct ospf_lsupd_packet *pkt;
continue;
}
+ u16 lsa_type = ntohs(lsa->type_raw);
+ lsa_type = xxxx(lsa_type); // XXXX finish
#ifdef OSPFv2
/* pg 143 (2) */
if ((lsa->type == 0) || (lsa->type == 6) || (lsa->type > LSA_T_NSSA))
}
/* pg 143 (3) */
- if ((lsa->type == LSA_T_EXT) && !oa_is_ext(ifa->oa))
+ if ((lsa_type == LSA_T_EXT) && !oa_is_ext(ifa->oa))
{
log(L_WARN "Received External LSA in stub area from %I", n->ip);
continue;
}
#else /* OSPFv3 */
/* 4.5.1 (2) */
- if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
+ if ((LSA_SCOPE(lsa_type) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
{
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))
+ if ((LSA_SCOPE(lsa_type) == LSA_SCOPE_RES))
{
log(L_WARN "Received LSA with invalid scope from %I", n->ip);
continue;
ntohlsah(lsa, &lsatmp);
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);
+ lsa_type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
/* FIXME domain should be link id for unknown LSA types with zero Ubit */
- u32 domain = ospf_lsa_domain(lsatmp.type, ifa);
+ u32 domain = ospf_lsa_domain(lsa_type, ifa);
lsadb = ospf_hash_find_header(po->gr, domain, &lsatmp);
#ifdef LOCAL_DEBUG
#ifdef OSPFv2
/* 13.4 - check self-originated LSAs of NET type */
- if ((!self) && (lsatmp.type == LSA_T_NET))
+ if ((!self) && (lsa_type == LSA_T_NET))
{
struct ospf_iface *nifa;
WALK_LIST(nifa, po->iface_list)
}
OSPF_TRACE(D_EVENTS, "Received old self-originated LSA (Type: %04x, Id: %R, Rt: %R)",
- lsatmp.type, lsatmp.id, lsatmp.rt);
+ lsa_type, lsatmp.id, lsatmp.rt);
if (lsadb)
{
#ifdef OSPFv3
/* Events 6,7 from RFC5340 4.4.3. */
- if ((lsatmp.type == LSA_T_LINK) &&
- (ifa->state == OSPF_IS_DR))
+ if ((lsa_type == LSA_T_LINK) && (ifa->state == OSPF_IS_DR))
schedule_net_lsa(ifa);
#endif
ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en)
{
struct ospf_lsa_header *lsa = &en->lsa;
- struct proto *p = &po->proto;
lsa->age = LSA_MAXAGE;
lsa->sn = LSA_MAXSEQNO;
lsasum_calculate(lsa, en->lsa_body);
OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa!");
- OSPF_TRACE(D_EVENTS, "Type: %04x, Id: %R, Rt: %R", lsa->type, lsa->id, lsa->rt);
+ OSPF_TRACE(D_EVENTS, "Type: %04x, Id: %R, Rt: %R", en->lsa_type, lsa->id, lsa->rt);
ospf_lsupd_flood(po, NULL, NULL, lsa, en->domain, 0);
}
#ifndef _BIRD_OSPF_LSUPD_H_
#define _BIRD_OSPF_LSUPD_H_
-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_lsahdr(struct proto_ospf *po, struct ospf_lsa_header *lsa_n);
+void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt);
void ospf_lsupd_send_list(struct ospf_neighbor *n, list * l);
void ospf_lsupd_receive(struct ospf_packet *ps_i,
struct ospf_iface *ifa, struct ospf_neighbor *n);
{
struct ospf_iface *ifa = n->ifa;
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
n->state = state;
n->dds = random_u32();
}
n->dds++;
- n->myimms.byte = 0;
- n->myimms.bit.ms = 1;
- n->myimms.bit.m = 1;
- n->myimms.bit.i = 1;
+ n->myimms = DBDES_IMMS;
}
if (state > NEIGHBOR_EXSTART)
- n->myimms.bit.i = 0;
+ n->myimms &= ~DBDES_I;
}
}
{
struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
struct ospf_iface *ifa = n->ifa;
- struct proto *p = &ifa->oa->po->proto;
+ struct proto_ospf *po = ifa->oa->po;
OSPF_TRACE(D_EVENTS,
"Inactivity timer fired on interface %s for neighbor %I.",
ospf_neigh_remove(struct ospf_neighbor *n)
{
struct ospf_iface *ifa = n->ifa;
- struct proto *p = &ifa->oa->po->proto;
+ struct proto_ospf *po = ifa->oa->po;
+ u32 rid = n->rid;
if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
{
neigh_chstate(n, NEIGHBOR_DOWN);
rem_node(NODE n);
rfree(n->pool);
- OSPF_TRACE(D_EVENTS, "Deleting neigbor.");
+ OSPF_TRACE(D_EVENTS, "Deleting neigbor %R", rid);
}
void
return;
}
- if ((n->state == NEIGHBOR_EXCHANGE) && n->myimms.bit.ms) /* I'm master */
+ if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS)) /* I'm master */
ospf_dbdes_send(n, 0);
static void
ospf_area_remove(struct ospf_area *oa)
{
- struct proto *p = &oa->po->proto;
+ struct proto_ospf *po = oa->po;
OSPF_TRACE(D_EVENTS, "Removing area %R", oa->areaid);
/* We suppose that interfaces are already removed */
- ospf_flush_area(oa->po, oa->areaid);
+ ospf_flush_area(po, oa->areaid);
fib_free(&oa->rtr);
fib_free(&oa->net_fib);
if (oa->translator_timer)
rfree(oa->translator_timer);
- oa->po->areano--;
+ po->areano--;
rem_node(NODE oa);
mb_free(oa);
}
void
schedule_net_lsa(struct ospf_iface *ifa)
{
- struct proto *p = &ifa->oa->po->proto;
+ struct proto_ospf *po = ifa->oa->po;
OSPF_TRACE(D_EVENTS, "Scheduling network-LSA origination for iface %s", ifa->iface->name);
ifa->orignet = 1;
void
schedule_link_lsa(struct ospf_iface *ifa)
{
- struct proto *p = &ifa->oa->po->proto;
+ struct proto_ospf *po = ifa->oa->po;
OSPF_TRACE(D_EVENTS, "Scheduling link-LSA origination for iface %s", ifa->iface->name);
ifa->origlink = 1;
void
schedule_rt_lsa(struct ospf_area *oa)
{
- struct proto *p = &oa->po->proto;
+ struct proto_ospf *po = oa->po;
OSPF_TRACE(D_EVENTS, "Scheduling router-LSA origination for area %R", oa->areaid);
oa->origrt = 1;
void
schedule_rtcalc(struct proto_ospf *po)
{
- struct proto *p = &po->proto;
-
if (po->calcrt)
return;
/* Now try to originate network LSA's */
WALK_LIST(ifa, po->iface_list)
{
-#ifdef OSPFv3
/* Link LSA should be originated before Network LSA */
- if (ifa->origlink && (ifa->oa == oa))
+ if (ospf_is_v3(po) && ifa->origlink && (ifa->oa == oa))
update_link_lsa(ifa);
-#endif
if (ifa->orignet && (ifa->oa == oa))
update_net_lsa(ifa);
#endif
+static int lsa_compare_ospf3; // XXXX fixme
+
static int
lsa_compare_for_state(const void *p1, const void *p2)
{
- struct top_hash_entry * he1 = * (struct top_hash_entry **) p1;
- struct top_hash_entry * he2 = * (struct top_hash_entry **) p2;
+ struct top_hash_entry *he1 = * (struct top_hash_entry **) p1;
+ struct top_hash_entry *he2 = * (struct top_hash_entry **) p2;
struct ospf_lsa_header *lsa1 = &(he1->lsa);
struct ospf_lsa_header *lsa2 = &(he2->lsa);
+ struct ospf_lsa_header lsatmp1, lsatmp2;
+ u16 lsa1_type = he1->lsa_type;
+ u16 lsa2_type = he2->lsa_type;
+ int px1 = 0;
+ int px2 = 0;
if (he1->domain != he2->domain)
return he1->domain - he2->domain;
-#ifdef OSPFv3
- struct ospf_lsa_header lsatmp1, lsatmp2;
+ if (lsa_compare_ospf3)
+ {
+ px1 = (lsa1_type == LSA_T_PREFIX);
+ px2 = (lsa2_type == LSA_T_PREFIX);
+ xxxx();
- int px1 = (lsa1->type == LSA_T_PREFIX);
- int px2 = (lsa2->type == LSA_T_PREFIX);
+ if (px1)
+ {
+ lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
+ lsa1_type = lsa1->type;
+ px1 = 1;
+ }
- if (px1)
- lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
+ if (px2)
+ lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
+ }
- if (px2)
- lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
-#endif
- int nt1 = (lsa1->type == LSA_T_NET);
- int nt2 = (lsa2->type == LSA_T_NET);
+ int nt1 = (lsa1_type == LSA_T_NET);
+ int nt2 = (lsa2_type == LSA_T_NET);
if (nt1 != nt2)
return nt1 - nt2;
if (lsa1->id != lsa2->id)
return lsa1->id - lsa2->id;
-#ifdef OSPFv3
if (px1 != px2)
return px1 - px2;
-#endif
return lsa1->sn - lsa2->sn;
}
if (lsa1->rt != lsa2->rt)
return lsa1->rt - lsa2->rt;
- if (lsa1->type != lsa2->type)
- return lsa1->type - lsa2->type;
+ if (lsa1_type != lsa2_type)
+ return lsa1_type - lsa2_type;
if (lsa1->id != lsa2->id)
return lsa1->id - lsa2->id;
-#ifdef OSPFv3
if (px1 != px2)
return px1 - px2;
-#endif
return lsa1->sn - lsa2->sn;
}
}
static inline void
-show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he, int first, int verbose)
+show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he, int verbose)
{
- struct ospf_lsa_header *lsa = &(he->lsa);
- struct ospf_lsa_rt *rt = he->lsa_body;
- struct ospf_lsa_rt_link *rr = (struct ospf_lsa_rt_link *) (rt + 1);
- int max = lsa_rt_count(lsa);
- int i;
-
- if (first)
- {
- cli_msg(-1016, "");
- cli_msg(-1016, "\trouter %R", he->lsa.rt);
- show_lsa_distance(he);
- }
+ struct ospf_lsa_rt_walk rtl;
+ cli_msg(-1016, "");
+ cli_msg(-1016, "\trouter %R", he->lsa.rt);
+ show_lsa_distance(he);
- for (i = 0; i < max; i++)
- if (rr[i].type == LSART_VLNK)
- cli_msg(-1016, "\t\tvlink %R metric %u", rr[i].id, rr[i].metric);
+ lsa_walk_rt_init(po, he, &rtl);
+ while (lsa_walk_rt(&rtl))
+ if (rtl.type == LSART_VLNK)
+ cli_msg(-1016, "\t\tvlink %R metric %u", rtl.id, rtl.metric);
- for (i = 0; i < max; i++)
- if (rr[i].type == LSART_PTP)
- cli_msg(-1016, "\t\trouter %R metric %u", rr[i].id, rr[i].metric);
+ lsa_walk_rt_init(po, he, &rtl);
+ while (lsa_walk_rt(&rtl))
+ if (rtl.type == LSART_PTP)
+ cli_msg(-1016, "\t\trouter %R metric %u", rtl.id, rtl.metric);
- for (i = 0; i < max; i++)
- if (rr[i].type == LSART_NET)
+ lsa_walk_rt_init(po, he, &rtl);
+ while (lsa_walk_rt(&rtl))
+ if (rtl.type == LSART_NET)
{
-#ifdef OSPFv2
- struct top_hash_entry *net_he = ospf_hash_find_net(po->gr, he->domain, rr[i].id);
-
- if (net_he)
+ if (ospf_is_v2(po))
{
- struct ospf_lsa_header *net_lsa = &(net_he->lsa);
- struct ospf_lsa_net *net_ln = net_he->lsa_body;
+ /* In OSPFv2, we try to find network-LSA to get prefix/pxlen */
+ struct top_hash_entry *net_he = ospf_hash_find_net(po->gr, he->domain, rtl.id, 0);
+
+ if (net_he)
+ {
+ struct ospf_lsa_header *net_lsa = &(net_he->lsa);
+ struct ospf_lsa_net *net_ln = net_he->lsa_body;
- cli_msg(-1016, "\t\tnetwork %I/%d metric %u",
- ipa_and(ipa_from_u32(net_lsa->id), net_ln->netmask),
- ipa_mklen(net_ln->netmask), rr[i].metric);
+ cli_msg(-1016, "\t\tnetwork %I/%d metric %u",
+ ipa_from_u32(net_lsa->id & net_ln->optx),
+ u32_masklen(net_ln->optx), rtl.metric);
+ }
+ else
+ cli_msg(-1016, "\t\tnetwork [%R] metric %u", rtl.id, rtl.metric);
}
else
- cli_msg(-1016, "\t\tnetwork [%R] metric %u", rr[i].id, rr[i].metric);
-
-#else /* OSPFv3 */
- cli_msg(-1016, "\t\tnetwork [%R-%u] metric %u", rr[i].id, rr[i].nif, rr[i].metric);
-#endif
+ cli_msg(-1016, "\t\tnetwork [%R-%u] metric %u", rtl.id, rtl.nif, rtl.metric);
}
-#ifdef OSPFv2
- if (!verbose)
- return;
-
- for (i = 0; i < max; i++)
- 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);
-#endif
+ if (ospf_is_v2(po) && verbose)
+ {
+ lsa_walk_rt_init(po, he, &rtl);
+ while (lsa_walk_rt(&rtl))
+ if (rtl.type == LSART_STUB)
+ cli_msg(-1016, "\t\tstubnet %I/%d metric %u",
+ ipa_from_u32(rtl.id), u32_masklen(rtl.data), rtl.metric);
+ }
}
static inline void
-show_lsa_network(struct top_hash_entry *he)
+show_lsa_network(struct top_hash_entry *he, int ospf2)
{
struct ospf_lsa_header *lsa = &(he->lsa);
struct ospf_lsa_net *ln = he->lsa_body;
u32 i;
-#ifdef OSPFv2
- 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, "\t\tdr %R", lsa->rt);
-#else /* OSPFv3 */
- cli_msg(-1016, "");
- cli_msg(-1016, "\tnetwork [%R-%u]", lsa->rt, lsa->id);
-#endif
+ if (ospf2)
+ {
+ cli_msg(-1016, "");
+ cli_msg(-1016, "\tnetwork %I/%d", ipa_from_u32(lsa->id & ln->optx), u32_masklen(ln->optx));
+ cli_msg(-1016, "\t\tdr %R", lsa->rt);
+ }
+ else
+ {
+ cli_msg(-1016, "");
+ cli_msg(-1016, "\tnetwork [%R-%u]", lsa->rt, lsa->id);
+ }
show_lsa_distance(he);
}
static inline void
-show_lsa_sum_net(struct top_hash_entry *he)
+show_lsa_sum_net(struct top_hash_entry *he, int ospf2)
{
ip_addr ip;
int pxlen;
-
-#ifdef OSPFv2
- struct ospf_lsa_sum *ls = he->lsa_body;
- pxlen = ipa_mklen(ls->netmask);
- ip = ipa_and(ipa_from_u32(he->lsa.id), ls->netmask);
-#else /* OSPFv3 */
u8 pxopts;
- u16 rest;
- struct ospf_lsa_sum_net *ls = he->lsa_body;
- lsa_get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts, &rest);
-#endif
+ u32 metric;
- cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, ls->metric);
+ lsa_parse_sum_net(he, ospf2, &ip, &pxlen, &pxopts, &metric);
+ cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, metric);
}
static inline void
-show_lsa_sum_rt(struct top_hash_entry *he)
+show_lsa_sum_rt(struct top_hash_entry *he, int ospf2)
{
+ u32 metric;
u32 dst_rid;
+ u32 options;
-#ifdef OSPFv2
- struct ospf_lsa_sum *ls = he->lsa_body;
- dst_rid = he->lsa.id;
- // options = 0;
-#else /* OSPFv3 */
- struct ospf_lsa_sum_rt *ls = he->lsa_body;
- dst_rid = ls->drid;
- // options = ls->options & OPTIONS_MASK;
-#endif
-
- cli_msg(-1016, "\t\txrouter %R metric %u", dst_rid, ls->metric);
+ lsa_parse_sum_rt(he, ospf2, &dst_rid, &metric, &options);
+ cli_msg(-1016, "\t\txrouter %R metric %u", dst_rid, metric);
}
static inline void
-show_lsa_external(struct top_hash_entry *he)
+show_lsa_external(struct top_hash_entry *he, int ospf2)
{
- struct ospf_lsa_ext *ext = he->lsa_body;
+ struct ospf_lsa_ext_local rt;
char str_via[STD_ADDRESS_P_LENGTH + 8] = "";
char str_tag[16] = "";
- ip_addr ip, rt_fwaddr;
- int pxlen, ebit, rt_fwaddr_valid;
- u32 rt_tag, rt_metric;
- if (he->lsa.type == LSA_T_EXT)
+ if (he->lsa_type == LSA_T_EXT)
he->domain = 0; /* Unmark the LSA */
- rt_metric = ext->metric & METRIC_MASK;
- ebit = ext->metric & LSA_EXT_EBIT;
-#ifdef OSPFv2
- ip = ipa_and(ipa_from_u32(he->lsa.id), ext->netmask);
- pxlen = ipa_mklen(ext->netmask);
- rt_fwaddr = ext->fwaddr;
- rt_fwaddr_valid = !ipa_equal(rt_fwaddr, IPA_NONE);
- rt_tag = ext->tag;
-#else /* OSPFv3 */
- u8 pxopts;
- u16 rest;
- u32 *buf = ext->rest;
- buf = lsa_get_ipv6_prefix(buf, &ip, &pxlen, &pxopts, &rest);
-
- rt_fwaddr_valid = ext->metric & LSA_EXT_FBIT;
- if (rt_fwaddr_valid)
- buf = lsa_get_ipv6_addr(buf, &rt_fwaddr);
- else
- rt_fwaddr = IPA_NONE;
-
- if (ext->metric & LSA_EXT_TBIT)
- rt_tag = *buf++;
- else
- rt_tag = 0;
-#endif
+ lsa_parse_ext(he, ospf2, &rt);
- if (rt_fwaddr_valid)
- bsprintf(str_via, " via %I", rt_fwaddr);
+ if (rt.fbit)
+ bsprintf(str_via, " via %I", rt.fwaddr);
- if (rt_tag)
- bsprintf(str_tag, " tag %08x", rt_tag);
+ if (rt.tag)
+ bsprintf(str_tag, " tag %08x", rt.tag);
cli_msg(-1016, "\t\t%s %I/%d metric%s %u%s%s",
- (he->lsa.type == LSA_T_NSSA) ? "nssa-ext" : "external",
- ip, pxlen, ebit ? "2" : "", rt_metric, str_via, str_tag);
+ (he->lsa_type == LSA_T_NSSA) ? "nssa-ext" : "external",
+ rt.ip, rt.pxlen, rt.ebit ? "2" : "", rt.metric, str_via, str_tag);
}
-#ifdef OSPFv3
static inline void
show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *cnode)
{
int i;
/* We check whether given prefix-LSA is related to the current node */
- if ((px->ref_type != cnode->type) || (px->ref_rt != cnode->rt))
+ if ((px->ref_type != cnode->type_raw) || (px->ref_rt != cnode->rt))
return;
if ((px->ref_type == LSA_T_RT) && (px->ref_id != 0))
cli_msg(-1016, "\t\taddress %I/%d", pxa, pxlen);
}
}
-#endif
void
ospf_sh_state(struct proto *p, int verbose, int reachable)
{
struct proto_ospf *po = (struct proto_ospf *) p;
struct ospf_lsa_header *cnode = NULL;
+ int ospf2 = ospf_is_v2(po);
int num = po->gr->hash_entries;
unsigned int i, ix, j1, j2, jx;
u32 last_area = 0xFFFFFFFF;
{
int accept;
- switch (he->lsa.type)
+ switch (he->lsa_type)
{
case LSA_T_RT:
case LSA_T_NET:
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
case LSA_T_NSSA:
-#ifdef OSPFv3
case LSA_T_PREFIX:
-#endif
accept = verbose;
break;
/* If there is no opened node, we open the LSA (if appropriate) or skip to the next one */
if (!cnode)
{
- if (((he->lsa.type == LSA_T_RT) || (he->lsa.type == LSA_T_NET))
+ if (((he->lsa_type == LSA_T_RT) || (he->lsa_type == LSA_T_NET))
&& ((he->color == INSPF) || !reachable))
{
cnode = &(he->lsa);
ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->rt));
- switch (he->lsa.type)
+ switch (he->lsa_type)
{
case LSA_T_RT:
- show_lsa_router(po, he, he->lsa.id == cnode->id, verbose);
+ if (he->lsa.id == cnode->id)
+ show_lsa_router(po, he, verbose);
break;
case LSA_T_NET:
- show_lsa_network(he);
+ show_lsa_network(he, ospf2);
break;
case LSA_T_SUM_NET:
if (cnode->type == LSA_T_RT)
- show_lsa_sum_net(he);
+ show_lsa_sum_net(he, ospf2);
break;
case LSA_T_SUM_RT:
if (cnode->type == LSA_T_RT)
- show_lsa_sum_rt(he);
+ show_lsa_sum_rt(he, ospf2);
break;
-#ifdef OSPFv3
- case LSA_T_PREFIX:
- show_lsa_prefix(he, cnode);
- break;
-#endif
-
case LSA_T_EXT:
case LSA_T_NSSA:
- show_lsa_external(he);
+ show_lsa_external(he, ospf2);
+ break;
+
+ case LSA_T_PREFIX:
+ show_lsa_prefix(he, cnode);
break;
}
if ((i+1 == j1)
|| (hea[i+1]->domain != last_area)
|| (hea[i+1]->lsa.rt != cnode->rt)
- || (hea[i+1]->lsa.type == LSA_T_NET))
+ || (hea[i+1]->lsa_type == LSA_T_NET))
{
while ((ix < jx) && (hex[ix]->lsa.rt < cnode->rt))
ix++;
while ((ix < jx) && (hex[ix]->lsa.rt == cnode->rt))
- show_lsa_external(hex[ix++]);
+ show_lsa_external(hex[ix++], ospf2);
cnode = NULL;
}
last_rt = he->lsa.rt;
}
- show_lsa_external(he);
+ show_lsa_external(he, ospf2);
}
}
struct top_hash_entry * he2 = * (struct top_hash_entry **) p2;
struct ospf_lsa_header *lsa1 = &(he1->lsa);
struct ospf_lsa_header *lsa2 = &(he2->lsa);
- int sc1 = LSA_SCOPE(lsa1);
- int sc2 = LSA_SCOPE(lsa2);
+ int sc1 = LSA_SCOPE(he1->lsa_type);
+ int sc2 = LSA_SCOPE(he2->lsa_type);
if (sc1 != sc2)
return sc2 - sc1;
if (lsa1->id != lsa2->id)
return lsa1->id - lsa2->id;
- if (lsa1->type != lsa2->type)
- return lsa1->type - lsa2->type;
+ if (he1->lsa_type != he2->lsa_type)
+ return he1->lsa_type - he2->lsa_type;
return lsa1->sn - lsa2->sn;
}
for (i = 0; i < j; i++)
{
struct ospf_lsa_header *lsa = &(hea[i]->lsa);
- int dscope = LSA_SCOPE(lsa);
+ int dscope = LSA_SCOPE(hea[i]->lsa_type);
if (ld->scope && (dscope != (ld->scope & 0xf000)))
continue;
continue;
/* Ignore high nibble */
+ // XXXX check
if (ld->type && ((lsa->type & 0x0fff) != (ld->type & 0x0fff)))
continue;
#ifndef _BIRD_OSPF_H_
#define _BIRD_OSPF_H_
-#define MAXNETS 10
+
#define OSPF_MAX_PKT_SIZE 65535
/*
* RFC 2328 says, maximum packet size is 65535 (IP packet size
#else
#define OSPF_FORCE_DEBUG 0
#endif
-#define OSPF_TRACE(flags, msg, args...) do { if ((p->debug & flags) || OSPF_FORCE_DEBUG) \
- log(L_TRACE "%s: " msg, p->name , ## args ); } while(0)
+
+#define OSPF_TRACE(flags, msg, args...) \
+do { if ((po->proto.debug & flags) || OSPF_FORCE_DEBUG) \
+ log(L_TRACE "%s: " msg, po->proto.name , ## args ); } while(0)
#define OSPF_PACKET(dumpfn, buffer, msg, args...) \
-do { if ((p->debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
-{ log(L_TRACE "%s: " msg, p->name, ## args ); dumpfn(p, buffer); } } while(0)
+do { if ((po->proto.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
+{ log(L_TRACE "%s: " msg, po->proto.name, ## args ); dumpfn(po, buffer); } } while(0)
#include "nest/bird.h"
#define OSPF_PROTO 89
-#ifndef IPV6
-#define OSPFv2 1
-#define OSPF_VERSION 2
-#define OSPF_VLINK_MTU 576 /* RFC 2328 A.1 */
-#define AllSPFRouters ipa_from_u32(0xe0000005) /* 224.0.0.5 */
-#define AllDRouters ipa_from_u32(0xe0000006) /* 224.0.0.6 */
-#else
+
+// XXXX
#define OSPFv3 1
#define OSPF_VERSION 3
-#define OSPF_VLINK_MTU 1280 /* RFC 5340 A.1 */
-#define AllSPFRouters _MI(0xFF020000, 0, 0, 5) /* FF02::5 */
-#define AllDRouters _MI(0xFF020000, 0, 0, 6) /* FF02::6 */
-#endif
+
#define LSREFRESHTIME 1800 /* 30 minutes */
};
-/* Option flags */
+/* Generic option flags */
+#define OPT_V6 0x01 /* OSPFv3, LSA relevant for IPv6 routing calculation */
+#define OPT_E 0x02 /* Related to AS-external LSAs */
+#define OPT_MC 0x04 /* Related to MOSPF, not used and obsolete */
+#define OPT_N 0x08 /* Related to NSSA */
+#define OPT_P 0x08 /* OSPFv2, flags P and N share position, see NSSA RFC */
+#define OPT_EA 0x10 /* OSPFv2, external attributes, not used and obsolete */
+#define OPT_R 0x10 /* OSPFv3, originator is active router */
+#define OPT_DC 0x20 /* Related to demand circuits, not used */
-#define OPT_E 0x02
-#define OPT_N 0x08
-#define OPT_DC 0x20
-
-#ifdef OSPFv2
-#define OPT_P 0x08 /* flags P and N share position, see NSSA RFC */
-#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)
-#define OPT_RT_NT (0x10 << 8)
-#endif
-
-#ifdef OSPFv3
-#define OPT_V6 0x01
-#define OPT_R 0x10
-
-/* VEB flags are are stored together with options in 'u32 options' */
+/* Router-LSA VEB flags are are stored together with links (OSPFv2) or options (OSPFv3) */
#define OPT_RT_B (0x01 << 24)
#define OPT_RT_E (0x02 << 24)
#define OPT_RT_V (0x04 << 24)
#define OPT_RT_NT (0x10 << 24)
+/* Prefix flags, specific for OSPFv3 */
#define OPT_PX_NU 0x01
#define OPT_PX_LA 0x02
#define OPT_PX_P 0x08
#define OPT_PX_DN 0x10
-#endif
+
+
+/* OSPF interface types */
+#define OSPF_IT_BCAST 0
+#define OSPF_IT_NBMA 1
+#define OSPF_IT_PTP 2
+#define OSPF_IT_PTMP 3
+#define OSPF_IT_VLINK 4
+#define OSPF_IT_UNDEF 5
+
+/* OSPF interface states */
+#define OSPF_IS_DOWN 0 /* Not active */
+#define OSPF_IS_LOOP 1 /* Iface with no link */
+#define OSPF_IS_WAITING 2 /* Waiting for Wait timer */
+#define OSPF_IS_PTP 3 /* PTP operational */
+#define OSPF_IS_DROTHER 4 /* I'm on BCAST or NBMA and I'm not DR */
+#define OSPF_IS_BACKUP 5 /* I'm BDR */
+#define OSPF_IS_DR 6 /* I'm DR */
struct ospf_iface
transmit a Link State Update Packet over this
interface. LSAs contained in the update */
u16 helloint; /* number of seconds between hello sending */
-
-#ifdef OSPFv2
list *passwords;
u16 autype;
u32 csn; /* Last used crypt seq number */
bird_clock_t csn_use; /* Last time when packet with that CSN was sent */
-#endif
-
ip_addr all_routers; /* */
ip_addr drip; /* Designated router */
ip_addr bdrip; /* Backup DR */
u32 bdrid;
s16 rt_pos_beg; /* Position of iface in Router-LSA, begin, inclusive */
s16 rt_pos_end; /* Position of iface in Router-LSA, end, exclusive */
-
-#ifdef OSPFv3
s16 px_pos_beg; /* Position of iface in Rt Prefix-LSA, begin, inclusive */
s16 px_pos_end; /* Position of iface in Rt Prefix-LSA, end, exclusive */
-
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 */
-#define OSPF_IT_BCAST 0
-#define OSPF_IT_NBMA 1
-#define OSPF_IT_PTP 2
-#define OSPF_IT_PTMP 3
-#define OSPF_IT_VLINK 4
-#define OSPF_IT_UNDEF 5
+ u8 type; /* OSPF view of type (OSPF_IT_*) */
u8 strictnbma; /* Can I talk with unknown neighbors? */
u8 stub; /* Inactive interface */
- u8 state; /* Interface state machine */
-#define OSPF_IS_DOWN 0 /* Not working */
-#define OSPF_IS_LOOP 1 /* Iface with no link */
-#define OSPF_IS_WAITING 2 /* Waiting for Wait timer */
-#define OSPF_IS_PTP 3 /* PTP operational */
-#define OSPF_IS_DROTHER 4 /* I'm on BCAST or NBMA and I'm not DR */
-#define OSPF_IS_BACKUP 5 /* I'm BDR */
-#define OSPF_IS_DR 6 /* I'm DR */
+ u8 state; /* Interface state machine (OSPF_IS_*) */
timer *wait_timer; /* WAIT timer */
timer *hello_timer; /* HELLOINT timer */
timer *poll_timer; /* Poll Interval - for NBMA */
struct top_hash_entry *net_lsa; /* Originated network LSA */
int orignet; /* Schedule network LSA origination */
-#ifdef OSPFv3
int origlink; /* Schedule link LSA origination */
struct top_hash_entry *link_lsa; /* Originated link LSA */
struct top_hash_entry *pxn_lsa; /* Originated prefix LSA */
-#endif
int fadj; /* Number of full adjacent neigh */
list nbma_list;
u8 priority; /* A router priority for DR election */
/* Packet types */
-#define HELLO_P 1 /* Hello */
-#define DBDES_P 2 /* Database description */
-#define LSREQ_P 3 /* Link state request */
-#define LSUPD_P 4 /* Link state update */
-#define LSACK_P 5 /* Link state acknowledgement */
+#define HELLO_P 1 /* Hello */
+#define DBDES_P 2 /* Database description */
+#define LSREQ_P 3 /* Link state request */
+#define LSUPD_P 4 /* Link state update */
+#define LSACK_P 5 /* Link state acknowledgement */
/* Area IDs */
-#define BACKBONE 0
-
-
-struct immsb
-{
-#ifdef CPU_BIG_ENDIAN
- u8 padding:5;
- u8 i:1;
- u8 m:1;
- u8 ms:1;
-#else
- u8 ms:1;
- u8 m:1;
- u8 i:1;
- u8 padding:5;
-#endif
-};
+#define BACKBONE 0
-union imms
-{
- u8 byte;
- struct immsb bit;
-};
-#define DBDES_MS 1
-#define DBDES_M 2
-#define DBDES_I 4
+#define DBDES_I 4 /* Init bit */
+#define DBDES_M 2 /* More bit */
+#define DBDES_MS 1 /* Master/Slave bit */
+#define DBDES_IMMS (DBDES_I | DBDES_M | DBDES_MS)
-#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 */
+/*
+ * There is slight difference in OSPF packet header between v2 and v3
+ * in vdep field. For OSPFv2, vdep is u16 authentication type and
+ * ospf_header is followed by union ospf_auth. For OSPFv3, higher byte
+ * of vdep is instance ID and lower byte is zero.
+ */
struct ospf_packet
{
u32 routerid;
u32 areaid;
u16 checksum;
- u8 instance_id;
- u8 zero;
+ u16 vdep;
};
-#endif
-
-
-
-
-struct ospf_lsa_header
-{
- u16 age; /* LS Age */
-#define LSA_MAXAGE 3600 /* 1 hour */
-#define LSA_CHECKAGE 300 /* 5 minutes */
-#define LSA_MAXAGEDIFF 900 /* 15 minutes */
-
-#ifdef OSPFv2
- u8 options;
- u8 type;
-
+// XXXX
+/*
#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
#define LSA_T_NSSA 7
-
-#define LSA_SCOPE_AREA 0x2000
-#define LSA_SCOPE_AS 0x4000
-
-#define LSA_SCOPE(lsa) (((lsa)->type == LSA_T_EXT) ? LSA_SCOPE_AS : LSA_SCOPE_AREA)
-
-#else /* OSPFv3 */
- u16 type;
+*/
#define LSA_T_RT 0x2001
#define LSA_T_NET 0x2002
#define LSA_SCOPE_AS 0x4000
#define LSA_SCOPE_RES 0x6000
#define LSA_SCOPE_MASK 0x6000
+#define LSA_SCOPE(lsa) ((lsa) & LSA_SCOPE_MASK)
-#define LSA_SCOPE(lsa) ((lsa)->type & LSA_SCOPE_MASK)
-#endif
+
+#define LSA_MAXAGE 3600 /* 1 hour */
+#define LSA_CHECKAGE 300 /* 5 minutes */
+#define LSA_MAXAGEDIFF 900 /* 15 minutes */
+
+#define LSA_INITSEQNO ((s32) 0x80000001)
+#define LSA_MAXSEQNO ((s32) 0x7fffffff)
+
+
+#define LSART_PTP 1
+#define LSART_NET 2
+#define LSART_STUB 3
+#define LSART_VLNK 4
+
+#define LSA_SUM2_TOS 0xFF000000
+
+#define LSA_EXT2_TOS 0x7F000000
+#define LSA_EXT2_EBIT 0x80000000
+
+#define LSA_EXT3_EBIT 0x4000000
+#define LSA_EXT3_FBIT 0x2000000
+#define LSA_EXT3_TBIT 0x1000000
+
+// XXXX remove
+#define LSA_EXT_EBIT 0x4000000
+
+
+struct ospf_lsa_header
+{
+ u16 age; /* LS Age */
+ u16 type_raw; /* Type, mixed with options on OSPFv2 */
u32 id;
u32 rt; /* Advertising router */
s32 sn; /* LS Sequence number */
-#define LSA_INITSEQNO ((s32) 0x80000001)
-#define LSA_MAXSEQNO ((s32) 0x7fffffff)
u16 checksum;
u16 length;
};
+/* In OSPFv2, options are embedded in higher half of type_raw */
+static inline u8 lsa_get_options(struct ospf_lsa_header *lsa)
+{ return lsa->type_raw >> 8; }
-#define LSART_PTP 1
-#define LSART_NET 2
-#define LSART_STUB 3
-#define LSART_VLNK 4
+static inline void lsa_set_options(struct ospf_lsa_header *lsa, u16 options)
+{ lsa->type_raw = (lsa->type_raw & 0xff) | (options << 8); }
-#ifdef OSPFv2
-
struct ospf_lsa_rt
{
-#ifdef CPU_BIG_ENDIAN
- u16 options; /* VEB flags only */
- u16 links;
-#else
- u16 links;
- u16 options; /* VEB flags only */
-#endif
+ u32 options; /* VEB flags, mixed with link count for OSPFv2 and options for OSPFv3 */
};
-struct ospf_lsa_rt_link
+struct ospf_lsa_rt2_link
{
u32 id;
u32 data;
#ifdef CPU_BIG_ENDIAN
u8 type;
- u8 padding;
+ u8 no_tos;
u16 metric;
#else
u16 metric;
- u8 padding;
+ u8 no_tos;
u8 type;
#endif
};
-struct ospf_lsa_net
-{
- ip_addr netmask;
- u32 routers[];
-};
-
-struct ospf_lsa_sum
-{
- ip_addr netmask;
- u32 metric;
-};
-
-struct ospf_lsa_ext
-{
- ip_addr netmask;
- u32 metric;
- ip_addr fwaddr;
- u32 tag;
-};
-
-#define LSA_SUM_TOS 0xFF000000
-#define LSA_EXT_TOS 0x7F000000
-#define LSA_EXT_EBIT 0x80000000
-
-/* Endianity swap for lsa->type */
-#define ntoht(x) x
-#define htont(x) x
-
-
-#else /* OSPFv3 */
-
-struct ospf_lsa_rt
-{
- u32 options;
-};
-
-struct ospf_lsa_rt_link
+struct ospf_lsa_rt3_link
{
#ifdef CPU_BIG_ENDIAN
u8 type;
u32 id; /* Neighbor router ID */
};
+
struct ospf_lsa_net
{
- u32 options;
+ u32 optx; /* Netmask for OSPFv2, options for OSPFv3 */
u32 routers[];
};
-struct ospf_lsa_sum_net
+struct ospf_lsa_sum2
+{
+ ip4_addr netmask;
+ u32 metric;
+};
+
+struct ospf_lsa_sum3_net
{
u32 metric;
u32 prefix[];
};
-struct ospf_lsa_sum_rt
+struct ospf_lsa_sum3_rt
{
u32 options;
u32 metric;
u32 drid;
};
-struct ospf_lsa_ext
+struct ospf_lsa_ext2
+{
+ ip4_addr netmask;
+ u32 metric;
+ ip4_addr fwaddr;
+ u32 tag;
+};
+
+struct ospf_lsa_ext3
{
u32 metric;
u32 rest[];
};
+struct ospf_lsa_ext_local
+{
+ ip_addr ip, fwaddr;
+ int pxlen;
+ u32 metric, ebit, fbit, tag, propagate;
+ u8 pxopts;
+};
+
struct ospf_lsa_link
{
u32 options;
- ip_addr lladdr;
+ ip6_addr lladdr;
u32 pxcount;
u32 rest[];
};
u32 rest[];
};
-#define LSA_EXT_EBIT 0x4000000
-#define LSA_EXT_FBIT 0x2000000
-#define LSA_EXT_TBIT 0x1000000
+
+
+
+#ifdef OSPFv2
+
+
+/* Endianity swap for lsa->type */
+#define ntoht(x) x
+#define htont(x) x
+
+
+#else /* OSPFv3 */
+
+
+
/* Endianity swap for lsa->type */
#define ntoht(x) ntohs(x)
#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)
#define NEIGHBOR_LOADING 6
#define NEIGHBOR_FULL 7
timer *inactim; /* Inactivity timer */
- union imms imms; /* I, M, Master/slave received */
+ u8 imms; /* I, M, Master/slave received */
+ u8 myimms; /* I, M Master/slave */
u32 dds; /* DD Sequence number being sent */
u32 ddr; /* last Dat Des packet received */
- union imms myimms; /* I, M Master/slave */
+
u32 rid; /* Router ID */
ip_addr ip; /* IP of it's interface */
u8 priority; /* Priority */
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 */
slist lsrql; /* Link state request */
u8 check_link;
u8 ecmp_weight;
u8 real_bcast; /* Not really used in OSPFv3 */
-
-#ifdef OSPFv2
list *passwords;
-#endif
-
-#ifdef OSPFv3
u8 instance_id;
-#endif
};
int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
void schedule_rtcalc(struct proto_ospf *po);
void schedule_net_lsa(struct ospf_iface *ifa);
+static inline int ospf_is_v2(struct proto_ospf *po)
+{ return 0; } // XXXX fixme
+static inline int ospf_is_v3(struct proto_ospf *po)
+{ return 1; } // XXXX fixme
+
+static inline void lsa_fix_options(struct proto_ospf *po, struct ospf_lsa_header *lsa, u8 options)
+{ if (ospf_is_v2(po)) lsa_set_options(lsa, options); }
+
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
static inline struct ospf_area *ospf_main_area(struct proto_ospf *po)
{ return (po->areano == 1) ? HEAD(po->area_list) : po->backbone; }
{ return oa->options & OPT_N; }
-#ifdef OSPFv3
-void schedule_link_lsa(struct ospf_iface *ifa);
-#else
-static inline void schedule_link_lsa(struct ospf_iface *ifa UNUSED) {}
-#endif
+
+void schedule_link_lsa(struct ospf_iface *ifa); // XXXX caller ??
void ospf_sh_neigh(struct proto *p, char *iff);
void ospf_sh(struct proto *p);
struct ospf_neighbor *n = find_neigh(ifa, rid);
#endif
- if(!n && (ps->type != HELLO_P))
+ if (!n && (ps->type != HELLO_P))
{
log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
sk->faddr, ifa->iface->name);
#ifdef OSPFv2
#define ipa_from_rid(x) _MI(x)
#else /* OSPFv3 */
-#define ipa_from_rid(x) _MI(0,0,0,x)
+#define ipa_from_rid(x) _MI6(0,0,0,x)
#endif
return NULL;
}
-#ifdef OSPFv3
static inline struct ospf_iface *
px_pos_to_ifa(struct ospf_area *oa, int pos)
{
return ifa;
return NULL;
}
-#endif
static void
add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_hash_entry *en, int pos)
{
+ struct proto_ospf *po = oa->po;
+
orta nf = {
.type = RTS_OSPF,
.options = 0,
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
{
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
- oa->po->proto.name, en->lsa.type, en->lsa.id, en->lsa.rt);
+ po->proto.name, en->lsa_type, en->lsa.id, en->lsa.rt);
return;
}
*/
struct ospf_iface *ifa;
-#ifdef OSPFv2
- ifa = rt_pos_to_ifa(oa, pos);
-#else /* OSPFv3 */
- ifa = px_pos_to_ifa(oa, pos);
-#endif
+ ifa = ospf_is_v2(po) ? rt_pos_to_ifa(oa, pos) : px_pos_to_ifa(oa, pos);
+ nf.nhs = ifa ? new_nexthop(po, IPA_NONE, ifa->iface, ifa->ecmp_weight) : NULL;
+ }
+
+ ri_install_net(po, px, pxlen, &nf);
+}
+
+
+
+static inline void
+spfa_process_rt(struct ospf_area *oa, struct top_hash_entry *act)
+{
+ struct proto_ospf *po = oa->po;
+ struct ospf_lsa_rt *rt = act->lsa_body;
+ struct ospf_lsa_rt_walk rtl;
+ struct top_hash_entry *tmp;
+ ip_addr prefix;
+ int pxlen;
+
+ if (rt->options & OPT_RT_V)
+ oa->trcap = 1;
- nf.nhs = ifa ? new_nexthop(oa->po, IPA_NONE, ifa->iface, ifa->ecmp_weight) : NULL;
+ /*
+ * In OSPFv3, all routers are added to per-area routing
+ * tables. But we use it just for ASBRs and ABRs. For the
+ * purpose of the last step in SPF - prefix-LSA processing in
+ * spfa_process_prefixes(), we use information stored in LSA db.
+ */
+ if (((rt->options & OPT_RT_E) || (rt->options & OPT_RT_B))
+ && (act->lsa.rt != po->router_id))
+ {
+ orta nf = {
+ .type = RTS_OSPF,
+ .options = rt->options,
+ .metric1 = act->dist,
+ .metric2 = LSINFINITY,
+ .tag = 0,
+ .rid = act->lsa.rt,
+ .oa = oa,
+ .nhs = act->nhs
+ };
+ ri_install_rt(oa, act->lsa.rt, &nf);
}
- ri_install_net(oa->po, px, pxlen, &nf);
+ /* Now process Rt links */
+ lsa_walk_rt_init(po, act, &rtl);
+ while (lsa_walk_rt(&rtl))
+ {
+ tmp = NULL;
+
+ switch (rtl.type)
+ {
+ case LSART_STUB:
+
+ /* Should not happen, LSART_STUB is not defined in OSPFv3 */
+ if (ospf_is_v3(po))
+ break;
+
+ /*
+ * RFC 2328 in 16.1. (2a) says to handle stub networks in an
+ * second phase after the SPF for an area is calculated. We get
+ * the same result by handing them here because add_network()
+ * will keep the best (not the first) found route.
+ */
+ prefix = ipa_from_u32(rtl.id & rtl.data);
+ pxlen = u32_masklen(rtl.data);
+ add_network(oa, prefix, pxlen, act->dist + rtl.metric, act, i);
+ break;
+
+ case LSART_NET:
+ tmp = ospf_hash_find_net(po->gr, oa->areaid, rtl.id, rtl.nif);
+ break;
+
+ case LSART_VLNK:
+ case LSART_PTP:
+ tmp = ospf_hash_find_rt(po->gr, oa->areaid, rtl.id);
+ break;
+ }
+
+ add_cand(&oa->cand, tmp, act, act->dist + rtl.metric, oa, i);
+ }
}
-#ifdef OSPFv3
-static void
-process_prefixes(struct ospf_area *oa)
+static inline void
+spfa_process_net(struct ospf_area *oa, struct top_hash_entry *act)
+{
+ struct proto_ospf *po = oa->po;
+ struct ospf_lsa_net *ln = act->lsa_body;
+ struct top_hash_entry *tmp;
+ ip_addr prefix;
+ int pxlen, i, cnt;
+
+ if (ospf_is_v2(po))
+ {
+ prefix = ipa_from_u32(act->lsa.id & ln->optx);
+ pxlen = u32_masklen(ln->optx);
+ add_network(oa, prefix, pxlen, act->dist, act, -1);
+ }
+
+ cnt = lsa_net_count(&act->lsa);
+ for (i = 0; i < cnt; i++)
+ {
+ tmp = ospf_hash_find_rt(po->gr, oa->areaid, ln->routers[i]);
+ add_cand(&oa->cand, tmp, act, act->dist, oa, -1);
+ }
+}
+
+static inline void
+spfa_process_prefixes(struct ospf_area *oa)
{
struct proto_ospf *po = oa->po;
// struct proto *p = &po->proto;
WALK_SLIST(en, po->lsal)
{
- if (en->lsa.type != LSA_T_PREFIX)
+ if (en->lsa_type != LSA_T_PREFIX)
continue;
if (en->domain != oa->areaid)
if (src->color != INSPF)
continue;
- if ((src->lsa.type != LSA_T_RT) && (src->lsa.type != LSA_T_NET))
+ if ((src->lsa_type != LSA_T_RT) && (src->lsa_type != LSA_T_NET))
continue;
buf = px->rest;
}
}
}
-#endif
-
-
-static void
-ospf_rt_spfa_rtlinks(struct ospf_area *oa, struct top_hash_entry *act, struct top_hash_entry *en)
-{
- // struct proto *p = &oa->po->proto;
- struct proto_ospf *po = oa->po;
- ip_addr prefix UNUSED;
- int pxlen UNUSED, i;
-
- struct ospf_lsa_rt *rt = en->lsa_body;
- struct ospf_lsa_rt_link *rr = (struct ospf_lsa_rt_link *) (rt + 1);
-
- for (i = 0; i < lsa_rt_count(&en->lsa); i++)
- {
- struct ospf_lsa_rt_link *rtl = rr + i;
- struct top_hash_entry *tmp = NULL;
-
- DBG(" Working on link: %R (type: %u) ", rtl->id, rtl->type);
- switch (rtl->type)
- {
-#ifdef OSPFv2
- case LSART_STUB:
- /*
- * RFC 2328 in 16.1. (2a) says to handle stub networks in an
- * second phase after the SPF for an area is calculated. We get
- * the same result by handing them here because add_network()
- * will keep the best (not the first) found route.
- */
- prefix = ipa_from_u32(rtl->id & rtl->data);
- pxlen = ipa_mklen(ipa_from_u32(rtl->data));
- add_network(oa, prefix, pxlen, act->dist + rtl->metric, act, i);
- break;
-#endif
-
- case LSART_NET:
-#ifdef OSPFv2
- /* In OSPFv2, rtl->id is IP addres of DR, Router ID is not known */
- tmp = ospf_hash_find_net(po->gr, oa->areaid, rtl->id);
-#else /* OSPFv3 */
- tmp = ospf_hash_find(po->gr, oa->areaid, rtl->nif, rtl->id, LSA_T_NET);
-#endif
- break;
-
- case LSART_VLNK:
- case LSART_PTP:
- tmp = ospf_hash_find_rt(po->gr, oa->areaid, rtl->id);
- break;
-
- default:
- log("Unknown link type in router lsa. (rid = %R)", act->lsa.id);
- break;
- }
-
- if (tmp)
- DBG("Going to add cand, Mydist: %u, Req: %u\n",
- tmp->dist, act->dist + rtl->metric);
- add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa, i);
- }
-}
/* RFC 2328 16.1. calculating shortest paths for an area */
static void
ospf_rt_spfa(struct ospf_area *oa)
{
- struct proto *p = &oa->po->proto;
struct proto_ospf *po = oa->po;
- struct ospf_lsa_rt *rt;
- struct ospf_lsa_net *ln;
- struct top_hash_entry *act, *tmp;
- ip_addr prefix UNUSED;
- int pxlen UNUSED;
- u32 i, *rts;
+ struct proto *p = &po->proto;
+ struct top_hash_entry *act;
node *n;
if (oa->rt == NULL)
oa->rt->color = CANDIDATE;
add_head(&oa->cand, &oa->rt->cn);
DBG("RT LSA: rt: %R, id: %R, type: %u\n",
- oa->rt->lsa.rt, oa->rt->lsa.id, oa->rt->lsa.type);
+ oa->rt->lsa.rt, oa->rt->lsa.id, oa->rt->lsa_type);
while (!EMPTY_LIST(oa->cand))
{
rem_node(n);
DBG("Working on LSA: rt: %R, id: %R, type: %u\n",
- act->lsa.rt, act->lsa.id, act->lsa.type);
+ act->lsa.rt, act->lsa.id, act->lsa_type);
act->color = INSPF;
- switch (act->lsa.type)
+ switch (act->lsa_type)
{
case LSA_T_RT:
- rt = (struct ospf_lsa_rt *) act->lsa_body;
- if (rt->options & OPT_RT_V)
- oa->trcap = 1;
-
- /*
- * In OSPFv3, all routers are added to per-area routing
- * tables. But we use it just for ASBRs and ABRs. For the
- * purpose of the last step in SPF - prefix-LSA processing in
- * process_prefixes(), we use information stored in LSA db.
- */
- if (((rt->options & OPT_RT_E) || (rt->options & OPT_RT_B))
- && (act->lsa.rt != po->router_id))
- {
- orta nf = {
- .type = RTS_OSPF,
- .options = rt->options,
- .metric1 = act->dist,
- .metric2 = LSINFINITY,
- .tag = 0,
- .rid = act->lsa.rt,
- .oa = oa,
- .nhs = act->nhs
- };
- ri_install_rt(oa, act->lsa.rt, &nf);
- }
-
-#ifdef OSPFv2
- ospf_rt_spfa_rtlinks(oa, act, act);
-#else /* OSPFv3 */
- for (tmp = ospf_hash_find_rt_first(po->gr, act->domain, act->lsa.rt);
- tmp; tmp = ospf_hash_find_rt_next(tmp))
- ospf_rt_spfa_rtlinks(oa, act, tmp);
-#endif
-
+ spfa_process_rt(oa, act);
break;
- case LSA_T_NET:
- ln = act->lsa_body;
-#ifdef OSPFv2
- prefix = ipa_and(ipa_from_u32(act->lsa.id), ln->netmask);
- pxlen = ipa_mklen(ln->netmask);
- add_network(oa, prefix, pxlen, act->dist, act, -1);
-#endif
-
- rts = (u32 *) (ln + 1);
- for (i = 0; i < lsa_net_count(&act->lsa); i++)
- {
- DBG(" Working on router %R ", rts[i]);
- tmp = ospf_hash_find_rt(po->gr, oa->areaid, rts[i]);
- if (tmp != NULL)
- DBG("Found :-)\n");
- else
- DBG("Not found!\n");
- add_cand(&oa->cand, tmp, act, act->dist, oa, -1);
- }
+ case LSA_T_NET:
+ spfa_process_net(oa, act);
break;
+
+ default:
+ log(L_WARN "%s: Unknown LSA type in SPF: %d", p->name, act->lsa_type);
}
}
-#ifdef OSPFv3
- process_prefixes(oa);
-#endif
+ if (ospf_is_v3(po))
+ spfa_process_prefixes(oa);
}
static int
link_back(struct ospf_area *oa, struct top_hash_entry *en, struct top_hash_entry *par)
{
- u32 i, *rts;
- struct ospf_lsa_net *ln;
- struct ospf_lsa_rt *rt;
- struct ospf_lsa_rt_link *rtl, *rr;
- struct top_hash_entry *tmp;
struct proto_ospf *po = oa->po;
+ struct proto *p = &po->proto;
+ struct ospf_lsa_rt_walk rtl;
+ struct top_hash_entry *tmp;
+ struct ospf_lsa_net *ln;
+ u32 i, cnt;
if (!en || !par) return 0;
it is set in process_prefixes() to any global addres in the area */
en->lb = IPA_NONE;
-#ifdef OSPFv3
en->lb_id = 0;
-#endif
- switch (en->lsa.type)
+
+ switch (en->lsa_type)
{
case LSA_T_RT:
- rt = (struct ospf_lsa_rt *) en->lsa_body;
- rr = (struct ospf_lsa_rt_link *) (rt + 1);
- for (i = 0; i < lsa_rt_count(&en->lsa); i++)
+ lsa_walk_rt_init(po, en, &rtl);
+ while (lsa_walk_rt(&rtl))
{
- rtl = (rr + i);
- switch (rtl->type)
+ switch (rtl.type)
{
case LSART_STUB:
break;
+
case LSART_NET:
-#ifdef OSPFv2
- /* In OSPFv2, rtl->id is IP addres of DR, Router ID is not known */
- tmp = ospf_hash_find_net(po->gr, oa->areaid, rtl->id);
-#else /* OSPFv3 */
- tmp = ospf_hash_find(po->gr, oa->areaid, rtl->nif, rtl->id, LSA_T_NET);
-#endif
+ tmp = ospf_hash_find_net(po->gr, oa->areaid, rtl.id, rtl.nif);
if (tmp == par)
{
-#ifdef OSPFv2
- en->lb = ipa_from_u32(rtl->data);
-#else /* OSPFv3 */
- en->lb_id = rtl->lif;
-#endif
+ if (ospf_is_v2(po))
+ en->lb = ipa_from_u32(rtl.data);
+ else
+ en->lb_id = rtl.lif;
+
return 1;
}
-
break;
+
case LSART_VLNK:
case LSART_PTP:
/* Not necessary the same link, see RFC 2328 [23] */
- tmp = ospf_hash_find_rt(po->gr, oa->areaid, rtl->id);
+ tmp = ospf_hash_find_rt(po->gr, oa->areaid, rtl.id);
if (tmp == par)
return 1;
-
- break;
- default:
- log(L_WARN "Unknown link type in router lsa. (rid = %R)", en->lsa.rt);
break;
}
}
break;
+
case LSA_T_NET:
ln = en->lsa_body;
- rts = (u32 *) (ln + 1);
- for (i = 0; i < lsa_net_count(&en->lsa); i++)
+ cnt = lsa_net_count(&en->lsa);
+ for (i = 0; i < cnt; i++)
{
- tmp = ospf_hash_find_rt(po->gr, oa->areaid, rts[i]);
+ tmp = ospf_hash_find_rt(po->gr, oa->areaid, ln->routers[i]);
if (tmp == par)
return 1;
}
break;
+
default:
- bug("Unknown lsa type %x.", en->lsa.type);
+ log(L_WARN "%s: Unknown LSA type in SPF: %d", p->name, en->lsa_type);
}
return 0;
}
struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
struct top_hash_entry *en;
- ip_addr ip = IPA_NONE;
- u32 dst_rid = 0;
- u32 metric, options;
+ ip_addr ip, abrip;
+ u32 dst_rid, metric, options;
ort *abr;
int pxlen = -1, type = -1;
+ u8 pxopts;
+
OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area (area %R)", oa->areaid);
WALK_SLIST(en, po->lsal)
{
- if ((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
+ if ((en->lsa_type != LSA_T_SUM_RT) && (en->lsa_type != LSA_T_SUM_NET))
continue;
if (en->domain != oa->areaid)
/* 16.2. (3) is handled later in ospf_rt_abr() by resetting such rt entry */
- if (en->lsa.type == LSA_T_SUM_NET)
+ if (en->lsa_type == LSA_T_SUM_NET)
{
-#ifdef OSPFv2
- struct ospf_lsa_sum *ls = en->lsa_body;
- ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
- pxlen = ipa_mklen(ls->netmask);
-#else /* OSPFv3 */
- u8 pxopts;
- u16 rest;
- struct ospf_lsa_sum_net *ls = en->lsa_body;
- lsa_get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts, &rest);
+ lsa_parse_sum_net(en, ospf_is_v2(po), &ip, &pxlen, &pxopts, &metric);
if (pxopts & OPT_PX_NU)
continue;
-#endif
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
{
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
- p->name, en->lsa.type, en->lsa.id, en->lsa.rt);
+ p->name, en->lsa_type, en->lsa.id, en->lsa.rt);
continue;
}
- metric = ls->metric & METRIC_MASK;
options = 0;
type = ORT_NET;
}
else /* 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
+ lsa_parse_sum_rt(en, ospf_is_v2(po), &dst_rid, &metric, &options);
/* We don't want local router in ASBR routing table */
if (dst_rid == po->router_id)
continue;
- metric = ls->metric & METRIC_MASK;
options |= ORTA_ASBR;
type = ORT_ROUTER;
}
continue;
/* 16.2. (4) */
- ip_addr abrip = ipa_from_rid(en->lsa.rt);
+ abrip = ipa_from_rid(en->lsa.rt);
abr = (ort *) fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH);
if (!abr || !abr->n.type)
continue;
static void
ospf_rt_sum_tr(struct ospf_area *oa)
{
- struct proto *p = &oa->po->proto;
struct proto_ospf *po = oa->po;
+ struct proto *p = &po->proto;
struct ospf_area *bb = po->backbone;
- ip_addr abrip;
struct top_hash_entry *en;
- u32 dst_rid, metric;
- ort *re = NULL, *abr;
+ ort *re, *abr;
+ ip_addr ip, abrip;
+ u32 dst_rid, metric, options;
+ int pxlen;
+ u8 pxopts;
- if (!bb) return;
+ if (!bb)
+ return;
WALK_SLIST(en, po->lsal)
{
- if ((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
+ if ((en->lsa_type != LSA_T_SUM_RT) && (en->lsa_type != LSA_T_SUM_NET))
continue;
if (en->domain != oa->areaid)
if (en->lsa.rt == po->router_id)
continue;
- if (en->lsa.type == LSA_T_SUM_NET)
+ if (en->lsa_type == LSA_T_SUM_NET)
{
- ip_addr ip;
- int pxlen;
-#ifdef OSPFv2
- struct ospf_lsa_sum *ls = en->lsa_body;
- ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
- pxlen = ipa_mklen(ls->netmask);
-#else /* OSPFv3 */
- u8 pxopts;
- u16 rest;
- struct ospf_lsa_sum_net *ls = en->lsa_body;
- lsa_get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts, &rest);
+ lsa_parse_sum_net(en, ospf_is_v2(po), &ip, &pxlen, &pxopts, &metric);
if (pxopts & OPT_PX_NU)
continue;
-#endif
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
{
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
- p->name, en->lsa.type, en->lsa.id, en->lsa.rt);
+ p->name, en->lsa_type, en->lsa.id, en->lsa.rt);
continue;
}
- metric = ls->metric & METRIC_MASK;
re = fib_find(&po->rtf, &ip, pxlen);
}
- else // en->lsa.type == LSA_T_SUM_RT
+ else // en->lsa_type == LSA_T_SUM_RT
{
-#ifdef OSPFv2
- struct ospf_lsa_sum *ls = en->lsa_body;
- dst_rid = en->lsa.id;
-#else /* OSPFv3 */
- struct ospf_lsa_sum_rt *ls = en->lsa_body;
- dst_rid = ls->drid;
-#endif
+ lsa_parse_sum_rt(en, ospf_is_v2(po), &dst_rid, &metric, &options);
- metric = ls->metric & METRIC_MASK;
- ip_addr ip = ipa_from_rid(dst_rid);
+ ip = ipa_from_rid(dst_rid);
re = fib_find(&bb->rtr, &ip, MAX_PREFIX_LENGTH);
}
}
static inline int
-decide_nssa_lsa(ort *nf, u32 *rt_metric, ip_addr *rt_fwaddr, u32 *rt_tag)
+decide_nssa_lsa(struct proto_ospf *po, ort *nf, u32 *rt_metric, ip_addr *rt_fwaddr, u32 *rt_tag)
{
struct ospf_area *oa = nf->n.oa;
struct top_hash_entry *en = nf->n.en;
- int propagate;
+ struct ospf_lsa_ext_local rt;
if (!rt_is_nssa(nf) || !oa->translate)
return 0;
if (fib_route(&oa->enet_fib, &nf->fn.prefix, nf->fn.pxlen))
return 0;
- if (!en || (en->lsa.type != LSA_T_NSSA))
+ if (!en || (en->lsa_type != LSA_T_NSSA))
return 0;
/* We do not store needed data in struct orta, we have to parse the LSA */
- struct ospf_lsa_ext *le = en->lsa_body;
-
-#ifdef OSPFv2
- *rt_fwaddr = le->fwaddr;
- *rt_tag = le->tag;
- propagate = en->lsa.options & OPT_P;
-#else /* OSPFv3 */
- u32 *buf = le->rest;
- u8 pxlen = (*buf >> 24);
- u8 pxopts = (*buf >> 16);
- buf += IPV6_PREFIX_WORDS(pxlen); /* Skip the IP prefix */
-
- if (pxopts & OPT_PX_NU)
+ lsa_parse_ext(en, ospf_is_v2(po), &rt);
+
+ if (rt.pxopts & OPT_PX_NU)
return 0;
- if (le->metric & LSA_EXT_FBIT)
- buf = lsa_get_ipv6_addr(buf, rt_fwaddr);
- else
- *rt_fwaddr = IPA_NONE;
-
- if (le->metric & LSA_EXT_TBIT)
- *rt_tag = *buf++;
- else
- *rt_tag = 0;
-
- propagate = pxopts & OPT_PX_P;
-#endif
-
- if (!propagate || ipa_zero(*rt_fwaddr))
+ if (!rt.propagate || ipa_zero(rt.fwaddr))
return 0;
- *rt_metric = le->metric & (METRIC_MASK | LSA_EXT_EBIT);
+ *rt_metric = rt.metric | rt.ebit;
+ *rt_fwaddr = rt.fwaddr;
+ *rt_tag = rt.tag;
return 1;
}
originate_ext_lsa(po->backbone, fn, EXT_NSSA, anet->metric, IPA_NONE, anet->tag, 0);
/* RFC 3103 3.2 (2) - originate the same network */
- else if (decide_nssa_lsa(nf, &rt_metric, &rt_fwaddr, &rt_tag))
+ else if (decide_nssa_lsa(po, nf, &rt_metric, &rt_fwaddr, &rt_tag))
originate_ext_lsa(po->backbone, fn, EXT_NSSA, rt_metric, rt_fwaddr, rt_tag, 0);
else if (fn->flags & OSPF_RT_NSSA)
static void
ospf_check_vlinks(struct proto_ospf *po)
{
- struct proto *p = &po->proto;
-
struct ospf_iface *iface;
WALK_LIST(iface, po->iface_list)
{
static void
ospf_ext_spf(struct proto_ospf *po)
{
+ struct proto *p = &po->proto;
+ struct top_hash_entry *en;
+ struct ospf_lsa_ext_local rt;
ort *nf1, *nf2;
orta nfa;
- struct top_hash_entry *en;
- struct proto *p = &po->proto;
- struct ospf_lsa_ext *le;
- int pxlen, ebit, rt_fwaddr_valid, rt_propagate;
- ip_addr ip, rtid, rt_fwaddr;
- u32 br_metric, rt_metric, rt_tag;
+ ip_addr rtid;
+ u32 br_metric;
struct ospf_area *atmp;
struct mpnh* nhs = NULL;
WALK_SLIST(en, po->lsal)
{
/* 16.4. (1) */
- if ((en->lsa.type != LSA_T_EXT) && (en->lsa.type != LSA_T_NSSA))
+ if ((en->lsa_type != LSA_T_EXT) && (en->lsa_type != LSA_T_NSSA))
continue;
if (en->lsa.age == LSA_MAXAGE)
continue;
DBG("%s: Working on LSA. ID: %R, RT: %R, Type: %u\n",
- p->name, en->lsa.id, en->lsa.rt, en->lsa.type);
-
- le = en->lsa_body;
+ p->name, en->lsa.id, en->lsa.rt, en->lsa_type);
- rt_metric = le->metric & METRIC_MASK;
- ebit = le->metric & LSA_EXT_EBIT;
+ lsa_parse_ext(en, ospf_is_v2(po), &rt);
- if (rt_metric == LSINFINITY)
+ if (rt.metric == LSINFINITY)
continue;
-#ifdef OSPFv2
- ip = ipa_and(ipa_from_u32(en->lsa.id), le->netmask);
- pxlen = ipa_mklen(le->netmask);
- rt_fwaddr = le->fwaddr;
- rt_fwaddr_valid = !ipa_equal(rt_fwaddr, IPA_NONE);
- rt_tag = le->tag;
- rt_propagate = en->lsa.options & OPT_P;
-#else /* OSPFv3 */
- u8 pxopts;
- u16 rest;
- u32 *buf = le->rest;
- buf = lsa_get_ipv6_prefix(buf, &ip, &pxlen, &pxopts, &rest);
-
- if (pxopts & OPT_PX_NU)
+ if (rt.pxopts & OPT_PX_NU)
continue;
- rt_fwaddr_valid = le->metric & LSA_EXT_FBIT;
- if (rt_fwaddr_valid)
- buf = lsa_get_ipv6_addr(buf, &rt_fwaddr);
- else
- rt_fwaddr = IPA_NONE;
-
- if (le->metric & LSA_EXT_TBIT)
- rt_tag = *buf++;
- else
- rt_tag = 0;
-
- rt_propagate = pxopts & OPT_PX_P;
-#endif
-
- if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
+ if (rt.pxlen < 0 || rt.pxlen > MAX_PREFIX_LENGTH)
{
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
- p->name, en->lsa.type, en->lsa.id, en->lsa.rt);
+ p->name, en->lsa_type, en->lsa.id, en->lsa.rt);
continue;
}
/* If there are more areas, we already precomputed preferred ASBR
entries in ospf_rt_abr1() and stored them in the backbone
table. For NSSA, we examine the area to which the LSA is assigned */
- if (en->lsa.type == LSA_T_EXT)
+ if (en->lsa_type == LSA_T_EXT)
atmp = ospf_main_area(po);
else /* NSSA */
atmp = ospf_find_area(po, en->domain);
/* 16.4. (3) NSSA - special rule for default routes */
/* ABR should use default only if P-bit is set and summaries are active */
- if ((en->lsa.type == LSA_T_NSSA) && ipa_zero(ip) && (pxlen == 0) &&
- (po->areano > 1) && !(rt_propagate && atmp->ac->summary))
+ if ((en->lsa_type == LSA_T_NSSA) && ipa_zero(rt.ip) && (rt.pxlen == 0) &&
+ (po->areano > 1) && !(rt.propagate && atmp->ac->summary))
continue;
- if (!rt_fwaddr_valid)
+ if (!rt.fbit)
{
nf2 = nf1;
nhs = nf1->n.nhs;
}
else
{
- nf2 = ospf_fib_route(&po->rtf, rt_fwaddr, MAX_PREFIX_LENGTH);
+ nf2 = ospf_fib_route(&po->rtf, rt.fwaddr, MAX_PREFIX_LENGTH);
if (!nf2)
continue;
- if (en->lsa.type == LSA_T_EXT)
+ if (en->lsa_type == LSA_T_EXT)
{
/* For ext routes, we accept intra-area or inter-area routes */
if ((nf2->n.type != RTS_OSPF) && (nf2->n.type != RTS_OSPF_IA))
nhs = nf2->n.nhs;
/* If gw is zero, it is a device route */
if (ipa_zero(nhs->gw))
- nhs = new_nexthop(po, rt_fwaddr, nhs->iface, nhs->weight);
+ nhs = new_nexthop(po, rt.fwaddr, nhs->iface, nhs->weight);
br_metric = nf2->n.metric1;
}
- if (ebit)
+ if (rt.ebit)
{
nfa.type = RTS_OSPF_EXT2;
nfa.metric1 = br_metric;
- nfa.metric2 = rt_metric;
+ nfa.metric2 = rt.metric;
}
else
{
nfa.type = RTS_OSPF_EXT1;
- nfa.metric1 = br_metric + rt_metric;
+ nfa.metric1 = br_metric + rt.metric;
nfa.metric2 = LSINFINITY;
}
/* Whether the route is preferred in route selection according to 16.4.1 */
nfa.options = epath_preferred(&nf2->n) ? ORTA_PREF : 0;
- if (en->lsa.type == LSA_T_NSSA)
+ if (en->lsa_type == LSA_T_NSSA)
{
nfa.options |= ORTA_NSSA;
- if (rt_propagate)
+ if (rt.propagate)
nfa.options |= ORTA_PROP;
}
- nfa.tag = rt_tag;
+ nfa.tag = rt.tag;
nfa.rid = en->lsa.rt;
nfa.oa = atmp; /* undefined in RFC 2328 */
nfa.voa = NULL;
nfa.nhs = nhs;
nfa.en = en; /* store LSA for later (NSSA processing) */
- ri_install_ext(po, ip, pxlen, &nfa);
+ ri_install_ext(po, rt.ip, rt.pxlen, &nfa);
}
}
void
ospf_rt_spf(struct proto_ospf *po)
{
- struct proto *p = &po->proto;
struct ospf_area *oa;
if (po->areano == 0)
/* 16.1.1. The next hop calculation */
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);
/* Usually, we inherit parent nexthops */
if (inherit_nexthops(pn))
*/
/* The first case - local network */
- if ((en->lsa.type == LSA_T_NET) && (par == oa->rt))
+ if ((en->lsa_type == LSA_T_NET) && (par == oa->rt))
{
ifa = rt_pos_to_ifa(oa, pos);
if (!ifa)
}
/* The second case - ptp or ptmp neighbor */
- if ((en->lsa.type == LSA_T_RT) && (par == oa->rt))
+ if ((en->lsa_type == LSA_T_RT) && (par == oa->rt))
{
ifa = rt_pos_to_ifa(oa, pos);
if (!ifa)
}
/* The third case - bcast or nbma neighbor */
- if ((en->lsa.type == LSA_T_RT) && (par->lsa.type == LSA_T_NET))
+ if ((en->lsa_type == LSA_T_RT) && (par->lsa_type == LSA_T_NET))
{
/* par->nhi should be defined from parent's calc_next_hop() */
if (!pn)
goto bad;
-#ifdef OSPFv2
- /*
- * In this case, next-hop is the same as link-back, which is
- * already computed in link_back().
- */
- if (ipa_zero(en->lb))
- goto bad;
-
- return new_nexthop(po, en->lb, pn->iface, pn->weight);
+ if (ospf_is_v2(po))
+ {
+ /*
+ * In this case, next-hop is the same as link-back, which is
+ * already computed in link_back().
+ */
+ if (ipa_zero(en->lb))
+ goto bad;
-#else /* OSPFv3 */
- /*
- * Next-hop is taken from lladdr field of Link-LSA, en->lb_id
- * is computed in link_back().
- */
- struct top_hash_entry *lhe;
- lhe = ospf_hash_find(po->gr, pn->iface->index, en->lb_id, rid, LSA_T_LINK);
+ return new_nexthop(po, en->lb, pn->iface, pn->weight);
+ }
+ else /* OSPFv3 */
+ {
+ /*
+ * Next-hop is taken from lladdr field of Link-LSA, en->lb_id
+ * is computed in link_back().
+ */
+ struct top_hash_entry *lhe;
+ lhe = ospf_hash_find(po->gr, pn->iface->index, en->lb_id, rid, LSA_T_LINK);
- if (!lhe)
- return NULL;
+ if (!lhe)
+ return NULL;
- struct ospf_lsa_link *llsa = lhe->lsa_body;
+ struct ospf_lsa_link *llsa = lhe->lsa_body;
- if (ipa_zero(llsa->lladdr))
- return NULL;
+ if (ipa_zero(llsa->lladdr))
+ return NULL;
- return new_nexthop(po, llsa->lladdr, pn->iface, pn->weight);
-#endif
+ return new_nexthop(po, llsa->lladdr, pn->iface, pn->weight);
+ }
}
bad:
if (en->lsa.age == LSA_MAXAGE)
return;
-#ifdef OSPFv3
- if (en->lsa.type == LSA_T_RT)
+ if (ospf_is_v3(po) && (en->lsa_type == LSA_T_RT))
{
+ /* In OSPFv3, check V6 and R flags */
struct ospf_lsa_rt *rt = en->lsa_body;
if (!(rt->options & OPT_V6) || !(rt->options & OPT_R))
return;
}
-#endif
/* 16.1. (2c) */
if (en->color == INSPF)
if (!nhs)
{
log(L_WARN "Cannot find next hop for LSA (Type: %04x, Id: %R, Rt: %R)",
- en->lsa.type, en->lsa.id, en->lsa.rt);
+ en->lsa_type, en->lsa.id, en->lsa.rt);
return;
}
}
DBG(" Adding candidate: rt: %R, id: %R, type: %u\n",
- en->lsa.rt, en->lsa.id, en->lsa.type);
+ en->lsa.rt, en->lsa.id, en->lsa_type);
if (en->color == CANDIDATE)
{ /* We found a shorter path */
{
act = SKIP_BACK(struct top_hash_entry, cn, n);
if ((act->dist > dist) ||
- ((act->dist == dist) && (act->lsa.type == LSA_T_RT)))
+ ((act->dist == dist) && (act->lsa_type == LSA_T_RT)))
{
if (prev == NULL)
add_head(l, &en->cn);
if (en->lsa.sn == LSA_MAXSEQNO)
{
log(L_WARN "OSPF: Premature origination of LSA (Type: %04x, Id: %R, Rt: %R)",
- en->lsa.type, en->lsa.id, en->lsa.rt);
+ en->lsa_type, en->lsa.id, en->lsa.rt);
return LSA_INITSEQNO;
}
}
+/*
+ * Router-LSA handling
+ * Type = LSA_T_RT
+ */
+
static int
configured_stubnet(struct ospf_area *oa, struct ifa *a)
{
return 0;
}
+static inline u32
+get_rt_options(struct proto_ospf *po, struct ospf_area *oa, int bitv)
+{
+ u32 opts = 0;
-#ifdef OSPFv2
+ if (po->areano > 1)
+ opts |= OPT_RT_B;
+
+ if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
+ opts |= OPT_RT_NT;
+
+ if (po->ebit && !oa_is_stub(oa))
+ opts |= OPT_RT_E;
+
+ if (bitv)
+ opts |= OPT_RT_V;
+
+ return opts;
+}
+
+static inline void
+add_rt2_lsa_link(struct proto_ospf *po, u8 type, u32 id, u32 data, u16 metric)
+{
+ struct ospf_lsa_rt2_link *ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt2_link));
+ ln->type = type;
+ ln->id = id;
+ ln->data = data;
+ ln->metric = metric;
+ ln->no_tos = 0;
+}
static void *
-originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
+originate_rt2_lsa_body(struct ospf_area *oa, u16 *length)
{
struct proto_ospf *po = oa->po;
struct ospf_iface *ifa;
int i = 0, bitv = 0;
- struct ospf_lsa_rt *rt;
- struct ospf_lsa_rt_link *ln;
struct ospf_neighbor *neigh;
ASSERT(po->lsab_used == 0);
- rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
-
- rt->options = 0;
-
- if (po->areano > 1)
- rt->options |= OPT_RT_B;
-
- if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
- rt->options |= OPT_RT_NT;
-
- if (po->ebit && !oa_is_stub(oa))
- rt->options |= OPT_RT_E;
-
- rt = NULL; /* buffer might be reallocated later */
+ lsab_allocz(po, sizeof(struct ospf_lsa_rt));
+ /* ospf_lsa_rt header will be filled later */
WALK_LIST(ifa, po->iface_list)
{
WALK_LIST(neigh, ifa->neigh_list)
if (neigh->state == NEIGHBOR_FULL)
{
- ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
- ln->type = LSART_PTP;
- ln->id = neigh->rid;
- ln->data = (ifa->addr->flags & IA_PEER) ?
- ifa->iface->index : ipa_to_u32(ifa->addr->ip);
- ln->metric = ifa->cost;
- ln->padding = 0;
+ u32 data = (ifa->addr->flags & IA_PEER) ? ifa->iface->index : ipa_to_u32(ifa->addr->ip);
+ add_rt2_lsa_link(po, LSART_PTP, neigh->rid, data, ifa->cost);
i++;
}
break;
case OSPF_IT_NBMA:
if (bcast_net_active(ifa))
{
- ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
- ln->type = LSART_NET;
- ln->id = ipa_to_u32(ifa->drip);
- ln->data = ipa_to_u32(ifa->addr->ip);
- ln->metric = ifa->cost;
- ln->padding = 0;
+ add_rt2_lsa_link(po, LSART_NET, ipa_to_u32(ifa->drip), ipa_to_u32(ifa->addr->ip), ifa->cost);
i++;
net_lsa = 1;
}
case OSPF_IT_VLINK:
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
- {
- ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
- ln->type = LSART_VLNK;
- ln->id = neigh->rid;
- ln->data = ipa_to_u32(ifa->addr->ip);
- ln->metric = ifa->cost;
- ln->padding = 0;
- i++;
- }
+ add_rt2_lsa_link(po, LSART_VLNK, neigh->rid, ipa_to_u32(ifa->addr->ip), ifa->cost), i++;
break;
default:
configured_stubnet(oa, ifa->addr))
continue;
- ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
+ /* Host or network stub entry */
if ((ifa->addr->flags & IA_HOST) ||
(ifa->state == OSPF_IS_LOOP) ||
(ifa->type == OSPF_IT_PTMP))
- {
- /* Host stub entry */
- ln->type = LSART_STUB;
- ln->id = ipa_to_u32(ifa->addr->ip);
- ln->data = 0xffffffff;
- ln->metric = 0;
- ln->padding = 0;
- }
+ add_rt2_lsa_link(po, LSART_STUB, ipa_to_u32(ifa->addr->ip), 0xffffffff, 0);
else
- {
- /* Network stub entry */
- ln->type = LSART_STUB;
- ln->id = ipa_to_u32(ifa->addr->prefix);
- ln->data = ipa_to_u32(ipa_mkmask(ifa->addr->pxlen));
- ln->metric = ifa->cost;
- ln->padding = 0;
- }
+ add_rt2_lsa_link(po, LSART_STUB, ipa_to_u32(ifa->addr->prefix), u32_mkmask(ifa->addr->pxlen), ifa->cost);
i++;
ifa->rt_pos_end = i;
}
struct ospf_stubnet_config *sn;
- if (oa->ac)
+ if (oa->ac) // XXXX ???
WALK_LIST(sn, oa->ac->stubnet_list)
if (!sn->hidden)
- {
- ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
- ln->type = LSART_STUB;
- ln->id = ipa_to_u32(sn->px.addr);
- ln->data = ipa_to_u32(ipa_mkmask(sn->px.len));
- ln->metric = sn->cost;
- ln->padding = 0;
- i++;
- }
-
- rt = po->lsab;
- rt->links = i;
+ add_rt2_lsa_link(po, LSART_STUB, ipa_to_u32(sn->px.addr), u32_mkmask(sn->px.len), sn->cost), i++;
- if (bitv)
- rt->options |= OPT_RT_V;
+ struct ospf_lsa_rt *rt = po->lsab;
+ /* Store number of links in lower half of options */
+ rt->options = get_rt_options(po, oa, bitv) | (u16) i;
- *length = po->lsab_used + sizeof(struct ospf_lsa_header);
+ *length = sizeof(struct ospf_lsa_header) + po->lsab_used;
return lsab_flush(po);
}
-#else /* OSPFv3 */
-
-static void
-add_lsa_rt_link(struct proto_ospf *po, struct ospf_iface *ifa, u8 type, u32 nif, u32 id)
+static inline void
+add_rt3_lsa_link(struct proto_ospf *po, u8 type, struct ospf_iface *ifa, u32 nif, u32 id)
{
- struct ospf_lsa_rt_link *ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
+ struct ospf_lsa_rt3_link *ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt3_link));
ln->type = type;
ln->padding = 0;
ln->metric = ifa->cost;
}
static void *
-originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
+originate_rt3_lsa_body(struct ospf_area *oa, u16 *length)
{
struct proto_ospf *po = oa->po;
struct ospf_iface *ifa;
+ struct ospf_neighbor *neigh;
int bitv = 0;
int i = 0;
- struct ospf_lsa_rt *rt;
- struct ospf_neighbor *neigh;
ASSERT(po->lsab_used == 0);
- rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
-
- rt->options = oa->options & OPTIONS_MASK;
-
- if (po->areano > 1)
- rt->options |= OPT_RT_B;
-
- if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator)
- rt->options |= OPT_RT_NT;
-
- if (po->ebit && !oa_is_stub(oa))
- rt->options |= OPT_RT_E;
-
- rt = NULL; /* buffer might be reallocated later */
+ lsab_allocz(po, sizeof(struct ospf_lsa_rt));
+ /* ospf_lsa_rt header will be filled later */
WALK_LIST(ifa, po->iface_list)
{
case OSPF_IT_PTMP:
WALK_LIST(neigh, ifa->neigh_list)
if (neigh->state == NEIGHBOR_FULL)
- add_lsa_rt_link(po, ifa, LSART_PTP, neigh->iface_id, neigh->rid), i++;
+ add_rt3_lsa_link(po, LSART_PTP, ifa, neigh->iface_id, neigh->rid), i++;
break;
case OSPF_IT_BCAST:
case OSPF_IT_NBMA:
if (bcast_net_active(ifa))
- add_lsa_rt_link(po, ifa, LSART_NET, ifa->dr_iface_id, ifa->drid), i++;
+ add_rt3_lsa_link(po, LSART_NET, ifa, ifa->dr_iface_id, ifa->drid), i++;
break;
case OSPF_IT_VLINK:
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
- add_lsa_rt_link(po, ifa, LSART_VLNK, neigh->iface_id, neigh->rid), i++;
+ add_rt3_lsa_link(po, LSART_VLNK, ifa, neigh->iface_id, neigh->rid), i++;
break;
default:
ifa->rt_pos_end = i;
}
- if (bitv)
- {
- rt = po->lsab;
- rt->options |= OPT_RT_V;
- }
+ struct ospf_lsa_rt *rt = po->lsab;
+ rt->options = get_rt_options(po, oa, bitv) | (oa->options & OPTIONS_MASK);
*length = po->lsab_used + sizeof(struct ospf_lsa_header);
return lsab_flush(po);
}
-#endif
+static inline void *
+originate_rt_lsa_body(struct proto_ospf *po, struct ospf_area *oa, u16 *length)
+{
+ return ospf_is_v2(po) ?
+ originate_rt2_lsa_body(oa, length) :
+ originate_rt3_lsa_body(oa, length);
+}
/**
* originate_rt_lsa - build new instance of router LSA
void
originate_rt_lsa(struct ospf_area *oa)
{
- struct ospf_lsa_header lsa;
struct proto_ospf *po = oa->po;
- struct proto *p = &po->proto;
+ struct ospf_lsa_header lsa;
+ u32 dom = oa->areaid;
void *body;
OSPF_TRACE(D_EVENTS, "Originating router-LSA for area %R", oa->areaid);
lsa.age = 0;
- lsa.type = LSA_T_RT;
-
-#ifdef OSPFv2
- lsa.options = oa->options;
- lsa.id = po->router_id;
-#else /* OSPFv3 */
- lsa.id = 0;
-#endif
-
+ lsa.type_raw = LSA_T_RT;
+ lsa.id = ospf_is_v2(po) ? po->router_id : 0;
lsa.rt = po->router_id;
lsa.sn = get_seqnum(oa->rt);
- u32 dom = oa->areaid;
+ lsa_fix_options(po, &lsa, oa->options);
- body = originate_rt_lsa_body(oa, &lsa.length);
+ body = originate_rt_lsa_body(po, oa, &lsa.length);
lsasum_calculate(&lsa, body);
oa->rt = lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
*/
originate_rt_lsa(oa);
-#ifdef OSPFv3
- originate_prefix_rt_lsa(oa);
-#endif
+ if (ospf_is_v3(po))
+ originate_prefix_rt_lsa(oa);
schedule_rtcalc(po);
oa->origrt = 0;
}
+
+/*
+ * Net-LSA handling
+ * Type = LSA_T_NET
+ */
+
static void *
-originate_net_lsa_body(struct ospf_iface *ifa, u16 *length,
- struct proto_ospf *po)
+originate_net2_lsa_body(struct proto_ospf *po, struct ospf_iface *ifa, u16 *length)
{
- u16 i = 1;
struct ospf_neighbor *n;
- struct ospf_lsa_net *net;
int nodes = ifa->fadj + 1;
+ int bsize = sizeof(struct ospf_lsa_net) + nodes * sizeof(u32);
+ u16 i = 1;
- net = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_net)
- + nodes * sizeof(u32));
+ struct ospf_lsa_net *net = mb_alloc(po->proto.pool, bsize);
+ *length = sizeof(struct ospf_lsa_header) + bsize;
-#ifdef OSPFv2
- net->netmask = ipa_mkmask(ifa->addr->pxlen);
-#endif
+ net->optx = u32_mkmask(ifa->addr->pxlen);
+ net->routers[0] = po->router_id;
-#ifdef OSPFv3
- /* In OSPFv3, we would like to merge options from Link LSAs of added neighbors */
+ WALK_LIST(n, ifa->neigh_list)
+ {
+ if (n->state == NEIGHBOR_FULL)
+ {
+ net->routers[i] = n->rid;
+ i++;
+ }
+ }
+ ASSERT(i == nodes);
+
+ return net;
+}
+
+static void *
+originate_net3_lsa_body(struct proto_ospf *po, struct ospf_iface *ifa, u16 *length)
+{
struct top_hash_entry *en;
+ struct ospf_neighbor *n;
+ int nodes = ifa->fadj + 1;
+ int bsize = sizeof(struct ospf_lsa_net) + nodes * sizeof(u32);
u32 options = 0;
-#endif
+ u16 i = 1;
+
+ struct ospf_lsa_net *net = mb_alloc(po->proto.pool, bsize);
+ *length = sizeof(struct ospf_lsa_header) + bsize;
net->routers[0] = po->router_id;
{
if (n->state == NEIGHBOR_FULL)
{
-#ifdef OSPFv3
+ /* In OSPFv3, we would like to merge options from Link LSAs of added neighbors */
en = ospf_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK);
if (en)
options |= ((struct ospf_lsa_link *) en->lsa_body)->options;
-#endif
net->routers[i] = n->rid;
i++;
}
ASSERT(i == nodes);
-#ifdef OSPFv3
- net->options = options & OPTIONS_MASK;
-#endif
+ net->optx = options & OPTIONS_MASK;
- *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_net)
- + nodes * sizeof(u32);
return net;
}
+static inline void *
+originate_net_lsa_body(struct proto_ospf *po, struct ospf_iface *ifa, u16 *length)
+{
+ return ospf_is_v2(po) ?
+ originate_net2_lsa_body(po, ifa, length) :
+ originate_net3_lsa_body(po, ifa, length);
+}
+
/**
* originate_net_lsa - originates of deletes network LSA
originate_net_lsa(struct ospf_iface *ifa)
{
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
struct ospf_lsa_header lsa;
u32 dom = ifa->oa->areaid;
-
void *body;
OSPF_TRACE(D_EVENTS, "Originating network-LSA for iface %s",
ifa->iface->name);
lsa.age = 0;
- lsa.type = LSA_T_NET;
-
-#ifdef OSPFv2
- lsa.options = ifa->oa->options;
- lsa.id = ipa_to_u32(ifa->addr->ip);
-#else /* OSPFv3 */
- lsa.id = ifa->iface->index;
-#endif
-
+ lsa.type_raw = LSA_T_NET;
+ lsa.id = ospf_is_v2(po) ? ipa_to_u32(ifa->addr->ip) : ifa->iface->index;
lsa.rt = po->router_id;
lsa.sn = get_seqnum(ifa->net_lsa);
+ lsa_fix_options(po, &lsa, ifa->oa->options);
- body = originate_net_lsa_body(ifa, &lsa.length, po);
+ body = originate_net_lsa_body(po, ifa, &lsa.length);
lsasum_calculate(&lsa, body);
ifa->net_lsa = lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
flush_net_lsa(struct ospf_iface *ifa)
{
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
u32 dom = ifa->oa->areaid;
if (ifa->net_lsa == NULL)
OSPF_TRACE(D_EVENTS, "Flushing network-LSA for iface %s",
ifa->iface->name);
+
ifa->net_lsa->lsa.sn += 1;
ifa->net_lsa->lsa.age = LSA_MAXAGE;
lsasum_calculate(&ifa->net_lsa->lsa, ifa->net_lsa->lsa_body);
if ((ifa->state != OSPF_IS_DR) || (ifa->fadj == 0))
{
flush_net_lsa(ifa);
-#ifdef OSPFv3
- flush_prefix_net_lsa(ifa);
-#endif
+ if (ospf_is_v3(po))
+ flush_prefix_net_lsa(ifa);
}
else
{
originate_net_lsa(ifa);
-#ifdef OSPFv3
- originate_prefix_net_lsa(ifa);
-#endif
+ if (ospf_is_v3(po))
+ originate_prefix_net_lsa(ifa);
}
schedule_rtcalc(po);
ifa->orignet = 0;
}
-#ifdef OSPFv2
+
+/*
+ * (Net|Rt)-summary-LSA handling
+ * (a.k.a. Inter-Area-(Prefix|Router)-LSA)
+ * Type = LSA_T_SUM_NET, LSA_T_SUM_RT
+ */
static inline void *
-originate_sum_lsa_body(struct proto_ospf *po, u16 *length, u32 mlen, u32 metric)
+originate_sum2_lsa_body(struct proto_ospf *po, u16 *length, u32 mlen, u32 metric)
{
- struct ospf_lsa_sum *sum = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_sum));
- *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_sum);
+ struct ospf_lsa_sum2 *sum = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_sum2));
+ *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_sum2);
- sum->netmask = ipa_mkmask(mlen);
+ sum->netmask = ip4_mkmask(mlen);
sum->metric = metric;
return sum;
}
-#define originate_sum_net_lsa_body(po,length,fn,metric) \
- originate_sum_lsa_body(po, length, (fn)->pxlen, metric)
+static inline void *
+originate_sum3_net_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn, u32 metric)
+{
+ int bsize = sizeof(struct ospf_lsa_sum3_net) + IPV6_PREFIX_SPACE(fn->pxlen);
+ struct ospf_lsa_sum3_net *sum = mb_alloc(po->proto.pool, bsize);
+ *length = sizeof(struct ospf_lsa_header) + bsize;
-#define originate_sum_rt_lsa_body(po,length,drid,metric,options) \
- originate_sum_lsa_body(po, length, 0, metric)
+ sum->metric = metric;
+ put_ipv6_prefix(sum->prefix, fn->prefix, fn->pxlen, 0, 0);
-static inline int
-check_sum_net_lsaid_collision(struct fib_node *fn, struct top_hash_entry *en)
-{
- struct ospf_lsa_sum *sum = en->lsa_body;
- return fn->pxlen != ipa_mklen(sum->netmask);
+ return sum;
}
-static inline int
-check_sum_lsa_same(struct top_hash_entry *en, u32 metric)
+static inline void *
+originate_sum3_rt_lsa_body(struct proto_ospf *po, u16 *length, u32 drid, u32 metric, u32 options)
{
- /* Netmask already checked in check_sum_net_lsaid_collision() */
- struct ospf_lsa_sum *sum = en->lsa_body;
- return (en->lsa.sn != LSA_MAXSEQNO) && (sum->metric == metric);
-}
-
-#define check_sum_net_lsa_same(en,metric) \
- check_sum_lsa_same(en, metric)
-
-#define check_sum_rt_lsa_same(en,drid,metric,options) \
- check_sum_lsa_same(en, metric)
+ struct ospf_lsa_sum3_rt *sum = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_sum3_rt));
+ *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_sum3_rt);
+ sum->options = options;
+ sum->metric = metric;
+ sum->drid = drid;
-#else /* OSPFv3 */
+ return sum;
+}
static inline void *
originate_sum_net_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn, u32 metric)
{
- int size = sizeof(struct ospf_lsa_sum_net) + IPV6_PREFIX_SPACE(fn->pxlen);
- struct ospf_lsa_sum_net *sum = mb_alloc(po->proto.pool, size);
- *length = sizeof(struct ospf_lsa_header) + size;
+ return ospf_is_v2(po) ?
+ originate_sum2_lsa_body(po, length, fn->pxlen, metric) :
+ originate_sum3_net_lsa_body(po, length, fn, metric);
+}
- sum->metric = metric;
- put_ipv6_prefix(sum->prefix, fn->prefix, fn->pxlen, 0, 0);
+static inline void *
+originate_sum_rt_lsa_body(struct proto_ospf *po, u16 *length, u32 drid, u32 metric, u32 options)
+{
+ return ospf_is_v2(po) ?
+ originate_sum2_lsa_body(po, length, 0, metric) :
+ originate_sum3_rt_lsa_body(po, length, drid, metric, options);
+}
- return sum;
+
+static inline int
+check_sum2_net_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric)
+{
+ struct ospf_lsa_sum2 *sum = en->lsa_body;
+
+ /* LSAID collision */
+ if (fn->pxlen != ip4_masklen(sum->netmask))
+ return -1;
+
+ return (en->lsa.sn != LSA_MAXSEQNO) && (sum->metric == metric);
}
static inline int
-check_sum_net_lsaid_collision(struct fib_node *fn, struct top_hash_entry *en)
+check_sum3_net_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric)
{
- struct ospf_lsa_sum_net *sum = en->lsa_body;
- ip_addr prefix;
+ struct ospf_lsa_sum3_net *sum = en->lsa_body;
+ ip6_addr prefix;
int pxlen;
u8 pxopts;
u16 rest;
-
lsa_get_ipv6_prefix(sum->prefix, &prefix, &pxlen, &pxopts, &rest);
- return (fn->pxlen != pxlen) || !ipa_equal(fn->prefix, prefix);
-}
-static inline int
-check_sum_net_lsa_same(struct top_hash_entry *en, u32 metric)
-{
- /* Prefix already checked in check_sum_net_lsaid_collision() */
- struct ospf_lsa_sum_net *sum = en->lsa_body;
+ /* LSAID collision */
+ if ((fn->pxlen != pxlen) || !ip6_equal(fn->prefix, prefix))
+ return -1;
+
return (en->lsa.sn != LSA_MAXSEQNO) && (sum->metric == metric);
}
-static inline void *
-originate_sum_rt_lsa_body(struct proto_ospf *po, u16 *length, u32 drid, u32 metric, u32 options)
+static int
+check_sum_net_lsa(struct proto_ospf *po, struct top_hash_entry *en, struct fib_node *fn, u32 metric)
{
- struct ospf_lsa_sum_rt *sum = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_sum_rt));
- *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_sum_rt);
+ int rv = ospf_is_v2(po) ?
+ check_sum2_net_lsa(en, fn, metric) :
+ check_sum3_net_lsa(en, fn, metric);
- sum->options = options;
- sum->metric = metric;
- sum->drid = drid;
+ if (rv < 0)
+ log(L_ERR "%s: LSAID collision for %I/%d", po->proto.name, fn->prefix, fn->pxlen);
- return sum;
+ return rv;
}
-static inline int
-check_sum_rt_lsa_same(struct top_hash_entry *en, u32 drid, u32 metric, u32 options)
+static int
+check_sum_rt_lsa(struct proto_ospf *po, struct top_hash_entry *en, u32 drid, u32 metric, u32 options)
{
- struct ospf_lsa_sum_rt *sum = en->lsa_body;
- return (en->lsa.sn != LSA_MAXSEQNO) && (sum->options == options) &&
- (sum->metric == metric) && (sum->drid == drid);
+ if (en->lsa.sn == LSA_MAXSEQNO)
+ return 0;
+
+ if (ospf_is_v2(po))
+ {
+ struct ospf_lsa_sum2 *sum = en->lsa_body;
+ return (sum->metric == metric);
+ }
+ else
+ {
+ struct ospf_lsa_sum3_rt *sum = en->lsa_body;
+ return (sum->options == options) && (sum->metric == metric) && (sum->drid == drid);
+ }
}
-#endif
void
originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric)
{
struct proto_ospf *po = oa->po;
- struct proto *p = &po->proto;
+ struct ospf_lsa_header lsa;
struct top_hash_entry *en;
u32 dom = oa->areaid;
- struct ospf_lsa_header lsa;
void *body;
OSPF_TRACE(D_EVENTS, "Originating net-summary-LSA for %I/%d (metric %d)",
/* options argument is used in ORT_NET and OSPFv3 only */
lsa.age = 0;
-#ifdef OSPFv2
- lsa.options = oa->options;
-#endif
- lsa.type = LSA_T_SUM_NET;
+ lsa.type_raw = LSA_T_SUM_NET;
lsa.id = fibnode_to_lsaid(po, fn);
lsa.rt = po->router_id;
+ lsa_fix_options(po, &lsa, oa->options);
- if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
- {
- if (check_sum_net_lsaid_collision(fn, en))
- {
- log(L_ERR "%s: LSAID collision for %I/%d",
- p->name, fn->prefix, fn->pxlen);
- return;
- }
-
- if (check_sum_net_lsa_same(en, metric))
- return;
- }
+ en = ospf_hash_find_header(po->gr, dom, &lsa);
+ if (en && check_sum_net_lsa(po, en, fn, metric))
+ return;
lsa.sn = get_seqnum(en);
body = originate_sum_net_lsa_body(po, &lsa.length, fn, metric);
}
void
-originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options UNUSED)
+originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options)
{
struct proto_ospf *po = oa->po;
- struct proto *p = &po->proto;
+ struct ospf_lsa_header lsa;
struct top_hash_entry *en;
- u32 dom = oa->areaid;
u32 rid = ipa_to_rid(fn->prefix);
- struct ospf_lsa_header lsa;
+ u32 dom = oa->areaid;
void *body;
OSPF_TRACE(D_EVENTS, "Originating rt-summary-LSA for %R (metric %d)",
rid, metric);
lsa.age = 0;
-#ifdef OSPFv2
- lsa.options = oa->options;
-#endif
- lsa.type = LSA_T_SUM_RT;
- /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
- lsa.id = rid;
+ lsa.type_raw = LSA_T_SUM_RT;
+ lsa.id = rid; /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
lsa.rt = po->router_id;
+ lsa_fix_options(po, &lsa, oa->options);
options &= OPTIONS_MASK;
- if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
- {
- if (check_sum_rt_lsa_same(en, lsa.id, metric, options))
- return;
- }
+
+ en = ospf_hash_find_header(po->gr, dom, &lsa);
+ if (en && check_sum_rt_lsa(po, en, rid, metric, options))
+ return;
lsa.sn = get_seqnum(en);
- body = originate_sum_rt_lsa_body(po, &lsa.length, lsa.id, metric, options);
+ body = originate_sum_rt_lsa_body(po, &lsa.length, rid, metric, options);
lsasum_calculate(&lsa, body);
lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
{
struct proto_ospf *po = oa->po;
- struct proto *p = &po->proto;
- struct top_hash_entry *en;
struct ospf_lsa_header lsa;
+ struct top_hash_entry *en;
+ u32 dom = oa->areaid;
lsa.rt = po->router_id;
if (type == ORT_NET)
{
lsa.id = fibnode_to_lsaid(po, fn);
- lsa.type = LSA_T_SUM_NET;
+ lsa.type_raw = LSA_T_SUM_NET;
}
else
{
/* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
lsa.id = ipa_to_rid(fn->prefix);
- lsa.type = LSA_T_SUM_RT;
+ lsa.type_raw = LSA_T_SUM_RT;
}
- if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
+ en = ospf_hash_find_header(po->gr, dom, &lsa);
+ if (en)
{
- if ((type == ORT_NET) && check_sum_net_lsaid_collision(fn, en))
- {
- log(L_ERR "%s: LSAID collision for %I/%d",
- p->name, fn->prefix, fn->pxlen);
- return;
- }
+ OSPF_TRACE(D_EVENTS, "Flushing summary-LSA (id=%R, type=%d)",
+ en->lsa.id, en->lsa.type_raw);
+
+ if ((type == ORT_NET) && (check_sum_net_lsa(po, en, fn, 0) < 0))
+ return;
struct ospf_lsa_sum *sum = en->lsa_body;
en->lsa.age = LSA_MAXAGE;
en->lsa.sn = LSA_MAXSEQNO;
lsasum_calculate(&en->lsa, sum);
-
- OSPF_TRACE(D_EVENTS, "Flushing summary-LSA (id=%R, type=%d)",
- en->lsa.id, en->lsa.type);
- ospf_lsupd_flood(po, NULL, NULL, &en->lsa, oa->areaid, 1);
+ ospf_lsupd_flood(po, NULL, NULL, &en->lsa, dom, 1);
if (can_flush_lsa(po)) flush_lsa(en, po);
}
}
-#ifdef OSPFv2
+
+/*
+ * AS-external-LSA and NSSA-LSA handling
+ * Type = LSA_T_EXT, LSA_T_NSSA
+ */
static inline void *
-originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
- u32 metric, ip_addr fwaddr, u32 tag, int pbit UNUSED)
+originate_ext2_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
+ u32 metric, ip_addr fwaddr, u32 tag)
{
- struct ospf_lsa_ext *ext = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_ext));
- *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_ext);
+ struct ospf_lsa_ext2 *ext = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_ext2));
+ *length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_ext2);
ext->metric = metric;
- ext->netmask = ipa_mkmask(fn->pxlen);
- ext->fwaddr = fwaddr;
+ ext->netmask = ip4_mkmask(fn->pxlen);
+ ext->fwaddr = ipa_to_ip4(fwaddr);
ext->tag = tag;
return ext;
}
-/*
- * check_ext_lsa() combines functions of check_*_lsaid_collision() and
- * check_*_lsa_same(). 'en' is existing ext LSA, and rest parameters
- * are parameters of new ext route. Function returns -1 if there is
- * LSAID collision, returns 1 if the existing LSA is the same and
- * returns 0 otherwise (in that case, we need to originate a new LSA).
- *
- * Really, checking for the same parameters is not as important as in
- * summary LSA origination, because in most cases the duplicate
- * external route propagation would be stopped by the nest. But there
- * are still some cases (route reload, the same route propagated through
- * different protocol) so it is also done here.
- */
-
-static inline int
-check_ext_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_addr fwaddr, u32 tag)
-{
- struct ospf_lsa_ext *ext = en->lsa_body;
-
- /* LSAID collision */
- if (fn->pxlen != ipa_mklen(ext->netmask))
- return -1;
-
- return (en->lsa.sn != LSA_MAXSEQNO) && (ext->metric == metric) &&
- (ext->tag == tag) && ipa_equal(ext->fwaddr,fwaddr);
-}
-
-#else /* OSPFv3 */
-
static inline void *
-originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
- u32 metric, ip_addr fwaddr, u32 tag, int pbit)
+originate_ext3_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
+ u32 metric, ip_addr fwaddr, u32 tag, int pbit)
{
- int size = sizeof(struct ospf_lsa_ext)
+ int bsize = sizeof(struct ospf_lsa_ext3)
+ IPV6_PREFIX_SPACE(fn->pxlen)
+ (ipa_nonzero(fwaddr) ? 16 : 0)
+ (tag ? 4 : 0);
- struct ospf_lsa_ext *ext = mb_alloc(po->proto.pool, size);
- *length = sizeof(struct ospf_lsa_header) + size;
+ struct ospf_lsa_ext3 *ext = mb_alloc(po->proto.pool, bsize);
+ *length = sizeof(struct ospf_lsa_header) + bsize;
ext->metric = metric;
if (ipa_nonzero(fwaddr))
{
- ext->metric |= LSA_EXT_FBIT;
+ ext->metric |= LSA_EXT3_FBIT;
buf = put_ipv6_addr(buf, fwaddr);
}
if (tag)
{
- ext->metric |= LSA_EXT_TBIT;
+ ext->metric |= LSA_EXT3_TBIT;
*buf++ = tag;
}
return ext;
}
+static inline void *
+originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
+ u32 metric, ip_addr fwaddr, u32 tag, int pbit)
+{
+ return ospf_is_v2(po) ?
+ originate_ext2_lsa_body(po, length, fn, metric, fwaddr, tag) :
+ originate_ext3_lsa_body(po, length, fn, metric, fwaddr, tag, pbit);
+}
+
+
+/*
+ * check_ext_lsa() combines functions of check_*_lsaid_collision() and
+ * check_*_lsa_same(). 'en' is existing ext LSA, and rest parameters
+ * are parameters of new ext route. Function returns -1 if there is
+ * LSAID collision, returns 1 if the existing LSA is the same and
+ * returns 0 otherwise (in that case, we need to originate a new LSA).
+ *
+ * Really, checking for the same parameters is not as important as in
+ * summary LSA origination, because in most cases the duplicate
+ * external route propagation would be stopped by the nest. But there
+ * are still some cases (route reload, the same route propagated through
+ * different protocol) so it is also done here.
+ */
+
+static inline int
+check_ext2_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_addr fwaddr, u32 tag)
+{
+ struct ospf_lsa_ext2 *ext = en->lsa_body;
+
+ /* LSAID collision */
+ if (fn->pxlen != ip4_masklen(ext->netmask))
+ return -1;
+
+ return (en->lsa.sn != LSA_MAXSEQNO) && (ext->metric == metric) &&
+ (ext->tag == tag) && ip4_equal(ext->fwaddr, ipa_to_ip4(fwaddr));
+}
+
static inline int
-check_ext_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_addr fwaddr, u32 tag)
+check_ext3_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_addr fwaddr, u32 tag)
{
- struct ospf_lsa_ext *ext = en->lsa_body;
+ struct ospf_lsa_ext3 *ext = en->lsa_body;
ip_addr prefix;
int pxlen;
u8 pxopts;
ip_addr rt_fwaddr = IPA_NONE;
u32 rt_tag = 0;
- if (ext->metric & LSA_EXT_FBIT)
+ if (ext->metric & LSA_EXT3_FBIT)
buf = lsa_get_ipv6_addr(buf, &rt_fwaddr);
- if (ext->metric & LSA_EXT_TBIT)
+ if (ext->metric & LSA_EXT3_TBIT)
rt_tag = *buf++;
return (rt_metric == metric) && ipa_equal(rt_fwaddr, fwaddr) && (rt_tag == tag);
}
+static int
+check_ext_lsa(struct proto_ospf *po, struct top_hash_entry *en, struct fib_node *fn,
+ u32 metric, ip_addr fwaddr, u32 tag)
+{
+ int rv = ospf_is_v2(po) ?
+ check_ext2_lsa(en, fn, metric, fwaddr, tag) :
+ check_ext3_lsa(en, fn, metric, fwaddr, tag);
+
+ if (rv < 0)
+ log(L_ERR "%s: LSAID collision for %I/%d", po->proto.name, fn->prefix, fn->pxlen);
+
+ return rv;
+}
-#endif
static inline ip_addr
find_surrogate_fwaddr(struct ospf_area *oa)
* @oa: ospf_area for which LSA is originated
* @fn: network prefix and mask
* @src: the source of origination of the LSA (EXT_EXPORT/EXT_NSSA)
- * @metric: the metric of a route
+ * @metric: the metric of a route (possibly with appropriate E-bit)
* @fwaddr: the forwarding address
* @tag: the route tag
* @pbit: P-bit for NSSA LSAs, ignored for external LSAs
struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
struct ospf_lsa_header lsa;
- struct top_hash_entry *en = NULL;
- void *body;
+ struct top_hash_entry *en;
int nssa = oa_is_nssa(oa);
u32 dom = nssa ? oa->areaid : 0;
+ void *body;
OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d",
nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
lsa.age = 0;
-#ifdef OSPFv2
- lsa.options = nssa ? (pbit ? OPT_P : 0) : OPT_E;
-#endif
- lsa.type = nssa ? LSA_T_NSSA : LSA_T_EXT;
+ lsa.type_raw = nssa ? LSA_T_NSSA : LSA_T_EXT;
lsa.id = fibnode_to_lsaid(po, fn);
lsa.rt = po->router_id;
+ lsa_fix_options(po, &lsa, nssa ? (pbit ? OPT_P : 0) : OPT_E);
if (nssa && pbit && ipa_zero(fwaddr))
{
}
}
- if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
- {
- int rv = check_ext_lsa(en, fn, metric, fwaddr, tag);
- if (rv < 0)
- {
- log(L_ERR "%s: LSAID collision for %I/%d",
- p->name, fn->prefix, fn->pxlen);
- return;
- }
-
- if (rv > 0)
- return;
- }
+ en = ospf_hash_find_header(po->gr, dom, &lsa);
+ if (en && check_ext_lsa(po, en, fn, metric, fwaddr, tag))
+ return;
lsa.sn = get_seqnum(en);
body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit);
struct proto *p = &po->proto;
struct top_hash_entry *en;
int nssa = oa_is_nssa(oa);
-
- OSPF_TRACE(D_EVENTS, "Flushing %s-LSA for %I/%d",
- nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
-
u32 dom = nssa ? oa->areaid : 0;
u32 type = nssa ? LSA_T_NSSA : LSA_T_EXT;
u32 lsaid = fibnode_to_lsaid(po, fn);
- if (en = ospf_hash_find(po->gr, dom, lsaid, po->router_id, type))
+ en = ospf_hash_find(po->gr, dom, lsaid, po->router_id, type);
+ if (en)
{
- if (check_ext_lsa(en, fn, 0, IPA_NONE, 0) < 0)
+ OSPF_TRACE(D_EVENTS, "Flushing %s-LSA for %I/%d",
+ nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
+
+ if (check_ext_lsa(po, en, fn, 0, IPA_NONE, 0) < 0)
{
log(L_ERR "%s: LSAID collision for %I/%d",
p->name, fn->prefix, fn->pxlen);
}
/* Clean up source bits */
- if (src)
+ if (src) // XXXX ???
fn->flags &= ~OSPF_RT_SRC;
ospf_lsupd_flush_nlsa(po, en);
}
}
-#ifdef OSPFv3
+/*
+ * Link-LSA handling (assume OSPFv3)
+ * Type = LSA_T_LINK
+ */
static void *
originate_link_lsa_body(struct ospf_iface *ifa, u16 *length)
void
originate_link_lsa(struct ospf_iface *ifa)
{
- struct ospf_lsa_header lsa;
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
+ struct ospf_lsa_header lsa;
+ u32 dom = ifa->iface->index;
void *body;
/* FIXME check for vlink and skip that? */
OSPF_TRACE(D_EVENTS, "Originating link-LSA for iface %s", ifa->iface->name);
lsa.age = 0;
- lsa.type = LSA_T_LINK;
+ lsa.type_raw = LSA_T_LINK;
lsa.id = ifa->iface->index;
lsa.rt = po->router_id;
lsa.sn = get_seqnum(ifa->link_lsa);
- u32 dom = ifa->iface->index;
body = originate_link_lsa_body(ifa, &lsa.length);
lsasum_calculate(&lsa, body);
ifa->origlink = 0;
}
+
+/*
+ * Prefix-Rt-LSA handling (assume OSPFv3)
+ * Type = LSA_T_PREFIX, referred type = LSA_T_RT
+ */
+
static inline void
lsa_put_prefix(struct proto_ospf *po, ip_addr prefix, u32 pxlen, u32 cost)
{
originate_prefix_rt_lsa(struct ospf_area *oa)
{
struct proto_ospf *po = oa->po;
- struct proto *p = &po->proto;
struct ospf_lsa_header lsa;
+ u32 dom = oa->areaid;
void *body;
OSPF_TRACE(D_EVENTS, "Originating router prefix-LSA for area %R", oa->areaid);
lsa.age = 0;
- lsa.type = LSA_T_PREFIX;
+ lsa.type_raw = LSA_T_PREFIX;
lsa.id = 0;
lsa.rt = po->router_id;
lsa.sn = get_seqnum(oa->pxr_lsa);
- u32 dom = oa->areaid;
body = originate_prefix_rt_lsa_body(oa, &lsa.length);
lsasum_calculate(&lsa, body);
}
+/*
+ * Prefix-Net-LSA handling (assume OSPFv3)
+ * Type = LSA_T_PREFIX, referred type = LSA_T_NET
+ */
+
static inline int
prefix_space(u32 *buf)
{
}
-
static void *
originate_prefix_net_lsa_body(struct ospf_iface *ifa, u16 *length)
{
originate_prefix_net_lsa(struct ospf_iface *ifa)
{
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
struct ospf_lsa_header lsa;
+ u32 dom = ifa->oa->areaid;
void *body;
OSPF_TRACE(D_EVENTS, "Originating network prefix-LSA for iface %s",
ifa->iface->name);
lsa.age = 0;
- lsa.type = LSA_T_PREFIX;
+ lsa.type_raw = LSA_T_PREFIX;
lsa.id = ifa->iface->index;
lsa.rt = po->router_id;
lsa.sn = get_seqnum(ifa->pxn_lsa);
- u32 dom = ifa->oa->areaid;
body = originate_prefix_net_lsa_body(ifa, &lsa.length);
lsasum_calculate(&lsa, body);
flush_prefix_net_lsa(struct ospf_iface *ifa)
{
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
struct top_hash_entry *en = ifa->pxn_lsa;
u32 dom = ifa->oa->areaid;
}
-#endif
-
-
static void
ospf_top_ht_alloc(struct top_graph *f)
{
return a;
}
-static inline unsigned
+static unsigned
ospf_top_hash(struct top_graph *f, u32 domain, u32 lsaid, u32 rtrid, u32 type)
{
/* In OSPFv2, we don't know Router ID when looking for network LSAs.
In both cases, there is (usually) just one (or small number)
appropriate LSA, so we just clear unknown part of key. */
- return (
-#ifdef OSPFv2
- ((type == LSA_T_NET) ? 0 : ospf_top_hash_u32(rtrid)) +
- ospf_top_hash_u32(lsaid) +
-#else /* OSPFv3 */
- ospf_top_hash_u32(rtrid) +
- ((type == LSA_T_RT) ? 0 : ospf_top_hash_u32(lsaid)) +
-#endif
+ return (((f->ospf2 && (type == LSA_T_NET)) ? 0 : ospf_top_hash_u32(rtrid)) +
+ ((!f->ospf2 && (type == LSA_T_RT)) ? 0 : ospf_top_hash_u32(lsaid)) +
type + domain) & f->hash_mask;
/*
/* In OSPFv2, sometimes we don't know Router ID when looking for network LSAs.
There should be just one, so we find any match. */
struct top_hash_entry *
-ospf_hash_find_net(struct top_graph *f, u32 domain, u32 lsa)
+ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif)
{
struct top_hash_entry *e;
- e = f->hash_table[ospf_top_hash(f, domain, lsa, 0, LSA_T_NET)];
+ e = f->hash_table[ospf_top_hash(f, domain, id, 0, LSA_T_NET)];
- while (e && (e->lsa.id != lsa || e->lsa.type != LSA_T_NET || e->domain != domain))
+ while (e && (e->lsa.id != id || e->lsa.type != LSA_T_NET || e->domain != domain))
e = e->next;
return e;
in intra-area routing table calculation */
struct top_hash_entry *next; /* Next in hash chain */
struct ospf_lsa_header lsa;
+ u16 lsa_type; /* lsa.type processed and converted to common values */
u32 domain; /* Area ID for area-wide LSAs, Iface ID for link-wide LSAs */
// struct ospf_area *oa;
void *lsa_body;
#ifdef OSPFv2
-struct top_hash_entry * ospf_hash_find_net(struct top_graph *f, u32 domain, u32 lsa);
+struct top_hash_entry * ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif);
static inline struct top_hash_entry *
ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
}
#else /* OSPFv3 */
+static inline struct top_hash_entry *
+ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif)
+{
+ return ospf_hash_find(f, domain, nif, id, LSA_T_NET);
+}
+
+
struct top_hash_entry * ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr);
struct top_hash_entry * ospf_hash_find_rt_first(struct top_graph *f, u32 domain, u32 rtr);
struct top_hash_entry * ospf_hash_find_rt_next(struct top_hash_entry *e);
}
RADV_TRACE(D_PACKETS, "Sending RA via %s", ifa->iface->name);
- sk_send_to(ifa->sk, ifa->plen, AllNodes, 0);
+ sk_send_to(ifa->sk, ifa->plen, IP6_ALL_NODES, 0);
}
if (sk_setup_multicast(sk) < 0)
goto err;
- if (sk_join_group(sk, AllRouters) < 0)
+ if (sk_join_group(sk, IP6_ALL_ROUTERS) < 0)
goto err;
ifa->sk = sk;
#define ICMPV6_PROTO 58
-#define AllNodes ipa_build6(0xFF020000, 0, 0, 1) /* FF02::1 */
-#define AllRouters ipa_build6(0xFF020000, 0, 0, 2) /* FF02::2 */
-
#define ICMPV6_RS 133
#define ICMPV6_RA 134