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