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