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