blob: 864e0c23aa3d9dfd7f758b4ebc2004270cc7519c [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Copyright (C) 2001 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 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include "ospf6d.h"
23
24#include "ospf6_dump.h"
25#include "ospf6_abr.h"
26
27static int abr_index;
28#define IS_OSPF6_DUMP_ABR (ospf6_dump_is_on (abr_index))
29
30#define ADD 0
31#define CHANGE 1
32#define REMOVE 2
33
34/* Inter-Area-Prefix-LSA Calculation */
35
36static struct ospf6_route_req *
37ospf6_abr_entry_lookup (struct ospf6_route_req *abr_entry,
38 u_int32_t router_id, struct ospf6_area *area)
39{
40 struct prefix_ls abr_id;
41 char router_string[32];
42
43 inet_ntop (AF_INET, &router_id, router_string, sizeof (router_string));
44
45 //zlog_info ("ABR: Finding router %s in area %s", router_string, area->str);
46
47 memset (&abr_id, 0, sizeof (abr_id));
48 abr_id.family = AF_UNSPEC;
49 abr_id.prefixlen = 64; /* xxx */
50 abr_id.id.s_addr = htonl (0);
51 abr_id.adv_router.s_addr = router_id;
52
53 ospf6_route_lookup (abr_entry, (struct prefix *) &abr_id,
54 area->table_topology);
55
56 if (ospf6_route_end (abr_entry))
57 {
58 if (IS_OSPF6_DUMP_ABR)
59 zlog_info ("ABR: Router %s not found in area %s",
60 router_string, area->str);
61 return NULL;
62 }
63
64 if (abr_entry->path.area_id != area->area_id)
65 {
66 if (IS_OSPF6_DUMP_ABR)
67 zlog_info ("ABR: ABR area id mismatch");
68 return NULL;
69 }
70
71 if (! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B))
72 {
73 if (IS_OSPF6_DUMP_ABR)
74 zlog_info ("ABR: ABR entry's B bit off");
75 return NULL;
76 }
77
78 return abr_entry;
79}
80
81static int
82ospf6_abr_prefix_lsa_to_route (struct ospf6_lsa *lsa,
83 struct ospf6_route_req *request)
84{
85 struct ospf6_inter_area_prefix_lsa *iep;
86 struct ospf6_route_req abr_entry;
87
88 if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTER_PREFIX))
89 {
90 if (IS_OSPF6_DUMP_ABR)
91 zlog_info ("ABR: LSA type mismatch");
92 return -1;
93 }
94
95 if (IS_LSA_MAXAGE (lsa))
96 {
97 if (IS_OSPF6_DUMP_ABR)
98 zlog_info ("ABR: LSA MaxAge");
99 return -1;
100 }
101
102 if (! ospf6_abr_entry_lookup (&abr_entry, lsa->header->adv_router,
103 (struct ospf6_area *) lsa->scope))
104 {
105 if (IS_OSPF6_DUMP_ABR)
106 zlog_info ("ABR: ABR check failed");
107 return -1;
108 }
109
110 iep = OSPF6_LSA_HEADER_END (lsa->header);
111
112 memset (request, 0, sizeof (struct ospf6_route_req));
113 request->route.type = OSPF6_DEST_TYPE_NETWORK;
114 request->route.prefix.family = AF_INET6;
115 request->route.prefix.prefixlen = iep->prefix.prefix_length;
116 ospf6_prefix_in6_addr (&iep->prefix, &request->route.prefix.u.prefix6);
117
118 request->path.cost = abr_entry.path.cost +
119 (ntohl (iep->metric) & ntohl (0x000fffff));
120 request->path.type = OSPF6_PATH_TYPE_INTER;
121 request->path.origin.type = lsa->header->type;
122 request->path.origin.id = lsa->header->id;
123 request->path.origin.adv_router = lsa->header->adv_router;
124 memcpy (&request->nexthop.address, &abr_entry.nexthop.address,
125 sizeof (request->nexthop.address));
126 request->nexthop.ifindex = abr_entry.nexthop.ifindex;
127
128 return 0;
129}
130
131void
132ospf6_abr_prefix_lsa_add (struct ospf6_lsa *lsa)
133{
134 struct ospf6_route_req request;
135 int ret;
136
137 if (IS_OSPF6_DUMP_ABR)
138 zlog_info ("ABR: Calculate %s", lsa->str);
139
140 ret = ospf6_abr_prefix_lsa_to_route (lsa, &request);
141 if (ret < 0)
142 return;
143
144 if (IS_OSPF6_DUMP_ABR)
145 zlog_info ("ABR: Inter Area Route add for %s", lsa->str);
146
147 ospf6_route_add (&request, ospf6->route_table);
148}
149
150void
151ospf6_abr_prefix_lsa_remove (struct ospf6_lsa *lsa)
152{
153 struct ospf6_inter_area_prefix_lsa *iep;
154 struct prefix_ipv6 prefix6;
155 struct ospf6_route_req request;
156
157 iep = OSPF6_LSA_HEADER_END (lsa->header);
158
159 prefix6.family = AF_INET6;
160 prefix6.prefixlen = iep->prefix.prefix_length;
161 ospf6_prefix_in6_addr (&iep->prefix, &prefix6.prefix);
162
163 if (IS_OSPF6_DUMP_ABR)
164 zlog_info ("ABR: Inter Area Route remove for %s", lsa->str);
165
166 for (ospf6_route_lookup (&request, (struct prefix *) &prefix6,
167 ospf6->route_table);
168 ! ospf6_route_end (&request);
169 ospf6_route_next (&request))
170 {
171 if (memcmp (&prefix6, &request.route.prefix, sizeof (prefix6)))
172 break;
173 if (request.path.origin.type != htons (OSPF6_LSA_TYPE_INTER_PREFIX) ||
174 request.path.origin.adv_router != lsa->header->adv_router ||
175 request.path.origin.id != lsa->header->id)
176 continue;
177
178 ospf6_route_remove (&request, ospf6->route_table);
179 }
180}
181
182static int
183ospf6_abr_router_lsa_to_route (struct ospf6_lsa *lsa,
184 struct ospf6_route_req *request)
185{
186 struct ospf6_inter_area_router_lsa *ier;
187 struct ospf6_route_req abr_entry;
188
189 if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTER_ROUTER))
190 {
191 if (IS_OSPF6_DUMP_ABR)
192 zlog_info ("ABR: LSA type mismatch");
193 return -1;
194 }
195
196 if (IS_LSA_MAXAGE (lsa))
197 {
198 if (IS_OSPF6_DUMP_ABR)
199 zlog_info ("ABR: LSA MaxAge");
200 return -1;
201 }
202
203 if (! ospf6_abr_entry_lookup (&abr_entry, lsa->header->adv_router,
204 (struct ospf6_area *) lsa->scope))
205 {
206 if (IS_OSPF6_DUMP_ABR)
207 zlog_info ("ABR: Advertising router check failed");
208 return -1;
209 }
210
211 ier = OSPF6_LSA_HEADER_END (lsa->header);
212
213 memset (request, 0, sizeof (struct ospf6_route_req));
214 request->route.type = OSPF6_DEST_TYPE_ROUTER;
215 request->route.prefix.family = AF_UNSPEC;
216 request->route.prefix.prefixlen = 64; /* XXX */
217 ((struct prefix_ls *) &request->route.prefix)->adv_router.s_addr
218 = ier->router_id;
219
220 request->path.cost = abr_entry.path.cost +
221 (ntohl (ier->metric & htonl (0x000fffff)));
222 request->path.type = OSPF6_PATH_TYPE_INTER;
223 request->path.origin.type = lsa->header->type;
224 request->path.origin.id = lsa->header->id;
225 request->path.origin.adv_router = lsa->header->adv_router;
226 SET_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E);
227 request->path.capability[0] = ier->options[0];
228 request->path.capability[1] = ier->options[1];
229 request->path.capability[2] = ier->options[2];
230
231 memcpy (&request->nexthop.address, &abr_entry.nexthop.address,
232 sizeof (request->nexthop.address));
233 request->nexthop.ifindex = abr_entry.nexthop.ifindex;
234
235 return 0;
236}
237
238void
239ospf6_abr_router_lsa_add (struct ospf6_lsa *lsa)
240{
241 struct ospf6_route_req request;
242 int ret;
243
244 if (IS_OSPF6_DUMP_ABR)
245 zlog_info ("ABR: Calculate %s", lsa->str);
246
247 ret = ospf6_abr_router_lsa_to_route (lsa, &request);
248 if (ret < 0)
249 return;
250
251 if (IS_OSPF6_DUMP_ABR)
252 zlog_info ("ABR: Inter Area Router add for %s", lsa->str);
253
254 ospf6_route_add (&request, ospf6->topology_table);
255}
256
257void
258ospf6_abr_router_lsa_remove (struct ospf6_lsa *lsa)
259{
260 struct ospf6_inter_area_router_lsa *ier;
261 struct prefix_ls prefix_ls;
262 struct ospf6_route_req request;
263
264 ier = OSPF6_LSA_HEADER_END (lsa->header);
265
266 memset (&prefix_ls, 0, sizeof (prefix_ls));
267 prefix_ls.family = AF_INET6;
268 prefix_ls.prefixlen = 64; /* XXX */
269 prefix_ls.adv_router.s_addr = ier->router_id;
270
271 if (IS_OSPF6_DUMP_ABR)
272 zlog_info ("ABR: Inter Area Route remove for %s", lsa->str);
273
274 for (ospf6_route_lookup (&request, (struct prefix *) &prefix_ls,
275 ospf6->route_table);
276 ! ospf6_route_end (&request);
277 ospf6_route_next (&request))
278 {
279 if (memcmp (&prefix_ls, &request.route.prefix, sizeof (prefix_ls)))
280 break;
281 if (request.path.origin.type != htons (OSPF6_LSA_TYPE_INTER_ROUTER) ||
282 request.path.origin.adv_router != lsa->header->adv_router ||
283 request.path.origin.id != lsa->header->id)
284 continue;
285
286 ospf6_route_remove (&request, ospf6->route_table);
287 }
288}
289
290
291void
292ospf6_abr_abr_entry_add (struct ospf6_route_req *abr_entry)
293{
294 struct ospf6_lsdb_node node;
295 struct prefix_ls *abr_id;
296 struct ospf6_route_req request;
297 struct ospf6_area *area;
298
299 if (IS_OSPF6_DUMP_ABR)
300 zlog_info ("ABR: New Area Border Router found");
301
302 area = ospf6_area_lookup (abr_entry->path.area_id, ospf6);
303 if (! area)
304 {
305 if (IS_OSPF6_DUMP_ABR)
306 zlog_info ("ABR: Can't find associated area");
307 return;
308 }
309
310 abr_id = (struct prefix_ls *) &abr_entry->route.prefix;
311 if (! ospf6_abr_entry_lookup (&request, abr_id->adv_router.s_addr, area))
312 {
313 if (IS_OSPF6_DUMP_ABR)
314 zlog_info ("ABR: back check failed");
315 return;
316 }
317
318 /* for each inter-prefix LSA this ABR originated */
319 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX),
320 abr_id->adv_router.s_addr, area->lsdb);
321 ! ospf6_lsdb_is_end (&node);
322 ospf6_lsdb_next (&node))
323 ospf6_abr_prefix_lsa_add (node.lsa);
324
325 /* for each inter-router LSA this ABR originated */
326 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_ROUTER),
327 abr_id->adv_router.s_addr, area->lsdb);
328 ! ospf6_lsdb_is_end (&node);
329 ospf6_lsdb_next (&node))
330 ospf6_abr_router_lsa_add (node.lsa);
331}
332
333void
334ospf6_abr_abr_entry_remove (struct ospf6_route_req *abr_entry)
335{
336 struct ospf6_lsdb_node node;
337 struct prefix_ls *abr_id;
338 struct ospf6_area *area;
339
340 if (IS_OSPF6_DUMP_ABR)
341 zlog_info ("ABR: Area Border Router removed");
342
343 abr_id = (struct prefix_ls *) &abr_entry->route.prefix;
344
345 area = ospf6_area_lookup (abr_entry->path.area_id, ospf6);
346 if (! area)
347 {
348 if (IS_OSPF6_DUMP_ABR)
349 zlog_info ("ABR: Can't find associated area");
350 return;
351 }
352
353 /* for each inter-prefix LSA this ABR originated */
354 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX),
355 abr_id->adv_router.s_addr, area->lsdb);
356 ! ospf6_lsdb_is_end (&node);
357 ospf6_lsdb_next (&node))
358 ospf6_abr_prefix_lsa_remove (node.lsa);
359
360 /* for each inter-router LSA this ABR originated */
361 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_ROUTER),
362 abr_id->adv_router.s_addr, area->lsdb);
363 ! ospf6_lsdb_is_end (&node);
364 ospf6_lsdb_next (&node))
365 ospf6_abr_router_lsa_remove (node.lsa);
366}
367
368/* Inter-Area-Prefix-LSA Origination */
369
370static void
371ospf6_abr_prefix_lsa_update_add (struct ospf6_route_req *request,
372 struct ospf6_area *area)
373{
374 char buffer [MAXLSASIZE];
375 u_int16_t size;
376 struct ospf6_inter_area_prefix_lsa *iep;
377 char *p;
378
379 if (IS_OSPF6_DUMP_ABR)
380 zlog_info ("Update Inter-Prefix for %s: ID: %lu",
381 area->str, (u_long) ntohl (request->route_id));
382
383 /* prepare buffer */
384 memset (buffer, 0, sizeof (buffer));
385 size = sizeof (struct ospf6_inter_area_prefix_lsa);
386 iep = (struct ospf6_inter_area_prefix_lsa *) buffer;
387 p = (char *) (iep + 1);
388
389 /* prefixlen */
390 iep->prefix.prefix_length = request->route.prefix.prefixlen;
391
392 /* PrefixOptions */
393 iep->prefix.prefix_options = request->path.prefix_options;
394
395 /* set Prefix */
396 memcpy (p, &request->route.prefix.u.prefix6,
397 OSPF6_PREFIX_SPACE (request->route.prefix.prefixlen));
398 ospf6_prefix_apply_mask (&iep->prefix);
399 size += OSPF6_PREFIX_SPACE (request->route.prefix.prefixlen);
400
401 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTER_PREFIX),
402 htonl (request->route_id), ospf6->router_id,
403 (char *) iep, size, area);
404}
405
406static void
407ospf6_abr_prefix_lsa_update_remove (struct ospf6_route_req *request,
408 struct ospf6_area *area)
409{
410 struct ospf6_lsa *lsa;
411 lsa = ospf6_lsdb_lookup_lsdb (htons (OSPF6_LSA_TYPE_INTER_PREFIX),
412 htonl (request->route_id),
413 ospf6->router_id, area->lsdb);
414 if (lsa)
415 ospf6_lsa_premature_aging (lsa);
416}
417
418static void
419ospf6_abr_prefix_lsa_update (int type, struct ospf6_route_req *request)
420{
421 struct ospf6_route_req route, target;
422 listnode node;
423 struct ospf6_area *area;
424 struct ospf6_interface *o6i;
425
426 if (request->route.type != OSPF6_DEST_TYPE_NETWORK)
427 return;
428
429 /* assert this is best path; if not, return */
430 ospf6_route_lookup (&route, &request->route.prefix, request->table);
431 if (memcmp (&route.path, &request->path, sizeof (route.path)))
432 return;
433
434 if (target.path.cost >= LS_INFINITY ||
435 target.path.cost_e2 >= LS_INFINITY)
436 {
437 if (IS_OSPF6_DUMP_ABR)
438 zlog_info ("ABR: Exceeds LS Infinity, ignore");
439 return;
440 }
441
442 ospf6_route_lookup (&target, &request->route.prefix, request->table);
443 if (type == REMOVE)
444 {
445 ospf6_route_next (&route);
446 if (! memcmp (&route.route, &request->route, sizeof (route.route)))
447 {
448 type = ADD;
449 ospf6_route_next (&target);
450 }
451 }
452
453 for (node = listhead (ospf6->area_list); node; nextnode (node))
454 {
455 area = getdata (node);
456
457 if (target.path.area_id == area->area_id)
458 continue;
459
460 o6i = ospf6_interface_lookup_by_index (target.nexthop.ifindex);
461 if (o6i && o6i->area && o6i->area->area_id == area->area_id)
462 {
463 zlog_info ("ABR: Logical equivalent of split horizon, skip for %s",
464 area->str);
465 continue;
466 }
467
468 if (area->area_id == ntohs (0) && /* Backbone */
469 target.path.type != OSPF6_PATH_TYPE_INTRA)
470 continue;
471
472 /* XXX, stub area check */
473
474 /* XXX, aggregate */
475 /* if either the area of the route or the area trying to
476 advertise is backbone, do not aggregate */
477
478 if (type == ADD)
479 ospf6_abr_prefix_lsa_update_add (&target, area);
480 else
481 ospf6_abr_prefix_lsa_update_remove (&target, area);
482 }
483}
484
485void
486ospf6_abr_route_add (struct ospf6_route_req *request)
487{
488 ospf6_abr_prefix_lsa_update (ADD, request);
489}
490
491void
492ospf6_abr_route_remove (struct ospf6_route_req *request)
493{
494 ospf6_abr_prefix_lsa_update (REMOVE, request);
495}
496
497int
498ospf6_abr_prefix_lsa_refresh (void *data)
499{
500 struct ospf6_lsa *lsa = data;
501 struct ospf6_inter_area_prefix_lsa *ier;
502 struct prefix_ipv6 prefix6;
503 struct ospf6_route_req route;
504
505 ier = OSPF6_LSA_HEADER_END (lsa->header);
506 memset (&prefix6, 0, sizeof (prefix6));
507 prefix6.family = AF_INET6;
508 prefix6.prefixlen = ier->prefix.prefix_length;
509 ospf6_prefix_in6_addr (&ier->prefix, &prefix6.prefix);
510
511 ospf6_route_lookup (&route, (struct prefix *) &prefix6,
512 ospf6->route_table);
513 assert (! ospf6_route_end (&route));
514
515 ospf6_abr_prefix_lsa_update (ADD, &route);
516 return 0;
517}
518
519int
520ospf6_abr_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
521{
522 struct ospf6_inter_area_prefix_lsa *ier;
523 char prefix[128];
524
525 assert (lsa->header);
526 ier = OSPF6_LSA_HEADER_END (lsa->header);
527
528 ospf6_prefix_string (&ier->prefix, prefix, sizeof (prefix));
529
530 vty_out (vty, " Metric: %d%s",
531 ntohl (ier->metric & htonl (0x000fffff)), VTY_NEWLINE);
532 vty_out (vty, " Prefix: %s%s", prefix, VTY_NEWLINE);
533
534 return 0;
535}
536
537int
538ospf6_abr_prefix_lsa_hook_add (void *data)
539{
540 struct ospf6_lsa *lsa = data;
541 ospf6_abr_prefix_lsa_add (lsa);
542 return 0;
543}
544
545int
546ospf6_abr_prefix_lsa_hook_remove (void *data)
547{
548 struct ospf6_lsa *lsa = data;
549 ospf6_abr_prefix_lsa_remove (lsa);
550 return 0;
551}
552
553void
554ospf6_abr_database_hook_inter_prefix (struct ospf6_lsa *old,
555 struct ospf6_lsa *new)
556{
557 if (old)
558 ospf6_abr_prefix_lsa_hook_remove (old);
559 if (new && ! IS_LSA_MAXAGE (new))
560 ospf6_abr_prefix_lsa_hook_add (new);
561}
562
563void
564ospf6_abr_register_inter_prefix ()
565{
566 struct ospf6_lsa_slot slot;
567
568 memset (&slot, 0, sizeof (slot));
569 slot.type = htons (OSPF6_LSA_TYPE_INTER_PREFIX);
570 slot.name = "Inter-Prefix";
571 slot.func_show = ospf6_abr_prefix_lsa_show;
572 slot.func_refresh = ospf6_abr_prefix_lsa_refresh;
573 ospf6_lsa_slot_register (&slot);
574
575 ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTER_PREFIX & OSPF6_LSTYPE_CODE_MASK].hook =
576 ospf6_abr_database_hook_inter_prefix;
577}
578
579int
580ospf6_abr_router_lsa_hook_add (void *data)
581{
582 struct ospf6_lsa *lsa = data;
583 ospf6_abr_router_lsa_add (lsa);
584 return 0;
585}
586
587int
588ospf6_abr_router_lsa_hook_remove (void *data)
589{
590 struct ospf6_lsa *lsa = data;
591 ospf6_abr_router_lsa_remove (lsa);
592 return 0;
593}
594
595int
596ospf6_abr_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
597{
598 return 0;
599}
600
601int
602ospf6_abr_router_lsa_refresh (void *data)
603{
604 return 0;
605}
606
607void
608ospf6_abr_database_hook_inter_router (struct ospf6_lsa *old,
609 struct ospf6_lsa *new)
610{
611 if (old)
612 ospf6_abr_router_lsa_hook_remove (old);
613 if (new && ! IS_LSA_MAXAGE (new))
614 ospf6_abr_router_lsa_hook_add (new);
615}
616
617void
618ospf6_abr_register_inter_router ()
619{
620 struct ospf6_lsa_slot slot;
621
622 memset (&slot, 0, sizeof (slot));
623 slot.type = htons (OSPF6_LSA_TYPE_INTER_ROUTER);
624 slot.name = "Inter-Router";
625 slot.func_show = ospf6_abr_router_lsa_show;
626 slot.func_refresh = ospf6_abr_router_lsa_refresh;
627 ospf6_lsa_slot_register (&slot);
628
629 ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTER_ROUTER & OSPF6_LSTYPE_CODE_MASK].hook =
630 ospf6_abr_database_hook_inter_router;
631}
632
633void
634ospf6_abr_inter_route_calculation (struct ospf6_area *area)
635{
636 struct ospf6_lsdb_node node;
637
638 /* for each inter-prefix LSA */
639 for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX),
640 area->lsdb);
641 ! ospf6_lsdb_is_end (&node);
642 ospf6_lsdb_next (&node))
643 ospf6_abr_prefix_lsa_add (node.lsa);
644}
645
646void
647ospf6_abr_init ()
648{
649 abr_index = ospf6_dump_install ("abr", "Area Border Router Function\n");
650
651 ospf6_abr_register_inter_prefix ();
652 ospf6_abr_register_inter_router ();
653}
654
655