Fininshing integrated OSPF.
This commit is contained in:
parent
88a183c6c9
commit
6f8bbaa10b
14 changed files with 389 additions and 240 deletions
|
@ -27,7 +27,7 @@ event_list global_event_list;
|
|||
inline void
|
||||
ev_postpone(event *e)
|
||||
{
|
||||
if (e->n.next)
|
||||
if (ev_active(e))
|
||||
{
|
||||
rem_node(&e->n);
|
||||
e->n.next = NULL;
|
||||
|
|
|
@ -30,4 +30,11 @@ void ev_schedule(event *);
|
|||
void ev_postpone(event *);
|
||||
int ev_run_list(event_list *);
|
||||
|
||||
static inline int
|
||||
ev_active(event *e)
|
||||
{
|
||||
return e->n.next != NULL;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -212,17 +212,6 @@ ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
|
|||
|
||||
ospf_prepare_dbdes(p, n);
|
||||
ospf_do_send_dbdes(p, n);
|
||||
|
||||
if (n->state == NEIGHBOR_EXSTART)
|
||||
return;
|
||||
|
||||
/* Master should restart RXMT timer for each DBDES exchange */
|
||||
if (n->myimms & DBDES_MS)
|
||||
tm_start(n->rxmt_timer, n->ifa->rxmtint);
|
||||
|
||||
if (!(n->myimms & DBDES_MS))
|
||||
if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
|
||||
ospf_neigh_sm(n, INM_EXDONE);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -277,13 +266,20 @@ ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_ne
|
|||
en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
|
||||
if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
|
||||
{
|
||||
/* This should be splitted to ospf_lsa_lsrq_up() */
|
||||
req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type);
|
||||
|
||||
if (!SNODE_VALID(req))
|
||||
s_add_tail(&n->lsrql, SNODE req);
|
||||
|
||||
if (!SNODE_VALID(n->lsrqi))
|
||||
n->lsrqi = req;
|
||||
|
||||
req->lsa = lsa;
|
||||
req->lsa_body = LSA_BODY_DUMMY;
|
||||
|
||||
if (!tm_active(n->lsrq_timer))
|
||||
tm_start(n->lsrq_timer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,13 +302,16 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
u32 rcv_ddseq, rcv_options;
|
||||
u16 rcv_iface_mtu;
|
||||
u8 rcv_imms;
|
||||
uint plen, err_val = 0, err_seqmis = 0;
|
||||
uint plen, err_val = 0;
|
||||
|
||||
/* RFC 2328 10.6 */
|
||||
|
||||
plen = ntohs(pkt->length);
|
||||
if (plen < ospf_dbdes_hdrlen(p))
|
||||
DROP("too short", plen);
|
||||
{
|
||||
LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
|
||||
return;
|
||||
}
|
||||
|
||||
OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from nbr %R on %s", n->rid, ifa->ifname);
|
||||
|
||||
|
@ -366,6 +365,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
n->options = rcv_options;
|
||||
n->myimms &= ~DBDES_MS;
|
||||
n->imms = rcv_imms;
|
||||
tm_stop(n->dbdes_timer);
|
||||
ospf_neigh_sm(n, INM_NEGDONE);
|
||||
ospf_send_dbdes(p, n);
|
||||
break;
|
||||
|
@ -381,6 +381,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
n->ddr = rcv_ddseq - 1; /* It will be set corectly a few lines down */
|
||||
n->imms = rcv_imms;
|
||||
ospf_neigh_sm(n, INM_NEGDONE);
|
||||
/* Continue to the NEIGHBOR_EXCHANGE case */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -394,9 +395,6 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
(rcv_ddseq == n->ddr))
|
||||
goto duplicate;
|
||||
|
||||
/* Do INM_SEQMIS during packet error */
|
||||
err_seqmis = 1;
|
||||
|
||||
if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))
|
||||
DROP("MS-bit mismatch", rcv_imms);
|
||||
|
||||
|
@ -422,9 +420,14 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
return;
|
||||
|
||||
if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
|
||||
{
|
||||
tm_stop(n->dbdes_timer);
|
||||
ospf_neigh_sm(n, INM_EXDONE);
|
||||
else
|
||||
ospf_send_dbdes(p, n);
|
||||
break;
|
||||
}
|
||||
|
||||
ospf_send_dbdes(p, n);
|
||||
tm_start(n->dbdes_timer, n->ifa->rxmtint);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -440,6 +443,9 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
return;
|
||||
|
||||
ospf_send_dbdes(p, n);
|
||||
|
||||
if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
|
||||
ospf_neigh_sm(n, INM_EXDONE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -450,8 +456,6 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
(rcv_ddseq == n->ddr))
|
||||
goto duplicate;
|
||||
|
||||
err_seqmis = 1;
|
||||
|
||||
DROP("too late for DD exchange", n->state);
|
||||
|
||||
default:
|
||||
|
@ -471,7 +475,6 @@ drop:
|
|||
LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)",
|
||||
n->rid, ifa->ifname, err_dsc, err_val);
|
||||
|
||||
if (err_seqmis)
|
||||
ospf_neigh_sm(n, INM_SEQMIS);
|
||||
ospf_neigh_sm(n, INM_SEQMIS);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -304,11 +304,8 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
nn->found = 1;
|
||||
}
|
||||
|
||||
// XXXX format
|
||||
// "ospf1: New neighbor found: 192.168.1.1/fe80:1234:1234:1234:1234 on eth0";
|
||||
// "ospf1: New neighbor found: 192.168.1.1 on eth0 at fe80:1234:1234:1234:1234";
|
||||
// "ospf1: Neighbor 192.168.1.1 on eth0 found, IP adress fe80:1234:1234:1234:1234";
|
||||
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, ifa->ifname);
|
||||
OSPF_TRACE(D_EVENTS, "New neighbor %R on %s, IP address %I",
|
||||
rcv_rid, ifa->ifname, faddr);
|
||||
|
||||
n = ospf_neighbor_new(ifa);
|
||||
|
||||
|
|
|
@ -58,6 +58,12 @@ ifa_bufsize(struct ospf_iface *ifa)
|
|||
return MAX(bsize, ifa->tx_length);
|
||||
}
|
||||
|
||||
static inline uint
|
||||
ifa_flood_queue_size(struct ospf_iface *ifa)
|
||||
{
|
||||
return ifa->tx_length / 24;
|
||||
}
|
||||
|
||||
int
|
||||
ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
|
||||
{
|
||||
|
@ -476,6 +482,9 @@ ospf_iface_add(struct object_lock *lock)
|
|||
|
||||
if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
|
||||
ifa->wait_timer = tm_new_set(ifa->pool, wait_timer_hook, ifa, 0, 0);
|
||||
|
||||
ifa->flood_queue_size = ifa_flood_queue_size(ifa);
|
||||
ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
|
||||
}
|
||||
|
||||
/* Do iface UP, unless there is no link and we use link detection */
|
||||
|
@ -679,6 +688,9 @@ ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip)
|
|||
add_tail(&p->iface_list, NODE ifa);
|
||||
|
||||
ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
|
||||
|
||||
ifa->flood_queue_size = ifa_flood_queue_size(ifa);
|
||||
ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -693,6 +705,20 @@ ospf_iface_change_timer(timer *tm, uint val)
|
|||
tm_start(tm, val);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ospf_iface_update_flood_queue_size(struct ospf_iface *ifa)
|
||||
{
|
||||
uint old_size = ifa->flood_queue_size;
|
||||
uint new_size = ifa_flood_queue_size(ifa);
|
||||
|
||||
if (new_size <= old_size)
|
||||
return;
|
||||
|
||||
ifa->flood_queue_size = new_size;
|
||||
ifa->flood_queue = mb_realloc(ifa->flood_queue, new_size * sizeof(void *));
|
||||
bzero(ifa->flood_queue + old_size, (new_size - old_size) * sizeof(void *));
|
||||
}
|
||||
|
||||
int
|
||||
ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
||||
{
|
||||
|
@ -739,6 +765,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
|||
ifname, ifa->rxmtint, new->rxmtint);
|
||||
|
||||
ifa->rxmtint = new->rxmtint;
|
||||
/* FIXME: Update neighbors' timers */
|
||||
}
|
||||
|
||||
/* POLL TIMER */
|
||||
|
@ -874,6 +901,9 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
|||
/* ifa cannot be vlink */
|
||||
ifa->tx_length = ifa_tx_length(ifa);
|
||||
update_buffers = 1;
|
||||
|
||||
if (!ifa->stub)
|
||||
ospf_iface_update_flood_queue_size(ifa);
|
||||
}
|
||||
|
||||
/* RX BUFFER */
|
||||
|
@ -1211,6 +1241,9 @@ ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa)
|
|||
sk_set_rbsize(ifa->sk, bsize);
|
||||
if (bsize > ifa->sk->tbsize)
|
||||
sk_set_tbsize(ifa->sk, bsize);
|
||||
|
||||
if (!ifa->stub)
|
||||
ospf_iface_update_flood_queue_size(ifa);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -162,23 +162,20 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
|
||||
if (lsa_comp(&lsa, &ret->lsa) != CMP_SAME)
|
||||
{
|
||||
OSPF_TRACE(D_PACKETS, "Strange LSACK from %I", n->ip);
|
||||
OSPF_TRACE(D_PACKETS, "Type: %04x, Id: %R, Rt: %R",
|
||||
OSPF_TRACE(D_PACKETS, "Strange LSACK from nbr %R on %s", n->rid, ifa->ifname);
|
||||
OSPF_TRACE(D_PACKETS, " Type: %04x, Id: %R, Rt: %R",
|
||||
lsa_type, lsa.id, lsa.rt);
|
||||
OSPF_TRACE(D_PACKETS, "I have: Age: %4u, Seq: %08x, Sum: %04x",
|
||||
ret->lsa.age, ret->lsa.sn, ret->lsa.checksum);
|
||||
OSPF_TRACE(D_PACKETS, "He has: Age: %4u, Seq: %08x, Sum: %04x",
|
||||
lsa.age, lsa.sn, lsa.checksum);
|
||||
OSPF_TRACE(D_PACKETS, " I have: Seq: %08x, Age: %4u, Sum: %04x",
|
||||
ret->lsa.sn, ret->lsa.age, ret->lsa.checksum);
|
||||
OSPF_TRACE(D_PACKETS, " It has: Seq: %08x, Age: %4u, Sum: %04x",
|
||||
lsa.sn, lsa.age, lsa.checksum);
|
||||
continue;
|
||||
}
|
||||
|
||||
en = ospf_hash_find_entry(p->gr, ret);
|
||||
if (en)
|
||||
en->ret_count--;
|
||||
|
||||
DBG("Deleting LSA (Type: %04x Id: %R Rt: %R) from lsrtl for neighbor %R\n",
|
||||
lsa_type, lsa.id, lsa.rt, n->rid);
|
||||
s_rem_node(SNODE ret);
|
||||
ospf_hash_delete(n->lsrth, ret);
|
||||
|
||||
en = ospf_hash_find_entry(p->gr, ret);
|
||||
ospf_lsa_lsrt_down_(en, n, ret);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,42 +54,37 @@ ospf_send_lsreq(struct ospf_proto *p, struct ospf_neighbor *n)
|
|||
{
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct ospf_lsreq_header *lsrs;
|
||||
struct top_hash_entry *en;
|
||||
struct top_hash_entry *req;
|
||||
struct ospf_packet *pkt;
|
||||
uint i, lsr_max, length;
|
||||
|
||||
/* RFC 2328 10.9 */
|
||||
|
||||
if (EMPTY_SLIST(n->lsrql))
|
||||
{
|
||||
if (n->state == NEIGHBOR_LOADING)
|
||||
ospf_neigh_sm(n, INM_LOADDONE);
|
||||
return;
|
||||
}
|
||||
/* ASSERT((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql)); */
|
||||
|
||||
pkt = ospf_tx_buffer(ifa);
|
||||
ospf_pkt_fill_hdr(ifa, pkt, LSREQ_P);
|
||||
ospf_lsreq_body(p, pkt, &lsrs, &lsr_max);
|
||||
|
||||
/* We send smaller LSREQ to prevent multiple LSACKs as answer */
|
||||
lsr_max = lsr_max / 4;
|
||||
|
||||
i = 0;
|
||||
WALK_SLIST(en, n->lsrql)
|
||||
WALK_SLIST(req, n->lsrql)
|
||||
{
|
||||
if (i == lsr_max)
|
||||
break;
|
||||
|
||||
DBG("Requesting %uth LSA: Type: %04u, 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);
|
||||
i, req->lsa_type, req->lsa.id, req->lsa.rt, req->lsa.sn, req->lsa.age);
|
||||
|
||||
u32 etype = lsa_get_etype(&en->lsa, p);
|
||||
u32 etype = lsa_get_etype(&req->lsa, p);
|
||||
lsrs[i].type = htonl(etype);
|
||||
lsrs[i].rt = htonl(en->lsa.rt);
|
||||
lsrs[i].id = htonl(en->lsa.id);
|
||||
lsrs[i].rt = htonl(req->lsa.rt);
|
||||
lsrs[i].id = htonl(req->lsa.id);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* We store the position to see whether requested LSAs have been received */
|
||||
n->lsrqi = req;
|
||||
|
||||
length = ospf_pkt_hdrlen(p) + i * sizeof(struct ospf_lsreq_header);
|
||||
pkt->length = htons(length);
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ ospf_dump_lsahdr(struct ospf_proto *p, struct ospf_lsa_header *lsa_n)
|
|||
lsa_ntoh_hdr(lsa_n, &lsa);
|
||||
lsa_etype = lsa_get_etype(&lsa, p);
|
||||
|
||||
log(L_TRACE "%s: LSA Type: %04x, Id: %R, Rt: %R, Age: %u, Seq: %08x, Sum: %04x",
|
||||
p->p.name, lsa_etype, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
|
||||
log(L_TRACE "%s: LSA Type: %04x, Id: %R, Rt: %R, Seq: %08x, Age: %u, Sum: %04x",
|
||||
p->p.name, lsa_etype, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -65,45 +65,63 @@ ospf_lsupd_set_lsa_count(struct ospf_packet *pkt, uint hdrlen, u32 val)
|
|||
|
||||
static inline void
|
||||
ospf_lsupd_body(struct ospf_proto *p, struct ospf_packet *pkt,
|
||||
uint *offset, uint *bound, uint *lsa_count)
|
||||
uint *offset, uint *lsa_count)
|
||||
{
|
||||
uint hlen = ospf_lsupd_hdrlen(p);
|
||||
*offset = hlen;
|
||||
*bound = ntohs(pkt->length) - sizeof(struct ospf_lsa_header);
|
||||
*lsa_count = ospf_lsupd_get_lsa_count(pkt, hlen);
|
||||
}
|
||||
|
||||
static void
|
||||
ospf_dump_lsupd(struct ospf_proto *p, struct ospf_packet *pkt)
|
||||
{
|
||||
uint offset, bound, i, lsa_count, lsalen;
|
||||
uint offset, plen, i, lsa_count, lsa_len;
|
||||
|
||||
ASSERT(pkt->type == LSUPD_P);
|
||||
ospf_dump_common(p, pkt);
|
||||
|
||||
ospf_lsupd_body(p, pkt, &offset, &bound, &lsa_count);
|
||||
plen = ntohs(pkt->length);
|
||||
ospf_lsupd_body(p, pkt, &offset, &lsa_count);
|
||||
for (i = 0; i < lsa_count; i++)
|
||||
{
|
||||
if (offset > bound)
|
||||
{
|
||||
log(L_TRACE "%s: LSA invalid", p->p.name);
|
||||
return;
|
||||
}
|
||||
if ((offset + sizeof(struct ospf_lsa_header)) > plen)
|
||||
goto invalid;
|
||||
|
||||
struct ospf_lsa_header *lsa = ((void *) pkt) + offset;
|
||||
ospf_dump_lsahdr(p, lsa);
|
||||
lsalen = ntohs(lsa->length);
|
||||
offset += lsalen;
|
||||
lsa_len = ntohs(lsa->length);
|
||||
|
||||
if (((lsalen % 4) != 0) || (lsalen <= sizeof(struct ospf_lsa_header)))
|
||||
{
|
||||
log(L_TRACE "%s: LSA invalid", p->p.name);
|
||||
return;
|
||||
}
|
||||
if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header)))
|
||||
goto invalid;
|
||||
|
||||
ospf_dump_lsahdr(p, lsa);
|
||||
offset += lsa_len;
|
||||
}
|
||||
return;
|
||||
|
||||
invalid:
|
||||
log(L_TRACE "%s: LSA invalid", p->p.name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
ospf_lsa_lsrq_down(struct top_hash_entry *req, struct ospf_neighbor *n, struct ospf_neighbor *from)
|
||||
{
|
||||
if (req == n->lsrqi)
|
||||
n->lsrqi = SNODE_NEXT(req);
|
||||
|
||||
s_rem_node(SNODE req);
|
||||
ospf_hash_delete(n->lsrqh, req);
|
||||
|
||||
if (EMPTY_SLIST(n->lsrql))
|
||||
{
|
||||
tm_stop(n->lsrq_timer);
|
||||
|
||||
if (n->state == NEIGHBOR_LOADING)
|
||||
ospf_neigh_sm(n, INM_LOADDONE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
ospf_lsa_lsrt_up(struct top_hash_entry *en, struct ospf_neighbor *n)
|
||||
{
|
||||
|
@ -117,6 +135,22 @@ ospf_lsa_lsrt_up(struct top_hash_entry *en, struct ospf_neighbor *n)
|
|||
|
||||
ret->lsa = en->lsa;
|
||||
ret->lsa_body = LSA_BODY_DUMMY;
|
||||
|
||||
if (!tm_active(n->lsrt_timer))
|
||||
tm_start(n->lsrt_timer, n->ifa->rxmtint);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_lsa_lsrt_down_(struct top_hash_entry *en, struct ospf_neighbor *n, struct top_hash_entry *ret)
|
||||
{
|
||||
if (en)
|
||||
en->ret_count--;
|
||||
|
||||
s_rem_node(SNODE ret);
|
||||
ospf_hash_delete(n->lsrth, ret);
|
||||
|
||||
if (EMPTY_SLIST(n->lsrtl))
|
||||
tm_stop(n->lsrt_timer);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -125,14 +159,9 @@ ospf_lsa_lsrt_down(struct top_hash_entry *en, struct ospf_neighbor *n)
|
|||
struct top_hash_entry *ret = ospf_hash_find_entry(n->lsrth, en);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
en->ret_count--;
|
||||
s_rem_node(SNODE ret);
|
||||
ospf_hash_delete(n->lsrth, ret);
|
||||
return 1;
|
||||
}
|
||||
ospf_lsa_lsrt_down_(en, n, ret);
|
||||
|
||||
return 0;
|
||||
return ret != NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -144,10 +173,61 @@ ospf_add_flushed_to_lsrt(struct ospf_proto *p, struct ospf_neighbor *n)
|
|||
if ((en->lsa.age == LSA_MAXAGE) && (en->lsa_body != NULL) &&
|
||||
lsa_flooding_allowed(en->lsa_type, en->domain, n->ifa))
|
||||
ospf_lsa_lsrt_up(en, n);
|
||||
|
||||
/* If we found any flushed LSA, we send them ASAP */
|
||||
if (tm_active(n->lsrt_timer))
|
||||
tm_start(n->lsrt_timer, 0);
|
||||
}
|
||||
|
||||
static int ospf_flood_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, uint lsa_min_count, struct ospf_iface *ifa);
|
||||
|
||||
static void ospf_send_lsupd_to_ifa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa);
|
||||
static void
|
||||
ospf_enqueue_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa)
|
||||
{
|
||||
if (ifa->flood_queue_used == ifa->flood_queue_size)
|
||||
{
|
||||
/* If we already have full queue, we send some packets */
|
||||
uint sent = ospf_flood_lsupd(p, ifa->flood_queue, ifa->flood_queue_used, ifa->flood_queue_used / 2, ifa);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sent; i++)
|
||||
ifa->flood_queue[i]->ret_count--;
|
||||
|
||||
ifa->flood_queue_used -= sent;
|
||||
memmove(ifa->flood_queue, ifa->flood_queue + sent, ifa->flood_queue_used * sizeof(void *));
|
||||
bzero(ifa->flood_queue + ifa->flood_queue_used, sent * sizeof(void *));
|
||||
}
|
||||
|
||||
en->ret_count++;
|
||||
ifa->flood_queue[ifa->flood_queue_used] = en;
|
||||
ifa->flood_queue_used++;
|
||||
|
||||
if (!ev_active(p->flood_event))
|
||||
ev_schedule(p->flood_event);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_flood_event(void *ptr)
|
||||
{
|
||||
struct ospf_proto *p = ptr;
|
||||
struct ospf_iface *ifa;
|
||||
int i, count;
|
||||
|
||||
WALK_LIST(ifa, p->iface_list)
|
||||
{
|
||||
if (ifa->flood_queue_used == 0)
|
||||
continue;
|
||||
|
||||
count = ifa->flood_queue_used;
|
||||
ospf_flood_lsupd(p, ifa->flood_queue, count, count, ifa);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
ifa->flood_queue[i]->ret_count--;
|
||||
|
||||
ifa->flood_queue_used = 0;
|
||||
bzero(ifa->flood_queue, count * sizeof(void *));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -195,14 +275,7 @@ ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neig
|
|||
|
||||
/* If same or newer, remove LSA from the link state request list */
|
||||
if (cmp > CMP_OLDER)
|
||||
{
|
||||
s_rem_node(SNODE req);
|
||||
ospf_hash_delete(n->lsrqh, req);
|
||||
n->want_lsreq = 1;
|
||||
|
||||
if ((EMPTY_SLIST(n->lsrql)) && (n->state == NEIGHBOR_LOADING))
|
||||
ospf_neigh_sm(n, INM_LOADDONE);
|
||||
}
|
||||
ospf_lsa_lsrq_down(req, n, from);
|
||||
|
||||
/* If older or same, skip processing of this neighbor */
|
||||
if (cmp < CMP_NEWER)
|
||||
|
@ -242,7 +315,7 @@ ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neig
|
|||
}
|
||||
|
||||
/* 13.3 (5) - finally flood the packet */
|
||||
ospf_send_lsupd_to_ifa(p, en, ifa);
|
||||
ospf_enqueue_lsa(p, en, ifa);
|
||||
}
|
||||
|
||||
return back;
|
||||
|
@ -302,26 +375,33 @@ ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
ospf_send_lsupd_to_ifa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa)
|
||||
static int
|
||||
ospf_flood_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, uint lsa_min_count, struct ospf_iface *ifa)
|
||||
{
|
||||
uint c = ospf_prepare_lsupd(p, ifa, &en, 1);
|
||||
uint i, c;
|
||||
|
||||
if (!c) /* Too large LSA */
|
||||
return;
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa),
|
||||
"LSUPD packet flooded via %s", ifa->ifname);
|
||||
|
||||
if (ifa->type == OSPF_IT_BCAST)
|
||||
for (i = 0; i < lsa_min_count; i += c)
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
ospf_send_to_all(ifa);
|
||||
c = ospf_prepare_lsupd(p, ifa, lsa_list + i, lsa_count - i);
|
||||
|
||||
if (!c) /* Too large LSA */
|
||||
{ i++; continue; }
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa),
|
||||
"LSUPD packet flooded via %s", ifa->ifname);
|
||||
|
||||
if (ifa->type == OSPF_IT_BCAST)
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
ospf_send_to_all(ifa);
|
||||
else
|
||||
ospf_send_to_des(ifa);
|
||||
}
|
||||
else
|
||||
ospf_send_to_des(ifa);
|
||||
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
|
||||
}
|
||||
else
|
||||
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -343,17 +423,19 @@ ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa
|
|||
ospf_send_to(ifa, n->ip);
|
||||
}
|
||||
|
||||
return lsa_count;
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
ospf_rxmt_lsupd(struct ospf_proto *p, struct ospf_neighbor *n)
|
||||
{
|
||||
const uint max = 128;
|
||||
uint max = 2 * n->ifa->flood_queue_size;
|
||||
struct top_hash_entry *entries[max];
|
||||
struct top_hash_entry *ret, *nxt, *en;
|
||||
uint i = 0;
|
||||
|
||||
/* ASSERT((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl)); */
|
||||
|
||||
WALK_SLIST_DELSAFE(ret, nxt, n->lsrtl)
|
||||
{
|
||||
if (i == max)
|
||||
|
@ -398,14 +480,15 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
struct ospf_proto *p = ifa->oa->po;
|
||||
const char *err_dsc = NULL;
|
||||
uint plen, err_val = 0;
|
||||
int skip_lsreq = 0;
|
||||
n->want_lsreq = 0;
|
||||
|
||||
/* RFC 2328 13. */
|
||||
|
||||
plen = ntohs(pkt->length);
|
||||
if (plen < (ospf_lsupd_hdrlen(p) + sizeof(struct ospf_lsa_header)))
|
||||
DROP("too short", plen);
|
||||
if (plen < ospf_lsupd_hdrlen(p))
|
||||
{
|
||||
LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
|
||||
return;
|
||||
}
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from nbr %R on %s", n->rid, ifa->ifname);
|
||||
|
||||
|
@ -417,8 +500,8 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
|
||||
ospf_neigh_sm(n, INM_HELLOREC); /* Questionable */
|
||||
|
||||
uint offset, bound, i, lsa_count;
|
||||
ospf_lsupd_body(p, pkt, &offset, &bound, &lsa_count);
|
||||
uint offset, i, lsa_count;
|
||||
ospf_lsupd_body(p, pkt, &offset, &lsa_count);
|
||||
|
||||
for (i = 0; i < lsa_count; i++)
|
||||
{
|
||||
|
@ -426,7 +509,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
struct top_hash_entry *en;
|
||||
u32 lsa_len, lsa_type, lsa_domain;
|
||||
|
||||
if (offset > bound)
|
||||
if ((offset + sizeof(struct ospf_lsa_header)) > plen)
|
||||
DROP("too short", plen);
|
||||
|
||||
/* LSA header in network order */
|
||||
|
@ -492,7 +575,6 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
if (en && ((now - en->inst_time) < MINLSARRIVAL))
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Skipping LSA received in less that MinLSArrival");
|
||||
skip_lsreq = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -559,7 +641,9 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* FIXME pg145 (6) */
|
||||
/* 13. (6) - received LSA is in Link state request list (but not newer) */
|
||||
if (ospf_hash_find_entry(n->lsrqh, en) != NULL)
|
||||
DROP1("error in LSA database exchange");
|
||||
|
||||
/* 13. (7) - received LSA is same */
|
||||
if (lsa_comp(&lsa, &en->lsa) == CMP_SAME)
|
||||
|
@ -576,7 +660,6 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
else
|
||||
ospf_enqueue_lsack(n, lsa_n, ACKL_DIRECT);
|
||||
|
||||
skip_lsreq = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -601,15 +684,24 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
|||
/* Send direct LSACKs */
|
||||
ospf_send_lsack(p, n, ACKL_DIRECT);
|
||||
|
||||
/* Send enqueued LSAs immediately, do not wait for flood_event */
|
||||
if (ev_active(p->flood_event))
|
||||
{
|
||||
ev_postpone(p->flood_event);
|
||||
ospf_flood_event(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* In loading state, we should ask for another batch of LSAs. This is only
|
||||
* vaguely mentioned in RFC 2328. We send a new LSREQ only if the current
|
||||
* LSUPD actually removed some entries from LSA request list (want_lsreq) and
|
||||
* did not contain duplicate or early LSAs (skip_lsreq). The first condition
|
||||
* prevents endless floods, the second condition helps with flow control.
|
||||
* During loading, we should ask for another batch of LSAs. This is only
|
||||
* vaguely mentioned in RFC 2328. We send a new LSREQ if all requests sent in
|
||||
* the last packet were already answered and/or removed from the LS request
|
||||
* list and therefore lsrqi is pointing to the first node of the list.
|
||||
*/
|
||||
if ((n->state == NEIGHBOR_LOADING) && n->want_lsreq && !skip_lsreq)
|
||||
if (!EMPTY_SLIST(n->lsrql) && (n->lsrqi == SHEAD(n->lsrql)))
|
||||
{
|
||||
ospf_send_lsreq(p, n);
|
||||
tm_start(n->lsrq_timer, n->ifa->rxmtint);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
|
@ -617,7 +709,7 @@ drop:
|
|||
LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)",
|
||||
n->rid, ifa->ifname, err_dsc, err_val);
|
||||
|
||||
// XXXX realy?
|
||||
ospf_neigh_sm(n, INM_SEQMIS);
|
||||
/* Malformed LSUPD - there is no defined error event, we abuse BadLSReq */
|
||||
ospf_neigh_sm(n, INM_BADLSREQ);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -23,14 +23,18 @@ const char *ospf_inm_names[] = {
|
|||
|
||||
|
||||
static int can_do_adj(struct ospf_neighbor *n);
|
||||
static void neighbor_timer_hook(timer * timer);
|
||||
static void rxmt_timer_hook(timer * timer);
|
||||
static void ackd_timer_hook(timer * t);
|
||||
static void inactivity_timer_hook(timer * timer);
|
||||
static void dbdes_timer_hook(timer *t);
|
||||
static void lsrq_timer_hook(timer *t);
|
||||
static void lsrt_timer_hook(timer *t);
|
||||
static void ackd_timer_hook(timer *t);
|
||||
|
||||
|
||||
static void
|
||||
init_lists(struct ospf_proto *p, struct ospf_neighbor *n)
|
||||
{
|
||||
s_init_list(&(n->lsrql));
|
||||
n->lsrqi = SHEAD(n->lsrql);
|
||||
n->lsrqh = ospf_top_new(p, n->pool);
|
||||
|
||||
s_init_list(&(n->lsrtl));
|
||||
|
@ -57,9 +61,16 @@ release_lsrtl(struct ospf_proto *p, struct ospf_neighbor *n)
|
|||
static void
|
||||
reset_lists(struct ospf_proto *p, struct ospf_neighbor *n)
|
||||
{
|
||||
release_lsrtl(p,n);
|
||||
release_lsrtl(p, n);
|
||||
ospf_top_free(n->lsrqh);
|
||||
ospf_top_free(n->lsrth);
|
||||
ospf_reset_lsack_queue(n);
|
||||
|
||||
tm_stop(n->dbdes_timer);
|
||||
tm_stop(n->lsrq_timer);
|
||||
tm_stop(n->lsrt_timer);
|
||||
tm_stop(n->ackd_timer);
|
||||
|
||||
init_lists(p, n);
|
||||
}
|
||||
|
||||
|
@ -80,30 +91,14 @@ ospf_neighbor_new(struct ospf_iface *ifa)
|
|||
init_lists(p, n);
|
||||
s_init(&(n->dbsi), &(p->lsal));
|
||||
|
||||
n->inactim = tm_new(pool);
|
||||
n->inactim->data = n;
|
||||
n->inactim->randomize = 0;
|
||||
n->inactim->hook = neighbor_timer_hook;
|
||||
n->inactim->recurrent = 0;
|
||||
DBG("%s: Installing inactivity timer.\n", p->p.name);
|
||||
|
||||
n->rxmt_timer = tm_new(pool);
|
||||
n->rxmt_timer->data = n;
|
||||
n->rxmt_timer->randomize = 0;
|
||||
n->rxmt_timer->hook = rxmt_timer_hook;
|
||||
n->rxmt_timer->recurrent = ifa->rxmtint;
|
||||
tm_start(n->rxmt_timer, n->ifa->rxmtint);
|
||||
DBG("%s: Installing rxmt timer.\n", p->p.name);
|
||||
|
||||
n->ackd_timer = tm_new(pool);
|
||||
n->ackd_timer->data = n;
|
||||
n->ackd_timer->randomize = 0;
|
||||
n->ackd_timer->hook = ackd_timer_hook;
|
||||
n->ackd_timer->recurrent = ifa->rxmtint / 2;
|
||||
init_list(&n->ackl[ACKL_DIRECT]);
|
||||
init_list(&n->ackl[ACKL_DELAY]);
|
||||
tm_start(n->ackd_timer, n->ifa->rxmtint / 2);
|
||||
DBG("%s: Installing ackd timer.\n", p->p.name);
|
||||
|
||||
n->inactim = tm_new_set(pool, inactivity_timer_hook, n, 0, 0);
|
||||
n->dbdes_timer = tm_new_set(pool, dbdes_timer_hook, n, 0, ifa->rxmtint);
|
||||
n->lsrq_timer = tm_new_set(pool, lsrq_timer_hook, n, 0, ifa->rxmtint);
|
||||
n->lsrt_timer = tm_new_set(pool, lsrt_timer_hook, n, 0, ifa->rxmtint);
|
||||
n->ackd_timer = tm_new_set(pool, ackd_timer_hook, n, 0, ifa->rxmtint / 2);
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
@ -188,6 +183,9 @@ ospf_neigh_chstate(struct ospf_neighbor *n, u8 state)
|
|||
|
||||
n->dds++;
|
||||
n->myimms = DBDES_IMMS;
|
||||
|
||||
tm_start(n->dbdes_timer, 0);
|
||||
tm_start(n->ackd_timer, ifa->rxmtint / 2);
|
||||
}
|
||||
|
||||
if (state > NEIGHBOR_EXSTART)
|
||||
|
@ -253,16 +251,16 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
|
|||
|
||||
/* Add MaxAge LSA entries to retransmission list */
|
||||
ospf_add_flushed_to_lsrt(p, n);
|
||||
|
||||
/* FIXME: Why is this here ? */
|
||||
ospf_reset_lsack_queue(n);
|
||||
}
|
||||
else
|
||||
bug("NEGDONE and I'm not in EXSTART?");
|
||||
break;
|
||||
|
||||
case INM_EXDONE:
|
||||
ospf_neigh_chstate(n, NEIGHBOR_LOADING);
|
||||
if (!EMPTY_SLIST(n->lsrql))
|
||||
ospf_neigh_chstate(n, NEIGHBOR_LOADING);
|
||||
else
|
||||
ospf_neigh_chstate(n, NEIGHBOR_FULL);
|
||||
break;
|
||||
|
||||
case INM_LOADDONE:
|
||||
|
@ -270,23 +268,15 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
|
|||
break;
|
||||
|
||||
case INM_ADJOK:
|
||||
switch (n->state)
|
||||
/* Can In build adjacency? */
|
||||
if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
|
||||
{
|
||||
case NEIGHBOR_2WAY:
|
||||
/* Can In build adjacency? */
|
||||
if (can_do_adj(n))
|
||||
{
|
||||
ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (n->state >= NEIGHBOR_EXSTART)
|
||||
if (!can_do_adj(n))
|
||||
{
|
||||
reset_lists(p, n);
|
||||
ospf_neigh_chstate(n, NEIGHBOR_2WAY);
|
||||
}
|
||||
break;
|
||||
ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
|
||||
}
|
||||
else if ((n->state >= NEIGHBOR_EXSTART) && !can_do_adj(n))
|
||||
{
|
||||
reset_lists(p, n);
|
||||
ospf_neigh_chstate(n, NEIGHBOR_2WAY);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -566,12 +556,12 @@ find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
|
|||
}
|
||||
|
||||
static void
|
||||
neighbor_timer_hook(timer * timer)
|
||||
inactivity_timer_hook(timer * timer)
|
||||
{
|
||||
struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
|
||||
struct ospf_proto *p = n->ifa->oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Inactivity timer expired for neighbor %R on %s",
|
||||
OSPF_TRACE(D_EVENTS, "Inactivity timer expired for nbr %R on %s",
|
||||
n->rid, n->ifa->ifname);
|
||||
ospf_neigh_sm(n, INM_INACTTIM);
|
||||
}
|
||||
|
@ -584,7 +574,7 @@ ospf_neigh_bfd_hook(struct bfd_request *req)
|
|||
|
||||
if (req->down)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "BFD session down for neighbor %R on %s",
|
||||
OSPF_TRACE(D_EVENTS, "BFD session down for nbr %R on %s",
|
||||
n->rid, n->ifa->ifname);
|
||||
ospf_neigh_sm(n, INM_INACTTIM);
|
||||
}
|
||||
|
@ -605,11 +595,60 @@ ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
dbdes_timer_hook(timer *t)
|
||||
{
|
||||
struct ospf_neighbor *n = t->data;
|
||||
struct ospf_proto *p = n->ifa->oa->po;
|
||||
|
||||
// OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
|
||||
|
||||
if (n->state == NEIGHBOR_EXSTART)
|
||||
ospf_send_dbdes(p, n);
|
||||
|
||||
if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS))
|
||||
ospf_rxmt_dbdes(p, n);
|
||||
}
|
||||
|
||||
static void
|
||||
lsrq_timer_hook(timer *t)
|
||||
{
|
||||
struct ospf_neighbor *n = t->data;
|
||||
struct ospf_proto *p = n->ifa->oa->po;
|
||||
|
||||
// OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
|
||||
|
||||
if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql))
|
||||
ospf_send_lsreq(p, n);
|
||||
}
|
||||
|
||||
static void
|
||||
lsrt_timer_hook(timer *t)
|
||||
{
|
||||
struct ospf_neighbor *n = t->data;
|
||||
struct ospf_proto *p = n->ifa->oa->po;
|
||||
|
||||
// OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
|
||||
|
||||
if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl))
|
||||
ospf_rxmt_lsupd(p, n);
|
||||
}
|
||||
|
||||
static void
|
||||
ackd_timer_hook(timer *t)
|
||||
{
|
||||
struct ospf_neighbor *n = t->data;
|
||||
struct ospf_proto *p = n->ifa->oa->po;
|
||||
|
||||
ospf_send_lsack(p, n, ACKL_DELAY);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ospf_sh_neigh_info(struct ospf_neighbor *n)
|
||||
{
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
char *pos = "ptp ";
|
||||
char *pos = "PtP ";
|
||||
char etime[6];
|
||||
int exp, sec, min;
|
||||
|
||||
|
@ -628,55 +667,13 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
|
|||
if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
|
||||
{
|
||||
if (n->rid == ifa->drid)
|
||||
pos = "dr ";
|
||||
pos = "DR ";
|
||||
else if (n->rid == ifa->bdrid)
|
||||
pos = "bdr ";
|
||||
pos = "BDR ";
|
||||
else
|
||||
pos = "other";
|
||||
pos = "Other";
|
||||
}
|
||||
|
||||
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
|
||||
ospf_ns_names[n->state], pos, etime, ifa->ifname, n->ip);
|
||||
}
|
||||
|
||||
static void
|
||||
rxmt_timer_hook(timer *t)
|
||||
{
|
||||
struct ospf_neighbor *n = t->data;
|
||||
struct ospf_proto *p = n->ifa->oa->po;
|
||||
|
||||
DBG("%s: RXMT timer fired on %s for neigh %I\n",
|
||||
p->p.name, n->ifa->ifname, n->ip);
|
||||
|
||||
switch (n->state)
|
||||
{
|
||||
case NEIGHBOR_EXSTART:
|
||||
ospf_send_dbdes(p, n);
|
||||
return;
|
||||
|
||||
case NEIGHBOR_EXCHANGE:
|
||||
if (n->myimms & DBDES_MS)
|
||||
ospf_rxmt_dbdes(p, n);
|
||||
case NEIGHBOR_LOADING:
|
||||
ospf_send_lsreq(p, n);
|
||||
return;
|
||||
|
||||
case NEIGHBOR_FULL:
|
||||
/* LSA retransmissions */
|
||||
if (!EMPTY_SLIST(n->lsrtl))
|
||||
ospf_rxmt_lsupd(p, n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ackd_timer_hook(timer *t)
|
||||
{
|
||||
struct ospf_neighbor *n = t->data;
|
||||
struct ospf_proto *p = n->ifa->oa->po;
|
||||
|
||||
DBG("%s: ACKD timer fired on %s for neigh %I\n",
|
||||
p->p.name, n->ifa->ifname, n->ip);
|
||||
|
||||
ospf_send_lsack(p, n, ACKL_DELAY);
|
||||
}
|
||||
|
|
|
@ -235,11 +235,7 @@ ospf_start(struct proto *P)
|
|||
p->asbr = c->asbr;
|
||||
p->ecmp = c->ecmp;
|
||||
p->tick = c->tick;
|
||||
p->disp_timer = tm_new(P->pool);
|
||||
p->disp_timer->data = p;
|
||||
p->disp_timer->randomize = 0;
|
||||
p->disp_timer->hook = ospf_disp;
|
||||
p->disp_timer->recurrent = p->tick;
|
||||
p->disp_timer = tm_new_set(P->pool, ospf_disp, p, 0, p->tick);
|
||||
tm_start(p->disp_timer, 1);
|
||||
p->lsab_size = 256;
|
||||
p->lsab_used = 0;
|
||||
|
@ -252,6 +248,10 @@ ospf_start(struct proto *P)
|
|||
p->gr = ospf_top_new(p, P->pool);
|
||||
s_init_list(&(p->lsal));
|
||||
|
||||
p->flood_event = ev_new(P->pool);
|
||||
p->flood_event->hook = ospf_flood_event;
|
||||
p->flood_event->data = p;
|
||||
|
||||
p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
|
||||
p->log_lsa_tbf = (struct tbf){ .rate = 4, .burst = 20 };
|
||||
|
||||
|
@ -1439,14 +1439,14 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
|
|||
break;
|
||||
}
|
||||
cli_msg(-1017, "");
|
||||
cli_msg(-1017," Type LS ID Router Age Sequence Checksum");
|
||||
cli_msg(-1017," Type LS ID Router Sequence Age Checksum");
|
||||
|
||||
last_dscope = dscope;
|
||||
last_domain = hea[i]->domain;
|
||||
}
|
||||
|
||||
cli_msg(-1017," %04x %-15R %-15R %5u %08x %04x",
|
||||
lsa_type, lsa->id, lsa->rt, lsa->age, lsa->sn, lsa->checksum);
|
||||
cli_msg(-1017," %04x %-15R %-15R %08x %5u %04x",
|
||||
lsa_type, lsa->id, lsa->rt, lsa->sn, lsa->age, lsa->checksum);
|
||||
}
|
||||
cli_msg(0, "");
|
||||
}
|
||||
|
|
|
@ -231,6 +231,7 @@ struct ospf_proto
|
|||
byte asbr; /* May i originate any ext/NSSA lsa? */
|
||||
byte ecmp; /* Maximal number of nexthops in ECMP route, or 0 */
|
||||
struct ospf_area *backbone; /* If exists */
|
||||
event *flood_event; /* Event for flooding LS updates */
|
||||
void *lsab; /* LSA buffer used when originating router LSAs */
|
||||
int lsab_size, lsab_used;
|
||||
linpool *nhpool; /* Linpool used for next hops computed in SPF */
|
||||
|
@ -317,8 +318,11 @@ struct ospf_iface
|
|||
struct top_hash_entry *link_lsa; /* Originated link LSA */
|
||||
struct top_hash_entry *net_lsa; /* Originated network LSA */
|
||||
struct top_hash_entry *pxn_lsa; /* Originated prefix LSA */
|
||||
struct top_hash_entry **flood_queue; /* LSAs queued for LSUPD */
|
||||
u8 update_link_lsa;
|
||||
u8 update_net_lsa;
|
||||
u16 flood_queue_used; /* The current number of LSAs in flood_queue */
|
||||
u16 flood_queue_size; /* The maximum number of LSAs in flood_queue */
|
||||
int fadj; /* Number of fully adjacent neighbors */
|
||||
list nbma_list;
|
||||
u8 priority; /* A router priority for DR election */
|
||||
|
@ -354,7 +358,6 @@ struct ospf_neighbor
|
|||
ip_addr ip; /* IP of it's interface */
|
||||
u8 priority; /* Priority */
|
||||
u8 adj; /* built adjacency? */
|
||||
u8 want_lsreq; /* Set to 1 when lsrql was shortened during LSUPD */
|
||||
u32 options; /* Options received */
|
||||
|
||||
/* Entries dr and bdr store IP addresses in OSPFv2 and router IDs in
|
||||
|
@ -373,6 +376,7 @@ struct ospf_neighbor
|
|||
*/
|
||||
slist lsrql; /* slist of struct top_hash_entry from n->lsrqh */
|
||||
struct top_graph *lsrqh;
|
||||
struct top_hash_entry *lsrqi; /* Pointer to the first unsent node in lsrql */
|
||||
|
||||
/* Link state retransmission list, controls LSA retransmission during flood.
|
||||
* Entries added as sent in lsupd packets, removed when received in lsack packets.
|
||||
|
@ -380,7 +384,9 @@ struct ospf_neighbor
|
|||
*/
|
||||
slist lsrtl; /* slist of struct top_hash_entry from n->lsrth */
|
||||
struct top_graph *lsrth;
|
||||
timer *rxmt_timer; /* RXMT timer */
|
||||
timer *dbdes_timer; /* DBDES exchange timer */
|
||||
timer *lsrq_timer; /* LSA request timer */
|
||||
timer *lsrt_timer; /* LSA retransmission timer */
|
||||
list ackl[2];
|
||||
#define ACKL_DIRECT 0
|
||||
#define ACKL_DELAY 1
|
||||
|
@ -940,7 +946,9 @@ void ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa, struct
|
|||
/* lsupd.c */
|
||||
void ospf_dump_lsahdr(struct ospf_proto *p, struct ospf_lsa_header *lsa_n);
|
||||
void ospf_dump_common(struct ospf_proto *p, struct ospf_packet *pkt);
|
||||
void ospf_lsa_lsrt_down_(struct top_hash_entry *en, struct ospf_neighbor *n, struct top_hash_entry *ret);
|
||||
void ospf_add_flushed_to_lsrt(struct ospf_proto *p, struct ospf_neighbor *n);
|
||||
void ospf_flood_event(void *ptr);
|
||||
int ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neighbor *from);
|
||||
int ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, struct ospf_neighbor *n);
|
||||
void ospf_rxmt_lsupd(struct ospf_proto *p, struct ospf_neighbor *n);
|
||||
|
|
|
@ -260,7 +260,7 @@ ospf_rx_hook(sock *sk, int len)
|
|||
* link-local src address, but does not enforce it. Strange.
|
||||
*/
|
||||
if (dst_mcast && !src_local)
|
||||
LOG_PKT_WARN("Multicast packet received from not-link-local %I via %s",
|
||||
LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s",
|
||||
sk->faddr, ifa->ifname);
|
||||
}
|
||||
|
||||
|
@ -396,8 +396,7 @@ found:
|
|||
|
||||
if (!n && (pkt->type != HELLO_P))
|
||||
{
|
||||
// XXXX format
|
||||
OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown neighbor %R on %s (%I)",
|
||||
OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
|
||||
rid, ifa->ifname, sk->faddr);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -404,9 +404,6 @@ ospf_refresh_lsa(struct ospf_proto *p, struct top_hash_entry *en)
|
|||
void
|
||||
ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Flushing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
|
||||
en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
|
||||
|
||||
if (en->next_lsa_body)
|
||||
{
|
||||
mb_free(en->next_lsa_body);
|
||||
|
@ -418,6 +415,9 @@ ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en)
|
|||
if (en->lsa.age == LSA_MAXAGE)
|
||||
return;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Flushing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
|
||||
en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
|
||||
|
||||
en->lsa.age = LSA_MAXAGE;
|
||||
ospf_flood_lsa(p, en, NULL);
|
||||
|
||||
|
@ -433,8 +433,12 @@ ospf_clear_lsa(struct ospf_proto *p, struct top_hash_entry *en)
|
|||
/*
|
||||
* Called by ospf_update_lsadb() as part of LSA flushing process.
|
||||
* Flushed LSA was acknowledged by neighbors and we can free its content.
|
||||
* The log message is for 'remove' - we hide empty LSAs from users.
|
||||
*/
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Removing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
|
||||
en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
|
||||
|
||||
if (en->lsa.sn == LSA_MAXSEQNO)
|
||||
en->lsa.sn = LSA_ZEROSEQNO;
|
||||
|
||||
|
@ -1143,6 +1147,9 @@ ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 m
|
|||
ospf_originate_lsa(p, &lsa);
|
||||
}
|
||||
|
||||
static struct top_hash_entry *
|
||||
ospf_hash_find_(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type);
|
||||
|
||||
static void
|
||||
ospf_flush_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf)
|
||||
{
|
||||
|
@ -1152,7 +1159,7 @@ ospf_flush_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf)
|
|||
u32 dom = oa ? oa->areaid : 0;
|
||||
u32 id = ort_to_lsaid(p, nf);
|
||||
|
||||
en = ospf_hash_find(p->gr, dom, id, p->router_id, type);
|
||||
en = ospf_hash_find_(p->gr, dom, id, p->router_id, type);
|
||||
|
||||
if (!en || (en->nf != nf))
|
||||
return;
|
||||
|
@ -1795,8 +1802,8 @@ ospf_top_rehash(struct top_graph *f, int step)
|
|||
ospf_top_ht_free(oldt);
|
||||
}
|
||||
|
||||
struct top_hash_entry *
|
||||
ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
||||
static struct top_hash_entry *
|
||||
ospf_hash_find_(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
||||
{
|
||||
struct top_hash_entry *e;
|
||||
e = f->hash_table[ospf_top_hash(f, domain, lsa, rtr, type)];
|
||||
|
@ -1805,6 +1812,14 @@ ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
|||
e->lsa_type != type || e->domain != domain))
|
||||
e = e->next;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
struct top_hash_entry *
|
||||
ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
||||
{
|
||||
struct top_hash_entry *e = ospf_hash_find_(f, domain, lsa, rtr, type);
|
||||
|
||||
/* Hide hash entry with empty lsa_body */
|
||||
return (e && e->lsa_body) ? e : NULL;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,12 @@ extern bird_clock_t now; /* Relative, monotonic time in seconds */
|
|||
extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */
|
||||
extern bird_clock_t boot_time;
|
||||
|
||||
static inline int
|
||||
tm_active(timer *t)
|
||||
{
|
||||
return t->expires != 0;
|
||||
}
|
||||
|
||||
static inline bird_clock_t
|
||||
tm_remains(timer *t)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue