2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "ospf6_proto.h"
35 #include "ospf6_lsa.h"
36 #include "ospf6_lsdb.h"
37 #include "ospf6_route.h"
38 #include "ospf6_zebra.h"
39 #include "ospf6_message.h"
41 #include "ospf6_top.h"
42 #include "ospf6_area.h"
43 #include "ospf6_interface.h"
44 #include "ospf6_neighbor.h"
45 #include "ospf6_asbr.h"
46 #include "ospf6_intra.h"
47 #include "ospf6_flood.h"
50 unsigned char conf_debug_ospf6_asbr
= 0;
52 #define ZROUTE_NAME(x) zebra_route_string(x)
54 /* AS External LSA origination */
56 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
))
69 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
70 zlog_debug ("Originate AS-External-LSA for %s", buf
);
74 memset (buffer
, 0, sizeof (buffer
));
75 lsa_header
= (struct ospf6_lsa_header
*) buffer
;
76 as_external_lsa
= (struct ospf6_as_external_lsa
*)
77 ((caddr_t
) lsa_header
+ sizeof (struct ospf6_lsa_header
));
79 ((caddr_t
) as_external_lsa
+ 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
))
121 memcpy (p
, &info
->forwarding
, sizeof (struct in6_addr
));
122 p
+= sizeof (struct in6_addr
);
125 /* External Route Tag */
126 if (CHECK_FLAG (as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
))
128 route_tag_t network_order
= htonl(info
->tag
);
130 memcpy (p
, &network_order
, sizeof(network_order
));
131 p
+= sizeof(network_order
);
134 /* Fill LSA Header */
136 lsa_header
->type
= htons (OSPF6_LSTYPE_AS_EXTERNAL
);
137 lsa_header
->id
= route
->path
.origin
.id
;
138 lsa_header
->adv_router
= ospf6
->router_id
;
140 ospf6_new_ls_seqnum (lsa_header
->type
, lsa_header
->id
,
141 lsa_header
->adv_router
, ospf6
->lsdb
);
142 lsa_header
->length
= htons ((caddr_t
) p
- (caddr_t
) lsa_header
);
145 ospf6_lsa_checksum (lsa_header
);
148 lsa
= ospf6_lsa_create (lsa_header
);
151 ospf6_lsa_originate_process (lsa
, ospf6
);
155 ospf6_as_external_lsa_get_tag (struct ospf6_lsa
*lsa
)
157 struct ospf6_as_external_lsa
*external
;
158 ptrdiff_t tag_offset
;
159 route_tag_t network_order
;
164 external
= (struct ospf6_as_external_lsa
*)
165 OSPF6_LSA_HEADER_END (lsa
->header
);
167 if (!CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_T
))
170 tag_offset
= sizeof(*external
) + OSPF6_PREFIX_SPACE(external
->prefix
.prefix_length
);
171 if (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_F
))
172 tag_offset
+= sizeof(struct in6_addr
);
174 memcpy(&network_order
, (caddr_t
)external
+ tag_offset
, sizeof(network_order
));
175 return ntohl(network_order
);
179 ospf6_asbr_lsa_add (struct ospf6_lsa
*lsa
)
181 struct ospf6_as_external_lsa
*external
;
182 struct prefix asbr_id
;
183 struct ospf6_route
*asbr_entry
, *route
;
184 char buf
[PREFIX2STR_BUFFER
];
186 external
= (struct ospf6_as_external_lsa
*)
187 OSPF6_LSA_HEADER_END (lsa
->header
);
189 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
190 zlog_debug ("Calculate AS-External route for %s", lsa
->name
);
192 if (lsa
->header
->adv_router
== ospf6
->router_id
)
194 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
195 zlog_debug ("Ignore self-originated AS-External-LSA");
199 if (OSPF6_ASBR_METRIC (external
) == OSPF_LS_INFINITY
)
201 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
202 zlog_debug ("Ignore LSA with LSInfinity Metric");
206 if (CHECK_FLAG(external
->prefix
.prefix_options
, OSPF6_PREFIX_OPTION_NU
))
208 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
209 zlog_debug ("Ignore LSA with NU bit set Metric");
213 ospf6_linkstate_prefix (lsa
->header
->adv_router
, htonl (0), &asbr_id
);
214 asbr_entry
= ospf6_route_lookup (&asbr_id
, ospf6
->brouter_table
);
215 if (asbr_entry
== NULL
||
216 ! CHECK_FLAG (asbr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_E
))
218 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
220 prefix2str (&asbr_id
, buf
, sizeof (buf
));
221 zlog_debug ("ASBR entry not found: %s", buf
);
226 route
= ospf6_route_create ();
227 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
228 route
->prefix
.family
= AF_INET6
;
229 route
->prefix
.prefixlen
= external
->prefix
.prefix_length
;
230 ospf6_prefix_in6_addr (&route
->prefix
.u
.prefix6
, &external
->prefix
);
232 route
->path
.area_id
= asbr_entry
->path
.area_id
;
233 route
->path
.origin
.type
= lsa
->header
->type
;
234 route
->path
.origin
.id
= lsa
->header
->id
;
235 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
237 route
->path
.prefix_options
= external
->prefix
.prefix_options
;
238 if (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_E
))
240 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL2
;
241 route
->path
.metric_type
= 2;
242 route
->path
.cost
= asbr_entry
->path
.cost
;
243 route
->path
.u
.cost_e2
= OSPF6_ASBR_METRIC (external
);
247 route
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL1
;
248 route
->path
.metric_type
= 1;
249 route
->path
.cost
= asbr_entry
->path
.cost
+ OSPF6_ASBR_METRIC (external
);
250 route
->path
.u
.cost_e2
= 0;
253 route
->path
.tag
= ospf6_as_external_lsa_get_tag (lsa
);
255 ospf6_route_copy_nexthops (route
, asbr_entry
);
257 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
259 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
260 zlog_debug ("AS-External route add: %s", buf
);
263 ospf6_route_add (route
, ospf6
->route_table
);
267 ospf6_asbr_lsa_remove (struct ospf6_lsa
*lsa
)
269 struct ospf6_as_external_lsa
*external
;
270 struct prefix prefix
;
271 struct ospf6_route
*route
, *nroute
;
272 char buf
[PREFIX2STR_BUFFER
];
274 external
= (struct ospf6_as_external_lsa
*)
275 OSPF6_LSA_HEADER_END (lsa
->header
);
277 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
278 zlog_debug ("Withdraw AS-External route for %s", lsa
->name
);
280 if (lsa
->header
->adv_router
== ospf6
->router_id
)
282 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
283 zlog_debug ("Ignore self-originated AS-External-LSA");
287 memset (&prefix
, 0, sizeof (struct prefix
));
288 prefix
.family
= AF_INET6
;
289 prefix
.prefixlen
= external
->prefix
.prefix_length
;
290 ospf6_prefix_in6_addr (&prefix
.u
.prefix6
, &external
->prefix
);
292 route
= ospf6_route_lookup (&prefix
, ospf6
->route_table
);
295 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
297 prefix2str (&prefix
, buf
, sizeof (buf
));
298 zlog_debug ("AS-External route %s not found", buf
);
303 for (ospf6_route_lock (route
);
304 route
&& ospf6_route_is_prefix (&prefix
, route
);
307 nroute
= ospf6_route_next (route
);
308 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
310 if (route
->path
.origin
.type
!= lsa
->header
->type
)
312 if (route
->path
.origin
.id
!= lsa
->header
->id
)
314 if (route
->path
.origin
.adv_router
!= lsa
->header
->adv_router
)
317 if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL
))
319 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
320 zlog_debug ("AS-External route remove: %s", buf
);
322 ospf6_route_remove (route
, ospf6
->route_table
);
325 ospf6_route_unlock (route
);
329 ospf6_asbr_lsentry_add (struct ospf6_route
*asbr_entry
)
331 struct ospf6_lsa
*lsa
;
335 if (! CHECK_FLAG (asbr_entry
->flag
, OSPF6_ROUTE_BEST
))
338 inet_ntop (AF_INET
, &ADV_ROUTER_IN_PREFIX (&asbr_entry
->prefix
),
340 zlog_info ("ignore non-best path: lsentry %s add", buf
);
344 type
= htons (OSPF6_LSTYPE_AS_EXTERNAL
);
345 router
= ospf6_linkstate_prefix_adv_router (&asbr_entry
->prefix
);
346 for (lsa
= ospf6_lsdb_type_router_head (type
, router
, ospf6
->lsdb
); lsa
;
347 lsa
= ospf6_lsdb_type_router_next (type
, router
, lsa
))
349 if (! OSPF6_LSA_IS_MAXAGE (lsa
))
350 ospf6_asbr_lsa_add (lsa
);
355 ospf6_asbr_lsentry_remove (struct ospf6_route
*asbr_entry
)
357 struct ospf6_lsa
*lsa
;
361 type
= htons (OSPF6_LSTYPE_AS_EXTERNAL
);
362 router
= ospf6_linkstate_prefix_adv_router (&asbr_entry
->prefix
);
363 for (lsa
= ospf6_lsdb_type_router_head (type
, router
, ospf6
->lsdb
);
364 lsa
; lsa
= ospf6_lsdb_type_router_next (type
, router
, lsa
))
365 ospf6_asbr_lsa_remove (lsa
);
370 /* redistribute function */
373 ospf6_asbr_routemap_set (int type
, const char *mapname
)
375 if (ospf6
->rmap
[type
].name
)
376 free (ospf6
->rmap
[type
].name
);
377 ospf6
->rmap
[type
].name
= strdup (mapname
);
378 ospf6
->rmap
[type
].map
= route_map_lookup_by_name (mapname
);
382 ospf6_asbr_routemap_unset (int type
)
384 if (ospf6
->rmap
[type
].name
)
385 free (ospf6
->rmap
[type
].name
);
386 ospf6
->rmap
[type
].name
= NULL
;
387 ospf6
->rmap
[type
].map
= NULL
;
391 ospf6_asbr_routemap_update (const char *mapname
)
398 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
400 if (ospf6
->rmap
[type
].name
)
401 ospf6
->rmap
[type
].map
=
402 route_map_lookup_by_name (ospf6
->rmap
[type
].name
);
404 ospf6
->rmap
[type
].map
= NULL
;
409 ospf6_asbr_is_asbr (struct ospf6
*o
)
411 return o
->external_table
->count
;
415 ospf6_asbr_redistribute_set (int type
)
417 ospf6_zebra_redistribute (type
);
421 ospf6_asbr_redistribute_unset (int type
)
423 struct ospf6_route
*route
;
424 struct ospf6_external_info
*info
;
426 ospf6_zebra_no_redistribute (type
);
428 for (route
= ospf6_route_head (ospf6
->external_table
); route
;
429 route
= ospf6_route_next (route
))
431 info
= route
->route_option
;
432 if (info
->type
!= type
)
435 ospf6_asbr_redistribute_remove (info
->type
, 0, &route
->prefix
);
438 ospf6_asbr_routemap_unset (type
);
441 /* When an area is unstubified, flood all the external LSAs in the area */
443 ospf6_asbr_send_externals_to_area (struct ospf6_area
*oa
)
445 struct ospf6_lsa
*lsa
;
447 for (lsa
= ospf6_lsdb_head (oa
->ospf6
->lsdb
); lsa
;
448 lsa
= ospf6_lsdb_next (lsa
))
450 if (ntohs (lsa
->header
->type
) == OSPF6_LSTYPE_AS_EXTERNAL
)
452 zlog_debug ("%s: Flooding AS-External LSA %s\n", __func__
, lsa
->name
);
453 ospf6_flood_area (NULL
, lsa
, oa
);
459 ospf6_asbr_redistribute_add (int type
, ifindex_t ifindex
, struct prefix
*prefix
,
460 u_int nexthop_num
, struct in6_addr
*nexthop
, route_tag_t tag
)
463 struct ospf6_route troute
;
464 struct ospf6_external_info tinfo
;
465 struct ospf6_route
*route
, *match
;
466 struct ospf6_external_info
*info
;
467 struct prefix prefix_id
;
468 struct route_node
*node
;
469 char pbuf
[PREFIX2STR_BUFFER
], ibuf
[16];
470 struct listnode
*lnode
, *lnnode
;
471 struct ospf6_area
*oa
;
473 if (! ospf6_zebra_is_redistribute (type
))
476 if (IS_OSPF6_DEBUG_ASBR
)
478 prefix2str (prefix
, pbuf
, sizeof (pbuf
));
479 zlog_debug ("Redistribute %s (%s)", pbuf
, ZROUTE_NAME (type
));
482 /* if route-map was specified but not found, do not advertise */
483 if (ospf6
->rmap
[type
].name
)
485 if (ospf6
->rmap
[type
].map
== NULL
)
486 ospf6_asbr_routemap_update (NULL
);
487 if (ospf6
->rmap
[type
].map
== NULL
)
489 zlog_warn ("route-map \"%s\" not found, suppress redistributing",
490 ospf6
->rmap
[type
].name
);
495 /* apply route-map */
496 if (ospf6
->rmap
[type
].map
)
498 memset (&troute
, 0, sizeof (troute
));
499 memset (&tinfo
, 0, sizeof (tinfo
));
500 troute
.route_option
= &tinfo
;
501 tinfo
.ifindex
= ifindex
;
504 ret
= route_map_apply (ospf6
->rmap
[type
].map
, prefix
,
505 RMAP_OSPF6
, &troute
);
506 if (ret
== RMAP_DENYMATCH
)
508 if (IS_OSPF6_DEBUG_ASBR
)
509 zlog_debug ("Denied by route-map \"%s\"", ospf6
->rmap
[type
].name
);
514 match
= ospf6_route_lookup (prefix
, ospf6
->external_table
);
517 info
= match
->route_option
;
519 /* copy result of route-map */
520 if (ospf6
->rmap
[type
].map
)
522 if (troute
.path
.metric_type
)
523 match
->path
.metric_type
= troute
.path
.metric_type
;
524 if (troute
.path
.cost
)
525 match
->path
.cost
= troute
.path
.cost
;
526 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo
.forwarding
))
527 memcpy (&info
->forwarding
, &tinfo
.forwarding
,
528 sizeof (struct in6_addr
));
529 info
->tag
= tinfo
.tag
;
533 /* If there is no route-map, simply update the tag */
539 if (nexthop_num
&& nexthop
)
540 ospf6_route_add_nexthop (match
, ifindex
, nexthop
);
542 ospf6_route_add_nexthop (match
, ifindex
, NULL
);
544 /* create/update binding in external_id_table */
545 prefix_id
.family
= AF_INET
;
546 prefix_id
.prefixlen
= 32;
547 prefix_id
.u
.prefix4
.s_addr
= htonl (info
->id
);
548 node
= route_node_get (ospf6
->external_id_table
, &prefix_id
);
551 if (IS_OSPF6_DEBUG_ASBR
)
553 inet_ntop (AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof (ibuf
));
554 zlog_debug ("Advertise as AS-External Id:%s", ibuf
);
557 match
->path
.origin
.id
= htonl (info
->id
);
558 ospf6_as_external_lsa_originate (match
);
562 /* create new entry */
563 route
= ospf6_route_create ();
564 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
565 memcpy (&route
->prefix
, prefix
, sizeof (struct prefix
));
567 info
= (struct ospf6_external_info
*)
568 XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO
, sizeof (struct ospf6_external_info
));
569 route
->route_option
= info
;
570 info
->id
= ospf6
->external_id
++;
572 /* copy result of route-map */
573 if (ospf6
->rmap
[type
].map
)
575 if (troute
.path
.metric_type
)
576 route
->path
.metric_type
= troute
.path
.metric_type
;
577 if (troute
.path
.cost
)
578 route
->path
.cost
= troute
.path
.cost
;
579 if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo
.forwarding
))
580 memcpy (&info
->forwarding
, &tinfo
.forwarding
,
581 sizeof (struct in6_addr
));
582 info
->tag
= tinfo
.tag
;
586 /* If there is no route-map, simply set the tag */
591 if (nexthop_num
&& nexthop
)
592 ospf6_route_add_nexthop (route
, ifindex
, nexthop
);
594 ospf6_route_add_nexthop (route
, ifindex
, NULL
);
596 /* create/update binding in external_id_table */
597 prefix_id
.family
= AF_INET
;
598 prefix_id
.prefixlen
= 32;
599 prefix_id
.u
.prefix4
.s_addr
= htonl (info
->id
);
600 node
= route_node_get (ospf6
->external_id_table
, &prefix_id
);
603 route
= ospf6_route_add (route
, ospf6
->external_table
);
604 route
->route_option
= info
;
606 if (IS_OSPF6_DEBUG_ASBR
)
608 inet_ntop (AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof (ibuf
));
609 zlog_debug ("Advertise as AS-External Id:%s", ibuf
);
612 route
->path
.origin
.id
= htonl (info
->id
);
613 ospf6_as_external_lsa_originate (route
);
615 /* Router-Bit (ASBR Flag) may have to be updated */
616 for (ALL_LIST_ELEMENTS (ospf6
->area_list
, lnode
, lnnode
, oa
))
617 OSPF6_ROUTER_LSA_SCHEDULE (oa
);
621 ospf6_asbr_redistribute_remove (int type
, ifindex_t ifindex
,
622 struct prefix
*prefix
)
624 struct ospf6_route
*match
;
625 struct ospf6_external_info
*info
= NULL
;
626 struct route_node
*node
;
627 struct ospf6_lsa
*lsa
;
628 struct prefix prefix_id
;
629 char pbuf
[PREFIX2STR_BUFFER
], ibuf
[16];
630 struct listnode
*lnode
, *lnnode
;
631 struct ospf6_area
*oa
;
633 match
= ospf6_route_lookup (prefix
, ospf6
->external_table
);
636 if (IS_OSPF6_DEBUG_ASBR
)
638 prefix2str (prefix
, pbuf
, sizeof (pbuf
));
639 zlog_debug ("No such route %s to withdraw", pbuf
);
644 info
= match
->route_option
;
647 if (info
->type
!= type
)
649 if (IS_OSPF6_DEBUG_ASBR
)
651 prefix2str (prefix
, pbuf
, sizeof (pbuf
));
652 zlog_debug ("Original protocol mismatch: %s", pbuf
);
657 if (IS_OSPF6_DEBUG_ASBR
)
659 prefix2str (prefix
, pbuf
, sizeof (pbuf
));
660 inet_ntop (AF_INET
, &prefix_id
.u
.prefix4
, ibuf
, sizeof (ibuf
));
661 zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf
, ibuf
);
664 lsa
= ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL
),
665 htonl (info
->id
), ospf6
->router_id
, ospf6
->lsdb
);
667 ospf6_lsa_purge (lsa
);
669 /* remove binding in external_id_table */
670 prefix_id
.family
= AF_INET
;
671 prefix_id
.prefixlen
= 32;
672 prefix_id
.u
.prefix4
.s_addr
= htonl (info
->id
);
673 node
= route_node_lookup (ospf6
->external_id_table
, &prefix_id
);
676 route_unlock_node (node
);
678 ospf6_route_remove (match
, ospf6
->external_table
);
679 XFREE (MTYPE_OSPF6_EXTERNAL_INFO
, info
);
681 /* Router-Bit (ASBR Flag) may have to be updated */
682 for (ALL_LIST_ELEMENTS (ospf6
->area_list
, lnode
, lnnode
, oa
))
683 OSPF6_ROUTER_LSA_SCHEDULE (oa
);
686 DEFUN (ospf6_redistribute
,
687 ospf6_redistribute_cmd
,
688 "redistribute " FRR_REDIST_STR_OSPF6D
,
690 FRR_REDIST_HELP_STR_OSPF6D
)
694 char *proto
= argv
[argc
- 1]->text
;
695 type
= proto_redistnum(AFI_IP6
, proto
);
699 ospf6_asbr_redistribute_unset (type
);
700 ospf6_asbr_redistribute_set (type
);
704 DEFUN (ospf6_redistribute_routemap
,
705 ospf6_redistribute_routemap_cmd
,
706 "redistribute " FRR_REDIST_STR_OSPF6D
" route-map WORD",
708 FRR_REDIST_HELP_STR_OSPF6D
709 "Route map reference\n"
712 int idx_protocol
= 1;
716 char *proto
= argv
[idx_protocol
]->text
;
717 type
= proto_redistnum(AFI_IP6
, proto
);
721 ospf6_asbr_redistribute_unset (type
);
722 ospf6_asbr_routemap_set (type
, argv
[idx_word
]->arg
);
723 ospf6_asbr_redistribute_set (type
);
727 DEFUN (no_ospf6_redistribute
,
728 no_ospf6_redistribute_cmd
,
729 "no redistribute " FRR_REDIST_STR_OSPF6D
" [route-map WORD]",
732 FRR_REDIST_HELP_STR_OSPF6D
733 "Route map reference\n"
736 int idx_protocol
= 2;
739 char *proto
= argv
[idx_protocol
]->text
;
740 type
= proto_redistnum(AFI_IP6
, proto
);
744 ospf6_asbr_redistribute_unset (type
);
750 ospf6_redistribute_config_write (struct vty
*vty
)
754 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
756 if (type
== ZEBRA_ROUTE_OSPF6
)
758 if (! ospf6_zebra_is_redistribute (type
))
761 if (ospf6
->rmap
[type
].name
)
762 vty_out (vty
, " redistribute %s route-map %s%s",
763 ZROUTE_NAME (type
), ospf6
->rmap
[type
].name
, VNL
);
765 vty_out (vty
, " redistribute %s%s",
766 ZROUTE_NAME (type
), VNL
);
773 ospf6_redistribute_show_config (struct vty
*vty
)
776 int nroute
[ZEBRA_ROUTE_MAX
];
778 struct ospf6_route
*route
;
779 struct ospf6_external_info
*info
;
782 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
784 for (route
= ospf6_route_head (ospf6
->external_table
); route
;
785 route
= ospf6_route_next (route
))
787 info
= route
->route_option
;
788 nroute
[info
->type
]++;
792 vty_out (vty
, "Redistributing External Routes from:%s", VNL
);
793 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
795 if (type
== ZEBRA_ROUTE_OSPF6
)
797 if (! ospf6_zebra_is_redistribute (type
))
800 if (ospf6
->rmap
[type
].name
)
801 vty_out (vty
, " %d: %s with route-map \"%s\"%s%s", nroute
[type
],
802 ZROUTE_NAME (type
), ospf6
->rmap
[type
].name
,
803 (ospf6
->rmap
[type
].map
? "" : " (not found !)"),
806 vty_out (vty
, " %d: %s%s", nroute
[type
],
807 ZROUTE_NAME (type
), VNL
);
809 vty_out (vty
, "Total %d routes%s", total
, VNL
);
814 /* Routemap Functions */
815 static route_map_result_t
816 ospf6_routemap_rule_match_address_prefixlist (void *rule
,
817 struct prefix
*prefix
,
818 route_map_object_t type
,
821 struct prefix_list
*plist
;
823 if (type
!= RMAP_OSPF6
)
826 plist
= prefix_list_lookup (AFI_IP6
, (char *) rule
);
830 return (prefix_list_apply (plist
, prefix
) == PREFIX_DENY
?
831 RMAP_NOMATCH
: RMAP_MATCH
);
835 ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg
)
837 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
841 ospf6_routemap_rule_match_address_prefixlist_free (void *rule
)
843 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
846 struct route_map_rule_cmd
847 ospf6_routemap_rule_match_address_prefixlist_cmd
=
849 "ipv6 address prefix-list",
850 ospf6_routemap_rule_match_address_prefixlist
,
851 ospf6_routemap_rule_match_address_prefixlist_compile
,
852 ospf6_routemap_rule_match_address_prefixlist_free
,
855 /* `match interface IFNAME' */
856 /* Match function should return 1 if match is success else return
858 static route_map_result_t
859 ospf6_routemap_rule_match_interface (void *rule
, struct prefix
*prefix
,
860 route_map_object_t type
, void *object
)
862 struct interface
*ifp
;
863 struct ospf6_external_info
*ei
;
865 if (type
== RMAP_OSPF6
)
867 ei
= ((struct ospf6_route
*) object
)->route_option
;
868 ifp
= if_lookup_by_name ((char *)rule
, VRF_DEFAULT
);
871 && ei
->ifindex
== ifp
->ifindex
)
878 /* Route map `interface' match statement. `arg' should be
881 ospf6_routemap_rule_match_interface_compile (const char *arg
)
883 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
886 /* Free route map's compiled `interface' value. */
888 ospf6_routemap_rule_match_interface_free (void *rule
)
890 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
893 /* Route map commands for interface matching. */
894 struct route_map_rule_cmd
895 ospf6_routemap_rule_match_interface_cmd
=
898 ospf6_routemap_rule_match_interface
,
899 ospf6_routemap_rule_match_interface_compile
,
900 ospf6_routemap_rule_match_interface_free
903 /* Match function for matching route tags */
904 static route_map_result_t
905 ospf6_routemap_rule_match_tag (void *rule
, struct prefix
*prefix
,
906 route_map_object_t type
, void *object
)
908 route_tag_t
*tag
= rule
;
909 struct ospf6_route
*route
= object
;
910 struct ospf6_external_info
*info
= route
->route_option
;
912 if (type
== RMAP_OSPF6
&& info
->tag
== *tag
)
918 static struct route_map_rule_cmd
919 ospf6_routemap_rule_match_tag_cmd
=
922 ospf6_routemap_rule_match_tag
,
923 route_map_rule_tag_compile
,
924 route_map_rule_tag_free
,
927 static route_map_result_t
928 ospf6_routemap_rule_set_metric_type (void *rule
, struct prefix
*prefix
,
929 route_map_object_t type
, void *object
)
931 char *metric_type
= rule
;
932 struct ospf6_route
*route
= object
;
934 if (type
!= RMAP_OSPF6
)
937 if (strcmp (metric_type
, "type-2") == 0)
938 route
->path
.metric_type
= 2;
940 route
->path
.metric_type
= 1;
946 ospf6_routemap_rule_set_metric_type_compile (const char *arg
)
948 if (strcmp (arg
, "type-2") && strcmp (arg
, "type-1"))
950 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
954 ospf6_routemap_rule_set_metric_type_free (void *rule
)
956 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
959 struct route_map_rule_cmd
960 ospf6_routemap_rule_set_metric_type_cmd
=
963 ospf6_routemap_rule_set_metric_type
,
964 ospf6_routemap_rule_set_metric_type_compile
,
965 ospf6_routemap_rule_set_metric_type_free
,
968 static route_map_result_t
969 ospf6_routemap_rule_set_metric (void *rule
, struct prefix
*prefix
,
970 route_map_object_t type
, void *object
)
973 struct ospf6_route
*route
= object
;
975 if (type
!= RMAP_OSPF6
)
978 route
->path
.cost
= atoi (metric
);
983 ospf6_routemap_rule_set_metric_compile (const char *arg
)
987 metric
= strtoul (arg
, &endp
, 0);
988 if (metric
> OSPF_LS_INFINITY
|| *endp
!= '\0')
990 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
994 ospf6_routemap_rule_set_metric_free (void *rule
)
996 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
999 struct route_map_rule_cmd
1000 ospf6_routemap_rule_set_metric_cmd
=
1003 ospf6_routemap_rule_set_metric
,
1004 ospf6_routemap_rule_set_metric_compile
,
1005 ospf6_routemap_rule_set_metric_free
,
1008 static route_map_result_t
1009 ospf6_routemap_rule_set_forwarding (void *rule
, struct prefix
*prefix
,
1010 route_map_object_t type
, void *object
)
1012 char *forwarding
= rule
;
1013 struct ospf6_route
*route
= object
;
1014 struct ospf6_external_info
*info
= route
->route_option
;
1016 if (type
!= RMAP_OSPF6
)
1019 if (inet_pton (AF_INET6
, forwarding
, &info
->forwarding
) != 1)
1021 memset (&info
->forwarding
, 0, sizeof (struct in6_addr
));
1029 ospf6_routemap_rule_set_forwarding_compile (const char *arg
)
1032 if (inet_pton (AF_INET6
, arg
, &a
) != 1)
1034 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
1038 ospf6_routemap_rule_set_forwarding_free (void *rule
)
1040 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
1043 struct route_map_rule_cmd
1044 ospf6_routemap_rule_set_forwarding_cmd
=
1046 "forwarding-address",
1047 ospf6_routemap_rule_set_forwarding
,
1048 ospf6_routemap_rule_set_forwarding_compile
,
1049 ospf6_routemap_rule_set_forwarding_free
,
1052 static route_map_result_t
1053 ospf6_routemap_rule_set_tag (void *rule
, struct prefix
*prefix
,
1054 route_map_object_t type
, void *object
)
1056 route_tag_t
*tag
= rule
;
1057 struct ospf6_route
*route
= object
;
1058 struct ospf6_external_info
*info
= route
->route_option
;
1060 if (type
!= RMAP_OSPF6
)
1067 static struct route_map_rule_cmd
1068 ospf6_routemap_rule_set_tag_cmd
=
1071 ospf6_routemap_rule_set_tag
,
1072 route_map_rule_tag_compile
,
1073 route_map_rule_tag_free
,
1077 route_map_command_status (struct vty
*vty
, int ret
)
1084 case RMAP_RULE_MISSING
:
1085 vty_out (vty
, "OSPF6 Can't find rule.%s", VNL
);
1087 case RMAP_COMPILE_ERROR
:
1088 vty_out (vty
, "OSPF6 Argument is malformed.%s", VNL
);
1091 vty_out (vty
, "OSPF6 route-map add set failed.%s", VNL
);
1097 /* add "set metric-type" */
1098 DEFUN (ospf6_routemap_set_metric_type
,
1099 ospf6_routemap_set_metric_type_cmd
,
1100 "set metric-type <type-1|type-2>",
1103 "OSPF6 external type 1 metric\n"
1104 "OSPF6 external type 2 metric\n")
1106 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1107 int idx_external
= 2;
1108 int ret
= route_map_add_set (route_map_index
,
1109 "metric-type", argv
[idx_external
]->arg
);
1110 return route_map_command_status (vty
, ret
);
1113 /* delete "set metric-type" */
1114 DEFUN (ospf6_routemap_no_set_metric_type
,
1115 ospf6_routemap_no_set_metric_type_cmd
,
1116 "no set metric-type [<type-1|type-2>]",
1120 "OSPF6 external type 1 metric\n"
1121 "OSPF6 external type 2 metric\n")
1123 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1124 char *ext
= (argc
== 4) ? argv
[3]->text
: NULL
;
1125 int ret
= route_map_delete_set (route_map_index
,
1126 "metric-type", ext
);
1127 return route_map_command_status (vty
, ret
);
1130 /* add "set forwarding-address" */
1131 DEFUN (ospf6_routemap_set_forwarding
,
1132 ospf6_routemap_set_forwarding_cmd
,
1133 "set forwarding-address X:X::X:X",
1135 "Forwarding Address\n"
1138 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1140 int ret
= route_map_add_set (route_map_index
,
1141 "forwarding-address", argv
[idx_ipv6
]->arg
);
1142 return route_map_command_status (vty
, ret
);
1145 /* delete "set forwarding-address" */
1146 DEFUN (ospf6_routemap_no_set_forwarding
,
1147 ospf6_routemap_no_set_forwarding_cmd
,
1148 "no set forwarding-address X:X::X:X",
1151 "Forwarding Address\n"
1154 VTY_DECLVAR_CONTEXT(route_map_index
, route_map_index
);
1156 int ret
= route_map_delete_set (route_map_index
,
1157 "forwarding-address", argv
[idx_ipv6
]->arg
);
1158 return route_map_command_status (vty
, ret
);
1162 ospf6_routemap_init (void)
1166 route_map_add_hook (ospf6_asbr_routemap_update
);
1167 route_map_delete_hook (ospf6_asbr_routemap_update
);
1169 route_map_set_metric_hook (generic_set_add
);
1170 route_map_no_set_metric_hook (generic_set_delete
);
1172 route_map_match_tag_hook (generic_match_add
);
1173 route_map_no_match_tag_hook (generic_match_delete
);
1175 route_map_match_ipv6_address_prefix_list_hook (generic_match_add
);
1176 route_map_no_match_ipv6_address_prefix_list_hook (generic_match_delete
);
1178 route_map_match_interface_hook (generic_match_add
);
1179 route_map_no_match_interface_hook (generic_match_delete
);
1181 route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd
);
1182 route_map_install_match (&ospf6_routemap_rule_match_interface_cmd
);
1183 route_map_install_match (&ospf6_routemap_rule_match_tag_cmd
);
1185 route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd
);
1186 route_map_install_set (&ospf6_routemap_rule_set_metric_cmd
);
1187 route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd
);
1188 route_map_install_set (&ospf6_routemap_rule_set_tag_cmd
);
1190 /* ASE Metric Type (e.g. Type-1/Type-2) */
1191 install_element (RMAP_NODE
, &ospf6_routemap_set_metric_type_cmd
);
1192 install_element (RMAP_NODE
, &ospf6_routemap_no_set_metric_type_cmd
);
1195 install_element (RMAP_NODE
, &ospf6_routemap_set_forwarding_cmd
);
1196 install_element (RMAP_NODE
, &ospf6_routemap_no_set_forwarding_cmd
);
1200 /* Display functions */
1202 ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa
*lsa
, char *buf
,
1203 int buflen
, int pos
)
1205 struct ospf6_as_external_lsa
*external
;
1206 struct in6_addr in6
;
1207 int prefix_length
= 0;
1211 external
= (struct ospf6_as_external_lsa
*)
1212 OSPF6_LSA_HEADER_END (lsa
->header
);
1216 ospf6_prefix_in6_addr (&in6
, &external
->prefix
);
1217 prefix_length
= external
->prefix
.prefix_length
;
1220 in6
= *((struct in6_addr
*)
1221 ((caddr_t
) external
+ sizeof (struct ospf6_as_external_lsa
) +
1222 OSPF6_PREFIX_SPACE (external
->prefix
.prefix_length
)));
1226 inet_ntop (AF_INET6
, &in6
, buf
, buflen
);
1228 sprintf (&buf
[strlen(buf
)], "/%d", prefix_length
);
1235 ospf6_as_external_lsa_show (struct vty
*vty
, struct ospf6_lsa
*lsa
)
1237 struct ospf6_as_external_lsa
*external
;
1240 assert (lsa
->header
);
1241 external
= (struct ospf6_as_external_lsa
*)
1242 OSPF6_LSA_HEADER_END (lsa
->header
);
1245 snprintf (buf
, sizeof (buf
), "%c%c%c",
1246 (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_E
) ? 'E' : '-'),
1247 (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_F
) ? 'F' : '-'),
1248 (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_T
) ? 'T' : '-'));
1250 vty_out (vty
, " Bits: %s%s", buf
, VNL
);
1251 vty_out (vty
, " Metric: %5lu%s", (u_long
) OSPF6_ASBR_METRIC (external
),
1254 ospf6_prefix_options_printbuf (external
->prefix
.prefix_options
,
1256 vty_out (vty
, " Prefix Options: %s%s", buf
,
1259 vty_out (vty
, " Referenced LSType: %d%s",
1260 ntohs (external
->prefix
.prefix_refer_lstype
),
1263 vty_out (vty
, " Prefix: %s%s",
1264 ospf6_as_external_lsa_get_prefix_str (lsa
, buf
, sizeof(buf
), 0), VNL
);
1266 /* Forwarding-Address */
1267 if (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_F
))
1269 vty_out (vty
, " Forwarding-Address: %s%s",
1270 ospf6_as_external_lsa_get_prefix_str (lsa
, buf
, sizeof(buf
), 1),
1275 if (CHECK_FLAG (external
->bits_metric
, OSPF6_ASBR_BIT_T
))
1277 vty_out (vty
, " Tag: %"ROUTE_TAG_PRI
"%s",
1278 ospf6_as_external_lsa_get_tag (lsa
), VNL
);
1285 ospf6_asbr_external_route_show (struct vty
*vty
, struct ospf6_route
*route
)
1287 struct ospf6_external_info
*info
= route
->route_option
;
1288 char prefix
[PREFIX2STR_BUFFER
], id
[16], forwarding
[64];
1291 prefix2str (&route
->prefix
, prefix
, sizeof (prefix
));
1292 tmp_id
= ntohl (info
->id
);
1293 inet_ntop (AF_INET
, &tmp_id
, id
, sizeof (id
));
1294 if (! IN6_IS_ADDR_UNSPECIFIED (&info
->forwarding
))
1295 inet_ntop (AF_INET6
, &info
->forwarding
, forwarding
, sizeof (forwarding
));
1297 snprintf (forwarding
, sizeof (forwarding
), ":: (ifindex %d)",
1298 ospf6_route_get_first_nh_index (route
));
1300 vty_out (vty
, "%c %-32s %-15s type-%d %5lu %s%s",
1301 zebra_route_char(info
->type
),
1302 prefix
, id
, route
->path
.metric_type
,
1303 (u_long
) (route
->path
.metric_type
== 2 ?
1304 route
->path
.u
.cost_e2
: route
->path
.cost
),
1308 DEFUN (show_ipv6_ospf6_redistribute
,
1309 show_ipv6_ospf6_redistribute_cmd
,
1310 "show ipv6 ospf6 redistribute",
1314 "redistributing External information\n"
1317 struct ospf6_route
*route
;
1319 OSPF6_CMD_CHECK_RUNNING ();
1321 ospf6_redistribute_show_config (vty
);
1323 for (route
= ospf6_route_head (ospf6
->external_table
); route
;
1324 route
= ospf6_route_next (route
))
1325 ospf6_asbr_external_route_show (vty
, route
);
1330 struct ospf6_lsa_handler as_external_handler
=
1332 OSPF6_LSTYPE_AS_EXTERNAL
,
1335 ospf6_as_external_lsa_show
,
1336 ospf6_as_external_lsa_get_prefix_str
1340 ospf6_asbr_init (void)
1342 ospf6_routemap_init ();
1344 ospf6_install_lsa_handler (&as_external_handler
);
1346 install_element (VIEW_NODE
, &show_ipv6_ospf6_redistribute_cmd
);
1348 install_element (OSPF6_NODE
, &ospf6_redistribute_cmd
);
1349 install_element (OSPF6_NODE
, &ospf6_redistribute_routemap_cmd
);
1350 install_element (OSPF6_NODE
, &no_ospf6_redistribute_cmd
);
1354 ospf6_asbr_redistribute_reset (void)
1358 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++)
1360 if (type
== ZEBRA_ROUTE_OSPF6
)
1362 if (ospf6_zebra_is_redistribute (type
))
1363 ospf6_asbr_redistribute_unset(type
);
1368 ospf6_asbr_terminate (void)
1370 route_map_finish ();
1373 DEFUN (debug_ospf6_asbr
,
1374 debug_ospf6_asbr_cmd
,
1378 "Debug OSPFv3 ASBR function\n"
1381 OSPF6_DEBUG_ASBR_ON ();
1385 DEFUN (no_debug_ospf6_asbr
,
1386 no_debug_ospf6_asbr_cmd
,
1387 "no debug ospf6 asbr",
1391 "Debug OSPFv3 ASBR function\n"
1394 OSPF6_DEBUG_ASBR_OFF ();
1399 config_write_ospf6_debug_asbr (struct vty
*vty
)
1401 if (IS_OSPF6_DEBUG_ASBR
)
1402 vty_out (vty
, "debug ospf6 asbr%s", VNL
);
1407 install_element_ospf6_debug_asbr ()
1409 install_element (ENABLE_NODE
, &debug_ospf6_asbr_cmd
);
1410 install_element (ENABLE_NODE
, &no_debug_ospf6_asbr_cmd
);
1411 install_element (CONFIG_NODE
, &debug_ospf6_asbr_cmd
);
1412 install_element (CONFIG_NODE
, &no_debug_ospf6_asbr_cmd
);