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
;
65 char buf
[PREFIX2STR_BUFFER
];
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 */
96 UNSET_FLAG (as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
99 OSPF6_ASBR_METRIC_SET (as_external_lsa
, route
->path
.cost
);
102 as_external_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
105 as_external_lsa
->prefix
.prefix_options
= route
->path
.prefix_options
;
107 /* don't use refer LS-type */
108 as_external_lsa
->prefix
.prefix_refer_lstype
= htons (0);
111 memcpy (p
, &route
->prefix
.u
.prefix6
,
112 OSPF6_PREFIX_SPACE (route
->prefix
.prefixlen
));
113 ospf6_prefix_apply_mask (&as_external_lsa
->prefix
);
114 p
+= OSPF6_PREFIX_SPACE (route
->prefix
.prefixlen
);
116 /* Forwarding address */
117 if (CHECK_FLAG (as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
))
119 memcpy (p
, &info
->forwarding
, sizeof (struct in6_addr
));
120 p
+= sizeof (struct in6_addr
);
123 /* External Route Tag */
124 if (CHECK_FLAG (as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
129 /* Fill LSA Header */
131 lsa_header
->type
= htons (OSPF6_LSTYPE_AS_EXTERNAL
);
132 lsa_header
->id
= route
->path
.origin
.id
;
133 lsa_header
->adv_router
= ospf6
->router_id
;
135 ospf6_new_ls_seqnum (lsa_header
->type
, lsa_header
->id
,
136 lsa_header
->adv_router
, ospf6
->lsdb
);
137 lsa_header
->length
= htons ((caddr_t
) p
- (caddr_t
) lsa_header
);
140 ospf6_lsa_checksum (lsa_header
);
143 lsa
= ospf6_lsa_create (lsa_header
);
146 ospf6_lsa_originate_process (lsa
, ospf6
);
151 ospf6_asbr_lsa_add (struct ospf6_lsa
*lsa
)
153 struct ospf6_as_external_lsa
*external
;
154 struct prefix asbr_id
;
155 struct ospf6_route
*asbr_entry
, *route
;
156 char buf
[PREFIX2STR_BUFFER
];
158 external
= (struct ospf6_as_external_lsa
*)
159 OSPF6_LSA_HEADER_END (lsa
->header
);
161 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
162 zlog_debug ("Calculate AS-External route for %s", lsa
->name
);
164 if (lsa
->header
->adv_router
== ospf6
->router_id
)
166 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
167 zlog_debug ("Ignore self-originated AS-External-LSA");
171 if (OSPF6_ASBR_METRIC (external
) == OSPF_LS_INFINITY
)
173 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
174 zlog_debug ("Ignore LSA with LSInfinity Metric");
178 if (CHECK_FLAG(external
->prefix
.prefix_options
, OSPF6_PREFIX_OPTION_NU
))
180 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
181 zlog_debug ("Ignore LSA with NU bit set Metric");
185 ospf6_linkstate_prefix (lsa
->header
->adv_router
, htonl (0), &asbr_id
);
186 asbr_entry
= ospf6_route_lookup (&asbr_id
, ospf6
->brouter_table
);
187 if (asbr_entry
== NULL
||
188 ! CHECK_FLAG (asbr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_E
))
190 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
192 prefix2str (&asbr_id
, buf
, sizeof (buf
));
193 zlog_debug ("ASBR entry not found: %s", buf
);
198 route
= ospf6_route_create ();
199 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
200 route
->prefix
.family
= AF_INET6
;
201 route
->prefix
.prefixlen
= external
->prefix
.prefix_length
;
202 ospf6_prefix_in6_addr (&route
->prefix
.u
.prefix6
, &external
->prefix
);
204 route
->path
.area_id
= asbr_entry
->path
.area_id
;
205 route
->path
.origin
.type
= lsa
->header
->type
;
206 route
->path
.origin
.id
= lsa
->header
->id
;
207 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
209 route
->path
.prefix_options
= external
->prefix
.prefix_options
;
210 if (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_E
))
212 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL2
;
213 route
->path
.metric_type
= 2;
214 route
->path
.cost
= asbr_entry
->path
.cost
;
215 route
->path
.u
.cost_e2
= OSPF6_ASBR_METRIC (external
);
219 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL1
;
220 route
->path
.metric_type
= 1;
221 route
->path
.cost
= asbr_entry
->path
.cost
+ OSPF6_ASBR_METRIC (external
);
222 route
->path
.u
.cost_e2
= 0;
225 ospf6_route_copy_nexthops (route
, asbr_entry
);
227 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
229 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
230 zlog_debug ("AS-External route add: %s", buf
);
233 ospf6_route_add (route
, ospf6
->route_table
);
237 ospf6_asbr_lsa_remove (struct ospf6_lsa
*lsa
)
239 struct ospf6_as_external_lsa
*external
;
240 struct prefix prefix
;
241 struct ospf6_route
*route
, *nroute
;
242 char buf
[PREFIX2STR_BUFFER
];
244 external
= (struct ospf6_as_external_lsa
*)
245 OSPF6_LSA_HEADER_END (lsa
->header
);
247 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
248 zlog_debug ("Withdraw AS-External route for %s", lsa
->name
);
250 if (lsa
->header
->adv_router
== ospf6
->router_id
)
252 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
253 zlog_debug ("Ignore self-originated AS-External-LSA");
257 memset (&prefix
, 0, sizeof (struct prefix
));
258 prefix
.family
= AF_INET6
;
259 prefix
.prefixlen
= external
->prefix
.prefix_length
;
260 ospf6_prefix_in6_addr (&prefix
.u
.prefix6
, &external
->prefix
);
262 route
= ospf6_route_lookup (&prefix
, ospf6
->route_table
);
265 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
267 prefix2str (&prefix
, buf
, sizeof (buf
));
268 zlog_debug ("AS-External route %s not found", buf
);
273 for (ospf6_route_lock (route
);
274 route
&& ospf6_route_is_prefix (&prefix
, route
);
277 nroute
= ospf6_route_next (route
);
278 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
280 if (route
->path
.origin
.type
!= lsa
->header
->type
)
282 if (route
->path
.origin
.id
!= lsa
->header
->id
)
284 if (route
->path
.origin
.adv_router
!= lsa
->header
->adv_router
)
287 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
289 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
290 zlog_debug ("AS-External route remove: %s", buf
);
292 ospf6_route_remove (route
, ospf6
->route_table
);
295 ospf6_route_unlock (route
);
299 ospf6_asbr_lsentry_add (struct ospf6_route
*asbr_entry
)
301 struct ospf6_lsa
*lsa
;
305 if (! CHECK_FLAG (asbr_entry
->flag
, OSPF6_ROUTE_BEST
))
308 inet_ntop (AF_INET
, &ADV_ROUTER_IN_PREFIX (&asbr_entry
->prefix
),
310 zlog_info ("ignore non-best path: lsentry %s add", buf
);
314 type
= htons (OSPF6_LSTYPE_AS_EXTERNAL
);
315 router
= ospf6_linkstate_prefix_adv_router (&asbr_entry
->prefix
);
316 for (lsa
= ospf6_lsdb_type_router_head (type
, router
, ospf6
->lsdb
); lsa
;
317 lsa
= ospf6_lsdb_type_router_next (type
, router
, lsa
))
319 if (! OSPF6_LSA_IS_MAXAGE (lsa
))
320 ospf6_asbr_lsa_add (lsa
);
325 ospf6_asbr_lsentry_remove (struct ospf6_route
*asbr_entry
)
327 struct ospf6_lsa
*lsa
;
331 type
= htons (OSPF6_LSTYPE_AS_EXTERNAL
);
332 router
= ospf6_linkstate_prefix_adv_router (&asbr_entry
->prefix
);
333 for (lsa
= ospf6_lsdb_type_router_head (type
, router
, ospf6
->lsdb
);
334 lsa
; lsa
= ospf6_lsdb_type_router_next (type
, router
, lsa
))
335 ospf6_asbr_lsa_remove (lsa
);
340 /* redistribute function */
343 ospf6_asbr_routemap_set (int type
, const char *mapname
)
345 if (ospf6
->rmap
[type
].name
)
346 free (ospf6
->rmap
[type
].name
);
347 ospf6
->rmap
[type
].name
= strdup (mapname
);
348 ospf6
->rmap
[type
].map
= route_map_lookup_by_name (mapname
);
352 ospf6_asbr_routemap_unset (int type
)
354 if (ospf6
->rmap
[type
].name
)
355 free (ospf6
->rmap
[type
].name
);
356 ospf6
->rmap
[type
].name
= NULL
;
357 ospf6
->rmap
[type
].map
= NULL
;
361 ospf6_asbr_routemap_update (const char *mapname
)
368 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
370 if (ospf6
->rmap
[type
].name
)
371 ospf6
->rmap
[type
].map
=
372 route_map_lookup_by_name (ospf6
->rmap
[type
].name
);
374 ospf6
->rmap
[type
].map
= NULL
;
379 ospf6_asbr_is_asbr (struct ospf6
*o
)
381 return o
->external_table
->count
;
385 ospf6_asbr_redistribute_set (int type
)
387 ospf6_zebra_redistribute (type
);
391 ospf6_asbr_redistribute_unset (int type
)
393 struct ospf6_route
*route
;
394 struct ospf6_external_info
*info
;
396 ospf6_zebra_no_redistribute (type
);
398 for (route
= ospf6_route_head (ospf6
->external_table
); route
;
399 route
= ospf6_route_next (route
))
401 info
= route
->route_option
;
402 if (info
->type
!= type
)
405 ospf6_asbr_redistribute_remove (info
->type
, 0, &route
->prefix
);
408 ospf6_asbr_routemap_unset (type
);
411 /* When an area is unstubified, flood all the external LSAs in the area */
413 ospf6_asbr_send_externals_to_area (struct ospf6_area
*oa
)
415 struct ospf6_lsa
*lsa
;
417 for (lsa
= ospf6_lsdb_head (oa
->ospf6
->lsdb
); lsa
;
418 lsa
= ospf6_lsdb_next (lsa
))
420 if (ntohs (lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
)
422 zlog_debug ("%s: Flooding AS-External LSA %s\n", __func__
, lsa
->name
);
423 ospf6_flood_area (NULL
, lsa
, oa
);
429 ospf6_asbr_redistribute_add (int type
, ifindex_t ifindex
, struct prefix
*prefix
,
430 u_int nexthop_num
, struct in6_addr
*nexthop
)
433 struct ospf6_route troute
;
434 struct ospf6_external_info tinfo
;
435 struct ospf6_route
*route
, *match
;
436 struct ospf6_external_info
*info
;
437 struct prefix prefix_id
;
438 struct route_node
*node
;
439 char pbuf
[PREFIX2STR_BUFFER
], ibuf
[16];
440 struct listnode
*lnode
, *lnnode
;
441 struct ospf6_area
*oa
;
443 if (! ospf6_zebra_is_redistribute (type
))
446 if (IS_OSPF6_DEBUG_ASBR
)
448 prefix2str (prefix
, pbuf
, sizeof (pbuf
));
449 zlog_debug ("Redistribute %s (%s)", pbuf
, ZROUTE_NAME (type
));
452 /* if route-map was specified but not found, do not advertise */
453 if (ospf6
->rmap
[type
].name
)
455 if (ospf6
->rmap
[type
].map
== NULL
)
456 ospf6_asbr_routemap_update (NULL
);
457 if (ospf6
->rmap
[type
].map
== NULL
)
459 zlog_warn ("route-map \"%s\" not found, suppress redistributing",
460 ospf6
->rmap
[type
].name
);
465 /* apply route-map */
466 if (ospf6
->rmap
[type
].map
)
468 memset (&troute
, 0, sizeof (troute
));
469 memset (&tinfo
, 0, sizeof (tinfo
));
470 troute
.route_option
= &tinfo
;
471 tinfo
.ifindex
= ifindex
;
473 ret
= route_map_apply (ospf6
->rmap
[type
].map
, prefix
,
474 RMAP_OSPF6
, &troute
);
475 if (ret
== RMAP_DENYMATCH
)
477 if (IS_OSPF6_DEBUG_ASBR
)
478 zlog_debug ("Denied by route-map \"%s\"", ospf6
->rmap
[type
].name
);
483 match
= ospf6_route_lookup (prefix
, ospf6
->external_table
);
486 info
= match
->route_option
;
488 /* copy result of route-map */
489 if (ospf6
->rmap
[type
].map
)
491 if (troute
.path
.metric_type
)
492 match
->path
.metric_type
= troute
.path
.metric_type
;
493 if (troute
.path
.cost
)
494 match
->path
.cost
= troute
.path
.cost
;
495 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo
.forwarding
))
496 memcpy (&info
->forwarding
, &tinfo
.forwarding
,
497 sizeof (struct in6_addr
));
502 if (nexthop_num
&& nexthop
)
503 ospf6_route_add_nexthop (match
, ifindex
, nexthop
);
505 ospf6_route_add_nexthop (match
, ifindex
, NULL
);
507 /* create/update binding in external_id_table */
508 prefix_id
.family
= AF_INET
;
509 prefix_id
.prefixlen
= 32;
510 prefix_id
.u
.prefix4
.s_addr
= htonl (info
->id
);
511 node
= route_node_get (ospf6
->external_id_table
, &prefix_id
);
514 if (IS_OSPF6_DEBUG_ASBR
)
516 inet_ntop (AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof (ibuf
));
517 zlog_debug ("Advertise as AS-External Id:%s", ibuf
);
520 match
->path
.origin
.id
= htonl (info
->id
);
521 ospf6_as_external_lsa_originate (match
);
525 /* create new entry */
526 route
= ospf6_route_create ();
527 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
528 memcpy (&route
->prefix
, prefix
, sizeof (struct prefix
));
530 info
= (struct ospf6_external_info
*)
531 XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO
, sizeof (struct ospf6_external_info
));
532 route
->route_option
= info
;
533 info
->id
= ospf6
->external_id
++;
535 /* copy result of route-map */
536 if (ospf6
->rmap
[type
].map
)
538 if (troute
.path
.metric_type
)
539 route
->path
.metric_type
= troute
.path
.metric_type
;
540 if (troute
.path
.cost
)
541 route
->path
.cost
= troute
.path
.cost
;
542 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo
.forwarding
))
543 memcpy (&info
->forwarding
, &tinfo
.forwarding
,
544 sizeof (struct in6_addr
));
548 if (nexthop_num
&& nexthop
)
549 ospf6_route_add_nexthop (route
, ifindex
, nexthop
);
551 ospf6_route_add_nexthop (route
, ifindex
, NULL
);
553 /* create/update binding in external_id_table */
554 prefix_id
.family
= AF_INET
;
555 prefix_id
.prefixlen
= 32;
556 prefix_id
.u
.prefix4
.s_addr
= htonl (info
->id
);
557 node
= route_node_get (ospf6
->external_id_table
, &prefix_id
);
560 route
= ospf6_route_add (route
, ospf6
->external_table
);
561 route
->route_option
= info
;
563 if (IS_OSPF6_DEBUG_ASBR
)
565 inet_ntop (AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof (ibuf
));
566 zlog_debug ("Advertise as AS-External Id:%s", ibuf
);
569 route
->path
.origin
.id
= htonl (info
->id
);
570 ospf6_as_external_lsa_originate (route
);
572 /* Router-Bit (ASBR Flag) may have to be updated */
573 for (ALL_LIST_ELEMENTS (ospf6
->area_list
, lnode
, lnnode
, oa
))
574 OSPF6_ROUTER_LSA_SCHEDULE (oa
);
578 ospf6_asbr_redistribute_remove (int type
, ifindex_t ifindex
,
579 struct prefix
*prefix
)
581 struct ospf6_route
*match
;
582 struct ospf6_external_info
*info
= NULL
;
583 struct route_node
*node
;
584 struct ospf6_lsa
*lsa
;
585 struct prefix prefix_id
;
586 char pbuf
[PREFIX2STR_BUFFER
], ibuf
[16];
587 struct listnode
*lnode
, *lnnode
;
588 struct ospf6_area
*oa
;
590 match
= ospf6_route_lookup (prefix
, ospf6
->external_table
);
593 if (IS_OSPF6_DEBUG_ASBR
)
595 prefix2str (prefix
, pbuf
, sizeof (pbuf
));
596 zlog_debug ("No such route %s to withdraw", pbuf
);
601 info
= match
->route_option
;
604 if (info
->type
!= type
)
606 if (IS_OSPF6_DEBUG_ASBR
)
608 prefix2str (prefix
, pbuf
, sizeof (pbuf
));
609 zlog_debug ("Original protocol mismatch: %s", pbuf
);
614 if (IS_OSPF6_DEBUG_ASBR
)
616 prefix2str (prefix
, pbuf
, sizeof (pbuf
));
617 inet_ntop (AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof (ibuf
));
618 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf
, ibuf
);
621 lsa
= ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL
),
622 htonl (info
->id
), ospf6
->router_id
, ospf6
->lsdb
);
624 ospf6_lsa_purge (lsa
);
626 /* remove binding in external_id_table */
627 prefix_id
.family
= AF_INET
;
628 prefix_id
.prefixlen
= 32;
629 prefix_id
.u
.prefix4
.s_addr
= htonl (info
->id
);
630 node
= route_node_lookup (ospf6
->external_id_table
, &prefix_id
);
633 route_unlock_node (node
);
635 ospf6_route_remove (match
, ospf6
->external_table
);
636 XFREE (MTYPE_OSPF6_EXTERNAL_INFO
, info
);
638 /* Router-Bit (ASBR Flag) may have to be updated */
639 for (ALL_LIST_ELEMENTS (ospf6
->area_list
, lnode
, lnnode
, oa
))
640 OSPF6_ROUTER_LSA_SCHEDULE (oa
);
643 DEFUN (ospf6_redistribute
,
644 ospf6_redistribute_cmd
,
645 "redistribute <kernel|connected|static|ripng|isis|bgp|table>",
647 QUAGGA_REDIST_HELP_STR_OSPF6D
652 type
= proto_redistnum(AFI_IP6
, argv
[2]->arg
);
653 if (type
< 0 || type
== ZEBRA_ROUTE_OSPF6
)
656 ospf6_asbr_redistribute_unset (type
);
657 ospf6_asbr_redistribute_set (type
);
661 DEFUN (ospf6_redistribute_routemap
,
662 ospf6_redistribute_routemap_cmd
,
663 "redistribute <kernel|connected|static|ripng|isis|bgp|table> route-map WORD",
665 QUAGGA_REDIST_HELP_STR_OSPF6D
666 "Route map reference\n"
670 int idx_protocol
= 1;
674 type
= proto_redistnum(AFI_IP6
, argv
[idx_protocol
]->arg
);
675 if (type
< 0 || type
== ZEBRA_ROUTE_OSPF6
)
678 ospf6_asbr_redistribute_unset (type
);
679 ospf6_asbr_routemap_set (type
, argv
[idx_word
]->arg
);
680 ospf6_asbr_redistribute_set (type
);
684 DEFUN (no_ospf6_redistribute
,
685 no_ospf6_redistribute_cmd
,
686 "no redistribute <kernel|connected|static|ripng|isis|bgp|table> [route-map WORD]",
689 QUAGGA_REDIST_HELP_STR_OSPF6D
690 "Route map reference\n"
693 int idx_protocol
= 2;
696 type
= proto_redistnum(AFI_IP6
, argv
[idx_protocol
]->text
);
697 if (type
< 0 || type
== ZEBRA_ROUTE_OSPF6
)
700 ospf6_asbr_redistribute_unset (type
);
707 ospf6_redistribute_config_write (struct vty
*vty
)
711 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
713 if (type
== ZEBRA_ROUTE_OSPF6
)
715 if (! ospf6_zebra_is_redistribute (type
))
718 if (ospf6
->rmap
[type
].name
)
719 vty_out (vty
, " redistribute %s route-map %s%s",
720 ZROUTE_NAME (type
), ospf6
->rmap
[type
].name
, VNL
);
722 vty_out (vty
, " redistribute %s%s",
723 ZROUTE_NAME (type
), VNL
);
730 ospf6_redistribute_show_config (struct vty
*vty
)
733 int nroute
[ZEBRA_ROUTE_MAX
];
735 struct ospf6_route
*route
;
736 struct ospf6_external_info
*info
;
739 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
741 for (route
= ospf6_route_head (ospf6
->external_table
); route
;
742 route
= ospf6_route_next (route
))
744 info
= route
->route_option
;
745 nroute
[info
->type
]++;
749 vty_out (vty
, "Redistributing External Routes from:%s", VNL
);
750 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
752 if (type
== ZEBRA_ROUTE_OSPF6
)
754 if (! ospf6_zebra_is_redistribute (type
))
757 if (ospf6
->rmap
[type
].name
)
758 vty_out (vty
, " %d: %s with route-map \"%s\"%s%s", nroute
[type
],
759 ZROUTE_NAME (type
), ospf6
->rmap
[type
].name
,
760 (ospf6
->rmap
[type
].map
? "" : " (not found !)"),
763 vty_out (vty
, " %d: %s%s", nroute
[type
],
764 ZROUTE_NAME (type
), VNL
);
766 vty_out (vty
, "Total %d routes%s", total
, VNL
);
771 /* Routemap Functions */
772 static route_map_result_t
773 ospf6_routemap_rule_match_address_prefixlist (void *rule
,
774 struct prefix
*prefix
,
775 route_map_object_t type
,
778 struct prefix_list
*plist
;
780 if (type
!= RMAP_OSPF6
)
783 plist
= prefix_list_lookup (AFI_IP6
, (char *) rule
);
787 return (prefix_list_apply (plist
, prefix
) == PREFIX_DENY
?
788 RMAP_NOMATCH
: RMAP_MATCH
);
792 ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg
)
794 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
798 ospf6_routemap_rule_match_address_prefixlist_free (void *rule
)
800 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
803 struct route_map_rule_cmd
804 ospf6_routemap_rule_match_address_prefixlist_cmd
=
806 "ipv6 address prefix-list",
807 ospf6_routemap_rule_match_address_prefixlist
,
808 ospf6_routemap_rule_match_address_prefixlist_compile
,
809 ospf6_routemap_rule_match_address_prefixlist_free
,
812 /* `match interface IFNAME' */
813 /* Match function should return 1 if match is success else return
815 static route_map_result_t
816 ospf6_routemap_rule_match_interface (void *rule
, struct prefix
*prefix
,
817 route_map_object_t type
, void *object
)
819 struct interface
*ifp
;
820 struct ospf6_external_info
*ei
;
822 if (type
== RMAP_OSPF6
)
824 ei
= ((struct ospf6_route
*) object
)->route_option
;
825 ifp
= if_lookup_by_name ((char *)rule
);
828 && ei
->ifindex
== ifp
->ifindex
)
835 /* Route map `interface' match statement. `arg' should be
838 ospf6_routemap_rule_match_interface_compile (const char *arg
)
840 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
843 /* Free route map's compiled `interface' value. */
845 ospf6_routemap_rule_match_interface_free (void *rule
)
847 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
850 /* Route map commands for interface matching. */
851 struct route_map_rule_cmd
852 ospf6_routemap_rule_match_interface_cmd
=
855 ospf6_routemap_rule_match_interface
,
856 ospf6_routemap_rule_match_interface_compile
,
857 ospf6_routemap_rule_match_interface_free
860 static route_map_result_t
861 ospf6_routemap_rule_set_metric_type (void *rule
, struct prefix
*prefix
,
862 route_map_object_t type
, void *object
)
864 char *metric_type
= rule
;
865 struct ospf6_route
*route
= object
;
867 if (type
!= RMAP_OSPF6
)
870 if (strcmp (metric_type
, "type-2") == 0)
871 route
->path
.metric_type
= 2;
873 route
->path
.metric_type
= 1;
879 ospf6_routemap_rule_set_metric_type_compile (const char *arg
)
881 if (strcmp (arg
, "type-2") && strcmp (arg
, "type-1"))
883 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
887 ospf6_routemap_rule_set_metric_type_free (void *rule
)
889 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
892 struct route_map_rule_cmd
893 ospf6_routemap_rule_set_metric_type_cmd
=
896 ospf6_routemap_rule_set_metric_type
,
897 ospf6_routemap_rule_set_metric_type_compile
,
898 ospf6_routemap_rule_set_metric_type_free
,
901 static route_map_result_t
902 ospf6_routemap_rule_set_metric (void *rule
, struct prefix
*prefix
,
903 route_map_object_t type
, void *object
)
906 struct ospf6_route
*route
= object
;
908 if (type
!= RMAP_OSPF6
)
911 route
->path
.cost
= atoi (metric
);
916 ospf6_routemap_rule_set_metric_compile (const char *arg
)
920 metric
= strtoul (arg
, &endp
, 0);
921 if (metric
> OSPF_LS_INFINITY
|| *endp
!= '\0')
923 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
927 ospf6_routemap_rule_set_metric_free (void *rule
)
929 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
932 struct route_map_rule_cmd
933 ospf6_routemap_rule_set_metric_cmd
=
936 ospf6_routemap_rule_set_metric
,
937 ospf6_routemap_rule_set_metric_compile
,
938 ospf6_routemap_rule_set_metric_free
,
941 static route_map_result_t
942 ospf6_routemap_rule_set_forwarding (void *rule
, struct prefix
*prefix
,
943 route_map_object_t type
, void *object
)
945 char *forwarding
= rule
;
946 struct ospf6_route
*route
= object
;
947 struct ospf6_external_info
*info
= route
->route_option
;
949 if (type
!= RMAP_OSPF6
)
952 if (inet_pton (AF_INET6
, forwarding
, &info
->forwarding
) != 1)
954 memset (&info
->forwarding
, 0, sizeof (struct in6_addr
));
962 ospf6_routemap_rule_set_forwarding_compile (const char *arg
)
965 if (inet_pton (AF_INET6
, arg
, &a
) != 1)
967 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
971 ospf6_routemap_rule_set_forwarding_free (void *rule
)
973 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
976 struct route_map_rule_cmd
977 ospf6_routemap_rule_set_forwarding_cmd
=
979 "forwarding-address",
980 ospf6_routemap_rule_set_forwarding
,
981 ospf6_routemap_rule_set_forwarding_compile
,
982 ospf6_routemap_rule_set_forwarding_free
,
986 route_map_command_status (struct vty
*vty
, int ret
)
993 case RMAP_RULE_MISSING
:
994 vty_out (vty
, "OSPF6 Can't find rule.%s", VNL
);
996 case RMAP_COMPILE_ERROR
:
997 vty_out (vty
, "OSPF6 Argument is malformed.%s", VNL
);
1000 vty_out (vty
, "OSPF6 route-map add set failed.%s", VNL
);
1006 /* add "match address" */
1007 DEFUN (ospf6_routemap_match_address_prefixlist
,
1008 ospf6_routemap_match_address_prefixlist_cmd
,
1009 "match ipv6 address prefix-list WORD",
1012 "Match address of route\n"
1013 "Match entries of prefix-lists\n"
1014 "IPv6 prefix-list name\n")
1017 int ret
= route_map_add_match ((struct route_map_index
*) vty
->index
,
1018 "ipv6 address prefix-list", argv
[idx_word
]->arg
);
1019 return route_map_command_status (vty
, ret
);
1022 /* delete "match address" */
1023 DEFUN (ospf6_routemap_no_match_address_prefixlist
,
1024 ospf6_routemap_no_match_address_prefixlist_cmd
,
1025 "no match ipv6 address prefix-list WORD",
1029 "Match address of route\n"
1030 "Match entries of prefix-lists\n"
1031 "IPv6 prefix-list name\n")
1034 int ret
= route_map_delete_match ((struct route_map_index
*) vty
->index
,
1035 "ipv6 address prefix-list", argv
[idx_word
]->arg
);
1036 return route_map_command_status (vty
, ret
);
1039 /* "match interface" */
1040 DEFUN (ospf6_routemap_match_interface
,
1041 ospf6_routemap_match_interface_cmd
,
1042 "match interface WORD",
1044 "Match first hop interface of route\n"
1048 return route_map_add_match ((struct route_map_index
*) vty
->index
,
1049 "interface", argv
[idx_word
]->arg
);
1052 /* "no match interface WORD" */
1053 DEFUN (ospf6_routemap_no_match_interface
,
1054 ospf6_routemap_no_match_interface_cmd
,
1055 "no match interface [WORD]",
1058 "Match first hop interface of route\n"
1065 ret
= route_map_delete_match ((struct route_map_index
*) vty
->index
,
1066 "interface", argv
[idx_word
]->arg
);
1068 ret
= route_map_delete_match ((struct route_map_index
*) vty
->index
,
1070 return route_map_command_status (vty
, ret
);
1073 /* add "set metric-type" */
1074 DEFUN (ospf6_routemap_set_metric_type
,
1075 ospf6_routemap_set_metric_type_cmd
,
1076 "set metric-type <type-1|type-2>",
1079 "OSPF6 external type 1 metric\n"
1080 "OSPF6 external type 2 metric\n")
1082 int idx_external
= 2;
1083 int ret
= route_map_add_set ((struct route_map_index
*) vty
->index
,
1084 "metric-type", argv
[idx_external
]->arg
);
1085 return route_map_command_status (vty
, ret
);
1088 /* delete "set metric-type" */
1089 DEFUN (ospf6_routemap_no_set_metric_type
,
1090 ospf6_routemap_no_set_metric_type_cmd
,
1091 "no set metric-type <type-1|type-2>",
1095 "OSPF6 external type 1 metric\n"
1096 "OSPF6 external type 2 metric\n")
1098 int idx_external
= 3;
1099 int ret
= route_map_delete_set ((struct route_map_index
*) vty
->index
,
1100 "metric-type", argv
[idx_external
]->arg
);
1101 return route_map_command_status (vty
, ret
);
1104 /* add "set forwarding-address" */
1105 DEFUN (ospf6_routemap_set_forwarding
,
1106 ospf6_routemap_set_forwarding_cmd
,
1107 "set forwarding-address X:X::X:X",
1109 "Forwarding Address\n"
1113 int ret
= route_map_add_set ((struct route_map_index
*) vty
->index
,
1114 "forwarding-address", argv
[idx_ipv6
]->arg
);
1115 return route_map_command_status (vty
, ret
);
1118 /* delete "set forwarding-address" */
1119 DEFUN (ospf6_routemap_no_set_forwarding
,
1120 ospf6_routemap_no_set_forwarding_cmd
,
1121 "no set forwarding-address X:X::X:X",
1124 "Forwarding Address\n"
1128 int ret
= route_map_delete_set ((struct route_map_index
*) vty
->index
,
1129 "forwarding-address", argv
[idx_ipv6
]->arg
);
1130 return route_map_command_status (vty
, ret
);
1134 ospf6_routemap_init (void)
1137 route_map_init_vty ();
1138 route_map_add_hook (ospf6_asbr_routemap_update
);
1139 route_map_delete_hook (ospf6_asbr_routemap_update
);
1141 route_map_set_metric_hook (generic_set_add
);
1142 route_map_no_set_metric_hook (generic_set_delete
);
1144 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd
);
1145 route_map_install_match (&ospf6_routemap_rule_match_interface_cmd
);
1147 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd
);
1148 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd
);
1149 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd
);
1151 /* Match address prefix-list */
1152 install_element (RMAP_NODE
, &ospf6_routemap_match_address_prefixlist_cmd
);
1153 install_element (RMAP_NODE
, &ospf6_routemap_no_match_address_prefixlist_cmd
);
1155 /* Match interface */
1156 install_element (RMAP_NODE
, &ospf6_routemap_match_interface_cmd
);
1157 install_element (RMAP_NODE
, &ospf6_routemap_no_match_interface_cmd
);
1159 /* ASE Metric Type (e.g. Type-1/Type-2) */
1160 install_element (RMAP_NODE
, &ospf6_routemap_set_metric_type_cmd
);
1161 install_element (RMAP_NODE
, &ospf6_routemap_no_set_metric_type_cmd
);
1164 install_element (RMAP_NODE
, &ospf6_routemap_set_forwarding_cmd
);
1165 install_element (RMAP_NODE
, &ospf6_routemap_no_set_forwarding_cmd
);
1169 /* Display functions */
1171 ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa
*lsa
, char *buf
,
1172 int buflen
, int pos
)
1174 struct ospf6_as_external_lsa
*external
;
1175 struct in6_addr in6
;
1176 int prefix_length
= 0;
1180 external
= (struct ospf6_as_external_lsa
*)
1181 OSPF6_LSA_HEADER_END (lsa
->header
);
1185 ospf6_prefix_in6_addr (&in6
, &external
->prefix
);
1186 prefix_length
= external
->prefix
.prefix_length
;
1189 in6
= *((struct in6_addr
*)
1190 ((caddr_t
) external
+ sizeof (struct ospf6_as_external_lsa
) +
1191 OSPF6_PREFIX_SPACE (external
->prefix
.prefix_length
)));
1195 inet_ntop (AF_INET6
, &in6
, buf
, buflen
);
1197 sprintf (&buf
[strlen(buf
)], "/%d", prefix_length
);
1204 ospf6_as_external_lsa_show (struct vty
*vty
, struct ospf6_lsa
*lsa
)
1206 struct ospf6_as_external_lsa
*external
;
1209 assert (lsa
->header
);
1210 external
= (struct ospf6_as_external_lsa
*)
1211 OSPF6_LSA_HEADER_END (lsa
->header
);
1214 snprintf (buf
, sizeof (buf
), "%c%c%c",
1215 (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_E
) ? 'E' : '-'),
1216 (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_F
) ? 'F' : '-'),
1217 (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_T
) ? 'T' : '-'));
1219 vty_out (vty
, " Bits: %s%s", buf
, VNL
);
1220 vty_out (vty
, " Metric: %5lu%s", (u_long
) OSPF6_ASBR_METRIC (external
),
1223 ospf6_prefix_options_printbuf (external
->prefix
.prefix_options
,
1225 vty_out (vty
, " Prefix Options: %s%s", buf
,
1228 vty_out (vty
, " Referenced LSType: %d%s",
1229 ntohs (external
->prefix
.prefix_refer_lstype
),
1232 vty_out (vty
, " Prefix: %s%s",
1233 ospf6_as_external_lsa_get_prefix_str (lsa
, buf
, sizeof(buf
), 0), VNL
);
1235 /* Forwarding-Address */
1236 if (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_F
))
1238 vty_out (vty
, " Forwarding-Address: %s%s",
1239 ospf6_as_external_lsa_get_prefix_str (lsa
, buf
, sizeof(buf
), 1),
1247 ospf6_asbr_external_route_show (struct vty
*vty
, struct ospf6_route
*route
)
1249 struct ospf6_external_info
*info
= route
->route_option
;
1250 char prefix
[PREFIX2STR_BUFFER
], id
[16], forwarding
[64];
1253 prefix2str (&route
->prefix
, prefix
, sizeof (prefix
));
1254 tmp_id
= ntohl (info
->id
);
1255 inet_ntop (AF_INET
, &tmp_id
, id
, sizeof (id
));
1256 if (! IN6_IS_ADDR_UNSPECIFIED (&info
->forwarding
))
1257 inet_ntop (AF_INET6
, &info
->forwarding
, forwarding
, sizeof (forwarding
));
1259 snprintf (forwarding
, sizeof (forwarding
), ":: (ifindex %d)",
1260 ospf6_route_get_first_nh_index (route
));
1262 vty_out (vty
, "%c %-32s %-15s type-%d %5lu %s%s",
1263 zebra_route_char(info
->type
),
1264 prefix
, id
, route
->path
.metric_type
,
1265 (u_long
) (route
->path
.metric_type
== 2 ?
1266 route
->path
.u
.cost_e2
: route
->path
.cost
),
1270 DEFUN (show_ipv6_ospf6_redistribute
,
1271 show_ipv6_ospf6_redistribute_cmd
,
1272 "show ipv6 ospf6 redistribute",
1276 "redistributing External information\n"
1279 struct ospf6_route
*route
;
1281 OSPF6_CMD_CHECK_RUNNING ();
1283 ospf6_redistribute_show_config (vty
);
1285 for (route
= ospf6_route_head (ospf6
->external_table
); route
;
1286 route
= ospf6_route_next (route
))
1287 ospf6_asbr_external_route_show (vty
, route
);
1292 struct ospf6_lsa_handler as_external_handler
=
1294 OSPF6_LSTYPE_AS_EXTERNAL
,
1297 ospf6_as_external_lsa_show
,
1298 ospf6_as_external_lsa_get_prefix_str
1302 ospf6_asbr_init (void)
1304 ospf6_routemap_init ();
1306 ospf6_install_lsa_handler (&as_external_handler
);
1308 install_element (VIEW_NODE
, &show_ipv6_ospf6_redistribute_cmd
);
1309 install_element (ENABLE_NODE
, &show_ipv6_ospf6_redistribute_cmd
);
1311 install_element (OSPF6_NODE
, &ospf6_redistribute_cmd
);
1312 install_element (OSPF6_NODE
, &ospf6_redistribute_routemap_cmd
);
1313 install_element (OSPF6_NODE
, &no_ospf6_redistribute_cmd
);
1317 ospf6_asbr_redistribute_reset (void)
1321 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
1323 if (type
== ZEBRA_ROUTE_OSPF6
)
1325 if (ospf6_zebra_is_redistribute (type
))
1326 ospf6_asbr_redistribute_unset(type
);
1331 ospf6_asbr_terminate (void)
1333 route_map_finish ();
1336 DEFUN (debug_ospf6_asbr
,
1337 debug_ospf6_asbr_cmd
,
1341 "Debug OSPFv3 ASBR function\n"
1344 OSPF6_DEBUG_ASBR_ON ();
1348 DEFUN (no_debug_ospf6_asbr
,
1349 no_debug_ospf6_asbr_cmd
,
1350 "no debug ospf6 asbr",
1354 "Debug OSPFv3 ASBR function\n"
1357 OSPF6_DEBUG_ASBR_OFF ();
1362 config_write_ospf6_debug_asbr (struct vty
*vty
)
1364 if (IS_OSPF6_DEBUG_ASBR
)
1365 vty_out (vty
, "debug ospf6 asbr%s", VNL
);
1370 install_element_ospf6_debug_asbr ()
1372 install_element (ENABLE_NODE
, &debug_ospf6_asbr_cmd
);
1373 install_element (ENABLE_NODE
, &no_debug_ospf6_asbr_cmd
);
1374 install_element (CONFIG_NODE
, &debug_ospf6_asbr_cmd
);
1375 install_element (CONFIG_NODE
, &no_debug_ospf6_asbr_cmd
);