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