]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_ri.c
*: make consistent & update GPLv2 file headers
[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)
909 vty_out (vty, " Router Capabilities: 0x%x%s", ntohl (top->value),
910 VTY_NEWLINE);
911 else
912 zlog_debug (" Router Capabilities: 0x%x", ntohl (top->value));
913
914 return RI_TLV_SIZE (tlvh);
915}
916
917static u_int16_t
918show_vty_pce_subtlv_address (struct vty *vty, struct ri_tlv_header *tlvh)
919{
920 struct ri_pce_subtlv_address *top = (struct ri_pce_subtlv_address *) tlvh;
921
922 if (ntohs (top->address.type) == PCE_ADDRESS_TYPE_IPV4)
923 {
924 if (vty != NULL)
925 vty_out (vty, " PCE Address: %s%s", inet_ntoa (top->address.value),
926 VTY_NEWLINE);
927 else
928 zlog_debug (" PCE Address: %s", inet_ntoa (top->address.value));
929 }
930 else
931 {
932 /* TODO: Add support to IPv6 with inet_ntop() */
933 if (vty != NULL)
934 vty_out (vty, " PCE Address: 0x%x%s",
935 ntohl (top->address.value.s_addr), VTY_NEWLINE);
936 else
937 zlog_debug (" PCE Address: 0x%x",
938 ntohl (top->address.value.s_addr));
939 }
940
941 return RI_TLV_SIZE (tlvh);
942}
943
944static u_int16_t
945show_vty_pce_subtlv_path_scope (struct vty *vty, struct ri_tlv_header *tlvh)
946{
947 struct ri_pce_subtlv_path_scope *top =
948 (struct ri_pce_subtlv_path_scope *) tlvh;
949
950 if (vty != NULL)
951 vty_out (vty, " PCE Path Scope: 0x%x%s", ntohl (top->value),
952 VTY_NEWLINE);
953 else
954 zlog_debug (" PCE Path Scope: 0x%x", ntohl (top->value));
955
956 return RI_TLV_SIZE (tlvh);
957}
958
959static u_int16_t
960show_vty_pce_subtlv_domain (struct vty *vty, struct ri_tlv_header *tlvh)
961{
962 struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *) tlvh;
963 struct in_addr tmp;
964
965 if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA)
966 {
967 tmp.s_addr = top->value;
968 if (vty != NULL)
969 vty_out (vty, " PCE domain Area: %s%s", inet_ntoa (tmp),
970 VTY_NEWLINE);
971 else
972 zlog_debug (" PCE domain Area: %s", inet_ntoa (tmp));
973 }
974 else
975 {
976 if (vty != NULL)
977 vty_out (vty, " PCE domain AS: %d%s", ntohl (top->value),
978 VTY_NEWLINE);
979 else
980 zlog_debug (" PCE domain AS: %d", ntohl (top->value));
981 }
982 return RI_TLV_SIZE (tlvh);
983}
984
985static u_int16_t
986show_vty_pce_subtlv_neighbor (struct vty *vty, struct ri_tlv_header *tlvh)
987{
988
989 struct ri_pce_subtlv_neighbor *top = (struct ri_pce_subtlv_neighbor *) tlvh;
990 struct in_addr tmp;
991
992 if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA)
993 {
994 tmp.s_addr = top->value;
995 if (vty != NULL)
996 vty_out (vty, " PCE neighbor Area: %s%s", inet_ntoa (tmp),
997 VTY_NEWLINE);
998 else
999 zlog_debug (" PCE neighbor Area: %s", inet_ntoa (tmp));
1000 }
1001 else
1002 {
1003 if (vty != NULL)
1004 vty_out (vty, " PCE neighbor AS: %d%s", ntohl (top->value),
1005 VTY_NEWLINE);
1006 else
1007 zlog_debug (" PCE neighbor AS: %d", ntohl (top->value));
1008 }
1009 return RI_TLV_SIZE (tlvh);
1010}
1011
1012static u_int16_t
1013show_vty_pce_subtlv_cap_flag (struct vty *vty, struct ri_tlv_header *tlvh)
1014{
1015 struct ri_pce_subtlv_cap_flag *top = (struct ri_pce_subtlv_cap_flag *) tlvh;
1016
1017 if (vty != NULL)
1018 vty_out (vty, " PCE Capabilities Flag: 0x%x%s", ntohl (top->value),
1019 VTY_NEWLINE);
1020 else
1021 zlog_debug (" PCE Capabilities Flag: 0x%x", ntohl (top->value));
1022
1023 return RI_TLV_SIZE (tlvh);
1024}
1025
1026static u_int16_t
1027show_vty_unknown_tlv (struct vty *vty, struct ri_tlv_header *tlvh)
1028{
1029 if (vty != NULL)
1030 vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]%s",
1031 ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
1032 else
1033 zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]",
1034 ntohs (tlvh->type), ntohs (tlvh->length));
1035
1036 return RI_TLV_SIZE (tlvh);
1037}
1038
1039static u_int16_t
1040show_vty_pce_info (struct vty *vty, struct ri_tlv_header *ri, uint32_t total)
1041{
1042 struct ri_tlv_header *tlvh;
1043 u_int16_t sum = 0;
1044
1045 for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT (tlvh))
1046 {
1047 switch (ntohs (tlvh->type))
1048 {
1049 case RI_PCE_SUBTLV_ADDRESS:
1050 sum += show_vty_pce_subtlv_address (vty, tlvh);
1051 break;
1052 case RI_PCE_SUBTLV_PATH_SCOPE:
1053 sum += show_vty_pce_subtlv_path_scope (vty, tlvh);
1054 break;
1055 case RI_PCE_SUBTLV_DOMAIN:
1056 sum += show_vty_pce_subtlv_domain (vty, tlvh);
1057 break;
1058 case RI_PCE_SUBTLV_NEIGHBOR:
1059 sum += show_vty_pce_subtlv_neighbor (vty, tlvh);
1060 break;
1061 case RI_PCE_SUBTLV_CAP_FLAG:
1062 sum += show_vty_pce_subtlv_cap_flag (vty, tlvh);
1063 break;
1064 default:
1065 sum += show_vty_unknown_tlv (vty, tlvh);
1066 break;
1067 }
1068 }
1069 return sum;
1070}
1071
1072static void
1073ospf_router_info_show_info (struct vty *vty, struct ospf_lsa *lsa)
1074{
1075 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1076 struct ri_tlv_header *tlvh;
1077 u_int16_t length = 0, sum = 0;
1078
1079 /* Initialize TLV browsing */
1080 length = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE;
1081
1082 for (tlvh = RI_TLV_HDR_TOP (lsah); sum < length;
1083 tlvh = RI_TLV_HDR_NEXT (tlvh))
1084 {
1085 switch (ntohs (tlvh->type))
1086 {
1087 case RI_TLV_CAPABILITIES:
1088 sum += show_vty_router_cap (vty, tlvh);
1089 break;
1090 case RI_TLV_PCE:
1091 tlvh++;
1092 sum += RI_TLV_HDR_SIZE;
1093 sum += show_vty_pce_info (vty, tlvh, length - sum);
1094 break;
1095 default:
1096 sum += show_vty_unknown_tlv (vty, tlvh);
1097 break;
1098 }
1099 }
1100
1101 return;
1102}
1103
1104static void
1105ospf_router_info_config_write_router (struct vty *vty)
1106{
1107 struct ospf_pce_info *pce = &OspfRI.pce_info;
1108 struct listnode *node;
1109 struct ri_pce_subtlv_domain *domain;
1110 struct ri_pce_subtlv_neighbor *neighbor;
1111 struct in_addr tmp;
1112
1113 if (OspfRI.status == enabled)
1114 {
1115 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1116 vty_out (vty, " router-info as%s", VTY_NEWLINE);
1117 else
1118 vty_out (vty, " router-info area %s%s", inet_ntoa (OspfRI.area_id),
1119 VTY_NEWLINE);
1120
1121 if (pce->pce_address.header.type != 0)
1122 vty_out (vty, " pce address %s%s",
1123 inet_ntoa (pce->pce_address.address.value), VTY_NEWLINE);
1124
1125 if (pce->pce_cap_flag.header.type != 0)
1126 vty_out (vty, " pce flag 0x%x%s", ntohl (pce->pce_cap_flag.value),
1127 VTY_NEWLINE);
1128
1129 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
1130 {
1131 if (domain->header.type != 0)
1132 {
1133 if (domain->type == PCE_DOMAIN_TYPE_AREA)
1134 {
1135 tmp.s_addr = domain->value;
1136 vty_out (vty, " pce domain area %s%s", inet_ntoa (tmp),
1137 VTY_NEWLINE);
1138 }
1139 else
1140 {
1141 vty_out (vty, " pce domain as %d%s", ntohl (domain->value),
1142 VTY_NEWLINE);
1143 }
1144 }
1145 }
1146
1147 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
1148 {
1149 if (neighbor->header.type != 0)
1150 {
1151 if (neighbor->type == PCE_DOMAIN_TYPE_AREA)
1152 {
1153 tmp.s_addr = neighbor->value;
1154 vty_out (vty, " pce neighbor area %s%s", inet_ntoa (tmp),
1155 VTY_NEWLINE);
1156 }
1157 else
1158 {
1159 vty_out (vty, " pce neighbor as %d%s",
1160 ntohl (neighbor->value), VTY_NEWLINE);
1161 }
1162 }
1163 }
1164
1165 if (pce->pce_scope.header.type != 0)
1166 vty_out (vty, " pce scope 0x%x%s",
1167 ntohl (OspfRI.pce_info.pce_scope.value), VTY_NEWLINE);
1168 }
1169 return;
1170}
1171
1172/*------------------------------------------------------------------------*
1173 * Followings are vty command functions.
1174 *------------------------------------------------------------------------*/
1175
1176DEFUN (router_info,
1177 router_info_area_cmd,
692b4c65 1178 "router-info <as|area A.B.C.D>",
0ef4bcdc 1179 OSPF_RI_STR
692b4c65 1180 "Enable the Router Information functionality with AS flooding scope\n"
0ef4bcdc
OD
1181 "Enable the Router Information functionality with Area flooding scope\n"
1182 "OSPF area ID in IP format")
1183{
8d769265 1184 int idx_ipv4 = 2;
ff788d08 1185 char *area = (argc == 3) ? argv[idx_ipv4]->arg : NULL;
0ef4bcdc
OD
1186
1187 u_int8_t scope;
1188
1189 if (OspfRI.status == enabled)
1190 return CMD_SUCCESS;
1191
1192 /* Check and get Area value if present */
692b4c65 1193 if (area)
0ef4bcdc 1194 {
692b4c65 1195 inet_aton (area, &OspfRI.area_id);
0ef4bcdc
OD
1196 scope = OSPF_OPAQUE_AREA_LSA;
1197 }
1198 else
1199 {
1200 OspfRI.area_id.s_addr = 0;
1201 scope = OSPF_OPAQUE_AS_LSA;
1202 }
1203
1204 /* First start to register Router Information callbacks */
1205 if ((ospf_router_info_register (scope)) != 0)
1206 {
1207 zlog_warn ("Enable to register Router Information callbacks. Abort!");
1208 return CMD_WARNING;
1209 }
1210
1211 OspfRI.status = enabled;
1212
1213 if (IS_DEBUG_OSPF_EVENT)
1214 zlog_debug ("RI-> Router Information (%s flooding): OFF -> ON",
1215 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
1216
1217 /*
1218 * Following code is intended to handle two cases;
1219 *
1220 * 1) Router Information was disabled at startup time, but now become enabled.
1221 * 2) Router Information was once enabled then disabled, and now enabled again.
1222 */
1223
1224 initialize_params (&OspfRI);
1225
1226 /* Refresh RI LSA if already engaged */
1227 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1228 {
1229 zlog_debug ("RI-> Initial origination following configuration");
1230 ospf_router_info_lsa_schedule (REORIGINATE_THIS_LSA);
1231 }
1232 return CMD_SUCCESS;
1233
1234}
1235
0ef4bcdc
OD
1236
1237DEFUN (no_router_info,
1238 no_router_info_cmd,
1239 "no router-info",
1240 NO_STR
1241 "Disable the Router Information functionality\n")
1242{
1243
1244 if (OspfRI.status == disabled)
1245 return CMD_SUCCESS;
1246
1247 if (IS_DEBUG_OSPF_EVENT)
1248 zlog_debug ("RI-> Router Information: ON -> OFF");
1249
1250 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1251 ospf_router_info_lsa_schedule (FLUSH_THIS_LSA);
1252
1253 /* Unregister the callbacks */
1254 ospf_router_info_unregister ();
1255
1256 OspfRI.status = disabled;
1257
1258 return CMD_SUCCESS;
1259}
1260
284a4a0c
DS
1261static int
1262ospf_ri_enabled (struct vty *vty)
1263{
1264 if (OspfRI.status == enabled)
1265 return 1;
1266
1267 if (vty)
1268 vty_out (vty, "%% OSPF RI is not turned on%s", VTY_NEWLINE);
1269
1270 return 0;
1271}
1272
0ef4bcdc
OD
1273DEFUN (pce_address,
1274 pce_address_cmd,
1275 "pce address A.B.C.D",
1276 PCE_STR
1277 "Stable IP address of the PCE\n"
1278 "PCE address in IPv4 address format\n")
1279{
8d769265 1280 int idx_ipv4 = 2;
0ef4bcdc
OD
1281 struct in_addr value;
1282 struct ospf_pce_info *pi = &OspfRI.pce_info;
1283
284a4a0c
DS
1284 if (!ospf_ri_enabled (vty))
1285 return CMD_WARNING;
1286
8d769265 1287 if (!inet_aton (argv[idx_ipv4]->arg, &value))
0ef4bcdc
OD
1288 {
1289 vty_out (vty, "Please specify PCE Address by A.B.C.D%s", VTY_NEWLINE);
1290 return CMD_WARNING;
1291 }
1292
1293 if (ntohs (pi->pce_address.header.type) == 0
1294 || ntohl (pi->pce_address.address.value.s_addr) != ntohl (value.s_addr))
1295 {
1296
1297 set_pce_address (value, pi);
1298
1299 /* Refresh RI LSA if already engaged */
284a4a0c 1300 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1301 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1302 }
1303
1304 return CMD_SUCCESS;
1305}
1306
1307DEFUN (no_pce_address,
1308 no_pce_address_cmd,
2328428d 1309 "no pce address [A.B.C.D]",
0ef4bcdc
OD
1310 NO_STR
1311 PCE_STR
59768a63
DS
1312 "Disable PCE address\n"
1313 "PCE address in IPv4 address format\n")
0ef4bcdc
OD
1314{
1315
1316 unset_param (&OspfRI.pce_info.pce_address.header);
1317
1318 /* Refresh RI LSA if already engaged */
1319 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1320 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1321
1322 return CMD_SUCCESS;
1323}
1324
1325DEFUN (pce_path_scope,
1326 pce_path_scope_cmd,
1327 "pce scope BITPATTERN",
1328 PCE_STR
1329 "Path scope visibilities of the PCE for path computation\n"
1330 "32-bit Hexadecimal value\n")
1331{
8d769265 1332 int idx_bitpattern = 2;
0ef4bcdc
OD
1333 uint32_t scope;
1334 struct ospf_pce_info *pi = &OspfRI.pce_info;
1335
284a4a0c
DS
1336 if (!ospf_ri_enabled (vty))
1337 return CMD_WARNING;
1338
8d769265 1339 if (sscanf (argv[idx_bitpattern]->arg, "0x%x", &scope) != 1)
0ef4bcdc
OD
1340 {
1341 vty_out (vty, "pce_path_scope: fscanf: %s%s", safe_strerror (errno),
1342 VTY_NEWLINE);
1343 return CMD_WARNING;
1344 }
1345
1346 if (ntohl (pi->pce_scope.header.type) == 0 || scope != pi->pce_scope.value)
1347 {
1348 set_pce_path_scope (scope, pi);
1349
1350 /* Refresh RI LSA if already engaged */
284a4a0c 1351 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1352 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1353 }
1354
1355 return CMD_SUCCESS;
1356}
1357
1358DEFUN (no_pce_path_scope,
1359 no_pce_path_scope_cmd,
2328428d 1360 "no pce scope [BITPATTERN]",
0ef4bcdc
OD
1361 NO_STR
1362 PCE_STR
59768a63
DS
1363 "Disable PCE path scope\n"
1364 "32-bit Hexadecimal value\n")
0ef4bcdc
OD
1365{
1366
1367 unset_param (&OspfRI.pce_info.pce_address.header);
1368
1369 /* Refresh RI LSA if already engaged */
1370 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1371 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1372
1373 return CMD_SUCCESS;
1374}
1375
1376DEFUN (pce_domain,
1377 pce_domain_cmd,
6147e2c6 1378 "pce domain as (0-65535)",
0ef4bcdc
OD
1379 PCE_STR
1380 "Configure PCE domain AS number\n"
1381 "AS number where the PCE as visibilities for path computation\n"
1382 "AS number in decimal <0-65535>\n")
1383{
8d769265 1384 int idx_number = 3;
0ef4bcdc
OD
1385
1386 uint32_t as;
1387 struct ospf_pce_info *pce = &OspfRI.pce_info;
1388 struct listnode *node;
1389 struct ri_pce_subtlv_domain *domain;
1390
284a4a0c
DS
1391 if (!ospf_ri_enabled (vty))
1392 return CMD_WARNING;
1393
8d769265 1394 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
0ef4bcdc
OD
1395 {
1396 vty_out (vty, "pce_domain: fscanf: %s%s", safe_strerror (errno),
1397 VTY_NEWLINE);
1398 return CMD_WARNING;
1399 }
1400
1401 /* Check if the domain is not already in the domain list */
1402 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
1403 {
1404 if (ntohl (domain->header.type) == 0 && as == domain->value)
284a4a0c 1405 return CMD_SUCCESS;
0ef4bcdc
OD
1406 }
1407
1408 /* Create new domain if not found */
1409 set_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce);
1410
1411 /* Refresh RI LSA if already engaged */
284a4a0c 1412 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1413 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1414
284a4a0c 1415 return CMD_SUCCESS;
0ef4bcdc
OD
1416}
1417
1418DEFUN (no_pce_domain,
1419 no_pce_domain_cmd,
6147e2c6 1420 "no pce domain as (0-65535)",
0ef4bcdc
OD
1421 NO_STR
1422 PCE_STR
1423 "Disable PCE domain AS number\n"
1424 "AS number where the PCE as visibilities for path computation\n"
1425 "AS number in decimal <0-65535>\n")
1426{
8d769265 1427 int idx_number = 4;
0ef4bcdc
OD
1428
1429 uint32_t as;
1430 struct ospf_pce_info *pce = &OspfRI.pce_info;
1431
8d769265 1432 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
0ef4bcdc
OD
1433 {
1434 vty_out (vty, "no_pce_domain: fscanf: %s%s", safe_strerror (errno),
1435 VTY_NEWLINE);
1436 return CMD_WARNING;
1437 }
1438
1439 /* Unset corresponding PCE domain */
1440 unset_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce);
1441
1442 /* Refresh RI LSA if already engaged */
1443 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1444 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1445
1446 return CMD_SUCCESS;
1447}
1448
1449DEFUN (pce_neigbhor,
1450 pce_neighbor_cmd,
6147e2c6 1451 "pce neighbor as (0-65535)",
0ef4bcdc
OD
1452 PCE_STR
1453 "Configure PCE neighbor domain AS number\n"
1454 "AS number of PCE neighbors\n"
1455 "AS number in decimal <0-65535>\n")
1456{
8d769265 1457 int idx_number = 3;
0ef4bcdc
OD
1458
1459 uint32_t as;
1460 struct ospf_pce_info *pce = &OspfRI.pce_info;
1461 struct listnode *node;
1462 struct ri_pce_subtlv_neighbor *neighbor;
1463
284a4a0c
DS
1464 if (!ospf_ri_enabled (vty))
1465 return CMD_WARNING;
1466
8d769265 1467 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
0ef4bcdc
OD
1468 {
1469 vty_out (vty, "pce_neighbor: fscanf: %s%s", safe_strerror (errno),
1470 VTY_NEWLINE);
1471 return CMD_WARNING;
1472 }
1473
1474 /* Check if the domain is not already in the domain list */
1475 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
1476 {
1477 if (ntohl (neighbor->header.type) == 0 && as == neighbor->value)
284a4a0c 1478 return CMD_SUCCESS;
0ef4bcdc
OD
1479 }
1480
1481 /* Create new domain if not found */
1482 set_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce);
1483
1484 /* Refresh RI LSA if already engaged */
284a4a0c 1485 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1486 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1487
284a4a0c 1488 return CMD_SUCCESS;
0ef4bcdc
OD
1489}
1490
1491DEFUN (no_pce_neighbor,
1492 no_pce_neighbor_cmd,
6147e2c6 1493 "no pce neighbor as (0-65535)",
0ef4bcdc
OD
1494 NO_STR
1495 PCE_STR
1496 "Disable PCE neighbor AS number\n"
1497 "AS number of PCE neighbor\n"
1498 "AS number in decimal <0-65535>\n")
1499{
8d769265 1500 int idx_number = 4;
0ef4bcdc
OD
1501
1502 uint32_t as;
1503 struct ospf_pce_info *pce = &OspfRI.pce_info;
1504
8d769265 1505 if (sscanf (argv[idx_number]->arg, "%d", &as) != 1)
0ef4bcdc
OD
1506 {
1507 vty_out (vty, "no_pce_neighbor: fscanf: %s%s", safe_strerror (errno),
1508 VTY_NEWLINE);
1509 return CMD_WARNING;
1510 }
1511
1512 /* Unset corresponding PCE domain */
1513 unset_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce);
1514
1515 /* Refresh RI LSA if already engaged */
1516 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1517 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1518
1519 return CMD_SUCCESS;
1520}
1521
1522DEFUN (pce_cap_flag,
1523 pce_cap_flag_cmd,
1524 "pce flag BITPATTERN",
1525 PCE_STR
1526 "Capabilities of the PCE for path computation\n"
1527 "32-bit Hexadecimal value\n")
1528{
8d769265 1529 int idx_bitpattern = 2;
0ef4bcdc
OD
1530
1531 uint32_t cap;
1532 struct ospf_pce_info *pce = &OspfRI.pce_info;
1533
284a4a0c
DS
1534 if (!ospf_ri_enabled (vty))
1535 return CMD_WARNING;
1536
8d769265 1537 if (sscanf (argv[idx_bitpattern]->arg, "0x%x", &cap) != 1)
0ef4bcdc
OD
1538 {
1539 vty_out (vty, "pce_cap_flag: fscanf: %s%s", safe_strerror (errno),
1540 VTY_NEWLINE);
1541 return CMD_WARNING;
1542 }
1543
1544 if (ntohl (pce->pce_cap_flag.header.type) == 0
1545 || cap != pce->pce_cap_flag.value)
1546 {
1547 set_pce_cap_flag (cap, pce);
1548
1549 /* Refresh RI LSA if already engaged */
284a4a0c 1550 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
0ef4bcdc
OD
1551 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1552 }
1553
1554 return CMD_SUCCESS;
1555}
1556
1557DEFUN (no_pce_cap_flag,
1558 no_pce_cap_flag_cmd,
1559 "no pce flag",
1560 NO_STR
1561 PCE_STR
1562 "Disable PCE capabilities\n")
1563{
1564
1565 unset_param (&OspfRI.pce_info.pce_cap_flag.header);
1566
1567 /* Refresh RI LSA if already engaged */
1568 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1569 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1570
1571 return CMD_SUCCESS;
1572}
1573
1574DEFUN (show_ip_ospf_router_info,
1575 show_ip_ospf_router_info_cmd,
1576 "show ip ospf router-info",
1577 SHOW_STR
1578 IP_STR
1579 OSPF_STR
1580 "Router Information\n")
1581{
1582
1583 if (OspfRI.status == enabled)
1584 {
1585 vty_out (vty, "--- Router Information parameters ---%s", VTY_NEWLINE);
1586 show_vty_router_cap (vty, &OspfRI.router_cap.header);
1587 }
1588 else
1589 {
1590 if (vty != NULL)
1591 vty_out (vty, " Router Information is disabled on this router%s", VTY_NEWLINE);
1592 }
1593 return CMD_SUCCESS;
1594}
1595
1596DEFUN (show_ip_opsf_router_info_pce,
1597 show_ip_ospf_router_info_pce_cmd,
1598 "show ip ospf router-info pce",
1599 SHOW_STR
1600 IP_STR
1601 OSPF_STR
1602 "Router Information\n"
1603 "PCE information\n")
1604{
1605
1606 struct ospf_pce_info *pce = &OspfRI.pce_info;
1607 struct listnode *node;
1608 struct ri_pce_subtlv_domain *domain;
1609 struct ri_pce_subtlv_neighbor *neighbor;
1610
1611 if (OspfRI.status == enabled)
1612 {
1613 vty_out (vty, "--- PCE parameters ---%s", VTY_NEWLINE);
1614
1615 if (pce->pce_address.header.type != 0)
1616 show_vty_pce_subtlv_address (vty, &pce->pce_address.header);
1617
1618 if (pce->pce_scope.header.type != 0)
1619 show_vty_pce_subtlv_path_scope (vty, &pce->pce_scope.header);
1620
1621 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
1622 {
1623 if (domain->header.type != 0)
1624 show_vty_pce_subtlv_domain (vty, &domain->header);
1625 }
1626
1627 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
1628 {
1629 if (neighbor->header.type != 0)
1630 show_vty_pce_subtlv_neighbor (vty, &neighbor->header);
1631 }
1632
1633 if (pce->pce_cap_flag.header.type != 0)
1634 show_vty_pce_subtlv_cap_flag (vty, &pce->pce_cap_flag.header);
1635
1636 }
1637 else
1638 {
1639 vty_out (vty, " Router Information is disabled on this router%s",
1640 VTY_NEWLINE);
1641 }
1642
1643 return CMD_SUCCESS;
1644}
1645
1646/* Install new CLI commands */
1647static void
1648ospf_router_info_register_vty (void)
1649{
1650 install_element (VIEW_NODE, &show_ip_ospf_router_info_cmd);
1651 install_element (VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
0ef4bcdc
OD
1652
1653 install_element (OSPF_NODE, &router_info_area_cmd);
0ef4bcdc
OD
1654 install_element (OSPF_NODE, &no_router_info_cmd);
1655 install_element (OSPF_NODE, &pce_address_cmd);
59768a63 1656 install_element (OSPF_NODE, &no_pce_address_cmd);
0ef4bcdc 1657 install_element (OSPF_NODE, &pce_path_scope_cmd);
59768a63 1658 install_element (OSPF_NODE, &no_pce_path_scope_cmd);
0ef4bcdc
OD
1659 install_element (OSPF_NODE, &pce_domain_cmd);
1660 install_element (OSPF_NODE, &no_pce_domain_cmd);
1661 install_element (OSPF_NODE, &pce_neighbor_cmd);
1662 install_element (OSPF_NODE, &no_pce_neighbor_cmd);
1663 install_element (OSPF_NODE, &pce_cap_flag_cmd);
d7d73ffc 1664 install_element (OSPF_NODE, &no_pce_cap_flag_cmd);
0ef4bcdc
OD
1665
1666 return;
1667}