Annotation of embedaddon/quagga/ospf6d/ospf6_asbr.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2003 Yasuhiro Ohara
3: *
4: * This file is part of GNU Zebra.
5: *
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
9: * later version.
10: *
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.
15: *
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.
20: */
21:
22: #include <zebra.h>
23:
24: #include "log.h"
25: #include "memory.h"
26: #include "prefix.h"
27: #include "command.h"
28: #include "vty.h"
29: #include "routemap.h"
30: #include "table.h"
31: #include "plist.h"
32: #include "thread.h"
33: #include "linklist.h"
34:
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:
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"
49: #include "ospf6d.h"
50:
51: unsigned char conf_debug_ospf6_asbr = 0;
52:
53: #define ZROUTE_NAME(x) zebra_route_string(x)
54:
55: /* AS External LSA origination */
56: static void
57: ospf6_as_external_lsa_originate (struct ospf6_route *route)
58: {
59: char buffer[OSPF6_MAX_LSASIZE];
60: struct ospf6_lsa_header *lsa_header;
61: struct ospf6_lsa *old, *lsa;
62: struct ospf6_external_info *info = route->route_option;
63:
64: struct ospf6_as_external_lsa *as_external_lsa;
65: char buf[64];
66: caddr_t p;
67:
68: /* find previous LSA */
69: old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
70: route->path.origin.id, ospf6->router_id,
71: ospf6->lsdb);
72:
73: if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL))
74: {
75: prefix2str (&route->prefix, buf, sizeof (buf));
76: zlog_debug ("Originate AS-External-LSA for %s", buf);
77: }
78:
79: /* prepare buffer */
80: memset (buffer, 0, sizeof (buffer));
81: lsa_header = (struct ospf6_lsa_header *) buffer;
82: as_external_lsa = (struct ospf6_as_external_lsa *)
83: ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
84: p = (caddr_t)
85: ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa));
86:
87: /* Fill AS-External-LSA */
88: /* Metric type */
89: if (route->path.metric_type == 2)
90: SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
91: else
92: UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
93:
94: /* forwarding address */
95: if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
96: SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
97: else
98: UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
99:
100: /* external route tag */
101: UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
102:
103: /* Set metric */
104: OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);
105:
106: /* prefixlen */
107: as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
108:
109: /* PrefixOptions */
110: as_external_lsa->prefix.prefix_options = route->path.prefix_options;
111:
112: /* don't use refer LS-type */
113: as_external_lsa->prefix.prefix_refer_lstype = htons (0);
114:
115: /* set Prefix */
116: memcpy (p, &route->prefix.u.prefix6,
117: OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
118: ospf6_prefix_apply_mask (&as_external_lsa->prefix);
119: p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
120:
121: /* Forwarding address */
122: if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
123: {
124: memcpy (p, &info->forwarding, sizeof (struct in6_addr));
125: p += sizeof (struct in6_addr);
126: }
127:
128: /* External Route Tag */
129: if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
130: {
131: /* xxx */
132: }
133:
134: /* Fill LSA Header */
135: lsa_header->age = 0;
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;
139: lsa_header->seqnum =
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);
143:
144: /* LSA checksum */
145: ospf6_lsa_checksum (lsa_header);
146:
147: /* create LSA */
148: lsa = ospf6_lsa_create (lsa_header);
149:
150: /* Originate */
151: ospf6_lsa_originate_process (lsa, ospf6);
152: }
153:
154:
155: void
156: ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
157: {
158: struct ospf6_as_external_lsa *external;
159: struct prefix asbr_id;
160: struct ospf6_route *asbr_entry, *route;
161: char buf[64];
162: int i;
163:
164: external = (struct ospf6_as_external_lsa *)
165: OSPF6_LSA_HEADER_END (lsa->header);
166:
167: if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
168: zlog_debug ("Calculate AS-External route for %s", lsa->name);
169:
170: if (lsa->header->adv_router == ospf6->router_id)
171: {
172: if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
173: zlog_debug ("Ignore self-originated AS-External-LSA");
174: return;
175: }
176:
177: if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
178: {
179: if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
180: zlog_debug ("Ignore LSA with LSInfinity Metric");
181: return;
182: }
183:
184: ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
185: asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
186: if (asbr_entry == NULL ||
187: ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
188: {
189: if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
190: {
191: prefix2str (&asbr_id, buf, sizeof (buf));
192: zlog_debug ("ASBR entry not found: %s", buf);
193: }
194: return;
195: }
196:
197: route = ospf6_route_create ();
198: route->type = OSPF6_DEST_TYPE_NETWORK;
199: route->prefix.family = AF_INET6;
200: route->prefix.prefixlen = external->prefix.prefix_length;
201: ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);
202:
203: route->path.area_id = asbr_entry->path.area_id;
204: route->path.origin.type = lsa->header->type;
205: route->path.origin.id = lsa->header->id;
206: route->path.origin.adv_router = lsa->header->adv_router;
207:
208: route->path.prefix_options = external->prefix.prefix_options;
209: if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
210: {
211: route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
212: route->path.metric_type = 2;
213: route->path.cost = asbr_entry->path.cost;
214: route->path.cost_e2 = OSPF6_ASBR_METRIC (external);
215: }
216: else
217: {
218: route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
219: route->path.metric_type = 1;
220: route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
221: route->path.cost_e2 = 0;
222: }
223:
224: for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
225: ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);
226:
227: if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
228: {
229: prefix2str (&route->prefix, buf, sizeof (buf));
230: zlog_debug ("AS-External route add: %s", buf);
231: }
232:
233: ospf6_route_add (route, ospf6->route_table);
234: }
235:
236: void
237: ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa)
238: {
239: struct ospf6_as_external_lsa *external;
240: struct prefix prefix;
241: struct ospf6_route *route;
242: char buf[64];
243:
244: external = (struct ospf6_as_external_lsa *)
245: OSPF6_LSA_HEADER_END (lsa->header);
246:
247: if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
248: zlog_debug ("Withdraw AS-External route for %s", lsa->name);
249:
250: if (lsa->header->adv_router == ospf6->router_id)
251: {
252: if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
253: zlog_debug ("Ignore self-originated AS-External-LSA");
254: return;
255: }
256:
257: memset (&prefix, 0, sizeof (struct prefix));
258: prefix.family = AF_INET6;
259: prefix.prefixlen = external->prefix.prefix_length;
260: ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix);
261:
262: route = ospf6_route_lookup (&prefix, ospf6->route_table);
263: if (route == NULL)
264: {
265: if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
266: {
267: prefix2str (&prefix, buf, sizeof (buf));
268: zlog_debug ("AS-External route %s not found", buf);
269: }
270: return;
271: }
272:
273: for (ospf6_route_lock (route);
274: route && ospf6_route_is_prefix (&prefix, route);
275: route = ospf6_route_next (route))
276: {
277: if (route->type != OSPF6_DEST_TYPE_NETWORK)
278: continue;
279: if (route->path.origin.type != lsa->header->type)
280: continue;
281: if (route->path.origin.id != lsa->header->id)
282: continue;
283: if (route->path.origin.adv_router != lsa->header->adv_router)
284: continue;
285:
286: if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
287: {
288: prefix2str (&route->prefix, buf, sizeof (buf));
289: zlog_debug ("AS-External route remove: %s", buf);
290: }
291: ospf6_route_remove (route, ospf6->route_table);
292: }
293: }
294:
295: void
296: ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
297: {
298: struct ospf6_lsa *lsa;
299: u_int16_t type;
300: u_int32_t router;
301:
302: if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
303: {
304: char buf[16];
305: inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
306: buf, sizeof (buf));
307: zlog_info ("ignore non-best path: lsentry %s add", buf);
308: return;
309: }
310:
311: type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
312: router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
313: for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
314: lsa = ospf6_lsdb_type_router_next (type, router, lsa))
315: {
316: if (! OSPF6_LSA_IS_MAXAGE (lsa))
317: ospf6_asbr_lsa_add (lsa);
318: }
319: }
320:
321: void
322: ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
323: {
324: struct ospf6_lsa *lsa;
325: u_int16_t type;
326: u_int32_t router;
327:
328: type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
329: router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
330: for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
331: lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
332: ospf6_asbr_lsa_remove (lsa);
333: }
334:
335:
336:
337: /* redistribute function */
338:
339: static void
340: ospf6_asbr_routemap_set (int type, const char *mapname)
341: {
342: if (ospf6->rmap[type].name)
343: free (ospf6->rmap[type].name);
344: ospf6->rmap[type].name = strdup (mapname);
345: ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
346: }
347:
348: static void
349: ospf6_asbr_routemap_unset (int type)
350: {
351: if (ospf6->rmap[type].name)
352: free (ospf6->rmap[type].name);
353: ospf6->rmap[type].name = NULL;
354: ospf6->rmap[type].map = NULL;
355: }
356:
357: static void
358: ospf6_asbr_routemap_update (const char *mapname)
359: {
360: int type;
361:
362: if (ospf6 == NULL)
363: return;
364:
365: for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
366: {
367: if (ospf6->rmap[type].name)
368: ospf6->rmap[type].map =
369: route_map_lookup_by_name (ospf6->rmap[type].name);
370: else
371: ospf6->rmap[type].map = NULL;
372: }
373: }
374:
375: int
376: ospf6_asbr_is_asbr (struct ospf6 *o)
377: {
378: return o->external_table->count;
379: }
380:
381: static void
382: ospf6_asbr_redistribute_set (int type)
383: {
384: ospf6_zebra_redistribute (type);
385: }
386:
387: static void
388: ospf6_asbr_redistribute_unset (int type)
389: {
390: struct ospf6_route *route;
391: struct ospf6_external_info *info;
392:
393: ospf6_zebra_no_redistribute (type);
394:
395: for (route = ospf6_route_head (ospf6->external_table); route;
396: route = ospf6_route_next (route))
397: {
398: info = route->route_option;
399: if (info->type != type)
400: continue;
401:
402: ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
403: &route->prefix);
404: }
405: }
406:
407: void
408: ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
409: u_int nexthop_num, struct in6_addr *nexthop)
410: {
411: int ret;
412: struct ospf6_route troute;
413: struct ospf6_external_info tinfo;
414: struct ospf6_route *route, *match;
415: struct ospf6_external_info *info;
416: struct prefix prefix_id;
417: struct route_node *node;
418: char pbuf[64], ibuf[16];
419: struct listnode *lnode, *lnnode;
420: struct ospf6_area *oa;
421:
422: if (! ospf6_zebra_is_redistribute (type))
423: return;
424:
425: if (IS_OSPF6_DEBUG_ASBR)
426: {
427: prefix2str (prefix, pbuf, sizeof (pbuf));
428: zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
429: }
430:
431: /* if route-map was specified but not found, do not advertise */
432: if (ospf6->rmap[type].name)
433: {
434: if (ospf6->rmap[type].map == NULL)
435: ospf6_asbr_routemap_update (NULL);
436: if (ospf6->rmap[type].map == NULL)
437: {
438: zlog_warn ("route-map \"%s\" not found, suppress redistributing",
439: ospf6->rmap[type].name);
440: return;
441: }
442: }
443:
444: /* apply route-map */
445: if (ospf6->rmap[type].map)
446: {
447: memset (&troute, 0, sizeof (troute));
448: memset (&tinfo, 0, sizeof (tinfo));
449: troute.route_option = &tinfo;
450:
451: ret = route_map_apply (ospf6->rmap[type].map, prefix,
452: RMAP_OSPF6, &troute);
453: if (ret == RMAP_DENYMATCH)
454: {
455: if (IS_OSPF6_DEBUG_ASBR)
456: zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
457: return;
458: }
459: }
460:
461: match = ospf6_route_lookup (prefix, ospf6->external_table);
462: if (match)
463: {
464: info = match->route_option;
465:
466: /* copy result of route-map */
467: if (ospf6->rmap[type].map)
468: {
469: if (troute.path.metric_type)
470: match->path.metric_type = troute.path.metric_type;
471: if (troute.path.cost)
472: match->path.cost = troute.path.cost;
473: if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
474: memcpy (&info->forwarding, &tinfo.forwarding,
475: sizeof (struct in6_addr));
476: }
477:
478: info->type = type;
479: match->nexthop[0].ifindex = ifindex;
480: if (nexthop_num && nexthop)
481: memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
482:
483: /* create/update binding in external_id_table */
484: prefix_id.family = AF_INET;
485: prefix_id.prefixlen = 32;
486: prefix_id.u.prefix4.s_addr = htonl (info->id);
487: node = route_node_get (ospf6->external_id_table, &prefix_id);
488: node->info = match;
489:
490: if (IS_OSPF6_DEBUG_ASBR)
491: {
492: inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
493: zlog_debug ("Advertise as AS-External Id:%s", ibuf);
494: }
495:
496: match->path.origin.id = htonl (info->id);
497: ospf6_as_external_lsa_originate (match);
498: return;
499: }
500:
501: /* create new entry */
502: route = ospf6_route_create ();
503: route->type = OSPF6_DEST_TYPE_NETWORK;
504: memcpy (&route->prefix, prefix, sizeof (struct prefix));
505:
506: info = (struct ospf6_external_info *)
507: XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
508: route->route_option = info;
509: info->id = ospf6->external_id++;
510:
511: /* copy result of route-map */
512: if (ospf6->rmap[type].map)
513: {
514: if (troute.path.metric_type)
515: route->path.metric_type = troute.path.metric_type;
516: if (troute.path.cost)
517: route->path.cost = troute.path.cost;
518: if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
519: memcpy (&info->forwarding, &tinfo.forwarding,
520: sizeof (struct in6_addr));
521: }
522:
523: info->type = type;
524: route->nexthop[0].ifindex = ifindex;
525: if (nexthop_num && nexthop)
526: memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
527:
528: /* create/update binding in external_id_table */
529: prefix_id.family = AF_INET;
530: prefix_id.prefixlen = 32;
531: prefix_id.u.prefix4.s_addr = htonl (info->id);
532: node = route_node_get (ospf6->external_id_table, &prefix_id);
533: node->info = route;
534:
535: route = ospf6_route_add (route, ospf6->external_table);
536: route->route_option = info;
537:
538: if (IS_OSPF6_DEBUG_ASBR)
539: {
540: inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
541: zlog_debug ("Advertise as AS-External Id:%s", ibuf);
542: }
543:
544: route->path.origin.id = htonl (info->id);
545: ospf6_as_external_lsa_originate (route);
546:
547: /* Router-Bit (ASBR Flag) may have to be updated */
548: for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
549: OSPF6_ROUTER_LSA_SCHEDULE (oa);
550: }
551:
552: void
553: ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
554: {
555: struct ospf6_route *match;
556: struct ospf6_external_info *info = NULL;
557: struct route_node *node;
558: struct ospf6_lsa *lsa;
559: struct prefix prefix_id;
560: char pbuf[64], ibuf[16];
561: struct listnode *lnode, *lnnode;
562: struct ospf6_area *oa;
563:
564: match = ospf6_route_lookup (prefix, ospf6->external_table);
565: if (match == NULL)
566: {
567: if (IS_OSPF6_DEBUG_ASBR)
568: {
569: prefix2str (prefix, pbuf, sizeof (pbuf));
570: zlog_debug ("No such route %s to withdraw", pbuf);
571: }
572: return;
573: }
574:
575: info = match->route_option;
576: assert (info);
577:
578: if (info->type != type)
579: {
580: if (IS_OSPF6_DEBUG_ASBR)
581: {
582: prefix2str (prefix, pbuf, sizeof (pbuf));
583: zlog_debug ("Original protocol mismatch: %s", pbuf);
584: }
585: return;
586: }
587:
588: if (IS_OSPF6_DEBUG_ASBR)
589: {
590: prefix2str (prefix, pbuf, sizeof (pbuf));
591: inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
592: zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
593: }
594:
595: lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
596: htonl (info->id), ospf6->router_id, ospf6->lsdb);
597: if (lsa)
598: ospf6_lsa_purge (lsa);
599:
600: /* remove binding in external_id_table */
601: prefix_id.family = AF_INET;
602: prefix_id.prefixlen = 32;
603: prefix_id.u.prefix4.s_addr = htonl (info->id);
604: node = route_node_lookup (ospf6->external_id_table, &prefix_id);
605: assert (node);
606: node->info = NULL;
607: route_unlock_node (node);
608:
609: ospf6_route_remove (match, ospf6->external_table);
610: XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
611:
612: /* Router-Bit (ASBR Flag) may have to be updated */
613: for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
614: OSPF6_ROUTER_LSA_SCHEDULE (oa);
615: }
616:
617: DEFUN (ospf6_redistribute,
618: ospf6_redistribute_cmd,
619: "redistribute (static|kernel|connected|ripng|bgp)",
620: "Redistribute\n"
621: "Static route\n"
622: "Kernel route\n"
623: "Connected route\n"
624: "RIPng route\n"
625: "BGP route\n"
626: )
627: {
628: int type = 0;
629:
630: if (strncmp (argv[0], "sta", 3) == 0)
631: type = ZEBRA_ROUTE_STATIC;
632: else if (strncmp (argv[0], "ker", 3) == 0)
633: type = ZEBRA_ROUTE_KERNEL;
634: else if (strncmp (argv[0], "con", 3) == 0)
635: type = ZEBRA_ROUTE_CONNECT;
636: else if (strncmp (argv[0], "rip", 3) == 0)
637: type = ZEBRA_ROUTE_RIPNG;
638: else if (strncmp (argv[0], "bgp", 3) == 0)
639: type = ZEBRA_ROUTE_BGP;
640:
641: ospf6_asbr_redistribute_unset (type);
642: ospf6_asbr_routemap_unset (type);
643: ospf6_asbr_redistribute_set (type);
644: return CMD_SUCCESS;
645: }
646:
647: DEFUN (ospf6_redistribute_routemap,
648: ospf6_redistribute_routemap_cmd,
649: "redistribute (static|kernel|connected|ripng|bgp) route-map WORD",
650: "Redistribute\n"
651: "Static routes\n"
652: "Kernel route\n"
653: "Connected route\n"
654: "RIPng route\n"
655: "BGP route\n"
656: "Route map reference\n"
657: "Route map name\n"
658: )
659: {
660: int type = 0;
661:
662: if (strncmp (argv[0], "sta", 3) == 0)
663: type = ZEBRA_ROUTE_STATIC;
664: else if (strncmp (argv[0], "ker", 3) == 0)
665: type = ZEBRA_ROUTE_KERNEL;
666: else if (strncmp (argv[0], "con", 3) == 0)
667: type = ZEBRA_ROUTE_CONNECT;
668: else if (strncmp (argv[0], "rip", 3) == 0)
669: type = ZEBRA_ROUTE_RIPNG;
670: else if (strncmp (argv[0], "bgp", 3) == 0)
671: type = ZEBRA_ROUTE_BGP;
672:
673: ospf6_asbr_redistribute_unset (type);
674: ospf6_asbr_routemap_set (type, argv[1]);
675: ospf6_asbr_redistribute_set (type);
676: return CMD_SUCCESS;
677: }
678:
679: DEFUN (no_ospf6_redistribute,
680: no_ospf6_redistribute_cmd,
681: "no redistribute (static|kernel|connected|ripng|bgp)",
682: NO_STR
683: "Redistribute\n"
684: "Static route\n"
685: "Kernel route\n"
686: "Connected route\n"
687: "RIPng route\n"
688: "BGP route\n"
689: )
690: {
691: int type = 0;
692:
693: if (strncmp (argv[0], "sta", 3) == 0)
694: type = ZEBRA_ROUTE_STATIC;
695: else if (strncmp (argv[0], "ker", 3) == 0)
696: type = ZEBRA_ROUTE_KERNEL;
697: else if (strncmp (argv[0], "con", 3) == 0)
698: type = ZEBRA_ROUTE_CONNECT;
699: else if (strncmp (argv[0], "rip", 3) == 0)
700: type = ZEBRA_ROUTE_RIPNG;
701: else if (strncmp (argv[0], "bgp", 3) == 0)
702: type = ZEBRA_ROUTE_BGP;
703:
704: ospf6_asbr_redistribute_unset (type);
705: ospf6_asbr_routemap_unset (type);
706:
707: return CMD_SUCCESS;
708: }
709:
710: int
711: ospf6_redistribute_config_write (struct vty *vty)
712: {
713: int type;
714:
715: for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
716: {
717: if (type == ZEBRA_ROUTE_OSPF6)
718: continue;
719: if (! ospf6_zebra_is_redistribute (type))
720: continue;
721:
722: if (ospf6->rmap[type].name)
723: vty_out (vty, " redistribute %s route-map %s%s",
724: ZROUTE_NAME (type), ospf6->rmap[type].name, VNL);
725: else
726: vty_out (vty, " redistribute %s%s",
727: ZROUTE_NAME (type), VNL);
728: }
729:
730: return 0;
731: }
732:
733: static void
734: ospf6_redistribute_show_config (struct vty *vty)
735: {
736: int type;
737: int nroute[ZEBRA_ROUTE_MAX];
738: int total;
739: struct ospf6_route *route;
740: struct ospf6_external_info *info;
741:
742: total = 0;
743: for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
744: nroute[type] = 0;
745: for (route = ospf6_route_head (ospf6->external_table); route;
746: route = ospf6_route_next (route))
747: {
748: info = route->route_option;
749: nroute[info->type]++;
750: total++;
751: }
752:
753: vty_out (vty, "Redistributing External Routes from:%s", VNL);
754: for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
755: {
756: if (type == ZEBRA_ROUTE_OSPF6)
757: continue;
758: if (! ospf6_zebra_is_redistribute (type))
759: continue;
760:
761: if (ospf6->rmap[type].name)
762: vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
763: ZROUTE_NAME (type), ospf6->rmap[type].name,
764: (ospf6->rmap[type].map ? "" : " (not found !)"),
765: VNL);
766: else
767: vty_out (vty, " %d: %s%s", nroute[type],
768: ZROUTE_NAME (type), VNL);
769: }
770: vty_out (vty, "Total %d routes%s", total, VNL);
771: }
772:
773:
774:
775: /* Routemap Functions */
776: static route_map_result_t
777: ospf6_routemap_rule_match_address_prefixlist (void *rule,
778: struct prefix *prefix,
779: route_map_object_t type,
780: void *object)
781: {
782: struct prefix_list *plist;
783:
784: if (type != RMAP_OSPF6)
785: return RMAP_NOMATCH;
786:
787: plist = prefix_list_lookup (AFI_IP6, (char *) rule);
788: if (plist == NULL)
789: return RMAP_NOMATCH;
790:
791: return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
792: RMAP_NOMATCH : RMAP_MATCH);
793: }
794:
795: static void *
796: ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg)
797: {
798: return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
799: }
800:
801: static void
802: ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
803: {
804: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
805: }
806:
807: struct route_map_rule_cmd
808: ospf6_routemap_rule_match_address_prefixlist_cmd =
809: {
810: "ipv6 address prefix-list",
811: ospf6_routemap_rule_match_address_prefixlist,
812: ospf6_routemap_rule_match_address_prefixlist_compile,
813: ospf6_routemap_rule_match_address_prefixlist_free,
814: };
815:
816: static route_map_result_t
817: ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
818: route_map_object_t type, void *object)
819: {
820: char *metric_type = rule;
821: struct ospf6_route *route = object;
822:
823: if (type != RMAP_OSPF6)
824: return RMAP_OKAY;
825:
826: if (strcmp (metric_type, "type-2") == 0)
827: route->path.metric_type = 2;
828: else
829: route->path.metric_type = 1;
830:
831: return RMAP_OKAY;
832: }
833:
834: static void *
835: ospf6_routemap_rule_set_metric_type_compile (const char *arg)
836: {
837: if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
838: return NULL;
839: return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
840: }
841:
842: static void
843: ospf6_routemap_rule_set_metric_type_free (void *rule)
844: {
845: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
846: }
847:
848: struct route_map_rule_cmd
849: ospf6_routemap_rule_set_metric_type_cmd =
850: {
851: "metric-type",
852: ospf6_routemap_rule_set_metric_type,
853: ospf6_routemap_rule_set_metric_type_compile,
854: ospf6_routemap_rule_set_metric_type_free,
855: };
856:
857: static route_map_result_t
858: ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
859: route_map_object_t type, void *object)
860: {
861: char *metric = rule;
862: struct ospf6_route *route = object;
863:
864: if (type != RMAP_OSPF6)
865: return RMAP_OKAY;
866:
867: route->path.cost = atoi (metric);
868: return RMAP_OKAY;
869: }
870:
871: static void *
872: ospf6_routemap_rule_set_metric_compile (const char *arg)
873: {
874: u_int32_t metric;
875: char *endp;
876: metric = strtoul (arg, &endp, 0);
877: if (metric > LS_INFINITY || *endp != '\0')
878: return NULL;
879: return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
880: }
881:
882: static void
883: ospf6_routemap_rule_set_metric_free (void *rule)
884: {
885: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
886: }
887:
888: struct route_map_rule_cmd
889: ospf6_routemap_rule_set_metric_cmd =
890: {
891: "metric",
892: ospf6_routemap_rule_set_metric,
893: ospf6_routemap_rule_set_metric_compile,
894: ospf6_routemap_rule_set_metric_free,
895: };
896:
897: static route_map_result_t
898: ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
899: route_map_object_t type, void *object)
900: {
901: char *forwarding = rule;
902: struct ospf6_route *route = object;
903: struct ospf6_external_info *info = route->route_option;
904:
905: if (type != RMAP_OSPF6)
906: return RMAP_OKAY;
907:
908: if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
909: {
910: memset (&info->forwarding, 0, sizeof (struct in6_addr));
911: return RMAP_ERROR;
912: }
913:
914: return RMAP_OKAY;
915: }
916:
917: static void *
918: ospf6_routemap_rule_set_forwarding_compile (const char *arg)
919: {
920: struct in6_addr a;
921: if (inet_pton (AF_INET6, arg, &a) != 1)
922: return NULL;
923: return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
924: }
925:
926: static void
927: ospf6_routemap_rule_set_forwarding_free (void *rule)
928: {
929: XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
930: }
931:
932: struct route_map_rule_cmd
933: ospf6_routemap_rule_set_forwarding_cmd =
934: {
935: "forwarding-address",
936: ospf6_routemap_rule_set_forwarding,
937: ospf6_routemap_rule_set_forwarding_compile,
938: ospf6_routemap_rule_set_forwarding_free,
939: };
940:
941: static int
942: route_map_command_status (struct vty *vty, int ret)
943: {
944: if (! ret)
945: return CMD_SUCCESS;
946:
947: switch (ret)
948: {
949: case RMAP_RULE_MISSING:
950: vty_out (vty, "Can't find rule.%s", VNL);
951: break;
952: case RMAP_COMPILE_ERROR:
953: vty_out (vty, "Argument is malformed.%s", VNL);
954: break;
955: default:
956: vty_out (vty, "route-map add set failed.%s", VNL);
957: break;
958: }
959: return CMD_WARNING;
960: }
961:
962: /* add "match address" */
963: DEFUN (ospf6_routemap_match_address_prefixlist,
964: ospf6_routemap_match_address_prefixlist_cmd,
965: "match ipv6 address prefix-list WORD",
966: "Match values\n"
967: IPV6_STR
968: "Match address of route\n"
969: "Match entries of prefix-lists\n"
970: "IPv6 prefix-list name\n")
971: {
972: int ret = route_map_add_match ((struct route_map_index *) vty->index,
973: "ipv6 address prefix-list", argv[0]);
974: return route_map_command_status (vty, ret);
975: }
976:
977: /* delete "match address" */
978: DEFUN (ospf6_routemap_no_match_address_prefixlist,
979: ospf6_routemap_no_match_address_prefixlist_cmd,
980: "no match ipv6 address prefix-list WORD",
981: NO_STR
982: "Match values\n"
983: IPV6_STR
984: "Match address of route\n"
985: "Match entries of prefix-lists\n"
986: "IPv6 prefix-list name\n")
987: {
988: int ret = route_map_delete_match ((struct route_map_index *) vty->index,
989: "ipv6 address prefix-list", argv[0]);
990: return route_map_command_status (vty, ret);
991: }
992:
993: /* add "set metric-type" */
994: DEFUN (ospf6_routemap_set_metric_type,
995: ospf6_routemap_set_metric_type_cmd,
996: "set metric-type (type-1|type-2)",
997: "Set value\n"
998: "Type of metric\n"
999: "OSPF6 external type 1 metric\n"
1000: "OSPF6 external type 2 metric\n")
1001: {
1002: int ret = route_map_add_set ((struct route_map_index *) vty->index,
1003: "metric-type", argv[0]);
1004: return route_map_command_status (vty, ret);
1005: }
1006:
1007: /* delete "set metric-type" */
1008: DEFUN (ospf6_routemap_no_set_metric_type,
1009: ospf6_routemap_no_set_metric_type_cmd,
1010: "no set metric-type (type-1|type-2)",
1011: NO_STR
1012: "Set value\n"
1013: "Type of metric\n"
1014: "OSPF6 external type 1 metric\n"
1015: "OSPF6 external type 2 metric\n")
1016: {
1017: int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1018: "metric-type", argv[0]);
1019: return route_map_command_status (vty, ret);
1020: }
1021:
1022: /* add "set metric" */
1023: DEFUN (set_metric,
1024: set_metric_cmd,
1025: "set metric <0-4294967295>",
1026: "Set value\n"
1027: "Metric value\n"
1028: "Metric value\n")
1029: {
1030: int ret = route_map_add_set ((struct route_map_index *) vty->index,
1031: "metric", argv[0]);
1032: return route_map_command_status (vty, ret);
1033: }
1034:
1035: /* delete "set metric" */
1036: DEFUN (no_set_metric,
1037: no_set_metric_cmd,
1038: "no set metric <0-4294967295>",
1039: NO_STR
1040: "Set value\n"
1041: "Metric\n"
1042: "METRIC value\n")
1043: {
1044: int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1045: "metric", argv[0]);
1046: return route_map_command_status (vty, ret);
1047: }
1048:
1049: /* add "set forwarding-address" */
1050: DEFUN (ospf6_routemap_set_forwarding,
1051: ospf6_routemap_set_forwarding_cmd,
1052: "set forwarding-address X:X::X:X",
1053: "Set value\n"
1054: "Forwarding Address\n"
1055: "IPv6 Address\n")
1056: {
1057: int ret = route_map_add_set ((struct route_map_index *) vty->index,
1058: "forwarding-address", argv[0]);
1059: return route_map_command_status (vty, ret);
1060: }
1061:
1062: /* delete "set forwarding-address" */
1063: DEFUN (ospf6_routemap_no_set_forwarding,
1064: ospf6_routemap_no_set_forwarding_cmd,
1065: "no set forwarding-address X:X::X:X",
1066: NO_STR
1067: "Set value\n"
1068: "Forwarding Address\n"
1069: "IPv6 Address\n")
1070: {
1071: int ret = route_map_delete_set ((struct route_map_index *) vty->index,
1072: "forwarding-address", argv[0]);
1073: return route_map_command_status (vty, ret);
1074: }
1075:
1076: static void
1077: ospf6_routemap_init (void)
1078: {
1079: route_map_init ();
1080: route_map_init_vty ();
1081: route_map_add_hook (ospf6_asbr_routemap_update);
1082: route_map_delete_hook (ospf6_asbr_routemap_update);
1083:
1084: route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
1085: route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
1086: route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
1087: route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
1088:
1089: /* Match address prefix-list */
1090: install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
1091: install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
1092:
1093: /* ASE Metric Type (e.g. Type-1/Type-2) */
1094: install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
1095: install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
1096:
1097: /* ASE Metric */
1098: install_element (RMAP_NODE, &set_metric_cmd);
1099: install_element (RMAP_NODE, &no_set_metric_cmd);
1100:
1101: /* ASE Metric */
1102: install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
1103: install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
1104: }
1105:
1106:
1107: /* Display functions */
1108: static int
1109: ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1110: {
1111: struct ospf6_as_external_lsa *external;
1112: char buf[64];
1113: struct in6_addr in6, *forwarding;
1114:
1115: assert (lsa->header);
1116: external = (struct ospf6_as_external_lsa *)
1117: OSPF6_LSA_HEADER_END (lsa->header);
1118:
1119: /* bits */
1120: snprintf (buf, sizeof (buf), "%c%c%c",
1121: (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
1122: (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
1123: (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
1124:
1125: vty_out (vty, " Bits: %s%s", buf, VNL);
1126: vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
1127: VNL);
1128:
1129: ospf6_prefix_options_printbuf (external->prefix.prefix_options,
1130: buf, sizeof (buf));
1131: vty_out (vty, " Prefix Options: %s%s", buf,
1132: VNL);
1133:
1134: vty_out (vty, " Referenced LSType: %d%s",
1135: ntohs (external->prefix.prefix_refer_lstype),
1136: VNL);
1137:
1138: ospf6_prefix_in6_addr (&in6, &external->prefix);
1139: inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
1140: vty_out (vty, " Prefix: %s/%d%s", buf,
1141: external->prefix.prefix_length, VNL);
1142:
1143: /* Forwarding-Address */
1144: if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
1145: {
1146: forwarding = (struct in6_addr *)
1147: ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
1148: OSPF6_PREFIX_SPACE (external->prefix.prefix_length));
1149: inet_ntop (AF_INET6, forwarding, buf, sizeof (buf));
1150: vty_out (vty, " Forwarding-Address: %s%s", buf, VNL);
1151: }
1152:
1153: return 0;
1154: }
1155:
1156: static void
1157: ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
1158: {
1159: struct ospf6_external_info *info = route->route_option;
1160: char prefix[64], id[16], forwarding[64];
1161: u_int32_t tmp_id;
1162:
1163: prefix2str (&route->prefix, prefix, sizeof (prefix));
1164: tmp_id = ntohl (info->id);
1165: inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
1166: if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
1167: inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
1168: else
1169: snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
1170: route->nexthop[0].ifindex);
1171:
1172: vty_out (vty, "%c %-32s %-15s type-%d %5lu %s%s",
1173: zebra_route_char(info->type),
1174: prefix, id, route->path.metric_type,
1175: (u_long) (route->path.metric_type == 2 ?
1176: route->path.cost_e2 : route->path.cost),
1177: forwarding, VNL);
1178: }
1179:
1180: DEFUN (show_ipv6_ospf6_redistribute,
1181: show_ipv6_ospf6_redistribute_cmd,
1182: "show ipv6 ospf6 redistribute",
1183: SHOW_STR
1184: IP6_STR
1185: OSPF6_STR
1186: "redistributing External information\n"
1187: )
1188: {
1189: struct ospf6_route *route;
1190:
1191: ospf6_redistribute_show_config (vty);
1192:
1193: for (route = ospf6_route_head (ospf6->external_table); route;
1194: route = ospf6_route_next (route))
1195: ospf6_asbr_external_route_show (vty, route);
1196:
1197: return CMD_SUCCESS;
1198: }
1199:
1200: struct ospf6_lsa_handler as_external_handler =
1201: {
1202: OSPF6_LSTYPE_AS_EXTERNAL,
1203: "AS-External",
1204: ospf6_as_external_lsa_show
1205: };
1206:
1207: void
1208: ospf6_asbr_init (void)
1209: {
1210: ospf6_routemap_init ();
1211:
1212: ospf6_install_lsa_handler (&as_external_handler);
1213:
1214: install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
1215: install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
1216:
1217: install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
1218: install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
1219: install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
1220: }
1221:
1222: void
1223: ospf6_asbr_terminate (void)
1224: {
1225: route_map_finish ();
1226: }
1227:
1228: DEFUN (debug_ospf6_asbr,
1229: debug_ospf6_asbr_cmd,
1230: "debug ospf6 asbr",
1231: DEBUG_STR
1232: OSPF6_STR
1233: "Debug OSPFv3 ASBR function\n"
1234: )
1235: {
1236: OSPF6_DEBUG_ASBR_ON ();
1237: return CMD_SUCCESS;
1238: }
1239:
1240: DEFUN (no_debug_ospf6_asbr,
1241: no_debug_ospf6_asbr_cmd,
1242: "no debug ospf6 asbr",
1243: NO_STR
1244: DEBUG_STR
1245: OSPF6_STR
1246: "Debug OSPFv3 ASBR function\n"
1247: )
1248: {
1249: OSPF6_DEBUG_ASBR_OFF ();
1250: return CMD_SUCCESS;
1251: }
1252:
1253: int
1254: config_write_ospf6_debug_asbr (struct vty *vty)
1255: {
1256: if (IS_OSPF6_DEBUG_ASBR)
1257: vty_out (vty, "debug ospf6 asbr%s", VNL);
1258: return 0;
1259: }
1260:
1261: void
1262: install_element_ospf6_debug_asbr ()
1263: {
1264: install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
1265: install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
1266: install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
1267: install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
1268: }
1269:
1270:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>