]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_ri.c
isisd: gracefully handle spf error
[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
cf9b9f77
OD
6 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
7 * Copyright (C) 2012 - 2017 Orange Labs http://www.orange.com/
0ef4bcdc
OD
8 *
9 * This file is part of GNU Quagga.
10 *
11 * GNU Zebra is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2, or (at your option) any
14 * later version.
15 *
16 * GNU Quagga is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
896014f4
DL
21 * You should have received a copy of the GNU General Public License along
22 * with this program; see the file COPYING; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
0ef4bcdc
OD
24 */
25
26#include <zebra.h>
27#include <math.h>
28
29#include "linklist.h"
30#include "prefix.h"
31#include "if.h"
32#include "table.h"
33#include "memory.h"
34#include "command.h"
35#include "vty.h"
36#include "stream.h"
37#include "log.h"
38#include "thread.h"
39#include "hash.h"
d62a17ae 40#include "sockunion.h" /* for inet_aton() */
cf9b9f77 41#include "mpls.h"
0ef4bcdc
OD
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"
cf9b9f77 58#include "ospfd/ospf_sr.h"
0ef4bcdc 59#include "ospfd/ospf_ri.h"
85c9b439 60#include "ospfd/ospf_errors.h"
0ef4bcdc 61
0ef4bcdc
OD
62/*
63 * Global variable to manage Opaque-LSA/Router Information on this node.
64 * Note that all parameter values are stored in network byte order.
65 */
66static struct ospf_router_info OspfRI;
67
68/*------------------------------------------------------------------------------*
d62a17ae 69 * Followings are initialize/terminate functions for Router Information
70 *handling.
0ef4bcdc
OD
71 *------------------------------------------------------------------------------*/
72
d62a17ae 73static void ospf_router_info_ism_change(struct ospf_interface *oi,
74 int old_status);
d62a17ae 75static void ospf_router_info_config_write_router(struct vty *vty);
76static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa);
77static int ospf_router_info_lsa_originate(void *arg);
78static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
ddd73a96
OD
79static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
80 enum lsa_opcode opcode);
d62a17ae 81static void ospf_router_info_register_vty(void);
cf9b9f77 82static int ospf_router_info_lsa_update(struct ospf_lsa *lsa);
ddd73a96 83static void del_area_info(void *val);
d62a17ae 84static void del_pce_info(void *val);
85
86int ospf_router_info_init(void)
0ef4bcdc
OD
87{
88
ddd73a96 89 zlog_info("RI (%s): Initialize Router Information", __func__);
cf9b9f77 90
d62a17ae 91 memset(&OspfRI, 0, sizeof(struct ospf_router_info));
32ab5cf4 92 OspfRI.enabled = false;
d62a17ae 93 OspfRI.registered = 0;
94 OspfRI.scope = OSPF_OPAQUE_AS_LSA;
ddd73a96
OD
95 OspfRI.as_flags = RIFLG_LSA_INACTIVE;
96 OspfRI.area_info = list_new();
97 OspfRI.area_info->del = del_area_info;
0ef4bcdc 98
d62a17ae 99 /* Initialize pce domain and neighbor list */
32ab5cf4 100 OspfRI.pce_info.enabled = false;
d62a17ae 101 OspfRI.pce_info.pce_domain = list_new();
102 OspfRI.pce_info.pce_domain->del = del_pce_info;
103 OspfRI.pce_info.pce_neighbor = list_new();
104 OspfRI.pce_info.pce_neighbor->del = del_pce_info;
0ef4bcdc 105
cf9b9f77
OD
106 /* Initialize Segment Routing information structure */
107 OspfRI.sr_info.enabled = false;
108
d62a17ae 109 ospf_router_info_register_vty();
0ef4bcdc 110
d62a17ae 111 return 0;
0ef4bcdc
OD
112}
113
d7c0a89a 114static int ospf_router_info_register(uint8_t scope)
0ef4bcdc 115{
d62a17ae 116 int rc = 0;
117
118 if (OspfRI.registered)
ead99d5f 119 return rc;
d62a17ae 120
ddd73a96
OD
121 zlog_info("RI (%s): Register Router Information with scope %s(%d)",
122 __func__,
d62a17ae 123 scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
124 rc = ospf_register_opaque_functab(
125 scope, OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
126 NULL, /* new interface */
127 NULL, /* del interface */
ddd73a96
OD
128 ospf_router_info_ism_change,
129 NULL, /* NSM change */
d62a17ae 130 ospf_router_info_config_write_router,
131 NULL, /* Config. write interface */
132 NULL, /* Config. write debug */
996c9314
LB
133 ospf_router_info_show_info, ospf_router_info_lsa_originate,
134 ospf_router_info_lsa_refresh, ospf_router_info_lsa_update,
cf9b9f77 135 NULL); /* del_lsa_hook */
d62a17ae 136
137 if (rc != 0) {
ade6974d 138 flog_warn(
cf444bcf 139 EC_OSPF_OPAQUE_REGISTRATION,
ddd73a96 140 "RI (%s): Failed to register functions", __func__);
d62a17ae 141 return rc;
142 }
143
144 OspfRI.registered = 1;
145 OspfRI.scope = scope;
ead99d5f 146 return rc;
0ef4bcdc
OD
147}
148
4d762f26 149static int ospf_router_info_unregister(void)
bcf4475e
OD
150{
151
152 if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
153 && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA)) {
ade6974d
QY
154 assert("Unable to unregister Router Info functions: Wrong scope!"
155 == NULL);
bcf4475e
OD
156 return -1;
157 }
158
159 ospf_delete_opaque_functab(OspfRI.scope,
160 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
161
162 OspfRI.registered = 0;
163 return 0;
164}
165
d62a17ae 166void ospf_router_info_term(void)
0ef4bcdc
OD
167{
168
6a154c88
DL
169 list_delete(&OspfRI.pce_info.pce_domain);
170 list_delete(&OspfRI.pce_info.pce_neighbor);
0ef4bcdc 171
32ab5cf4 172 OspfRI.enabled = false;
0ef4bcdc 173
bcf4475e
OD
174 ospf_router_info_unregister();
175
d62a17ae 176 return;
0ef4bcdc
OD
177}
178
bcf4475e
OD
179void ospf_router_info_finish(void)
180{
731271b0
OD
181 struct listnode *node, *nnode;
182 struct ospf_ri_area_info *ai;
183
184 /* Flush Router Info LSA */
185 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai))
186 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
187 ospf_router_info_lsa_schedule(ai, FLUSH_THIS_LSA);
188
bcf4475e
OD
189 list_delete_all_node(OspfRI.pce_info.pce_domain);
190 list_delete_all_node(OspfRI.pce_info.pce_neighbor);
191
192 OspfRI.enabled = false;
193}
194
ddd73a96
OD
195static void del_area_info(void *val)
196{
197 XFREE(MTYPE_OSPF_ROUTER_INFO, val);
198}
199
d62a17ae 200static void del_pce_info(void *val)
0ef4bcdc 201{
d62a17ae 202 XFREE(MTYPE_OSPF_PCE_PARAMS, val);
0ef4bcdc
OD
203}
204
cf9b9f77
OD
205/* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
206struct scope_info ospf_router_info_get_flooding_scope(void)
207{
208 struct scope_info flooding_scope;
7743f2f8 209
cf9b9f77
OD
210 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
211 flooding_scope.scope = OSPF_OPAQUE_AS_LSA;
ddd73a96 212 flooding_scope.areas = NULL;
cf9b9f77
OD
213 return flooding_scope;
214 }
215 flooding_scope.scope = OSPF_OPAQUE_AREA_LSA;
ddd73a96 216 flooding_scope.areas = OspfRI.area_info;
cf9b9f77
OD
217 return flooding_scope;
218}
219
ddd73a96
OD
220static struct ospf_ri_area_info *lookup_by_area(struct ospf_area *area)
221{
222 struct listnode *node, *nnode;
223 struct ospf_ri_area_info *ai;
224
225 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai))
226 if (ai->area == area)
227 return ai;
228
229 return NULL;
230}
231
0ef4bcdc 232/*------------------------------------------------------------------------*
d62a17ae 233 * Followings are control functions for ROUTER INFORMATION parameters
234 *management.
0ef4bcdc
OD
235 *------------------------------------------------------------------------*/
236
d62a17ae 237static void set_router_info_capabilities(struct ri_tlv_router_cap *ric,
d7c0a89a 238 uint32_t cap)
0ef4bcdc 239{
d62a17ae 240 ric->header.type = htons(RI_TLV_CAPABILITIES);
241 ric->header.length = htons(RI_TLV_LENGTH);
242 ric->value = htonl(cap);
243 return;
0ef4bcdc
OD
244}
245
d62a17ae 246static int set_pce_header(struct ospf_pce_info *pce)
0ef4bcdc 247{
d7c0a89a 248 uint16_t length = 0;
d62a17ae 249 struct listnode *node;
250 struct ri_pce_subtlv_domain *domain;
251 struct ri_pce_subtlv_neighbor *neighbor;
252
253 /* PCE Address */
254 if (ntohs(pce->pce_address.header.type) != 0)
ead99d5f 255 length += TLV_SIZE(&pce->pce_address.header);
d62a17ae 256
257 /* PCE Path Scope */
258 if (ntohs(pce->pce_scope.header.type) != 0)
ead99d5f 259 length += TLV_SIZE(&pce->pce_scope.header);
d62a17ae 260
261 /* PCE Domain */
262 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
263 if (ntohs(domain->header.type) != 0)
ead99d5f 264 length += TLV_SIZE(&domain->header);
d62a17ae 265 }
266
267 /* PCE Neighbor */
268 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
269 if (ntohs(neighbor->header.type) != 0)
ead99d5f 270 length += TLV_SIZE(&neighbor->header);
d62a17ae 271 }
272
273 /* PCE Capabilities */
274 if (ntohs(pce->pce_cap_flag.header.type) != 0)
ead99d5f 275 length += TLV_SIZE(&pce->pce_cap_flag.header);
d62a17ae 276
277 if (length != 0) {
278 pce->pce_header.header.type = htons(RI_TLV_PCE);
279 pce->pce_header.header.length = htons(length);
32ab5cf4 280 pce->enabled = true;
d62a17ae 281 } else {
282 pce->pce_header.header.type = 0;
283 pce->pce_header.header.length = 0;
32ab5cf4 284 pce->enabled = false;
d62a17ae 285 }
286
287 return length;
0ef4bcdc
OD
288}
289
d62a17ae 290static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce)
0ef4bcdc
OD
291{
292
d62a17ae 293 /* Enable PCE Info */
294 pce->pce_header.header.type = htons(RI_TLV_PCE);
295 /* Set PCE Address */
296 pce->pce_address.header.type = htons(RI_PCE_SUBTLV_ADDRESS);
297 pce->pce_address.header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
298 pce->pce_address.address.type = htons(PCE_ADDRESS_TYPE_IPV4);
299 pce->pce_address.address.value = ipv4;
0ef4bcdc 300
d62a17ae 301 return;
0ef4bcdc
OD
302}
303
d7c0a89a 304static void set_pce_path_scope(uint32_t scope, struct ospf_pce_info *pce)
0ef4bcdc
OD
305{
306
d62a17ae 307 /* Set PCE Scope */
308 pce->pce_scope.header.type = htons(RI_PCE_SUBTLV_PATH_SCOPE);
309 pce->pce_scope.header.length = htons(RI_TLV_LENGTH);
310 pce->pce_scope.value = htonl(scope);
0ef4bcdc 311
d62a17ae 312 return;
0ef4bcdc
OD
313}
314
d7c0a89a 315static void set_pce_domain(uint16_t type, uint32_t domain,
d62a17ae 316 struct ospf_pce_info *pce)
0ef4bcdc
OD
317{
318
d62a17ae 319 struct ri_pce_subtlv_domain *new;
0ef4bcdc 320
d62a17ae 321 /* Create new domain info */
322 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
323 sizeof(struct ri_pce_subtlv_domain));
0ef4bcdc 324
d62a17ae 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);
0ef4bcdc 329
d62a17ae 330 /* Add new domain to the list */
331 listnode_add(pce->pce_domain, new);
0ef4bcdc 332
d62a17ae 333 return;
0ef4bcdc
OD
334}
335
d7c0a89a 336static void unset_pce_domain(uint16_t type, uint32_t domain,
d62a17ae 337 struct ospf_pce_info *pce)
0ef4bcdc 338{
d62a17ae 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 if ((old->type == htons(type))
346 && (old->value == htonl(domain))) {
347 found = 1;
348 break;
349 }
350 }
351
352 /* if found remove it */
353 if (found) {
354 listnode_delete(pce->pce_domain, old);
355
d62a17ae 356 /* Finally free the old domain */
357 XFREE(MTYPE_OSPF_PCE_PARAMS, old);
358 }
0ef4bcdc
OD
359}
360
d7c0a89a 361static void set_pce_neighbor(uint16_t type, uint32_t domain,
d62a17ae 362 struct ospf_pce_info *pce)
0ef4bcdc
OD
363{
364
d62a17ae 365 struct ri_pce_subtlv_neighbor *new;
0ef4bcdc 366
d62a17ae 367 /* Create new neighbor info */
368 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
369 sizeof(struct ri_pce_subtlv_neighbor));
0ef4bcdc 370
d62a17ae 371 new->header.type = htons(RI_PCE_SUBTLV_NEIGHBOR);
372 new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
373 new->type = htons(type);
374 new->value = htonl(domain);
0ef4bcdc 375
d62a17ae 376 /* Add new domain to the list */
377 listnode_add(pce->pce_neighbor, new);
0ef4bcdc 378
d62a17ae 379 return;
0ef4bcdc
OD
380}
381
d7c0a89a 382static void unset_pce_neighbor(uint16_t type, uint32_t domain,
d62a17ae 383 struct ospf_pce_info *pce)
0ef4bcdc 384{
d62a17ae 385 struct listnode *node;
386 struct ri_pce_subtlv_neighbor *old = NULL;
387 int found = 0;
388
389 /* Search the corresponding node */
390 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, old)) {
391 if ((old->type == htons(type))
392 && (old->value == htonl(domain))) {
393 found = 1;
394 break;
395 }
396 }
397
398 /* if found remove it */
399 if (found) {
400 listnode_delete(pce->pce_neighbor, old);
401
d62a17ae 402 /* Finally free the old domain */
403 XFREE(MTYPE_OSPF_PCE_PARAMS, old);
404 }
0ef4bcdc
OD
405}
406
d7c0a89a 407static void set_pce_cap_flag(uint32_t cap, struct ospf_pce_info *pce)
0ef4bcdc
OD
408{
409
d62a17ae 410 /* Set PCE Capabilities flag */
411 pce->pce_cap_flag.header.type = htons(RI_PCE_SUBTLV_CAP_FLAG);
412 pce->pce_cap_flag.header.length = htons(RI_TLV_LENGTH);
413 pce->pce_cap_flag.value = htonl(cap);
0ef4bcdc 414
d62a17ae 415 return;
0ef4bcdc
OD
416}
417
cf9b9f77
OD
418/* Segment Routing TLV setter */
419
420/* Algorithm SubTLV - section 3.1 */
93f0a26e 421static void set_sr_algorithm(uint8_t algo)
cf9b9f77
OD
422{
423
424 OspfRI.sr_info.algo.value[0] = algo;
425 for (int i = 1; i < ALGORITHM_COUNT; i++)
426 OspfRI.sr_info.algo.value[i] = SR_ALGORITHM_UNSET;
427
428 /* Set TLV type and length == only 1 Algorithm */
429 TLV_TYPE(OspfRI.sr_info.algo) = htons(RI_SR_TLV_SR_ALGORITHM);
93f0a26e 430 TLV_LEN(OspfRI.sr_info.algo) = htons(sizeof(uint8_t));
cf9b9f77
OD
431}
432
433/* unset Aglogithm SubTLV */
93f0a26e 434static void unset_sr_algorithm(uint8_t algo)
cf9b9f77
OD
435{
436
437 for (int i = 0; i < ALGORITHM_COUNT; i++)
438 OspfRI.sr_info.algo.value[i] = SR_ALGORITHM_UNSET;
439
440 /* Unset TLV type and length */
441 TLV_TYPE(OspfRI.sr_info.algo) = htons(0);
442 TLV_LEN(OspfRI.sr_info.algo) = htons(0);
cf9b9f77
OD
443}
444
445/* Segment Routing Global Block SubTLV - section 3.2 */
446static void set_sr_sid_label_range(struct sr_srgb srgb)
447{
448 /* Set Header */
449 TLV_TYPE(OspfRI.sr_info.range) = htons(RI_SR_TLV_SID_LABEL_RANGE);
450 TLV_LEN(OspfRI.sr_info.range) =
93f0a26e 451 htons(SUBTLV_SID_LABEL_SIZE + sizeof(uint32_t));
cf9b9f77
OD
452 /* Set Range Size */
453 OspfRI.sr_info.range.size = htonl(SET_RANGE_SIZE(srgb.range_size));
454 /* Set Lower bound label SubTLV */
455 TLV_TYPE(OspfRI.sr_info.range.lower) = htons(SUBTLV_SID_LABEL);
456 TLV_LEN(OspfRI.sr_info.range.lower) = htons(SID_RANGE_LABEL_LENGTH);
457 OspfRI.sr_info.range.lower.value = htonl(SET_LABEL(srgb.lower_bound));
cf9b9f77
OD
458}
459
460/* Unset this SRGB SubTLV */
7743f2f8 461static void unset_sr_sid_label_range(void)
cf9b9f77
OD
462{
463
464 TLV_TYPE(OspfRI.sr_info.range) = htons(0);
465 TLV_LEN(OspfRI.sr_info.range) = htons(0);
466 TLV_TYPE(OspfRI.sr_info.range.lower) = htons(0);
467 TLV_LEN(OspfRI.sr_info.range.lower) = htons(0);
cf9b9f77
OD
468}
469
470/* Set Maximum Stack Depth for this router */
93f0a26e 471static void set_sr_node_msd(uint8_t msd)
cf9b9f77
OD
472{
473 TLV_TYPE(OspfRI.sr_info.msd) = htons(RI_SR_TLV_NODE_MSD);
93f0a26e 474 TLV_LEN(OspfRI.sr_info.msd) = htons(sizeof(uint32_t));
cf9b9f77 475 OspfRI.sr_info.msd.value = msd;
cf9b9f77
OD
476}
477
478/* Unset this router MSD */
7743f2f8 479static void unset_sr_node_msd(void)
cf9b9f77
OD
480{
481 TLV_TYPE(OspfRI.sr_info.msd) = htons(0);
482 TLV_LEN(OspfRI.sr_info.msd) = htons(0);
cf9b9f77 483}
0ef4bcdc 484
9ffaacb0 485static void unset_param(void *tlv_buffer)
0ef4bcdc 486{
9ffaacb0 487 struct tlv_header *tlv = (struct tlv_header *)tlv_buffer;
0ef4bcdc 488
d62a17ae 489 tlv->type = 0;
490 /* Fill the Value to 0 */
9ffaacb0 491 memset(TLV_DATA(tlv_buffer), 0, TLV_BODY_SIZE(tlv));
d62a17ae 492 tlv->length = 0;
0ef4bcdc 493
d62a17ae 494 return;
0ef4bcdc
OD
495}
496
d62a17ae 497static void initialize_params(struct ospf_router_info *ori)
0ef4bcdc 498{
d7c0a89a 499 uint32_t cap = 0;
d62a17ae 500 struct ospf *top;
ddd73a96
OD
501 struct listnode *node, *nnode;
502 struct ospf_area *area;
503 struct ospf_ri_area_info *new;
d62a17ae 504
505 /*
506 * Initialize default Router Information Capabilities.
507 */
ead99d5f 508 cap = RI_TE_SUPPORT;
d62a17ae 509
510 set_router_info_capabilities(&ori->router_cap, cap);
511
512 /* If Area address is not null and exist, retrieve corresponding
513 * structure */
b5a8894d 514 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
ddd73a96
OD
515 zlog_info("RI (%s): Initialize Router Info for %s scope", __func__,
516 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
d62a17ae 517
ddd73a96
OD
518 /* Try to get available Area's context from ospf at this step.
519 * Do it latter if not available */
520 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
731271b0
OD
521 if (!list_isempty(OspfRI.area_info))
522 list_delete_all_node(OspfRI.area_info);
ddd73a96
OD
523 for (ALL_LIST_ELEMENTS(top->areas, node, nnode, area)) {
524 zlog_debug("RI (%s): Add area %s to Router Information",
525 __func__, inet_ntoa(area->area_id));
526 new = XCALLOC(MTYPE_OSPF_ROUTER_INFO,
527 sizeof(struct ospf_ri_area_info));
528 new->area = area;
529 new->flags = RIFLG_LSA_INACTIVE;
530 listnode_add(OspfRI.area_info, new);
531 }
532 }
d62a17ae 533
534 /*
535 * Initialize default PCE Information values
536 */
537 /* PCE address == OSPF Router ID */
538 set_pce_address(top->router_id, &ori->pce_info);
539
540 /* PCE scope */
541 cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path
542 computation */
543 set_pce_path_scope(cap, &ori->pce_info);
544
545 /* PCE Capabilities */
546 cap = PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES
547 | PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ;
548 set_pce_cap_flag(cap, &ori->pce_info);
549
d62a17ae 550 return;
0ef4bcdc
OD
551}
552
d62a17ae 553static int is_mandated_params_set(struct ospf_router_info ori)
0ef4bcdc 554{
d62a17ae 555 int rc = 0;
0ef4bcdc 556
d62a17ae 557 if (ntohs(ori.router_cap.header.type) == 0)
ead99d5f 558 return rc;
0ef4bcdc 559
d62a17ae 560 if ((ntohs(ori.pce_info.pce_header.header.type) == RI_TLV_PCE)
561 && (ntohs(ori.pce_info.pce_address.header.type) == 0)
562 && (ntohs(ori.pce_info.pce_cap_flag.header.type) == 0))
ead99d5f 563 return rc;
0ef4bcdc 564
cf9b9f77
OD
565 if ((ori.sr_info.enabled) && (ntohs(TLV_TYPE(ori.sr_info.algo)) == 0)
566 && (ntohs(TLV_TYPE(ori.sr_info.range)) == 0))
567 return rc;
568
d62a17ae 569 rc = 1;
0ef4bcdc 570
d62a17ae 571 return rc;
0ef4bcdc
OD
572}
573
cf9b9f77
OD
574/*
575 * Used by Segment Routing to set new TLVs and Sub-TLVs values
576 *
577 * @param enable To activate or not Segment Routing router Information flooding
578 * @param size Size of Label Range i.e. SRGB size
579 * @param lower Lower bound of the Label Range i.e. SRGB first label
0437e105 580 * @param msd Maximum label Stack Depth supported by the router
cf9b9f77
OD
581 *
582 * @return none
583 */
93f0a26e 584void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
cf9b9f77 585{
ddd73a96
OD
586 struct listnode *node, *nnode;
587 struct ospf_ri_area_info *ai;
588
589 /* First, check if Router Information is registered or not */
590 if (!OspfRI.registered)
591 ospf_router_info_register(OSPF_OPAQUE_AREA_LSA);
592
593 /* Verify that scope is AREA */
594 if (OspfRI.scope != OSPF_OPAQUE_AREA_LSA) {
595 zlog_err(
596 "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
597 __func__,
598 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
599 return;
600 }
cf9b9f77 601
ddd73a96 602 /* Then, activate and initialize Router Information if necessary */
cf9b9f77
OD
603 if (!OspfRI.enabled) {
604 OspfRI.enabled = true;
605 initialize_params(&OspfRI);
606 }
607
608 if (IS_DEBUG_OSPF_SR)
ddd73a96
OD
609 zlog_debug("RI (%s): %s Routing Information for Segment Routing",
610 __func__, enable ? "Enable" : "Disable");
cf9b9f77
OD
611
612 /* Unset or Set SR parameters */
613 if (!enable) {
614 unset_sr_algorithm(SR_ALGORITHM_SPF);
615 unset_sr_sid_label_range();
616 unset_sr_node_msd();
617 OspfRI.sr_info.enabled = false;
618 } else {
619 // Only SR_ALGORITHM_SPF is supported
620 set_sr_algorithm(SR_ALGORITHM_SPF);
621 set_sr_sid_label_range(srgb);
622 if (msd != 0)
623 set_sr_node_msd(msd);
624 else
625 unset_sr_node_msd();
626 OspfRI.sr_info.enabled = true;
627 }
628
629 /* Refresh if already engaged or originate RI LSA */
ddd73a96
OD
630 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
631 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
632 ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
633 else
634 ospf_router_info_lsa_schedule(ai,
635 REORIGINATE_THIS_LSA);
636
637 }
cf9b9f77
OD
638}
639
0ef4bcdc
OD
640/*------------------------------------------------------------------------*
641 * Followings are callback functions against generic Opaque-LSAs handling.
642 *------------------------------------------------------------------------*/
d62a17ae 643static void ospf_router_info_ism_change(struct ospf_interface *oi,
644 int old_state)
0ef4bcdc 645{
0ef4bcdc 646
ddd73a96
OD
647 struct ospf_ri_area_info *ai;
648
649 /* Collect area information */
650 ai = lookup_by_area(oi->area);
651
652 /* Check if area is not yet registered */
653 if (ai != NULL)
654 return;
655
656 /* Add this new area to the list */
657 ai = XCALLOC(MTYPE_OSPF_ROUTER_INFO, sizeof(struct ospf_ri_area_info));
658 ai->area = oi->area;
659 ai->flags = RIFLG_LSA_INACTIVE;
660 listnode_add(OspfRI.area_info, ai);
661
d62a17ae 662 return;
0ef4bcdc
OD
663}
664
665/*------------------------------------------------------------------------*
666 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
667 *------------------------------------------------------------------------*/
668
ead99d5f 669static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
0ef4bcdc
OD
670{
671
ead99d5f 672 stream_put(s, tlvh, sizeof(struct tlv_header));
d62a17ae 673 return;
0ef4bcdc
OD
674}
675
ead99d5f 676static void build_tlv(struct stream *s, struct tlv_header *tlvh)
0ef4bcdc
OD
677{
678
d62a17ae 679 if (ntohs(tlvh->type) != 0) {
680 build_tlv_header(s, tlvh);
5d0df50f 681 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
d62a17ae 682 }
683 return;
0ef4bcdc
OD
684}
685
d62a17ae 686static void ospf_router_info_lsa_body_set(struct stream *s)
0ef4bcdc
OD
687{
688
d62a17ae 689 struct listnode *node;
690 struct ri_pce_subtlv_domain *domain;
691 struct ri_pce_subtlv_neighbor *neighbor;
0ef4bcdc 692
d62a17ae 693 /* Build Router Information TLV */
694 build_tlv(s, &OspfRI.router_cap.header);
0ef4bcdc 695
cf9b9f77
OD
696 /* Build Segment Routing TLVs if enabled */
697 if (OspfRI.sr_info.enabled) {
698 /* Build Algorithm TLV */
699 build_tlv(s, &TLV_HDR(OspfRI.sr_info.algo));
700 /* Build SRGB TLV */
701 build_tlv(s, &TLV_HDR(OspfRI.sr_info.range));
702 /* Build MSD TLV */
703 build_tlv(s, &TLV_HDR(OspfRI.sr_info.msd));
704 }
ead99d5f
OD
705
706 /* Add RI PCE TLV if it is set */
32ab5cf4 707 if (OspfRI.pce_info.enabled) {
0ef4bcdc 708
cf9b9f77 709 /* Compute PCE Info header first */
996c9314 710 set_pce_header(&OspfRI.pce_info);
cf9b9f77 711
d62a17ae 712 /* Build PCE TLV */
713 build_tlv_header(s, &OspfRI.pce_info.pce_header.header);
0ef4bcdc 714
d62a17ae 715 /* Build PCE address sub-tlv */
716 build_tlv(s, &OspfRI.pce_info.pce_address.header);
0ef4bcdc 717
d62a17ae 718 /* Build PCE path scope sub-tlv */
719 build_tlv(s, &OspfRI.pce_info.pce_scope.header);
0ef4bcdc 720
d62a17ae 721 /* Build PCE domain sub-tlv */
722 for (ALL_LIST_ELEMENTS_RO(OspfRI.pce_info.pce_domain, node,
723 domain))
724 build_tlv(s, &domain->header);
0ef4bcdc 725
d62a17ae 726 /* Build PCE neighbor sub-tlv */
727 for (ALL_LIST_ELEMENTS_RO(OspfRI.pce_info.pce_neighbor, node,
728 neighbor))
729 build_tlv(s, &neighbor->header);
0ef4bcdc 730
d62a17ae 731 /* Build PCE cap flag sub-tlv */
732 build_tlv(s, &OspfRI.pce_info.pce_cap_flag.header);
733 }
0ef4bcdc 734
d62a17ae 735 return;
0ef4bcdc
OD
736}
737
738/* Create new opaque-LSA. */
ddd73a96 739static struct ospf_lsa *ospf_router_info_lsa_new(struct ospf_area *area)
0ef4bcdc 740{
d62a17ae 741 struct ospf *top;
742 struct stream *s;
743 struct lsa_header *lsah;
744 struct ospf_lsa *new = NULL;
d7c0a89a 745 uint8_t options, lsa_type;
d62a17ae 746 struct in_addr lsa_id;
d7c0a89a
QY
747 uint32_t tmp;
748 uint16_t length;
d62a17ae 749
750 /* Create a stream for LSA. */
266469eb
DS
751 s = stream_new(OSPF_MAX_LSA_SIZE);
752
d62a17ae 753 lsah = (struct lsa_header *)STREAM_DATA(s);
754
755 options = OSPF_OPTION_E; /* Enable AS external as we flood RI with
756 Opaque Type 11 */
757 options |= OSPF_OPTION_O; /* Don't forget this :-) */
758
759 lsa_type = OspfRI.scope;
760 /* LSA ID == 0 for Router Information see RFC 4970 */
761 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
762 lsa_id.s_addr = htonl(tmp);
763
764 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
765 zlog_debug(
766 "LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
767 lsa_type, inet_ntoa(lsa_id));
768
b5a8894d 769 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 770
771 /* Set opaque-LSA header fields. */
772 lsa_header_set(s, options, lsa_type, lsa_id, top->router_id);
773
774 /* Set opaque-LSA body fields. */
775 ospf_router_info_lsa_body_set(s);
776
777 /* Set length. */
778 length = stream_get_endp(s);
779 lsah->length = htons(length);
780
781 /* Now, create an OSPF LSA instance. */
5b3d4186 782 new = ospf_lsa_new_and_data(length);
d62a17ae 783
ddd73a96 784 new->area = area;
d62a17ae 785
b5a8894d
CS
786 if (new->area && new->area->ospf)
787 new->vrf_id = new->area->ospf->vrf_id;
788 else
789 new->vrf_id = VRF_DEFAULT;
790
d62a17ae 791 SET_FLAG(new->flags, OSPF_LSA_SELF);
792 memcpy(new->data, lsah, length);
793 stream_free(s);
794
d62a17ae 795 return new;
0ef4bcdc
OD
796}
797
ddd73a96 798static int ospf_router_info_lsa_originate_as(void *arg)
0ef4bcdc 799{
d62a17ae 800 struct ospf_lsa *new;
801 struct ospf *top;
d62a17ae 802 int rc = -1;
b5a8894d 803 vrf_id_t vrf_id = VRF_DEFAULT;
d62a17ae 804
ddd73a96 805 /* Sanity Check */
d62a17ae 806 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
ddd73a96
OD
807 flog_warn(
808 EC_OSPF_LSA_INSTALL_FAILURE,
809 "RI (%s): wrong flooding scope AREA instead of AS ?",
810 __func__);
811 return rc;
d62a17ae 812 }
813
814 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
ddd73a96
OD
815 new = ospf_router_info_lsa_new(NULL);
816 new->vrf_id = VRF_DEFAULT;
817 top = (struct ospf *)arg;
d62a17ae 818
ddd73a96 819 /* Check ospf info */
b5a8894d 820 if (top == NULL) {
ddd73a96
OD
821 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
822 __func__, vrf_id);
c2a2f37b 823 ospf_lsa_unlock(&new);
b5a8894d
CS
824 return rc;
825 }
d62a17ae 826
827 /* Install this LSA into LSDB. */
828 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
542a208f 829 flog_warn(
cf444bcf 830 EC_OSPF_LSA_INSTALL_FAILURE,
ddd73a96
OD
831 "RI (%s): ospf_lsa_install() ?", __func__);
832 ospf_lsa_unlock(&new);
833 return rc;
834 }
835
836 /* Update new LSA origination count. */
837 top->lsa_originate_count++;
838
839 /* Flood new LSA through AREA or AS. */
840 SET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
841 ospf_flood_through_as(top, NULL /*nbr */, new);
842
843 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
844 zlog_debug(
845 "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
846 new->data->type, inet_ntoa(new->data->id));
847 ospf_lsa_header_dump(new->data);
848 }
849
850 rc = 0;
851 return rc;
852}
853
854static int ospf_router_info_lsa_originate_area(void *arg)
855{
856 struct ospf_lsa *new;
857 struct ospf *top;
858 struct ospf_ri_area_info *ai = NULL;
859 int rc = -1;
860 vrf_id_t vrf_id = VRF_DEFAULT;
861
862 /* Sanity Check */
863 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
864 flog_warn(
865 EC_OSPF_LSA_INSTALL_FAILURE,
866 "RI (%s): wrong flooding scope AS instead of AREA ?",
867 __func__);
868 return rc;
869 }
870
871 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
872 ai = lookup_by_area((struct ospf_area *)arg);
873 if (ai == NULL) {
874 zlog_debug(
875 "RI (%s): There is no context for this Router Information. Stop processing",
876 __func__);
877 return rc;
878 }
879 if (ai->area->ospf) {
880 vrf_id = ai->area->ospf->vrf_id;
881 top = ai->area->ospf;
882 } else {
883 top = ospf_lookup_by_vrf_id(vrf_id);
884 }
885 new = ospf_router_info_lsa_new(ai->area);
886 new->vrf_id = vrf_id;
887
888 /* Check ospf info */
889 if (top == NULL) {
890 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
891 __func__, vrf_id);
d62a17ae 892 ospf_lsa_unlock(&new);
ead99d5f 893 return rc;
d62a17ae 894 }
895
ddd73a96
OD
896 /* Install this LSA into LSDB. */
897 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
898 flog_warn(
899 EC_OSPF_LSA_INSTALL_FAILURE,
900 "RI (%s): ospf_lsa_install() ?", __func__);
901 ospf_lsa_unlock(&new);
902 return rc;
903 }
d62a17ae 904
905 /* Update new LSA origination count. */
906 top->lsa_originate_count++;
907
ddd73a96
OD
908 /* Flood new LSA through AREA or AS. */
909 SET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
910 ospf_flood_through_area(ai->area, NULL /*nbr */, new);
d62a17ae 911
912 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
913 zlog_debug(
914 "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
915 new->data->type, inet_ntoa(new->data->id));
916 ospf_lsa_header_dump(new->data);
917 }
918
919 rc = 0;
d62a17ae 920 return rc;
0ef4bcdc
OD
921}
922
d62a17ae 923static int ospf_router_info_lsa_originate(void *arg)
0ef4bcdc
OD
924{
925
ddd73a96 926 struct ospf_ri_area_info *ai;
d62a17ae 927 int rc = -1;
928
32ab5cf4 929 if (!OspfRI.enabled) {
ddd73a96
OD
930 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
931 __func__);
d62a17ae 932 rc = 0; /* This is not an error case. */
ead99d5f 933 return rc;
d62a17ae 934 }
935
936 /* Check if Router Information LSA is already engaged */
ddd73a96
OD
937 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
938 if ((CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
939 && (CHECK_FLAG(OspfRI.as_flags,
940 RIFLG_LSA_FORCED_REFRESH))) {
941 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_FORCED_REFRESH);
942 ospf_router_info_lsa_schedule(NULL, REFRESH_THIS_LSA);
943 rc = 0;
944 return rc;
d62a17ae 945 }
946 } else {
ddd73a96
OD
947 ai = lookup_by_area((struct ospf_area *)arg);
948 if (ai == NULL) {
239697e3 949 flog_warn(
cf444bcf 950 EC_OSPF_LSA,
ddd73a96 951 "RI (%s): Missing area information", __func__);
ead99d5f 952 return rc;
ddd73a96
OD
953 }
954 if ((CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
955 && (CHECK_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH))) {
956 UNSET_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH);
957 ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
958 rc = 0;
959 return rc;
960 }
d62a17ae 961 }
962
ddd73a96
OD
963 /* Router Information is not yet Engaged, check parameters */
964 if (!is_mandated_params_set(OspfRI))
965 flog_warn(
966 EC_OSPF_LSA,
967 "RI (%s): lacks mandated ROUTER INFORMATION parameters",
968 __func__);
969
970 /* Ok, let's try to originate an LSA */
971 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
972 rc = ospf_router_info_lsa_originate_as(arg);
973 else
974 rc = ospf_router_info_lsa_originate_area(arg);
975
d62a17ae 976 return rc;
0ef4bcdc
OD
977}
978
d62a17ae 979static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
0ef4bcdc 980{
ddd73a96 981 struct ospf_ri_area_info *ai = NULL;
d62a17ae 982 struct ospf_lsa *new = NULL;
983 struct ospf *top;
984
32ab5cf4 985 if (!OspfRI.enabled) {
d62a17ae 986 /*
987 * This LSA must have flushed before due to ROUTER INFORMATION
988 * status change.
989 * It seems a slip among routers in the routing domain.
990 */
ddd73a96
OD
991 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
992 __func__);
d62a17ae 993 lsa->data->ls_age =
994 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
995 }
996
997 /* Verify that the Router Information ID is supported */
998 if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) {
239697e3 999 flog_warn(
cf444bcf 1000 EC_OSPF_LSA,
ddd73a96
OD
1001 "RI (%s): Unsupported Router Information ID",
1002 __func__);
ead99d5f 1003 return NULL;
d62a17ae 1004 }
1005
ddd73a96
OD
1006 /* Process LSA depending of the flooding scope */
1007 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
1008 /* Get context AREA context */
1009 ai = lookup_by_area(lsa->area);
1010 if (ai == NULL) {
1011 flog_warn(
1012 EC_OSPF_LSA,
1013 "RI (%s): No associated Area", __func__);
1014 return NULL;
1015 }
1016 /* Flush LSA, if the lsa's age reached to MaxAge. */
1017 if (IS_LSA_MAXAGE(lsa)) {
1018 UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
1019 ospf_opaque_lsa_flush_schedule(lsa);
1020 return NULL;
1021 }
1022 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1023 new = ospf_router_info_lsa_new(ai->area);
1024 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1025 new->vrf_id = lsa->vrf_id;
1026 /* Install this LSA into LSDB. */
1027 /* Given "lsa" will be freed in the next function. */
1028 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1029 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1030 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1031 "RI (%s): ospf_lsa_install() ?", __func__);
1032 ospf_lsa_unlock(&new);
1033 return new;
1034 }
1035 /* Flood updated LSA through AREA */
1036 ospf_flood_through_area(ai->area, NULL /*nbr */, new);
1037
1038 } else { /* AS Flooding scope */
1039 /* Flush LSA, if the lsa's age reached to MaxAge. */
1040 if (IS_LSA_MAXAGE(lsa)) {
1041 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
1042 ospf_opaque_lsa_flush_schedule(lsa);
1043 return NULL;
1044 }
1045 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1046 new = ospf_router_info_lsa_new(NULL);
1047 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1048 new->vrf_id = lsa->vrf_id;
1049 /* Install this LSA into LSDB. */
1050 /* Given "lsa" will be freed in the next function. */
1051 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1052 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1053 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1054 "RI (%s): ospf_lsa_install() ?", __func__);
1055 ospf_lsa_unlock(&new);
1056 return new;
1057 }
1058 /* Flood updated LSA through AS */
d62a17ae 1059 ospf_flood_through_as(top, NULL /*nbr */, new);
ddd73a96 1060 }
d62a17ae 1061
1062 /* Debug logging. */
1063 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1064 zlog_debug(
1065 "LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
1066 new->data->type, inet_ntoa(new->data->id));
1067 ospf_lsa_header_dump(new->data);
1068 }
1069
d62a17ae 1070 return new;
0ef4bcdc
OD
1071}
1072
ddd73a96
OD
1073static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
1074 enum lsa_opcode opcode)
0ef4bcdc 1075{
d62a17ae 1076 struct ospf_lsa lsa;
1077 struct lsa_header lsah;
1078 struct ospf *top;
d7c0a89a 1079 uint32_t tmp;
d62a17ae 1080
1081 memset(&lsa, 0, sizeof(lsa));
1082 memset(&lsah, 0, sizeof(lsah));
1083
ddd73a96 1084 zlog_debug("RI (%s): LSA schedule %s%s%s", __func__,
d62a17ae 1085 opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
1086 opcode == REFRESH_THIS_LSA ? "Refresh" : "",
1087 opcode == FLUSH_THIS_LSA ? "Flush" : "");
1088
ddd73a96
OD
1089 /* Check LSA flags state coherence and collect area information */
1090 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
1091 if ((ai == NULL) || (ai->area == NULL)) {
1092 flog_warn(
1093 EC_OSPF_LSA,
1094 "RI (%s): Router Info is Area scope flooding but area is not set",
1095 __func__);
1096 return;
1097 }
ead99d5f 1098
ddd73a96
OD
1099 if (!CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
1100 && (opcode != REORIGINATE_THIS_LSA))
1101 return;
ead99d5f 1102
ddd73a96
OD
1103 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
1104 && (opcode == REORIGINATE_THIS_LSA))
1105 opcode = REFRESH_THIS_LSA;
1106
1107 lsa.area = ai->area;
1108 top = ai->area->ospf;
1109 } else {
1110 if (!CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
1111 && (opcode != REORIGINATE_THIS_LSA))
1112 return;
1113
1114 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
1115 && (opcode == REORIGINATE_THIS_LSA))
1116 opcode = REFRESH_THIS_LSA;
1117
1118 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1119 lsa.area = NULL;
d62a17ae 1120 }
ddd73a96 1121
d62a17ae 1122 lsa.data = &lsah;
1123 lsah.type = OspfRI.scope;
1124
1125 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1126 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
1127 lsah.id.s_addr = htonl(tmp);
1128
1129 switch (opcode) {
1130 case REORIGINATE_THIS_LSA:
1131 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
1132 ospf_opaque_lsa_reoriginate_schedule(
ddd73a96 1133 (void *)ai->area, OSPF_OPAQUE_AREA_LSA,
d62a17ae 1134 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
1135 else
1136 ospf_opaque_lsa_reoriginate_schedule(
1137 (void *)top, OSPF_OPAQUE_AS_LSA,
1138 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
1139 break;
1140 case REFRESH_THIS_LSA:
1141 ospf_opaque_lsa_refresh_schedule(&lsa);
1142 break;
1143 case FLUSH_THIS_LSA:
ddd73a96
OD
1144 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
1145 UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
1146 else
1147 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
d62a17ae 1148 ospf_opaque_lsa_flush_schedule(&lsa);
1149 break;
d62a17ae 1150 }
1151
1152 return;
0ef4bcdc
OD
1153}
1154
cf9b9f77
OD
1155/* Callback to handle Segment Routing information */
1156static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
1157{
1158
1159 /* Sanity Check */
1160 if (lsa == NULL) {
ddd73a96 1161 flog_warn(EC_OSPF_LSA, "RI (%s): Abort! LSA is NULL",
239697e3 1162 __func__);
cf9b9f77
OD
1163 return -1;
1164 }
1165
6aaf0fdd
OD
1166 /* Process only Opaque LSA */
1167 if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
1168 && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
cf9b9f77
OD
1169 return 0;
1170
1171 /* Process only Router Information LSA */
996c9314
LB
1172 if (GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
1173 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA)
cf9b9f77
OD
1174 return 0;
1175
6aaf0fdd
OD
1176 /* Check if it is not my LSA */
1177 if (IS_LSA_SELF(lsa))
1178 return 0;
1179
cf9b9f77
OD
1180 /* Check if Router Info & Segment Routing are enable */
1181 if (!OspfRI.enabled || !OspfRI.sr_info.enabled)
1182 return 0;
1183
1184 /* Call Segment Routing LSA update or deletion */
1185 if (!IS_LSA_MAXAGE(lsa))
1186 ospf_sr_ri_lsa_update(lsa);
1187 else
1188 ospf_sr_ri_lsa_delete(lsa);
1189
1190 return 0;
1191}
1192
0ef4bcdc
OD
1193/*------------------------------------------------------------------------*
1194 * Followings are vty session control functions.
1195 *------------------------------------------------------------------------*/
1196
d7c0a89a 1197static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh)
0ef4bcdc 1198{
d62a17ae 1199 struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
0ef4bcdc 1200
d62a17ae 1201 if (vty != NULL)
1202 vty_out(vty, " Router Capabilities: 0x%x\n",
1203 ntohl(top->value));
1204 else
1205 zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value));
0ef4bcdc 1206
ead99d5f 1207 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1208}
1209
d7c0a89a
QY
1210static uint16_t show_vty_pce_subtlv_address(struct vty *vty,
1211 struct tlv_header *tlvh)
0ef4bcdc 1212{
d62a17ae 1213 struct ri_pce_subtlv_address *top =
1214 (struct ri_pce_subtlv_address *)tlvh;
1215
1216 if (ntohs(top->address.type) == PCE_ADDRESS_TYPE_IPV4) {
1217 if (vty != NULL)
1218 vty_out(vty, " PCE Address: %s\n",
1219 inet_ntoa(top->address.value));
1220 else
1221 zlog_debug(" PCE Address: %s",
1222 inet_ntoa(top->address.value));
1223 } else {
1224 /* TODO: Add support to IPv6 with inet_ntop() */
1225 if (vty != NULL)
1226 vty_out(vty, " PCE Address: 0x%x\n",
1227 ntohl(top->address.value.s_addr));
1228 else
1229 zlog_debug(" PCE Address: 0x%x",
1230 ntohl(top->address.value.s_addr));
1231 }
1232
ead99d5f 1233 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1234}
1235
d7c0a89a
QY
1236static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
1237 struct tlv_header *tlvh)
0ef4bcdc 1238{
d62a17ae 1239 struct ri_pce_subtlv_path_scope *top =
1240 (struct ri_pce_subtlv_path_scope *)tlvh;
0ef4bcdc 1241
d62a17ae 1242 if (vty != NULL)
1243 vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value));
1244 else
1245 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value));
0ef4bcdc 1246
ead99d5f 1247 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1248}
1249
d7c0a89a
QY
1250static uint16_t show_vty_pce_subtlv_domain(struct vty *vty,
1251 struct tlv_header *tlvh)
0ef4bcdc 1252{
d62a17ae 1253 struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
1254 struct in_addr tmp;
1255
1256 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1257 tmp.s_addr = top->value;
1258 if (vty != NULL)
1259 vty_out(vty, " PCE domain Area: %s\n", inet_ntoa(tmp));
1260 else
1261 zlog_debug(" PCE domain Area: %s", inet_ntoa(tmp));
1262 } else {
1263 if (vty != NULL)
1264 vty_out(vty, " PCE domain AS: %d\n",
1265 ntohl(top->value));
1266 else
1267 zlog_debug(" PCE domain AS: %d", ntohl(top->value));
1268 }
ead99d5f 1269 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1270}
1271
d7c0a89a
QY
1272static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
1273 struct tlv_header *tlvh)
0ef4bcdc
OD
1274{
1275
d62a17ae 1276 struct ri_pce_subtlv_neighbor *top =
1277 (struct ri_pce_subtlv_neighbor *)tlvh;
1278 struct in_addr tmp;
1279
1280 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1281 tmp.s_addr = top->value;
1282 if (vty != NULL)
1283 vty_out(vty, " PCE neighbor Area: %s\n",
1284 inet_ntoa(tmp));
1285 else
1286 zlog_debug(" PCE neighbor Area: %s", inet_ntoa(tmp));
1287 } else {
1288 if (vty != NULL)
1289 vty_out(vty, " PCE neighbor AS: %d\n",
1290 ntohl(top->value));
1291 else
1292 zlog_debug(" PCE neighbor AS: %d",
1293 ntohl(top->value));
1294 }
ead99d5f 1295 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1296}
1297
d7c0a89a
QY
1298static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
1299 struct tlv_header *tlvh)
0ef4bcdc 1300{
d62a17ae 1301 struct ri_pce_subtlv_cap_flag *top =
1302 (struct ri_pce_subtlv_cap_flag *)tlvh;
0ef4bcdc 1303
d62a17ae 1304 if (vty != NULL)
1305 vty_out(vty, " PCE Capabilities Flag: 0x%x\n",
1306 ntohl(top->value));
1307 else
1308 zlog_debug(" PCE Capabilities Flag: 0x%x",
1309 ntohl(top->value));
0ef4bcdc 1310
ead99d5f 1311 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1312}
1313
d7c0a89a 1314static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
0ef4bcdc 1315{
d62a17ae 1316 if (vty != NULL)
1317 vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1318 ntohs(tlvh->type), ntohs(tlvh->length));
1319 else
1320 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1321 ntohs(tlvh->type), ntohs(tlvh->length));
1322
ead99d5f 1323 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1324}
1325
d7c0a89a
QY
1326static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
1327 uint32_t total)
0ef4bcdc 1328{
ead99d5f 1329 struct tlv_header *tlvh;
d7c0a89a 1330 uint16_t sum = 0;
d62a17ae 1331
ead99d5f 1332 for (tlvh = ri; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
d62a17ae 1333 switch (ntohs(tlvh->type)) {
1334 case RI_PCE_SUBTLV_ADDRESS:
1335 sum += show_vty_pce_subtlv_address(vty, tlvh);
1336 break;
1337 case RI_PCE_SUBTLV_PATH_SCOPE:
1338 sum += show_vty_pce_subtlv_path_scope(vty, tlvh);
1339 break;
1340 case RI_PCE_SUBTLV_DOMAIN:
1341 sum += show_vty_pce_subtlv_domain(vty, tlvh);
1342 break;
1343 case RI_PCE_SUBTLV_NEIGHBOR:
1344 sum += show_vty_pce_subtlv_neighbor(vty, tlvh);
1345 break;
1346 case RI_PCE_SUBTLV_CAP_FLAG:
1347 sum += show_vty_pce_subtlv_cap_flag(vty, tlvh);
1348 break;
1349 default:
1350 sum += show_vty_unknown_tlv(vty, tlvh);
1351 break;
1352 }
1353 }
1354 return sum;
0ef4bcdc
OD
1355}
1356
cf9b9f77 1357/* Display Segment Routing Algorithm TLV information */
93f0a26e 1358static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
cf9b9f77
OD
1359{
1360 struct ri_sr_tlv_sr_algorithm *algo =
1361 (struct ri_sr_tlv_sr_algorithm *)tlvh;
1362 int i;
7743f2f8 1363
cf9b9f77
OD
1364 if (vty != NULL) {
1365 vty_out(vty, " Segment Routing Algorithm TLV:\n");
1366 for (i = 0; i < ntohs(algo->header.length); i++) {
1367 switch (algo->value[i]) {
1368 case 0:
1369 vty_out(vty, " Algorithm %d: SPF\n", i);
1370 break;
1371 case 1:
1372 vty_out(vty, " Algorithm %d: Strict SPF\n",
1373 i);
1374 break;
1375 default:
1376 vty_out(vty,
1377 " Algorithm %d: Unknown value %d\n", i,
1378 algo->value[i]);
1379 break;
1380 }
1381 }
1382 }
1383
1384 else {
9165c5f5 1385 zlog_debug(" Segment Routing Algorithm TLV:");
cf9b9f77
OD
1386 for (i = 0; i < ntohs(algo->header.length); i++)
1387 switch (algo->value[i]) {
1388 case 0:
9165c5f5 1389 zlog_debug(" Algorithm %d: SPF", i);
cf9b9f77
OD
1390 break;
1391 case 1:
9165c5f5 1392 zlog_debug(" Algorithm %d: Strict SPF", i);
cf9b9f77
OD
1393 break;
1394 default:
63efca0e
DL
1395 zlog_debug(" Algorithm %d: Unknown value %d",
1396 i, algo->value[i]);
cf9b9f77
OD
1397 break;
1398 }
1399 }
1400
1401 return TLV_SIZE(tlvh);
1402}
1403
1404/* Display Segment Routing SID/Label Range TLV information */
93f0a26e 1405static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
cf9b9f77
OD
1406{
1407 struct ri_sr_tlv_sid_label_range *range =
1408 (struct ri_sr_tlv_sid_label_range *)tlvh;
1409
1410 if (vty != NULL) {
1411 vty_out(vty,
1412 " Segment Routing Range TLV:\n"
1413 " Range Size = %d\n"
1414 " SID Label = %d\n\n",
1415 GET_RANGE_SIZE(ntohl(range->size)),
1416 GET_LABEL(ntohl(range->lower.value)));
1417 } else {
1418 zlog_debug(
1419 " Segment Routing Range TLV:\n"
1420 " Range Size = %d\n"
1421 " SID Label = %d\n\n",
1422 GET_RANGE_SIZE(ntohl(range->size)),
1423 GET_LABEL(ntohl(range->lower.value)));
1424 }
1425
1426 return TLV_SIZE(tlvh);
1427}
1428
1429/* Display Segment Routing Maximum Stack Depth TLV information */
93f0a26e 1430static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
cf9b9f77
OD
1431{
1432 struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
1433
1434 if (vty != NULL) {
1435 vty_out(vty,
1436 " Segment Routing MSD TLV:\n"
1437 " Node Maximum Stack Depth = %d\n",
1438 msd->value);
1439 } else {
1440 zlog_debug(
1441 " Segment Routing MSD TLV:\n"
1442 " Node Maximum Stack Depth = %d\n",
1443 msd->value);
1444 }
1445
1446 return TLV_SIZE(tlvh);
1447}
1448
d62a17ae 1449static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
0ef4bcdc 1450{
c4efd0f4 1451 struct lsa_header *lsah = lsa->data;
ead99d5f 1452 struct tlv_header *tlvh;
d7c0a89a 1453 uint16_t length = 0, sum = 0;
d62a17ae 1454
1455 /* Initialize TLV browsing */
1456 length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
1457
ead99d5f
OD
1458 for (tlvh = TLV_HDR_TOP(lsah); sum < length;
1459 tlvh = TLV_HDR_NEXT(tlvh)) {
d62a17ae 1460 switch (ntohs(tlvh->type)) {
1461 case RI_TLV_CAPABILITIES:
1462 sum += show_vty_router_cap(vty, tlvh);
1463 break;
1464 case RI_TLV_PCE:
1465 tlvh++;
ead99d5f 1466 sum += TLV_HDR_SIZE;
d62a17ae 1467 sum += show_vty_pce_info(vty, tlvh, length - sum);
1468 break;
cf9b9f77
OD
1469 case RI_SR_TLV_SR_ALGORITHM:
1470 sum += show_vty_sr_algorithm(vty, tlvh);
1471 break;
1472 case RI_SR_TLV_SID_LABEL_RANGE:
1473 sum += show_vty_sr_range(vty, tlvh);
1474 break;
1475 case RI_SR_TLV_NODE_MSD:
1476 sum += show_vty_sr_msd(vty, tlvh);
1477 break;
1478
d62a17ae 1479 default:
1480 sum += show_vty_unknown_tlv(vty, tlvh);
1481 break;
1482 }
1483 }
1484
1485 return;
0ef4bcdc
OD
1486}
1487
d62a17ae 1488static void ospf_router_info_config_write_router(struct vty *vty)
0ef4bcdc 1489{
d62a17ae 1490 struct ospf_pce_info *pce = &OspfRI.pce_info;
1491 struct listnode *node;
1492 struct ri_pce_subtlv_domain *domain;
1493 struct ri_pce_subtlv_neighbor *neighbor;
1494 struct in_addr tmp;
1495
cf9b9f77
OD
1496 if (!OspfRI.enabled)
1497 return;
1498
1499 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1500 vty_out(vty, " router-info as\n");
1501 else
ddd73a96 1502 vty_out(vty, " router-info area\n");
cf9b9f77
OD
1503
1504 if (OspfRI.pce_info.enabled) {
1505
1506 if (pce->pce_address.header.type != 0)
1507 vty_out(vty, " pce address %s\n",
1508 inet_ntoa(pce->pce_address.address.value));
1509
1510 if (pce->pce_cap_flag.header.type != 0)
1511 vty_out(vty, " pce flag 0x%x\n",
1512 ntohl(pce->pce_cap_flag.value));
1513
1514 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1515 if (domain->header.type != 0) {
1516 if (domain->type == PCE_DOMAIN_TYPE_AREA) {
1517 tmp.s_addr = domain->value;
1518 vty_out(vty, " pce domain area %s\n",
1519 inet_ntoa(tmp));
1520 } else {
1521 vty_out(vty, " pce domain as %d\n",
1522 ntohl(domain->value));
d62a17ae 1523 }
1524 }
cf9b9f77 1525 }
d62a17ae 1526
cf9b9f77
OD
1527 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1528 if (neighbor->header.type != 0) {
1529 if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
1530 tmp.s_addr = neighbor->value;
1531 vty_out(vty, " pce neighbor area %s\n",
1532 inet_ntoa(tmp));
1533 } else {
1534 vty_out(vty, " pce neighbor as %d\n",
1535 ntohl(neighbor->value));
d62a17ae 1536 }
1537 }
ead99d5f 1538 }
cf9b9f77
OD
1539
1540 if (pce->pce_scope.header.type != 0)
1541 vty_out(vty, " pce scope 0x%x\n",
1542 ntohl(OspfRI.pce_info.pce_scope.value));
d62a17ae 1543 }
1544 return;
0ef4bcdc
OD
1545}
1546
1547/*------------------------------------------------------------------------*
1548 * Followings are vty command functions.
1549 *------------------------------------------------------------------------*/
ddd73a96
OD
1550/* Simple wrapper schedule RI LSA action in function of the scope */
1551static void ospf_router_info_schedule(enum lsa_opcode opcode)
1552{
1553 struct listnode *node, *nnode;
1554 struct ospf_ri_area_info *ai;
1555
1556 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
1557 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
1558 ospf_router_info_lsa_schedule(NULL, opcode);
1559 else if (opcode == REORIGINATE_THIS_LSA)
1560 ospf_router_info_lsa_schedule(NULL, opcode);
1561 } else {
1562 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
1563 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
1564 ospf_router_info_lsa_schedule(ai, opcode);
1565 }
1566 }
1567}
0ef4bcdc
OD
1568
1569DEFUN (router_info,
1570 router_info_area_cmd,
ddd73a96 1571 "router-info <as|area [A.B.C.D]>",
0ef4bcdc 1572 OSPF_RI_STR
692b4c65 1573 "Enable the Router Information functionality with AS flooding scope\n"
0ef4bcdc 1574 "Enable the Router Information functionality with Area flooding scope\n"
ddd73a96 1575 "OSPF area ID in IP format (deprecated)\n")
0ef4bcdc 1576{
ddd73a96 1577 int idx_mode = 1;
d7c0a89a 1578 uint8_t scope;
d62a17ae 1579
32ab5cf4 1580 if (OspfRI.enabled)
d62a17ae 1581 return CMD_SUCCESS;
1582
1583 /* Check and get Area value if present */
ddd73a96 1584 if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
d62a17ae 1585 scope = OSPF_OPAQUE_AS_LSA;
ddd73a96
OD
1586 else
1587 scope = OSPF_OPAQUE_AREA_LSA;
d62a17ae 1588
1589 /* First start to register Router Information callbacks */
ddd73a96 1590 if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
239697e3
DS
1591 vty_out(vty,
1592 "%% Unable to register Router Information callbacks.");
1593 flog_err(
cf444bcf 1594 EC_OSPF_INIT_FAIL,
ddd73a96
OD
1595 "RI (%s): Unable to register Router Information callbacks. Abort!",
1596 __func__);
d62a17ae 1597 return CMD_WARNING_CONFIG_FAILED;
1598 }
1599
32ab5cf4 1600 OspfRI.enabled = true;
d62a17ae 1601
1602 if (IS_DEBUG_OSPF_EVENT)
1603 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1604 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area"
1605 : "AS");
1606
1607 /*
1608 * Following code is intended to handle two cases;
1609 *
1610 * 1) Router Information was disabled at startup time, but now become
1611 * enabled.
1612 * 2) Router Information was once enabled then disabled, and now enabled
1613 * again.
1614 */
1615
1616 initialize_params(&OspfRI);
1617
ddd73a96
OD
1618 /* Originate or Refresh RI LSA if already engaged */
1619 ospf_router_info_schedule(REORIGINATE_THIS_LSA);
d62a17ae 1620 return CMD_SUCCESS;
0ef4bcdc
OD
1621}
1622
0ef4bcdc
OD
1623
1624DEFUN (no_router_info,
1625 no_router_info_cmd,
1626 "no router-info",
1627 NO_STR
1628 "Disable the Router Information functionality\n")
1629{
1630
32ab5cf4 1631 if (!OspfRI.enabled)
d62a17ae 1632 return CMD_SUCCESS;
0ef4bcdc 1633
d62a17ae 1634 if (IS_DEBUG_OSPF_EVENT)
1635 zlog_debug("RI-> Router Information: ON -> OFF");
0ef4bcdc 1636
ddd73a96 1637 ospf_router_info_schedule(FLUSH_THIS_LSA);
0ef4bcdc 1638
32ab5cf4 1639 OspfRI.enabled = false;
0ef4bcdc 1640
d62a17ae 1641 return CMD_SUCCESS;
0ef4bcdc
OD
1642}
1643
d62a17ae 1644static int ospf_ri_enabled(struct vty *vty)
284a4a0c 1645{
32ab5cf4 1646 if (OspfRI.enabled)
d62a17ae 1647 return 1;
284a4a0c 1648
d62a17ae 1649 if (vty)
1650 vty_out(vty, "%% OSPF RI is not turned on\n");
284a4a0c 1651
d62a17ae 1652 return 0;
284a4a0c
DS
1653}
1654
0ef4bcdc
OD
1655DEFUN (pce_address,
1656 pce_address_cmd,
1657 "pce address A.B.C.D",
1658 PCE_STR
1659 "Stable IP address of the PCE\n"
1660 "PCE address in IPv4 address format\n")
1661{
d62a17ae 1662 int idx_ipv4 = 2;
1663 struct in_addr value;
1664 struct ospf_pce_info *pi = &OspfRI.pce_info;
0ef4bcdc 1665
d62a17ae 1666 if (!ospf_ri_enabled(vty))
1667 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1668
d62a17ae 1669 if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
1670 vty_out(vty, "Please specify PCE Address by A.B.C.D\n");
1671 return CMD_WARNING_CONFIG_FAILED;
1672 }
0ef4bcdc 1673
d62a17ae 1674 if (ntohs(pi->pce_address.header.type) == 0
1675 || ntohl(pi->pce_address.address.value.s_addr)
1676 != ntohl(value.s_addr)) {
0ef4bcdc 1677
d62a17ae 1678 set_pce_address(value, pi);
0ef4bcdc 1679
d62a17ae 1680 /* Refresh RI LSA if already engaged */
ddd73a96 1681 ospf_router_info_schedule(REFRESH_THIS_LSA);
d62a17ae 1682 }
0ef4bcdc 1683
d62a17ae 1684 return CMD_SUCCESS;
0ef4bcdc
OD
1685}
1686
1687DEFUN (no_pce_address,
1688 no_pce_address_cmd,
2328428d 1689 "no pce address [A.B.C.D]",
0ef4bcdc
OD
1690 NO_STR
1691 PCE_STR
59768a63
DS
1692 "Disable PCE address\n"
1693 "PCE address in IPv4 address format\n")
0ef4bcdc
OD
1694{
1695
9ffaacb0 1696 unset_param(&OspfRI.pce_info.pce_address);
0ef4bcdc 1697
d62a17ae 1698 /* Refresh RI LSA if already engaged */
ddd73a96 1699 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1700
d62a17ae 1701 return CMD_SUCCESS;
0ef4bcdc
OD
1702}
1703
1704DEFUN (pce_path_scope,
1705 pce_path_scope_cmd,
1706 "pce scope BITPATTERN",
1707 PCE_STR
1708 "Path scope visibilities of the PCE for path computation\n"
1709 "32-bit Hexadecimal value\n")
1710{
d62a17ae 1711 int idx_bitpattern = 2;
1712 uint32_t scope;
1713 struct ospf_pce_info *pi = &OspfRI.pce_info;
0ef4bcdc 1714
d62a17ae 1715 if (!ospf_ri_enabled(vty))
1716 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1717
d62a17ae 1718 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &scope) != 1) {
1719 vty_out(vty, "pce_path_scope: fscanf: %s\n",
1720 safe_strerror(errno));
1721 return CMD_WARNING_CONFIG_FAILED;
1722 }
0ef4bcdc 1723
d62a17ae 1724 if (ntohl(pi->pce_scope.header.type) == 0
1725 || scope != pi->pce_scope.value) {
1726 set_pce_path_scope(scope, pi);
0ef4bcdc 1727
d62a17ae 1728 /* Refresh RI LSA if already engaged */
ddd73a96 1729 ospf_router_info_schedule(REFRESH_THIS_LSA);
d62a17ae 1730 }
0ef4bcdc 1731
d62a17ae 1732 return CMD_SUCCESS;
0ef4bcdc
OD
1733}
1734
1735DEFUN (no_pce_path_scope,
1736 no_pce_path_scope_cmd,
2328428d 1737 "no pce scope [BITPATTERN]",
0ef4bcdc
OD
1738 NO_STR
1739 PCE_STR
59768a63
DS
1740 "Disable PCE path scope\n"
1741 "32-bit Hexadecimal value\n")
0ef4bcdc
OD
1742{
1743
9ffaacb0 1744 unset_param(&OspfRI.pce_info.pce_address);
0ef4bcdc 1745
d62a17ae 1746 /* Refresh RI LSA if already engaged */
ddd73a96 1747 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1748
d62a17ae 1749 return CMD_SUCCESS;
0ef4bcdc
OD
1750}
1751
1752DEFUN (pce_domain,
1753 pce_domain_cmd,
6147e2c6 1754 "pce domain as (0-65535)",
0ef4bcdc
OD
1755 PCE_STR
1756 "Configure PCE domain AS number\n"
1757 "AS number where the PCE as visibilities for path computation\n"
1758 "AS number in decimal <0-65535>\n")
1759{
d62a17ae 1760 int idx_number = 3;
0ef4bcdc 1761
d62a17ae 1762 uint32_t as;
1763 struct ospf_pce_info *pce = &OspfRI.pce_info;
1764 struct listnode *node;
1765 struct ri_pce_subtlv_domain *domain;
0ef4bcdc 1766
d62a17ae 1767 if (!ospf_ri_enabled(vty))
1768 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1769
0651460e 1770 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1771 vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno));
1772 return CMD_WARNING_CONFIG_FAILED;
1773 }
0ef4bcdc 1774
d62a17ae 1775 /* Check if the domain is not already in the domain list */
1776 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1777 if (ntohl(domain->header.type) == 0 && as == domain->value)
1778 return CMD_SUCCESS;
1779 }
0ef4bcdc 1780
d62a17ae 1781 /* Create new domain if not found */
1782 set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1783
d62a17ae 1784 /* Refresh RI LSA if already engaged */
ddd73a96 1785 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1786
d62a17ae 1787 return CMD_SUCCESS;
0ef4bcdc
OD
1788}
1789
1790DEFUN (no_pce_domain,
1791 no_pce_domain_cmd,
6147e2c6 1792 "no pce domain as (0-65535)",
0ef4bcdc
OD
1793 NO_STR
1794 PCE_STR
1795 "Disable PCE domain AS number\n"
1796 "AS number where the PCE as visibilities for path computation\n"
1797 "AS number in decimal <0-65535>\n")
1798{
d62a17ae 1799 int idx_number = 4;
0ef4bcdc 1800
d62a17ae 1801 uint32_t as;
1802 struct ospf_pce_info *pce = &OspfRI.pce_info;
0ef4bcdc 1803
0651460e 1804 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1805 vty_out(vty, "no_pce_domain: fscanf: %s\n",
1806 safe_strerror(errno));
1807 return CMD_WARNING_CONFIG_FAILED;
1808 }
0ef4bcdc 1809
d62a17ae 1810 /* Unset corresponding PCE domain */
1811 unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1812
d62a17ae 1813 /* Refresh RI LSA if already engaged */
ddd73a96 1814 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1815
d62a17ae 1816 return CMD_SUCCESS;
0ef4bcdc
OD
1817}
1818
1819DEFUN (pce_neigbhor,
1820 pce_neighbor_cmd,
6147e2c6 1821 "pce neighbor as (0-65535)",
0ef4bcdc
OD
1822 PCE_STR
1823 "Configure PCE neighbor domain AS number\n"
1824 "AS number of PCE neighbors\n"
1825 "AS number in decimal <0-65535>\n")
1826{
d62a17ae 1827 int idx_number = 3;
0ef4bcdc 1828
d62a17ae 1829 uint32_t as;
1830 struct ospf_pce_info *pce = &OspfRI.pce_info;
1831 struct listnode *node;
1832 struct ri_pce_subtlv_neighbor *neighbor;
0ef4bcdc 1833
d62a17ae 1834 if (!ospf_ri_enabled(vty))
1835 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1836
0651460e 1837 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1838 vty_out(vty, "pce_neighbor: fscanf: %s\n",
1839 safe_strerror(errno));
1840 return CMD_WARNING_CONFIG_FAILED;
1841 }
0ef4bcdc 1842
d62a17ae 1843 /* Check if the domain is not already in the domain list */
1844 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1845 if (ntohl(neighbor->header.type) == 0 && as == neighbor->value)
1846 return CMD_SUCCESS;
1847 }
0ef4bcdc 1848
d62a17ae 1849 /* Create new domain if not found */
1850 set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1851
d62a17ae 1852 /* Refresh RI LSA if already engaged */
ddd73a96 1853 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1854
d62a17ae 1855 return CMD_SUCCESS;
0ef4bcdc
OD
1856}
1857
1858DEFUN (no_pce_neighbor,
1859 no_pce_neighbor_cmd,
6147e2c6 1860 "no pce neighbor as (0-65535)",
0ef4bcdc
OD
1861 NO_STR
1862 PCE_STR
1863 "Disable PCE neighbor AS number\n"
1864 "AS number of PCE neighbor\n"
1865 "AS number in decimal <0-65535>\n")
1866{
d62a17ae 1867 int idx_number = 4;
0ef4bcdc 1868
d62a17ae 1869 uint32_t as;
1870 struct ospf_pce_info *pce = &OspfRI.pce_info;
0ef4bcdc 1871
0651460e 1872 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1873 vty_out(vty, "no_pce_neighbor: fscanf: %s\n",
1874 safe_strerror(errno));
1875 return CMD_WARNING_CONFIG_FAILED;
1876 }
0ef4bcdc 1877
d62a17ae 1878 /* Unset corresponding PCE domain */
1879 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1880
d62a17ae 1881 /* Refresh RI LSA if already engaged */
ddd73a96 1882 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1883
d62a17ae 1884 return CMD_SUCCESS;
0ef4bcdc
OD
1885}
1886
1887DEFUN (pce_cap_flag,
1888 pce_cap_flag_cmd,
1889 "pce flag BITPATTERN",
1890 PCE_STR
1891 "Capabilities of the PCE for path computation\n"
1892 "32-bit Hexadecimal value\n")
1893{
d62a17ae 1894 int idx_bitpattern = 2;
0ef4bcdc 1895
d62a17ae 1896 uint32_t cap;
1897 struct ospf_pce_info *pce = &OspfRI.pce_info;
0ef4bcdc 1898
d62a17ae 1899 if (!ospf_ri_enabled(vty))
1900 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1901
d62a17ae 1902 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &cap) != 1) {
1903 vty_out(vty, "pce_cap_flag: fscanf: %s\n",
1904 safe_strerror(errno));
1905 return CMD_WARNING_CONFIG_FAILED;
1906 }
0ef4bcdc 1907
d62a17ae 1908 if (ntohl(pce->pce_cap_flag.header.type) == 0
1909 || cap != pce->pce_cap_flag.value) {
1910 set_pce_cap_flag(cap, pce);
0ef4bcdc 1911
d62a17ae 1912 /* Refresh RI LSA if already engaged */
ddd73a96 1913 ospf_router_info_schedule(REFRESH_THIS_LSA);
d62a17ae 1914 }
0ef4bcdc 1915
d62a17ae 1916 return CMD_SUCCESS;
0ef4bcdc
OD
1917}
1918
1919DEFUN (no_pce_cap_flag,
1920 no_pce_cap_flag_cmd,
1921 "no pce flag",
1922 NO_STR
1923 PCE_STR
1924 "Disable PCE capabilities\n")
1925{
1926
9ffaacb0 1927 unset_param(&OspfRI.pce_info.pce_cap_flag);
0ef4bcdc 1928
d62a17ae 1929 /* Refresh RI LSA if already engaged */
ddd73a96 1930 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1931
d62a17ae 1932 return CMD_SUCCESS;
0ef4bcdc
OD
1933}
1934
1935DEFUN (show_ip_ospf_router_info,
1936 show_ip_ospf_router_info_cmd,
1937 "show ip ospf router-info",
1938 SHOW_STR
1939 IP_STR
1940 OSPF_STR
1941 "Router Information\n")
1942{
1943
32ab5cf4 1944 if (OspfRI.enabled) {
d62a17ae 1945 vty_out(vty, "--- Router Information parameters ---\n");
1946 show_vty_router_cap(vty, &OspfRI.router_cap.header);
1947 } else {
1948 if (vty != NULL)
1949 vty_out(vty,
1950 " Router Information is disabled on this router\n");
1951 }
1952 return CMD_SUCCESS;
0ef4bcdc
OD
1953}
1954
1955DEFUN (show_ip_opsf_router_info_pce,
1956 show_ip_ospf_router_info_pce_cmd,
1957 "show ip ospf router-info pce",
1958 SHOW_STR
1959 IP_STR
1960 OSPF_STR
1961 "Router Information\n"
1962 "PCE information\n")
1963{
1964
d62a17ae 1965 struct ospf_pce_info *pce = &OspfRI.pce_info;
1966 struct listnode *node;
1967 struct ri_pce_subtlv_domain *domain;
1968 struct ri_pce_subtlv_neighbor *neighbor;
0ef4bcdc 1969
cf9b9f77 1970 if ((OspfRI.enabled) && (OspfRI.pce_info.enabled)) {
d62a17ae 1971 vty_out(vty, "--- PCE parameters ---\n");
0ef4bcdc 1972
d62a17ae 1973 if (pce->pce_address.header.type != 0)
1974 show_vty_pce_subtlv_address(vty,
1975 &pce->pce_address.header);
0ef4bcdc 1976
d62a17ae 1977 if (pce->pce_scope.header.type != 0)
1978 show_vty_pce_subtlv_path_scope(vty,
1979 &pce->pce_scope.header);
0ef4bcdc 1980
d62a17ae 1981 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1982 if (domain->header.type != 0)
1983 show_vty_pce_subtlv_domain(vty,
1984 &domain->header);
1985 }
0ef4bcdc 1986
d62a17ae 1987 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1988 if (neighbor->header.type != 0)
1989 show_vty_pce_subtlv_neighbor(vty,
1990 &neighbor->header);
1991 }
0ef4bcdc 1992
d62a17ae 1993 if (pce->pce_cap_flag.header.type != 0)
1994 show_vty_pce_subtlv_cap_flag(vty,
1995 &pce->pce_cap_flag.header);
0ef4bcdc 1996
d62a17ae 1997 } else {
996c9314 1998 vty_out(vty, " PCE info is disabled on this router\n");
d62a17ae 1999 }
0ef4bcdc 2000
d62a17ae 2001 return CMD_SUCCESS;
0ef4bcdc
OD
2002}
2003
2004/* Install new CLI commands */
d62a17ae 2005static void ospf_router_info_register_vty(void)
0ef4bcdc 2006{
d62a17ae 2007 install_element(VIEW_NODE, &show_ip_ospf_router_info_cmd);
2008 install_element(VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
2009
2010 install_element(OSPF_NODE, &router_info_area_cmd);
2011 install_element(OSPF_NODE, &no_router_info_cmd);
2012 install_element(OSPF_NODE, &pce_address_cmd);
2013 install_element(OSPF_NODE, &no_pce_address_cmd);
2014 install_element(OSPF_NODE, &pce_path_scope_cmd);
2015 install_element(OSPF_NODE, &no_pce_path_scope_cmd);
2016 install_element(OSPF_NODE, &pce_domain_cmd);
2017 install_element(OSPF_NODE, &no_pce_domain_cmd);
2018 install_element(OSPF_NODE, &pce_neighbor_cmd);
2019 install_element(OSPF_NODE, &no_pce_neighbor_cmd);
2020 install_element(OSPF_NODE, &pce_cap_flag_cmd);
2021 install_element(OSPF_NODE, &no_pce_cap_flag_cmd);
2022
2023 return;
0ef4bcdc 2024}