summaryrefslogtreecommitdiff
path: root/proto/ospf/lsack.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/ospf/lsack.c')
-rw-r--r--proto/ospf/lsack.c225
1 files changed, 107 insertions, 118 deletions
diff --git a/proto/ospf/lsack.c b/proto/ospf/lsack.c
index fd8ead01..5cac3f69 100644
--- a/proto/ospf/lsack.c
+++ b/proto/ospf/lsack.c
@@ -1,7 +1,9 @@
/*
* BIRD -- OSPF
*
- * (c) 2000-2004 Ondrej Filip <feela@network.cz>
+ * (c) 2000--2004 Ondrej Filip <feela@network.cz>
+ * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
+ * (c) 2009--2014 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -9,184 +11,171 @@
#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;
+ struct ospf_lsa_header lsas[];
+};
+*/
-char *s_queue[] = { "direct", "delayed" };
+struct lsa_node
+{
+ node n;
+ struct ospf_lsa_header lsa;
+};
-static void ospf_dump_lsack(struct proto *p, struct ospf_lsack_packet *pkt)
+static inline void
+ospf_lsack_body(struct ospf_proto *p, struct ospf_packet *pkt,
+ struct ospf_lsa_header **body, uint *count)
{
- struct ospf_packet *op = &pkt->ospf_packet;
+ uint plen = ntohs(pkt->length);
+ uint hlen = ospf_pkt_hdrlen(p);
- ASSERT(op->type == LSACK_P);
- ospf_dump_common(p, op);
+ *body = ((void *) pkt) + hlen;
+ *count = (plen - hlen) / sizeof(struct ospf_lsa_header);
+}
- unsigned int i, j;
- j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) /
- sizeof(struct ospf_lsa_header);
+static void
+ospf_dump_lsack(struct ospf_proto *p, struct ospf_packet *pkt)
+{
+ struct ospf_lsa_header *lsas;
+ uint i, lsa_count;
- for (i = 0; i < j; i++)
- ospf_dump_lsahdr(p, pkt->lsh + i);
-}
+ ASSERT(pkt->type == LSACK_P);
+ ospf_dump_common(p, pkt);
+ ospf_lsack_body(p, pkt, &lsas, &lsa_count);
+ for (i = 0; i < lsa_count; i++)
+ ospf_dump_lsahdr(p, lsas + i);
+}
-/*
- * =====================================
- * Note, that h is in network endianity!
- * =====================================
- */
void
-ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h,
- int queue)
+ospf_enqueue_lsack(struct ospf_neighbor *n, struct ospf_lsa_header *h_n, int queue)
{
- struct lsah_n *no = mb_alloc(n->pool, sizeof(struct lsah_n));
- memcpy(&no->lsa, h, sizeof(struct ospf_lsa_header));
+ /* Note that h_n is in network endianity */
+ struct lsa_node *no = mb_alloc(n->pool, sizeof(struct lsa_node));
+ memcpy(&no->lsa, h_n, 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],
- n->rid, ntohl(h->id), ntohl(h->rt), h->type);
+ DBG("Adding %s ack for %R, ID: %R, RT: %R, Type: %u\n",
+ (queue == ACKL_DIRECT) ? "direct" : "delayed",
+ n->rid, ntohl(h_n->id), ntohl(h_n->rt), h_n->type);
}
void
-ospf_lsack_send(struct ospf_neighbor *n, int queue)
+ospf_reset_lsack_queue(struct ospf_neighbor *n)
{
- 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;
+ struct lsa_node *no;
- if (EMPTY_LIST(n->ackl[queue]))
- return;
+ WALK_LIST_FIRST(no, n->ackl[ACKL_DELAY])
+ {
+ rem_node(NODE no);
+ mb_free(no);
+ }
+}
- pk = ospf_tx_buffer(ifa);
- op = &pk->ospf_packet;
+static inline void
+ospf_send_lsack_(struct ospf_proto *p, struct ospf_neighbor *n, int queue)
+{
+ struct ospf_iface *ifa = n->ifa;
+ struct ospf_lsa_header *lsas;
+ struct ospf_packet *pkt;
+ struct lsa_node *no;
+ uint i, lsa_max, length;
- ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
- h = pk->lsh;
+ /* RFC 2328 13.5 */
- while (!EMPTY_LIST(n->ackl[queue]))
+ pkt = ospf_tx_buffer(ifa);
+ ospf_pkt_fill_hdr(ifa, pkt, LSACK_P);
+ ospf_lsack_body(p, pkt, &lsas, &lsa_max);
+
+ 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++;
+ no = (struct lsa_node *) HEAD(n->ackl[queue]);
+ 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->ifname);
-
- 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(p) + i * sizeof(struct ospf_lsa_header);
+ pkt->length = htons(length);
- OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->ifname);
+ OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet sent 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 if (ifa->cf->real_bcast)
- ospf_send_to_bdr(ifa);
else
- ospf_send_to(ifa, AllDRouters);
+ ospf_send_to_des(ifa);
}
else
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
}
void
-ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
+ospf_send_lsack(struct ospf_proto *p, struct ospf_neighbor *n, int queue)
+{
+ while (!EMPTY_LIST(n->ackl[queue]))
+ ospf_send_lsack_(p, n, queue);
+}
+
+void
+ospf_receive_lsack(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 top_hash_entry *en;
- unsigned int i, lsano;
+ struct ospf_proto *p = ifa->oa->po;
+ struct ospf_lsa_header lsa, *lsas;
+ struct top_hash_entry *ret, *en;
+ uint i, lsa_count;
+ u32 lsa_type, lsa_domain;
- 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;
- }
+ /* RFC 2328 13.7 */
- struct ospf_lsack_packet *ps = (void *) ps_i;
- OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->ifname);
+ /* No need to check length, lsack has only basic header */
- ospf_neigh_sm(n, INM_HELLOREC);
+ OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet received from %I via %s", n->ip, ifa->ifname);
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(p, pkt, &lsas, &lsa_count);
+ for (i = 0; i < lsa_count; i++)
{
- ntohlsah(ps->lsh + 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 */
+ lsa_ntoh_hdr(&lsas[i], &lsa);
+ lsa_get_type_domain(&lsa, n->ifa, &lsa_type, &lsa_domain);
- if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */
- {
- if ((lsa.sn == LSA_MAXSEQNO) && (lsa.age == LSA_MAXAGE))
- continue;
+ ret = ospf_hash_find(n->lsrth, lsa_domain, lsa.id, lsa.rt, lsa_type);
+ if (!ret)
+ continue;
+ 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",
- lsa.type, lsa.id, lsa.rt);
+ lsa_type, lsa.id, lsa.rt);
OSPF_TRACE(D_PACKETS, "I have: Age: %4u, Seq: %08x, Sum: %04x",
- en->lsa.age, en->lsa.sn, en->lsa.checksum);
+ 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);
continue;
}
- DBG("Deleting LS Id: %R RT: %R Type: %u from LS Retl for neighbor %R\n",
- lsa.id, lsa.rt, lsa.type, n->rid);
- s_rem_node(SNODE en);
- ospf_hash_delete(n->lsrth, en);
+ 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);
}
}