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
33 #include "lib/northbound_cli.h"
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"
41 #include "ospf6_spf.h"
43 #include "ospf6_top.h"
45 #include "ospf6_area.h"
46 #include "ospf6_interface.h"
47 #include "ospf6_neighbor.h"
48 #include "ospf6_asbr.h"
49 #include "ospf6_abr.h"
50 #include "ospf6_intra.h"
51 #include "ospf6_flood.h"
55 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_EXTERNAL_INFO
, "OSPF6 ext. info");
56 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_DIST_ARGS
, "OSPF6 Distribute arguments");
57 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_REDISTRIBUTE
, "OSPF6 Redistribute arguments");
59 static void ospf6_asbr_redistribute_set(int type
, vrf_id_t vrf_id
);
60 static void ospf6_asbr_redistribute_unset(struct ospf6
*ospf6
,
61 struct ospf6_redist
*red
, int type
);
63 #ifndef VTYSH_EXTRACT_PL
64 #include "ospf6d/ospf6_asbr_clippy.c"
67 unsigned char conf_debug_ospf6_asbr
= 0;
69 #define ZROUTE_NAME(x) zebra_route_string(x)
71 /* AS External LSA origination */
72 static void ospf6_as_external_lsa_originate(struct ospf6_route
*route
,
75 char buffer
[OSPF6_MAX_LSASIZE
];
76 struct ospf6_lsa_header
*lsa_header
;
77 struct ospf6_lsa
*lsa
;
78 struct ospf6_external_info
*info
= route
->route_option
;
80 struct ospf6_as_external_lsa
*as_external_lsa
;
83 if (IS_OSPF6_DEBUG_ASBR
|| IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL
))
84 zlog_debug("Originate AS-External-LSA for %pFX",
88 memset(buffer
, 0, sizeof(buffer
));
89 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
90 as_external_lsa
= (struct ospf6_as_external_lsa
91 *)((caddr_t
)lsa_header
92 + sizeof(struct ospf6_lsa_header
));
93 p
= (caddr_t
)((caddr_t
)as_external_lsa
94 + sizeof(struct ospf6_as_external_lsa
));
96 /* Fill AS-External-LSA */
98 if (route
->path
.metric_type
== 2)
99 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
101 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
103 /* forwarding address */
104 if (!IN6_IS_ADDR_UNSPECIFIED(&info
->forwarding
))
105 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
107 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
109 /* external route tag */
111 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
113 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
116 OSPF6_ASBR_METRIC_SET(as_external_lsa
, route
->path
.cost
);
119 as_external_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
122 as_external_lsa
->prefix
.prefix_options
= route
->path
.prefix_options
;
124 /* don't use refer LS-type */
125 as_external_lsa
->prefix
.prefix_refer_lstype
= htons(0);
128 memcpy(p
, &route
->prefix
.u
.prefix6
,
129 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
130 ospf6_prefix_apply_mask(&as_external_lsa
->prefix
);
131 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
133 /* Forwarding address */
134 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
)) {
135 memcpy(p
, &info
->forwarding
, sizeof(struct in6_addr
));
136 p
+= sizeof(struct in6_addr
);
139 /* External Route Tag */
140 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
)) {
141 route_tag_t network_order
= htonl(info
->tag
);
143 memcpy(p
, &network_order
, sizeof(network_order
));
144 p
+= sizeof(network_order
);
147 /* Fill LSA Header */
149 lsa_header
->type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
150 lsa_header
->id
= route
->path
.origin
.id
;
151 lsa_header
->adv_router
= ospf6
->router_id
;
153 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
154 lsa_header
->adv_router
, ospf6
->lsdb
);
155 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
158 ospf6_lsa_checksum(lsa_header
);
161 lsa
= ospf6_lsa_create(lsa_header
);
164 ospf6_lsa_originate_process(lsa
, ospf6
);
167 int ospf6_orig_as_external_lsa(struct thread
*thread
)
169 struct ospf6_interface
*oi
;
170 struct ospf6_lsa
*lsa
;
171 uint32_t type
, adv_router
;
173 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
174 oi
->thread_as_extern_lsa
= NULL
;
176 if (oi
->state
== OSPF6_INTERFACE_DOWN
)
179 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
180 adv_router
= oi
->area
->ospf6
->router_id
;
181 for (ALL_LSDB_TYPED_ADVRTR(oi
->area
->ospf6
->lsdb
, type
, adv_router
,
183 if (IS_OSPF6_DEBUG_ASBR
)
185 "%s: Send update of AS-External LSA %s seq 0x%x",
187 ntohl(lsa
->header
->seqnum
));
189 ospf6_flood_interface(NULL
, lsa
, oi
);
195 static route_tag_t
ospf6_as_external_lsa_get_tag(struct ospf6_lsa
*lsa
)
197 struct ospf6_as_external_lsa
*external
;
198 ptrdiff_t tag_offset
;
199 route_tag_t network_order
;
204 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
207 if (!CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
))
210 tag_offset
= sizeof(*external
)
211 + OSPF6_PREFIX_SPACE(external
->prefix
.prefix_length
);
212 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
))
213 tag_offset
+= sizeof(struct in6_addr
);
215 memcpy(&network_order
, (caddr_t
)external
+ tag_offset
,
216 sizeof(network_order
));
217 return ntohl(network_order
);
220 void ospf6_asbr_update_route_ecmp_path(struct ospf6_route
*old
,
221 struct ospf6_route
*route
,
224 struct ospf6_route
*old_route
, *next_route
;
225 struct ospf6_path
*ecmp_path
, *o_path
= NULL
;
226 struct listnode
*anode
, *anext
;
227 struct listnode
*nnode
, *rnode
, *rnext
;
228 struct ospf6_nexthop
*nh
, *rnh
;
229 bool route_found
= false;
231 /* check for old entry match with new route origin,
234 for (old_route
= old
; old_route
; old_route
= next_route
) {
235 bool route_updated
= false;
237 next_route
= old_route
->next
;
239 if (!ospf6_route_is_same(old_route
, route
)
240 || (old_route
->path
.type
!= route
->path
.type
))
243 /* Current and New route has same origin,
246 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
, anext
,
248 /* Check old route path and route has same
251 if (o_path
->area_id
!= route
->path
.area_id
252 || (memcmp(&(o_path
)->origin
, &(route
)->path
.origin
,
253 sizeof(struct ospf6_ls_origin
))
257 /* Cost is not same then delete current path */
258 if ((o_path
->cost
== route
->path
.cost
)
259 && (o_path
->u
.cost_e2
== route
->path
.u
.cost_e2
))
262 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
264 "%s: route %pFX cost old %u new %u is not same, replace route",
265 __func__
, &old_route
->prefix
, o_path
->cost
,
269 /* Remove selected current rout path's nh from
272 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
273 for (ALL_LIST_ELEMENTS(old_route
->nh_list
,
274 rnode
, rnext
, rnh
)) {
275 if (!ospf6_nexthop_is_same(rnh
, nh
))
277 listnode_delete(old_route
->nh_list
,
279 ospf6_nexthop_delete(rnh
);
283 listnode_delete(old_route
->paths
, o_path
);
284 ospf6_path_free(o_path
);
285 route_updated
= true;
287 /* Current route's path (adv_router info) is similar
288 * to route being added.
289 * Replace current route's path with paths list head.
290 * Update FIB with effective NHs.
292 if (listcount(old_route
->paths
)) {
293 for (ALL_LIST_ELEMENTS(old_route
->paths
,
294 anode
, anext
, o_path
)) {
295 ospf6_merge_nexthops(
299 /* Update RIB/FIB with effective
302 if (ospf6
->route_table
->hook_add
)
303 (*ospf6
->route_table
->hook_add
)(
306 if (old_route
->path
.origin
.id
307 == route
->path
.origin
.id
308 && old_route
->path
.origin
.adv_router
309 == route
->path
.origin
311 struct ospf6_path
*h_path
;
313 h_path
= (struct ospf6_path
*)
314 listgetdata(listhead(
316 old_route
->path
.origin
.type
=
318 old_route
->path
.origin
.id
=
320 old_route
->path
.origin
.adv_router
=
321 h_path
->origin
.adv_router
;
324 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
326 "%s: route %pFX old cost %u new cost %u, delete old entry.",
327 __func__
, &old_route
->prefix
,
328 old_route
->path
.cost
,
331 if (old
== old_route
)
333 ospf6_route_remove(old_route
,
342 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
344 /* Current and New Route prefix or route type
345 * is not same skip this current node.
347 if (!ospf6_route_is_same(old_route
, route
)
348 || (old_route
->path
.type
!= route
->path
.type
))
351 /* Old Route and New Route have Equal Cost, Merge NHs */
352 if ((old_route
->path
.cost
== route
->path
.cost
)
353 && (old_route
->path
.u
.cost_e2
== route
->path
.u
.cost_e2
)) {
355 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
357 "%s: old route %pFX path cost %u e2 %u",
358 __func__
, &old_route
->prefix
,
359 old_route
->path
.cost
,
360 old_route
->path
.u
.cost_e2
);
363 /* check if this path exists already in
364 * route->paths list, if so, replace nh_list
367 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
369 if (o_path
->area_id
== route
->path
.area_id
370 && (memcmp(&(o_path
)->origin
,
371 &(route
)->path
.origin
,
372 sizeof(struct ospf6_ls_origin
))
376 /* If path is not found in old_route paths's list,
377 * add a new path to route paths list and merge
378 * nexthops in route->path->nh_list.
379 * Otherwise replace existing path's nh_list.
381 if (o_path
== NULL
) {
382 ecmp_path
= ospf6_path_dup(&route
->path
);
384 /* Add a nh_list to new ecmp path */
385 ospf6_copy_nexthops(ecmp_path
->nh_list
,
388 /* Add the new path to route's path list */
389 listnode_add_sort(old_route
->paths
, ecmp_path
);
391 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
393 "%s: route %pFX another path added with nh %u, effective paths %u nh %u",
394 __func__
, &route
->prefix
,
395 listcount(ecmp_path
->nh_list
),
396 old_route
->paths
? listcount(
399 listcount(old_route
->nh_list
));
402 list_delete_all_node(o_path
->nh_list
);
403 ospf6_copy_nexthops(o_path
->nh_list
,
407 /* Reset nexthop lists, rebuild from brouter table
408 * for each adv. router.
410 list_delete_all_node(old_route
->nh_list
);
412 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
414 struct ospf6_route
*asbr_entry
;
416 asbr_entry
= ospf6_route_lookup(
418 ospf6
->brouter_table
);
419 if (asbr_entry
== NULL
) {
420 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
422 "%s: ls_prfix %pFX asbr_entry not found.",
427 ospf6_route_merge_nexthops(old_route
,
431 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
433 "%s: route %pFX with effective paths %u nh %u",
434 __func__
, &route
->prefix
,
436 ? listcount(old_route
->paths
)
439 ? listcount(old_route
->nh_list
)
443 if (ospf6
->route_table
->hook_add
)
444 (*ospf6
->route_table
->hook_add
)(old_route
);
446 /* Delete the new route its info added to existing
449 ospf6_route_delete(route
);
456 /* Add new route to existing node in ospf6 route table. */
457 ospf6_route_add(route
, ospf6
->route_table
);
461 void ospf6_asbr_lsa_add(struct ospf6_lsa
*lsa
)
463 struct ospf6_as_external_lsa
*external
;
464 struct prefix asbr_id
;
465 struct ospf6_route
*asbr_entry
, *route
, *old
;
466 struct ospf6_path
*path
;
469 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
472 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
473 zlog_debug("Calculate AS-External route for %s", lsa
->name
);
475 ospf6
= ospf6_get_by_lsdb(lsa
);
477 if (lsa
->header
->adv_router
== ospf6
->router_id
) {
478 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
479 zlog_debug("Ignore self-originated AS-External-LSA");
483 if (OSPF6_ASBR_METRIC(external
) == OSPF_LS_INFINITY
) {
484 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
485 zlog_debug("Ignore LSA with LSInfinity Metric");
489 if (CHECK_FLAG(external
->prefix
.prefix_options
,
490 OSPF6_PREFIX_OPTION_NU
)) {
491 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
492 zlog_debug("Ignore LSA with NU bit set Metric");
496 ospf6_linkstate_prefix(lsa
->header
->adv_router
, htonl(0), &asbr_id
);
497 asbr_entry
= ospf6_route_lookup(&asbr_id
, ospf6
->brouter_table
);
498 if (asbr_entry
== NULL
499 || !CHECK_FLAG(asbr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)) {
500 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
501 zlog_debug("ASBR entry not found: %pFX", &asbr_id
);
505 route
= ospf6_route_create();
506 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
507 route
->prefix
.family
= AF_INET6
;
508 route
->prefix
.prefixlen
= external
->prefix
.prefix_length
;
509 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
, external
,
512 route
->path
.area_id
= asbr_entry
->path
.area_id
;
513 route
->path
.origin
.type
= lsa
->header
->type
;
514 route
->path
.origin
.id
= lsa
->header
->id
;
515 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
516 route
->path
.prefix_options
= external
->prefix
.prefix_options
;
517 memcpy(&route
->path
.ls_prefix
, &asbr_id
, sizeof(struct prefix
));
519 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_E
)) {
520 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL2
;
521 route
->path
.metric_type
= 2;
522 route
->path
.cost
= asbr_entry
->path
.cost
;
523 route
->path
.u
.cost_e2
= OSPF6_ASBR_METRIC(external
);
525 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL1
;
526 route
->path
.metric_type
= 1;
528 asbr_entry
->path
.cost
+ OSPF6_ASBR_METRIC(external
);
529 route
->path
.u
.cost_e2
= 0;
532 route
->path
.tag
= ospf6_as_external_lsa_get_tag(lsa
);
534 ospf6_route_copy_nexthops(route
, asbr_entry
);
536 path
= ospf6_path_dup(&route
->path
);
537 ospf6_copy_nexthops(path
->nh_list
, asbr_entry
->nh_list
);
538 listnode_add_sort(route
->paths
, path
);
541 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
543 "%s: AS-External %u route add %pFX cost %u(%u) nh %u",
545 (route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL1
) ? 1 : 2,
546 &route
->prefix
, route
->path
.cost
, route
->path
.u
.cost_e2
,
547 listcount(route
->nh_list
));
549 old
= ospf6_route_lookup(&route
->prefix
, ospf6
->route_table
);
551 /* Add the new route to ospf6 instance route table. */
552 ospf6_route_add(route
, ospf6
->route_table
);
555 * ECMP: Keep new equal preference path in current
556 * route's path list, update zebra with new effective
557 * list along with addition of ECMP path.
559 ospf6_asbr_update_route_ecmp_path(old
, route
, ospf6
);
563 void ospf6_asbr_lsa_remove(struct ospf6_lsa
*lsa
,
564 struct ospf6_route
*asbr_entry
)
566 struct ospf6_as_external_lsa
*external
;
567 struct prefix prefix
;
568 struct ospf6_route
*route
, *nroute
, *route_to_del
;
569 struct ospf6_area
*oa
= NULL
;
572 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
575 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
576 zlog_debug("Withdraw AS-External route for %s", lsa
->name
);
578 ospf6
= ospf6_get_by_lsdb(lsa
);
579 if (ospf6_is_router_abr(ospf6
))
580 oa
= ospf6
->backbone
;
582 oa
= listnode_head(ospf6
->area_list
);
587 if (lsa
->header
->adv_router
== oa
->ospf6
->router_id
) {
588 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
589 zlog_debug("Ignore self-originated AS-External-LSA");
593 route_to_del
= ospf6_route_create();
594 route_to_del
->type
= OSPF6_DEST_TYPE_NETWORK
;
595 route_to_del
->prefix
.family
= AF_INET6
;
596 route_to_del
->prefix
.prefixlen
= external
->prefix
.prefix_length
;
597 ospf6_prefix_in6_addr(&route_to_del
->prefix
.u
.prefix6
, external
,
600 route_to_del
->path
.origin
.type
= lsa
->header
->type
;
601 route_to_del
->path
.origin
.id
= lsa
->header
->id
;
602 route_to_del
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
605 route_to_del
->path
.area_id
= asbr_entry
->path
.area_id
;
606 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_E
)) {
607 route_to_del
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL2
;
608 route_to_del
->path
.metric_type
= 2;
609 route_to_del
->path
.cost
= asbr_entry
->path
.cost
;
610 route_to_del
->path
.u
.cost_e2
=
611 OSPF6_ASBR_METRIC(external
);
613 route_to_del
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL1
;
614 route_to_del
->path
.metric_type
= 1;
615 route_to_del
->path
.cost
= asbr_entry
->path
.cost
616 + OSPF6_ASBR_METRIC(external
);
617 route_to_del
->path
.u
.cost_e2
= 0;
621 memset(&prefix
, 0, sizeof(struct prefix
));
622 prefix
.family
= AF_INET6
;
623 prefix
.prefixlen
= external
->prefix
.prefix_length
;
624 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, external
, &external
->prefix
);
626 route
= ospf6_route_lookup(&prefix
, oa
->ospf6
->route_table
);
628 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
629 zlog_debug("AS-External route %pFX not found", &prefix
);
632 ospf6_route_delete(route_to_del
);
636 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
638 "%s: Current route %pFX cost %u e2 %u, route to del cost %u e2 %u",
639 __func__
, &prefix
, route
->path
.cost
, route
->path
.u
.cost_e2
,
640 route_to_del
->path
.cost
, route_to_del
->path
.u
.cost_e2
);
643 for (ospf6_route_lock(route
);
644 route
&& ospf6_route_is_prefix(&prefix
, route
); route
= nroute
) {
645 nroute
= ospf6_route_next(route
);
647 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
650 /* Route has multiple ECMP paths, remove matching
651 * path. Update current route's effective nh list
652 * after removal of one of the path.
654 if (listcount(route
->paths
) > 1) {
655 struct listnode
*anode
, *anext
;
656 struct listnode
*nnode
, *rnode
, *rnext
;
657 struct ospf6_nexthop
*nh
, *rnh
;
658 struct ospf6_path
*o_path
;
659 bool nh_updated
= false;
661 /* Iterate all paths of route to find maching with LSA
662 * remove from route path list. If route->path is same,
663 * replace from paths list.
665 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
,
667 if ((o_path
->origin
.type
!= lsa
->header
->type
)
668 || (o_path
->origin
.adv_router
669 != lsa
->header
->adv_router
)
670 || (o_path
->origin
.id
!= lsa
->header
->id
))
673 /* Compare LSA cost with current
677 && (o_path
->cost
!= route_to_del
->path
.cost
679 != route_to_del
->path
.u
681 if (IS_OSPF6_DEBUG_EXAMIN(
684 "%s: route %pFX to delete is not same, cost %u del cost %u. skip",
693 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
695 "%s: route %pFX path found with cost %u nh %u to remove.",
696 __func__
, &prefix
, route
->path
.cost
,
697 listcount(o_path
->nh_list
));
700 /* Remove found path's nh_list from
701 * the route's nh_list.
703 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
,
705 for (ALL_LIST_ELEMENTS(route
->nh_list
,
708 if (!ospf6_nexthop_is_same(rnh
,
711 listnode_delete(route
->nh_list
,
713 ospf6_nexthop_delete(rnh
);
716 /* Delete the path from route's path list */
717 listnode_delete(route
->paths
, o_path
);
718 ospf6_path_free(o_path
);
723 /* Iterate all paths and merge nexthop,
724 * unlesss any of the nexthop similar to
725 * ones deleted as part of path deletion.
728 for (ALL_LIST_ELEMENTS(route
->paths
, anode
,
730 ospf6_merge_nexthops(route
->nh_list
,
734 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
736 "%s: AS-External %u route %pFX update paths %u nh %u",
739 == OSPF6_PATH_TYPE_EXTERNAL1
)
742 &route
->prefix
, listcount(route
->paths
),
743 route
->nh_list
? listcount(
748 if (listcount(route
->paths
)) {
749 /* Update RIB/FIB with effective
752 if (oa
->ospf6
->route_table
->hook_add
)
753 (*oa
->ospf6
->route_table
756 /* route's primary path is similar
757 * to LSA, replace route's primary
758 * path with route's paths list head.
760 if ((route
->path
.origin
.id
==
762 (route
->path
.origin
.adv_router
763 == lsa
->header
->adv_router
)) {
764 struct ospf6_path
*h_path
;
766 h_path
= (struct ospf6_path
*)
768 listhead(route
->paths
));
769 route
->path
.origin
.type
=
771 route
->path
.origin
.id
=
773 route
->path
.origin
.adv_router
=
774 h_path
->origin
.adv_router
;
778 route
, oa
->ospf6
->route_table
);
784 /* Compare LSA origin and cost with current route info.
785 * if any check fails skip del this route node.
788 && (!ospf6_route_is_same_origin(route
, route_to_del
)
789 || (route
->path
.type
!= route_to_del
->path
.type
)
790 || (route
->path
.cost
!= route_to_del
->path
.cost
)
791 || (route
->path
.u
.cost_e2
792 != route_to_del
->path
.u
.cost_e2
))) {
793 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
795 "%s: route %pFX to delete is not same, cost %u del cost %u. skip",
796 __func__
, &prefix
, route
->path
.cost
,
797 route_to_del
->path
.cost
);
802 if ((route
->path
.origin
.type
!= lsa
->header
->type
)
803 || (route
->path
.origin
.adv_router
804 != lsa
->header
->adv_router
)
805 || (route
->path
.origin
.id
!= lsa
->header
->id
))
808 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
810 "%s: AS-External %u route remove %pFX cost %u(%u) nh %u",
812 route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL1
815 &route
->prefix
, route
->path
.cost
, route
->path
.u
.cost_e2
,
816 listcount(route
->nh_list
));
818 ospf6_route_remove(route
, oa
->ospf6
->route_table
);
821 ospf6_route_unlock(route
);
823 ospf6_route_delete(route_to_del
);
826 void ospf6_asbr_lsentry_add(struct ospf6_route
*asbr_entry
, struct ospf6
*ospf6
)
828 struct ospf6_lsa
*lsa
;
832 if (!CHECK_FLAG(asbr_entry
->flag
, OSPF6_ROUTE_BEST
)) {
834 inet_ntop(AF_INET
, &ADV_ROUTER_IN_PREFIX(&asbr_entry
->prefix
),
836 zlog_info("ignore non-best path: lsentry %s add", buf
);
840 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
841 router
= ospf6_linkstate_prefix_adv_router(&asbr_entry
->prefix
);
842 for (ALL_LSDB_TYPED_ADVRTR(ospf6
->lsdb
, type
, router
, lsa
)) {
843 if (!OSPF6_LSA_IS_MAXAGE(lsa
))
844 ospf6_asbr_lsa_add(lsa
);
848 void ospf6_asbr_lsentry_remove(struct ospf6_route
*asbr_entry
,
851 struct ospf6_lsa
*lsa
;
855 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
856 router
= ospf6_linkstate_prefix_adv_router(&asbr_entry
->prefix
);
857 for (ALL_LSDB_TYPED_ADVRTR(ospf6
->lsdb
, type
, router
, lsa
))
858 ospf6_asbr_lsa_remove(lsa
, asbr_entry
);
862 /* redistribute function */
863 static void ospf6_asbr_routemap_set(struct ospf6_redist
*red
,
866 if (ROUTEMAP_NAME(red
)) {
867 route_map_counter_decrement(ROUTEMAP(red
));
868 free(ROUTEMAP_NAME(red
));
871 ROUTEMAP_NAME(red
) = strdup(mapname
);
872 ROUTEMAP(red
) = route_map_lookup_by_name(mapname
);
873 route_map_counter_increment(ROUTEMAP(red
));
876 static void ospf6_asbr_routemap_unset(struct ospf6_redist
*red
)
878 if (ROUTEMAP_NAME(red
))
879 free(ROUTEMAP_NAME(red
));
881 route_map_counter_decrement(ROUTEMAP(red
));
883 ROUTEMAP_NAME(red
) = NULL
;
884 ROUTEMAP(red
) = NULL
;
887 static int ospf6_asbr_routemap_update_timer(struct thread
*thread
)
892 struct ospf6_redist
*red
;
894 arg
= THREAD_ARG(thread
);
895 ospf6
= (struct ospf6
*)arg
[0];
896 arg_type
= (int)(intptr_t)arg
[1];
898 ospf6
->t_distribute_update
= NULL
;
900 red
= ospf6_redist_lookup(ospf6
, arg_type
, 0);
902 if (red
&& ROUTEMAP_NAME(red
))
903 ROUTEMAP(red
) = route_map_lookup_by_name(ROUTEMAP_NAME(red
));
904 if (red
&& ROUTEMAP(red
)) {
905 if (IS_OSPF6_DEBUG_ASBR
)
906 zlog_debug("%s: route-map %s update, reset redist %s",
907 __func__
, ROUTEMAP_NAME(red
),
908 ZROUTE_NAME(arg_type
));
910 ospf6_zebra_no_redistribute(arg_type
, ospf6
->vrf_id
);
911 ospf6_zebra_redistribute(arg_type
, ospf6
->vrf_id
);
914 XFREE(MTYPE_OSPF6_DIST_ARGS
, arg
);
918 void ospf6_asbr_distribute_list_update(int type
, struct ospf6
*ospf6
)
922 if (ospf6
->t_distribute_update
)
925 args
= XCALLOC(MTYPE_OSPF6_DIST_ARGS
, sizeof(void *) * 2);
928 args
[1] = (void *)((ptrdiff_t)type
);
930 if (IS_OSPF6_DEBUG_ASBR
)
931 zlog_debug("%s: trigger redistribute %s reset thread", __func__
,
934 ospf6
->t_distribute_update
= NULL
;
935 thread_add_timer_msec(master
, ospf6_asbr_routemap_update_timer
, args
,
936 OSPF_MIN_LS_INTERVAL
,
937 &ospf6
->t_distribute_update
);
940 static void ospf6_asbr_routemap_update(const char *mapname
)
943 struct listnode
*node
, *nnode
;
944 struct ospf6
*ospf6
= NULL
;
945 struct ospf6_redist
*red
;
950 for (ALL_LIST_ELEMENTS(om6
->ospf6
, node
, nnode
, ospf6
)) {
951 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
952 red
= ospf6_redist_lookup(ospf6
, type
, 0);
953 if (!red
|| (ROUTEMAP_NAME(red
) == NULL
))
956 route_map_lookup_by_name(ROUTEMAP_NAME(red
));
959 || strcmp(ROUTEMAP_NAME(red
), mapname
))
962 if (IS_OSPF6_DEBUG_ASBR
)
964 "%s: route-map %s update, reset redist %s",
970 route_map_counter_increment(ROUTEMAP(red
));
972 ospf6_asbr_distribute_list_update(type
, ospf6
);
975 * if the mapname matches a
976 * route-map on ospf6 but the
977 * map doesn't exist, it is
978 * being deleted. flush and then
981 if (IS_OSPF6_DEBUG_ASBR
)
983 "%s: route-map %s deleted, reset redist %s",
988 ospf6_asbr_redistribute_unset(ospf6
, red
, type
);
989 ospf6_asbr_routemap_set(red
, mapname
);
990 ospf6_asbr_redistribute_set(
991 type
, ospf6
->vrf_id
);
997 static void ospf6_asbr_routemap_event(const char *name
)
1000 struct listnode
*node
, *nnode
;
1001 struct ospf6
*ospf6
;
1002 struct ospf6_redist
*red
;
1006 for (ALL_LIST_ELEMENTS(om6
->ospf6
, node
, nnode
, ospf6
)) {
1007 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
1008 red
= ospf6_redist_lookup(ospf6
, type
, 0);
1009 if (red
&& ROUTEMAP_NAME(red
)
1010 && (strcmp(ROUTEMAP_NAME(red
), name
) == 0))
1011 ospf6_asbr_distribute_list_update(type
, ospf6
);
1016 int ospf6_asbr_is_asbr(struct ospf6
*o
)
1018 return o
->external_table
->count
;
1021 struct ospf6_redist
*ospf6_redist_lookup(struct ospf6
*ospf6
, int type
,
1022 unsigned short instance
)
1024 struct list
*red_list
;
1025 struct listnode
*node
;
1026 struct ospf6_redist
*red
;
1028 red_list
= ospf6
->redist
[type
];
1032 for (ALL_LIST_ELEMENTS_RO(red_list
, node
, red
))
1033 if (red
->instance
== instance
)
1039 static struct ospf6_redist
*ospf6_redist_add(struct ospf6
*ospf6
, int type
,
1042 struct ospf6_redist
*red
;
1044 red
= ospf6_redist_lookup(ospf6
, type
, instance
);
1048 if (!ospf6
->redist
[type
])
1049 ospf6
->redist
[type
] = list_new();
1051 red
= XCALLOC(MTYPE_OSPF6_REDISTRIBUTE
, sizeof(struct ospf6_redist
));
1052 red
->instance
= instance
;
1053 ROUTEMAP_NAME(red
) = NULL
;
1054 ROUTEMAP(red
) = NULL
;
1056 listnode_add(ospf6
->redist
[type
], red
);
1057 ospf6
->redistribute
++;
1062 static void ospf6_redist_del(struct ospf6
*ospf6
, struct ospf6_redist
*red
,
1066 listnode_delete(ospf6
->redist
[type
], red
);
1067 if (!ospf6
->redist
[type
]->count
) {
1068 list_delete(&ospf6
->redist
[type
]);
1070 XFREE(MTYPE_OSPF6_REDISTRIBUTE
, red
);
1071 ospf6
->redistribute
--;
1075 static void ospf6_asbr_redistribute_set(int type
, vrf_id_t vrf_id
)
1077 ospf6_zebra_redistribute(type
, vrf_id
);
1080 static void ospf6_asbr_redistribute_unset(struct ospf6
*ospf6
,
1081 struct ospf6_redist
*red
, int type
)
1083 struct ospf6_route
*route
;
1084 struct ospf6_external_info
*info
;
1086 ospf6_zebra_no_redistribute(type
, ospf6
->vrf_id
);
1088 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
1089 route
= ospf6_route_next(route
)) {
1090 info
= route
->route_option
;
1091 if (info
->type
!= type
)
1094 ospf6_asbr_redistribute_remove(info
->type
, 0, &route
->prefix
,
1098 ospf6_asbr_routemap_unset(red
);
1101 /* When an area is unstubified, flood all the external LSAs in the area */
1102 void ospf6_asbr_send_externals_to_area(struct ospf6_area
*oa
)
1104 struct ospf6_lsa
*lsa
, *lsanext
;
1106 for (ALL_LSDB(oa
->ospf6
->lsdb
, lsa
, lsanext
)) {
1107 if (ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
1108 if (IS_OSPF6_DEBUG_ASBR
)
1109 zlog_debug("%s: Flooding AS-External LSA %s",
1110 __func__
, lsa
->name
);
1112 ospf6_flood_area(NULL
, lsa
, oa
);
1117 /* When an area is stubified, remove all the external LSAs in the area */
1118 void ospf6_asbr_remove_externals_from_area(struct ospf6_area
*oa
)
1120 struct ospf6_lsa
*lsa
, *lsanext
;
1121 struct listnode
*node
, *nnode
;
1122 struct ospf6_area
*area
;
1123 struct ospf6
*ospf6
= oa
->ospf6
;
1124 const struct route_node
*iterend
;
1126 /* skip if router is in other non-stub areas */
1127 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, area
))
1128 if (!IS_AREA_STUB(area
))
1131 /* if router is only in a stub area then purge AS-External LSAs */
1132 iterend
= ospf6_lsdb_head(ospf6
->lsdb
, 0, 0, 0, &lsa
);
1133 while (lsa
!= NULL
) {
1134 assert(lsa
->lock
> 1);
1135 lsanext
= ospf6_lsdb_next(iterend
, lsa
);
1136 if (ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
)
1137 ospf6_lsdb_remove(lsa
, ospf6
->lsdb
);
1142 /* Update ASBR status. */
1143 static void ospf6_asbr_status_update(struct ospf6
*ospf6
, uint8_t status
)
1145 struct listnode
*lnode
, *lnnode
;
1146 struct ospf6_area
*oa
;
1148 zlog_info("ASBR[%s:Status:%d]: Update", ospf6
->name
, status
);
1151 if (IS_OSPF6_ASBR(ospf6
)) {
1152 zlog_info("ASBR[%s:Status:%d]: Already ASBR",
1153 ospf6
->name
, status
);
1156 SET_FLAG(ospf6
->flag
, OSPF6_FLAG_ASBR
);
1158 if (!IS_OSPF6_ASBR(ospf6
)) {
1159 zlog_info("ASBR[%s:Status:%d]: Already non ASBR",
1160 ospf6
->name
, status
);
1163 UNSET_FLAG(ospf6
->flag
, OSPF6_FLAG_ASBR
);
1166 ospf6_spf_schedule(ospf6
, OSPF6_SPF_FLAGS_ASBR_STATUS_CHANGE
);
1167 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, lnode
, lnnode
, oa
))
1168 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
1171 void ospf6_asbr_redistribute_add(int type
, ifindex_t ifindex
,
1172 struct prefix
*prefix
,
1173 unsigned int nexthop_num
,
1174 struct in6_addr
*nexthop
, route_tag_t tag
,
1175 struct ospf6
*ospf6
)
1177 route_map_result_t ret
;
1178 struct ospf6_route troute
;
1179 struct ospf6_external_info tinfo
;
1180 struct ospf6_route
*route
, *match
;
1181 struct ospf6_external_info
*info
;
1182 struct prefix prefix_id
;
1183 struct route_node
*node
;
1185 struct ospf6_redist
*red
;
1187 red
= ospf6_redist_lookup(ospf6
, type
, 0);
1192 if ((type
!= DEFAULT_ROUTE
)
1193 && !ospf6_zebra_is_redistribute(type
, ospf6
->vrf_id
))
1196 memset(&troute
, 0, sizeof(troute
));
1197 memset(&tinfo
, 0, sizeof(tinfo
));
1199 if (IS_OSPF6_DEBUG_ASBR
)
1200 zlog_debug("Redistribute %pFX (%s)", prefix
, ZROUTE_NAME(type
));
1202 /* if route-map was specified but not found, do not advertise */
1203 if (ROUTEMAP_NAME(red
)) {
1204 if (ROUTEMAP(red
) == NULL
)
1205 ospf6_asbr_routemap_update(NULL
);
1206 if (ROUTEMAP(red
) == NULL
) {
1208 "route-map \"%s\" not found, suppress redistributing",
1209 ROUTEMAP_NAME(red
));
1214 /* apply route-map */
1215 if (ROUTEMAP(red
)) {
1216 troute
.route_option
= &tinfo
;
1217 tinfo
.ifindex
= ifindex
;
1220 ret
= route_map_apply(ROUTEMAP(red
), prefix
, &troute
);
1221 if (ret
== RMAP_DENYMATCH
) {
1222 if (IS_OSPF6_DEBUG_ASBR
)
1223 zlog_debug("Denied by route-map \"%s\"",
1224 ROUTEMAP_NAME(red
));
1225 ospf6_asbr_redistribute_remove(type
, ifindex
, prefix
,
1231 match
= ospf6_route_lookup(prefix
, ospf6
->external_table
);
1233 info
= match
->route_option
;
1234 /* copy result of route-map */
1235 if (ROUTEMAP(red
)) {
1236 if (troute
.path
.metric_type
)
1237 match
->path
.metric_type
=
1238 troute
.path
.metric_type
;
1239 if (troute
.path
.cost
)
1240 match
->path
.cost
= troute
.path
.cost
;
1241 if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo
.forwarding
))
1242 memcpy(&info
->forwarding
, &tinfo
.forwarding
,
1243 sizeof(struct in6_addr
));
1244 info
->tag
= tinfo
.tag
;
1246 /* If there is no route-map, simply update the tag and
1249 match
->path
.metric_type
= metric_type(ospf6
, type
, 0);
1250 match
->path
.cost
= metric_value(ospf6
, type
, 0);
1256 if (nexthop_num
&& nexthop
)
1257 ospf6_route_add_nexthop(match
, ifindex
, nexthop
);
1259 ospf6_route_add_nexthop(match
, ifindex
, NULL
);
1261 /* create/update binding in external_id_table */
1262 prefix_id
.family
= AF_INET
;
1263 prefix_id
.prefixlen
= 32;
1264 prefix_id
.u
.prefix4
.s_addr
= htonl(info
->id
);
1265 node
= route_node_get(ospf6
->external_id_table
, &prefix_id
);
1268 if (IS_OSPF6_DEBUG_ASBR
) {
1269 inet_ntop(AF_INET
, &prefix_id
.u
.prefix4
, ibuf
,
1272 "Advertise as AS-External Id:%s prefix %pFX metric %u",
1273 ibuf
, prefix
, match
->path
.metric_type
);
1276 match
->path
.origin
.id
= htonl(info
->id
);
1277 ospf6_as_external_lsa_originate(match
, ospf6
);
1278 ospf6_asbr_status_update(ospf6
, ospf6
->redistribute
);
1282 /* create new entry */
1283 route
= ospf6_route_create();
1284 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1285 prefix_copy(&route
->prefix
, prefix
);
1287 info
= (struct ospf6_external_info
*)XCALLOC(
1288 MTYPE_OSPF6_EXTERNAL_INFO
, sizeof(struct ospf6_external_info
));
1289 route
->route_option
= info
;
1290 info
->id
= ospf6
->external_id
++;
1292 /* copy result of route-map */
1293 if (ROUTEMAP(red
)) {
1294 if (troute
.path
.metric_type
)
1295 route
->path
.metric_type
= troute
.path
.metric_type
;
1296 if (troute
.path
.cost
)
1297 route
->path
.cost
= troute
.path
.cost
;
1298 if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo
.forwarding
))
1299 memcpy(&info
->forwarding
, &tinfo
.forwarding
,
1300 sizeof(struct in6_addr
));
1301 info
->tag
= tinfo
.tag
;
1303 /* If there is no route-map, simply update the tag and metric
1306 route
->path
.metric_type
= metric_type(ospf6
, type
, 0);
1307 route
->path
.cost
= metric_value(ospf6
, type
, 0);
1312 if (nexthop_num
&& nexthop
)
1313 ospf6_route_add_nexthop(route
, ifindex
, nexthop
);
1315 ospf6_route_add_nexthop(route
, ifindex
, NULL
);
1317 /* create/update binding in external_id_table */
1318 prefix_id
.family
= AF_INET
;
1319 prefix_id
.prefixlen
= 32;
1320 prefix_id
.u
.prefix4
.s_addr
= htonl(info
->id
);
1321 node
= route_node_get(ospf6
->external_id_table
, &prefix_id
);
1324 route
= ospf6_route_add(route
, ospf6
->external_table
);
1325 route
->route_option
= info
;
1327 if (IS_OSPF6_DEBUG_ASBR
) {
1328 inet_ntop(AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof(ibuf
));
1330 "Advertise as AS-External Id:%s prefix %pFX metric %u",
1331 ibuf
, prefix
, route
->path
.metric_type
);
1334 route
->path
.origin
.id
= htonl(info
->id
);
1335 ospf6_as_external_lsa_originate(route
, ospf6
);
1336 ospf6_asbr_status_update(ospf6
, ospf6
->redistribute
);
1339 void ospf6_asbr_redistribute_remove(int type
, ifindex_t ifindex
,
1340 struct prefix
*prefix
, struct ospf6
*ospf6
)
1342 struct ospf6_route
*match
;
1343 struct ospf6_external_info
*info
= NULL
;
1344 struct route_node
*node
;
1345 struct ospf6_lsa
*lsa
;
1346 struct prefix prefix_id
;
1349 match
= ospf6_route_lookup(prefix
, ospf6
->external_table
);
1350 if (match
== NULL
) {
1351 if (IS_OSPF6_DEBUG_ASBR
)
1352 zlog_debug("No such route %pFX to withdraw", prefix
);
1356 info
= match
->route_option
;
1359 if (info
->type
!= type
) {
1360 if (IS_OSPF6_DEBUG_ASBR
)
1361 zlog_debug("Original protocol mismatch: %pFX", prefix
);
1365 if (IS_OSPF6_DEBUG_ASBR
) {
1366 inet_ntop(AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof(ibuf
));
1367 zlog_debug("Withdraw %pFX (AS-External Id:%s)", prefix
, ibuf
);
1370 lsa
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
1371 htonl(info
->id
), ospf6
->router_id
, ospf6
->lsdb
);
1373 ospf6_lsa_purge(lsa
);
1375 /* remove binding in external_id_table */
1376 prefix_id
.family
= AF_INET
;
1377 prefix_id
.prefixlen
= 32;
1378 prefix_id
.u
.prefix4
.s_addr
= htonl(info
->id
);
1379 node
= route_node_lookup(ospf6
->external_id_table
, &prefix_id
);
1382 route_unlock_node(node
); /* to free the lookup lock */
1383 route_unlock_node(node
); /* to free the original lock */
1385 ospf6_route_remove(match
, ospf6
->external_table
);
1386 XFREE(MTYPE_OSPF6_EXTERNAL_INFO
, info
);
1388 ospf6_asbr_status_update(ospf6
, ospf6
->redistribute
);
1391 DEFUN (ospf6_redistribute
,
1392 ospf6_redistribute_cmd
,
1393 "redistribute " FRR_REDIST_STR_OSPF6D
,
1395 FRR_REDIST_HELP_STR_OSPF6D
)
1398 struct ospf6_redist
*red
;
1400 VTY_DECLVAR_CONTEXT(ospf6
, ospf6
);
1402 char *proto
= argv
[argc
- 1]->text
;
1403 type
= proto_redistnum(AFI_IP6
, proto
);
1405 return CMD_WARNING_CONFIG_FAILED
;
1407 red
= ospf6_redist_add(ospf6
, type
, 0);
1411 ospf6_asbr_redistribute_unset(ospf6
, red
, type
);
1412 ospf6_asbr_redistribute_set(type
, ospf6
->vrf_id
);
1417 DEFUN (ospf6_redistribute_routemap
,
1418 ospf6_redistribute_routemap_cmd
,
1419 "redistribute " FRR_REDIST_STR_OSPF6D
" route-map WORD",
1421 FRR_REDIST_HELP_STR_OSPF6D
1422 "Route map reference\n"
1425 int idx_protocol
= 1;
1428 struct ospf6_redist
*red
;
1430 VTY_DECLVAR_CONTEXT(ospf6
, ospf6
);
1432 char *proto
= argv
[idx_protocol
]->text
;
1433 type
= proto_redistnum(AFI_IP6
, proto
);
1435 return CMD_WARNING_CONFIG_FAILED
;
1437 red
= ospf6_redist_add(ospf6
, type
, 0);
1441 ospf6_asbr_redistribute_unset(ospf6
, red
, type
);
1442 ospf6_asbr_routemap_set(red
, argv
[idx_word
]->arg
);
1443 ospf6_asbr_redistribute_set(type
, ospf6
->vrf_id
);
1448 DEFUN (no_ospf6_redistribute
,
1449 no_ospf6_redistribute_cmd
,
1450 "no redistribute " FRR_REDIST_STR_OSPF6D
" [route-map WORD]",
1453 FRR_REDIST_HELP_STR_OSPF6D
1454 "Route map reference\n"
1457 int idx_protocol
= 2;
1459 struct ospf6_redist
*red
;
1461 VTY_DECLVAR_CONTEXT(ospf6
, ospf6
);
1463 char *proto
= argv
[idx_protocol
]->text
;
1464 type
= proto_redistnum(AFI_IP6
, proto
);
1466 return CMD_WARNING_CONFIG_FAILED
;
1468 red
= ospf6_redist_lookup(ospf6
, type
, 0);
1472 ospf6_asbr_redistribute_unset(ospf6
, red
, type
);
1473 ospf6_redist_del(ospf6
, red
, type
);
1478 int ospf6_redistribute_config_write(struct vty
*vty
, struct ospf6
*ospf6
)
1481 struct ospf6_redist
*red
;
1483 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
1484 red
= ospf6_redist_lookup(ospf6
, type
, 0);
1487 if (type
== ZEBRA_ROUTE_OSPF6
)
1490 if (ROUTEMAP_NAME(red
))
1491 vty_out(vty
, " redistribute %s route-map %s\n",
1492 ZROUTE_NAME(type
), ROUTEMAP_NAME(red
));
1494 vty_out(vty
, " redistribute %s\n", ZROUTE_NAME(type
));
1500 static void ospf6_redistribute_show_config(struct vty
*vty
, struct ospf6
*ospf6
,
1501 json_object
*json_array
,
1502 json_object
*json
, bool use_json
)
1505 int nroute
[ZEBRA_ROUTE_MAX
];
1507 struct ospf6_route
*route
;
1508 struct ospf6_external_info
*info
;
1509 json_object
*json_route
;
1510 struct ospf6_redist
*red
;
1513 memset(nroute
, 0, sizeof(nroute
));
1514 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
1515 route
= ospf6_route_next(route
)) {
1516 info
= route
->route_option
;
1517 nroute
[info
->type
]++;
1522 vty_out(vty
, "Redistributing External Routes from:\n");
1524 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
1526 red
= ospf6_redist_lookup(ospf6
, type
, 0);
1530 if (type
== ZEBRA_ROUTE_OSPF6
)
1534 json_route
= json_object_new_object();
1535 json_object_string_add(json_route
, "routeType",
1537 json_object_int_add(json_route
, "numberOfRoutes",
1539 json_object_boolean_add(json_route
,
1540 "routeMapNamePresent",
1541 ROUTEMAP_NAME(red
));
1544 if (ROUTEMAP_NAME(red
)) {
1546 json_object_string_add(json_route
,
1548 ROUTEMAP_NAME(red
));
1549 json_object_boolean_add(json_route
,
1554 " %d: %s with route-map \"%s\"%s\n",
1555 nroute
[type
], ZROUTE_NAME(type
),
1558 : " (not found !)"));
1561 vty_out(vty
, " %d: %s\n", nroute
[type
],
1566 json_object_array_add(json_array
, json_route
);
1569 json_object_object_add(json
, "redistributedRoutes", json_array
);
1570 json_object_int_add(json
, "totalRoutes", total
);
1572 vty_out(vty
, "Total %d routes\n", total
);
1575 static void ospf6_redistribute_default_set(struct ospf6
*ospf6
, int originate
)
1577 struct prefix_ipv6 p
= {};
1578 struct in6_addr nexthop
= {};
1579 int cur_originate
= ospf6
->default_originate
;
1581 p
.family
= AF_INET6
;
1584 ospf6
->default_originate
= originate
;
1586 switch (cur_originate
) {
1587 case DEFAULT_ORIGINATE_NONE
:
1589 case DEFAULT_ORIGINATE_ZEBRA
:
1590 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE
,
1591 zclient
, AFI_IP6
, ospf6
->vrf_id
);
1592 ospf6_asbr_redistribute_remove(DEFAULT_ROUTE
, 0,
1593 (struct prefix
*)&p
, ospf6
);
1596 case DEFAULT_ORIGINATE_ALWAYS
:
1597 ospf6_asbr_redistribute_remove(DEFAULT_ROUTE
, 0,
1598 (struct prefix
*)&p
, ospf6
);
1602 switch (originate
) {
1603 case DEFAULT_ORIGINATE_NONE
:
1605 case DEFAULT_ORIGINATE_ZEBRA
:
1606 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD
,
1607 zclient
, AFI_IP6
, ospf6
->vrf_id
);
1610 case DEFAULT_ORIGINATE_ALWAYS
:
1611 ospf6_asbr_redistribute_add(DEFAULT_ROUTE
, 0,
1612 (struct prefix
*)&p
, 0, &nexthop
, 0,
1618 /* Default Route originate. */
1619 DEFPY (ospf6_default_route_originate
,
1620 ospf6_default_route_originate_cmd
,
1621 "default-information originate [{always$always|metric (0-16777214)$mval|metric-type (1-2)$mtype|route-map WORD$rtmap}]",
1622 "Control distribution of default route\n"
1623 "Distribute a default route\n"
1624 "Always advertise default route\n"
1625 "OSPFv3 default metric\n"
1627 "OSPFv3 metric type for default routes\n"
1628 "Set OSPFv3 External Type 1/2 metrics\n"
1629 "Route map reference\n"
1630 "Pointer to route-map entries\n")
1632 int default_originate
= DEFAULT_ORIGINATE_ZEBRA
;
1633 struct ospf6_redist
*red
;
1634 bool sameRtmap
= false;
1636 VTY_DECLVAR_CONTEXT(ospf6
, ospf6
);
1638 int cur_originate
= ospf6
->default_originate
;
1640 red
= ospf6_redist_add(ospf6
, DEFAULT_ROUTE
, 0);
1643 default_originate
= DEFAULT_ORIGINATE_ALWAYS
;
1645 if (mval_str
== NULL
)
1648 if (mtype_str
== NULL
)
1651 /* To check ,if user is providing same route map */
1652 if ((rtmap
== ROUTEMAP_NAME(red
))
1653 || (rtmap
&& ROUTEMAP_NAME(red
)
1654 && (strcmp(rtmap
, ROUTEMAP_NAME(red
)) == 0)))
1657 /* Don't allow if the same lsa is aleardy originated. */
1658 if ((sameRtmap
) && (red
->dmetric
.type
== mtype
)
1659 && (red
->dmetric
.value
== mval
)
1660 && (cur_originate
== default_originate
))
1663 /* Updating Metric details */
1664 red
->dmetric
.type
= mtype
;
1665 red
->dmetric
.value
= mval
;
1667 /* updating route map details */
1669 ospf6_asbr_routemap_set(red
, rtmap
);
1671 ospf6_asbr_routemap_unset(red
);
1673 ospf6_redistribute_default_set(ospf6
, default_originate
);
1677 DEFPY (no_ospf6_default_information_originate
,
1678 no_ospf6_default_information_originate_cmd
,
1679 "no default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
1681 "Control distribution of default information\n"
1682 "Distribute a default route\n"
1683 "Always advertise default route\n"
1684 "OSPFv3 default metric\n"
1686 "OSPFv3 metric type for default routes\n"
1687 "Set OSPFv3 External Type 1/2 metrics\n"
1688 "Route map reference\n"
1689 "Pointer to route-map entries\n")
1691 struct ospf6_redist
*red
;
1693 VTY_DECLVAR_CONTEXT(ospf6
, ospf6
);
1695 red
= ospf6_redist_lookup(ospf6
, DEFAULT_ROUTE
, 0);
1699 ospf6_asbr_routemap_unset(red
);
1700 ospf6_redist_del(ospf6
, red
, DEFAULT_ROUTE
);
1702 ospf6_redistribute_default_set(ospf6
, DEFAULT_ORIGINATE_NONE
);
1706 /* Routemap Functions */
1707 static enum route_map_cmd_result_t
1708 ospf6_routemap_rule_match_address_prefixlist(void *rule
,
1709 const struct prefix
*prefix
,
1713 struct prefix_list
*plist
;
1715 plist
= prefix_list_lookup(AFI_IP6
, (char *)rule
);
1717 return RMAP_NOMATCH
;
1719 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
? RMAP_NOMATCH
1724 ospf6_routemap_rule_match_address_prefixlist_compile(const char *arg
)
1726 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1729 static void ospf6_routemap_rule_match_address_prefixlist_free(void *rule
)
1731 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1734 static const struct route_map_rule_cmd
1735 ospf6_routemap_rule_match_address_prefixlist_cmd
= {
1736 "ipv6 address prefix-list",
1737 ospf6_routemap_rule_match_address_prefixlist
,
1738 ospf6_routemap_rule_match_address_prefixlist_compile
,
1739 ospf6_routemap_rule_match_address_prefixlist_free
,
1742 /* `match interface IFNAME' */
1743 /* Match function should return 1 if match is success else return
1745 static enum route_map_cmd_result_t
1746 ospf6_routemap_rule_match_interface(void *rule
, const struct prefix
*prefix
,
1749 struct interface
*ifp
;
1750 struct ospf6_external_info
*ei
;
1752 ei
= ((struct ospf6_route
*)object
)->route_option
;
1753 ifp
= if_lookup_by_name_all_vrf((char *)rule
);
1755 if (ifp
!= NULL
&& ei
->ifindex
== ifp
->ifindex
)
1758 return RMAP_NOMATCH
;
1761 /* Route map `interface' match statement. `arg' should be
1763 static void *ospf6_routemap_rule_match_interface_compile(const char *arg
)
1765 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1768 /* Free route map's compiled `interface' value. */
1769 static void ospf6_routemap_rule_match_interface_free(void *rule
)
1771 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1774 /* Route map commands for interface matching. */
1775 static const struct route_map_rule_cmd
1776 ospf6_routemap_rule_match_interface_cmd
= {
1778 ospf6_routemap_rule_match_interface
,
1779 ospf6_routemap_rule_match_interface_compile
,
1780 ospf6_routemap_rule_match_interface_free
1783 /* Match function for matching route tags */
1784 static enum route_map_cmd_result_t
1785 ospf6_routemap_rule_match_tag(void *rule
, const struct prefix
*p
, void *object
)
1787 route_tag_t
*tag
= rule
;
1788 struct ospf6_route
*route
= object
;
1789 struct ospf6_external_info
*info
= route
->route_option
;
1791 if (info
->tag
== *tag
)
1794 return RMAP_NOMATCH
;
1797 static const struct route_map_rule_cmd
1798 ospf6_routemap_rule_match_tag_cmd
= {
1800 ospf6_routemap_rule_match_tag
,
1801 route_map_rule_tag_compile
,
1802 route_map_rule_tag_free
,
1805 static enum route_map_cmd_result_t
1806 ospf6_routemap_rule_set_metric_type(void *rule
, const struct prefix
*prefix
,
1809 char *metric_type
= rule
;
1810 struct ospf6_route
*route
= object
;
1812 if (strcmp(metric_type
, "type-2") == 0)
1813 route
->path
.metric_type
= 2;
1815 route
->path
.metric_type
= 1;
1820 static void *ospf6_routemap_rule_set_metric_type_compile(const char *arg
)
1822 if (strcmp(arg
, "type-2") && strcmp(arg
, "type-1"))
1824 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1827 static void ospf6_routemap_rule_set_metric_type_free(void *rule
)
1829 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1832 static const struct route_map_rule_cmd
1833 ospf6_routemap_rule_set_metric_type_cmd
= {
1835 ospf6_routemap_rule_set_metric_type
,
1836 ospf6_routemap_rule_set_metric_type_compile
,
1837 ospf6_routemap_rule_set_metric_type_free
,
1840 static enum route_map_cmd_result_t
1841 ospf6_routemap_rule_set_metric(void *rule
, const struct prefix
*prefix
,
1844 char *metric
= rule
;
1845 struct ospf6_route
*route
= object
;
1847 route
->path
.cost
= atoi(metric
);
1851 static void *ospf6_routemap_rule_set_metric_compile(const char *arg
)
1855 metric
= strtoul(arg
, &endp
, 0);
1856 if (metric
> OSPF_LS_INFINITY
|| *endp
!= '\0')
1858 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1861 static void ospf6_routemap_rule_set_metric_free(void *rule
)
1863 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1866 static const struct route_map_rule_cmd
1867 ospf6_routemap_rule_set_metric_cmd
= {
1869 ospf6_routemap_rule_set_metric
,
1870 ospf6_routemap_rule_set_metric_compile
,
1871 ospf6_routemap_rule_set_metric_free
,
1874 static enum route_map_cmd_result_t
1875 ospf6_routemap_rule_set_forwarding(void *rule
, const struct prefix
*prefix
,
1878 char *forwarding
= rule
;
1879 struct ospf6_route
*route
= object
;
1880 struct ospf6_external_info
*info
= route
->route_option
;
1882 if (inet_pton(AF_INET6
, forwarding
, &info
->forwarding
) != 1) {
1883 memset(&info
->forwarding
, 0, sizeof(struct in6_addr
));
1890 static void *ospf6_routemap_rule_set_forwarding_compile(const char *arg
)
1893 if (inet_pton(AF_INET6
, arg
, &a
) != 1)
1895 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1898 static void ospf6_routemap_rule_set_forwarding_free(void *rule
)
1900 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1903 static const struct route_map_rule_cmd
1904 ospf6_routemap_rule_set_forwarding_cmd
= {
1905 "forwarding-address",
1906 ospf6_routemap_rule_set_forwarding
,
1907 ospf6_routemap_rule_set_forwarding_compile
,
1908 ospf6_routemap_rule_set_forwarding_free
,
1911 static enum route_map_cmd_result_t
1912 ospf6_routemap_rule_set_tag(void *rule
, const struct prefix
*p
, void *object
)
1914 route_tag_t
*tag
= rule
;
1915 struct ospf6_route
*route
= object
;
1916 struct ospf6_external_info
*info
= route
->route_option
;
1922 static const struct route_map_rule_cmd ospf6_routemap_rule_set_tag_cmd
= {
1924 ospf6_routemap_rule_set_tag
,
1925 route_map_rule_tag_compile
,
1926 route_map_rule_tag_free
,
1929 /* add "set metric-type" */
1930 DEFUN_YANG (ospf6_routemap_set_metric_type
, ospf6_routemap_set_metric_type_cmd
,
1931 "set metric-type <type-1|type-2>",
1934 "OSPF6 external type 1 metric\n"
1935 "OSPF6 external type 2 metric\n")
1937 char *ext
= argv
[2]->text
;
1940 "./set-action[action='frr-ospf-route-map:metric-type']";
1941 char xpath_value
[XPATH_MAXLEN
];
1943 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1944 snprintf(xpath_value
, sizeof(xpath_value
),
1945 "%s/rmap-set-action/frr-ospf-route-map:metric-type", xpath
);
1946 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, ext
);
1947 return nb_cli_apply_changes(vty
, NULL
);
1950 /* delete "set metric-type" */
1951 DEFUN_YANG (ospf6_routemap_no_set_metric_type
, ospf6_routemap_no_set_metric_type_cmd
,
1952 "no set metric-type [<type-1|type-2>]",
1956 "OSPF6 external type 1 metric\n"
1957 "OSPF6 external type 2 metric\n")
1960 "./set-action[action='frr-ospf-route-map:metric-type']";
1962 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
1963 return nb_cli_apply_changes(vty
, NULL
);
1966 /* add "set forwarding-address" */
1967 DEFUN_YANG (ospf6_routemap_set_forwarding
, ospf6_routemap_set_forwarding_cmd
,
1968 "set forwarding-address X:X::X:X",
1970 "Forwarding Address\n"
1975 "./set-action[action='frr-ospf6-route-map:forwarding-address']";
1976 char xpath_value
[XPATH_MAXLEN
];
1978 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1979 snprintf(xpath_value
, sizeof(xpath_value
),
1980 "%s/rmap-set-action/frr-ospf6-route-map:ipv6-address", xpath
);
1981 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
,
1982 argv
[idx_ipv6
]->arg
);
1983 return nb_cli_apply_changes(vty
, NULL
);
1986 /* delete "set forwarding-address" */
1987 DEFUN_YANG (ospf6_routemap_no_set_forwarding
, ospf6_routemap_no_set_forwarding_cmd
,
1988 "no set forwarding-address [X:X::X:X]",
1991 "Forwarding Address\n"
1995 "./set-action[action='frr-ospf6-route-map:forwarding-address']";
1997 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
1998 return nb_cli_apply_changes(vty
, NULL
);
2001 static void ospf6_routemap_init(void)
2005 route_map_add_hook(ospf6_asbr_routemap_update
);
2006 route_map_delete_hook(ospf6_asbr_routemap_update
);
2007 route_map_event_hook(ospf6_asbr_routemap_event
);
2009 route_map_set_metric_hook(generic_set_add
);
2010 route_map_no_set_metric_hook(generic_set_delete
);
2012 route_map_match_tag_hook(generic_match_add
);
2013 route_map_no_match_tag_hook(generic_match_delete
);
2015 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
2016 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
2018 route_map_match_interface_hook(generic_match_add
);
2019 route_map_no_match_interface_hook(generic_match_delete
);
2021 route_map_install_match(
2022 &ospf6_routemap_rule_match_address_prefixlist_cmd
);
2023 route_map_install_match(&ospf6_routemap_rule_match_interface_cmd
);
2024 route_map_install_match(&ospf6_routemap_rule_match_tag_cmd
);
2026 route_map_install_set(&ospf6_routemap_rule_set_metric_type_cmd
);
2027 route_map_install_set(&ospf6_routemap_rule_set_metric_cmd
);
2028 route_map_install_set(&ospf6_routemap_rule_set_forwarding_cmd
);
2029 route_map_install_set(&ospf6_routemap_rule_set_tag_cmd
);
2031 /* ASE Metric Type (e.g. Type-1/Type-2) */
2032 install_element(RMAP_NODE
, &ospf6_routemap_set_metric_type_cmd
);
2033 install_element(RMAP_NODE
, &ospf6_routemap_no_set_metric_type_cmd
);
2036 install_element(RMAP_NODE
, &ospf6_routemap_set_forwarding_cmd
);
2037 install_element(RMAP_NODE
, &ospf6_routemap_no_set_forwarding_cmd
);
2041 /* Display functions */
2042 static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
2043 char *buf
, int buflen
,
2046 struct ospf6_as_external_lsa
*external
;
2047 struct in6_addr in6
;
2048 int prefix_length
= 0;
2052 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
2056 ospf6_prefix_in6_addr(&in6
, external
,
2058 prefix_length
= external
->prefix
.prefix_length
;
2060 in6
= *((struct in6_addr
2061 *)((caddr_t
)external
2063 ospf6_as_external_lsa
)
2064 + OSPF6_PREFIX_SPACE(
2069 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
2070 if (prefix_length
) {
2071 snprintf(tbuf
, sizeof(tbuf
), "/%d",
2073 strlcat(buf
, tbuf
, buflen
);
2080 static int ospf6_as_external_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
2081 json_object
*json_obj
, bool use_json
)
2083 struct ospf6_as_external_lsa
*external
;
2086 assert(lsa
->header
);
2087 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
2091 snprintf(buf
, sizeof(buf
), "%c%c%c",
2092 (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_E
) ? 'E'
2094 (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
) ? 'F'
2096 (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
) ? 'T'
2100 json_object_string_add(json_obj
, "bits", buf
);
2101 json_object_int_add(json_obj
, "metric",
2102 (unsigned long)OSPF6_ASBR_METRIC(external
));
2103 ospf6_prefix_options_printbuf(external
->prefix
.prefix_options
,
2105 json_object_string_add(json_obj
, "prefixOptions", buf
);
2106 json_object_int_add(
2107 json_obj
, "referenceLsType",
2108 ntohs(external
->prefix
.prefix_refer_lstype
));
2109 json_object_string_add(json_obj
, "prefix",
2110 ospf6_as_external_lsa_get_prefix_str(
2111 lsa
, buf
, sizeof(buf
), 0));
2113 /* Forwarding-Address */
2114 json_object_boolean_add(
2115 json_obj
, "forwardingAddressPresent",
2116 CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
));
2117 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
))
2118 json_object_string_add(
2119 json_obj
, "forwardingAddress",
2120 ospf6_as_external_lsa_get_prefix_str(
2121 lsa
, buf
, sizeof(buf
), 1));
2124 json_object_boolean_add(
2125 json_obj
, "tagPresent",
2126 CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
));
2127 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
))
2128 json_object_int_add(json_obj
, "tag",
2129 ospf6_as_external_lsa_get_tag(lsa
));
2131 vty_out(vty
, " Bits: %s\n", buf
);
2132 vty_out(vty
, " Metric: %5lu\n",
2133 (unsigned long)OSPF6_ASBR_METRIC(external
));
2135 ospf6_prefix_options_printbuf(external
->prefix
.prefix_options
,
2137 vty_out(vty
, " Prefix Options: %s\n", buf
);
2139 vty_out(vty
, " Referenced LSType: %d\n",
2140 ntohs(external
->prefix
.prefix_refer_lstype
));
2142 vty_out(vty
, " Prefix: %s\n",
2143 ospf6_as_external_lsa_get_prefix_str(lsa
, buf
,
2146 /* Forwarding-Address */
2147 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
)) {
2148 vty_out(vty
, " Forwarding-Address: %s\n",
2149 ospf6_as_external_lsa_get_prefix_str(
2150 lsa
, buf
, sizeof(buf
), 1));
2154 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
)) {
2155 vty_out(vty
, " Tag: %" ROUTE_TAG_PRI
"\n",
2156 ospf6_as_external_lsa_get_tag(lsa
));
2163 static void ospf6_asbr_external_route_show(struct vty
*vty
,
2164 struct ospf6_route
*route
,
2165 json_object
*json_array
,
2168 struct ospf6_external_info
*info
= route
->route_option
;
2169 char prefix
[PREFIX2STR_BUFFER
], id
[16], forwarding
[64];
2171 json_object
*json_route
;
2174 prefix2str(&route
->prefix
, prefix
, sizeof(prefix
));
2175 tmp_id
= ntohl(info
->id
);
2176 inet_ntop(AF_INET
, &tmp_id
, id
, sizeof(id
));
2177 if (!IN6_IS_ADDR_UNSPECIFIED(&info
->forwarding
))
2178 inet_ntop(AF_INET6
, &info
->forwarding
, forwarding
,
2179 sizeof(forwarding
));
2181 snprintf(forwarding
, sizeof(forwarding
), ":: (ifindex %d)",
2182 ospf6_route_get_first_nh_index(route
));
2185 json_route
= json_object_new_object();
2186 snprintf(route_type
, sizeof(route_type
), "%c",
2187 zebra_route_char(info
->type
));
2188 json_object_string_add(json_route
, "routeType", route_type
);
2189 json_object_string_add(json_route
, "destination", prefix
);
2190 json_object_string_add(json_route
, "id", id
);
2191 json_object_int_add(json_route
, "metricType",
2192 route
->path
.metric_type
);
2193 json_object_int_add(
2194 json_route
, "routeCost",
2195 (unsigned long)(route
->path
.metric_type
== 2
2196 ? route
->path
.u
.cost_e2
2197 : route
->path
.cost
));
2198 json_object_string_add(json_route
, "forwarding", forwarding
);
2200 json_object_array_add(json_array
, json_route
);
2203 vty_out(vty
, "%c %-32pFX %-15s type-%d %5lu %s\n",
2204 zebra_route_char(info
->type
), &route
->prefix
, id
,
2205 route
->path
.metric_type
,
2206 (unsigned long)(route
->path
.metric_type
== 2
2207 ? route
->path
.u
.cost_e2
2208 : route
->path
.cost
),
2212 DEFUN(show_ipv6_ospf6_redistribute
, show_ipv6_ospf6_redistribute_cmd
,
2213 "show ipv6 ospf6 [vrf <NAME|all>] redistribute [json]",
2214 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
2216 "redistributing External information\n" JSON_STR
)
2218 struct ospf6_route
*route
;
2219 struct ospf6
*ospf6
= NULL
;
2220 json_object
*json
= NULL
;
2221 bool uj
= use_json(argc
, argv
);
2222 struct listnode
*node
;
2223 const char *vrf_name
= NULL
;
2224 bool all_vrf
= false;
2227 json_object
*json_array_routes
= NULL
;
2228 json_object
*json_array_redistribute
= NULL
;
2230 OSPF6_CMD_CHECK_RUNNING();
2231 OSPF6_FIND_VRF_ARGS(argv
, argc
, idx_vrf
, vrf_name
, all_vrf
);
2234 json
= json_object_new_object();
2235 json_array_routes
= json_object_new_array();
2236 json_array_redistribute
= json_object_new_array();
2239 for (ALL_LIST_ELEMENTS_RO(om6
->ospf6
, node
, ospf6
)) {
2241 || ((ospf6
->name
== NULL
&& vrf_name
== NULL
)
2242 || (ospf6
->name
&& vrf_name
2243 && strcmp(ospf6
->name
, vrf_name
) == 0))) {
2244 ospf6_redistribute_show_config(
2245 vty
, ospf6
, json_array_redistribute
, json
, uj
);
2247 for (route
= ospf6_route_head(ospf6
->external_table
);
2248 route
; route
= ospf6_route_next(route
)) {
2249 ospf6_asbr_external_route_show(
2250 vty
, route
, json_array_routes
, uj
);
2254 json_object_object_add(json
, "routes",
2256 vty_out(vty
, "%s\n",
2257 json_object_to_json_string_ext(
2258 json
, JSON_C_TO_STRING_PRETTY
));
2259 json_object_free(json
);
2270 static struct ospf6_lsa_handler as_external_handler
= {
2271 .lh_type
= OSPF6_LSTYPE_AS_EXTERNAL
,
2272 .lh_name
= "AS-External",
2273 .lh_short_name
= "ASE",
2274 .lh_show
= ospf6_as_external_lsa_show
,
2275 .lh_get_prefix_str
= ospf6_as_external_lsa_get_prefix_str
,
2278 void ospf6_asbr_init(void)
2280 ospf6_routemap_init();
2282 ospf6_install_lsa_handler(&as_external_handler
);
2284 install_element(VIEW_NODE
, &show_ipv6_ospf6_redistribute_cmd
);
2286 install_element(OSPF6_NODE
, &ospf6_default_route_originate_cmd
);
2287 install_element(OSPF6_NODE
,
2288 &no_ospf6_default_information_originate_cmd
);
2289 install_element(OSPF6_NODE
, &ospf6_redistribute_cmd
);
2290 install_element(OSPF6_NODE
, &ospf6_redistribute_routemap_cmd
);
2291 install_element(OSPF6_NODE
, &no_ospf6_redistribute_cmd
);
2294 void ospf6_asbr_redistribute_reset(struct ospf6
*ospf6
)
2297 struct ospf6_redist
*red
;
2299 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
2300 red
= ospf6_redist_lookup(ospf6
, type
, 0);
2303 if (type
== ZEBRA_ROUTE_OSPF6
)
2305 ospf6_asbr_redistribute_unset(ospf6
, red
, type
);
2306 ospf6_redist_del(ospf6
, red
, type
);
2308 red
= ospf6_redist_lookup(ospf6
, DEFAULT_ROUTE
, 0);
2310 ospf6_asbr_routemap_unset(red
);
2311 ospf6_redist_del(ospf6
, red
, type
);
2312 ospf6_redistribute_default_set(ospf6
, DEFAULT_ORIGINATE_NONE
);
2316 void ospf6_asbr_terminate(void)
2318 /* Cleanup route maps */
2322 DEFUN (debug_ospf6_asbr
,
2323 debug_ospf6_asbr_cmd
,
2327 "Debug OSPFv3 ASBR function\n"
2330 OSPF6_DEBUG_ASBR_ON();
2334 DEFUN (no_debug_ospf6_asbr
,
2335 no_debug_ospf6_asbr_cmd
,
2336 "no debug ospf6 asbr",
2340 "Debug OSPFv3 ASBR function\n"
2343 OSPF6_DEBUG_ASBR_OFF();
2347 int config_write_ospf6_debug_asbr(struct vty
*vty
)
2349 if (IS_OSPF6_DEBUG_ASBR
)
2350 vty_out(vty
, "debug ospf6 asbr\n");
2354 int ospf6_distribute_config_write(struct vty
*vty
, struct ospf6
*ospf6
)
2356 struct ospf6_redist
*red
;
2359 /* default-route print. */
2360 if (ospf6
->default_originate
!= DEFAULT_ORIGINATE_NONE
) {
2361 vty_out(vty
, " default-information originate");
2362 if (ospf6
->default_originate
2363 == DEFAULT_ORIGINATE_ALWAYS
)
2364 vty_out(vty
, " always");
2366 red
= ospf6_redist_lookup(ospf6
, DEFAULT_ROUTE
, 0);
2368 if (red
->dmetric
.value
>= 0)
2369 vty_out(vty
, " metric %d",
2370 red
->dmetric
.value
);
2372 if (red
->dmetric
.type
>= 0)
2373 vty_out(vty
, " metric-type %d",
2376 if (ROUTEMAP_NAME(red
))
2377 vty_out(vty
, " route-map %s",
2378 ROUTEMAP_NAME(red
));
2387 void install_element_ospf6_debug_asbr(void)
2389 install_element(ENABLE_NODE
, &debug_ospf6_asbr_cmd
);
2390 install_element(ENABLE_NODE
, &no_debug_ospf6_asbr_cmd
);
2391 install_element(CONFIG_NODE
, &debug_ospf6_asbr_cmd
);
2392 install_element(CONFIG_NODE
, &no_debug_ospf6_asbr_cmd
);