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 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
34 #include "ospf6_proto.h"
35 #include "ospf6_lsa.h"
36 #include "ospf6_lsdb.h"
37 #include "ospf6_route.h"
38 #include "ospf6_zebra.h"
39 #include "ospf6_message.h"
41 #include "ospf6_top.h"
42 #include "ospf6_area.h"
43 #include "ospf6_interface.h"
44 #include "ospf6_neighbor.h"
45 #include "ospf6_asbr.h"
46 #include "ospf6_intra.h"
47 #include "ospf6_flood.h"
50 unsigned char conf_debug_ospf6_asbr
= 0;
52 #define ZROUTE_NAME(x) zebra_route_string(x)
54 /* AS External LSA origination */
55 static void ospf6_as_external_lsa_originate(struct ospf6_route
*route
)
57 char buffer
[OSPF6_MAX_LSASIZE
];
58 struct ospf6_lsa_header
*lsa_header
;
59 struct ospf6_lsa
*lsa
;
60 struct ospf6_external_info
*info
= route
->route_option
;
62 struct ospf6_as_external_lsa
*as_external_lsa
;
63 char buf
[PREFIX2STR_BUFFER
];
66 if (IS_OSPF6_DEBUG_ASBR
|| IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL
)) {
67 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
68 zlog_debug("Originate AS-External-LSA for %s", buf
);
72 memset(buffer
, 0, sizeof(buffer
));
73 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
74 as_external_lsa
= (struct ospf6_as_external_lsa
75 *)((caddr_t
)lsa_header
76 + sizeof(struct ospf6_lsa_header
));
77 p
= (caddr_t
)((caddr_t
)as_external_lsa
78 + sizeof(struct ospf6_as_external_lsa
));
80 /* Fill AS-External-LSA */
82 if (route
->path
.metric_type
== 2)
83 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
85 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
87 /* forwarding address */
88 if (!IN6_IS_ADDR_UNSPECIFIED(&info
->forwarding
))
89 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
91 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
93 /* external route tag */
95 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
97 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
100 OSPF6_ASBR_METRIC_SET(as_external_lsa
, route
->path
.cost
);
103 as_external_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
106 as_external_lsa
->prefix
.prefix_options
= route
->path
.prefix_options
;
108 /* don't use refer LS-type */
109 as_external_lsa
->prefix
.prefix_refer_lstype
= htons(0);
112 memcpy(p
, &route
->prefix
.u
.prefix6
,
113 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
114 ospf6_prefix_apply_mask(&as_external_lsa
->prefix
);
115 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
117 /* Forwarding address */
118 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
)) {
125 route_tag_t network_order
= htonl(info
->tag
);
127 memcpy(p
, &network_order
, sizeof(network_order
));
128 p
+= sizeof(network_order
);
131 /* Fill LSA Header */
133 lsa_header
->type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
134 lsa_header
->id
= route
->path
.origin
.id
;
135 lsa_header
->adv_router
= ospf6
->router_id
;
137 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
138 lsa_header
->adv_router
, ospf6
->lsdb
);
139 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
142 ospf6_lsa_checksum(lsa_header
);
145 lsa
= ospf6_lsa_create(lsa_header
);
148 ospf6_lsa_originate_process(lsa
, ospf6
);
151 static route_tag_t
ospf6_as_external_lsa_get_tag(struct ospf6_lsa
*lsa
)
153 struct ospf6_as_external_lsa
*external
;
154 ptrdiff_t tag_offset
;
155 route_tag_t network_order
;
160 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
163 if (!CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
))
166 tag_offset
= sizeof(*external
)
167 + OSPF6_PREFIX_SPACE(external
->prefix
.prefix_length
);
168 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
))
169 tag_offset
+= sizeof(struct in6_addr
);
171 memcpy(&network_order
, (caddr_t
)external
+ tag_offset
,
172 sizeof(network_order
));
173 return ntohl(network_order
);
176 void ospf6_asbr_update_route_ecmp_path(struct ospf6_route
*old
,
177 struct ospf6_route
*route
)
179 struct ospf6_route
*old_route
;
180 struct ospf6_path
*ecmp_path
, *o_path
= NULL
;
181 struct listnode
*anode
;
182 struct listnode
*nnode
, *rnode
, *rnext
;
183 struct ospf6_nexthop
*nh
, *rnh
;
184 char buf
[PREFIX2STR_BUFFER
];
185 bool route_found
= false;
187 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
188 if (ospf6_route_is_same(old_route
, route
) &&
189 (old_route
->path
.type
== route
->path
.type
) &&
190 (old_route
->path
.cost
== route
->path
.cost
) &&
191 (old_route
->path
.u
.cost_e2
== route
->path
.u
.cost_e2
)) {
193 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
194 prefix2str(&old_route
->prefix
, buf
,
196 zlog_debug("%s: old route %s path cost %u [%u]",
197 __PRETTY_FUNCTION__
, buf
,
198 old_route
->path
.cost
,
199 ospf6_route_is_same(old_route
,
203 /* check if this path exists already in
204 * route->paths list, if so, replace nh_list
207 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
209 if ((o_path
->origin
.id
== route
->path
.origin
.id
)
210 && (o_path
->origin
.adv_router
==
211 route
->path
.origin
.adv_router
))
214 /* If path is not found in old_route paths's list,
215 * add a new path to route paths list and merge
216 * nexthops in route->path->nh_list.
217 * Otherwise replace existing path's nh_list.
219 if (o_path
== NULL
) {
220 ecmp_path
= ospf6_path_dup(&route
->path
);
222 /* Add a nh_list to new ecmp path */
223 ospf6_copy_nexthops(ecmp_path
->nh_list
,
225 /* Merge nexthop to existing route's nh_list */
226 ospf6_route_merge_nexthops(old_route
, route
);
229 if (ospf6
->route_table
->hook_add
)
230 (*ospf6
->route_table
->hook_add
)
233 /* Add the new path to route's path list */
234 listnode_add_sort(old_route
->paths
, ecmp_path
);
236 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
237 prefix2str(&route
->prefix
, buf
,
239 zlog_debug("%s: route %s another path added with nh %u, Paths %u",
240 __PRETTY_FUNCTION__
, buf
,
241 listcount(ecmp_path
->nh_list
),
243 listcount(old_route
->paths
)
247 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
,
249 for (ALL_LIST_ELEMENTS(
251 rnode
, rnext
, rnh
)) {
252 if (!ospf6_nexthop_is_same(rnh
,
259 ospf6_nexthop_delete(rnh
);
262 list_delete_all_node(o_path
->nh_list
);
263 ospf6_copy_nexthops(o_path
->nh_list
,
266 /* Merge nexthop to existing route's nh_list */
267 ospf6_route_merge_nexthops(old_route
,
270 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
271 prefix2str(&route
->prefix
,
273 zlog_debug("%s: existing route %s with effective nh count %u",
274 __PRETTY_FUNCTION__
, buf
,
276 listcount(old_route
->nh_list
)
281 if (ospf6
->route_table
->hook_add
)
282 (*ospf6
->route_table
->hook_add
)
286 /* Delete the new route its info added to existing
289 ospf6_route_delete(route
);
295 /* Add new route to existing node in ospf6 route table. */
296 ospf6_route_add(route
, ospf6
->route_table
);
300 void ospf6_asbr_lsa_add(struct ospf6_lsa
*lsa
)
302 struct ospf6_as_external_lsa
*external
;
303 struct prefix asbr_id
;
304 struct ospf6_route
*asbr_entry
, *route
, *old
;
305 struct ospf6_path
*path
;
306 char buf
[PREFIX2STR_BUFFER
];
308 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
311 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
312 zlog_debug("Calculate AS-External route for %s", lsa
->name
);
314 if (lsa
->header
->adv_router
== ospf6
->router_id
) {
315 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
316 zlog_debug("Ignore self-originated AS-External-LSA");
320 if (OSPF6_ASBR_METRIC(external
) == OSPF_LS_INFINITY
) {
321 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
322 zlog_debug("Ignore LSA with LSInfinity Metric");
326 if (CHECK_FLAG(external
->prefix
.prefix_options
,
327 OSPF6_PREFIX_OPTION_NU
)) {
328 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
329 zlog_debug("Ignore LSA with NU bit set Metric");
333 ospf6_linkstate_prefix(lsa
->header
->adv_router
, htonl(0), &asbr_id
);
334 asbr_entry
= ospf6_route_lookup(&asbr_id
, ospf6
->brouter_table
);
335 if (asbr_entry
== NULL
336 || !CHECK_FLAG(asbr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)) {
337 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
338 prefix2str(&asbr_id
, buf
, sizeof(buf
));
339 zlog_debug("ASBR entry not found: %s", buf
);
344 route
= ospf6_route_create();
345 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
346 route
->prefix
.family
= AF_INET6
;
347 route
->prefix
.prefixlen
= external
->prefix
.prefix_length
;
348 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
, &external
->prefix
);
350 route
->path
.area_id
= asbr_entry
->path
.area_id
;
351 route
->path
.origin
.type
= lsa
->header
->type
;
352 route
->path
.origin
.id
= lsa
->header
->id
;
353 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
355 route
->path
.prefix_options
= external
->prefix
.prefix_options
;
356 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_E
)) {
357 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL2
;
358 route
->path
.metric_type
= 2;
359 route
->path
.cost
= asbr_entry
->path
.cost
;
360 route
->path
.u
.cost_e2
= OSPF6_ASBR_METRIC(external
);
362 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL1
;
363 route
->path
.metric_type
= 1;
365 asbr_entry
->path
.cost
+ OSPF6_ASBR_METRIC(external
);
366 route
->path
.u
.cost_e2
= 0;
369 route
->path
.tag
= ospf6_as_external_lsa_get_tag(lsa
);
371 ospf6_route_copy_nexthops(route
, asbr_entry
);
373 path
= ospf6_path_dup(&route
->path
);
374 ospf6_copy_nexthops(path
->nh_list
, asbr_entry
->nh_list
);
375 listnode_add_sort(route
->paths
, path
);
378 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
379 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
380 zlog_debug("%s: AS-External %u route add %s cost %u(%u) nh %u",
382 (route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL1
)
383 ? 1 : 2, buf
, route
->path
.cost
,
384 route
->path
.u
.cost_e2
,
385 listcount(route
->nh_list
));
388 old
= ospf6_route_lookup(&route
->prefix
, ospf6
->route_table
);
390 /* Add the new route to ospf6 instance route table. */
391 ospf6_route_add(route
, ospf6
->route_table
);
394 * ECMP: Keep new equal preference path in current
395 * route's path list, update zebra with new effective
396 * list along with addition of ECMP path.
398 ospf6_asbr_update_route_ecmp_path(old
, route
);
403 void ospf6_asbr_lsa_remove(struct ospf6_lsa
*lsa
)
405 struct ospf6_as_external_lsa
*external
;
406 struct prefix prefix
;
407 struct ospf6_route
*route
, *nroute
;
408 char buf
[PREFIX2STR_BUFFER
];
410 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
413 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
414 zlog_debug("Withdraw AS-External route for %s", lsa
->name
);
416 if (lsa
->header
->adv_router
== ospf6
->router_id
) {
417 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
418 zlog_debug("Ignore self-originated AS-External-LSA");
422 memset(&prefix
, 0, sizeof(struct prefix
));
423 prefix
.family
= AF_INET6
;
424 prefix
.prefixlen
= external
->prefix
.prefix_length
;
425 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, &external
->prefix
);
427 route
= ospf6_route_lookup(&prefix
, ospf6
->route_table
);
429 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
430 prefix2str(&prefix
, buf
, sizeof(buf
));
431 zlog_debug("AS-External route %s not found", buf
);
436 for (ospf6_route_lock(route
);
437 route
&& ospf6_route_is_prefix(&prefix
, route
); route
= nroute
) {
438 nroute
= ospf6_route_next(route
);
439 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
442 /* Route has multiple ECMP paths remove,
443 * matching path and update effective route's nh list.
445 if (listcount(route
->paths
) > 1) {
446 struct listnode
*anode
, *anext
;
447 struct listnode
*nnode
, *rnode
, *rnext
;
448 struct ospf6_nexthop
*nh
, *rnh
;
449 struct ospf6_path
*o_path
;
450 bool nh_updated
= false;
452 /* Iterate all paths of route to find maching with LSA
453 * remove from route path list. If route->path is same,
454 * replace from paths list.
456 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
,
458 if (o_path
->origin
.type
!= lsa
->header
->type
)
460 if (o_path
->origin
.id
!= lsa
->header
->id
)
462 if (o_path
->origin
.adv_router
!=
463 lsa
->header
->adv_router
)
466 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
467 prefix2str(&prefix
, buf
, sizeof(buf
));
469 "%s: route %s path found with nh %u",
470 __PRETTY_FUNCTION__
, buf
,
471 listcount(o_path
->nh_list
));
474 /* Remove found path's nh_list from
475 * the route's nh_list.
477 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
,
479 for (ALL_LIST_ELEMENTS(route
->nh_list
,
480 rnode
, rnext
, rnh
)) {
481 if (!ospf6_nexthop_is_same(rnh
,
484 listnode_delete(route
->nh_list
,
486 ospf6_nexthop_delete(rnh
);
489 /* Delete the path from route's path list */
490 listnode_delete(route
->paths
, o_path
);
491 ospf6_path_free(o_path
);
496 /* Iterate all paths and merge nexthop,
497 * unlesss any of the nexthop similar to
498 * ones deleted as part of path deletion.
501 for (ALL_LIST_ELEMENTS(route
->paths
, anode
,
503 ospf6_merge_nexthops(route
->nh_list
,
507 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
508 prefix2str(&route
->prefix
, buf
,
510 zlog_debug("%s: AS-External %u route %s update paths %u nh %u"
511 , __PRETTY_FUNCTION__
,
513 OSPF6_PATH_TYPE_EXTERNAL1
)
515 listcount(route
->paths
),
516 listcount(route
->nh_list
));
519 /* Update RIB/FIB w/ effective nh_list */
520 if (ospf6
->route_table
->hook_add
)
521 (*ospf6
->route_table
->hook_add
)(route
);
523 /* route's path is similar to lsa header,
524 * replace route's path with route's
527 if (route
->path
.origin
.id
== lsa
->header
->id
&&
528 route
->path
.origin
.adv_router
==
529 lsa
->header
->adv_router
) {
530 struct ospf6_path
*h_path
;
532 h_path
= (struct ospf6_path
*)
533 listgetdata(listhead(route
->paths
));
534 route
->path
.origin
.type
=
536 route
->path
.origin
.id
=
538 route
->path
.origin
.adv_router
=
539 h_path
->origin
.adv_router
;
545 if (route
->path
.origin
.type
!= lsa
->header
->type
)
547 if (route
->path
.origin
.id
!= lsa
->header
->id
)
549 if (route
->path
.origin
.adv_router
!=
550 lsa
->header
->adv_router
)
553 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
554 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
555 zlog_debug("%s: AS-External %u route remove %s cost %u(%u) nh %u",
557 route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL1
558 ? 1 : 2, buf
, route
->path
.cost
,
559 route
->path
.u
.cost_e2
,
560 listcount(route
->nh_list
));
562 ospf6_route_remove(route
, ospf6
->route_table
);
565 ospf6_route_unlock(route
);
568 void ospf6_asbr_lsentry_add(struct ospf6_route
*asbr_entry
)
570 struct ospf6_lsa
*lsa
;
574 if (!CHECK_FLAG(asbr_entry
->flag
, OSPF6_ROUTE_BEST
)) {
576 inet_ntop(AF_INET
, &ADV_ROUTER_IN_PREFIX(&asbr_entry
->prefix
),
578 zlog_info("ignore non-best path: lsentry %s add", buf
);
582 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
583 router
= ospf6_linkstate_prefix_adv_router(&asbr_entry
->prefix
);
584 for (ALL_LSDB_TYPED_ADVRTR(ospf6
->lsdb
, type
, router
, lsa
)) {
585 if (!OSPF6_LSA_IS_MAXAGE(lsa
))
586 ospf6_asbr_lsa_add(lsa
);
590 void ospf6_asbr_lsentry_remove(struct ospf6_route
*asbr_entry
)
592 struct ospf6_lsa
*lsa
;
596 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
597 router
= ospf6_linkstate_prefix_adv_router(&asbr_entry
->prefix
);
598 for (ALL_LSDB_TYPED_ADVRTR(ospf6
->lsdb
, type
, router
, lsa
))
599 ospf6_asbr_lsa_remove(lsa
);
603 /* redistribute function */
605 static void ospf6_asbr_routemap_set(int type
, const char *mapname
)
607 if (ospf6
->rmap
[type
].name
)
608 free(ospf6
->rmap
[type
].name
);
609 ospf6
->rmap
[type
].name
= strdup(mapname
);
610 ospf6
->rmap
[type
].map
= route_map_lookup_by_name(mapname
);
613 static void ospf6_asbr_routemap_unset(int type
)
615 if (ospf6
->rmap
[type
].name
)
616 free(ospf6
->rmap
[type
].name
);
617 ospf6
->rmap
[type
].name
= NULL
;
618 ospf6
->rmap
[type
].map
= NULL
;
621 static void ospf6_asbr_routemap_update(const char *mapname
)
628 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
629 if (ospf6
->rmap
[type
].name
) {
630 ospf6
->rmap
[type
].map
= route_map_lookup_by_name(
631 ospf6
->rmap
[type
].name
);
633 if (mapname
&& ospf6
->rmap
[type
].map
&&
634 (strcmp(ospf6
->rmap
[type
].name
, mapname
) == 0)) {
635 if (IS_OSPF6_DEBUG_ASBR
)
636 zlog_debug("%s: route-map %s update, reset redist %s",
637 __PRETTY_FUNCTION__
, mapname
,
640 ospf6_zebra_no_redistribute(type
);
641 ospf6_zebra_redistribute(type
);
644 ospf6
->rmap
[type
].map
= NULL
;
648 int ospf6_asbr_is_asbr(struct ospf6
*o
)
650 return o
->external_table
->count
;
653 static void ospf6_asbr_redistribute_set(int type
)
655 ospf6_zebra_redistribute(type
);
658 static void ospf6_asbr_redistribute_unset(int type
)
660 struct ospf6_route
*route
;
661 struct ospf6_external_info
*info
;
663 ospf6_zebra_no_redistribute(type
);
665 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
666 route
= ospf6_route_next(route
)) {
667 info
= route
->route_option
;
668 if (info
->type
!= type
)
671 ospf6_asbr_redistribute_remove(info
->type
, 0, &route
->prefix
);
674 ospf6_asbr_routemap_unset(type
);
677 /* When an area is unstubified, flood all the external LSAs in the area */
678 void ospf6_asbr_send_externals_to_area(struct ospf6_area
*oa
)
680 struct ospf6_lsa
*lsa
;
682 for (ALL_LSDB(oa
->ospf6
->lsdb
, lsa
)) {
683 if (ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
684 zlog_debug("%s: Flooding AS-External LSA %s\n",
685 __func__
, lsa
->name
);
686 ospf6_flood_area(NULL
, lsa
, oa
);
691 void ospf6_asbr_redistribute_add(int type
, ifindex_t ifindex
,
692 struct prefix
*prefix
, u_int nexthop_num
,
693 struct in6_addr
*nexthop
, route_tag_t tag
)
696 struct ospf6_route troute
;
697 struct ospf6_external_info tinfo
;
698 struct ospf6_route
*route
, *match
;
699 struct ospf6_external_info
*info
;
700 struct prefix prefix_id
;
701 struct route_node
*node
;
702 char pbuf
[PREFIX2STR_BUFFER
], ibuf
[16];
703 struct listnode
*lnode
, *lnnode
;
704 struct ospf6_area
*oa
;
706 if (!ospf6_zebra_is_redistribute(type
))
709 memset(&troute
, 0, sizeof(troute
));
710 memset(&tinfo
, 0, sizeof(tinfo
));
712 if (IS_OSPF6_DEBUG_ASBR
) {
713 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
714 zlog_debug("Redistribute %s (%s)", pbuf
, ZROUTE_NAME(type
));
717 /* if route-map was specified but not found, do not advertise */
718 if (ospf6
->rmap
[type
].name
) {
719 if (ospf6
->rmap
[type
].map
== NULL
)
720 ospf6_asbr_routemap_update(NULL
);
721 if (ospf6
->rmap
[type
].map
== NULL
) {
723 "route-map \"%s\" not found, suppress redistributing",
724 ospf6
->rmap
[type
].name
);
729 /* apply route-map */
730 if (ospf6
->rmap
[type
].map
) {
731 troute
.route_option
= &tinfo
;
732 tinfo
.ifindex
= ifindex
;
735 ret
= route_map_apply(ospf6
->rmap
[type
].map
, prefix
, RMAP_OSPF6
,
737 if (ret
== RMAP_DENYMATCH
) {
738 if (IS_OSPF6_DEBUG_ASBR
)
739 zlog_debug("Denied by route-map \"%s\"",
740 ospf6
->rmap
[type
].name
);
745 match
= ospf6_route_lookup(prefix
, ospf6
->external_table
);
747 info
= match
->route_option
;
749 /* copy result of route-map */
750 if (ospf6
->rmap
[type
].map
) {
751 if (troute
.path
.metric_type
)
752 match
->path
.metric_type
=
753 troute
.path
.metric_type
;
754 if (troute
.path
.cost
)
755 match
->path
.cost
= troute
.path
.cost
;
756 if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo
.forwarding
))
757 memcpy(&info
->forwarding
, &tinfo
.forwarding
,
758 sizeof(struct in6_addr
));
759 info
->tag
= tinfo
.tag
;
761 /* If there is no route-map, simply update the tag */
767 if (nexthop_num
&& nexthop
)
768 ospf6_route_add_nexthop(match
, ifindex
, nexthop
);
770 ospf6_route_add_nexthop(match
, ifindex
, NULL
);
772 /* create/update binding in external_id_table */
773 prefix_id
.family
= AF_INET
;
774 prefix_id
.prefixlen
= 32;
775 prefix_id
.u
.prefix4
.s_addr
= htonl(info
->id
);
776 node
= route_node_get(ospf6
->external_id_table
, &prefix_id
);
779 if (IS_OSPF6_DEBUG_ASBR
) {
780 inet_ntop(AF_INET
, &prefix_id
.u
.prefix4
, ibuf
,
782 zlog_debug("Advertise as AS-External Id:%s", ibuf
);
785 match
->path
.origin
.id
= htonl(info
->id
);
786 ospf6_as_external_lsa_originate(match
);
790 /* create new entry */
791 route
= ospf6_route_create();
792 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
793 memcpy(&route
->prefix
, prefix
, sizeof(struct prefix
));
795 info
= (struct ospf6_external_info
*)XCALLOC(
796 MTYPE_OSPF6_EXTERNAL_INFO
, sizeof(struct ospf6_external_info
));
797 route
->route_option
= info
;
798 info
->id
= ospf6
->external_id
++;
800 /* copy result of route-map */
801 if (ospf6
->rmap
[type
].map
) {
802 if (troute
.path
.metric_type
)
803 route
->path
.metric_type
= troute
.path
.metric_type
;
804 if (troute
.path
.cost
)
805 route
->path
.cost
= troute
.path
.cost
;
806 if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo
.forwarding
))
807 memcpy(&info
->forwarding
, &tinfo
.forwarding
,
808 sizeof(struct in6_addr
));
809 info
->tag
= tinfo
.tag
;
811 /* If there is no route-map, simply set the tag */
816 if (nexthop_num
&& nexthop
)
817 ospf6_route_add_nexthop(route
, ifindex
, nexthop
);
819 ospf6_route_add_nexthop(route
, ifindex
, NULL
);
821 /* create/update binding in external_id_table */
822 prefix_id
.family
= AF_INET
;
823 prefix_id
.prefixlen
= 32;
824 prefix_id
.u
.prefix4
.s_addr
= htonl(info
->id
);
825 node
= route_node_get(ospf6
->external_id_table
, &prefix_id
);
828 route
= ospf6_route_add(route
, ospf6
->external_table
);
829 route
->route_option
= info
;
831 if (IS_OSPF6_DEBUG_ASBR
) {
832 inet_ntop(AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof(ibuf
));
833 zlog_debug("Advertise as AS-External Id:%s", ibuf
);
836 route
->path
.origin
.id
= htonl(info
->id
);
837 ospf6_as_external_lsa_originate(route
);
839 /* Router-Bit (ASBR Flag) may have to be updated */
840 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, lnode
, lnnode
, oa
))
841 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
844 void ospf6_asbr_redistribute_remove(int type
, ifindex_t ifindex
,
845 struct prefix
*prefix
)
847 struct ospf6_route
*match
;
848 struct ospf6_external_info
*info
= NULL
;
849 struct route_node
*node
;
850 struct ospf6_lsa
*lsa
;
851 struct prefix prefix_id
;
852 char pbuf
[PREFIX2STR_BUFFER
], ibuf
[16];
853 struct listnode
*lnode
, *lnnode
;
854 struct ospf6_area
*oa
;
856 match
= ospf6_route_lookup(prefix
, ospf6
->external_table
);
858 if (IS_OSPF6_DEBUG_ASBR
) {
859 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
860 zlog_debug("No such route %s to withdraw", pbuf
);
865 info
= match
->route_option
;
868 if (info
->type
!= type
) {
869 if (IS_OSPF6_DEBUG_ASBR
) {
870 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
871 zlog_debug("Original protocol mismatch: %s", pbuf
);
876 if (IS_OSPF6_DEBUG_ASBR
) {
877 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
878 inet_ntop(AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof(ibuf
));
879 zlog_debug("Withdraw %s (AS-External Id:%s)", pbuf
, ibuf
);
882 lsa
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
883 htonl(info
->id
), ospf6
->router_id
, ospf6
->lsdb
);
885 ospf6_lsa_purge(lsa
);
887 /* remove binding in external_id_table */
888 prefix_id
.family
= AF_INET
;
889 prefix_id
.prefixlen
= 32;
890 prefix_id
.u
.prefix4
.s_addr
= htonl(info
->id
);
891 node
= route_node_lookup(ospf6
->external_id_table
, &prefix_id
);
894 route_unlock_node(node
); /* to free the lookup lock */
895 route_unlock_node(node
); /* to free the original lock */
897 ospf6_route_remove(match
, ospf6
->external_table
);
898 XFREE(MTYPE_OSPF6_EXTERNAL_INFO
, info
);
900 /* Router-Bit (ASBR Flag) may have to be updated */
901 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, lnode
, lnnode
, oa
))
902 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
905 DEFUN (ospf6_redistribute
,
906 ospf6_redistribute_cmd
,
907 "redistribute " FRR_REDIST_STR_OSPF6D
,
909 FRR_REDIST_HELP_STR_OSPF6D
)
913 char *proto
= argv
[argc
- 1]->text
;
914 type
= proto_redistnum(AFI_IP6
, proto
);
916 return CMD_WARNING_CONFIG_FAILED
;
918 ospf6_asbr_redistribute_unset(type
);
919 ospf6_asbr_redistribute_set(type
);
923 DEFUN (ospf6_redistribute_routemap
,
924 ospf6_redistribute_routemap_cmd
,
925 "redistribute " FRR_REDIST_STR_OSPF6D
" route-map WORD",
927 FRR_REDIST_HELP_STR_OSPF6D
928 "Route map reference\n"
931 int idx_protocol
= 1;
935 char *proto
= argv
[idx_protocol
]->text
;
936 type
= proto_redistnum(AFI_IP6
, proto
);
938 return CMD_WARNING_CONFIG_FAILED
;
940 ospf6_asbr_redistribute_unset(type
);
941 ospf6_asbr_routemap_set(type
, argv
[idx_word
]->arg
);
942 ospf6_asbr_redistribute_set(type
);
946 DEFUN (no_ospf6_redistribute
,
947 no_ospf6_redistribute_cmd
,
948 "no redistribute " FRR_REDIST_STR_OSPF6D
" [route-map WORD]",
951 FRR_REDIST_HELP_STR_OSPF6D
952 "Route map reference\n"
955 int idx_protocol
= 2;
958 char *proto
= argv
[idx_protocol
]->text
;
959 type
= proto_redistnum(AFI_IP6
, proto
);
961 return CMD_WARNING_CONFIG_FAILED
;
963 ospf6_asbr_redistribute_unset(type
);
968 int ospf6_redistribute_config_write(struct vty
*vty
)
972 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
973 if (type
== ZEBRA_ROUTE_OSPF6
)
975 if (!ospf6_zebra_is_redistribute(type
))
978 if (ospf6
->rmap
[type
].name
)
979 vty_out(vty
, " redistribute %s route-map %s\n",
980 ZROUTE_NAME(type
), ospf6
->rmap
[type
].name
);
982 vty_out(vty
, " redistribute %s\n", ZROUTE_NAME(type
));
988 static void ospf6_redistribute_show_config(struct vty
*vty
)
991 int nroute
[ZEBRA_ROUTE_MAX
];
993 struct ospf6_route
*route
;
994 struct ospf6_external_info
*info
;
997 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
999 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
1000 route
= ospf6_route_next(route
)) {
1001 info
= route
->route_option
;
1002 nroute
[info
->type
]++;
1006 vty_out(vty
, "Redistributing External Routes from:\n");
1007 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
1008 if (type
== ZEBRA_ROUTE_OSPF6
)
1010 if (!ospf6_zebra_is_redistribute(type
))
1013 if (ospf6
->rmap
[type
].name
)
1014 vty_out(vty
, " %d: %s with route-map \"%s\"%s\n",
1015 nroute
[type
], ZROUTE_NAME(type
),
1016 ospf6
->rmap
[type
].name
,
1017 (ospf6
->rmap
[type
].map
? ""
1018 : " (not found !)"));
1020 vty_out(vty
, " %d: %s\n", nroute
[type
],
1023 vty_out(vty
, "Total %d routes\n", total
);
1027 /* Routemap Functions */
1028 static route_map_result_t
1029 ospf6_routemap_rule_match_address_prefixlist(void *rule
, struct prefix
*prefix
,
1030 route_map_object_t type
,
1033 struct prefix_list
*plist
;
1035 if (type
!= RMAP_OSPF6
)
1036 return RMAP_NOMATCH
;
1038 plist
= prefix_list_lookup(AFI_IP6
, (char *)rule
);
1040 return RMAP_NOMATCH
;
1042 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
? RMAP_NOMATCH
1047 ospf6_routemap_rule_match_address_prefixlist_compile(const char *arg
)
1049 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1052 static void ospf6_routemap_rule_match_address_prefixlist_free(void *rule
)
1054 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1057 struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd
= {
1058 "ipv6 address prefix-list",
1059 ospf6_routemap_rule_match_address_prefixlist
,
1060 ospf6_routemap_rule_match_address_prefixlist_compile
,
1061 ospf6_routemap_rule_match_address_prefixlist_free
,
1064 /* `match interface IFNAME' */
1065 /* Match function should return 1 if match is success else return
1067 static route_map_result_t
1068 ospf6_routemap_rule_match_interface(void *rule
, struct prefix
*prefix
,
1069 route_map_object_t type
, void *object
)
1071 struct interface
*ifp
;
1072 struct ospf6_external_info
*ei
;
1074 if (type
== RMAP_OSPF6
) {
1075 ei
= ((struct ospf6_route
*)object
)->route_option
;
1076 ifp
= if_lookup_by_name((char *)rule
, VRF_DEFAULT
);
1078 if (ifp
!= NULL
&& ei
->ifindex
== ifp
->ifindex
)
1082 return RMAP_NOMATCH
;
1085 /* Route map `interface' match statement. `arg' should be
1087 static void *ospf6_routemap_rule_match_interface_compile(const char *arg
)
1089 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1092 /* Free route map's compiled `interface' value. */
1093 static void ospf6_routemap_rule_match_interface_free(void *rule
)
1095 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1098 /* Route map commands for interface matching. */
1099 struct route_map_rule_cmd ospf6_routemap_rule_match_interface_cmd
= {
1100 "interface", ospf6_routemap_rule_match_interface
,
1101 ospf6_routemap_rule_match_interface_compile
,
1102 ospf6_routemap_rule_match_interface_free
};
1104 /* Match function for matching route tags */
1105 static route_map_result_t
ospf6_routemap_rule_match_tag(void *rule
,
1106 struct prefix
*prefix
,
1107 route_map_object_t type
,
1110 route_tag_t
*tag
= rule
;
1111 struct ospf6_route
*route
= object
;
1112 struct ospf6_external_info
*info
= route
->route_option
;
1114 if (type
== RMAP_OSPF6
&& info
->tag
== *tag
)
1117 return RMAP_NOMATCH
;
1120 static struct route_map_rule_cmd ospf6_routemap_rule_match_tag_cmd
= {
1121 "tag", ospf6_routemap_rule_match_tag
, route_map_rule_tag_compile
,
1122 route_map_rule_tag_free
,
1125 static route_map_result_t
1126 ospf6_routemap_rule_set_metric_type(void *rule
, struct prefix
*prefix
,
1127 route_map_object_t type
, void *object
)
1129 char *metric_type
= rule
;
1130 struct ospf6_route
*route
= object
;
1132 if (type
!= RMAP_OSPF6
)
1135 if (strcmp(metric_type
, "type-2") == 0)
1136 route
->path
.metric_type
= 2;
1138 route
->path
.metric_type
= 1;
1143 static void *ospf6_routemap_rule_set_metric_type_compile(const char *arg
)
1145 if (strcmp(arg
, "type-2") && strcmp(arg
, "type-1"))
1147 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1150 static void ospf6_routemap_rule_set_metric_type_free(void *rule
)
1152 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1155 struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd
= {
1156 "metric-type", ospf6_routemap_rule_set_metric_type
,
1157 ospf6_routemap_rule_set_metric_type_compile
,
1158 ospf6_routemap_rule_set_metric_type_free
,
1161 static route_map_result_t
1162 ospf6_routemap_rule_set_metric(void *rule
, struct prefix
*prefix
,
1163 route_map_object_t type
, void *object
)
1165 char *metric
= rule
;
1166 struct ospf6_route
*route
= object
;
1168 if (type
!= RMAP_OSPF6
)
1171 route
->path
.cost
= atoi(metric
);
1175 static void *ospf6_routemap_rule_set_metric_compile(const char *arg
)
1179 metric
= strtoul(arg
, &endp
, 0);
1180 if (metric
> OSPF_LS_INFINITY
|| *endp
!= '\0')
1182 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1185 static void ospf6_routemap_rule_set_metric_free(void *rule
)
1187 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1190 struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd
= {
1191 "metric", ospf6_routemap_rule_set_metric
,
1192 ospf6_routemap_rule_set_metric_compile
,
1193 ospf6_routemap_rule_set_metric_free
,
1196 static route_map_result_t
1197 ospf6_routemap_rule_set_forwarding(void *rule
, struct prefix
*prefix
,
1198 route_map_object_t type
, void *object
)
1200 char *forwarding
= rule
;
1201 struct ospf6_route
*route
= object
;
1202 struct ospf6_external_info
*info
= route
->route_option
;
1204 if (type
!= RMAP_OSPF6
)
1207 if (inet_pton(AF_INET6
, forwarding
, &info
->forwarding
) != 1) {
1208 memset(&info
->forwarding
, 0, sizeof(struct in6_addr
));
1215 static void *ospf6_routemap_rule_set_forwarding_compile(const char *arg
)
1218 if (inet_pton(AF_INET6
, arg
, &a
) != 1)
1220 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1223 static void ospf6_routemap_rule_set_forwarding_free(void *rule
)
1225 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1228 struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd
= {
1229 "forwarding-address", ospf6_routemap_rule_set_forwarding
,
1230 ospf6_routemap_rule_set_forwarding_compile
,
1231 ospf6_routemap_rule_set_forwarding_free
,
1234 static route_map_result_t
ospf6_routemap_rule_set_tag(void *rule
,
1235 struct prefix
*prefix
,
1236 route_map_object_t type
,
1239 route_tag_t
*tag
= rule
;
1240 struct ospf6_route
*route
= object
;
1241 struct ospf6_external_info
*info
= route
->route_option
;
1243 if (type
!= RMAP_OSPF6
)
1250 static struct route_map_rule_cmd ospf6_routemap_rule_set_tag_cmd
= {
1251 "tag", ospf6_routemap_rule_set_tag
, route_map_rule_tag_compile
,
1252 route_map_rule_tag_free
,
1255 static int route_map_command_status(struct vty
*vty
, int ret
)
1258 case RMAP_RULE_MISSING
:
1259 vty_out(vty
, "OSPF6 Can't find rule.\n");
1260 return CMD_WARNING_CONFIG_FAILED
;
1262 case RMAP_COMPILE_ERROR
:
1263 vty_out(vty
, "OSPF6 Argument is malformed.\n");
1264 return CMD_WARNING_CONFIG_FAILED
;
1266 case RMAP_COMPILE_SUCCESS
:
1273 /* add "set metric-type" */
1274 DEFUN (ospf6_routemap_set_metric_type
,
1275 ospf6_routemap_set_metric_type_cmd
,
1276 "set metric-type <type-1|type-2>",
1279 "OSPF6 external type 1 metric\n"
1280 "OSPF6 external type 2 metric\n")
1282 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1283 int idx_external
= 2;
1284 int ret
= route_map_add_set(route_map_index
, "metric-type",
1285 argv
[idx_external
]->arg
);
1286 return route_map_command_status(vty
, ret
);
1289 /* delete "set metric-type" */
1290 DEFUN (ospf6_routemap_no_set_metric_type
,
1291 ospf6_routemap_no_set_metric_type_cmd
,
1292 "no set metric-type [<type-1|type-2>]",
1296 "OSPF6 external type 1 metric\n"
1297 "OSPF6 external type 2 metric\n")
1299 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1300 char *ext
= (argc
== 4) ? argv
[3]->text
: NULL
;
1301 int ret
= route_map_delete_set(route_map_index
, "metric-type", ext
);
1302 return route_map_command_status(vty
, ret
);
1305 /* add "set forwarding-address" */
1306 DEFUN (ospf6_routemap_set_forwarding
,
1307 ospf6_routemap_set_forwarding_cmd
,
1308 "set forwarding-address X:X::X:X",
1310 "Forwarding Address\n"
1313 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1315 int ret
= route_map_add_set(route_map_index
, "forwarding-address",
1316 argv
[idx_ipv6
]->arg
);
1317 return route_map_command_status(vty
, ret
);
1320 /* delete "set forwarding-address" */
1321 DEFUN (ospf6_routemap_no_set_forwarding
,
1322 ospf6_routemap_no_set_forwarding_cmd
,
1323 "no set forwarding-address X:X::X:X",
1326 "Forwarding Address\n"
1329 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1331 int ret
= route_map_delete_set(route_map_index
, "forwarding-address",
1332 argv
[idx_ipv6
]->arg
);
1333 return route_map_command_status(vty
, ret
);
1336 static void ospf6_routemap_init(void)
1340 route_map_add_hook(ospf6_asbr_routemap_update
);
1341 route_map_delete_hook(ospf6_asbr_routemap_update
);
1343 route_map_set_metric_hook(generic_set_add
);
1344 route_map_no_set_metric_hook(generic_set_delete
);
1346 route_map_match_tag_hook(generic_match_add
);
1347 route_map_no_match_tag_hook(generic_match_delete
);
1349 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
1350 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
1352 route_map_match_interface_hook(generic_match_add
);
1353 route_map_no_match_interface_hook(generic_match_delete
);
1355 route_map_install_match(
1356 &ospf6_routemap_rule_match_address_prefixlist_cmd
);
1357 route_map_install_match(&ospf6_routemap_rule_match_interface_cmd
);
1358 route_map_install_match(&ospf6_routemap_rule_match_tag_cmd
);
1360 route_map_install_set(&ospf6_routemap_rule_set_metric_type_cmd
);
1361 route_map_install_set(&ospf6_routemap_rule_set_metric_cmd
);
1362 route_map_install_set(&ospf6_routemap_rule_set_forwarding_cmd
);
1363 route_map_install_set(&ospf6_routemap_rule_set_tag_cmd
);
1365 /* ASE Metric Type (e.g. Type-1/Type-2) */
1366 install_element(RMAP_NODE
, &ospf6_routemap_set_metric_type_cmd
);
1367 install_element(RMAP_NODE
, &ospf6_routemap_no_set_metric_type_cmd
);
1370 install_element(RMAP_NODE
, &ospf6_routemap_set_forwarding_cmd
);
1371 install_element(RMAP_NODE
, &ospf6_routemap_no_set_forwarding_cmd
);
1375 /* Display functions */
1376 static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1377 char *buf
, int buflen
,
1380 struct ospf6_as_external_lsa
*external
;
1381 struct in6_addr in6
;
1382 int prefix_length
= 0;
1385 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
1389 ospf6_prefix_in6_addr(&in6
, &external
->prefix
);
1390 prefix_length
= external
->prefix
.prefix_length
;
1392 in6
= *((struct in6_addr
1393 *)((caddr_t
)external
1395 ospf6_as_external_lsa
)
1396 + OSPF6_PREFIX_SPACE(
1401 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
1403 sprintf(&buf
[strlen(buf
)], "/%d",
1410 static int ospf6_as_external_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
1412 struct ospf6_as_external_lsa
*external
;
1415 assert(lsa
->header
);
1416 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
1420 snprintf(buf
, sizeof(buf
), "%c%c%c",
1421 (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_E
) ? 'E'
1423 (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
) ? 'F'
1425 (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
) ? 'T'
1428 vty_out(vty
, " Bits: %s\n", buf
);
1429 vty_out(vty
, " Metric: %5lu\n",
1430 (u_long
)OSPF6_ASBR_METRIC(external
));
1432 ospf6_prefix_options_printbuf(external
->prefix
.prefix_options
, buf
,
1434 vty_out(vty
, " Prefix Options: %s\n", buf
);
1436 vty_out(vty
, " Referenced LSType: %d\n",
1437 ntohs(external
->prefix
.prefix_refer_lstype
));
1439 vty_out(vty
, " Prefix: %s\n",
1440 ospf6_as_external_lsa_get_prefix_str(lsa
, buf
, sizeof(buf
), 0));
1442 /* Forwarding-Address */
1443 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
)) {
1444 vty_out(vty
, " Forwarding-Address: %s\n",
1445 ospf6_as_external_lsa_get_prefix_str(lsa
, buf
,
1450 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
)) {
1451 vty_out(vty
, " Tag: %" ROUTE_TAG_PRI
"\n",
1452 ospf6_as_external_lsa_get_tag(lsa
));
1458 static void ospf6_asbr_external_route_show(struct vty
*vty
,
1459 struct ospf6_route
*route
)
1461 struct ospf6_external_info
*info
= route
->route_option
;
1462 char prefix
[PREFIX2STR_BUFFER
], id
[16], forwarding
[64];
1465 prefix2str(&route
->prefix
, prefix
, sizeof(prefix
));
1466 tmp_id
= ntohl(info
->id
);
1467 inet_ntop(AF_INET
, &tmp_id
, id
, sizeof(id
));
1468 if (!IN6_IS_ADDR_UNSPECIFIED(&info
->forwarding
))
1469 inet_ntop(AF_INET6
, &info
->forwarding
, forwarding
,
1470 sizeof(forwarding
));
1472 snprintf(forwarding
, sizeof(forwarding
), ":: (ifindex %d)",
1473 ospf6_route_get_first_nh_index(route
));
1475 vty_out(vty
, "%c %-32s %-15s type-%d %5lu %s\n",
1476 zebra_route_char(info
->type
), prefix
, id
,
1477 route
->path
.metric_type
,
1478 (u_long
)(route
->path
.metric_type
== 2 ? route
->path
.u
.cost_e2
1479 : route
->path
.cost
),
1483 DEFUN (show_ipv6_ospf6_redistribute
,
1484 show_ipv6_ospf6_redistribute_cmd
,
1485 "show ipv6 ospf6 redistribute",
1489 "redistributing External information\n"
1492 struct ospf6_route
*route
;
1494 OSPF6_CMD_CHECK_RUNNING();
1496 ospf6_redistribute_show_config(vty
);
1498 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
1499 route
= ospf6_route_next(route
))
1500 ospf6_asbr_external_route_show(vty
, route
);
1505 struct ospf6_lsa_handler as_external_handler
= {
1506 .lh_type
= OSPF6_LSTYPE_AS_EXTERNAL
,
1507 .lh_name
= "AS-External",
1508 .lh_short_name
= "ASE",
1509 .lh_show
= ospf6_as_external_lsa_show
,
1510 .lh_get_prefix_str
= ospf6_as_external_lsa_get_prefix_str
,
1514 void ospf6_asbr_init(void)
1516 ospf6_routemap_init();
1518 ospf6_install_lsa_handler(&as_external_handler
);
1520 install_element(VIEW_NODE
, &show_ipv6_ospf6_redistribute_cmd
);
1522 install_element(OSPF6_NODE
, &ospf6_redistribute_cmd
);
1523 install_element(OSPF6_NODE
, &ospf6_redistribute_routemap_cmd
);
1524 install_element(OSPF6_NODE
, &no_ospf6_redistribute_cmd
);
1527 void ospf6_asbr_redistribute_reset(void)
1531 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
1532 if (type
== ZEBRA_ROUTE_OSPF6
)
1534 if (ospf6_zebra_is_redistribute(type
))
1535 ospf6_asbr_redistribute_unset(type
);
1539 void ospf6_asbr_terminate(void)
1544 DEFUN (debug_ospf6_asbr
,
1545 debug_ospf6_asbr_cmd
,
1549 "Debug OSPFv3 ASBR function\n"
1552 OSPF6_DEBUG_ASBR_ON();
1556 DEFUN (no_debug_ospf6_asbr
,
1557 no_debug_ospf6_asbr_cmd
,
1558 "no debug ospf6 asbr",
1562 "Debug OSPFv3 ASBR function\n"
1565 OSPF6_DEBUG_ASBR_OFF();
1569 int config_write_ospf6_debug_asbr(struct vty
*vty
)
1571 if (IS_OSPF6_DEBUG_ASBR
)
1572 vty_out(vty
, "debug ospf6 asbr\n");
1576 void install_element_ospf6_debug_asbr()
1578 install_element(ENABLE_NODE
, &debug_ospf6_asbr_cmd
);
1579 install_element(ENABLE_NODE
, &no_debug_ospf6_asbr_cmd
);
1580 install_element(CONFIG_NODE
, &debug_ospf6_asbr_cmd
);
1581 install_element(CONFIG_NODE
, &no_debug_ospf6_asbr_cmd
);