2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
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
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.
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.
35 #include "ospf6_proto.h"
36 #include "ospf6_lsa.h"
37 #include "ospf6_lsdb.h"
38 #include "ospf6_route.h"
39 #include "ospf6_zebra.h"
40 #include "ospf6_message.h"
42 #include "ospf6_top.h"
43 #include "ospf6_area.h"
44 #include "ospf6_interface.h"
45 #include "ospf6_neighbor.h"
46 #include "ospf6_asbr.h"
47 #include "ospf6_intra.h"
48 #include "ospf6_flood.h"
51 unsigned char conf_debug_ospf6_asbr = 0;
53 #define ZROUTE_NAME(x) zebra_route_string(x)
55 /* AS External LSA origination */
57 ospf6_as_external_lsa_originate (struct ospf6_route *route)
59 char buffer[OSPF6_MAX_LSASIZE];
60 struct ospf6_lsa_header *lsa_header;
61 struct ospf6_lsa *lsa;
62 struct ospf6_external_info *info = route->route_option;
64 struct ospf6_as_external_lsa *as_external_lsa;
68 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL))
70 prefix2str (&route->prefix, buf, sizeof (buf));
71 zlog_debug ("Originate AS-External-LSA for %s", buf);
75 memset (buffer, 0, sizeof (buffer));
76 lsa_header = (struct ospf6_lsa_header *) buffer;
77 as_external_lsa = (struct ospf6_as_external_lsa *)
78 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
80 ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa));
82 /* Fill AS-External-LSA */
84 if (route->path.metric_type == 2)
85 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
87 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
89 /* forwarding address */
90 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
91 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
93 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
95 /* external route tag */
97 SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
99 UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
102 OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);
105 as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
108 as_external_lsa->prefix.prefix_options = route->path.prefix_options;
110 /* don't use refer LS-type */
111 as_external_lsa->prefix.prefix_refer_lstype = htons (0);
114 memcpy (p, &route->prefix.u.prefix6,
115 OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
116 ospf6_prefix_apply_mask (&as_external_lsa->prefix);
117 p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
119 /* Forwarding address */
120 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
122 memcpy (p, &info->forwarding, sizeof (struct in6_addr));
123 p += sizeof (struct in6_addr);
126 /* External Route Tag */
127 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
129 route_tag_t network_order = htonl(info->tag);
131 memcpy (p, &network_order, sizeof(network_order));
132 p += sizeof(network_order);
135 /* Fill LSA Header */
137 lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
138 lsa_header->id = route->path.origin.id;
139 lsa_header->adv_router = ospf6->router_id;
141 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
142 lsa_header->adv_router, ospf6->lsdb);
143 lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
146 ospf6_lsa_checksum (lsa_header);
149 lsa = ospf6_lsa_create (lsa_header);
152 ospf6_lsa_originate_process (lsa, ospf6);
156 ospf6_as_external_lsa_get_tag (struct ospf6_lsa *lsa)
158 struct ospf6_as_external_lsa *external;
159 ptrdiff_t tag_offset;
160 route_tag_t network_order;
165 external = (struct ospf6_as_external_lsa *)
166 OSPF6_LSA_HEADER_END (lsa->header);
168 if (!CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
171 tag_offset = sizeof(*external) + OSPF6_PREFIX_SPACE(external->prefix.prefix_length);
172 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
173 tag_offset += sizeof(struct in6_addr);
175 memcpy(&network_order, (caddr_t)external + tag_offset, sizeof(network_order));
176 return ntohl(network_order);
180 ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
182 struct ospf6_as_external_lsa *external;
183 struct prefix asbr_id;
184 struct ospf6_route *asbr_entry, *route;
188 external = (struct ospf6_as_external_lsa *)
189 OSPF6_LSA_HEADER_END (lsa->header);
191 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
192 zlog_debug ("Calculate AS-External route for %s", lsa->name);
194 if (lsa->header->adv_router == ospf6->router_id)
196 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
197 zlog_debug ("Ignore self-originated AS-External-LSA");
201 if (OSPF6_ASBR_METRIC (external) == OSPF_LS_INFINITY)
203 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
204 zlog_debug ("Ignore LSA with LSInfinity Metric");
208 if (CHECK_FLAG(external->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU))
210 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
211 zlog_debug ("Ignore LSA with NU bit set Metric");
215 ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
216 asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
217 if (asbr_entry == NULL ||
218 ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
220 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
222 prefix2str (&asbr_id, buf, sizeof (buf));
223 zlog_debug ("ASBR entry not found: %s", buf);
228 route = ospf6_route_create ();
229 route->type = OSPF6_DEST_TYPE_NETWORK;
230 route->prefix.family = AF_INET6;
231 route->prefix.prefixlen = external->prefix.prefix_length;
232 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);
234 route->path.area_id = asbr_entry->path.area_id;
235 route->path.origin.type = lsa->header->type;
236 route->path.origin.id = lsa->header->id;
237 route->path.origin.adv_router = lsa->header->adv_router;
239 route->path.prefix_options = external->prefix.prefix_options;
240 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
242 route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
243 route->path.metric_type = 2;
244 route->path.cost = asbr_entry->path.cost;
245 route->path.cost_e2 = OSPF6_ASBR_METRIC (external);
249 route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
250 route->path.metric_type = 1;
251 route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
252 route->path.cost_e2 = 0;
255 route->path.tag = ospf6_as_external_lsa_get_tag (lsa);
257 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
258 ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);
260 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
262 prefix2str (&route->prefix, buf, sizeof (buf));
263 zlog_debug ("AS-External route add: %s", buf);
266 ospf6_route_add (route, ospf6->route_table);
270 ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa)
272 struct ospf6_as_external_lsa *external;
273 struct prefix prefix;
274 struct ospf6_route *route, *nroute;
277 external = (struct ospf6_as_external_lsa *)
278 OSPF6_LSA_HEADER_END (lsa->header);
280 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
281 zlog_debug ("Withdraw AS-External route for %s", lsa->name);
283 if (lsa->header->adv_router == ospf6->router_id)
285 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
286 zlog_debug ("Ignore self-originated AS-External-LSA");
290 memset (&prefix, 0, sizeof (struct prefix));
291 prefix.family = AF_INET6;
292 prefix.prefixlen = external->prefix.prefix_length;
293 ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix);
295 route = ospf6_route_lookup (&prefix, ospf6->route_table);
298 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
300 prefix2str (&prefix, buf, sizeof (buf));
301 zlog_debug ("AS-External route %s not found", buf);
306 for (ospf6_route_lock (route);
307 route && ospf6_route_is_prefix (&prefix, route);
310 nroute = ospf6_route_next (route);
311 if (route->type != OSPF6_DEST_TYPE_NETWORK)
313 if (route->path.origin.type != lsa->header->type)
315 if (route->path.origin.id != lsa->header->id)
317 if (route->path.origin.adv_router != lsa->header->adv_router)
320 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
322 prefix2str (&route->prefix, buf, sizeof (buf));
323 zlog_debug ("AS-External route remove: %s", buf);
325 ospf6_route_remove (route, ospf6->route_table);
328 ospf6_route_unlock (route);
332 ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
334 struct ospf6_lsa *lsa;
338 if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
341 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
343 zlog_info ("ignore non-best path: lsentry %s add", buf);
347 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
348 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
349 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
350 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
352 if (! OSPF6_LSA_IS_MAXAGE (lsa))
353 ospf6_asbr_lsa_add (lsa);
358 ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
360 struct ospf6_lsa *lsa;
364 type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
365 router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
366 for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
367 lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
368 ospf6_asbr_lsa_remove (lsa);
373 /* redistribute function */
376 ospf6_asbr_routemap_set (int type, const char *mapname)
378 if (ospf6->rmap[type].name)
379 free (ospf6->rmap[type].name);
380 ospf6->rmap[type].name = strdup (mapname);
381 ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
385 ospf6_asbr_routemap_unset (int type)
387 if (ospf6->rmap[type].name)
388 free (ospf6->rmap[type].name);
389 ospf6->rmap[type].name = NULL;
390 ospf6->rmap[type].map = NULL;
394 ospf6_asbr_routemap_update (const char *mapname)
401 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
403 if (ospf6->rmap[type].name)
404 ospf6->rmap[type].map =
405 route_map_lookup_by_name (ospf6->rmap[type].name);
407 ospf6->rmap[type].map = NULL;
412 ospf6_asbr_is_asbr (struct ospf6 *o)
414 return o->external_table->count;
418 ospf6_asbr_redistribute_set (int type)
420 ospf6_zebra_redistribute (type);
424 ospf6_asbr_redistribute_unset (int type)
426 struct ospf6_route *route;
427 struct ospf6_external_info *info;
429 ospf6_zebra_no_redistribute (type);
431 for (route = ospf6_route_head (ospf6->external_table); route;
432 route = ospf6_route_next (route))
434 info = route->route_option;
435 if (info->type != type)
438 ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
442 ospf6_asbr_routemap_unset (type);
446 ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix,
447 u_int nexthop_num, struct in6_addr *nexthop, route_tag_t tag)
450 struct ospf6_route troute;
451 struct ospf6_external_info tinfo;
452 struct ospf6_route *route, *match;
453 struct ospf6_external_info *info;
454 struct prefix prefix_id;
455 struct route_node *node;
456 char pbuf[64], ibuf[16];
457 struct listnode *lnode, *lnnode;
458 struct ospf6_area *oa;
460 if (! ospf6_zebra_is_redistribute (type))
463 if (IS_OSPF6_DEBUG_ASBR)
465 prefix2str (prefix, pbuf, sizeof (pbuf));
466 zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
469 /* if route-map was specified but not found, do not advertise */
470 if (ospf6->rmap[type].name)
472 if (ospf6->rmap[type].map == NULL)
473 ospf6_asbr_routemap_update (NULL);
474 if (ospf6->rmap[type].map == NULL)
476 zlog_warn ("route-map \"%s\" not found, suppress redistributing",
477 ospf6->rmap[type].name);
482 /* apply route-map */
483 if (ospf6->rmap[type].map)
485 memset (&troute, 0, sizeof (troute));
486 memset (&tinfo, 0, sizeof (tinfo));
487 troute.route_option = &tinfo;
488 tinfo.ifindex = ifindex;
491 ret = route_map_apply (ospf6->rmap[type].map, prefix,
492 RMAP_OSPF6, &troute);
493 if (ret == RMAP_DENYMATCH)
495 if (IS_OSPF6_DEBUG_ASBR)
496 zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
501 match = ospf6_route_lookup (prefix, ospf6->external_table);
504 info = match->route_option;
506 /* copy result of route-map */
507 if (ospf6->rmap[type].map)
509 if (troute.path.metric_type)
510 match->path.metric_type = troute.path.metric_type;
511 if (troute.path.cost)
512 match->path.cost = troute.path.cost;
513 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
514 memcpy (&info->forwarding, &tinfo.forwarding,
515 sizeof (struct in6_addr));
516 info->tag = tinfo.tag;
520 /* If there is no route-map, simply update the tag */
525 match->nexthop[0].ifindex = ifindex;
526 if (nexthop_num && nexthop)
527 memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
529 /* create/update binding in external_id_table */
530 prefix_id.family = AF_INET;
531 prefix_id.prefixlen = 32;
532 prefix_id.u.prefix4.s_addr = htonl (info->id);
533 node = route_node_get (ospf6->external_id_table, &prefix_id);
536 if (IS_OSPF6_DEBUG_ASBR)
538 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
539 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
542 match->path.origin.id = htonl (info->id);
543 ospf6_as_external_lsa_originate (match);
547 /* create new entry */
548 route = ospf6_route_create ();
549 route->type = OSPF6_DEST_TYPE_NETWORK;
550 memcpy (&route->prefix, prefix, sizeof (struct prefix));
552 info = (struct ospf6_external_info *)
553 XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
554 route->route_option = info;
555 info->id = ospf6->external_id++;
557 /* copy result of route-map */
558 if (ospf6->rmap[type].map)
560 if (troute.path.metric_type)
561 route->path.metric_type = troute.path.metric_type;
562 if (troute.path.cost)
563 route->path.cost = troute.path.cost;
564 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
565 memcpy (&info->forwarding, &tinfo.forwarding,
566 sizeof (struct in6_addr));
567 info->tag = tinfo.tag;
571 /* If there is no route-map, simply set the tag */
576 route->nexthop[0].ifindex = ifindex;
577 if (nexthop_num && nexthop)
578 memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
580 /* create/update binding in external_id_table */
581 prefix_id.family = AF_INET;
582 prefix_id.prefixlen = 32;
583 prefix_id.u.prefix4.s_addr = htonl (info->id);
584 node = route_node_get (ospf6->external_id_table, &prefix_id);
587 route = ospf6_route_add (route, ospf6->external_table);
588 route->route_option = info;
590 if (IS_OSPF6_DEBUG_ASBR)
592 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
593 zlog_debug ("Advertise as AS-External Id:%s", ibuf);
596 route->path.origin.id = htonl (info->id);
597 ospf6_as_external_lsa_originate (route);
599 /* Router-Bit (ASBR Flag) may have to be updated */
600 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
601 OSPF6_ROUTER_LSA_SCHEDULE (oa);
605 ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex,
606 struct prefix *prefix)
608 struct ospf6_route *match;
609 struct ospf6_external_info *info = NULL;
610 struct route_node *node;
611 struct ospf6_lsa *lsa;
612 struct prefix prefix_id;
613 char pbuf[64], ibuf[16];
614 struct listnode *lnode, *lnnode;
615 struct ospf6_area *oa;
617 match = ospf6_route_lookup (prefix, ospf6->external_table);
620 if (IS_OSPF6_DEBUG_ASBR)
622 prefix2str (prefix, pbuf, sizeof (pbuf));
623 zlog_debug ("No such route %s to withdraw", pbuf);
628 info = match->route_option;
631 if (info->type != type)
633 if (IS_OSPF6_DEBUG_ASBR)
635 prefix2str (prefix, pbuf, sizeof (pbuf));
636 zlog_debug ("Original protocol mismatch: %s", pbuf);
641 if (IS_OSPF6_DEBUG_ASBR)
643 prefix2str (prefix, pbuf, sizeof (pbuf));
644 inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
645 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
648 lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
649 htonl (info->id), ospf6->router_id, ospf6->lsdb);
651 ospf6_lsa_purge (lsa);
653 /* remove binding in external_id_table */
654 prefix_id.family = AF_INET;
655 prefix_id.prefixlen = 32;
656 prefix_id.u.prefix4.s_addr = htonl (info->id);
657 node = route_node_lookup (ospf6->external_id_table, &prefix_id);
660 route_unlock_node (node);
662 ospf6_route_remove (match, ospf6->external_table);
663 XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
665 /* Router-Bit (ASBR Flag) may have to be updated */
666 for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
667 OSPF6_ROUTER_LSA_SCHEDULE (oa);
670 DEFUN (ospf6_redistribute,
671 ospf6_redistribute_cmd,
672 "redistribute " QUAGGA_REDIST_STR_OSPF6D,
674 QUAGGA_REDIST_HELP_STR_OSPF6D
679 type = proto_redistnum(AFI_IP6, argv[0]);
680 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
683 ospf6_asbr_redistribute_unset (type);
684 ospf6_asbr_redistribute_set (type);
688 DEFUN (ospf6_redistribute_routemap,
689 ospf6_redistribute_routemap_cmd,
690 "redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
692 QUAGGA_REDIST_HELP_STR_OSPF6D
693 "Route map reference\n"
699 type = proto_redistnum(AFI_IP6, argv[0]);
700 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
703 ospf6_asbr_redistribute_unset (type);
704 ospf6_asbr_routemap_set (type, argv[1]);
705 ospf6_asbr_redistribute_set (type);
709 DEFUN (no_ospf6_redistribute,
710 no_ospf6_redistribute_cmd,
711 "no redistribute " QUAGGA_REDIST_STR_OSPF6D,
714 QUAGGA_REDIST_HELP_STR_OSPF6D
719 type = proto_redistnum(AFI_IP6, argv[0]);
720 if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
723 ospf6_asbr_redistribute_unset (type);
728 ALIAS (no_ospf6_redistribute,
729 no_ospf6_redistribute_route_map_cmd,
730 "no redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
733 QUAGGA_REDIST_HELP_STR_OSPF6D
734 "Route map reference\n"
738 ospf6_redistribute_config_write (struct vty *vty)
742 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
744 if (type == ZEBRA_ROUTE_OSPF6)
746 if (! ospf6_zebra_is_redistribute (type))
749 if (ospf6->rmap[type].name)
750 vty_out (vty, " redistribute %s route-map %s%s",
751 ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
753 vty_out (vty, " redistribute %s%s",
754 ZROUTE_NAME (type), VNL);
761 ospf6_redistribute_show_config (struct vty *vty)
764 int nroute[ZEBRA_ROUTE_MAX];
766 struct ospf6_route *route;
767 struct ospf6_external_info *info;
770 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
772 for (route = ospf6_route_head (ospf6->external_table); route;
773 route = ospf6_route_next (route))
775 info = route->route_option;
776 nroute[info->type]++;
780 vty_out (vty, "Redistributing External Routes from:%s", VNL);
781 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
783 if (type == ZEBRA_ROUTE_OSPF6)
785 if (! ospf6_zebra_is_redistribute (type))
788 if (ospf6->rmap[type].name)
789 vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
790 ZROUTE_NAME (type), ospf6->rmap[type].name,
791 (ospf6->rmap[type].map ? "" : " (not found !)"),
794 vty_out (vty, " %d: %s%s", nroute[type],
795 ZROUTE_NAME (type), VNL);
797 vty_out (vty, "Total %d routes%s", total, VNL);
802 /* Routemap Functions */
803 static route_map_result_t
804 ospf6_routemap_rule_match_address_prefixlist (void *rule,
805 struct prefix *prefix,
806 route_map_object_t type,
809 struct prefix_list *plist;
811 if (type != RMAP_OSPF6)
814 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
818 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
819 RMAP_NOMATCH : RMAP_MATCH);
823 ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
825 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
829 ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
831 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
834 struct route_map_rule_cmd
835 ospf6_routemap_rule_match_address_prefixlist_cmd =
837 "ipv6 address prefix-list",
838 ospf6_routemap_rule_match_address_prefixlist,
839 ospf6_routemap_rule_match_address_prefixlist_compile,
840 ospf6_routemap_rule_match_address_prefixlist_free,
843 /* `match interface IFNAME' */
844 /* Match function should return 1 if match is success else return
846 static route_map_result_t
847 ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix,
848 route_map_object_t type, void *object)
850 struct interface *ifp;
851 struct ospf6_external_info *ei;
853 if (type == RMAP_OSPF6)
855 ei = ((struct ospf6_route *) object)->route_option;
856 ifp = if_lookup_by_name ((char *)rule);
859 && ei->ifindex == ifp->ifindex)
866 /* Route map `interface' match statement. `arg' should be
869 ospf6_routemap_rule_match_interface_compile (const char *arg)
871 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
874 /* Free route map's compiled `interface' value. */
876 ospf6_routemap_rule_match_interface_free (void *rule)
878 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
881 /* Route map commands for interface matching. */
882 struct route_map_rule_cmd
883 ospf6_routemap_rule_match_interface_cmd =
886 ospf6_routemap_rule_match_interface,
887 ospf6_routemap_rule_match_interface_compile,
888 ospf6_routemap_rule_match_interface_free
891 /* Match function for matching route tags */
892 static route_map_result_t
893 ospf6_routemap_rule_match_tag (void *rule, struct prefix *prefix,
894 route_map_object_t type, void *object)
896 route_tag_t *tag = rule;
897 struct ospf6_route *route = object;
898 struct ospf6_external_info *info = route->route_option;
900 if (type == RMAP_OSPF6 && info->tag == *tag)
906 static struct route_map_rule_cmd
907 ospf6_routemap_rule_match_tag_cmd =
910 ospf6_routemap_rule_match_tag,
911 route_map_rule_tag_compile,
912 route_map_rule_tag_free,
915 static route_map_result_t
916 ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
917 route_map_object_t type, void *object)
919 char *metric_type = rule;
920 struct ospf6_route *route = object;
922 if (type != RMAP_OSPF6)
925 if (strcmp (metric_type, "type-2") == 0)
926 route->path.metric_type = 2;
928 route->path.metric_type = 1;
934 ospf6_routemap_rule_set_metric_type_compile (const char *arg)
936 if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
938 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
942 ospf6_routemap_rule_set_metric_type_free (void *rule)
944 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
947 struct route_map_rule_cmd
948 ospf6_routemap_rule_set_metric_type_cmd =
951 ospf6_routemap_rule_set_metric_type,
952 ospf6_routemap_rule_set_metric_type_compile,
953 ospf6_routemap_rule_set_metric_type_free,
956 static route_map_result_t
957 ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
958 route_map_object_t type, void *object)
961 struct ospf6_route *route = object;
963 if (type != RMAP_OSPF6)
966 route->path.cost = atoi (metric);
971 ospf6_routemap_rule_set_metric_compile (const char *arg)
975 metric = strtoul (arg, &endp, 0);
976 if (metric > OSPF_LS_INFINITY || *endp != '\0')
978 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
982 ospf6_routemap_rule_set_metric_free (void *rule)
984 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
987 struct route_map_rule_cmd
988 ospf6_routemap_rule_set_metric_cmd =
991 ospf6_routemap_rule_set_metric,
992 ospf6_routemap_rule_set_metric_compile,
993 ospf6_routemap_rule_set_metric_free,
996 static route_map_result_t
997 ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
998 route_map_object_t type, void *object)
1000 char *forwarding = rule;
1001 struct ospf6_route *route = object;
1002 struct ospf6_external_info *info = route->route_option;
1004 if (type != RMAP_OSPF6)
1007 if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
1009 memset (&info->forwarding, 0, sizeof (struct in6_addr));
1017 ospf6_routemap_rule_set_forwarding_compile (const char *arg)
1020 if (inet_pton (AF_INET6, arg, &a) != 1)
1022 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1026 ospf6_routemap_rule_set_forwarding_free (void *rule)
1028 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1031 struct route_map_rule_cmd
1032 ospf6_routemap_rule_set_forwarding_cmd =
1034 "forwarding-address",
1035 ospf6_routemap_rule_set_forwarding,
1036 ospf6_routemap_rule_set_forwarding_compile,
1037 ospf6_routemap_rule_set_forwarding_free,
1040 static route_map_result_t
1041 ospf6_routemap_rule_set_tag (void *rule, struct prefix *prefix,
1042 route_map_object_t type, void *object)
1044 route_tag_t *tag = rule;
1045 struct ospf6_route *route = object;
1046 struct ospf6_external_info *info = route->route_option;
1048 if (type != RMAP_OSPF6)
1055 static struct route_map_rule_cmd
1056 ospf6_routemap_rule_set_tag_cmd =
1059 ospf6_routemap_rule_set_tag,
1060 route_map_rule_tag_compile,
1061 route_map_rule_tag_free,
1065 route_map_command_status (struct vty *vty, int ret)
1072 case RMAP_RULE_MISSING:
1073 vty_out (vty, "OSPF6 Can't find rule.%s", VNL);
1075 case RMAP_COMPILE_ERROR:
1076 vty_out (vty, "OSPF6 Argument is malformed.%s", VNL);
1079 vty_out (vty, "OSPF6 route-map add set failed.%s", VNL);
1085 /* add "match address" */
1086 DEFUN (ospf6_routemap_match_address_prefixlist,
1087 ospf6_routemap_match_address_prefixlist_cmd,
1088 "match ipv6 address prefix-list WORD",
1091 "Match address of route\n"
1092 "Match entries of prefix-lists\n"
1093 "IPv6 prefix-list name\n")
1095 int ret = route_map_add_match ((struct route_map_index *) vty->index,
1096 "ipv6 address prefix-list", argv[0]);
1097 return route_map_command_status (vty, ret);
1100 /* delete "match address" */
1101 DEFUN (ospf6_routemap_no_match_address_prefixlist,
1102 ospf6_routemap_no_match_address_prefixlist_cmd,
1103 "no match ipv6 address prefix-list WORD",
1107 "Match address of route\n"
1108 "Match entries of prefix-lists\n"
1109 "IPv6 prefix-list name\n")
1111 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1112 "ipv6 address prefix-list", argv[0]);
1113 return route_map_command_status (vty, ret);
1116 /* "match interface" */
1117 DEFUN (ospf6_routemap_match_interface,
1118 ospf6_routemap_match_interface_cmd,
1119 "match interface WORD",
1121 "Match first hop interface of route\n"
1124 return route_map_add_match ((struct route_map_index *) vty->index,
1125 "interface", argv[0]);
1128 /* "no match interface WORD" */
1129 DEFUN (ospf6_routemap_no_match_interface,
1130 ospf6_routemap_no_match_interface_cmd,
1131 "no match interface",
1134 "Match first hop interface of route\n")
1136 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1137 "interface", (argc == 0) ? NULL : argv[0]);
1138 return route_map_command_status (vty, ret);
1141 ALIAS (ospf6_routemap_no_match_interface,
1142 ospf6_routemap_no_match_interface_val_cmd,
1143 "no match interface WORD",
1146 "Match first hop interface of route\n"
1149 /* add "match tag" */
1150 DEFUN (ospf6_routemap_match_tag,
1151 ospf6_routemap_match_tag_cmd,
1152 "match tag <1-4294967295>",
1154 "Tag value for routing protocol\n"
1157 int ret = route_map_add_match ((struct route_map_index *) vty->index,
1159 return route_map_command_status (vty, ret);
1162 /* delete "match tag" */
1163 DEFUN (ospf6_routemap_no_match_tag,
1164 ospf6_routemap_no_match_tag_cmd,
1168 "Tag value for routing protocol\n")
1170 int ret = route_map_delete_match ((struct route_map_index *) vty->index,
1171 "tag", argc ? argv[0] : NULL);
1172 return route_map_command_status (vty, ret);
1175 ALIAS (ospf6_routemap_no_match_tag,
1176 ospf6_routemap_no_match_tag_val_cmd,
1177 "no match tag <1-4294967295>",
1180 "Tag value for routing protocol\n"
1183 /* add "set metric-type" */
1184 DEFUN (ospf6_routemap_set_metric_type,
1185 ospf6_routemap_set_metric_type_cmd,
1186 "set metric-type (type-1|type-2)",
1189 "OSPF6 external type 1 metric\n"
1190 "OSPF6 external type 2 metric\n")
1192 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1193 "metric-type", argv[0]);
1194 return route_map_command_status (vty, ret);
1197 /* delete "set metric-type" */
1198 DEFUN (ospf6_routemap_no_set_metric_type,
1199 ospf6_routemap_no_set_metric_type_cmd,
1200 "no set metric-type (type-1|type-2)",
1204 "OSPF6 external type 1 metric\n"
1205 "OSPF6 external type 2 metric\n")
1207 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1208 "metric-type", argv[0]);
1209 return route_map_command_status (vty, ret);
1212 /* add "set metric" */
1215 "set metric <0-4294967295>",
1220 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1222 return route_map_command_status (vty, ret);
1225 /* delete "set metric" */
1226 DEFUN (no_set_metric,
1231 "Metric value for destination routing protocol\n")
1236 ret = route_map_delete_set ((struct route_map_index *) vty->index,
1239 ret = route_map_delete_set ((struct route_map_index *) vty->index,
1241 return route_map_command_status (vty, ret);
1244 ALIAS (no_set_metric,
1245 no_set_metric_val_cmd,
1246 "no set metric <0-4294967295>",
1249 "Metric value for destination routing protocol\n"
1252 /* add "set forwarding-address" */
1253 DEFUN (ospf6_routemap_set_forwarding,
1254 ospf6_routemap_set_forwarding_cmd,
1255 "set forwarding-address X:X::X:X",
1257 "Forwarding Address\n"
1260 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1261 "forwarding-address", argv[0]);
1262 return route_map_command_status (vty, ret);
1265 /* delete "set forwarding-address" */
1266 DEFUN (ospf6_routemap_no_set_forwarding,
1267 ospf6_routemap_no_set_forwarding_cmd,
1268 "no set forwarding-address X:X::X:X",
1271 "Forwarding Address\n"
1274 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1275 "forwarding-address", argv[0]);
1276 return route_map_command_status (vty, ret);
1280 DEFUN (ospf6_routemap_set_tag,
1281 ospf6_routemap_set_tag_cmd,
1282 "set tag <1-4294967295>",
1284 "Tag value for routing protocol\n"
1287 int ret = route_map_add_set ((struct route_map_index *) vty->index,
1289 return route_map_command_status (vty, ret);
1292 /* delete "set tag" */
1293 DEFUN (ospf6_routemap_no_set_tag,
1294 ospf6_routemap_no_set_tag_cmd,
1298 "Tag value for routing protocol\n")
1300 int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1301 "tag", argc ? argv[0] : NULL);
1302 return route_map_command_status (vty, ret);
1305 ALIAS (ospf6_routemap_no_set_tag,
1306 ospf6_routemap_no_set_tag_val_cmd,
1307 "no set tag <1-4294967295>",
1310 "Tag value for routing protocol\n"
1314 ospf6_routemap_init (void)
1317 route_map_init_vty ();
1318 route_map_add_hook (ospf6_asbr_routemap_update);
1319 route_map_delete_hook (ospf6_asbr_routemap_update);
1321 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
1322 route_map_install_match (&ospf6_routemap_rule_match_interface_cmd);
1323 route_map_install_match (&ospf6_routemap_rule_match_tag_cmd);
1325 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
1326 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
1327 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
1328 route_map_install_set (&ospf6_routemap_rule_set_tag_cmd);
1330 /* Match address prefix-list */
1331 install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
1332 install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
1334 /* Match interface */
1335 install_element (RMAP_NODE, &ospf6_routemap_match_interface_cmd);
1336 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_cmd);
1337 install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_val_cmd);
1340 install_element (RMAP_NODE, &ospf6_routemap_match_tag_cmd);
1341 install_element (RMAP_NODE, &ospf6_routemap_no_match_tag_cmd);
1342 install_element (RMAP_NODE, &ospf6_routemap_no_match_tag_val_cmd);
1344 /* ASE Metric Type (e.g. Type-1/Type-2) */
1345 install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1346 install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
1349 install_element (RMAP_NODE, &set_metric_cmd);
1350 install_element (RMAP_NODE, &no_set_metric_cmd);
1351 install_element (RMAP_NODE, &no_set_metric_val_cmd);
1353 /* Forwarding address */
1354 install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1355 install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
1358 install_element (RMAP_NODE, &ospf6_routemap_set_tag_cmd);
1359 install_element (RMAP_NODE, &ospf6_routemap_no_set_tag_cmd);
1360 install_element (RMAP_NODE, &ospf6_routemap_no_set_tag_val_cmd);
1364 /* Display functions */
1366 ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
1367 int buflen, int pos)
1369 struct ospf6_as_external_lsa *external;
1370 struct in6_addr in6;
1371 int prefix_length = 0;
1375 external = (struct ospf6_as_external_lsa *)
1376 OSPF6_LSA_HEADER_END (lsa->header);
1380 ospf6_prefix_in6_addr (&in6, &external->prefix);
1381 prefix_length = external->prefix.prefix_length;
1384 in6 = *((struct in6_addr *)
1385 ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
1386 OSPF6_PREFIX_SPACE (external->prefix.prefix_length)));
1390 inet_ntop (AF_INET6, &in6, buf, buflen);
1392 sprintf (&buf[strlen(buf)], "/%d", prefix_length);
1399 ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1401 struct ospf6_as_external_lsa *external;
1404 assert (lsa->header);
1405 external = (struct ospf6_as_external_lsa *)
1406 OSPF6_LSA_HEADER_END (lsa->header);
1409 snprintf (buf, sizeof (buf), "%c%c%c",
1410 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
1411 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
1412 (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
1414 vty_out (vty, " Bits: %s%s", buf, VNL);
1415 vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
1418 ospf6_prefix_options_printbuf (external->prefix.prefix_options,
1420 vty_out (vty, " Prefix Options: %s%s", buf,
1423 vty_out (vty, " Referenced LSType: %d%s",
1424 ntohs (external->prefix.prefix_refer_lstype),
1427 vty_out (vty, " Prefix: %s%s",
1428 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0), VNL);
1430 /* Forwarding-Address */
1431 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
1433 vty_out (vty, " Forwarding-Address: %s%s",
1434 ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1),
1439 if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
1441 vty_out (vty, " Tag: %u%s",
1442 ospf6_as_external_lsa_get_tag (lsa), VNL);
1449 ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
1451 struct ospf6_external_info *info = route->route_option;
1452 char prefix[64], id[16], forwarding[64];
1455 prefix2str (&route->prefix, prefix, sizeof (prefix));
1456 tmp_id = ntohl (info->id);
1457 inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
1458 if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
1459 inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
1461 snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
1462 route->nexthop[0].ifindex);
1464 vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
1465 zebra_route_char(info->type),
1466 prefix, id, route->path.metric_type,
1467 (u_long) (route->path.metric_type == 2 ?
1468 route->path.cost_e2 : route->path.cost),
1472 DEFUN (show_ipv6_ospf6_redistribute,
1473 show_ipv6_ospf6_redistribute_cmd,
1474 "show ipv6 ospf6 redistribute",
1478 "redistributing External information\n"
1481 struct ospf6_route *route;
1483 OSPF6_CMD_CHECK_RUNNING ();
1485 ospf6_redistribute_show_config (vty);
1487 for (route = ospf6_route_head (ospf6->external_table); route;
1488 route = ospf6_route_next (route))
1489 ospf6_asbr_external_route_show (vty, route);
1494 struct ospf6_lsa_handler as_external_handler =
1496 OSPF6_LSTYPE_AS_EXTERNAL,
1499 ospf6_as_external_lsa_show,
1500 ospf6_as_external_lsa_get_prefix_str
1504 ospf6_asbr_init (void)
1506 ospf6_routemap_init ();
1508 ospf6_install_lsa_handler (&as_external_handler);
1510 install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
1512 install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1513 install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1514 install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
1515 install_element (OSPF6_NODE, &no_ospf6_redistribute_route_map_cmd);
1519 ospf6_asbr_redistribute_reset (void)
1523 for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
1525 if (type == ZEBRA_ROUTE_OSPF6)
1527 if (ospf6_zebra_is_redistribute (type))
1528 ospf6_asbr_redistribute_unset(type);
1533 ospf6_asbr_terminate (void)
1535 route_map_finish ();
1538 DEFUN (debug_ospf6_asbr,
1539 debug_ospf6_asbr_cmd,
1543 "Debug OSPFv3 ASBR function\n"
1546 OSPF6_DEBUG_ASBR_ON ();
1550 DEFUN (no_debug_ospf6_asbr,
1551 no_debug_ospf6_asbr_cmd,
1552 "no debug ospf6 asbr",
1556 "Debug OSPFv3 ASBR function\n"
1559 OSPF6_DEBUG_ASBR_OFF ();
1564 config_write_ospf6_debug_asbr (struct vty *vty)
1566 if (IS_OSPF6_DEBUG_ASBR)
1567 vty_out (vty, "debug ospf6 asbr%s", VNL);
1572 install_element_ospf6_debug_asbr ()
1574 install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
1575 install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1576 install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
1577 install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);