]> git.ipfire.org Git - thirdparty/bird.git/blame - proto/ospf/lsack.c
Real broadcast mode for OSPFv2.
[thirdparty/bird.git] / proto / ospf / lsack.c
CommitLineData
de769e24
OF
1/*
2 * BIRD -- OSPF
3 *
c76ba51a 4 * (c) 2000-2004 Ondrej Filip <feela@network.cz>
de769e24
OF
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9#include "ospf.h"
10
c3226991
OZ
11
12struct ospf_lsack_packet
13{
14 struct ospf_packet ospf_packet;
15 struct ospf_lsa_header lsh[];
16};
17
18
fb9bf688 19char *s_queue[] = { "direct", "delayed" };
67315ef6 20
8298d780
OZ
21
22static void ospf_dump_lsack(struct proto *p, struct ospf_lsack_packet *pkt)
23{
24 struct ospf_packet *op = &pkt->ospf_packet;
25
26 ASSERT(op->type == LSACK_P);
27 ospf_dump_common(p, op);
28
a6bc04d5 29 unsigned int i, j;
8298d780
OZ
30 j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) /
31 sizeof(struct ospf_lsa_header);
32
33 for (i = 0; i < j; i++)
c3226991 34 ospf_dump_lsahdr(p, pkt->lsh + i);
8298d780
OZ
35}
36
37
c76ba51a
OF
38/*
39 * =====================================
40 * Note, that h is in network endianity!
41 * =====================================
42 */
fb9bf688 43
67315ef6 44void
fb9bf688 45ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h,
8e15e048 46 int queue)
67315ef6 47{
8e15e048 48 struct lsah_n *no = mb_alloc(n->pool, sizeof(struct lsah_n));
fb9bf688 49 memcpy(&no->lsa, h, sizeof(struct ospf_lsa_header));
c76ba51a 50 add_tail(&n->ackl[queue], NODE no);
3aab39f5
OZ
51 DBG("Adding (%s) ack for %R, ID: %R, RT: %R, Type: %u\n", s_queue[queue],
52 n->rid, ntohl(h->id), ntohl(h->rt), h->type);
67315ef6
OF
53}
54
67315ef6 55void
c76ba51a 56ospf_lsack_send(struct ospf_neighbor *n, int queue)
67315ef6
OF
57{
58 struct ospf_packet *op;
59 struct ospf_lsack_packet *pk;
fb9bf688 60 u16 len, i = 0;
67315ef6
OF
61 struct ospf_lsa_header *h;
62 struct lsah_n *no;
fb9bf688 63 struct ospf_iface *ifa = n->ifa;
86c84d76 64 struct proto *p = &n->ifa->oa->po->proto;
67315ef6 65
fb9bf688
OF
66 if (EMPTY_LIST(n->ackl[queue]))
67 return;
c76ba51a 68
e7b76b97 69 pk = ospf_tx_buffer(ifa);
353729f5 70 op = &pk->ospf_packet;
67315ef6 71
3e2bd0f1 72 ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
c3226991 73 h = pk->lsh;
67315ef6 74
fb9bf688 75 while (!EMPTY_LIST(n->ackl[queue]))
67315ef6 76 {
fb9bf688
OF
77 no = (struct lsah_n *) HEAD(n->ackl[queue]);
78 memcpy(h + i, &no->lsa, sizeof(struct ospf_lsa_header));
69fbf9a2 79 DBG("Iter %u ID: %R, RT: %R, Type: %04x\n", i, ntohl((h + i)->id),
3aab39f5 80 ntohl((h + i)->rt), (h + i)->type);
69fbf9a2 81 i++;
023f5e86 82 rem_node(NODE no);
284c43ff 83 mb_free(no);
fb9bf688 84 if ((i * sizeof(struct ospf_lsa_header) +
3e2bd0f1 85 sizeof(struct ospf_lsack_packet)) > ospf_pkt_maxsize(n->ifa))
67315ef6 86 {
fb9bf688 87 if (!EMPTY_LIST(n->ackl[queue]))
67315ef6 88 {
fb9bf688
OF
89 len =
90 sizeof(struct ospf_lsack_packet) +
91 i * sizeof(struct ospf_lsa_header);
92 op->length = htons(len);
fb9bf688 93 DBG("Sending and continuing! Len=%u\n", len);
8298d780 94
353729f5 95 OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name);
8298d780 96
fb9bf688 97 if (ifa->type == OSPF_IT_BCAST)
67315ef6 98 {
fb9bf688 99 if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
95127cbb
OZ
100 ospf_send_to_all(ifa);
101 else if (ifa->cf->real_bcast)
102 ospf_send_to_bdr(ifa);
67315ef6 103 else
f9c799a0 104 ospf_send_to(ifa, AllDRouters);
67315ef6
OF
105 }
106 else
107 {
fb9bf688 108 if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
f9c799a0 109 ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
eb436e16 110 else
f9c799a0 111 ospf_send_to_bdr(ifa);
67315ef6 112 }
284c43ff 113
3e2bd0f1 114 ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
fb9bf688 115 i = 0;
67315ef6
OF
116 }
117 }
118 }
119
fb9bf688
OF
120 len = sizeof(struct ospf_lsack_packet) + i * sizeof(struct ospf_lsa_header);
121 op->length = htons(len);
fb9bf688 122 DBG("Sending! Len=%u\n", len);
8298d780 123
353729f5 124 OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name);
8298d780 125
fb9bf688 126 if (ifa->type == OSPF_IT_BCAST)
67315ef6 127 {
fb9bf688 128 if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
95127cbb
OZ
129 ospf_send_to_all(ifa);
130 else if (ifa->cf->real_bcast)
131 ospf_send_to_bdr(ifa);
67315ef6 132 else
f9c799a0 133 ospf_send_to(ifa, AllDRouters);
67315ef6
OF
134 }
135 else
f9c799a0 136 ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
de769e24
OF
137}
138
139void
c3226991
OZ
140ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
141 struct ospf_neighbor *n)
de769e24 142{
a6bc04d5 143 struct proto *p = &ifa->oa->po->proto;
c3226991 144 struct ospf_lsa_header lsa;
4bf41ac8 145 struct top_hash_entry *en;
a6bc04d5
OZ
146 unsigned int i, lsano;
147
148 unsigned int size = ntohs(ps_i->length);
149 if (size < sizeof(struct ospf_lsack_packet))
150 {
151 log(L_ERR "Bad OSPF LSACK packet from %I - too short (%u B)", n->ip, size);
152 return;
153 }
ebff007f 154
a6bc04d5 155 struct ospf_lsack_packet *ps = (void *) ps_i;
8298d780
OZ
156 OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->iface->name);
157
4bb9ce56 158 ospf_neigh_sm(n, INM_HELLOREC);
9669362f 159
fb9bf688
OF
160 if (n->state < NEIGHBOR_EXCHANGE)
161 return;
9669362f 162
a6bc04d5 163 lsano = (size - sizeof(struct ospf_lsack_packet)) /
4bf41ac8 164 sizeof(struct ospf_lsa_header);
a6bc04d5 165 for (i = 0; i < lsano; i++)
4bf41ac8 166 {
c3226991 167 ntohlsah(ps->lsh + i, &lsa);
b49e6f5a
OZ
168 u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
169 if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL)
2e10a170 170 continue; /* pg 155 */
4bf41ac8 171
9b7de4c4 172 if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */
4bf41ac8 173 {
fb9bf688
OF
174 if ((lsa.sn == LSA_MAXSEQNO) && (lsa.age == LSA_MAXAGE))
175 continue;
37282678 176
34a877cc
OZ
177 OSPF_TRACE(D_PACKETS, "Strange LSACK from %I", n->ip);
178 OSPF_TRACE(D_PACKETS, "Type: %04x, Id: %R, Rt: %R",
179 lsa.type, lsa.id, lsa.rt);
180 OSPF_TRACE(D_PACKETS, "I have: Age: %4u, Seq: %08x, Sum: %04x",
fb9bf688 181 en->lsa.age, en->lsa.sn, en->lsa.checksum);
34a877cc 182 OSPF_TRACE(D_PACKETS, "He has: Age: %4u, Seq: %08x, Sum: %04x",
fb9bf688 183 lsa.age, lsa.sn, lsa.checksum);
4bf41ac8
OF
184 continue;
185 }
186
3aab39f5
OZ
187 DBG("Deleting LS Id: %R RT: %R Type: %u from LS Retl for neighbor %R\n",
188 lsa.id, lsa.rt, lsa.type, n->rid);
4bf41ac8 189 s_rem_node(SNODE en);
fb9bf688
OF
190 ospf_hash_delete(n->lsrth, en);
191 }
de769e24 192}