Coverage Report

Created: 2025-08-28 06:29

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