]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_flood.c
Merge pull request #9028 from mobash-rasool/ospfv3-asbr-summarisation
[mirror_frr.git] / ospf6d / ospf6_flood.c
CommitLineData
48454375 1/*
2 * Copyright (C) 2003 Yasuhiro Ohara
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
48454375 19 */
20
21#include <zebra.h>
22
23#include "log.h"
24#include "thread.h"
25#include "linklist.h"
26#include "vty.h"
1e05838a 27#include "command.h"
48454375 28
29#include "ospf6d.h"
30#include "ospf6_proto.h"
31#include "ospf6_lsa.h"
32#include "ospf6_lsdb.h"
33#include "ospf6_message.h"
34#include "ospf6_route.h"
35#include "ospf6_spf.h"
36
37#include "ospf6_top.h"
38#include "ospf6_area.h"
39#include "ospf6_interface.h"
40#include "ospf6_neighbor.h"
41
6452df09 42#include "ospf6_flood.h"
ad500b22 43#include "ospf6_nssa.h"
48454375 44
1e05838a 45unsigned char conf_debug_ospf6_flooding;
46
d62a17ae 47struct ospf6_lsdb *ospf6_get_scoped_lsdb(struct ospf6_lsa *lsa)
48454375 48{
d62a17ae 49 struct ospf6_lsdb *lsdb = NULL;
50 switch (OSPF6_LSA_SCOPE(lsa->header->type)) {
51 case OSPF6_SCOPE_LINKLOCAL:
52 lsdb = OSPF6_INTERFACE(lsa->lsdb->data)->lsdb;
53 break;
54 case OSPF6_SCOPE_AREA:
55 lsdb = OSPF6_AREA(lsa->lsdb->data)->lsdb;
56 break;
57 case OSPF6_SCOPE_AS:
58 lsdb = OSPF6_PROCESS(lsa->lsdb->data)->lsdb;
59 break;
60 default:
61 assert(0);
62 break;
63 }
64 return lsdb;
48454375 65}
66
d62a17ae 67struct ospf6_lsdb *ospf6_get_scoped_lsdb_self(struct ospf6_lsa *lsa)
48454375 68{
d62a17ae 69 struct ospf6_lsdb *lsdb_self = NULL;
70 switch (OSPF6_LSA_SCOPE(lsa->header->type)) {
71 case OSPF6_SCOPE_LINKLOCAL:
72 lsdb_self = OSPF6_INTERFACE(lsa->lsdb->data)->lsdb_self;
73 break;
74 case OSPF6_SCOPE_AREA:
75 lsdb_self = OSPF6_AREA(lsa->lsdb->data)->lsdb_self;
76 break;
77 case OSPF6_SCOPE_AS:
78 lsdb_self = OSPF6_PROCESS(lsa->lsdb->data)->lsdb_self;
79 break;
80 default:
81 assert(0);
82 break;
83 }
84 return lsdb_self;
6452df09 85}
86
d62a17ae 87void ospf6_lsa_originate(struct ospf6_lsa *lsa)
6452df09 88{
d62a17ae 89 struct ospf6_lsa *old;
90 struct ospf6_lsdb *lsdb_self;
91
2e9db233
DL
92 if (lsa->header->adv_router == INADDR_ANY) {
93 if (IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type))
94 zlog_debug(
95 "Refusing to originate LSA (zero router ID): %s",
96 lsa->name);
97
98 ospf6_lsa_delete(lsa);
99 return;
100 }
101
d62a17ae 102 /* find previous LSA */
103 old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
104 lsa->header->adv_router, lsa->lsdb);
105
106 /* if the new LSA does not differ from previous,
107 suppress this update of the LSA */
108 if (old && !OSPF6_LSA_IS_DIFFER(lsa, old)) {
109 if (IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type))
110 zlog_debug("Suppress updating LSA: %s", lsa->name);
111 ospf6_lsa_delete(lsa);
112 return;
113 }
114
115 /* store it in the LSDB for self-originated LSAs */
116 lsdb_self = ospf6_get_scoped_lsdb_self(lsa);
117 ospf6_lsdb_add(ospf6_lsa_copy(lsa), lsdb_self);
118
4dc43886 119 THREAD_OFF(lsa->refresh);
d62a17ae 120 thread_add_timer(master, ospf6_lsa_refresh, lsa, OSPF_LS_REFRESH_TIME,
121 &lsa->refresh);
122
123 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
124 || IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type)) {
125 zlog_debug("LSA Originate:");
126 ospf6_lsa_header_print(lsa);
127 }
128
129 ospf6_install_lsa(lsa);
130 ospf6_flood(NULL, lsa);
6452df09 131}
3b4cd3a9 132
d62a17ae 133void ospf6_lsa_originate_process(struct ospf6_lsa *lsa, struct ospf6 *process)
6452df09 134{
d62a17ae 135 lsa->lsdb = process->lsdb;
136 ospf6_lsa_originate(lsa);
3b4cd3a9 137}
138
d62a17ae 139void ospf6_lsa_originate_area(struct ospf6_lsa *lsa, struct ospf6_area *oa)
48454375 140{
d62a17ae 141 lsa->lsdb = oa->lsdb;
142 ospf6_lsa_originate(lsa);
6452df09 143}
144
d62a17ae 145void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa,
146 struct ospf6_interface *oi)
6452df09 147{
d62a17ae 148 lsa->lsdb = oi->lsdb;
149 ospf6_lsa_originate(lsa);
6452df09 150}
48454375 151
4dc43886
MR
152void ospf6_remove_id_from_external_id_table(struct ospf6 *ospf6,
153 uint32_t id)
154{
155 struct prefix prefix_id;
156 struct route_node *node;
157
158 /* remove binding in external_id_table */
159 prefix_id.family = AF_INET;
160 prefix_id.prefixlen = 32;
161 prefix_id.u.prefix4.s_addr = id;
162 node = route_node_lookup(ospf6->external_id_table, &prefix_id);
163 assert(node);
164 node->info = NULL;
165 route_unlock_node(node); /* to free the lookup lock */
166 route_unlock_node(node); /* to free the original lock */
167
168}
169
170void ospf6_external_lsa_purge(struct ospf6 *ospf6, struct ospf6_lsa *lsa)
171{
172 ospf6_lsa_purge(lsa);
173
174 ospf6_remove_id_from_external_id_table(ospf6, lsa->header->id);
175}
176
d62a17ae 177void ospf6_lsa_purge(struct ospf6_lsa *lsa)
6452df09 178{
d62a17ae 179 struct ospf6_lsa *self;
180 struct ospf6_lsdb *lsdb_self;
181
182 /* remove it from the LSDB for self-originated LSAs */
183 lsdb_self = ospf6_get_scoped_lsdb_self(lsa);
184 self = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
185 lsa->header->adv_router, lsdb_self);
186 if (self) {
187 THREAD_OFF(self->expire);
188 THREAD_OFF(self->refresh);
189 ospf6_lsdb_remove(self, lsdb_self);
190 }
191
192 ospf6_lsa_premature_aging(lsa);
6452df09 193}
48454375 194
690df177
CS
195/* Puring Multi Link-State IDs LSAs:
196 * Same Advertising Router with Multiple Link-State IDs
197 * LSAs, purging require to traverse all Link-State IDs
198 */
199void ospf6_lsa_purge_multi_ls_id(struct ospf6_area *oa, struct ospf6_lsa *lsa)
200{
201 int ls_id = 0;
202 struct ospf6_lsa *lsa_next;
203 uint16_t type;
204
205 type = lsa->header->type;
206
207 ospf6_lsa_purge(lsa);
208
209 lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id),
210 oa->ospf6->router_id, oa->lsdb);
211 while (lsa_next) {
212 ospf6_lsa_purge(lsa_next);
213 lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id),
214 oa->ospf6->router_id, oa->lsdb);
215 }
216}
48454375 217
d62a17ae 218void ospf6_increment_retrans_count(struct ospf6_lsa *lsa)
6452df09 219{
d62a17ae 220 /* The LSA must be the original one (see the description
221 in ospf6_decrement_retrans_count () below) */
222 lsa->retrans_count++;
6452df09 223}
48454375 224
d62a17ae 225void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa)
6452df09 226{
d62a17ae 227 struct ospf6_lsdb *lsdb;
228 struct ospf6_lsa *orig;
229
230 /* The LSA must be on the retrans-list of a neighbor. It means
231 the "lsa" is a copied one, and we have to decrement the
232 retransmission count of the original one (instead of this "lsa"'s).
233 In order to find the original LSA, first we have to find
234 appropriate LSDB that have the original LSA. */
235 lsdb = ospf6_get_scoped_lsdb(lsa);
236
237 /* Find the original LSA of which the retrans_count should be
238 * decremented */
239 orig = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
240 lsa->header->adv_router, lsdb);
241 if (orig) {
242 orig->retrans_count--;
243 assert(orig->retrans_count >= 0);
244 }
48454375 245}
246
247/* RFC2328 section 13.2 Installing LSAs in the database */
d62a17ae 248void ospf6_install_lsa(struct ospf6_lsa *lsa)
48454375 249{
d62a17ae 250 struct timeval now;
251 struct ospf6_lsa *old;
ad500b22 252 struct ospf6_area *area = NULL;
d62a17ae 253
d62a17ae 254 /* Remove the old instance from all neighbors' Link state
255 retransmission list (RFC2328 13.2 last paragraph) */
256 old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
257 lsa->header->adv_router, lsa->lsdb);
258 if (old) {
ad500b22
K
259 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) {
260 if (IS_OSPF6_DEBUG_NSSA)
261 zlog_debug("%s : old LSA %s", __func__,
262 lsa->name);
263 lsa->external_lsa_id = old->external_lsa_id;
264 }
d62a17ae 265 THREAD_OFF(old->expire);
266 THREAD_OFF(old->refresh);
267 ospf6_flood_clear(old);
268 }
269
270 monotime(&now);
271 if (!OSPF6_LSA_IS_MAXAGE(lsa)) {
272 lsa->expire = NULL;
273 thread_add_timer(master, ospf6_lsa_expire, lsa,
274 OSPF_LSA_MAXAGE + lsa->birth.tv_sec
275 - now.tv_sec,
276 &lsa->expire);
277 } else
278 lsa->expire = NULL;
279
280 if (OSPF6_LSA_IS_SEQWRAP(lsa)
281 && !(CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)
282 && lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER))) {
283 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
284 zlog_debug("lsa install wrapping: sequence 0x%x",
285 ntohl(lsa->header->seqnum));
286 SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
287 /* in lieu of premature_aging, since we do not want to recreate
288 * this lsa
289 * and/or mess with timers etc, we just want to wrap the
290 * sequence number
291 * and reflood the lsa before continuing.
292 * NOTE: Flood needs to be called right after this function
293 * call, by the
294 * caller
295 */
296 lsa->header->seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER);
297 lsa->header->age = htons(OSPF_LSA_MAXAGE);
298 ospf6_lsa_checksum(lsa->header);
299 }
300
76249532
CS
301 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
302 || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
303 zlog_debug("%s Install LSA: %s age %d seqnum %x in LSDB.",
15569c58
DA
304 __func__, lsa->name, ntohs(lsa->header->age),
305 ntohl(lsa->header->seqnum));
76249532 306
d62a17ae 307 /* actually install */
308 lsa->installed = now;
309 ospf6_lsdb_add(lsa, lsa->lsdb);
310
ad500b22
K
311 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) {
312 area = OSPF6_AREA(lsa->lsdb->data);
313 ospf6_translated_nssa_refresh(area, lsa, NULL);
314 ospf6_schedule_abr_task(area->ospf6);
315 }
316
317 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER) {
318 area = OSPF6_AREA(lsa->lsdb->data);
319 if (old == NULL) {
320 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
321 || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
322 zlog_debug("%s: New router LSA %s", __func__,
323 lsa->name);
324 ospf6_abr_nssa_check_status(area->ospf6);
325 }
326 }
d62a17ae 327 return;
48454375 328}
329
6452df09 330/* RFC2740 section 3.5.2. Sending Link State Update packets */
48454375 331/* RFC2328 section 13.3 Next step in the flooding procedure */
996c9314
LB
332void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa,
333 struct ospf6_interface *oi)
48454375 334{
d62a17ae 335 struct listnode *node, *nnode;
336 struct ospf6_neighbor *on;
c1e4c0dc 337 struct ospf6_lsa *req, *old;
d62a17ae 338 int retrans_added = 0;
339 int is_debug = 0;
340
341 if (IS_OSPF6_DEBUG_FLOODING
342 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) {
343 is_debug++;
344 zlog_debug("Flooding on %s: %s", oi->interface->name,
345 lsa->name);
346 }
347
348 /* (1) For each neighbor */
349 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
350 if (is_debug)
351 zlog_debug("To neighbor %s", on->name);
352
353 /* (a) if neighbor state < Exchange, examin next */
354 if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
355 if (is_debug)
356 zlog_debug(
357 "Neighbor state less than ExChange, next neighbor");
358 continue;
359 }
360
361 /* (b) if neighbor not yet Full, check request-list */
362 if (on->state != OSPF6_NEIGHBOR_FULL) {
363 if (is_debug)
364 zlog_debug("Neighbor not yet Full");
365
366 req = ospf6_lsdb_lookup(
367 lsa->header->type, lsa->header->id,
368 lsa->header->adv_router, on->request_list);
369 if (req == NULL) {
370 if (is_debug)
371 zlog_debug(
372 "Not on request-list for this neighbor");
373 /* fall through */
374 } else {
375 /* If new LSA less recent, examin next neighbor
376 */
377 if (ospf6_lsa_compare(lsa, req) > 0) {
378 if (is_debug)
379 zlog_debug(
380 "Requesting is older, next neighbor");
381 continue;
382 }
383
384 /* If the same instance, delete from
385 request-list and
386 examin next neighbor */
387 if (ospf6_lsa_compare(lsa, req) == 0) {
388 if (is_debug)
389 zlog_debug(
390 "Requesting the same, remove it, next neighbor");
391 if (req == on->last_ls_req) {
c957f7d9
QY
392 /* sanity check refcount */
393 assert(req->lock >= 2);
744ba569 394 req = ospf6_lsa_unlock(req);
d62a17ae 395 on->last_ls_req = NULL;
396 }
744ba569
DS
397 if (req)
398 ospf6_lsdb_remove(
399 req, on->request_list);
d62a17ae 400 ospf6_check_nbr_loading(on);
401 continue;
402 }
403
404 /* If the new LSA is more recent, delete from
405 * request-list */
406 if (ospf6_lsa_compare(lsa, req) < 0) {
407 if (is_debug)
408 zlog_debug(
409 "Received is newer, remove requesting");
410 if (req == on->last_ls_req) {
744ba569 411 req = ospf6_lsa_unlock(req);
d62a17ae 412 on->last_ls_req = NULL;
413 }
ce872c6a 414 if (req)
415 ospf6_lsdb_remove(req,
416 on->request_list);
d62a17ae 417 ospf6_check_nbr_loading(on);
418 /* fall through */
419 }
420 }
421 }
422
423 /* (c) If the new LSA was received from this neighbor,
424 examin next neighbor */
425 if (from == on) {
426 if (is_debug)
427 zlog_debug(
428 "Received is from the neighbor, next neighbor");
429 continue;
430 }
431
ad500b22
K
432 if ((oi->area->ospf6->inst_shutdown)
433 || CHECK_FLAG(lsa->flag, OSPF6_LSA_FLUSH)) {
76249532 434 if (is_debug)
996c9314
LB
435 zlog_debug(
436 "%s: Send LSA %s (age %d) update now",
5e81f5dd 437 __func__, lsa->name,
996c9314 438 ntohs(lsa->header->age));
76249532
CS
439 ospf6_lsupdate_send_neighbor_now(on, lsa);
440 continue;
441 } else {
442 /* (d) add retrans-list, schedule retransmission */
443 if (is_debug)
f6c5f2e0 444 zlog_debug("Add retrans-list of neighbor %s ",
445 on->name);
c1e4c0dc
MR
446
447 /* Do not increment the retrans count if the lsa is
448 * already present in the retrans list.
449 */
450 old = ospf6_lsdb_lookup(
451 lsa->header->type, lsa->header->id,
452 lsa->header->adv_router, on->retrans_list);
453 if (!old) {
454 if (is_debug)
455 zlog_debug(
456 "Increment %s from retrans_list of %s",
457 lsa->name, on->name);
458 ospf6_increment_retrans_count(lsa);
459 ospf6_lsdb_add(ospf6_lsa_copy(lsa),
460 on->retrans_list);
461 thread_add_timer(
462 master, ospf6_lsupdate_send_neighbor,
463 on, on->ospf6_if->rxmt_interval,
464 &on->thread_send_lsupdate);
465 retrans_added++;
466 }
76249532 467 }
d62a17ae 468 }
469
470 /* (2) examin next interface if not added to retrans-list */
471 if (retrans_added == 0) {
472 if (is_debug)
473 zlog_debug(
f6c5f2e0 474 "No retransmission scheduled, next interface %s",
475 oi->interface->name);
d62a17ae 476 return;
477 }
478
479 /* (3) If the new LSA was received on this interface,
480 and it was from DR or BDR, examin next interface */
481 if (from && from->ospf6_if == oi
482 && (from->router_id == oi->drouter
483 || from->router_id == oi->bdrouter)) {
484 if (is_debug)
485 zlog_debug(
486 "Received is from the I/F's DR or BDR, next interface");
487 return;
488 }
489
490 /* (4) If the new LSA was received on this interface,
491 and the interface state is BDR, examin next interface */
492 if (from && from->ospf6_if == oi) {
493 if (oi->state == OSPF6_INTERFACE_BDR) {
494 if (is_debug)
495 zlog_debug(
496 "Received is from the I/F, itself BDR, next interface");
497 return;
498 }
499 SET_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK);
500 }
501
502 /* (5) flood the LSA out the interface. */
503 if (is_debug)
504 zlog_debug("Schedule flooding for the interface");
505 if ((oi->type == OSPF_IFTYPE_BROADCAST)
506 || (oi->type == OSPF_IFTYPE_POINTOPOINT)) {
507 ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsupdate_list);
508 thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0,
509 &oi->thread_send_lsupdate);
510 } else {
511 /* reschedule retransmissions to all neighbors */
512 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
513 THREAD_OFF(on->thread_send_lsupdate);
514 on->thread_send_lsupdate = NULL;
515 thread_add_event(master, ospf6_lsupdate_send_neighbor,
516 on, 0, &on->thread_send_lsupdate);
517 }
7cf99722 518 }
6452df09 519}
520
d62a17ae 521void ospf6_flood_area(struct ospf6_neighbor *from, struct ospf6_lsa *lsa,
522 struct ospf6_area *oa)
6452df09 523{
d62a17ae 524 struct listnode *node, *nnode;
525 struct ospf6_interface *oi;
6452df09 526
d62a17ae 527 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
528 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL
529 && oi != OSPF6_INTERFACE(lsa->lsdb->data))
530 continue;
48454375 531
d62a17ae 532 ospf6_flood_interface(from, lsa, oi);
533 }
6452df09 534}
535
d62a17ae 536static void ospf6_flood_process(struct ospf6_neighbor *from,
537 struct ospf6_lsa *lsa, struct ospf6 *process)
6452df09 538{
d62a17ae 539 struct listnode *node, *nnode;
540 struct ospf6_area *oa;
541
542 for (ALL_LIST_ELEMENTS(process->area_list, node, nnode, oa)) {
0889da24
KS
543
544 /* If unknown LSA and U-bit clear, treat as link local
545 * flooding scope
546 */
547 if (!OSPF6_LSA_IS_KNOWN(lsa->header->type)
548 && !(ntohs(lsa->header->type) & OSPF6_LSTYPE_UBIT_MASK)
549 && (oa != OSPF6_INTERFACE(lsa->lsdb->data)->area)) {
550
551 if (IS_OSPF6_DEBUG_FLOODING)
552 zlog_debug("Unknown LSA, do not flood");
553 continue;
554 }
555
d62a17ae 556 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_AREA
557 && oa != OSPF6_AREA(lsa->lsdb->data))
558 continue;
559 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL
560 && oa != OSPF6_INTERFACE(lsa->lsdb->data)->area)
561 continue;
562
563 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL
ad500b22
K
564 && (IS_AREA_STUB(oa) || IS_AREA_NSSA(oa)))
565 continue;
566
567 /* Check for NSSA LSA */
568 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7
569 && !IS_AREA_NSSA(oa) && !OSPF6_LSA_IS_MAXAGE(lsa))
d62a17ae 570 continue;
571
572 ospf6_flood_area(from, lsa, oa);
573 }
6452df09 574}
575
d62a17ae 576void ospf6_flood(struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
6452df09 577{
beadc736 578 struct ospf6 *ospf6;
579
580 ospf6 = ospf6_get_by_lsdb(lsa);
581 if (ospf6 == NULL)
582 return;
583
d62a17ae 584 ospf6_flood_process(from, lsa, ospf6);
6452df09 585}
586
d62a17ae 587static void ospf6_flood_clear_interface(struct ospf6_lsa *lsa,
588 struct ospf6_interface *oi)
6452df09 589{
d62a17ae 590 struct listnode *node, *nnode;
591 struct ospf6_neighbor *on;
592 struct ospf6_lsa *rem;
593
594 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
595 rem = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
596 lsa->header->adv_router,
597 on->retrans_list);
598 if (rem && !ospf6_lsa_compare(rem, lsa)) {
599 if (IS_OSPF6_DEBUG_FLOODING
600 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type))
601 zlog_debug("Remove %s from retrans_list of %s",
602 rem->name, on->name);
603 ospf6_decrement_retrans_count(rem);
604 ospf6_lsdb_remove(rem, on->retrans_list);
605 }
606 }
6452df09 607}
608
ad500b22 609void ospf6_flood_clear_area(struct ospf6_lsa *lsa, struct ospf6_area *oa)
6452df09 610{
d62a17ae 611 struct listnode *node, *nnode;
612 struct ospf6_interface *oi;
6452df09 613
d62a17ae 614 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
615 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL
616 && oi != OSPF6_INTERFACE(lsa->lsdb->data))
617 continue;
6452df09 618
d62a17ae 619 ospf6_flood_clear_interface(lsa, oi);
620 }
6452df09 621}
622
d62a17ae 623static void ospf6_flood_clear_process(struct ospf6_lsa *lsa,
624 struct ospf6 *process)
6452df09 625{
d62a17ae 626 struct listnode *node, *nnode;
627 struct ospf6_area *oa;
628
629 for (ALL_LIST_ELEMENTS(process->area_list, node, nnode, oa)) {
630 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_AREA
631 && oa != OSPF6_AREA(lsa->lsdb->data))
632 continue;
633 if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL
634 && oa != OSPF6_INTERFACE(lsa->lsdb->data)->area)
635 continue;
636
637 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL
ad500b22
K
638 && (IS_AREA_STUB(oa) || (IS_AREA_NSSA(oa))))
639 continue;
640 /* Check for NSSA LSA */
641 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7
642 && !IS_AREA_NSSA(oa))
d62a17ae 643 continue;
644
645 ospf6_flood_clear_area(lsa, oa);
646 }
6452df09 647}
648
d62a17ae 649void ospf6_flood_clear(struct ospf6_lsa *lsa)
6452df09 650{
beadc736 651 struct ospf6 *ospf6;
652
653 ospf6 = ospf6_get_by_lsdb(lsa);
ad500b22
K
654 if (ospf6 == NULL)
655 return;
d62a17ae 656 ospf6_flood_clear_process(lsa, ospf6);
48454375 657}
658
6452df09 659
48454375 660/* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
d62a17ae 661static void ospf6_acknowledge_lsa_bdrouter(struct ospf6_lsa *lsa,
662 int ismore_recent,
663 struct ospf6_neighbor *from)
48454375 664{
d62a17ae 665 struct ospf6_interface *oi;
666 int is_debug = 0;
667
668 if (IS_OSPF6_DEBUG_FLOODING
669 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type))
670 is_debug++;
671
672 assert(from && from->ospf6_if);
673 oi = from->ospf6_if;
674
675 /* LSA is more recent than database copy, but was not flooded
676 back out receiving interface. Delayed acknowledgement sent
677 if advertisement received from Designated Router,
678 otherwide do nothing. */
679 if (ismore_recent < 0) {
680 if (oi->drouter == from->router_id) {
681 if (is_debug)
682 zlog_debug(
683 "Delayed acknowledgement (BDR & MoreRecent & from DR)");
684 /* Delayed acknowledgement */
685 ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list);
686 thread_add_timer(master, ospf6_lsack_send_interface, oi,
687 3, &oi->thread_send_lsack);
688 } else {
689 if (is_debug)
690 zlog_debug(
691 "No acknowledgement (BDR & MoreRecent & ! from DR)");
692 }
693 return;
694 }
695
696 /* LSA is a duplicate, and was treated as an implied acknowledgement.
697 Delayed acknowledgement sent if advertisement received from
698 Designated Router, otherwise do nothing */
699 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)
700 && CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) {
701 if (oi->drouter == from->router_id) {
702 if (is_debug)
703 zlog_debug(
704 "Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
705 /* Delayed acknowledgement */
706 ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list);
707 thread_add_timer(master, ospf6_lsack_send_interface, oi,
708 3, &oi->thread_send_lsack);
709 } else {
710 if (is_debug)
711 zlog_debug(
712 "No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
713 }
714 return;
715 }
716
717 /* LSA is a duplicate, and was not treated as an implied
718 acknowledgement.
719 Direct acknowledgement sent */
720 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)
721 && !CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) {
722 if (is_debug)
723 zlog_debug("Direct acknowledgement (BDR & Duplicate)");
724 ospf6_lsdb_add(ospf6_lsa_copy(lsa), from->lsack_list);
725 thread_add_event(master, ospf6_lsack_send_neighbor, from, 0,
726 &from->thread_send_lsack);
727 return;
728 }
729
730 /* LSA's LS age is equal to Maxage, and there is no current instance
731 of the LSA in the link state database, and none of router's
732 neighbors are in states Exchange or Loading */
733 /* Direct acknowledgement sent, but this case is handled in
734 early of ospf6_receive_lsa () */
48454375 735}
736
d62a17ae 737static void ospf6_acknowledge_lsa_allother(struct ospf6_lsa *lsa,
738 int ismore_recent,
739 struct ospf6_neighbor *from)
48454375 740{
d62a17ae 741 struct ospf6_interface *oi;
742 int is_debug = 0;
743
744 if (IS_OSPF6_DEBUG_FLOODING
745 || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type))
746 is_debug++;
747
748 assert(from && from->ospf6_if);
749 oi = from->ospf6_if;
750
751 /* LSA has been flood back out receiving interface.
752 No acknowledgement sent. */
753 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK)) {
754 if (is_debug)
755 zlog_debug("No acknowledgement (AllOther & FloodBack)");
756 return;
757 }
758
759 /* LSA is more recent than database copy, but was not flooded
760 back out receiving interface. Delayed acknowledgement sent. */
761 if (ismore_recent < 0) {
762 if (is_debug)
763 zlog_debug(
764 "Delayed acknowledgement (AllOther & MoreRecent)");
765 /* Delayed acknowledgement */
766 ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list);
767 thread_add_timer(master, ospf6_lsack_send_interface, oi, 3,
768 &oi->thread_send_lsack);
769 return;
770 }
771
772 /* LSA is a duplicate, and was treated as an implied acknowledgement.
773 No acknowledgement sent. */
774 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)
775 && CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) {
776 if (is_debug)
777 zlog_debug(
778 "No acknowledgement (AllOther & Duplicate & ImpliedAck)");
779 return;
780 }
781
782 /* LSA is a duplicate, and was not treated as an implied
783 acknowledgement.
784 Direct acknowledgement sent */
785 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)
786 && !CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) {
787 if (is_debug)
788 zlog_debug(
789 "Direct acknowledgement (AllOther & Duplicate)");
790 ospf6_lsdb_add(ospf6_lsa_copy(lsa), from->lsack_list);
791 thread_add_event(master, ospf6_lsack_send_neighbor, from, 0,
792 &from->thread_send_lsack);
793 return;
794 }
795
796 /* LSA's LS age is equal to Maxage, and there is no current instance
797 of the LSA in the link state database, and none of router's
798 neighbors are in states Exchange or Loading */
799 /* Direct acknowledgement sent, but this case is handled in
800 early of ospf6_receive_lsa () */
48454375 801}
802
d62a17ae 803static void ospf6_acknowledge_lsa(struct ospf6_lsa *lsa, int ismore_recent,
804 struct ospf6_neighbor *from)
48454375 805{
d62a17ae 806 struct ospf6_interface *oi;
48454375 807
d62a17ae 808 assert(from && from->ospf6_if);
809 oi = from->ospf6_if;
48454375 810
d62a17ae 811 if (oi->state == OSPF6_INTERFACE_BDR)
812 ospf6_acknowledge_lsa_bdrouter(lsa, ismore_recent, from);
813 else
814 ospf6_acknowledge_lsa_allother(lsa, ismore_recent, from);
48454375 815}
816
817/* RFC2328 section 13 (4):
818 if MaxAge LSA and if we have no instance, and no neighbor
819 is in states Exchange or Loading
820 returns 1 if match this case, else returns 0 */
d62a17ae 821static int ospf6_is_maxage_lsa_drop(struct ospf6_lsa *lsa,
822 struct ospf6_neighbor *from)
48454375 823{
d62a17ae 824 struct ospf6_neighbor *on;
825 struct ospf6_interface *oi;
826 struct ospf6_area *oa;
827 struct ospf6 *process = NULL;
828 struct listnode *i, *j, *k;
829 int count = 0;
830
831 if (!OSPF6_LSA_IS_MAXAGE(lsa))
832 return 0;
833
834 if (ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
835 lsa->header->adv_router, lsa->lsdb))
836 return 0;
837
838 process = from->ospf6_if->area->ospf6;
839
840 for (ALL_LIST_ELEMENTS_RO(process->area_list, i, oa))
841 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
842 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on))
843 if (on->state == OSPF6_NEIGHBOR_EXCHANGE
844 || on->state == OSPF6_NEIGHBOR_LOADING)
845 count++;
846
847 if (count == 0)
848 return 1;
849 return 0;
48454375 850}
851
852/* RFC2328 section 13 The Flooding Procedure */
d62a17ae 853void ospf6_receive_lsa(struct ospf6_neighbor *from,
854 struct ospf6_lsa_header *lsa_header)
48454375 855{
d62a17ae 856 struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
857 int ismore_recent;
858 int is_debug = 0;
859 unsigned int time_delta_ms;
860
861 ismore_recent = 1;
862 assert(from);
863
c5467a12 864 /* if we receive a LSA with invalid seqnum drop it */
865 if (ntohl(lsa_header->seqnum) - 1 == OSPF_MAX_SEQUENCE_NUMBER) {
866 if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa_header->type)) {
867 zlog_debug(
868 "received lsa [%s Id:%pI4 Adv:%pI4] with invalid seqnum 0x%x, ignore",
869 ospf6_lstype_name(lsa_header->type),
870 &lsa_header->id, &lsa_header->adv_router,
871 ntohl(lsa_header->seqnum));
872 }
873 return;
874 }
875
d62a17ae 876 /* make lsa structure for received lsa */
877 new = ospf6_lsa_create(lsa_header);
878
879 if (IS_OSPF6_DEBUG_FLOODING
880 || IS_OSPF6_DEBUG_FLOOD_TYPE(new->header->type)) {
881 is_debug++;
882 zlog_debug("LSA Receive from %s", from->name);
883 ospf6_lsa_header_print(new);
884 }
885
886 /* (1) LSA Checksum */
887 if (!ospf6_lsa_checksum_valid(new->header)) {
888 if (is_debug)
889 zlog_debug("Wrong LSA Checksum, discard");
890 ospf6_lsa_delete(new);
891 return;
892 }
893
894 /* (2) Examine the LSA's LS type.
895 RFC2470 3.5.1. Receiving Link State Update packets */
896 if (IS_AREA_STUB(from->ospf6_if->area)
897 && OSPF6_LSA_SCOPE(new->header->type) == OSPF6_SCOPE_AS) {
898 if (is_debug)
899 zlog_debug(
900 "AS-External-LSA (or AS-scope LSA) in stub area, discard");
901 ospf6_lsa_delete(new);
902 return;
903 }
904
905 /* (3) LSA which have reserved scope is discarded
906 RFC2470 3.5.1. Receiving Link State Update packets */
907 /* Flooding scope check. LSAs with unknown scope are discarded here.
908 Set appropriate LSDB for the LSA */
909 switch (OSPF6_LSA_SCOPE(new->header->type)) {
910 case OSPF6_SCOPE_LINKLOCAL:
911 new->lsdb = from->ospf6_if->lsdb;
912 break;
913 case OSPF6_SCOPE_AREA:
914 new->lsdb = from->ospf6_if->area->lsdb;
915 break;
916 case OSPF6_SCOPE_AS:
917 new->lsdb = from->ospf6_if->area->ospf6->lsdb;
918 break;
919 default:
920 if (is_debug)
921 zlog_debug("LSA has reserved scope, discard");
922 ospf6_lsa_delete(new);
923 return;
924 }
925
926 /* (4) if MaxAge LSA and if we have no instance, and no neighbor
927 is in states Exchange or Loading */
928 if (ospf6_is_maxage_lsa_drop(new, from)) {
929 /* log */
930 if (is_debug)
931 zlog_debug(
932 "Drop MaxAge LSA with direct acknowledgement.");
933
934 /* a) Acknowledge back to neighbor (Direct acknowledgement,
935 * 13.5) */
936 ospf6_lsdb_add(ospf6_lsa_copy(new), from->lsack_list);
937 thread_add_event(master, ospf6_lsack_send_neighbor, from, 0,
938 &from->thread_send_lsack);
939
940 /* b) Discard */
941 ospf6_lsa_delete(new);
942 return;
943 }
944
945 /* (5) */
946 /* lookup the same database copy in lsdb */
947 old = ospf6_lsdb_lookup(new->header->type, new->header->id,
948 new->header->adv_router, new->lsdb);
949 if (old) {
950 ismore_recent = ospf6_lsa_compare(new, old);
951 if (ntohl(new->header->seqnum) == ntohl(old->header->seqnum)) {
952 if (is_debug)
953 zlog_debug("Received is duplicated LSA");
954 SET_FLAG(new->flag, OSPF6_LSA_DUPLICATE);
955 }
956 }
957
958 /* if no database copy or received is more recent */
959 if (old == NULL || ismore_recent < 0) {
960 /* in case we have no database copy */
961 ismore_recent = -1;
962
963 /* (a) MinLSArrival check */
964 if (old) {
965 struct timeval now, res;
966 monotime(&now);
967 timersub(&now, &old->installed, &res);
968 time_delta_ms =
969 (res.tv_sec * 1000) + (int)(res.tv_usec / 1000);
970 if (time_delta_ms
971 < from->ospf6_if->area->ospf6->lsa_minarrival) {
972 if (is_debug)
973 zlog_debug(
974 "LSA can't be updated within MinLSArrival, %dms < %dms, discard",
975 time_delta_ms,
976 from->ospf6_if->area->ospf6
977 ->lsa_minarrival);
978 ospf6_lsa_delete(new);
979 return; /* examin next lsa */
980 }
981 }
982
983 monotime(&new->received);
984
985 if (is_debug)
986 zlog_debug(
987 "Install, Flood, Possibly acknowledge the received LSA");
988
989 /* Remove older copies of this LSA from retx lists */
990 if (old)
991 ospf6_flood_clear(old);
992
993 /* (b) immediately flood and (c) remove from all retrans-list */
994 /* Prevent self-originated LSA to be flooded. this is to make
995 reoriginated instance of the LSA not to be rejected by other
996 routers
997 due to MinLSArrival. */
998 if (new->header->adv_router
999 != from->ospf6_if->area->ospf6->router_id)
1000 ospf6_flood(from, new);
1001
1002 /* (d), installing lsdb, which may cause routing
1003 table calculation (replacing database copy) */
1004 ospf6_install_lsa(new);
1005
1006 if (OSPF6_LSA_IS_MAXAGE(new))
1007 ospf6_maxage_remove(from->ospf6_if->area->ospf6);
1008
1009 /* (e) possibly acknowledge */
1010 ospf6_acknowledge_lsa(new, ismore_recent, from);
1011
1012 /* (f) Self Originated LSA, section 13.4 */
1013 if (new->header->adv_router
1014 == from->ospf6_if->area->ospf6->router_id) {
1015 /* Self-originated LSA (newer than ours) is received
1016 from
1017 another router. We have to make a new instance of the
1018 LSA
1019 or have to flush this LSA. */
1020 if (is_debug) {
1021 zlog_debug(
1022 "Newer instance of the self-originated LSA");
1023 zlog_debug("Schedule reorigination");
1024 }
1025 new->refresh = NULL;
1026 thread_add_event(master, ospf6_lsa_refresh, new, 0,
1027 &new->refresh);
1028 }
1029
1030 return;
1031 }
1032
1033 /* (6) if there is instance on sending neighbor's request list */
1034 if (ospf6_lsdb_lookup(new->header->type, new->header->id,
1035 new->header->adv_router, from->request_list)) {
1036 /* if no database copy, should go above state (5) */
1037 assert(old);
1038
1b1f7b4f 1039 zlog_warn(
1040 "Received is not newer, on the neighbor %s request-list",
1041 from->name);
1042 zlog_warn(
1043 "BadLSReq, discard the received LSA lsa %s send badLSReq",
1044 new->name);
d62a17ae 1045
1046 /* BadLSReq */
1047 thread_add_event(master, bad_lsreq, from, 0, NULL);
1048
1049 ospf6_lsa_delete(new);
1050 return;
1051 }
1052
1053 /* (7) if neither one is more recent */
1054 if (ismore_recent == 0) {
1055 if (is_debug)
1056 zlog_debug(
1057 "The same instance as database copy (neither recent)");
1058
1059 /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack
1060 */
1061 rem = ospf6_lsdb_lookup(new->header->type, new->header->id,
1062 new->header->adv_router,
1063 from->retrans_list);
1064 if (rem) {
1065 if (is_debug) {
1066 zlog_debug(
1067 "It is on the neighbor's retrans-list.");
1068 zlog_debug(
1069 "Treat as an Implied acknowledgement");
1070 }
1071 SET_FLAG(new->flag, OSPF6_LSA_IMPLIEDACK);
1072 ospf6_decrement_retrans_count(rem);
1073 ospf6_lsdb_remove(rem, from->retrans_list);
1074 }
1075
1076 if (is_debug)
1077 zlog_debug("Possibly acknowledge and then discard");
1078
1079 /* (b) possibly acknowledge */
1080 ospf6_acknowledge_lsa(new, ismore_recent, from);
1081
1082 ospf6_lsa_delete(new);
1083 return;
1084 }
1085
1086 /* (8) previous database copy is more recent */
1087 {
1088 assert(old);
1089
1090 /* If database copy is in 'Seqnumber Wrapping',
1091 simply discard the received LSA */
1092 if (OSPF6_LSA_IS_MAXAGE(old)
1093 && old->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER)) {
1094 if (is_debug) {
1095 zlog_debug("The LSA is in Seqnumber Wrapping");
1096 zlog_debug("MaxAge & MaxSeqNum, discard");
1097 }
1098 ospf6_lsa_delete(new);
1099 return;
1100 }
1101
1102 /* Otherwise, Send database copy of this LSA to this neighbor */
1103 {
1104 if (is_debug) {
1105 zlog_debug("Database copy is more recent.");
1106 zlog_debug(
1107 "Send back directly and then discard");
1108 }
1109
76249532
CS
1110 /* Neighbor router sent recent age for LSA,
1111 * Router could be restarted while current copy is
1112 * MAXAGEd and not removed.*/
996c9314
LB
1113 if (OSPF6_LSA_IS_MAXAGE(old)
1114 && !OSPF6_LSA_IS_MAXAGE(new)) {
76249532 1115 if (new->header->adv_router
4c63a76a
MB
1116 != from->ospf6_if->area->ospf6->router_id) {
1117 if (is_debug)
1118 zlog_debug(
1119 "%s: Current copy of LSA %s is MAXAGE, but new has recent age, flooding/installing.",
2d84ae9c 1120 __PRETTY_FUNCTION__, old->name);
4c63a76a 1121 ospf6_lsa_purge(old);
76249532 1122 ospf6_flood(from, new);
4c63a76a 1123 ospf6_install_lsa(new);
2d84ae9c 1124 return;
4c63a76a 1125 }
2d84ae9c
MB
1126 /* For self-originated LSA, only trust
1127 * ourselves. Fall through and send
1128 * LS Update with our current copy.
1129 */
1130 if (is_debug)
1131 zlog_debug(
1132 "%s: Current copy of self-originated LSA %s is MAXAGE, but new has recent age, re-sending current one.",
1133 __PRETTY_FUNCTION__, old->name);
76249532
CS
1134 }
1135
d62a17ae 1136 /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
1137
1138 ospf6_lsdb_add(ospf6_lsa_copy(old),
1139 from->lsupdate_list);
1140 thread_add_event(master, ospf6_lsupdate_send_neighbor,
1141 from, 0, &from->thread_send_lsupdate);
76249532 1142
d62a17ae 1143 ospf6_lsa_delete(new);
1144 return;
1145 }
1146 return;
1147 }
48454375 1148}
1149
1e05838a 1150DEFUN (debug_ospf6_flooding,
1151 debug_ospf6_flooding_cmd,
1152 "debug ospf6 flooding",
1153 DEBUG_STR
1154 OSPF6_STR
1155 "Debug OSPFv3 flooding function\n"
1156 )
1157{
d62a17ae 1158 OSPF6_DEBUG_FLOODING_ON();
1159 return CMD_SUCCESS;
1e05838a 1160}
1161
1162DEFUN (no_debug_ospf6_flooding,
1163 no_debug_ospf6_flooding_cmd,
1164 "no debug ospf6 flooding",
1165 NO_STR
1166 DEBUG_STR
1167 OSPF6_STR
1168 "Debug OSPFv3 flooding function\n"
1169 )
1170{
d62a17ae 1171 OSPF6_DEBUG_FLOODING_OFF();
1172 return CMD_SUCCESS;
1e05838a 1173}
1174
d62a17ae 1175int config_write_ospf6_debug_flood(struct vty *vty)
1e05838a 1176{
d62a17ae 1177 if (IS_OSPF6_DEBUG_FLOODING)
1178 vty_out(vty, "debug ospf6 flooding\n");
1179 return 0;
1e05838a 1180}
1181
d62a17ae 1182void install_element_ospf6_debug_flood(void)
1e05838a 1183{
d62a17ae 1184 install_element(ENABLE_NODE, &debug_ospf6_flooding_cmd);
1185 install_element(ENABLE_NODE, &no_debug_ospf6_flooding_cmd);
1186 install_element(CONFIG_NODE, &debug_ospf6_flooding_cmd);
1187 install_element(CONFIG_NODE, &no_debug_ospf6_flooding_cmd);
1e05838a 1188}