2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
35 #include "ospf6_proto.h"
36 #include "ospf6_lsa.h"
37 #include "ospf6_lsdb.h"
38 #include "ospf6_route.h"
39 #include "ospf6_zebra.h"
40 #include "ospf6_message.h"
42 #include "ospf6_top.h"
43 #include "ospf6_area.h"
44 #include "ospf6_interface.h"
45 #include "ospf6_neighbor.h"
46 #include "ospf6_asbr.h"
47 #include "ospf6_intra.h"
48 #include "ospf6_flood.h"
51 unsigned char conf_debug_ospf6_asbr
= 0;
53 #define ZROUTE_NAME(x) zebra_route_string(x)
55 /* AS External LSA origination */
56 static void ospf6_as_external_lsa_originate(struct ospf6_route
*route
)
58 char buffer
[OSPF6_MAX_LSASIZE
];
59 struct ospf6_lsa_header
*lsa_header
;
60 struct ospf6_lsa
*lsa
;
61 struct ospf6_external_info
*info
= route
->route_option
;
63 struct ospf6_as_external_lsa
*as_external_lsa
;
64 char buf
[PREFIX2STR_BUFFER
];
67 if (IS_OSPF6_DEBUG_ASBR
|| IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL
)) {
68 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
69 zlog_debug("Originate AS-External-LSA for %s", buf
);
73 memset(buffer
, 0, sizeof(buffer
));
74 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
75 as_external_lsa
= (struct ospf6_as_external_lsa
76 *)((caddr_t
)lsa_header
77 + sizeof(struct ospf6_lsa_header
));
78 p
= (caddr_t
)((caddr_t
)as_external_lsa
79 + sizeof(struct ospf6_as_external_lsa
));
81 /* Fill AS-External-LSA */
83 if (route
->path
.metric_type
== 2)
84 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
86 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
88 /* forwarding address */
89 if (!IN6_IS_ADDR_UNSPECIFIED(&info
->forwarding
))
90 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
92 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
94 /* external route tag */
96 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
98 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
101 OSPF6_ASBR_METRIC_SET(as_external_lsa
, route
->path
.cost
);
104 as_external_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
107 as_external_lsa
->prefix
.prefix_options
= route
->path
.prefix_options
;
109 /* don't use refer LS-type */
110 as_external_lsa
->prefix
.prefix_refer_lstype
= htons(0);
113 memcpy(p
, &route
->prefix
.u
.prefix6
,
114 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
115 ospf6_prefix_apply_mask(&as_external_lsa
->prefix
);
116 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
118 /* Forwarding address */
119 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
)) {
120 memcpy(p
, &info
->forwarding
, sizeof(struct in6_addr
));
121 p
+= sizeof(struct in6_addr
);
124 /* External Route Tag */
125 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
)) {
126 route_tag_t network_order
= htonl(info
->tag
);
128 memcpy(p
, &network_order
, sizeof(network_order
));
129 p
+= sizeof(network_order
);
132 /* Fill LSA Header */
134 lsa_header
->type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
135 lsa_header
->id
= route
->path
.origin
.id
;
136 lsa_header
->adv_router
= ospf6
->router_id
;
138 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
139 lsa_header
->adv_router
, ospf6
->lsdb
);
140 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
143 ospf6_lsa_checksum(lsa_header
);
146 lsa
= ospf6_lsa_create(lsa_header
);
149 ospf6_lsa_originate_process(lsa
, ospf6
);
152 static route_tag_t
ospf6_as_external_lsa_get_tag(struct ospf6_lsa
*lsa
)
154 struct ospf6_as_external_lsa
*external
;
155 ptrdiff_t tag_offset
;
156 route_tag_t network_order
;
161 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
164 if (!CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
))
167 tag_offset
= sizeof(*external
)
168 + OSPF6_PREFIX_SPACE(external
->prefix
.prefix_length
);
169 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
))
170 tag_offset
+= sizeof(struct in6_addr
);
172 memcpy(&network_order
, (caddr_t
)external
+ tag_offset
,
173 sizeof(network_order
));
174 return ntohl(network_order
);
177 void ospf6_asbr_lsa_add(struct ospf6_lsa
*lsa
)
179 struct ospf6_as_external_lsa
*external
;
180 struct prefix asbr_id
;
181 struct ospf6_route
*asbr_entry
, *route
;
182 char buf
[PREFIX2STR_BUFFER
];
184 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
187 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
188 zlog_debug("Calculate AS-External route for %s", lsa
->name
);
190 if (lsa
->header
->adv_router
== ospf6
->router_id
) {
191 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
192 zlog_debug("Ignore self-originated AS-External-LSA");
196 if (OSPF6_ASBR_METRIC(external
) == OSPF_LS_INFINITY
) {
197 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
198 zlog_debug("Ignore LSA with LSInfinity Metric");
202 if (CHECK_FLAG(external
->prefix
.prefix_options
,
203 OSPF6_PREFIX_OPTION_NU
)) {
204 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
205 zlog_debug("Ignore LSA with NU bit set Metric");
209 ospf6_linkstate_prefix(lsa
->header
->adv_router
, htonl(0), &asbr_id
);
210 asbr_entry
= ospf6_route_lookup(&asbr_id
, ospf6
->brouter_table
);
211 if (asbr_entry
== NULL
212 || !CHECK_FLAG(asbr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)) {
213 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
214 prefix2str(&asbr_id
, buf
, sizeof(buf
));
215 zlog_debug("ASBR entry not found: %s", buf
);
220 route
= ospf6_route_create();
221 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
222 route
->prefix
.family
= AF_INET6
;
223 route
->prefix
.prefixlen
= external
->prefix
.prefix_length
;
224 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
, &external
->prefix
);
226 route
->path
.area_id
= asbr_entry
->path
.area_id
;
227 route
->path
.origin
.type
= lsa
->header
->type
;
228 route
->path
.origin
.id
= lsa
->header
->id
;
229 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
231 route
->path
.prefix_options
= external
->prefix
.prefix_options
;
232 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_E
)) {
233 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL2
;
234 route
->path
.metric_type
= 2;
235 route
->path
.cost
= asbr_entry
->path
.cost
;
236 route
->path
.u
.cost_e2
= OSPF6_ASBR_METRIC(external
);
238 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL1
;
239 route
->path
.metric_type
= 1;
241 asbr_entry
->path
.cost
+ OSPF6_ASBR_METRIC(external
);
242 route
->path
.u
.cost_e2
= 0;
245 route
->path
.tag
= ospf6_as_external_lsa_get_tag(lsa
);
247 ospf6_route_copy_nexthops(route
, asbr_entry
);
249 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
250 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
251 zlog_debug("AS-External route add: %s", buf
);
254 ospf6_route_add(route
, ospf6
->route_table
);
257 void ospf6_asbr_lsa_remove(struct ospf6_lsa
*lsa
)
259 struct ospf6_as_external_lsa
*external
;
260 struct prefix prefix
;
261 struct ospf6_route
*route
, *nroute
;
262 char buf
[PREFIX2STR_BUFFER
];
264 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
267 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
268 zlog_debug("Withdraw AS-External route for %s", lsa
->name
);
270 if (lsa
->header
->adv_router
== ospf6
->router_id
) {
271 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
))
272 zlog_debug("Ignore self-originated AS-External-LSA");
276 memset(&prefix
, 0, sizeof(struct prefix
));
277 prefix
.family
= AF_INET6
;
278 prefix
.prefixlen
= external
->prefix
.prefix_length
;
279 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, &external
->prefix
);
281 route
= ospf6_route_lookup(&prefix
, ospf6
->route_table
);
283 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
284 prefix2str(&prefix
, buf
, sizeof(buf
));
285 zlog_debug("AS-External route %s not found", buf
);
290 for (ospf6_route_lock(route
);
291 route
&& ospf6_route_is_prefix(&prefix
, route
); route
= nroute
) {
292 nroute
= ospf6_route_next(route
);
293 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
295 if (route
->path
.origin
.type
!= lsa
->header
->type
)
297 if (route
->path
.origin
.id
!= lsa
->header
->id
)
299 if (route
->path
.origin
.adv_router
!= lsa
->header
->adv_router
)
302 if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL
)) {
303 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
304 zlog_debug("AS-External route remove: %s", buf
);
306 ospf6_route_remove(route
, ospf6
->route_table
);
309 ospf6_route_unlock(route
);
312 void ospf6_asbr_lsentry_add(struct ospf6_route
*asbr_entry
)
314 struct ospf6_lsa
*lsa
;
318 if (!CHECK_FLAG(asbr_entry
->flag
, OSPF6_ROUTE_BEST
)) {
320 inet_ntop(AF_INET
, &ADV_ROUTER_IN_PREFIX(&asbr_entry
->prefix
),
322 zlog_info("ignore non-best path: lsentry %s add", buf
);
326 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
327 router
= ospf6_linkstate_prefix_adv_router(&asbr_entry
->prefix
);
328 for (lsa
= ospf6_lsdb_type_router_head(type
, router
, ospf6
->lsdb
); lsa
;
329 lsa
= ospf6_lsdb_type_router_next(type
, router
, lsa
)) {
330 if (!OSPF6_LSA_IS_MAXAGE(lsa
))
331 ospf6_asbr_lsa_add(lsa
);
335 void ospf6_asbr_lsentry_remove(struct ospf6_route
*asbr_entry
)
337 struct ospf6_lsa
*lsa
;
341 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
342 router
= ospf6_linkstate_prefix_adv_router(&asbr_entry
->prefix
);
343 for (lsa
= ospf6_lsdb_type_router_head(type
, router
, ospf6
->lsdb
); lsa
;
344 lsa
= ospf6_lsdb_type_router_next(type
, router
, lsa
))
345 ospf6_asbr_lsa_remove(lsa
);
349 /* redistribute function */
351 static void ospf6_asbr_routemap_set(int type
, const char *mapname
)
353 if (ospf6
->rmap
[type
].name
)
354 free(ospf6
->rmap
[type
].name
);
355 ospf6
->rmap
[type
].name
= strdup(mapname
);
356 ospf6
->rmap
[type
].map
= route_map_lookup_by_name(mapname
);
359 static void ospf6_asbr_routemap_unset(int type
)
361 if (ospf6
->rmap
[type
].name
)
362 free(ospf6
->rmap
[type
].name
);
363 ospf6
->rmap
[type
].name
= NULL
;
364 ospf6
->rmap
[type
].map
= NULL
;
367 static void ospf6_asbr_routemap_update(const char *mapname
)
374 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
375 if (ospf6
->rmap
[type
].name
)
376 ospf6
->rmap
[type
].map
= route_map_lookup_by_name(
377 ospf6
->rmap
[type
].name
);
379 ospf6
->rmap
[type
].map
= NULL
;
383 int ospf6_asbr_is_asbr(struct ospf6
*o
)
385 return o
->external_table
->count
;
388 static void ospf6_asbr_redistribute_set(int type
)
390 ospf6_zebra_redistribute(type
);
393 static void ospf6_asbr_redistribute_unset(int type
)
395 struct ospf6_route
*route
;
396 struct ospf6_external_info
*info
;
398 ospf6_zebra_no_redistribute(type
);
400 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
401 route
= ospf6_route_next(route
)) {
402 info
= route
->route_option
;
403 if (info
->type
!= type
)
406 ospf6_asbr_redistribute_remove(info
->type
, 0, &route
->prefix
);
409 ospf6_asbr_routemap_unset(type
);
412 /* When an area is unstubified, flood all the external LSAs in the area */
413 void ospf6_asbr_send_externals_to_area(struct ospf6_area
*oa
)
415 struct ospf6_lsa
*lsa
;
417 for (lsa
= ospf6_lsdb_head(oa
->ospf6
->lsdb
); lsa
;
418 lsa
= ospf6_lsdb_next(lsa
)) {
419 if (ntohs(lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
) {
420 zlog_debug("%s: Flooding AS-External LSA %s\n",
421 __func__
, lsa
->name
);
422 ospf6_flood_area(NULL
, lsa
, oa
);
427 void ospf6_asbr_redistribute_add(int type
, ifindex_t ifindex
,
428 struct prefix
*prefix
, u_int nexthop_num
,
429 struct in6_addr
*nexthop
, route_tag_t tag
)
432 struct ospf6_route troute
;
433 struct ospf6_external_info tinfo
;
434 struct ospf6_route
*route
, *match
;
435 struct ospf6_external_info
*info
;
436 struct prefix prefix_id
;
437 struct route_node
*node
;
438 char pbuf
[PREFIX2STR_BUFFER
], ibuf
[16];
439 struct listnode
*lnode
, *lnnode
;
440 struct ospf6_area
*oa
;
442 if (!ospf6_zebra_is_redistribute(type
))
445 if (IS_OSPF6_DEBUG_ASBR
) {
446 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
447 zlog_debug("Redistribute %s (%s)", pbuf
, ZROUTE_NAME(type
));
450 /* if route-map was specified but not found, do not advertise */
451 if (ospf6
->rmap
[type
].name
) {
452 if (ospf6
->rmap
[type
].map
== NULL
)
453 ospf6_asbr_routemap_update(NULL
);
454 if (ospf6
->rmap
[type
].map
== NULL
) {
456 "route-map \"%s\" not found, suppress redistributing",
457 ospf6
->rmap
[type
].name
);
462 /* apply route-map */
463 if (ospf6
->rmap
[type
].map
) {
464 memset(&troute
, 0, sizeof(troute
));
465 memset(&tinfo
, 0, sizeof(tinfo
));
466 troute
.route_option
= &tinfo
;
467 tinfo
.ifindex
= ifindex
;
470 ret
= route_map_apply(ospf6
->rmap
[type
].map
, prefix
, RMAP_OSPF6
,
472 if (ret
== RMAP_DENYMATCH
) {
473 if (IS_OSPF6_DEBUG_ASBR
)
474 zlog_debug("Denied by route-map \"%s\"",
475 ospf6
->rmap
[type
].name
);
480 match
= ospf6_route_lookup(prefix
, ospf6
->external_table
);
482 info
= match
->route_option
;
484 /* copy result of route-map */
485 if (ospf6
->rmap
[type
].map
) {
486 if (troute
.path
.metric_type
)
487 match
->path
.metric_type
=
488 troute
.path
.metric_type
;
489 if (troute
.path
.cost
)
490 match
->path
.cost
= troute
.path
.cost
;
491 if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo
.forwarding
))
492 memcpy(&info
->forwarding
, &tinfo
.forwarding
,
493 sizeof(struct in6_addr
));
494 info
->tag
= tinfo
.tag
;
496 /* If there is no route-map, simply update the tag */
502 if (nexthop_num
&& nexthop
)
503 ospf6_route_add_nexthop(match
, ifindex
, nexthop
);
505 ospf6_route_add_nexthop(match
, ifindex
, NULL
);
507 /* create/update binding in external_id_table */
508 prefix_id
.family
= AF_INET
;
509 prefix_id
.prefixlen
= 32;
510 prefix_id
.u
.prefix4
.s_addr
= htonl(info
->id
);
511 node
= route_node_get(ospf6
->external_id_table
, &prefix_id
);
514 if (IS_OSPF6_DEBUG_ASBR
) {
515 inet_ntop(AF_INET
, &prefix_id
.u
.prefix4
, ibuf
,
517 zlog_debug("Advertise as AS-External Id:%s", ibuf
);
520 match
->path
.origin
.id
= htonl(info
->id
);
521 ospf6_as_external_lsa_originate(match
);
525 /* create new entry */
526 route
= ospf6_route_create();
527 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
528 memcpy(&route
->prefix
, prefix
, sizeof(struct prefix
));
530 info
= (struct ospf6_external_info
*)XCALLOC(
531 MTYPE_OSPF6_EXTERNAL_INFO
, sizeof(struct ospf6_external_info
));
532 route
->route_option
= info
;
533 info
->id
= ospf6
->external_id
++;
535 /* copy result of route-map */
536 if (ospf6
->rmap
[type
].map
) {
537 if (troute
.path
.metric_type
)
538 route
->path
.metric_type
= troute
.path
.metric_type
;
539 if (troute
.path
.cost
)
540 route
->path
.cost
= troute
.path
.cost
;
541 if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo
.forwarding
))
542 memcpy(&info
->forwarding
, &tinfo
.forwarding
,
543 sizeof(struct in6_addr
));
544 info
->tag
= tinfo
.tag
;
546 /* If there is no route-map, simply set the tag */
551 if (nexthop_num
&& nexthop
)
552 ospf6_route_add_nexthop(route
, ifindex
, nexthop
);
554 ospf6_route_add_nexthop(route
, ifindex
, NULL
);
556 /* create/update binding in external_id_table */
557 prefix_id
.family
= AF_INET
;
558 prefix_id
.prefixlen
= 32;
559 prefix_id
.u
.prefix4
.s_addr
= htonl(info
->id
);
560 node
= route_node_get(ospf6
->external_id_table
, &prefix_id
);
563 route
= ospf6_route_add(route
, ospf6
->external_table
);
564 route
->route_option
= info
;
566 if (IS_OSPF6_DEBUG_ASBR
) {
567 inet_ntop(AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof(ibuf
));
568 zlog_debug("Advertise as AS-External Id:%s", ibuf
);
571 route
->path
.origin
.id
= htonl(info
->id
);
572 ospf6_as_external_lsa_originate(route
);
574 /* Router-Bit (ASBR Flag) may have to be updated */
575 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, lnode
, lnnode
, oa
))
576 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
579 void ospf6_asbr_redistribute_remove(int type
, ifindex_t ifindex
,
580 struct prefix
*prefix
)
582 struct ospf6_route
*match
;
583 struct ospf6_external_info
*info
= NULL
;
584 struct route_node
*node
;
585 struct ospf6_lsa
*lsa
;
586 struct prefix prefix_id
;
587 char pbuf
[PREFIX2STR_BUFFER
], ibuf
[16];
588 struct listnode
*lnode
, *lnnode
;
589 struct ospf6_area
*oa
;
591 match
= ospf6_route_lookup(prefix
, ospf6
->external_table
);
593 if (IS_OSPF6_DEBUG_ASBR
) {
594 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
595 zlog_debug("No such route %s to withdraw", pbuf
);
600 info
= match
->route_option
;
603 if (info
->type
!= type
) {
604 if (IS_OSPF6_DEBUG_ASBR
) {
605 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
606 zlog_debug("Original protocol mismatch: %s", pbuf
);
611 if (IS_OSPF6_DEBUG_ASBR
) {
612 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
613 inet_ntop(AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof(ibuf
));
614 zlog_debug("Withdraw %s (AS-External Id:%s)", pbuf
, ibuf
);
617 lsa
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
618 htonl(info
->id
), ospf6
->router_id
, ospf6
->lsdb
);
620 ospf6_lsa_purge(lsa
);
622 /* remove binding in external_id_table */
623 prefix_id
.family
= AF_INET
;
624 prefix_id
.prefixlen
= 32;
625 prefix_id
.u
.prefix4
.s_addr
= htonl(info
->id
);
626 node
= route_node_lookup(ospf6
->external_id_table
, &prefix_id
);
629 route_unlock_node(node
);
631 ospf6_route_remove(match
, ospf6
->external_table
);
632 XFREE(MTYPE_OSPF6_EXTERNAL_INFO
, info
);
634 /* Router-Bit (ASBR Flag) may have to be updated */
635 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, lnode
, lnnode
, oa
))
636 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
639 DEFUN (ospf6_redistribute
,
640 ospf6_redistribute_cmd
,
641 "redistribute " FRR_REDIST_STR_OSPF6D
,
643 FRR_REDIST_HELP_STR_OSPF6D
)
647 char *proto
= argv
[argc
- 1]->text
;
648 type
= proto_redistnum(AFI_IP6
, proto
);
652 ospf6_asbr_redistribute_unset(type
);
653 ospf6_asbr_redistribute_set(type
);
657 DEFUN (ospf6_redistribute_routemap
,
658 ospf6_redistribute_routemap_cmd
,
659 "redistribute " FRR_REDIST_STR_OSPF6D
" route-map WORD",
661 FRR_REDIST_HELP_STR_OSPF6D
662 "Route map reference\n"
665 int idx_protocol
= 1;
669 char *proto
= argv
[idx_protocol
]->text
;
670 type
= proto_redistnum(AFI_IP6
, proto
);
674 ospf6_asbr_redistribute_unset(type
);
675 ospf6_asbr_routemap_set(type
, argv
[idx_word
]->arg
);
676 ospf6_asbr_redistribute_set(type
);
680 DEFUN (no_ospf6_redistribute
,
681 no_ospf6_redistribute_cmd
,
682 "no redistribute " FRR_REDIST_STR_OSPF6D
" [route-map WORD]",
685 FRR_REDIST_HELP_STR_OSPF6D
686 "Route map reference\n"
689 int idx_protocol
= 2;
692 char *proto
= argv
[idx_protocol
]->text
;
693 type
= proto_redistnum(AFI_IP6
, proto
);
697 ospf6_asbr_redistribute_unset(type
);
702 int ospf6_redistribute_config_write(struct vty
*vty
)
706 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
707 if (type
== ZEBRA_ROUTE_OSPF6
)
709 if (!ospf6_zebra_is_redistribute(type
))
712 if (ospf6
->rmap
[type
].name
)
713 vty_out(vty
, " redistribute %s route-map %s%s",
714 ZROUTE_NAME(type
), ospf6
->rmap
[type
].name
, VNL
);
716 vty_out(vty
, " redistribute %s%s", ZROUTE_NAME(type
),
723 static void ospf6_redistribute_show_config(struct vty
*vty
)
726 int nroute
[ZEBRA_ROUTE_MAX
];
728 struct ospf6_route
*route
;
729 struct ospf6_external_info
*info
;
732 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
734 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
735 route
= ospf6_route_next(route
)) {
736 info
= route
->route_option
;
737 nroute
[info
->type
]++;
741 vty_out(vty
, "Redistributing External Routes from:%s", VNL
);
742 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
743 if (type
== ZEBRA_ROUTE_OSPF6
)
745 if (!ospf6_zebra_is_redistribute(type
))
748 if (ospf6
->rmap
[type
].name
)
749 vty_out(vty
, " %d: %s with route-map \"%s\"%s%s",
750 nroute
[type
], ZROUTE_NAME(type
),
751 ospf6
->rmap
[type
].name
,
752 (ospf6
->rmap
[type
].map
? "" : " (not found !)"),
755 vty_out(vty
, " %d: %s%s", nroute
[type
],
756 ZROUTE_NAME(type
), VNL
);
758 vty_out(vty
, "Total %d routes%s", total
, VNL
);
762 /* Routemap Functions */
763 static route_map_result_t
764 ospf6_routemap_rule_match_address_prefixlist(void *rule
, struct prefix
*prefix
,
765 route_map_object_t type
,
768 struct prefix_list
*plist
;
770 if (type
!= RMAP_OSPF6
)
773 plist
= prefix_list_lookup(AFI_IP6
, (char *)rule
);
777 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
? RMAP_NOMATCH
782 ospf6_routemap_rule_match_address_prefixlist_compile(const char *arg
)
784 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
787 static void ospf6_routemap_rule_match_address_prefixlist_free(void *rule
)
789 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
792 struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd
= {
793 "ipv6 address prefix-list",
794 ospf6_routemap_rule_match_address_prefixlist
,
795 ospf6_routemap_rule_match_address_prefixlist_compile
,
796 ospf6_routemap_rule_match_address_prefixlist_free
,
799 /* `match interface IFNAME' */
800 /* Match function should return 1 if match is success else return
802 static route_map_result_t
803 ospf6_routemap_rule_match_interface(void *rule
, struct prefix
*prefix
,
804 route_map_object_t type
, void *object
)
806 struct interface
*ifp
;
807 struct ospf6_external_info
*ei
;
809 if (type
== RMAP_OSPF6
) {
810 ei
= ((struct ospf6_route
*)object
)->route_option
;
811 ifp
= if_lookup_by_name((char *)rule
, VRF_DEFAULT
);
813 if (ifp
!= NULL
&& ei
->ifindex
== ifp
->ifindex
)
820 /* Route map `interface' match statement. `arg' should be
822 static void *ospf6_routemap_rule_match_interface_compile(const char *arg
)
824 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
827 /* Free route map's compiled `interface' value. */
828 static void ospf6_routemap_rule_match_interface_free(void *rule
)
830 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
833 /* Route map commands for interface matching. */
834 struct route_map_rule_cmd ospf6_routemap_rule_match_interface_cmd
= {
835 "interface", ospf6_routemap_rule_match_interface
,
836 ospf6_routemap_rule_match_interface_compile
,
837 ospf6_routemap_rule_match_interface_free
};
839 /* Match function for matching route tags */
840 static route_map_result_t
ospf6_routemap_rule_match_tag(void *rule
,
841 struct prefix
*prefix
,
842 route_map_object_t type
,
845 route_tag_t
*tag
= rule
;
846 struct ospf6_route
*route
= object
;
847 struct ospf6_external_info
*info
= route
->route_option
;
849 if (type
== RMAP_OSPF6
&& info
->tag
== *tag
)
855 static struct route_map_rule_cmd ospf6_routemap_rule_match_tag_cmd
= {
856 "tag", ospf6_routemap_rule_match_tag
, route_map_rule_tag_compile
,
857 route_map_rule_tag_free
,
860 static route_map_result_t
861 ospf6_routemap_rule_set_metric_type(void *rule
, struct prefix
*prefix
,
862 route_map_object_t type
, void *object
)
864 char *metric_type
= rule
;
865 struct ospf6_route
*route
= object
;
867 if (type
!= RMAP_OSPF6
)
870 if (strcmp(metric_type
, "type-2") == 0)
871 route
->path
.metric_type
= 2;
873 route
->path
.metric_type
= 1;
878 static void *ospf6_routemap_rule_set_metric_type_compile(const char *arg
)
880 if (strcmp(arg
, "type-2") && strcmp(arg
, "type-1"))
882 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
885 static void ospf6_routemap_rule_set_metric_type_free(void *rule
)
887 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
890 struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd
= {
891 "metric-type", ospf6_routemap_rule_set_metric_type
,
892 ospf6_routemap_rule_set_metric_type_compile
,
893 ospf6_routemap_rule_set_metric_type_free
,
896 static route_map_result_t
897 ospf6_routemap_rule_set_metric(void *rule
, struct prefix
*prefix
,
898 route_map_object_t type
, void *object
)
901 struct ospf6_route
*route
= object
;
903 if (type
!= RMAP_OSPF6
)
906 route
->path
.cost
= atoi(metric
);
910 static void *ospf6_routemap_rule_set_metric_compile(const char *arg
)
914 metric
= strtoul(arg
, &endp
, 0);
915 if (metric
> OSPF_LS_INFINITY
|| *endp
!= '\0')
917 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
920 static void ospf6_routemap_rule_set_metric_free(void *rule
)
922 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
925 struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd
= {
926 "metric", ospf6_routemap_rule_set_metric
,
927 ospf6_routemap_rule_set_metric_compile
,
928 ospf6_routemap_rule_set_metric_free
,
931 static route_map_result_t
932 ospf6_routemap_rule_set_forwarding(void *rule
, struct prefix
*prefix
,
933 route_map_object_t type
, void *object
)
935 char *forwarding
= rule
;
936 struct ospf6_route
*route
= object
;
937 struct ospf6_external_info
*info
= route
->route_option
;
939 if (type
!= RMAP_OSPF6
)
942 if (inet_pton(AF_INET6
, forwarding
, &info
->forwarding
) != 1) {
943 memset(&info
->forwarding
, 0, sizeof(struct in6_addr
));
950 static void *ospf6_routemap_rule_set_forwarding_compile(const char *arg
)
953 if (inet_pton(AF_INET6
, arg
, &a
) != 1)
955 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
958 static void ospf6_routemap_rule_set_forwarding_free(void *rule
)
960 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
963 struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd
= {
964 "forwarding-address", ospf6_routemap_rule_set_forwarding
,
965 ospf6_routemap_rule_set_forwarding_compile
,
966 ospf6_routemap_rule_set_forwarding_free
,
969 static route_map_result_t
ospf6_routemap_rule_set_tag(void *rule
,
970 struct prefix
*prefix
,
971 route_map_object_t type
,
974 route_tag_t
*tag
= rule
;
975 struct ospf6_route
*route
= object
;
976 struct ospf6_external_info
*info
= route
->route_option
;
978 if (type
!= RMAP_OSPF6
)
985 static struct route_map_rule_cmd ospf6_routemap_rule_set_tag_cmd
= {
986 "tag", ospf6_routemap_rule_set_tag
, route_map_rule_tag_compile
,
987 route_map_rule_tag_free
,
990 static int route_map_command_status(struct vty
*vty
, int ret
)
996 case RMAP_RULE_MISSING
:
997 vty_out(vty
, "OSPF6 Can't find rule.%s", VNL
);
999 case RMAP_COMPILE_ERROR
:
1000 vty_out(vty
, "OSPF6 Argument is malformed.%s", VNL
);
1003 vty_out(vty
, "OSPF6 route-map add set failed.%s", VNL
);
1009 /* add "set metric-type" */
1010 DEFUN (ospf6_routemap_set_metric_type
,
1011 ospf6_routemap_set_metric_type_cmd
,
1012 "set metric-type <type-1|type-2>",
1015 "OSPF6 external type 1 metric\n"
1016 "OSPF6 external type 2 metric\n")
1018 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1019 int idx_external
= 2;
1020 int ret
= route_map_add_set(route_map_index
, "metric-type",
1021 argv
[idx_external
]->arg
);
1022 return route_map_command_status(vty
, ret
);
1025 /* delete "set metric-type" */
1026 DEFUN (ospf6_routemap_no_set_metric_type
,
1027 ospf6_routemap_no_set_metric_type_cmd
,
1028 "no set metric-type [<type-1|type-2>]",
1032 "OSPF6 external type 1 metric\n"
1033 "OSPF6 external type 2 metric\n")
1035 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1036 char *ext
= (argc
== 4) ? argv
[3]->text
: NULL
;
1037 int ret
= route_map_delete_set(route_map_index
, "metric-type", ext
);
1038 return route_map_command_status(vty
, ret
);
1041 /* add "set forwarding-address" */
1042 DEFUN (ospf6_routemap_set_forwarding
,
1043 ospf6_routemap_set_forwarding_cmd
,
1044 "set forwarding-address X:X::X:X",
1046 "Forwarding Address\n"
1049 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1051 int ret
= route_map_add_set(route_map_index
, "forwarding-address",
1052 argv
[idx_ipv6
]->arg
);
1053 return route_map_command_status(vty
, ret
);
1056 /* delete "set forwarding-address" */
1057 DEFUN (ospf6_routemap_no_set_forwarding
,
1058 ospf6_routemap_no_set_forwarding_cmd
,
1059 "no set forwarding-address X:X::X:X",
1062 "Forwarding Address\n"
1065 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1067 int ret
= route_map_delete_set(route_map_index
, "forwarding-address",
1068 argv
[idx_ipv6
]->arg
);
1069 return route_map_command_status(vty
, ret
);
1072 static void ospf6_routemap_init(void)
1076 route_map_add_hook(ospf6_asbr_routemap_update
);
1077 route_map_delete_hook(ospf6_asbr_routemap_update
);
1079 route_map_set_metric_hook(generic_set_add
);
1080 route_map_no_set_metric_hook(generic_set_delete
);
1082 route_map_match_tag_hook(generic_match_add
);
1083 route_map_no_match_tag_hook(generic_match_delete
);
1085 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
1086 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
1088 route_map_match_interface_hook(generic_match_add
);
1089 route_map_no_match_interface_hook(generic_match_delete
);
1091 route_map_install_match(
1092 &ospf6_routemap_rule_match_address_prefixlist_cmd
);
1093 route_map_install_match(&ospf6_routemap_rule_match_interface_cmd
);
1094 route_map_install_match(&ospf6_routemap_rule_match_tag_cmd
);
1096 route_map_install_set(&ospf6_routemap_rule_set_metric_type_cmd
);
1097 route_map_install_set(&ospf6_routemap_rule_set_metric_cmd
);
1098 route_map_install_set(&ospf6_routemap_rule_set_forwarding_cmd
);
1099 route_map_install_set(&ospf6_routemap_rule_set_tag_cmd
);
1101 /* ASE Metric Type (e.g. Type-1/Type-2) */
1102 install_element(RMAP_NODE
, &ospf6_routemap_set_metric_type_cmd
);
1103 install_element(RMAP_NODE
, &ospf6_routemap_no_set_metric_type_cmd
);
1106 install_element(RMAP_NODE
, &ospf6_routemap_set_forwarding_cmd
);
1107 install_element(RMAP_NODE
, &ospf6_routemap_no_set_forwarding_cmd
);
1111 /* Display functions */
1112 static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1113 char *buf
, int buflen
,
1116 struct ospf6_as_external_lsa
*external
;
1117 struct in6_addr in6
;
1118 int prefix_length
= 0;
1121 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
1125 ospf6_prefix_in6_addr(&in6
, &external
->prefix
);
1126 prefix_length
= external
->prefix
.prefix_length
;
1128 in6
= *((struct in6_addr
1129 *)((caddr_t
)external
1131 ospf6_as_external_lsa
)
1132 + OSPF6_PREFIX_SPACE(
1137 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
1139 sprintf(&buf
[strlen(buf
)], "/%d",
1146 static int ospf6_as_external_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
1148 struct ospf6_as_external_lsa
*external
;
1151 assert(lsa
->header
);
1152 external
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
1156 snprintf(buf
, sizeof(buf
), "%c%c%c",
1157 (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_E
) ? 'E'
1159 (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
) ? 'F'
1161 (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
) ? 'T'
1164 vty_out(vty
, " Bits: %s%s", buf
, VNL
);
1165 vty_out(vty
, " Metric: %5lu%s", (u_long
)OSPF6_ASBR_METRIC(external
),
1168 ospf6_prefix_options_printbuf(external
->prefix
.prefix_options
, buf
,
1170 vty_out(vty
, " Prefix Options: %s%s", buf
, VNL
);
1172 vty_out(vty
, " Referenced LSType: %d%s",
1173 ntohs(external
->prefix
.prefix_refer_lstype
), VNL
);
1175 vty_out(vty
, " Prefix: %s%s",
1176 ospf6_as_external_lsa_get_prefix_str(lsa
, buf
, sizeof(buf
), 0),
1179 /* Forwarding-Address */
1180 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_F
)) {
1181 vty_out(vty
, " Forwarding-Address: %s%s",
1182 ospf6_as_external_lsa_get_prefix_str(lsa
, buf
,
1188 if (CHECK_FLAG(external
->bits_metric
, OSPF6_ASBR_BIT_T
)) {
1189 vty_out(vty
, " Tag: %" ROUTE_TAG_PRI
"%s",
1190 ospf6_as_external_lsa_get_tag(lsa
), VNL
);
1196 static void ospf6_asbr_external_route_show(struct vty
*vty
,
1197 struct ospf6_route
*route
)
1199 struct ospf6_external_info
*info
= route
->route_option
;
1200 char prefix
[PREFIX2STR_BUFFER
], id
[16], forwarding
[64];
1203 prefix2str(&route
->prefix
, prefix
, sizeof(prefix
));
1204 tmp_id
= ntohl(info
->id
);
1205 inet_ntop(AF_INET
, &tmp_id
, id
, sizeof(id
));
1206 if (!IN6_IS_ADDR_UNSPECIFIED(&info
->forwarding
))
1207 inet_ntop(AF_INET6
, &info
->forwarding
, forwarding
,
1208 sizeof(forwarding
));
1210 snprintf(forwarding
, sizeof(forwarding
), ":: (ifindex %d)",
1211 ospf6_route_get_first_nh_index(route
));
1213 vty_out(vty
, "%c %-32s %-15s type-%d %5lu %s%s",
1214 zebra_route_char(info
->type
), prefix
, id
,
1215 route
->path
.metric_type
,
1216 (u_long
)(route
->path
.metric_type
== 2 ? route
->path
.u
.cost_e2
1217 : route
->path
.cost
),
1221 DEFUN (show_ipv6_ospf6_redistribute
,
1222 show_ipv6_ospf6_redistribute_cmd
,
1223 "show ipv6 ospf6 redistribute",
1227 "redistributing External information\n"
1230 struct ospf6_route
*route
;
1232 OSPF6_CMD_CHECK_RUNNING();
1234 ospf6_redistribute_show_config(vty
);
1236 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
1237 route
= ospf6_route_next(route
))
1238 ospf6_asbr_external_route_show(vty
, route
);
1243 struct ospf6_lsa_handler as_external_handler
= {
1244 OSPF6_LSTYPE_AS_EXTERNAL
, "AS-External", "ASE",
1245 ospf6_as_external_lsa_show
, ospf6_as_external_lsa_get_prefix_str
};
1247 void ospf6_asbr_init(void)
1249 ospf6_routemap_init();
1251 ospf6_install_lsa_handler(&as_external_handler
);
1253 install_element(VIEW_NODE
, &show_ipv6_ospf6_redistribute_cmd
);
1255 install_element(OSPF6_NODE
, &ospf6_redistribute_cmd
);
1256 install_element(OSPF6_NODE
, &ospf6_redistribute_routemap_cmd
);
1257 install_element(OSPF6_NODE
, &no_ospf6_redistribute_cmd
);
1260 void ospf6_asbr_redistribute_reset(void)
1264 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
1265 if (type
== ZEBRA_ROUTE_OSPF6
)
1267 if (ospf6_zebra_is_redistribute(type
))
1268 ospf6_asbr_redistribute_unset(type
);
1272 void ospf6_asbr_terminate(void)
1277 DEFUN (debug_ospf6_asbr
,
1278 debug_ospf6_asbr_cmd
,
1282 "Debug OSPFv3 ASBR function\n"
1285 OSPF6_DEBUG_ASBR_ON();
1289 DEFUN (no_debug_ospf6_asbr
,
1290 no_debug_ospf6_asbr_cmd
,
1291 "no debug ospf6 asbr",
1295 "Debug OSPFv3 ASBR function\n"
1298 OSPF6_DEBUG_ASBR_OFF();
1302 int config_write_ospf6_debug_asbr(struct vty
*vty
)
1304 if (IS_OSPF6_DEBUG_ASBR
)
1305 vty_out(vty
, "debug ospf6 asbr%s", VNL
);
1309 void install_element_ospf6_debug_asbr()
1311 install_element(ENABLE_NODE
, &debug_ospf6_asbr_cmd
);
1312 install_element(ENABLE_NODE
, &no_debug_ospf6_asbr_cmd
);
1313 install_element(CONFIG_NODE
, &debug_ospf6_asbr_cmd
);
1314 install_element(CONFIG_NODE
, &no_debug_ospf6_asbr_cmd
);