]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_ri.c
*: add indent control files
[mirror_frr.git] / ospfd / ospf_ri.c
CommitLineData
0ef4bcdc
OD
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 *
896014f4
DL
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
0ef4bcdc
OD
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
61struct 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. */
74struct 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 */
102static struct ospf_router_info OspfRI;
103
104/*------------------------------------------------------------------------------*
105 * Followings are initialize/terminate functions for Router Information handling.
106 *------------------------------------------------------------------------------*/
107
108static void ospf_router_info_ism_change (struct ospf_interface *oi,
109 int old_status);
110static void ospf_router_info_nsm_change (struct ospf_neighbor *nbr,
111 int old_status);
112static void ospf_router_info_config_write_router (struct vty *vty);
113static void ospf_router_info_show_info (struct vty *vty,
114 struct ospf_lsa *lsa);
115static int ospf_router_info_lsa_originate (void *arg);
116static struct ospf_lsa *ospf_router_info_lsa_refresh (struct ospf_lsa *lsa);
117static void ospf_router_info_lsa_schedule (opcode_t opcode);
118static void ospf_router_info_register_vty (void);
119static void del_pce_info (void *val);
120
121int
122ospf_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
142static int
143ospf_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
178static int
179ospf_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
197void
198ospf_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
213static void
214del_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
224static void
225set_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
233static int
234set_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
281static void
282set_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
296static void
297set_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
310static void
311set_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
335static void
336unset_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
366static void
367set_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
391static void
392unset_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
423static void
424set_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
438static void
439unset_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
450static void
451initialize_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
496static int
497is_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
511out:
512 return rc;
513}
514
515/*------------------------------------------------------------------------*
516 * Followings are callback functions against generic Opaque-LSAs handling.
517 *------------------------------------------------------------------------*/
518static void
519ospf_router_info_ism_change (struct ospf_interface *oi, int old_state)
520{
521 /* So far, nothing to do here. */
522 return;
523
524}
525
526static void
527ospf_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
538static void
539build_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
546static void
547build_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
558static void
559ospf_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. */
600static struct ospf_lsa *
601ospf_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
667out:return new;
668}
669
670static int
671ospf_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;
730out:return rc;
731}
732
733static int
734ospf_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;
768out:return rc;
769}
770
771static struct ospf_lsa *
772ospf_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
837out:return new;
838}
839
840static void
841ospf_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
903static u_int16_t
904show_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)
5c7571d4 909 vty_out (vty, " Router Capabilities: 0x%x\n",ntohl(top->value));
96ade3ed
QY
910 else
911 zlog_debug (" Router Capabilities: 0x%x", ntohl (top->value));
0ef4bcdc
OD
912
913 return RI_TLV_SIZE (tlvh);
914}
915
916static u_int16_t
917show_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)
5c7571d4 924 vty_out (vty, " PCE Address: %s\n",inet_ntoa(top->address.value));
96ade3ed
QY
925 else
926 zlog_debug (" PCE Address: %s", inet_ntoa (top->address.value));
0ef4bcdc
OD
927 }
928 else
929 {
930 /* TODO: Add support to IPv6 with inet_ntop() */
931 if (vty != NULL)
5c7571d4 932 vty_out (vty, " PCE Address: 0x%x\n",
96ade3ed
QY
933 ntohl(top->address.value.s_addr));
934 else
935 zlog_debug (" PCE Address: 0x%x",
936 ntohl (top->address.value.s_addr));
0ef4bcdc
OD
937 }
938
939 return RI_TLV_SIZE (tlvh);
940}
941
942static u_int16_t
943show_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)
5c7571d4 949 vty_out (vty, " PCE Path Scope: 0x%x\n",ntohl(top->value));
96ade3ed
QY
950 else
951 zlog_debug (" PCE Path Scope: 0x%x", ntohl (top->value));
0ef4bcdc
OD
952
953 return RI_TLV_SIZE (tlvh);
954}
955
956static u_int16_t
957show_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)
5c7571d4 966 vty_out (vty, " PCE domain Area: %s\n",inet_ntoa(tmp));
96ade3ed
QY
967 else
968 zlog_debug (" PCE domain Area: %s", inet_ntoa (tmp));
0ef4bcdc
OD
969 }
970 else
971 {
972 if (vty != NULL)
5c7571d4 973 vty_out (vty, " PCE domain AS: %d\n",ntohl(top->value));
96ade3ed
QY
974 else
975 zlog_debug (" PCE domain AS: %d", ntohl (top->value));
0ef4bcdc
OD
976 }
977 return RI_TLV_SIZE (tlvh);
978}
979
980static u_int16_t
981show_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)
5c7571d4 991 vty_out (vty, " PCE neighbor Area: %s\n",inet_ntoa(tmp));
96ade3ed
QY
992 else
993 zlog_debug (" PCE neighbor Area: %s", inet_ntoa (tmp));
0ef4bcdc
OD
994 }
995 else
996 {
997 if (vty != NULL)
5c7571d4 998 vty_out (vty, " PCE neighbor AS: %d\n",ntohl(top->value));
96ade3ed
QY
999 else
1000 zlog_debug (" PCE neighbor AS: %d", ntohl (top->value));
0ef4bcdc
OD
1001 }
1002 return RI_TLV_SIZE (tlvh);
1003}
1004
1005static u_int16_t
1006show_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)
5c7571d4 1011 vty_out (vty, " PCE Capabilities Flag: 0x%x\n",ntohl(top->value));
96ade3ed
QY
1012 else
1013 zlog_debug (" PCE Capabilities Flag: 0x%x", ntohl (top->value));
0ef4bcdc
OD
1014
1015 return RI_TLV_SIZE (tlvh);
1016}
1017
1018static u_int16_t
1019show_vty_unknown_tlv (struct vty *vty, struct ri_tlv_header *tlvh)
1020{
1021 if (vty != NULL)
5c7571d4 1022 vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
96ade3ed
QY
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));
0ef4bcdc
OD
1027
1028 return RI_TLV_SIZE (tlvh);
1029}
1030
1031static u_int16_t
1032show_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
1064static void
1065ospf_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
1096static void
1097ospf_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)
5c7571d4 1108 vty_out (vty, " router-info as\n");
0ef4bcdc 1109 else
5c7571d4 1110 vty_out (vty, " router-info area %s\n",inet_ntoa(OspfRI.area_id));
0ef4bcdc
OD
1111
1112 if (pce->pce_address.header.type != 0)
5c7571d4 1113 vty_out (vty, " pce address %s\n",
96ade3ed 1114 inet_ntoa(pce->pce_address.address.value));
0ef4bcdc
OD
1115
1116 if (pce->pce_cap_flag.header.type != 0)
5c7571d4 1117 vty_out (vty, " pce flag 0x%x\n",ntohl(pce->pce_cap_flag.value));
0ef4bcdc
OD
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;
5c7571d4 1126 vty_out (vty, " pce domain area %s\n",inet_ntoa(tmp));
0ef4bcdc
OD
1127 }
1128 else
1129 {
5c7571d4 1130 vty_out (vty, " pce domain as %d\n",ntohl(domain->value));
0ef4bcdc
OD
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;
5c7571d4 1142 vty_out (vty, " pce neighbor area %s\n",inet_ntoa(tmp));
0ef4bcdc
OD
1143 }
1144 else
1145 {
5c7571d4 1146 vty_out (vty, " pce neighbor as %d\n",
96ade3ed 1147 ntohl(neighbor->value));
0ef4bcdc
OD
1148 }
1149 }
1150 }
1151
1152 if (pce->pce_scope.header.type != 0)
5c7571d4 1153 vty_out (vty, " pce scope 0x%x\n",
96ade3ed 1154 ntohl(OspfRI.pce_info.pce_scope.value));
0ef4bcdc
OD
1155 }
1156 return;
1157}
1158
1159/*------------------------------------------------------------------------*
1160 * Followings are vty command functions.
1161 *------------------------------------------------------------------------*/
1162
1163DEFUN (router_info,
1164 router_info_area_cmd,
692b4c65 1165 "router-info <as|area A.B.C.D>",
0ef4bcdc 1166 OSPF_RI_STR
692b4c65 1167 "Enable the Router Information functionality with AS flooding scope\n"
0ef4bcdc
OD
1168 "Enable the Router Information functionality with Area flooding scope\n"
1169 "OSPF area ID in IP format")
1170{
8d769265 1171 int idx_ipv4 = 2;
ff788d08 1172 char *area = (argc == 3) ? argv[idx_ipv4]->arg : NULL;
0ef4bcdc
OD
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 */
692b4c65 1180 if (area)
0ef4bcdc 1181 {
e6fda497
DS
1182 if (!inet_aton (area, &OspfRI.area_id))
1183 {
5c7571d4 1184 vty_out (vty, "%% specified Area ID %s is invalid\n",
96ade3ed 1185 area);
f1a05de9 1186 return CMD_WARNING_CONFIG_FAILED;
e6fda497 1187 }
0ef4bcdc
OD
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!");
f1a05de9 1200 return CMD_WARNING_CONFIG_FAILED;
0ef4bcdc
OD
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
0ef4bcdc
OD
1228
1229DEFUN (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
284a4a0c
DS
1253static int
1254ospf_ri_enabled (struct vty *vty)
1255{
1256 if (OspfRI.status == enabled)
1257 return 1;
1258
1259 if (vty)
5c7571d4 1260 vty_out (vty, "%% OSPF RI is not turned on\n");
284a4a0c
DS
1261
1262 return 0;
1263}
1264
0ef4bcdc
OD
1265DEFUN (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{
8d769265 1272 int idx_ipv4 = 2;
0ef4bcdc
OD
1273 struct in_addr value;
1274 struct ospf_pce_info *pi = &OspfRI.pce_info;
1275
284a4a0c 1276 if (!ospf_ri_enabled (vty))
f1a05de9 1277 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1278
8d769265 1279 if (!inet_aton (argv[idx_ipv4]->arg, &value))
0ef4bcdc 1280 {
5c7571d4 1281 vty_out (vty, "Please specify PCE Address by A.B.C.D\n");
f1a05de9 1282 return CMD_WARNING_CONFIG_FAILED;
0ef4bcdc
OD
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 */
284a4a0c 1292 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1293 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1294 }
1295
1296 return CMD_SUCCESS;
1297}
1298
1299DEFUN (no_pce_address,
1300 no_pce_address_cmd,
2328428d 1301 "no pce address [A.B.C.D]",
0ef4bcdc
OD
1302 NO_STR
1303 PCE_STR
59768a63
DS
1304 "Disable PCE address\n"
1305 "PCE address in IPv4 address format\n")
0ef4bcdc
OD
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
1317DEFUN (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{
8d769265 1324 int idx_bitpattern = 2;
0ef4bcdc
OD
1325 uint32_t scope;
1326 struct ospf_pce_info *pi = &OspfRI.pce_info;
1327
284a4a0c 1328 if (!ospf_ri_enabled (vty))
f1a05de9 1329 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1330
8d769265 1331 if (sscanf (argv[idx_bitpattern]->arg, "0x%x", &scope) != 1)
0ef4bcdc 1332 {
5c7571d4 1333 vty_out (vty, "pce_path_scope: fscanf: %s\n",safe_strerror(errno));
f1a05de9 1334 return CMD_WARNING_CONFIG_FAILED;
0ef4bcdc
OD
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 */
284a4a0c 1342 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1343 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1344 }
1345
1346 return CMD_SUCCESS;
1347}
1348
1349DEFUN (no_pce_path_scope,
1350 no_pce_path_scope_cmd,
2328428d 1351 "no pce scope [BITPATTERN]",
0ef4bcdc
OD
1352 NO_STR
1353 PCE_STR
59768a63
DS
1354 "Disable PCE path scope\n"
1355 "32-bit Hexadecimal value\n")
0ef4bcdc
OD
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
1367DEFUN (pce_domain,
1368 pce_domain_cmd,
6147e2c6 1369 "pce domain as (0-65535)",
0ef4bcdc
OD
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{
8d769265 1375 int idx_number = 3;
0ef4bcdc
OD
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
284a4a0c 1382 if (!ospf_ri_enabled (vty))
f1a05de9 1383 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1384
8d769265 1385 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
0ef4bcdc 1386 {
5c7571d4 1387 vty_out (vty, "pce_domain: fscanf: %s\n",safe_strerror(errno));
f1a05de9 1388 return CMD_WARNING_CONFIG_FAILED;
0ef4bcdc
OD
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)
284a4a0c 1395 return CMD_SUCCESS;
0ef4bcdc
OD
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 */
284a4a0c 1402 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1403 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1404
284a4a0c 1405 return CMD_SUCCESS;
0ef4bcdc
OD
1406}
1407
1408DEFUN (no_pce_domain,
1409 no_pce_domain_cmd,
6147e2c6 1410 "no pce domain as (0-65535)",
0ef4bcdc
OD
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{
8d769265 1417 int idx_number = 4;
0ef4bcdc
OD
1418
1419 uint32_t as;
1420 struct ospf_pce_info *pce = &OspfRI.pce_info;
1421
8d769265 1422 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
0ef4bcdc 1423 {
5c7571d4 1424 vty_out (vty, "no_pce_domain: fscanf: %s\n",safe_strerror(errno));
f1a05de9 1425 return CMD_WARNING_CONFIG_FAILED;
0ef4bcdc
OD
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
1438DEFUN (pce_neigbhor,
1439 pce_neighbor_cmd,
6147e2c6 1440 "pce neighbor as (0-65535)",
0ef4bcdc
OD
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{
8d769265 1446 int idx_number = 3;
0ef4bcdc
OD
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
284a4a0c 1453 if (!ospf_ri_enabled (vty))
f1a05de9 1454 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1455
8d769265 1456 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
0ef4bcdc 1457 {
5c7571d4 1458 vty_out (vty, "pce_neighbor: fscanf: %s\n",safe_strerror(errno));
f1a05de9 1459 return CMD_WARNING_CONFIG_FAILED;
0ef4bcdc
OD
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)
284a4a0c 1466 return CMD_SUCCESS;
0ef4bcdc
OD
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 */
284a4a0c 1473 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1474 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1475
284a4a0c 1476 return CMD_SUCCESS;
0ef4bcdc
OD
1477}
1478
1479DEFUN (no_pce_neighbor,
1480 no_pce_neighbor_cmd,
6147e2c6 1481 "no pce neighbor as (0-65535)",
0ef4bcdc
OD
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{
8d769265 1488 int idx_number = 4;
0ef4bcdc
OD
1489
1490 uint32_t as;
1491 struct ospf_pce_info *pce = &OspfRI.pce_info;
1492
8d769265 1493 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
0ef4bcdc 1494 {
5c7571d4 1495 vty_out (vty, "no_pce_neighbor: fscanf: %s\n",safe_strerror(errno));
f1a05de9 1496 return CMD_WARNING_CONFIG_FAILED;
0ef4bcdc
OD
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
1509DEFUN (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{
8d769265 1516 int idx_bitpattern = 2;
0ef4bcdc
OD
1517
1518 uint32_t cap;
1519 struct ospf_pce_info *pce = &OspfRI.pce_info;
1520
284a4a0c 1521 if (!ospf_ri_enabled (vty))
f1a05de9 1522 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1523
8d769265 1524 if (sscanf (argv[idx_bitpattern]->arg, "0x%x", &cap) != 1)
0ef4bcdc 1525 {
5c7571d4 1526 vty_out (vty, "pce_cap_flag: fscanf: %s\n",safe_strerror(errno));
f1a05de9 1527 return CMD_WARNING_CONFIG_FAILED;
0ef4bcdc
OD
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 */
284a4a0c 1536 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1537 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1538 }
1539
1540 return CMD_SUCCESS;
1541}
1542
1543DEFUN (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
1560DEFUN (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 {
5c7571d4 1571 vty_out (vty, "--- Router Information parameters ---\n");
0ef4bcdc
OD
1572 show_vty_router_cap (vty, &OspfRI.router_cap.header);
1573 }
1574 else
1575 {
1576 if (vty != NULL)
5c7571d4 1577 vty_out (vty, " Router Information is disabled on this router\n");
0ef4bcdc
OD
1578 }
1579 return CMD_SUCCESS;
1580}
1581
1582DEFUN (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 {
5c7571d4 1599 vty_out (vty, "--- PCE parameters ---\n");
0ef4bcdc
OD
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 {
5c7571d4 1625 vty_out (vty," Router Information is disabled on this router\n");
0ef4bcdc
OD
1626 }
1627
1628 return CMD_SUCCESS;
1629}
1630
1631/* Install new CLI commands */
1632static void
1633ospf_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);
0ef4bcdc
OD
1637
1638 install_element (OSPF_NODE, &router_info_area_cmd);
0ef4bcdc
OD
1639 install_element (OSPF_NODE, &no_router_info_cmd);
1640 install_element (OSPF_NODE, &pce_address_cmd);
59768a63 1641 install_element (OSPF_NODE, &no_pce_address_cmd);
0ef4bcdc 1642 install_element (OSPF_NODE, &pce_path_scope_cmd);
59768a63 1643 install_element (OSPF_NODE, &no_pce_path_scope_cmd);
0ef4bcdc
OD
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);
d7d73ffc 1649 install_element (OSPF_NODE, &no_pce_cap_flag_cmd);
0ef4bcdc
OD
1650
1651 return;
1652}