iof-bird-daemon / proto / ospf / lsupd.c @ a7a7372a
History | View | Annotate | Download (16 KB)
1 |
/*
|
---|---|
2 |
* BIRD -- OSPF
|
3 |
*
|
4 |
* (c) 2000--2004 Ondrej Filip <feela@network.cz>
|
5 |
* (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
|
6 |
* (c) 2009--2014 CZ.NIC z.s.p.o.
|
7 |
*
|
8 |
* Can be freely distributed and used under the terms of the GNU GPL.
|
9 |
*/
|
10 |
|
11 |
#include "ospf.h" |
12 |
|
13 |
|
14 |
/*
|
15 |
struct ospf_lsupd_packet
|
16 |
{
|
17 |
struct ospf_packet hdr;
|
18 |
// union ospf_auth auth;
|
19 |
|
20 |
u32 lsa_count;
|
21 |
void lsas[];
|
22 |
};
|
23 |
*/
|
24 |
|
25 |
|
26 |
void
|
27 |
ospf_dump_lsahdr(struct ospf_proto *p, struct ospf_lsa_header *lsa_n) |
28 |
{ |
29 |
struct ospf_lsa_header lsa;
|
30 |
u32 lsa_etype; |
31 |
|
32 |
lsa_ntoh_hdr(lsa_n, &lsa); |
33 |
lsa_etype = lsa_get_etype(&lsa, p); |
34 |
|
35 |
log(L_TRACE "%s: LSA Type: %04x, Id: %R, Rt: %R, Age: %u, Seq: %08x, Sum: %04x",
|
36 |
p->p.name, lsa_etype, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum); |
37 |
} |
38 |
|
39 |
void
|
40 |
ospf_dump_common(struct ospf_proto *p, struct ospf_packet *pkt) |
41 |
{ |
42 |
log(L_TRACE "%s: length %d", p->p.name, ntohs(pkt->length));
|
43 |
log(L_TRACE "%s: router %R", p->p.name, ntohl(pkt->routerid));
|
44 |
} |
45 |
|
46 |
static inline uint |
47 |
ospf_lsupd_hdrlen(struct ospf_proto *p)
|
48 |
{ |
49 |
return ospf_pkt_hdrlen(p) + 4; /* + u32 lsa count field */ |
50 |
} |
51 |
|
52 |
static inline u32 |
53 |
ospf_lsupd_get_lsa_count(struct ospf_packet *pkt, uint hdrlen)
|
54 |
{ |
55 |
u32 *c = ((void *) pkt) + hdrlen - 4; |
56 |
return ntohl(*c);
|
57 |
} |
58 |
|
59 |
static inline void |
60 |
ospf_lsupd_set_lsa_count(struct ospf_packet *pkt, uint hdrlen, u32 val)
|
61 |
{ |
62 |
u32 *c = ((void *) pkt) + hdrlen - 4; |
63 |
*c = htonl(val); |
64 |
} |
65 |
|
66 |
static inline void |
67 |
ospf_lsupd_body(struct ospf_proto *p, struct ospf_packet *pkt, |
68 |
uint *offset, uint *bound, uint *lsa_count) |
69 |
{ |
70 |
uint hlen = ospf_lsupd_hdrlen(p); |
71 |
*offset = hlen; |
72 |
*bound = ntohs(pkt->length) - sizeof(struct ospf_lsa_header); |
73 |
*lsa_count = ospf_lsupd_get_lsa_count(pkt, hlen); |
74 |
} |
75 |
|
76 |
static void |
77 |
ospf_dump_lsupd(struct ospf_proto *p, struct ospf_packet *pkt) |
78 |
{ |
79 |
uint offset, bound, i, lsa_count, lsalen; |
80 |
|
81 |
ASSERT(pkt->type == LSUPD_P); |
82 |
ospf_dump_common(p, pkt); |
83 |
|
84 |
ospf_lsupd_body(p, pkt, &offset, &bound, &lsa_count); |
85 |
for (i = 0; i < lsa_count; i++) |
86 |
{ |
87 |
if (offset > bound)
|
88 |
{ |
89 |
log(L_TRACE "%s: LSA invalid", p->p.name);
|
90 |
return;
|
91 |
} |
92 |
|
93 |
struct ospf_lsa_header *lsa = ((void *) pkt) + offset; |
94 |
ospf_dump_lsahdr(p, lsa); |
95 |
lsalen = ntohs(lsa->length); |
96 |
offset += lsalen; |
97 |
|
98 |
if (((lsalen % 4) != 0) || (lsalen <= sizeof(struct ospf_lsa_header))) |
99 |
{ |
100 |
log(L_TRACE "%s: LSA invalid", p->p.name);
|
101 |
return;
|
102 |
} |
103 |
} |
104 |
} |
105 |
|
106 |
|
107 |
static inline void |
108 |
ospf_lsa_lsrt_up(struct top_hash_entry *en, struct ospf_neighbor *n) |
109 |
{ |
110 |
struct top_hash_entry *ret = ospf_hash_get_entry(n->lsrth, en);
|
111 |
|
112 |
if (!SNODE_VALID(ret))
|
113 |
{ |
114 |
en->ret_count++; |
115 |
s_add_tail(&n->lsrtl, SNODE ret); |
116 |
} |
117 |
|
118 |
ret->lsa = en->lsa; |
119 |
ret->lsa_body = LSA_BODY_DUMMY; |
120 |
} |
121 |
|
122 |
static inline int |
123 |
ospf_lsa_lsrt_down(struct top_hash_entry *en, struct ospf_neighbor *n) |
124 |
{ |
125 |
struct top_hash_entry *ret = ospf_hash_find_entry(n->lsrth, en);
|
126 |
|
127 |
if (ret)
|
128 |
{ |
129 |
en->ret_count--; |
130 |
s_rem_node(SNODE ret); |
131 |
ospf_hash_delete(n->lsrth, ret); |
132 |
return 1; |
133 |
} |
134 |
|
135 |
return 0; |
136 |
} |
137 |
|
138 |
void
|
139 |
ospf_add_flushed_to_lsrt(struct ospf_proto *p, struct ospf_neighbor *n) |
140 |
{ |
141 |
struct top_hash_entry *en;
|
142 |
|
143 |
WALK_SLIST(en, p->lsal) |
144 |
if ((en->lsa.age == LSA_MAXAGE) && (en->lsa_body != NULL) && |
145 |
lsa_flooding_allowed(en->lsa_type, en->domain, n->ifa)) |
146 |
ospf_lsa_lsrt_up(en, n); |
147 |
} |
148 |
|
149 |
|
150 |
static void ospf_send_lsupd_to_ifa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa); |
151 |
|
152 |
|
153 |
/**
|
154 |
* ospf_flood_lsa - send LSA to the neighbors
|
155 |
* @p: OSPF protocol instance
|
156 |
* @en: LSA entry
|
157 |
* @from: neighbor than sent this LSA (or NULL if LSA is local)
|
158 |
*
|
159 |
* return value - was the LSA flooded back?
|
160 |
*/
|
161 |
int
|
162 |
ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neighbor *from) |
163 |
{ |
164 |
struct ospf_iface *ifa;
|
165 |
struct ospf_neighbor *n;
|
166 |
|
167 |
/* RFC 2328 13.3 */
|
168 |
|
169 |
int back = 0; |
170 |
WALK_LIST(ifa, p->iface_list) |
171 |
{ |
172 |
if (ifa->stub)
|
173 |
continue;
|
174 |
|
175 |
if (! lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
|
176 |
continue;
|
177 |
|
178 |
DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
|
179 |
hh->type, hh->id, hh->rt, hh->sn, hh->age); |
180 |
|
181 |
int used = 0; |
182 |
WALK_LIST(n, ifa->neigh_list) |
183 |
{ |
184 |
/* 13.3 (1a) */
|
185 |
if (n->state < NEIGHBOR_EXCHANGE)
|
186 |
continue;
|
187 |
|
188 |
/* 13.3 (1b) */
|
189 |
if (n->state < NEIGHBOR_FULL)
|
190 |
{ |
191 |
struct top_hash_entry *req = ospf_hash_find_entry(n->lsrqh, en);
|
192 |
if (req != NULL) |
193 |
{ |
194 |
int cmp = lsa_comp(&en->lsa, &req->lsa);
|
195 |
|
196 |
/* If same or newer, remove LSA from the link state request list */
|
197 |
if (cmp > CMP_OLDER)
|
198 |
{ |
199 |
s_rem_node(SNODE req); |
200 |
ospf_hash_delete(n->lsrqh, req); |
201 |
n->want_lsreq = 1;
|
202 |
|
203 |
if ((EMPTY_SLIST(n->lsrql)) && (n->state == NEIGHBOR_LOADING))
|
204 |
ospf_neigh_sm(n, INM_LOADDONE); |
205 |
} |
206 |
|
207 |
/* If older or same, skip processing of this neighbor */
|
208 |
if (cmp < CMP_NEWER)
|
209 |
continue;
|
210 |
} |
211 |
} |
212 |
|
213 |
/* 13.3 (1c) */
|
214 |
if (n == from)
|
215 |
continue;
|
216 |
|
217 |
/* In OSPFv3, there should be check whether receiving router understand
|
218 |
that type of LSA (for LSA types with U-bit == 0). But as we do not support
|
219 |
any optional LSA types, this is not needed yet */
|
220 |
|
221 |
/* 13.3 (1d) - add LSA to the link state retransmission list */
|
222 |
ospf_lsa_lsrt_up(en, n); |
223 |
|
224 |
used = 1;
|
225 |
} |
226 |
|
227 |
/* 13.3 (2) */
|
228 |
if (!used)
|
229 |
continue;
|
230 |
|
231 |
if (from && (from->ifa == ifa))
|
232 |
{ |
233 |
/* 13.3 (3) */
|
234 |
if ((from->rid == ifa->drid) || (from->rid == ifa->bdrid))
|
235 |
continue;
|
236 |
|
237 |
/* 13.3 (4) */
|
238 |
if (ifa->state == OSPF_IS_BACKUP)
|
239 |
continue;
|
240 |
|
241 |
back = 1;
|
242 |
} |
243 |
|
244 |
/* 13.3 (5) - finally flood the packet */
|
245 |
ospf_send_lsupd_to_ifa(p, en, ifa); |
246 |
} |
247 |
|
248 |
return back;
|
249 |
} |
250 |
|
251 |
static uint
|
252 |
ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa, |
253 |
struct top_hash_entry **lsa_list, uint lsa_count)
|
254 |
{ |
255 |
struct ospf_packet *pkt;
|
256 |
uint hlen, pos, i, maxsize; |
257 |
|
258 |
pkt = ospf_tx_buffer(ifa); |
259 |
hlen = ospf_lsupd_hdrlen(p); |
260 |
maxsize = ospf_pkt_maxsize(ifa); |
261 |
|
262 |
ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P); |
263 |
pos = hlen; |
264 |
|
265 |
for (i = 0; i < lsa_count; i++) |
266 |
{ |
267 |
struct top_hash_entry *en = lsa_list[i];
|
268 |
uint len = en->lsa.length; |
269 |
|
270 |
if ((pos + len) > maxsize)
|
271 |
{ |
272 |
/* The packet if full, stop adding LSAs and sent it */
|
273 |
if (i > 0) |
274 |
break;
|
275 |
|
276 |
/* LSA is larger than MTU, check buffer size */
|
277 |
if (ospf_iface_assure_bufsize(ifa, pos + len) < 0) |
278 |
{ |
279 |
/* Cannot fit in a tx buffer, skip that */
|
280 |
log(L_ERR "%s: LSA too large to send on %s (Type: %04x, Id: %R, Rt: %R)",
|
281 |
p->p.name, ifa->ifname, en->lsa_type, en->lsa.id, en->lsa.rt); |
282 |
break;
|
283 |
} |
284 |
|
285 |
/* TX buffer could be reallocated */
|
286 |
pkt = ospf_tx_buffer(ifa); |
287 |
} |
288 |
|
289 |
struct ospf_lsa_header *buf = ((void *) pkt) + pos; |
290 |
lsa_hton_hdr(&en->lsa, buf); |
291 |
lsa_hton_body(en->lsa_body, ((void *) buf) + sizeof(struct ospf_lsa_header), |
292 |
len - sizeof(struct ospf_lsa_header)); |
293 |
buf->age = htons(MIN(en->lsa.age + ifa->inftransdelay, LSA_MAXAGE)); |
294 |
|
295 |
pos += len; |
296 |
} |
297 |
|
298 |
ospf_lsupd_set_lsa_count(pkt, hlen, i); |
299 |
pkt->length = htons(pos); |
300 |
|
301 |
return i;
|
302 |
} |
303 |
|
304 |
|
305 |
static void |
306 |
ospf_send_lsupd_to_ifa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa) |
307 |
{ |
308 |
uint c = ospf_prepare_lsupd(p, ifa, &en, 1);
|
309 |
|
310 |
if (!c) /* Too large LSA */ |
311 |
return;
|
312 |
|
313 |
OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa), |
314 |
"LSUPD packet flooded via %s", ifa->ifname);
|
315 |
|
316 |
if (ifa->type == OSPF_IT_BCAST)
|
317 |
{ |
318 |
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
319 |
ospf_send_to_all(ifa); |
320 |
else
|
321 |
ospf_send_to_des(ifa); |
322 |
} |
323 |
else
|
324 |
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE); |
325 |
} |
326 |
|
327 |
int
|
328 |
ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, struct ospf_neighbor *n) |
329 |
{ |
330 |
struct ospf_iface *ifa = n->ifa;
|
331 |
uint i, c; |
332 |
|
333 |
for (i = 0; i < lsa_count; i += c) |
334 |
{ |
335 |
c = ospf_prepare_lsupd(p, ifa, lsa_list + i, lsa_count - i); |
336 |
|
337 |
if (!c) /* Too large LSA */ |
338 |
{ i++; continue; }
|
339 |
|
340 |
OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa), |
341 |
"LSUPD packet sent to %I via %s", n->ip, ifa->ifname);
|
342 |
|
343 |
ospf_send_to(ifa, n->ip); |
344 |
} |
345 |
|
346 |
return lsa_count;
|
347 |
} |
348 |
|
349 |
void
|
350 |
ospf_rxmt_lsupd(struct ospf_proto *p, struct ospf_neighbor *n) |
351 |
{ |
352 |
const uint max = 128; |
353 |
struct top_hash_entry *entries[max];
|
354 |
struct top_hash_entry *ret, *nxt, *en;
|
355 |
uint i = 0;
|
356 |
|
357 |
WALK_SLIST_DELSAFE(ret, nxt, n->lsrtl) |
358 |
{ |
359 |
if (i == max)
|
360 |
break;
|
361 |
|
362 |
en = ospf_hash_find_entry(p->gr, ret); |
363 |
if (!en)
|
364 |
{ |
365 |
/* Probably flushed LSA, this should not happen */
|
366 |
log(L_WARN "%s: LSA disappeared (Type: %04x, Id: %R, Rt: %R)",
|
367 |
p->p.name, ret->lsa_type, ret->lsa.id, ret->lsa.rt); |
368 |
|
369 |
s_rem_node(SNODE ret); |
370 |
ospf_hash_delete(n->lsrth, ret); |
371 |
|
372 |
continue;
|
373 |
} |
374 |
|
375 |
entries[i] = en; |
376 |
i++; |
377 |
} |
378 |
|
379 |
ospf_send_lsupd(p, entries, i, n); |
380 |
} |
381 |
|
382 |
|
383 |
static inline int |
384 |
ospf_addr_is_local(struct ospf_proto *p, struct ospf_area *oa, ip_addr ip) |
385 |
{ |
386 |
struct ospf_iface *ifa;
|
387 |
WALK_LIST(ifa, p->iface_list) |
388 |
if ((ifa->oa == oa) && ifa->addr && ipa_equal(ifa->addr->ip, ip))
|
389 |
return 1; |
390 |
|
391 |
return 0; |
392 |
} |
393 |
|
394 |
void
|
395 |
ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, |
396 |
struct ospf_neighbor *n)
|
397 |
{ |
398 |
struct ospf_proto *p = ifa->oa->po;
|
399 |
|
400 |
/* RFC 2328 13. */
|
401 |
|
402 |
int skip_lsreq = 0; |
403 |
n->want_lsreq = 0;
|
404 |
|
405 |
uint plen = ntohs(pkt->length); |
406 |
if (plen < (ospf_lsupd_hdrlen(p) + sizeof(struct ospf_lsa_header))) |
407 |
{ |
408 |
log(L_ERR "OSPF: Bad LSUPD packet from %I - too short (%u B)", n->ip, plen);
|
409 |
return;
|
410 |
} |
411 |
|
412 |
OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from %I via %s", n->ip, ifa->ifname);
|
413 |
|
414 |
if (n->state < NEIGHBOR_EXCHANGE)
|
415 |
{ |
416 |
OSPF_TRACE(D_PACKETS, "Received lsupd in lesser state than EXCHANGE from (%I)", n->ip);
|
417 |
return;
|
418 |
} |
419 |
|
420 |
ospf_neigh_sm(n, INM_HELLOREC); /* Questionable */
|
421 |
|
422 |
uint offset, bound, i, lsa_count; |
423 |
ospf_lsupd_body(p, pkt, &offset, &bound, &lsa_count); |
424 |
|
425 |
for (i = 0; i < lsa_count; i++) |
426 |
{ |
427 |
struct ospf_lsa_header lsa, *lsa_n;
|
428 |
struct top_hash_entry *en;
|
429 |
u32 lsa_len, lsa_type, lsa_domain; |
430 |
|
431 |
if (offset > bound)
|
432 |
{ |
433 |
log(L_WARN "%s: Received LSUPD from %I is too short", p->p.name, n->ip);
|
434 |
ospf_neigh_sm(n, INM_BADLSREQ); |
435 |
return;
|
436 |
} |
437 |
|
438 |
/* LSA header in network order */
|
439 |
lsa_n = ((void *) pkt) + offset;
|
440 |
lsa_len = ntohs(lsa_n->length); |
441 |
offset += lsa_len; |
442 |
|
443 |
if ((offset > plen) || ((lsa_len % 4) != 0) || |
444 |
(lsa_len <= sizeof(struct ospf_lsa_header))) |
445 |
{ |
446 |
log(L_WARN "%s: Received LSA from %I with bad length", p->p.name, n->ip);
|
447 |
ospf_neigh_sm(n, INM_BADLSREQ); |
448 |
return;
|
449 |
} |
450 |
|
451 |
/* RFC 2328 13. (1) - validate LSA checksum */
|
452 |
u16 chsum = lsa_n->checksum; |
453 |
if (chsum != lsasum_check(lsa_n, NULL)) |
454 |
{ |
455 |
log(L_WARN "%s: Received LSA from %I with bad checksum: %x %x",
|
456 |
p->p.name, n->ip, chsum, lsa_n->checksum); |
457 |
continue;
|
458 |
} |
459 |
|
460 |
/* LSA header in host order */
|
461 |
lsa_ntoh_hdr(lsa_n, &lsa); |
462 |
lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain); |
463 |
|
464 |
DBG("Update Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
|
465 |
lsa_type, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum); |
466 |
|
467 |
/* RFC 2328 13. (2) */
|
468 |
if (!lsa_type)
|
469 |
{ |
470 |
log(L_WARN "%s: Received unknown LSA type from %I", p->p.name, n->ip);
|
471 |
continue;
|
472 |
} |
473 |
|
474 |
/* RFC 5340 4.5.1 (2) and RFC 2328 13. (3) */
|
475 |
if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
|
476 |
{ |
477 |
log(L_WARN "%s: Received LSA with AS scope in stub area from %I", p->p.name, n->ip);
|
478 |
continue;
|
479 |
} |
480 |
|
481 |
/* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
|
482 |
if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
|
483 |
{ |
484 |
log(L_WARN "%s: Received rt-summary-LSA in stub area from %I", p->p.name, n->ip);
|
485 |
continue;
|
486 |
} |
487 |
|
488 |
/* RFC 5340 4.5.1 (3) */
|
489 |
if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
|
490 |
{ |
491 |
log(L_WARN "%s: Received LSA with invalid scope from %I", p->p.name, n->ip);
|
492 |
continue;
|
493 |
} |
494 |
|
495 |
/* Find local copy of LSA in link state database */
|
496 |
en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type); |
497 |
|
498 |
#ifdef LOCAL_DEBUG
|
499 |
if (en)
|
500 |
DBG("I have Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
|
501 |
en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age, en->lsa.checksum); |
502 |
#endif
|
503 |
|
504 |
/* 13. (4) - ignore maxage LSA if i have no local copy */
|
505 |
if ((lsa.age == LSA_MAXAGE) && !en && (p->padj == 0)) |
506 |
{ |
507 |
/* 13.5. - schedule ACKs (tbl 19, case 5) */
|
508 |
ospf_enqueue_lsack(n, lsa_n, ACKL_DIRECT); |
509 |
continue;
|
510 |
} |
511 |
|
512 |
/* 13. (5) - received LSA is newer (or no local copy) */
|
513 |
if (!en || (lsa_comp(&lsa, &en->lsa) == CMP_NEWER))
|
514 |
{ |
515 |
/* 13. (5a) - enforce minimum time between updates for received LSAs */
|
516 |
/* We also use this to ratelimit reactions to received self-originated LSAs */
|
517 |
if (en && ((now - en->inst_time) < MINLSARRIVAL))
|
518 |
{ |
519 |
OSPF_TRACE(D_EVENTS, "Skipping LSA received in less that MinLSArrival");
|
520 |
skip_lsreq = 1;
|
521 |
continue;
|
522 |
} |
523 |
|
524 |
/* Copy and validate LSA body */
|
525 |
int blen = lsa.length - sizeof(struct ospf_lsa_header); |
526 |
void *body = mb_alloc(p->p.pool, blen);
|
527 |
lsa_ntoh_body(lsa_n + 1, body, blen);
|
528 |
|
529 |
if (lsa_validate(&lsa, lsa_type, ospf_is_v2(p), body) == 0) |
530 |
{ |
531 |
log(L_WARN "%s: Received invalid LSA from %I", p->p.name, n->ip);
|
532 |
mb_free(body); |
533 |
continue;
|
534 |
} |
535 |
|
536 |
/* 13. (5f) - handle self-originated LSAs, see also 13.4. */
|
537 |
if ((lsa.rt == p->router_id) ||
|
538 |
(ospf_is_v2(p) && (lsa_type == LSA_T_NET) && ospf_addr_is_local(p, ifa->oa, ipa_from_u32(lsa.id)))) |
539 |
{ |
540 |
OSPF_TRACE(D_EVENTS, "Received unexpected self-originated LSA");
|
541 |
ospf_advance_lsa(p, en, &lsa, lsa_type, lsa_domain, body); |
542 |
continue;
|
543 |
} |
544 |
|
545 |
/* 13. (5c) - remove old LSA from all retransmission lists */
|
546 |
/*
|
547 |
* We only need to remove it from the retransmission list of the neighbor
|
548 |
* that send us the new LSA. The old LSA is automatically replaced in
|
549 |
* retransmission lists by the new LSA.
|
550 |
*/
|
551 |
if (en)
|
552 |
ospf_lsa_lsrt_down(en, n); |
553 |
|
554 |
#if 0
|
555 |
/*
|
556 |
* Old code for removing LSA from all retransmission lists. Must be done
|
557 |
* before (5b), otherwise it also removes the new entries from (5b).
|
558 |
*/
|
559 |
struct ospf_iface *ifi;
|
560 |
struct ospf_neighbor *ni;
|
561 |
|
562 |
WALK_LIST(ifi, p->iface_list)
|
563 |
WALK_LIST(ni, ifi->neigh_list)
|
564 |
if (ni->state > NEIGHBOR_EXSTART)
|
565 |
ospf_lsa_lsrt_down(en, ni);
|
566 |
#endif
|
567 |
|
568 |
/* 13. (5d) - install new LSA into database */
|
569 |
en = ospf_install_lsa(p, &lsa, lsa_type, lsa_domain, body); |
570 |
|
571 |
/* RFC 5340 4.4.3 Events 6+7 - new Link LSA received */
|
572 |
if (lsa_type == LSA_T_LINK)
|
573 |
ospf_notify_net_lsa(ifa); |
574 |
|
575 |
/* 13. (5b) - flood new LSA */
|
576 |
int flood_back = ospf_flood_lsa(p, en, n);
|
577 |
|
578 |
/* 13.5. - schedule ACKs (tbl 19, cases 1+2) */
|
579 |
if (! flood_back)
|
580 |
if ((ifa->state != OSPF_IS_BACKUP) || (n->rid == ifa->drid))
|
581 |
ospf_enqueue_lsack(n, lsa_n, ACKL_DELAY); |
582 |
|
583 |
/* FIXME: remove LSA entry if it is LSA_MAXAGE and it is possible? */
|
584 |
|
585 |
continue;
|
586 |
} |
587 |
|
588 |
/* FIXME pg145 (6) */
|
589 |
|
590 |
/* 13. (7) - received LSA is same */
|
591 |
if (lsa_comp(&lsa, &en->lsa) == CMP_SAME)
|
592 |
{ |
593 |
/* Duplicate LSA, treat as implicit ACK */
|
594 |
int implicit_ack = ospf_lsa_lsrt_down(en, n);
|
595 |
|
596 |
/* 13.5. - schedule ACKs (tbl 19, cases 3+4) */
|
597 |
if (implicit_ack)
|
598 |
{ |
599 |
if ((ifa->state == OSPF_IS_BACKUP) && (n->rid == ifa->drid))
|
600 |
ospf_enqueue_lsack(n, lsa_n, ACKL_DELAY); |
601 |
} |
602 |
else
|
603 |
ospf_enqueue_lsack(n, lsa_n, ACKL_DIRECT); |
604 |
|
605 |
skip_lsreq = 1;
|
606 |
continue;
|
607 |
} |
608 |
|
609 |
/* 13. (8) - received LSA is older */
|
610 |
{ |
611 |
/* Seqnum is wrapping, wait until it is flushed */
|
612 |
if ((en->lsa.age == LSA_MAXAGE) && (en->lsa.sn == LSA_MAXSEQNO))
|
613 |
continue;
|
614 |
|
615 |
/* Send newer local copy back to neighbor */
|
616 |
/* FIXME - check for MinLSArrival ? */
|
617 |
ospf_send_lsupd(p, &en, 1, n);
|
618 |
} |
619 |
} |
620 |
|
621 |
/* Send direct LSACKs */
|
622 |
ospf_send_lsack(p, n, ACKL_DIRECT); |
623 |
|
624 |
/*
|
625 |
* In loading state, we should ask for another batch of LSAs. This is only
|
626 |
* vaguely mentioned in RFC 2328. We send a new LSREQ only if the current
|
627 |
* LSUPD actually removed some entries from LSA request list (want_lsreq) and
|
628 |
* did not contain duplicate or early LSAs (skip_lsreq). The first condition
|
629 |
* prevents endless floods, the second condition helps with flow control.
|
630 |
*/
|
631 |
if ((n->state == NEIGHBOR_LOADING) && n->want_lsreq && !skip_lsreq)
|
632 |
ospf_send_lsreq(p, n); |
633 |
} |
634 |
|