]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_ri.c
vtysh: return non-zero for configuration failures
[mirror_frr.git] / ospfd / ospf_ri.c
1 /*
2 * This is an implementation of RFC4970 Router Information
3 * with support of RFC5088 PCE Capabilites announcement
4 *
5 * Module name: Router Information
6 * Version: 0.99.22
7 * Created: 2012-02-01 by Olivier Dugeon
8 * Copyright (C) 2012 Orange Labs http://www.orange.com/
9 *
10 * This file is part of GNU Quagga.
11 *
12 * GNU Zebra is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2, or (at your option) any
15 * later version.
16 *
17 * GNU Quagga is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; see the file COPYING; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 */
26
27 #include <zebra.h>
28 #include <math.h>
29
30 #include "linklist.h"
31 #include "prefix.h"
32 #include "if.h"
33 #include "table.h"
34 #include "memory.h"
35 #include "command.h"
36 #include "vty.h"
37 #include "stream.h"
38 #include "log.h"
39 #include "thread.h"
40 #include "hash.h"
41 #include "sockunion.h" /* for inet_aton() */
42
43 #include "ospfd/ospfd.h"
44 #include "ospfd/ospf_interface.h"
45 #include "ospfd/ospf_ism.h"
46 #include "ospfd/ospf_asbr.h"
47 #include "ospfd/ospf_lsa.h"
48 #include "ospfd/ospf_lsdb.h"
49 #include "ospfd/ospf_neighbor.h"
50 #include "ospfd/ospf_nsm.h"
51 #include "ospfd/ospf_flood.h"
52 #include "ospfd/ospf_packet.h"
53 #include "ospfd/ospf_spf.h"
54 #include "ospfd/ospf_dump.h"
55 #include "ospfd/ospf_route.h"
56 #include "ospfd/ospf_ase.h"
57 #include "ospfd/ospf_zebra.h"
58 #include "ospfd/ospf_ri.h"
59 #include "ospfd/ospf_te.h"
60
61 struct ospf_pce_info
62 {
63
64 /* Store Router Information PCE TLV and SubTLV in network byte order. */
65 struct ri_tlv_pce pce_header;
66 struct ri_pce_subtlv_address pce_address;
67 struct ri_pce_subtlv_path_scope pce_scope;
68 struct list *pce_domain;
69 struct list *pce_neighbor;
70 struct ri_pce_subtlv_cap_flag pce_cap_flag;
71 };
72
73 /* Following structure are internal use only. */
74 struct ospf_router_info
75 {
76 status_t status;
77
78 u_int8_t registered;
79 u_int8_t scope;
80
81 /* Flags to manage this router information. */
82 #define RIFLG_LOOKUP_DONE 0x1
83 #define RIFLG_LSA_ENGAGED 0x2
84 #define RIFLG_LSA_FORCED_REFRESH 0x4
85 u_int32_t flags;
86
87 /* area pointer if flooding is Type 10 Null if flooding is AS scope */
88 struct ospf_area *area;
89 struct in_addr area_id;
90
91 /* Store Router Information Capabilities LSA */
92 struct ri_tlv_router_cap router_cap;
93
94 /* Store PCE capability LSA */
95 struct ospf_pce_info pce_info;
96 };
97
98 /*
99 * Global variable to manage Opaque-LSA/Router Information on this node.
100 * Note that all parameter values are stored in network byte order.
101 */
102 static struct ospf_router_info OspfRI;
103
104 /*------------------------------------------------------------------------------*
105 * Followings are initialize/terminate functions for Router Information handling.
106 *------------------------------------------------------------------------------*/
107
108 static void ospf_router_info_ism_change (struct ospf_interface *oi,
109 int old_status);
110 static void ospf_router_info_nsm_change (struct ospf_neighbor *nbr,
111 int old_status);
112 static void ospf_router_info_config_write_router (struct vty *vty);
113 static void ospf_router_info_show_info (struct vty *vty,
114 struct ospf_lsa *lsa);
115 static int ospf_router_info_lsa_originate (void *arg);
116 static struct ospf_lsa *ospf_router_info_lsa_refresh (struct ospf_lsa *lsa);
117 static void ospf_router_info_lsa_schedule (opcode_t opcode);
118 static void ospf_router_info_register_vty (void);
119 static void del_pce_info (void *val);
120
121 int
122 ospf_router_info_init (void)
123 {
124
125 memset (&OspfRI, 0, sizeof (struct ospf_router_info));
126 OspfRI.status = disabled;
127 OspfRI.registered = 0;
128 OspfRI.scope = OSPF_OPAQUE_AS_LSA;
129 OspfRI.flags = 0;
130
131 /* Initialize pce domain and neighbor list */
132 OspfRI.pce_info.pce_domain = list_new ();
133 OspfRI.pce_info.pce_domain->del = del_pce_info;
134 OspfRI.pce_info.pce_neighbor = list_new ();
135 OspfRI.pce_info.pce_neighbor->del = del_pce_info;
136
137 ospf_router_info_register_vty ();
138
139 return 0;
140 }
141
142 static int
143 ospf_router_info_register (u_int8_t scope)
144 {
145 int rc = 0;
146
147 if (OspfRI.registered)
148 return 0;
149
150 zlog_info ("Register Router Information with scope %s(%d)",
151 scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
152 rc = ospf_register_opaque_functab (scope,
153 OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
154 NULL, /* new interface */
155 NULL, /* del interface */
156 ospf_router_info_ism_change,
157 ospf_router_info_nsm_change,
158 ospf_router_info_config_write_router,
159 NULL, /* Config. write interface */
160 NULL, /* Config. write debug */
161 ospf_router_info_show_info,
162 ospf_router_info_lsa_originate,
163 ospf_router_info_lsa_refresh,
164 NULL, /* new_lsa_hook */
165 NULL); /* del_lsa_hook */
166
167 if (rc != 0)
168 {
169 zlog_warn ("ospf_router_info_init: Failed to register functions");
170 return rc;
171 }
172
173 OspfRI.registered = 1;
174 OspfRI.scope = scope;
175 return 0;
176 }
177
178 static int
179 ospf_router_info_unregister ()
180 {
181
182 if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
183 && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA))
184 {
185 zlog_warn ("Unable to unregister Router Info functions: Wrong scope!");
186 return -1;
187 }
188
189 ospf_delete_opaque_functab (OspfRI.scope,
190 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
191
192 OspfRI.registered = 0;
193 return 0;
194
195 }
196
197 void
198 ospf_router_info_term (void)
199 {
200
201 list_delete (OspfRI.pce_info.pce_domain);
202 list_delete (OspfRI.pce_info.pce_neighbor);
203
204 OspfRI.pce_info.pce_domain = NULL;
205 OspfRI.pce_info.pce_neighbor = NULL;
206 OspfRI.status = disabled;
207
208 ospf_router_info_unregister ();
209
210 return;
211 }
212
213 static void
214 del_pce_info (void *val)
215 {
216 XFREE (MTYPE_OSPF_PCE_PARAMS, val);
217 return;
218 }
219
220 /*------------------------------------------------------------------------*
221 * Followings are control functions for ROUTER INFORMATION parameters management.
222 *------------------------------------------------------------------------*/
223
224 static void
225 set_router_info_capabilities (struct ri_tlv_router_cap *ric, u_int32_t cap)
226 {
227 ric->header.type = htons (RI_TLV_CAPABILITIES);
228 ric->header.length = htons (RI_TLV_LENGTH);
229 ric->value = htonl (cap);
230 return;
231 }
232
233 static int
234 set_pce_header (struct ospf_pce_info *pce)
235 {
236 u_int16_t length = 0;
237 struct listnode *node;
238 struct ri_pce_subtlv_domain *domain;
239 struct ri_pce_subtlv_neighbor *neighbor;
240
241 /* PCE Address */
242 if (ntohs (pce->pce_address.header.type) != 0)
243 length += RI_TLV_SIZE (&pce->pce_address.header);
244
245 /* PCE Path Scope */
246 if (ntohs (pce->pce_scope.header.type) != 0)
247 length += RI_TLV_SIZE (&pce->pce_scope.header);
248
249 /* PCE Domain */
250 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
251 {
252 if (ntohs (domain->header.type) != 0)
253 length += RI_TLV_SIZE (&domain->header);
254 }
255
256 /* PCE Neighbor */
257 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
258 {
259 if (ntohs (neighbor->header.type) != 0)
260 length += RI_TLV_SIZE (&neighbor->header);
261 }
262
263 /* PCE Capabilities */
264 if (ntohs (pce->pce_cap_flag.header.type) != 0)
265 length += RI_TLV_SIZE (&pce->pce_cap_flag.header);
266
267 if (length != 0)
268 {
269 pce->pce_header.header.type = htons (RI_TLV_PCE);
270 pce->pce_header.header.length = htons (length);
271 }
272 else
273 {
274 pce->pce_header.header.type = 0;
275 pce->pce_header.header.length = 0;
276 }
277
278 return length;
279 }
280
281 static void
282 set_pce_address (struct in_addr ipv4, struct ospf_pce_info *pce)
283 {
284
285 /* Enable PCE Info */
286 pce->pce_header.header.type = htons (RI_TLV_PCE);
287 /* Set PCE Address */
288 pce->pce_address.header.type = htons (RI_PCE_SUBTLV_ADDRESS);
289 pce->pce_address.header.length = htons (PCE_ADDRESS_LENGTH_IPV4);
290 pce->pce_address.address.type = htons (PCE_ADDRESS_TYPE_IPV4);
291 pce->pce_address.address.value = ipv4;
292
293 return;
294 }
295
296 static void
297 set_pce_path_scope (u_int32_t scope, struct ospf_pce_info *pce)
298 {
299
300 /* Enable PCE Info */
301 pce->pce_header.header.type = htons (RI_TLV_PCE);
302 /* Set PCE Scope */
303 pce->pce_scope.header.type = htons (RI_PCE_SUBTLV_PATH_SCOPE);
304 pce->pce_scope.header.length = htons (RI_TLV_LENGTH);
305 pce->pce_scope.value = htonl (scope);
306
307 return;
308 }
309
310 static void
311 set_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce)
312 {
313
314 struct ri_pce_subtlv_domain *new;
315
316 /* Enable PCE Info */
317 pce->pce_header.header.type = htons (RI_TLV_PCE);
318
319 /* Create new domain info */
320 new =
321 XCALLOC (MTYPE_OSPF_PCE_PARAMS,
322 sizeof (struct ri_pce_subtlv_domain));
323
324 new->header.type = htons (RI_PCE_SUBTLV_DOMAIN);
325 new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4);
326 new->type = htons (type);
327 new->value = htonl (domain);
328
329 /* Add new domain to the list */
330 listnode_add (pce->pce_domain, new);
331
332 return;
333 }
334
335 static void
336 unset_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce)
337 {
338 struct listnode *node;
339 struct ri_pce_subtlv_domain *old = NULL;
340 int found = 0;
341
342 /* Search the corresponding node */
343 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, old))
344 {
345 if ((old->type == htons (type)) && (old->value == htonl (domain)))
346 {
347 found = 1;
348 break;
349 }
350 }
351
352 /* if found remove it */
353 if (found)
354 {
355 listnode_delete (pce->pce_domain, old);
356
357 /* Avoid misjudgement in the next lookup. */
358 if (listcount (pce->pce_domain) == 0)
359 pce->pce_domain->head = pce->pce_domain->tail = NULL;
360
361 /* Finally free the old domain */
362 XFREE (MTYPE_OSPF_PCE_PARAMS, old);
363 }
364 }
365
366 static void
367 set_pce_neighbor (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce)
368 {
369
370 struct ri_pce_subtlv_neighbor *new;
371
372 /* Enable PCE Info */
373 pce->pce_header.header.type = htons (RI_TLV_PCE);
374
375 /* Create new neighbor info */
376 new =
377 XCALLOC (MTYPE_OSPF_PCE_PARAMS,
378 sizeof (struct ri_pce_subtlv_neighbor));
379
380 new->header.type = htons (RI_PCE_SUBTLV_NEIGHBOR);
381 new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4);
382 new->type = htons (type);
383 new->value = htonl (domain);
384
385 /* Add new domain to the list */
386 listnode_add (pce->pce_neighbor, new);
387
388 return;
389 }
390
391 static void
392 unset_pce_neighbor (u_int16_t type, u_int32_t domain,
393 struct ospf_pce_info *pce)
394 {
395 struct listnode *node;
396 struct ri_pce_subtlv_neighbor *old = NULL;
397 int found = 0;
398
399 /* Search the corresponding node */
400 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, old))
401 {
402 if ((old->type == htons (type)) && (old->value == htonl (domain)))
403 {
404 found = 1;
405 break;
406 }
407 }
408
409 /* if found remove it */
410 if (found)
411 {
412 listnode_delete (pce->pce_neighbor, old);
413
414 /* Avoid misjudgement in the next lookup. */
415 if (listcount (pce->pce_neighbor) == 0)
416 pce->pce_neighbor->head = pce->pce_neighbor->tail = NULL;
417
418 /* Finally free the old domain */
419 XFREE (MTYPE_OSPF_PCE_PARAMS, old);
420 }
421 }
422
423 static void
424 set_pce_cap_flag (u_int32_t cap, struct ospf_pce_info *pce)
425 {
426
427 /* Enable PCE Info */
428 pce->pce_header.header.type = htons (RI_TLV_PCE);
429 /* Set PCE Capabilities flag */
430 pce->pce_cap_flag.header.type = htons (RI_PCE_SUBTLV_CAP_FLAG);
431 pce->pce_cap_flag.header.length = htons (RI_TLV_LENGTH);
432 pce->pce_cap_flag.value = htonl (cap);
433
434 return;
435 }
436
437
438 static void
439 unset_param (struct ri_tlv_header *tlv)
440 {
441
442 tlv->type = 0;
443 /* Fill the Value to 0 */
444 memset ((tlv + RI_TLV_HDR_SIZE), 0, RI_TLV_BODY_SIZE (tlv));
445 tlv->length = 0;
446
447 return;
448 }
449
450 static void
451 initialize_params (struct ospf_router_info *ori)
452 {
453 u_int32_t cap;
454 struct ospf *top;
455
456 /*
457 * Initialize default Router Information Capabilities.
458 */
459 cap = 0;
460 cap = cap | RI_TE_SUPPORT;
461
462 set_router_info_capabilities (&ori->router_cap, cap);
463
464 /* If Area address is not null and exist, retrieve corresponding structure */
465 top = ospf_lookup ();
466 zlog_info ("RI-> Initialize Router Info for %s scope within area %s",
467 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS",
468 inet_ntoa (OspfRI.area_id));
469
470 /* Try to get the Area context at this step. Do it latter if not available */
471 if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL))
472 OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id);
473
474 /*
475 * Initialize default PCE Information values
476 */
477 /* PCE address == OSPF Router ID */
478 set_pce_address (top->router_id, &ori->pce_info);
479
480 /* PCE scope */
481 cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path computation */
482 set_pce_path_scope (cap, &ori->pce_info);
483
484 /* PCE Capabilities */
485 cap =
486 PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES |
487 PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ;
488 set_pce_cap_flag (cap, &ori->pce_info);
489
490 /* Finally compute PCE header */
491 set_pce_header (&ori->pce_info);
492
493 return;
494 }
495
496 static int
497 is_mandated_params_set (struct ospf_router_info ori)
498 {
499 int rc = 0;
500
501 if (ntohs (ori.router_cap.header.type) == 0)
502 goto out;
503
504 if ((ntohs (ori.pce_info.pce_header.header.type) == RI_TLV_PCE)
505 && (ntohs (ori.pce_info.pce_address.header.type) == 0)
506 && (ntohs (ori.pce_info.pce_cap_flag.header.type) == 0))
507 goto out;
508
509 rc = 1;
510
511 out:
512 return rc;
513 }
514
515 /*------------------------------------------------------------------------*
516 * Followings are callback functions against generic Opaque-LSAs handling.
517 *------------------------------------------------------------------------*/
518 static void
519 ospf_router_info_ism_change (struct ospf_interface *oi, int old_state)
520 {
521 /* So far, nothing to do here. */
522 return;
523
524 }
525
526 static void
527 ospf_router_info_nsm_change (struct ospf_neighbor *nbr, int old_state)
528 {
529
530 /* So far, nothing to do here. */
531 return;
532 }
533
534 /*------------------------------------------------------------------------*
535 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
536 *------------------------------------------------------------------------*/
537
538 static void
539 build_tlv_header (struct stream *s, struct ri_tlv_header *tlvh)
540 {
541
542 stream_put (s, tlvh, sizeof (struct ri_tlv_header));
543 return;
544 }
545
546 static void
547 build_tlv (struct stream *s, struct ri_tlv_header *tlvh)
548 {
549
550 if (ntohs (tlvh->type) != 0)
551 {
552 build_tlv_header (s, tlvh);
553 stream_put (s, tlvh + 1, RI_TLV_BODY_SIZE (tlvh));
554 }
555 return;
556 }
557
558 static void
559 ospf_router_info_lsa_body_set (struct stream *s)
560 {
561
562 struct listnode *node;
563 struct ri_pce_subtlv_domain *domain;
564 struct ri_pce_subtlv_neighbor *neighbor;
565
566 /* Build Router Information TLV */
567 build_tlv (s, &OspfRI.router_cap.header);
568
569 /* Add RI PCE TLV if it is set */
570 /* Compute PCE Info header first */
571 if ((set_pce_header (&OspfRI.pce_info)) != 0)
572 {
573
574 /* Build PCE TLV */
575 build_tlv_header (s, &OspfRI.pce_info.pce_header.header);
576
577 /* Build PCE address sub-tlv */
578 build_tlv (s, &OspfRI.pce_info.pce_address.header);
579
580 /* Build PCE path scope sub-tlv */
581 build_tlv (s, &OspfRI.pce_info.pce_scope.header);
582
583 /* Build PCE domain sub-tlv */
584 for (ALL_LIST_ELEMENTS_RO (OspfRI.pce_info.pce_domain, node, domain))
585 build_tlv (s, &domain->header);
586
587 /* Build PCE neighbor sub-tlv */
588 for (ALL_LIST_ELEMENTS_RO
589 (OspfRI.pce_info.pce_neighbor, node, neighbor))
590 build_tlv (s, &neighbor->header);
591
592 /* Build PCE cap flag sub-tlv */
593 build_tlv (s, &OspfRI.pce_info.pce_cap_flag.header);
594 }
595
596 return;
597 }
598
599 /* Create new opaque-LSA. */
600 static struct ospf_lsa *
601 ospf_router_info_lsa_new ()
602 {
603 struct ospf *top;
604 struct stream *s;
605 struct lsa_header *lsah;
606 struct ospf_lsa *new = NULL;
607 u_char options, lsa_type;
608 struct in_addr lsa_id;
609 u_int32_t tmp;
610 u_int16_t length;
611
612 /* Create a stream for LSA. */
613 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
614 {
615 zlog_warn ("ospf_router_info_lsa_new: stream_new() ?");
616 goto out;
617 }
618 lsah = (struct lsa_header *) STREAM_DATA (s);
619
620 options = OSPF_OPTION_E; /* Enable AS external as we flood RI with Opaque Type 11 */
621 options |= OSPF_OPTION_O; /* Don't forget this :-) */
622
623 lsa_type = OspfRI.scope;
624 /* LSA ID == 0 for Router Information see RFC 4970 */
625 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
626 lsa_id.s_addr = htonl (tmp);
627
628 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
629 zlog_debug
630 ("LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
631 lsa_type, inet_ntoa (lsa_id));
632
633 top = ospf_lookup ();
634
635 /* Set opaque-LSA header fields. */
636 lsa_header_set (s, options, lsa_type, lsa_id, top->router_id);
637
638 /* Set opaque-LSA body fields. */
639 ospf_router_info_lsa_body_set (s);
640
641 /* Set length. */
642 length = stream_get_endp (s);
643 lsah->length = htons (length);
644
645 /* Now, create an OSPF LSA instance. */
646 if ((new = ospf_lsa_new ()) == NULL)
647 {
648 zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_new() ?");
649 stream_free (s);
650 goto out;
651 }
652 if ((new->data = ospf_lsa_data_new (length)) == NULL)
653 {
654 zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
655 ospf_lsa_unlock (&new);
656 new = NULL;
657 stream_free (s);
658 goto out;
659 }
660
661 new->area = OspfRI.area; /* Area must be null if the Opaque type is AS scope, fulfill otherwise */
662
663 SET_FLAG (new->flags, OSPF_LSA_SELF);
664 memcpy (new->data, lsah, length);
665 stream_free (s);
666
667 out:return new;
668 }
669
670 static int
671 ospf_router_info_lsa_originate1 (void *arg)
672 {
673 struct ospf_lsa *new;
674 struct ospf *top;
675 struct ospf_area *area;
676 int rc = -1;
677
678 /* First check if the area is known if flooding scope is Area */
679 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
680 {
681 area = (struct ospf_area *) arg;
682 if (area->area_id.s_addr != OspfRI.area_id.s_addr)
683 {
684 zlog_debug
685 ("RI -> This is not the Router Information Area. Stop processing");
686 goto out;
687 }
688 OspfRI.area = area;
689 }
690
691 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
692 if ((new = ospf_router_info_lsa_new ()) == NULL)
693 {
694 zlog_warn
695 ("ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?");
696 goto out;
697 }
698
699 /* Get ospf info */
700 top = ospf_lookup ();
701
702 /* Install this LSA into LSDB. */
703 if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
704 {
705 zlog_warn ("ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
706 ospf_lsa_unlock (&new);
707 goto out;
708 }
709
710 /* Now this Router Info parameter entry has associated LSA. */
711 SET_FLAG (OspfRI.flags, RIFLG_LSA_ENGAGED);
712
713 /* Update new LSA origination count. */
714 top->lsa_originate_count++;
715
716 /* Flood new LSA through AS. */
717 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
718 ospf_flood_through_as (top, NULL /*nbr */ , new);
719 else
720 ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new);
721
722 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
723 {
724 zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
725 new->data->type, inet_ntoa (new->data->id));
726 ospf_lsa_header_dump (new->data);
727 }
728
729 rc = 0;
730 out:return rc;
731 }
732
733 static int
734 ospf_router_info_lsa_originate (void *arg)
735 {
736
737 int rc = -1;
738
739 if (OspfRI.status == disabled)
740 {
741 zlog_info
742 ("ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
743 rc = 0; /* This is not an error case. */
744 goto out;
745 }
746
747 /* Check if Router Information LSA is already engaged */
748 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
749 {
750 if (OspfRI.flags & RIFLG_LSA_FORCED_REFRESH)
751 {
752 OspfRI.flags &= ~RIFLG_LSA_FORCED_REFRESH;
753 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
754 }
755 }
756 else
757 {
758 if (!is_mandated_params_set (OspfRI))
759 zlog_warn
760 ("ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
761
762 /* Ok, let's try to originate an LSA */
763 if (ospf_router_info_lsa_originate1 (arg) != 0)
764 goto out;
765 }
766
767 rc = 0;
768 out:return rc;
769 }
770
771 static struct ospf_lsa *
772 ospf_router_info_lsa_refresh (struct ospf_lsa *lsa)
773 {
774 struct ospf_lsa *new = NULL;
775 struct ospf *top;
776
777 if (OspfRI.status == disabled)
778 {
779 /*
780 * This LSA must have flushed before due to ROUTER INFORMATION status change.
781 * It seems a slip among routers in the routing domain.
782 */
783 zlog_info
784 ("ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
785 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
786 }
787
788 /* Verify that the Router Information ID is supported */
789 if (GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)) != 0)
790 {
791 zlog_warn
792 ("ospf_router_info_lsa_refresh: Unsupported Router Information ID");
793 goto out;
794 }
795
796 /* If the lsa's age reached to MaxAge, start flushing procedure. */
797 if (IS_LSA_MAXAGE (lsa))
798 {
799 OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
800 ospf_opaque_lsa_flush_schedule (lsa);
801 goto out;
802 }
803
804 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
805 if ((new = ospf_router_info_lsa_new ()) == NULL)
806 {
807 zlog_warn
808 ("ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?");
809 goto out;
810 }
811 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
812
813 /* Install this LSA into LSDB. */
814 /* Given "lsa" will be freed in the next function. */
815 top = ospf_lookup ();
816 if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
817 {
818 zlog_warn ("ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
819 ospf_lsa_unlock (&new);
820 goto out;
821 }
822
823 /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
824 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
825 ospf_flood_through_as (top, NULL /*nbr */ , new);
826 else
827 ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new);
828
829 /* Debug logging. */
830 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
831 {
832 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
833 new->data->type, inet_ntoa (new->data->id));
834 ospf_lsa_header_dump (new->data);
835 }
836
837 out:return new;
838 }
839
840 static void
841 ospf_router_info_lsa_schedule (opcode_t opcode)
842 {
843 struct ospf_lsa lsa;
844 struct lsa_header lsah;
845 struct ospf *top;
846 u_int32_t tmp;
847
848 memset (&lsa, 0, sizeof (lsa));
849 memset (&lsah, 0, sizeof (lsah));
850
851 zlog_debug ("RI-> LSA schedule %s%s%s",
852 opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
853 opcode == REFRESH_THIS_LSA ? "Refresh" : "",
854 opcode == FLUSH_THIS_LSA ? "Flush" : "");
855
856 top = ospf_lookup ();
857 if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL))
858 {
859 zlog_warn
860 ("ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
861 OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id);
862 }
863 lsa.area = OspfRI.area;
864 lsa.data = &lsah;
865 lsah.type = OspfRI.scope;
866
867 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
868 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
869 lsah.id.s_addr = htonl (tmp);
870
871 switch (opcode)
872 {
873 case REORIGINATE_THIS_LSA:
874 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
875 ospf_opaque_lsa_reoriginate_schedule ((void *) OspfRI.area,
876 OSPF_OPAQUE_AREA_LSA,
877 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
878 else
879 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
880 OSPF_OPAQUE_AS_LSA,
881 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
882 break;
883 case REFRESH_THIS_LSA:
884 ospf_opaque_lsa_refresh_schedule (&lsa);
885 break;
886 case FLUSH_THIS_LSA:
887 OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
888 ospf_opaque_lsa_flush_schedule (&lsa);
889 break;
890 default:
891 zlog_warn ("ospf_router_info_lsa_schedule: Unknown opcode (%u)",
892 opcode);
893 break;
894 }
895
896 return;
897 }
898
899 /*------------------------------------------------------------------------*
900 * Followings are vty session control functions.
901 *------------------------------------------------------------------------*/
902
903 static u_int16_t
904 show_vty_router_cap (struct vty *vty, struct ri_tlv_header *tlvh)
905 {
906 struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *) tlvh;
907
908 if (vty != NULL)
909 vty_outln (vty, " Router Capabilities: 0x%x",ntohl(top->value));
910 else
911 zlog_debug (" Router Capabilities: 0x%x", ntohl (top->value));
912
913 return RI_TLV_SIZE (tlvh);
914 }
915
916 static u_int16_t
917 show_vty_pce_subtlv_address (struct vty *vty, struct ri_tlv_header *tlvh)
918 {
919 struct ri_pce_subtlv_address *top = (struct ri_pce_subtlv_address *) tlvh;
920
921 if (ntohs (top->address.type) == PCE_ADDRESS_TYPE_IPV4)
922 {
923 if (vty != NULL)
924 vty_outln (vty, " PCE Address: %s",inet_ntoa(top->address.value));
925 else
926 zlog_debug (" PCE Address: %s", inet_ntoa (top->address.value));
927 }
928 else
929 {
930 /* TODO: Add support to IPv6 with inet_ntop() */
931 if (vty != NULL)
932 vty_outln (vty, " PCE Address: 0x%x",
933 ntohl(top->address.value.s_addr));
934 else
935 zlog_debug (" PCE Address: 0x%x",
936 ntohl (top->address.value.s_addr));
937 }
938
939 return RI_TLV_SIZE (tlvh);
940 }
941
942 static u_int16_t
943 show_vty_pce_subtlv_path_scope (struct vty *vty, struct ri_tlv_header *tlvh)
944 {
945 struct ri_pce_subtlv_path_scope *top =
946 (struct ri_pce_subtlv_path_scope *) tlvh;
947
948 if (vty != NULL)
949 vty_outln (vty, " PCE Path Scope: 0x%x",ntohl(top->value));
950 else
951 zlog_debug (" PCE Path Scope: 0x%x", ntohl (top->value));
952
953 return RI_TLV_SIZE (tlvh);
954 }
955
956 static u_int16_t
957 show_vty_pce_subtlv_domain (struct vty *vty, struct ri_tlv_header *tlvh)
958 {
959 struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *) tlvh;
960 struct in_addr tmp;
961
962 if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA)
963 {
964 tmp.s_addr = top->value;
965 if (vty != NULL)
966 vty_outln (vty, " PCE domain Area: %s",inet_ntoa(tmp));
967 else
968 zlog_debug (" PCE domain Area: %s", inet_ntoa (tmp));
969 }
970 else
971 {
972 if (vty != NULL)
973 vty_outln (vty, " PCE domain AS: %d",ntohl(top->value));
974 else
975 zlog_debug (" PCE domain AS: %d", ntohl (top->value));
976 }
977 return RI_TLV_SIZE (tlvh);
978 }
979
980 static u_int16_t
981 show_vty_pce_subtlv_neighbor (struct vty *vty, struct ri_tlv_header *tlvh)
982 {
983
984 struct ri_pce_subtlv_neighbor *top = (struct ri_pce_subtlv_neighbor *) tlvh;
985 struct in_addr tmp;
986
987 if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA)
988 {
989 tmp.s_addr = top->value;
990 if (vty != NULL)
991 vty_outln (vty, " PCE neighbor Area: %s",inet_ntoa(tmp));
992 else
993 zlog_debug (" PCE neighbor Area: %s", inet_ntoa (tmp));
994 }
995 else
996 {
997 if (vty != NULL)
998 vty_outln (vty, " PCE neighbor AS: %d",ntohl(top->value));
999 else
1000 zlog_debug (" PCE neighbor AS: %d", ntohl (top->value));
1001 }
1002 return RI_TLV_SIZE (tlvh);
1003 }
1004
1005 static u_int16_t
1006 show_vty_pce_subtlv_cap_flag (struct vty *vty, struct ri_tlv_header *tlvh)
1007 {
1008 struct ri_pce_subtlv_cap_flag *top = (struct ri_pce_subtlv_cap_flag *) tlvh;
1009
1010 if (vty != NULL)
1011 vty_outln (vty, " PCE Capabilities Flag: 0x%x",ntohl(top->value));
1012 else
1013 zlog_debug (" PCE Capabilities Flag: 0x%x", ntohl (top->value));
1014
1015 return RI_TLV_SIZE (tlvh);
1016 }
1017
1018 static u_int16_t
1019 show_vty_unknown_tlv (struct vty *vty, struct ri_tlv_header *tlvh)
1020 {
1021 if (vty != NULL)
1022 vty_outln (vty, " Unknown TLV: [type(0x%x), length(0x%x)]",
1023 ntohs (tlvh->type), ntohs(tlvh->length));
1024 else
1025 zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]",
1026 ntohs (tlvh->type), ntohs (tlvh->length));
1027
1028 return RI_TLV_SIZE (tlvh);
1029 }
1030
1031 static u_int16_t
1032 show_vty_pce_info (struct vty *vty, struct ri_tlv_header *ri, uint32_t total)
1033 {
1034 struct ri_tlv_header *tlvh;
1035 u_int16_t sum = 0;
1036
1037 for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT (tlvh))
1038 {
1039 switch (ntohs (tlvh->type))
1040 {
1041 case RI_PCE_SUBTLV_ADDRESS:
1042 sum += show_vty_pce_subtlv_address (vty, tlvh);
1043 break;
1044 case RI_PCE_SUBTLV_PATH_SCOPE:
1045 sum += show_vty_pce_subtlv_path_scope (vty, tlvh);
1046 break;
1047 case RI_PCE_SUBTLV_DOMAIN:
1048 sum += show_vty_pce_subtlv_domain (vty, tlvh);
1049 break;
1050 case RI_PCE_SUBTLV_NEIGHBOR:
1051 sum += show_vty_pce_subtlv_neighbor (vty, tlvh);
1052 break;
1053 case RI_PCE_SUBTLV_CAP_FLAG:
1054 sum += show_vty_pce_subtlv_cap_flag (vty, tlvh);
1055 break;
1056 default:
1057 sum += show_vty_unknown_tlv (vty, tlvh);
1058 break;
1059 }
1060 }
1061 return sum;
1062 }
1063
1064 static void
1065 ospf_router_info_show_info (struct vty *vty, struct ospf_lsa *lsa)
1066 {
1067 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1068 struct ri_tlv_header *tlvh;
1069 u_int16_t length = 0, sum = 0;
1070
1071 /* Initialize TLV browsing */
1072 length = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE;
1073
1074 for (tlvh = RI_TLV_HDR_TOP (lsah); sum < length;
1075 tlvh = RI_TLV_HDR_NEXT (tlvh))
1076 {
1077 switch (ntohs (tlvh->type))
1078 {
1079 case RI_TLV_CAPABILITIES:
1080 sum += show_vty_router_cap (vty, tlvh);
1081 break;
1082 case RI_TLV_PCE:
1083 tlvh++;
1084 sum += RI_TLV_HDR_SIZE;
1085 sum += show_vty_pce_info (vty, tlvh, length - sum);
1086 break;
1087 default:
1088 sum += show_vty_unknown_tlv (vty, tlvh);
1089 break;
1090 }
1091 }
1092
1093 return;
1094 }
1095
1096 static void
1097 ospf_router_info_config_write_router (struct vty *vty)
1098 {
1099 struct ospf_pce_info *pce = &OspfRI.pce_info;
1100 struct listnode *node;
1101 struct ri_pce_subtlv_domain *domain;
1102 struct ri_pce_subtlv_neighbor *neighbor;
1103 struct in_addr tmp;
1104
1105 if (OspfRI.status == enabled)
1106 {
1107 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1108 vty_outln (vty, " router-info as");
1109 else
1110 vty_outln (vty, " router-info area %s",inet_ntoa(OspfRI.area_id));
1111
1112 if (pce->pce_address.header.type != 0)
1113 vty_outln (vty, " pce address %s",
1114 inet_ntoa(pce->pce_address.address.value));
1115
1116 if (pce->pce_cap_flag.header.type != 0)
1117 vty_outln (vty, " pce flag 0x%x",ntohl(pce->pce_cap_flag.value));
1118
1119 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
1120 {
1121 if (domain->header.type != 0)
1122 {
1123 if (domain->type == PCE_DOMAIN_TYPE_AREA)
1124 {
1125 tmp.s_addr = domain->value;
1126 vty_outln (vty, " pce domain area %s",inet_ntoa(tmp));
1127 }
1128 else
1129 {
1130 vty_outln (vty, " pce domain as %d",ntohl(domain->value));
1131 }
1132 }
1133 }
1134
1135 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
1136 {
1137 if (neighbor->header.type != 0)
1138 {
1139 if (neighbor->type == PCE_DOMAIN_TYPE_AREA)
1140 {
1141 tmp.s_addr = neighbor->value;
1142 vty_outln (vty, " pce neighbor area %s",inet_ntoa(tmp));
1143 }
1144 else
1145 {
1146 vty_outln (vty, " pce neighbor as %d",
1147 ntohl(neighbor->value));
1148 }
1149 }
1150 }
1151
1152 if (pce->pce_scope.header.type != 0)
1153 vty_outln (vty, " pce scope 0x%x",
1154 ntohl(OspfRI.pce_info.pce_scope.value));
1155 }
1156 return;
1157 }
1158
1159 /*------------------------------------------------------------------------*
1160 * Followings are vty command functions.
1161 *------------------------------------------------------------------------*/
1162
1163 DEFUN (router_info,
1164 router_info_area_cmd,
1165 "router-info <as|area A.B.C.D>",
1166 OSPF_RI_STR
1167 "Enable the Router Information functionality with AS flooding scope\n"
1168 "Enable the Router Information functionality with Area flooding scope\n"
1169 "OSPF area ID in IP format")
1170 {
1171 int idx_ipv4 = 2;
1172 char *area = (argc == 3) ? argv[idx_ipv4]->arg : NULL;
1173
1174 u_int8_t scope;
1175
1176 if (OspfRI.status == enabled)
1177 return CMD_SUCCESS;
1178
1179 /* Check and get Area value if present */
1180 if (area)
1181 {
1182 if (!inet_aton (area, &OspfRI.area_id))
1183 {
1184 vty_outln (vty, "%% specified Area ID %s is invalid",
1185 area);
1186 return CMD_WARNING_CONFIG_FAILED;
1187 }
1188 scope = OSPF_OPAQUE_AREA_LSA;
1189 }
1190 else
1191 {
1192 OspfRI.area_id.s_addr = 0;
1193 scope = OSPF_OPAQUE_AS_LSA;
1194 }
1195
1196 /* First start to register Router Information callbacks */
1197 if ((ospf_router_info_register (scope)) != 0)
1198 {
1199 zlog_warn ("Enable to register Router Information callbacks. Abort!");
1200 return CMD_WARNING_CONFIG_FAILED;
1201 }
1202
1203 OspfRI.status = enabled;
1204
1205 if (IS_DEBUG_OSPF_EVENT)
1206 zlog_debug ("RI-> Router Information (%s flooding): OFF -> ON",
1207 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
1208
1209 /*
1210 * Following code is intended to handle two cases;
1211 *
1212 * 1) Router Information was disabled at startup time, but now become enabled.
1213 * 2) Router Information was once enabled then disabled, and now enabled again.
1214 */
1215
1216 initialize_params (&OspfRI);
1217
1218 /* Refresh RI LSA if already engaged */
1219 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1220 {
1221 zlog_debug ("RI-> Initial origination following configuration");
1222 ospf_router_info_lsa_schedule (REORIGINATE_THIS_LSA);
1223 }
1224 return CMD_SUCCESS;
1225
1226 }
1227
1228
1229 DEFUN (no_router_info,
1230 no_router_info_cmd,
1231 "no router-info",
1232 NO_STR
1233 "Disable the Router Information functionality\n")
1234 {
1235
1236 if (OspfRI.status == disabled)
1237 return CMD_SUCCESS;
1238
1239 if (IS_DEBUG_OSPF_EVENT)
1240 zlog_debug ("RI-> Router Information: ON -> OFF");
1241
1242 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1243 ospf_router_info_lsa_schedule (FLUSH_THIS_LSA);
1244
1245 /* Unregister the callbacks */
1246 ospf_router_info_unregister ();
1247
1248 OspfRI.status = disabled;
1249
1250 return CMD_SUCCESS;
1251 }
1252
1253 static int
1254 ospf_ri_enabled (struct vty *vty)
1255 {
1256 if (OspfRI.status == enabled)
1257 return 1;
1258
1259 if (vty)
1260 vty_outln (vty, "%% OSPF RI is not turned on");
1261
1262 return 0;
1263 }
1264
1265 DEFUN (pce_address,
1266 pce_address_cmd,
1267 "pce address A.B.C.D",
1268 PCE_STR
1269 "Stable IP address of the PCE\n"
1270 "PCE address in IPv4 address format\n")
1271 {
1272 int idx_ipv4 = 2;
1273 struct in_addr value;
1274 struct ospf_pce_info *pi = &OspfRI.pce_info;
1275
1276 if (!ospf_ri_enabled (vty))
1277 return CMD_WARNING_CONFIG_FAILED;
1278
1279 if (!inet_aton (argv[idx_ipv4]->arg, &value))
1280 {
1281 vty_outln (vty, "Please specify PCE Address by A.B.C.D");
1282 return CMD_WARNING_CONFIG_FAILED;
1283 }
1284
1285 if (ntohs (pi->pce_address.header.type) == 0
1286 || ntohl (pi->pce_address.address.value.s_addr) != ntohl (value.s_addr))
1287 {
1288
1289 set_pce_address (value, pi);
1290
1291 /* Refresh RI LSA if already engaged */
1292 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1293 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1294 }
1295
1296 return CMD_SUCCESS;
1297 }
1298
1299 DEFUN (no_pce_address,
1300 no_pce_address_cmd,
1301 "no pce address [A.B.C.D]",
1302 NO_STR
1303 PCE_STR
1304 "Disable PCE address\n"
1305 "PCE address in IPv4 address format\n")
1306 {
1307
1308 unset_param (&OspfRI.pce_info.pce_address.header);
1309
1310 /* Refresh RI LSA if already engaged */
1311 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1312 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1313
1314 return CMD_SUCCESS;
1315 }
1316
1317 DEFUN (pce_path_scope,
1318 pce_path_scope_cmd,
1319 "pce scope BITPATTERN",
1320 PCE_STR
1321 "Path scope visibilities of the PCE for path computation\n"
1322 "32-bit Hexadecimal value\n")
1323 {
1324 int idx_bitpattern = 2;
1325 uint32_t scope;
1326 struct ospf_pce_info *pi = &OspfRI.pce_info;
1327
1328 if (!ospf_ri_enabled (vty))
1329 return CMD_WARNING_CONFIG_FAILED;
1330
1331 if (sscanf (argv[idx_bitpattern]->arg, "0x%x", &scope) != 1)
1332 {
1333 vty_outln (vty, "pce_path_scope: fscanf: %s",safe_strerror(errno));
1334 return CMD_WARNING_CONFIG_FAILED;
1335 }
1336
1337 if (ntohl (pi->pce_scope.header.type) == 0 || scope != pi->pce_scope.value)
1338 {
1339 set_pce_path_scope (scope, pi);
1340
1341 /* Refresh RI LSA if already engaged */
1342 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1343 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1344 }
1345
1346 return CMD_SUCCESS;
1347 }
1348
1349 DEFUN (no_pce_path_scope,
1350 no_pce_path_scope_cmd,
1351 "no pce scope [BITPATTERN]",
1352 NO_STR
1353 PCE_STR
1354 "Disable PCE path scope\n"
1355 "32-bit Hexadecimal value\n")
1356 {
1357
1358 unset_param (&OspfRI.pce_info.pce_address.header);
1359
1360 /* Refresh RI LSA if already engaged */
1361 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1362 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1363
1364 return CMD_SUCCESS;
1365 }
1366
1367 DEFUN (pce_domain,
1368 pce_domain_cmd,
1369 "pce domain as (0-65535)",
1370 PCE_STR
1371 "Configure PCE domain AS number\n"
1372 "AS number where the PCE as visibilities for path computation\n"
1373 "AS number in decimal <0-65535>\n")
1374 {
1375 int idx_number = 3;
1376
1377 uint32_t as;
1378 struct ospf_pce_info *pce = &OspfRI.pce_info;
1379 struct listnode *node;
1380 struct ri_pce_subtlv_domain *domain;
1381
1382 if (!ospf_ri_enabled (vty))
1383 return CMD_WARNING_CONFIG_FAILED;
1384
1385 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
1386 {
1387 vty_outln (vty, "pce_domain: fscanf: %s",safe_strerror(errno));
1388 return CMD_WARNING_CONFIG_FAILED;
1389 }
1390
1391 /* Check if the domain is not already in the domain list */
1392 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
1393 {
1394 if (ntohl (domain->header.type) == 0 && as == domain->value)
1395 return CMD_SUCCESS;
1396 }
1397
1398 /* Create new domain if not found */
1399 set_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce);
1400
1401 /* Refresh RI LSA if already engaged */
1402 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1403 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1404
1405 return CMD_SUCCESS;
1406 }
1407
1408 DEFUN (no_pce_domain,
1409 no_pce_domain_cmd,
1410 "no pce domain as (0-65535)",
1411 NO_STR
1412 PCE_STR
1413 "Disable PCE domain AS number\n"
1414 "AS number where the PCE as visibilities for path computation\n"
1415 "AS number in decimal <0-65535>\n")
1416 {
1417 int idx_number = 4;
1418
1419 uint32_t as;
1420 struct ospf_pce_info *pce = &OspfRI.pce_info;
1421
1422 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
1423 {
1424 vty_outln (vty, "no_pce_domain: fscanf: %s",safe_strerror(errno));
1425 return CMD_WARNING_CONFIG_FAILED;
1426 }
1427
1428 /* Unset corresponding PCE domain */
1429 unset_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce);
1430
1431 /* Refresh RI LSA if already engaged */
1432 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1433 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1434
1435 return CMD_SUCCESS;
1436 }
1437
1438 DEFUN (pce_neigbhor,
1439 pce_neighbor_cmd,
1440 "pce neighbor as (0-65535)",
1441 PCE_STR
1442 "Configure PCE neighbor domain AS number\n"
1443 "AS number of PCE neighbors\n"
1444 "AS number in decimal <0-65535>\n")
1445 {
1446 int idx_number = 3;
1447
1448 uint32_t as;
1449 struct ospf_pce_info *pce = &OspfRI.pce_info;
1450 struct listnode *node;
1451 struct ri_pce_subtlv_neighbor *neighbor;
1452
1453 if (!ospf_ri_enabled (vty))
1454 return CMD_WARNING_CONFIG_FAILED;
1455
1456 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
1457 {
1458 vty_outln (vty, "pce_neighbor: fscanf: %s",safe_strerror(errno));
1459 return CMD_WARNING_CONFIG_FAILED;
1460 }
1461
1462 /* Check if the domain is not already in the domain list */
1463 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
1464 {
1465 if (ntohl (neighbor->header.type) == 0 && as == neighbor->value)
1466 return CMD_SUCCESS;
1467 }
1468
1469 /* Create new domain if not found */
1470 set_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce);
1471
1472 /* Refresh RI LSA if already engaged */
1473 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1474 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1475
1476 return CMD_SUCCESS;
1477 }
1478
1479 DEFUN (no_pce_neighbor,
1480 no_pce_neighbor_cmd,
1481 "no pce neighbor as (0-65535)",
1482 NO_STR
1483 PCE_STR
1484 "Disable PCE neighbor AS number\n"
1485 "AS number of PCE neighbor\n"
1486 "AS number in decimal <0-65535>\n")
1487 {
1488 int idx_number = 4;
1489
1490 uint32_t as;
1491 struct ospf_pce_info *pce = &OspfRI.pce_info;
1492
1493 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
1494 {
1495 vty_outln (vty, "no_pce_neighbor: fscanf: %s",safe_strerror(errno));
1496 return CMD_WARNING_CONFIG_FAILED;
1497 }
1498
1499 /* Unset corresponding PCE domain */
1500 unset_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce);
1501
1502 /* Refresh RI LSA if already engaged */
1503 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1504 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1505
1506 return CMD_SUCCESS;
1507 }
1508
1509 DEFUN (pce_cap_flag,
1510 pce_cap_flag_cmd,
1511 "pce flag BITPATTERN",
1512 PCE_STR
1513 "Capabilities of the PCE for path computation\n"
1514 "32-bit Hexadecimal value\n")
1515 {
1516 int idx_bitpattern = 2;
1517
1518 uint32_t cap;
1519 struct ospf_pce_info *pce = &OspfRI.pce_info;
1520
1521 if (!ospf_ri_enabled (vty))
1522 return CMD_WARNING_CONFIG_FAILED;
1523
1524 if (sscanf (argv[idx_bitpattern]->arg, "0x%x", &cap) != 1)
1525 {
1526 vty_outln (vty, "pce_cap_flag: fscanf: %s",safe_strerror(errno));
1527 return CMD_WARNING_CONFIG_FAILED;
1528 }
1529
1530 if (ntohl (pce->pce_cap_flag.header.type) == 0
1531 || cap != pce->pce_cap_flag.value)
1532 {
1533 set_pce_cap_flag (cap, pce);
1534
1535 /* Refresh RI LSA if already engaged */
1536 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1537 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1538 }
1539
1540 return CMD_SUCCESS;
1541 }
1542
1543 DEFUN (no_pce_cap_flag,
1544 no_pce_cap_flag_cmd,
1545 "no pce flag",
1546 NO_STR
1547 PCE_STR
1548 "Disable PCE capabilities\n")
1549 {
1550
1551 unset_param (&OspfRI.pce_info.pce_cap_flag.header);
1552
1553 /* Refresh RI LSA if already engaged */
1554 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1555 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1556
1557 return CMD_SUCCESS;
1558 }
1559
1560 DEFUN (show_ip_ospf_router_info,
1561 show_ip_ospf_router_info_cmd,
1562 "show ip ospf router-info",
1563 SHOW_STR
1564 IP_STR
1565 OSPF_STR
1566 "Router Information\n")
1567 {
1568
1569 if (OspfRI.status == enabled)
1570 {
1571 vty_outln (vty, "--- Router Information parameters ---");
1572 show_vty_router_cap (vty, &OspfRI.router_cap.header);
1573 }
1574 else
1575 {
1576 if (vty != NULL)
1577 vty_outln (vty, " Router Information is disabled on this router");
1578 }
1579 return CMD_SUCCESS;
1580 }
1581
1582 DEFUN (show_ip_opsf_router_info_pce,
1583 show_ip_ospf_router_info_pce_cmd,
1584 "show ip ospf router-info pce",
1585 SHOW_STR
1586 IP_STR
1587 OSPF_STR
1588 "Router Information\n"
1589 "PCE information\n")
1590 {
1591
1592 struct ospf_pce_info *pce = &OspfRI.pce_info;
1593 struct listnode *node;
1594 struct ri_pce_subtlv_domain *domain;
1595 struct ri_pce_subtlv_neighbor *neighbor;
1596
1597 if (OspfRI.status == enabled)
1598 {
1599 vty_outln (vty, "--- PCE parameters ---");
1600
1601 if (pce->pce_address.header.type != 0)
1602 show_vty_pce_subtlv_address (vty, &pce->pce_address.header);
1603
1604 if (pce->pce_scope.header.type != 0)
1605 show_vty_pce_subtlv_path_scope (vty, &pce->pce_scope.header);
1606
1607 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
1608 {
1609 if (domain->header.type != 0)
1610 show_vty_pce_subtlv_domain (vty, &domain->header);
1611 }
1612
1613 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
1614 {
1615 if (neighbor->header.type != 0)
1616 show_vty_pce_subtlv_neighbor (vty, &neighbor->header);
1617 }
1618
1619 if (pce->pce_cap_flag.header.type != 0)
1620 show_vty_pce_subtlv_cap_flag (vty, &pce->pce_cap_flag.header);
1621
1622 }
1623 else
1624 {
1625 vty_outln (vty," Router Information is disabled on this router");
1626 }
1627
1628 return CMD_SUCCESS;
1629 }
1630
1631 /* Install new CLI commands */
1632 static void
1633 ospf_router_info_register_vty (void)
1634 {
1635 install_element (VIEW_NODE, &show_ip_ospf_router_info_cmd);
1636 install_element (VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
1637
1638 install_element (OSPF_NODE, &router_info_area_cmd);
1639 install_element (OSPF_NODE, &no_router_info_cmd);
1640 install_element (OSPF_NODE, &pce_address_cmd);
1641 install_element (OSPF_NODE, &no_pce_address_cmd);
1642 install_element (OSPF_NODE, &pce_path_scope_cmd);
1643 install_element (OSPF_NODE, &no_pce_path_scope_cmd);
1644 install_element (OSPF_NODE, &pce_domain_cmd);
1645 install_element (OSPF_NODE, &no_pce_domain_cmd);
1646 install_element (OSPF_NODE, &pce_neighbor_cmd);
1647 install_element (OSPF_NODE, &no_pce_neighbor_cmd);
1648 install_element (OSPF_NODE, &pce_cap_flag_cmd);
1649 install_element (OSPF_NODE, &no_pce_cap_flag_cmd);
1650
1651 return;
1652 }