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