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