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