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