Coverage Report

Created: 2025-10-23 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/ospfd/ospf_ext.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * This is an implementation of RFC7684 OSPFv2 Prefix/Link Attribute
4
 * Advertisement
5
 *
6
 * Module name: Extended Prefix/Link Opaque LSA
7
 *
8
 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
9
 * Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
10
 *
11
 * Copyright (C) 2016 - 2018 Orange Labs http://www.orange.com
12
 */
13
14
#include <zebra.h>
15
#include <math.h>
16
#include <stdio.h>
17
#include <stdlib.h>
18
19
#include "linklist.h"
20
#include "prefix.h"
21
#include "if.h"
22
#include "table.h"
23
#include "memory.h"
24
#include "command.h"
25
#include "vty.h"
26
#include "stream.h"
27
#include "log.h"
28
#include "frrevent.h"
29
#include "hash.h"
30
#include "sockunion.h" /* for inet_aton() */
31
#include "network.h"
32
#include "if.h"
33
#include "libospf.h" /* for ospf interface types */
34
35
#include "ospfd/ospfd.h"
36
#include "ospfd/ospf_interface.h"
37
#include "ospfd/ospf_ism.h"
38
#include "ospfd/ospf_asbr.h"
39
#include "ospfd/ospf_lsa.h"
40
#include "ospfd/ospf_lsdb.h"
41
#include "ospfd/ospf_neighbor.h"
42
#include "ospfd/ospf_nsm.h"
43
#include "ospfd/ospf_flood.h"
44
#include "ospfd/ospf_packet.h"
45
#include "ospfd/ospf_spf.h"
46
#include "ospfd/ospf_dump.h"
47
#include "ospfd/ospf_route.h"
48
#include "ospfd/ospf_ase.h"
49
#include "ospfd/ospf_zebra.h"
50
#include "ospfd/ospf_sr.h"
51
#include "ospfd/ospf_ext.h"
52
#include "ospfd/ospf_errors.h"
53
54
/* Following structure are internal use only. */
55
56
/*
57
 * Global variable to manage Extended Prefix/Link Opaque LSA on this node.
58
 * Note that all parameter values are stored in network byte order.
59
 */
60
static struct ospf_ext_lp OspfEXT;
61
62
/*
63
 * -----------------------------------------------------------------------
64
 * Following are initialize/terminate functions for Extended Prefix/Link
65
 * Opaque LSA handling.
66
 * -----------------------------------------------------------------------
67
 */
68
69
/* Extended Prefix Opaque LSA related callback functions */
70
static void ospf_ext_pref_show_info(struct vty *vty, struct json_object *json,
71
            struct ospf_lsa *lsa);
72
static int ospf_ext_pref_lsa_originate(void *arg);
73
static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa);
74
static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti,
75
               enum lsa_opcode opcode);
76
/* Extended Link Opaque LSA related callback functions */
77
static int ospf_ext_link_new_if(struct interface *ifp);
78
static int ospf_ext_link_del_if(struct interface *ifp);
79
static void ospf_ext_ism_change(struct ospf_interface *oi, int old_status);
80
static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status);
81
static void ospf_ext_link_show_info(struct vty *vty, struct json_object *json,
82
            struct ospf_lsa *lsa);
83
static int ospf_ext_link_lsa_originate(void *arg);
84
static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa);
85
static void ospf_ext_link_lsa_schedule(struct ext_itf *exti,
86
               enum lsa_opcode opcode);
87
static void ospf_ext_lsa_schedule(struct ext_itf *exti, enum lsa_opcode op);
88
static int ospf_ext_link_lsa_update(struct ospf_lsa *lsa);
89
static int ospf_ext_pref_lsa_update(struct ospf_lsa *lsa);
90
static void ospf_ext_link_delete_adj_sid(struct ext_itf *exti);
91
static void del_ext_info(void *val);
92
93
/*
94
 * Extended Link/Prefix initialization
95
 *
96
 * @param - none
97
 *
98
 * @return - 0 if OK, <> 0 otherwise
99
 */
100
int ospf_ext_init(void)
101
1
{
102
1
  int rc = 0;
103
104
1
  memset(&OspfEXT, 0, sizeof(OspfEXT));
105
1
  OspfEXT.enabled = false;
106
  /* Only Area flooding is supported yet */
107
1
  OspfEXT.scope = OSPF_OPAQUE_AREA_LSA;
108
  /* Initialize interface list */
109
1
  OspfEXT.iflist = list_new();
110
1
  OspfEXT.iflist->del = del_ext_info;
111
112
1
  zlog_info("EXT (%s): Register Extended Link Opaque LSA", __func__);
113
1
  rc = ospf_register_opaque_functab(
114
1
    OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_EXTENDED_LINK_LSA,
115
1
    ospf_ext_link_new_if, /* new if */
116
1
    ospf_ext_link_del_if, /* del if */
117
1
    ospf_ext_ism_change,  /* ism change */
118
1
    ospf_ext_link_nsm_change,    /* nsm change */
119
1
    NULL,          /* Write router config. */
120
1
    NULL,          /* Write interface conf. */
121
1
    NULL,          /* Write debug config. */
122
1
    ospf_ext_link_show_info,     /* Show LSA info */
123
1
    ospf_ext_link_lsa_originate, /* Originate LSA */
124
1
    ospf_ext_link_lsa_refresh,   /* Refresh LSA */
125
1
    ospf_ext_link_lsa_update,    /* new_lsa_hook */
126
1
    NULL);           /* del_lsa_hook */
127
128
1
  if (rc != 0) {
129
0
    flog_warn(EC_OSPF_OPAQUE_REGISTRATION,
130
0
        "EXT (%s): Failed to register Extended Link LSA",
131
0
        __func__);
132
0
    return rc;
133
0
  }
134
135
1
  zlog_info("EXT (%s): Register Extended Prefix Opaque LSA", __func__);
136
1
  rc = ospf_register_opaque_functab(
137
1
    OspfEXT.scope, OPAQUE_TYPE_EXTENDED_PREFIX_LSA,
138
1
    NULL,          /* new if handle by link */
139
1
    NULL,          /* del if handle by link */
140
1
    NULL,          /* ism change */
141
1
    NULL,          /* nsm change */
142
1
    ospf_sr_config_write_router, /* Write router config. */
143
1
    NULL,          /* Write interface conf. */
144
1
    NULL,          /* Write debug config. */
145
1
    ospf_ext_pref_show_info,     /* Show LSA info */
146
1
    ospf_ext_pref_lsa_originate, /* Originate LSA */
147
1
    ospf_ext_pref_lsa_refresh,   /* Refresh LSA */
148
1
    ospf_ext_pref_lsa_update,    /* new_lsa_hook */
149
1
    NULL);           /* del_lsa_hook */
150
1
  if (rc != 0) {
151
0
    flog_warn(EC_OSPF_OPAQUE_REGISTRATION,
152
0
        "EXT (%s): Failed to register Extended Prefix LSA",
153
0
        __func__);
154
0
    return rc;
155
0
  }
156
157
1
  return rc;
158
1
}
159
160
/*
161
 * Extended Link/Prefix termination function
162
 *
163
 * @param - none
164
 * @return - none
165
 */
166
void ospf_ext_term(void)
167
0
{
168
169
0
  if ((OspfEXT.scope == OSPF_OPAQUE_AREA_LSA)
170
0
      || (OspfEXT.scope == OSPF_OPAQUE_AS_LSA))
171
0
    ospf_delete_opaque_functab(OspfEXT.scope,
172
0
             OPAQUE_TYPE_EXTENDED_PREFIX_LSA);
173
174
0
  ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
175
0
           OPAQUE_TYPE_EXTENDED_LINK_LSA);
176
177
0
  list_delete(&OspfEXT.iflist);
178
0
  OspfEXT.scope = 0;
179
0
  OspfEXT.enabled = false;
180
181
0
  return;
182
0
}
183
184
/*
185
 * Extended Link/Prefix finish function
186
 *
187
 * @param - none
188
 * @return - none
189
 */
190
void ospf_ext_finish(void)
191
0
{
192
193
0
  struct listnode *node;
194
0
  struct ext_itf *exti;
195
196
  /* Flush Router Info LSA */
197
0
  for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti))
198
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
199
0
      ospf_ext_lsa_schedule(exti, FLUSH_THIS_LSA);
200
201
0
  OspfEXT.enabled = false;
202
0
}
203
204
/*
205
 * ---------------------------------------------------------------------
206
 * Following are control functions for Extended Prefix/Link Opaque LSA
207
 * parameters management.
208
 * ---------------------------------------------------------------------
209
 */
210
211
/* Functions to free memory space */
212
static void del_ext_info(void *val)
213
0
{
214
0
  XFREE(MTYPE_OSPF_EXT_PARAMS, val);
215
0
}
216
217
/* Increment instance value for Extended Prefix Opaque LSAs Opaque ID field */
218
static uint32_t get_ext_pref_instance_value(void)
219
0
{
220
0
  static uint32_t seqno = 0;
221
222
0
  if (seqno < MAX_LEGAL_EXT_INSTANCE_NUM)
223
0
    seqno += 1;
224
0
  else
225
0
    seqno = 1; /* Avoid zero. */
226
227
0
  return seqno;
228
0
}
229
230
/* Increment instance value for Extended Link Opaque LSAs Opaque ID field */
231
static uint32_t get_ext_link_instance_value(void)
232
0
{
233
0
  static uint32_t seqno = 0;
234
235
0
  if (seqno < MAX_LEGAL_EXT_INSTANCE_NUM)
236
0
    seqno += 1;
237
0
  else
238
0
    seqno = 1; /* Avoid zero. */
239
240
0
  return seqno;
241
0
}
242
243
/* Lookup Extended Prefix/Links by ifp from OspfEXT struct iflist */
244
static struct ext_itf *lookup_ext_by_ifp(struct interface *ifp)
245
1
{
246
1
  struct listnode *node;
247
1
  struct ext_itf *exti;
248
249
1
  for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti))
250
0
    if (exti->ifp == ifp)
251
0
      return exti;
252
253
1
  return NULL;
254
1
}
255
256
/* Lookup Extended Prefix/Links by LSA ID from OspfEXT struct iflist */
257
static struct ext_itf *lookup_ext_by_instance(struct ospf_lsa *lsa)
258
0
{
259
0
  struct listnode *node;
260
0
  struct ext_itf *exti;
261
0
  uint32_t key = GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr));
262
0
  uint8_t type = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
263
264
265
0
  for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti))
266
0
    if ((exti->instance == key) && (exti->type == type))
267
0
      return exti;
268
269
0
  return NULL;
270
0
}
271
272
/*
273
 * ----------------------------------------------------------------------
274
 * The underlying subsection defines setters and unsetters to create and
275
 * delete tlvs and subtlvs
276
 * ----------------------------------------------------------------------
277
 */
278
279
/* Extended Prefix TLV - RFC7684 section 2.1 */
280
static void set_ext_prefix(struct ext_itf *exti, uint8_t route_type,
281
         uint8_t flags, struct prefix_ipv4 p)
282
0
{
283
284
0
  TLV_TYPE(exti->prefix) = htons(EXT_TLV_PREFIX);
285
  /* Warning: Size must be adjust depending of subTLV's */
286
0
  TLV_LEN(exti->prefix) = htons(EXT_TLV_PREFIX_SIZE);
287
0
  exti->prefix.route_type = route_type;
288
0
  exti->prefix.flags = flags;
289
  /* Only Address Family Ipv4 (0) is defined in RFC 7684 */
290
0
  exti->prefix.af = 0;
291
0
  exti->prefix.pref_length = p.prefixlen;
292
0
  exti->prefix.address = p.prefix;
293
294
0
  SET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
295
0
}
296
297
/* Extended Link TLV - RFC7684 section 3.1 */
298
static void set_ext_link(struct ext_itf *exti, uint8_t type, struct in_addr id,
299
       struct in_addr data)
300
0
{
301
302
0
  TLV_TYPE(exti->link) = htons(EXT_TLV_LINK);
303
  /* Warning: Size must be adjust depending of subTLV's */
304
0
  TLV_LEN(exti->link) = htons(EXT_TLV_LINK_SIZE);
305
0
  exti->link.link_type = type;
306
0
  exti->link.link_id = id;
307
0
  exti->link.link_data = data;
308
0
}
309
310
/* Prefix SID SubTLV - section 5 */
311
static void set_prefix_sid(struct ext_itf *exti, uint8_t algorithm,
312
         uint32_t value, int value_type, uint8_t flags)
313
0
{
314
315
0
  if ((algorithm != SR_ALGORITHM_SPF)
316
0
      && (algorithm != SR_ALGORITHM_STRICT_SPF)) {
317
0
    flog_err(EC_OSPF_INVALID_ALGORITHM,
318
0
       "EXT (%s): unrecognized algorithm, not SPF or S-SPF",
319
0
       __func__);
320
0
    return;
321
0
  }
322
323
  /* Update flags according to the type of value field: label or index */
324
0
  if (value_type == SID_LABEL)
325
0
    SET_FLAG(flags, EXT_SUBTLV_PREFIX_SID_VFLG);
326
327
  /* set prefix sid subtlv for an extended prefix tlv */
328
0
  TLV_TYPE(exti->node_sid) = htons(EXT_SUBTLV_PREFIX_SID);
329
0
  exti->node_sid.algorithm = algorithm;
330
0
  exti->node_sid.flags = flags;
331
0
  exti->node_sid.mtid = 0; /* Multi-Topology is not supported */
332
333
  /* Set Label or Index value */
334
0
  if (value_type == SID_LABEL) {
335
0
    TLV_LEN(exti->node_sid) =
336
0
      htons(SID_LABEL_SIZE(EXT_SUBTLV_PREFIX_SID_SIZE));
337
0
    exti->node_sid.value = htonl(SET_LABEL(value));
338
0
  } else {
339
0
    TLV_LEN(exti->node_sid) =
340
0
      htons(SID_INDEX_SIZE(EXT_SUBTLV_PREFIX_SID_SIZE));
341
0
    exti->node_sid.value = htonl(value);
342
0
  }
343
0
}
344
345
/* Adjacency SID SubTLV - section 6.1 */
346
static void set_adj_sid(struct ext_itf *exti, bool backup, uint32_t value,
347
      int value_type)
348
0
{
349
0
  int index;
350
0
  uint8_t flags;
351
352
  /* Determine which ADJ_SID must be set: nominal or backup */
353
0
  if (backup) {
354
0
    flags = EXT_SUBTLV_LINK_ADJ_SID_BFLG;
355
0
    index = 1;
356
0
  } else {
357
0
    index = 0;
358
0
    flags = 0;
359
0
  }
360
361
  /* Set Header */
362
0
  TLV_TYPE(exti->adj_sid[index]) = htons(EXT_SUBTLV_ADJ_SID);
363
364
  /* Only Local ADJ-SID is supported for the moment */
365
0
  SET_FLAG(flags, EXT_SUBTLV_LINK_ADJ_SID_LFLG);
366
367
0
  exti->adj_sid[index].mtid = 0; /* Multi-Topology is not supported */
368
369
  /* Adjust Length, Flags and Value depending on the type of Label */
370
0
  if (value_type == SID_LABEL) {
371
0
    SET_FLAG(flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG);
372
0
    TLV_LEN(exti->adj_sid[index]) =
373
0
      htons(SID_LABEL_SIZE(EXT_SUBTLV_ADJ_SID_SIZE));
374
0
    exti->adj_sid[index].value = htonl(SET_LABEL(value));
375
0
  } else {
376
0
    UNSET_FLAG(flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG);
377
0
    TLV_LEN(exti->adj_sid[index]) =
378
0
      htons(SID_INDEX_SIZE(EXT_SUBTLV_ADJ_SID_SIZE));
379
0
    exti->adj_sid[index].value = htonl(value);
380
0
  }
381
382
0
  exti->adj_sid[index].flags = flags; /* Set computed flags */
383
0
  exti->adj_sid[index].mtid = 0;   /* Multi-Topology is not supported */
384
0
  exti->adj_sid[index].weight = 0; /* Load-Balancing is not supported */
385
0
}
386
387
/* LAN Adjacency SID SubTLV - section 6.2 */
388
static void set_lan_adj_sid(struct ext_itf *exti, bool backup, uint32_t value,
389
          int value_type, struct in_addr neighbor_id)
390
0
{
391
392
0
  int index;
393
0
  uint8_t flags;
394
395
  /* Determine which ADJ_SID must be set: nominal or backup */
396
0
  if (backup) {
397
0
    flags = EXT_SUBTLV_LINK_ADJ_SID_BFLG;
398
0
    index = 1;
399
0
  } else {
400
0
    index = 0;
401
0
    flags = 0;
402
0
  }
403
404
  /* Set Header */
405
0
  TLV_TYPE(exti->lan_sid[index]) = htons(EXT_SUBTLV_LAN_ADJ_SID);
406
407
  /* Only Local ADJ-SID is supported for the moment */
408
0
  SET_FLAG(flags, EXT_SUBTLV_LINK_ADJ_SID_LFLG);
409
410
  /* Adjust Length, Flags and Value depending on the type of Label */
411
0
  if (value_type == SID_LABEL) {
412
0
    SET_FLAG(flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG);
413
0
    TLV_LEN(exti->lan_sid[index]) =
414
0
      htons(SID_LABEL_SIZE(EXT_SUBTLV_PREFIX_RANGE_SIZE));
415
0
    exti->lan_sid[index].value = htonl(SET_LABEL(value));
416
0
  } else {
417
0
    UNSET_FLAG(flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG);
418
0
    TLV_LEN(exti->lan_sid[index]) =
419
0
      htons(SID_INDEX_SIZE(EXT_SUBTLV_PREFIX_RANGE_SIZE));
420
0
    exti->lan_sid[index].value = htonl(value);
421
0
  }
422
423
0
  exti->lan_sid[index].flags = flags; /* Set computed flags */
424
0
  exti->lan_sid[index].mtid = 0;   /* Multi-Topology is not supported */
425
0
  exti->lan_sid[index].weight = 0; /* Load-Balancing is not supported */
426
0
  exti->lan_sid[index].neighbor_id = neighbor_id;
427
0
}
428
429
static void unset_adjacency_sid(struct ext_itf *exti)
430
0
{
431
  /* Reset Adjacency TLV */
432
0
  if (exti->type == ADJ_SID) {
433
0
    TLV_TYPE(exti->adj_sid[0]) = 0;
434
0
    TLV_TYPE(exti->adj_sid[1]) = 0;
435
0
  }
436
  /* or Lan-Adjacency TLV */
437
0
  if (exti->type == LAN_ADJ_SID) {
438
0
    TLV_TYPE(exti->lan_sid[0]) = 0;
439
0
    TLV_TYPE(exti->lan_sid[1]) = 0;
440
0
  }
441
0
}
442
443
/* Experimental SubTLV from Cisco */
444
static void set_rmt_itf_addr(struct ext_itf *exti, struct in_addr rmtif)
445
0
{
446
447
0
  TLV_TYPE(exti->rmt_itf_addr) = htons(EXT_SUBTLV_RMT_ITF_ADDR);
448
0
  TLV_LEN(exti->rmt_itf_addr) = htons(sizeof(struct in_addr));
449
0
  exti->rmt_itf_addr.value = rmtif;
450
0
}
451
452
/* Delete Extended LSA */
453
static void ospf_extended_lsa_delete(struct ext_itf *exti)
454
0
{
455
456
  /* Avoid deleting LSA if Extended is not enable */
457
0
  if (!OspfEXT.enabled)
458
0
    return;
459
460
  /* Process only Active Extended Prefix/Link LSA */
461
0
  if (!CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE))
462
0
    return;
463
464
0
  osr_debug("EXT (%s): Disable %s%s%s-SID on interface %s", __func__,
465
0
      exti->stype == LOCAL_SID ? "Prefix" : "",
466
0
      exti->stype == ADJ_SID ? "Adjacency" : "",
467
0
      exti->stype == LAN_ADJ_SID ? "LAN-Adjacency" : "",
468
0
      exti->ifp->name);
469
470
  /* Flush LSA if already engaged */
471
0
  if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED)) {
472
0
    ospf_ext_lsa_schedule(exti, FLUSH_THIS_LSA);
473
0
    UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
474
0
  }
475
476
  /* De-activate this Extended Prefix/Link and remove corresponding
477
   * Segment-Routing Prefix-SID or (LAN)-ADJ-SID */
478
0
  if (exti->stype == ADJ_SID || exti->stype == LAN_ADJ_SID)
479
0
    ospf_ext_link_delete_adj_sid(exti);
480
0
  else
481
0
    ospf_sr_ext_itf_delete(exti);
482
0
}
483
484
/*
485
 * Update Extended prefix SID index for Loopback interface type
486
 *
487
 * @param ifname - Loopback interface name
488
 * @param index - new value for the prefix SID of this interface
489
 * @param p - prefix for this interface or NULL if Extended Prefix
490
 * should be remove
491
 *
492
 * @return instance number if update is OK, 0 otherwise
493
 */
494
uint32_t ospf_ext_schedule_prefix_index(struct interface *ifp, uint32_t index,
495
          struct prefix_ipv4 *p, uint8_t flags)
496
0
{
497
0
  int rc = 0;
498
0
  struct ext_itf *exti;
499
500
  /* Find Extended Prefix interface */
501
0
  exti = lookup_ext_by_ifp(ifp);
502
0
  if (exti == NULL)
503
0
    return rc;
504
505
0
  if (p != NULL) {
506
0
    osr_debug("EXT (%s): Schedule new prefix %pFX with index %u on interface %s", __func__, p, index, ifp->name);
507
508
    /* Set first Extended Prefix then the Prefix SID information */
509
0
    set_ext_prefix(exti, OSPF_PATH_INTRA_AREA, EXT_TLV_PREF_NFLG,
510
0
             *p);
511
0
    set_prefix_sid(exti, SR_ALGORITHM_SPF, index, SID_INDEX, flags);
512
513
    /* Try to Schedule LSA */
514
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE)) {
515
0
      if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
516
0
        ospf_ext_pref_lsa_schedule(exti,
517
0
                 REFRESH_THIS_LSA);
518
0
      else
519
0
        ospf_ext_pref_lsa_schedule(
520
0
          exti, REORIGINATE_THIS_LSA);
521
0
    }
522
0
  } else {
523
0
    osr_debug("EXT (%s): Remove prefix for interface %s", __func__,
524
0
        ifp->name);
525
526
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
527
0
      ospf_ext_pref_lsa_schedule(exti, FLUSH_THIS_LSA);
528
0
  }
529
530
0
  return SET_OPAQUE_LSID(exti->type, exti->instance);
531
0
}
532
533
/**
534
 * Update Adjacecny-SID for Extended Link LSA
535
 *
536
 * @param exti  Extended Link information
537
 */
538
static void ospf_ext_link_update_adj_sid(struct ext_itf *exti)
539
0
{
540
0
  mpls_label_t label;
541
0
  mpls_label_t bck_label;
542
543
  /* Process only (LAN)Adjacency-SID Type */
544
0
  if (exti->stype != ADJ_SID && exti->stype != LAN_ADJ_SID)
545
0
    return;
546
547
  /* Request Primary & Backup Labels from Label Manager */
548
0
  bck_label = ospf_sr_local_block_request_label();
549
0
  label = ospf_sr_local_block_request_label();
550
0
  if (bck_label == MPLS_INVALID_LABEL || label == MPLS_INVALID_LABEL) {
551
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
552
0
      ospf_ext_lsa_schedule(exti, FLUSH_THIS_LSA);
553
0
    return;
554
0
  }
555
556
  /* Set Adjacency-SID, backup first */
557
0
  if (exti->stype == ADJ_SID) {
558
0
    set_adj_sid(exti, true, bck_label, SID_LABEL);
559
0
    set_adj_sid(exti, false, label, SID_LABEL);
560
0
  } else {
561
0
    set_lan_adj_sid(exti, true, bck_label, SID_LABEL,
562
0
        exti->lan_sid[0].neighbor_id);
563
0
    set_lan_adj_sid(exti, false, label, SID_LABEL,
564
0
        exti->lan_sid[1].neighbor_id);
565
0
  }
566
567
  /* Finally, add corresponding SR Link in SRDB & MPLS LFIB */
568
0
  SET_FLAG(exti->flags, EXT_LPFLG_FIB_ENTRY_SET);
569
0
  ospf_sr_ext_itf_add(exti);
570
0
}
571
572
/**
573
 * Delete Adjacecny-SID for Extended Link LSA
574
 *
575
 * @param exti  Extended Link information
576
 */
577
static void ospf_ext_link_delete_adj_sid(struct ext_itf *exti)
578
0
{
579
  /* Process only (LAN)Adjacency-SID Type */
580
0
  if (exti->stype != ADJ_SID && exti->stype != LAN_ADJ_SID)
581
0
    return;
582
583
  /* Release Primary & Backup Labels from Label Manager */
584
0
  if (exti->stype == ADJ_SID) {
585
0
    ospf_sr_local_block_release_label(exti->adj_sid[0].value);
586
0
    ospf_sr_local_block_release_label(exti->adj_sid[1].value);
587
0
  } else {
588
0
    ospf_sr_local_block_release_label(exti->lan_sid[0].value);
589
0
    ospf_sr_local_block_release_label(exti->lan_sid[1].value);
590
0
  }
591
  /* And reset corresponding TLV */
592
0
  unset_adjacency_sid(exti);
593
594
  /* Finally, remove corresponding SR Link in SRDB & MPLS LFIB */
595
0
  UNSET_FLAG(exti->flags, EXT_LPFLG_FIB_ENTRY_SET);
596
0
  ospf_sr_ext_itf_delete(exti);
597
0
}
598
599
/**
600
 * Update Extended Link LSA once Segment Routing Label Block has been changed.
601
 */
602
void ospf_ext_link_srlb_update(void)
603
0
{
604
0
  struct listnode *node;
605
0
  struct ext_itf *exti;
606
607
608
0
  osr_debug("EXT (%s): Update Extended Links with new SRLB", __func__);
609
610
  /* Update all Extended Link Adjaceny-SID  */
611
0
  for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti)) {
612
    /* Skip Extended Prefix */
613
0
    if (exti->stype == PREF_SID || exti->stype == LOCAL_SID)
614
0
      continue;
615
616
    /* Skip inactive Extended Link */
617
0
    if (!CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE))
618
0
      continue;
619
620
0
    ospf_ext_link_update_adj_sid(exti);
621
0
  }
622
0
}
623
624
/*
625
 * Used by Segment Routing to activate/deactivate Extended Link/Prefix flooding
626
 *
627
 * @param enable To activate or not Segment Routing Extended LSA flooding
628
 *
629
 * @return none
630
 */
631
void ospf_ext_update_sr(bool enable)
632
0
{
633
0
  struct listnode *node;
634
0
  struct ext_itf *exti;
635
636
0
  osr_debug("EXT (%s): %s Extended LSAs for Segment Routing ", __func__,
637
0
      enable ? "Enable" : "Disable");
638
639
0
  if (enable) {
640
0
    OspfEXT.enabled = true;
641
642
    /* Refresh LSAs if already engaged or originate */
643
0
    for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti)) {
644
      /* Skip Inactive Extended Link */
645
0
      if (!CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE))
646
0
        continue;
647
648
      /* Update Extended Link (LAN)Adj-SID if not set  */
649
0
      if (!CHECK_FLAG(exti->flags, EXT_LPFLG_FIB_ENTRY_SET))
650
0
        ospf_ext_link_update_adj_sid(exti);
651
652
      /* Finally, flood the extended Link */
653
0
      if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
654
0
        ospf_ext_lsa_schedule(exti, REFRESH_THIS_LSA);
655
0
      else
656
0
        ospf_ext_lsa_schedule(exti,
657
0
                  REORIGINATE_THIS_LSA);
658
0
    }
659
0
  } else {
660
    /* Start by Removing Extended LSA */
661
0
    for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti))
662
0
      ospf_extended_lsa_delete(exti);
663
664
    /* And then disable Extended Link/Prefix */
665
0
    OspfEXT.enabled = false;
666
0
  }
667
0
}
668
669
/*
670
 * -----------------------------------------------------------------------
671
 * Following are callback functions against generic Opaque-LSAs handling
672
 * -----------------------------------------------------------------------
673
 */
674
675
/* Add new Interface in Extended Interface List */
676
static int ospf_ext_link_new_if(struct interface *ifp)
677
1
{
678
1
  struct ext_itf *new;
679
1
  int rc = -1;
680
681
1
  if (lookup_ext_by_ifp(ifp) != NULL) {
682
0
    rc = 0; /* Do nothing here. */
683
0
    return rc;
684
0
  }
685
686
1
  new = XCALLOC(MTYPE_OSPF_EXT_PARAMS, sizeof(struct ext_itf));
687
688
  /* initialize new information and link back the interface */
689
1
  new->ifp = ifp;
690
1
  new->flags = EXT_LPFLG_LSA_INACTIVE;
691
692
1
  listnode_add(OspfEXT.iflist, new);
693
694
1
  rc = 0;
695
1
  return rc;
696
1
}
697
698
/* Remove existing Interface from Extended Interface List */
699
static int ospf_ext_link_del_if(struct interface *ifp)
700
0
{
701
0
  struct ext_itf *exti;
702
0
  int rc = -1;
703
704
0
  exti = lookup_ext_by_ifp(ifp);
705
0
  if (exti != NULL) {
706
    /* Flush LSA and remove Adjacency SID */
707
0
    ospf_extended_lsa_delete(exti);
708
709
    /* Dequeue listnode entry from the list. */
710
0
    listnode_delete(OspfEXT.iflist, exti);
711
712
0
    XFREE(MTYPE_OSPF_EXT_PARAMS, exti);
713
714
0
    rc = 0;
715
0
  } else {
716
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
717
0
        "EXT (%s): interface %s is not found", __func__,
718
0
        ifp ? ifp->name : "-");
719
0
  }
720
721
0
  return rc;
722
0
}
723
724
/*
725
 * Determine if an Interface belongs to an Extended Link Adjacency or
726
 * Extended Prefix SID type and allocate new instance value accordingly
727
 */
728
static void ospf_ext_ism_change(struct ospf_interface *oi, int old_status)
729
0
{
730
0
  struct ext_itf *exti;
731
732
  /* Get interface information for Segment Routing */
733
0
  exti = lookup_ext_by_ifp(oi->ifp);
734
0
  if (exti == NULL) {
735
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
736
0
        "EXT (%s): Cannot get Extended info. from OI(%s)",
737
0
        __func__, IF_NAME(oi));
738
0
    return;
739
0
  }
740
741
  /* Reset Extended information if ospf interface goes Down */
742
0
  if (oi->state == ISM_Down) {
743
0
    ospf_extended_lsa_delete(exti);
744
0
    exti->area = NULL;
745
0
    exti->flags = EXT_LPFLG_LSA_INACTIVE;
746
0
    return;
747
0
  }
748
749
  /* Determine if interface is related to a Prefix or an Adjacency SID */
750
0
  if (oi->type == OSPF_IFTYPE_LOOPBACK) {
751
0
    exti->stype = PREF_SID;
752
0
    exti->type = OPAQUE_TYPE_EXTENDED_PREFIX_LSA;
753
0
    exti->instance = get_ext_pref_instance_value();
754
0
    exti->area = oi->area;
755
756
    /* Complete SRDB if the interface belongs to a Prefix */
757
0
    if (OspfEXT.enabled) {
758
0
      osr_debug("EXT (%s): Set Prefix SID to interface %s ",
759
0
          __func__, oi->ifp->name);
760
0
      ospf_sr_update_local_prefix(oi->ifp, oi->address);
761
0
    }
762
0
  } else {
763
    /* Determine if interface is related to Adj. or LAN Adj. SID */
764
0
    if (oi->state == ISM_DR)
765
0
      exti->stype = LAN_ADJ_SID;
766
0
    else
767
0
      exti->stype = ADJ_SID;
768
769
0
    exti->type = OPAQUE_TYPE_EXTENDED_LINK_LSA;
770
0
    exti->instance = get_ext_link_instance_value();
771
0
    exti->area = oi->area;
772
773
    /*
774
     * Note: Adjacency SID information are completed when ospf
775
     * adjacency become up see ospf_ext_link_nsm_change()
776
     */
777
0
    if (OspfEXT.enabled)
778
0
      osr_debug(
779
0
        "EXT (%s): Set %sAdjacency SID for interface %s ",
780
0
        __func__, exti->stype == ADJ_SID ? "" : "LAN-",
781
0
        oi->ifp->name);
782
0
  }
783
0
}
784
785
/*
786
 * Finish Extended Link configuration and flood corresponding LSA
787
 * when OSPF adjacency on this link fire up
788
 */
789
static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status)
790
0
{
791
0
  struct ospf_interface *oi = nbr->oi;
792
0
  struct ext_itf *exti;
793
794
  /* Process Link only when neighbor old or new state is NSM Full */
795
0
  if (nbr->state != NSM_Full && old_status != NSM_Full)
796
0
    return;
797
798
  /* Get interface information for Segment Routing */
799
0
  exti = lookup_ext_by_ifp(oi->ifp);
800
0
  if (exti == NULL) {
801
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
802
0
        "EXT (%s): Cannot get Extended info. from OI(%s)",
803
0
        __func__, IF_NAME(oi));
804
0
    return;
805
0
  }
806
807
  /* Check that we have a valid area and ospf context */
808
0
  if (oi->area == NULL || oi->area->ospf == NULL) {
809
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
810
0
        "EXT (%s): Cannot refer to OSPF from OI(%s)",
811
0
        __func__, IF_NAME(oi));
812
0
    return;
813
0
  }
814
815
  /* Remove Extended Link if Neighbor State goes Down or Deleted */
816
0
  if (OspfEXT.enabled
817
0
      && (nbr->state == NSM_Down || nbr->state == NSM_Deleted)) {
818
0
    ospf_ext_link_delete_adj_sid(exti);
819
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
820
0
      ospf_ext_link_lsa_schedule(exti, FLUSH_THIS_LSA);
821
0
    exti->flags = EXT_LPFLG_LSA_INACTIVE;
822
0
    return;
823
0
  }
824
825
  /* Keep Area information in combination with SR info. */
826
0
  exti->area = oi->area;
827
828
  /* Process only Adjacency/LAN SID */
829
0
  if (exti->stype == PREF_SID)
830
0
    return;
831
832
0
  switch (oi->state) {
833
0
  case ISM_PointToPoint:
834
    /* Segment ID is an Adjacency one */
835
0
    exti->stype = ADJ_SID;
836
837
    /* Set Extended Link TLV with link_id == Nbr Router ID */
838
0
    set_ext_link(exti, OSPF_IFTYPE_POINTOPOINT, nbr->router_id,
839
0
           oi->address->u.prefix4);
840
841
    /* And Remote Interface address */
842
0
    set_rmt_itf_addr(exti, nbr->address.u.prefix4);
843
844
0
    break;
845
846
0
  case ISM_DR:
847
    /* Segment ID is a LAN Adjacency for the DR only */
848
0
    exti->stype = LAN_ADJ_SID;
849
850
    /* Set Extended Link TLV with link_id == DR */
851
0
    set_ext_link(exti, OSPF_IFTYPE_BROADCAST, DR(oi),
852
0
           oi->address->u.prefix4);
853
854
    /* Set Neighbor ID */
855
0
    exti->lan_sid[0].neighbor_id = nbr->router_id;
856
0
    exti->lan_sid[1].neighbor_id = nbr->router_id;
857
858
0
    break;
859
860
0
  case ISM_DROther:
861
0
  case ISM_Backup:
862
    /* Segment ID is an Adjacency if not the DR */
863
0
    exti->stype = ADJ_SID;
864
865
    /* Set Extended Link TLV with link_id == DR */
866
0
    set_ext_link(exti, OSPF_IFTYPE_BROADCAST, DR(oi),
867
0
           oi->address->u.prefix4);
868
869
0
    break;
870
871
0
  default:
872
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_FIB_ENTRY_SET))
873
0
      ospf_ext_link_delete_adj_sid(exti);
874
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
875
0
      ospf_ext_link_lsa_schedule(exti, FLUSH_THIS_LSA);
876
0
    exti->flags = EXT_LPFLG_LSA_INACTIVE;
877
0
    return;
878
0
  }
879
880
0
  SET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
881
882
0
  if (OspfEXT.enabled) {
883
0
    osr_debug("EXT (%s): Set %sAdjacency SID for interface %s ",
884
0
        __func__, exti->stype == ADJ_SID ? "" : "LAN-",
885
0
        oi->ifp->name);
886
887
    /* Update (LAN)Adjacency SID */
888
0
    ospf_ext_link_update_adj_sid(exti);
889
890
    /* flood this links params if everything is ok */
891
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
892
0
      ospf_ext_link_lsa_schedule(exti, REFRESH_THIS_LSA);
893
0
    else
894
0
      ospf_ext_link_lsa_schedule(exti, REORIGINATE_THIS_LSA);
895
0
  }
896
0
}
897
898
/* Callbacks to handle Extended Link Segment Routing LSA information */
899
static int ospf_ext_link_lsa_update(struct ospf_lsa *lsa)
900
1.07k
{
901
  /* Sanity Check */
902
1.07k
  if (lsa == NULL) {
903
0
    flog_warn(EC_OSPF_LSA_NULL, "EXT (%s): Abort! LSA is NULL",
904
0
        __func__);
905
0
    return -1;
906
0
  }
907
908
  /* Process only Opaque LSA */
909
1.07k
  if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
910
1.04k
      && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
911
1.02k
    return 0;
912
913
  /* Process only Extended Link LSA */
914
44
  if (GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
915
44
      != OPAQUE_TYPE_EXTENDED_LINK_LSA)
916
44
    return 0;
917
918
  /* Check if it is not my LSA */
919
0
  if (IS_LSA_SELF(lsa))
920
0
    return 0;
921
922
  /* Check if Extended is enable */
923
0
  if (!OspfEXT.enabled)
924
0
    return 0;
925
926
  /* Call Segment Routing LSA update or deletion */
927
0
  if (!IS_LSA_MAXAGE(lsa))
928
0
    ospf_sr_ext_link_lsa_update(lsa);
929
0
  else
930
0
    ospf_sr_ext_link_lsa_delete(lsa);
931
932
0
  return 0;
933
0
}
934
935
/* Callbacks to handle Extended Prefix Segment Routing LSA information */
936
static int ospf_ext_pref_lsa_update(struct ospf_lsa *lsa)
937
1.07k
{
938
939
  /* Sanity Check */
940
1.07k
  if (lsa == NULL) {
941
0
    flog_warn(EC_OSPF_LSA_NULL, "EXT (%s): Abort! LSA is NULL",
942
0
        __func__);
943
0
    return -1;
944
0
  }
945
946
  /* Process only Opaque LSA */
947
1.07k
  if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
948
1.04k
      && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
949
1.02k
    return 0;
950
951
  /* Process only Extended Prefix LSA */
952
44
  if (GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
953
44
      != OPAQUE_TYPE_EXTENDED_PREFIX_LSA)
954
44
    return 0;
955
956
  /* Check if it is not my LSA */
957
0
  if (IS_LSA_SELF(lsa))
958
0
    return 0;
959
960
  /* Check if Extended is enable */
961
0
  if (!OspfEXT.enabled)
962
0
    return 0;
963
964
  /* Call Segment Routing LSA update or deletion */
965
0
  if (!IS_LSA_MAXAGE(lsa))
966
0
    ospf_sr_ext_prefix_lsa_update(lsa);
967
0
  else
968
0
    ospf_sr_ext_prefix_lsa_delete(lsa);
969
970
0
  return 0;
971
0
}
972
973
/*
974
 * -------------------------------------------------------
975
 * Following are OSPF protocol processing functions for
976
 * Extended Prefix/Link Opaque LSA
977
 * -------------------------------------------------------
978
 */
979
980
static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
981
0
{
982
0
  stream_put(s, tlvh, sizeof(struct tlv_header));
983
0
}
984
985
static void build_tlv(struct stream *s, struct tlv_header *tlvh)
986
0
{
987
988
0
  if ((tlvh != NULL) && (ntohs(tlvh->type) != 0)) {
989
0
    build_tlv_header(s, tlvh);
990
0
    stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
991
0
  }
992
0
}
993
994
/* Build an Extended Prefix Opaque LSA body for extended prefix TLV */
995
static void ospf_ext_pref_lsa_body_set(struct stream *s, struct ext_itf *exti)
996
0
{
997
998
  /* Sanity check */
999
0
  if ((exti == NULL) || (exti->stype != PREF_SID))
1000
0
    return;
1001
1002
  /* Adjust Extended Prefix TLV size */
1003
0
  TLV_LEN(exti->prefix) = htons(ntohs(TLV_LEN(exti->node_sid))
1004
0
              + EXT_TLV_PREFIX_SIZE + TLV_HDR_SIZE);
1005
1006
  /* Build LSA body for an Extended Prefix TLV */
1007
0
  build_tlv_header(s, &exti->prefix.header);
1008
0
  stream_put(s, TLV_DATA(&exti->prefix.header), EXT_TLV_PREFIX_SIZE);
1009
  /* Then add Prefix SID SubTLV */
1010
0
  build_tlv(s, &exti->node_sid.header);
1011
0
}
1012
1013
/* Build an Extended Link Opaque LSA body for extended link TLV */
1014
static void ospf_ext_link_lsa_body_set(struct stream *s, struct ext_itf *exti)
1015
0
{
1016
0
  size_t size;
1017
1018
  /* Sanity check */
1019
0
  if ((exti == NULL)
1020
0
      || ((exti->stype != ADJ_SID) && (exti->stype != LAN_ADJ_SID)))
1021
0
    return;
1022
1023
0
  if (exti->stype == ADJ_SID) {
1024
    /* Adjust Extended Link TLV size for Adj. SID */
1025
0
    size = EXT_TLV_LINK_SIZE + 2 * EXT_SUBTLV_ADJ_SID_SIZE
1026
0
           + 2 * TLV_HDR_SIZE;
1027
0
    if (ntohs(TLV_TYPE(exti->rmt_itf_addr)) != 0)
1028
0
      size = size + EXT_SUBTLV_RMT_ITF_ADDR_SIZE
1029
0
             + TLV_HDR_SIZE;
1030
0
    TLV_LEN(exti->link) = htons(size);
1031
1032
    /* Build LSA body for an Extended Link TLV with Adj. SID */
1033
0
    build_tlv_header(s, &exti->link.header);
1034
0
    stream_put(s, TLV_DATA(&exti->link.header), EXT_TLV_LINK_SIZE);
1035
    /* then add Adjacency SubTLVs */
1036
0
    build_tlv(s, &exti->adj_sid[1].header);
1037
0
    build_tlv(s, &exti->adj_sid[0].header);
1038
1039
    /* Add Cisco experimental SubTLV if interface is PtoP */
1040
0
    if (ntohs(TLV_TYPE(exti->rmt_itf_addr)) != 0)
1041
0
      build_tlv(s, &exti->rmt_itf_addr.header);
1042
0
  } else {
1043
    /* Adjust Extended Link TLV size for LAN SID */
1044
0
    size = EXT_TLV_LINK_SIZE
1045
0
           + 2 * (EXT_SUBTLV_LAN_ADJ_SID_SIZE + TLV_HDR_SIZE);
1046
0
    TLV_LEN(exti->link) = htons(size);
1047
1048
    /* Build LSA body for an Extended Link TLV with LAN SID */
1049
0
    build_tlv_header(s, &exti->link.header);
1050
0
    stream_put(s, TLV_DATA(&exti->link.header), EXT_TLV_LINK_SIZE);
1051
    /* then add LAN-Adjacency SubTLVs */
1052
0
    build_tlv(s, &exti->lan_sid[1].header);
1053
0
    build_tlv(s, &exti->lan_sid[0].header);
1054
0
  }
1055
0
}
1056
1057
/* Create new Extended Prefix opaque-LSA for every extended prefix */
1058
static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area,
1059
                struct ext_itf *exti)
1060
0
{
1061
0
  struct stream *s;
1062
0
  struct lsa_header *lsah;
1063
0
  struct ospf_lsa *new = NULL;
1064
0
  struct ospf *top;
1065
0
  uint8_t options, lsa_type;
1066
0
  struct in_addr lsa_id;
1067
0
  struct in_addr router_id;
1068
0
  uint32_t tmp;
1069
0
  uint16_t length;
1070
1071
  /* Sanity Check */
1072
0
  if (exti == NULL)
1073
0
    return NULL;
1074
1075
  /* Create a stream for LSA. */
1076
0
  s = stream_new(OSPF_MAX_LSA_SIZE);
1077
1078
  /* Prepare LSA Header */
1079
0
  lsah = (struct lsa_header *)STREAM_DATA(s);
1080
1081
0
  lsa_type = OspfEXT.scope;
1082
1083
  /*
1084
   * LSA ID is a variable number identifying different instances of
1085
   * Extended Prefix Opaque LSA from the same router see RFC 7684
1086
   */
1087
0
  tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_EXTENDED_PREFIX_LSA, exti->instance);
1088
0
  lsa_id.s_addr = htonl(tmp);
1089
1090
0
  options = OSPF_OPTION_O; /* Don't forget this :-) */
1091
1092
  /* Fix Options and Router ID depending of the flooding scope */
1093
0
  if ((OspfEXT.scope == OSPF_OPAQUE_AS_LSA) || (area == NULL)) {
1094
0
    options = OSPF_OPTION_E;
1095
0
    top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1096
0
    router_id.s_addr = top ? top->router_id.s_addr : 0;
1097
0
  } else {
1098
0
    options |= LSA_OPTIONS_GET(area); /* Get area default option */
1099
0
    options |= LSA_OPTIONS_NSSA_GET(area);
1100
0
    router_id = area->ospf->router_id;
1101
0
  }
1102
1103
  /* Set opaque-LSA header fields. */
1104
0
  lsa_header_set(s, options, lsa_type, lsa_id, router_id);
1105
1106
0
  osr_debug(
1107
0
    "EXT (%s): LSA[Type%u:%pI4]: Create an Opaque-LSA Extended Prefix Opaque LSA instance",
1108
0
    __func__, lsa_type, &lsa_id);
1109
1110
  /* Set opaque-LSA body fields. */
1111
0
  ospf_ext_pref_lsa_body_set(s, exti);
1112
1113
  /* Set length. */
1114
0
  length = stream_get_endp(s);
1115
0
  lsah->length = htons(length);
1116
1117
  /* Now, create an OSPF LSA instance. */
1118
0
  new = ospf_lsa_new_and_data(length);
1119
1120
  /* Segment Routing belongs only to default VRF */
1121
0
  new->vrf_id = VRF_DEFAULT;
1122
0
  new->area = area;
1123
0
  SET_FLAG(new->flags, OSPF_LSA_SELF);
1124
0
  memcpy(new->data, lsah, length);
1125
0
  stream_free(s);
1126
1127
0
  return new;
1128
0
}
1129
1130
/* Create new Extended Link opaque-LSA for every extended link TLV */
1131
static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area,
1132
                struct ext_itf *exti)
1133
0
{
1134
0
  struct stream *s;
1135
0
  struct lsa_header *lsah;
1136
0
  struct ospf_lsa *new = NULL;
1137
0
  uint8_t options, lsa_type;
1138
0
  struct in_addr lsa_id;
1139
0
  uint32_t tmp;
1140
0
  uint16_t length;
1141
1142
  /* Sanity Check */
1143
0
  if (exti == NULL)
1144
0
    return NULL;
1145
1146
  /* Create a stream for LSA. */
1147
0
  s = stream_new(OSPF_MAX_LSA_SIZE);
1148
0
  lsah = (struct lsa_header *)STREAM_DATA(s);
1149
1150
0
  options = OSPF_OPTION_O;   /* Don't forget this :-) */
1151
0
  options |= LSA_OPTIONS_GET(area); /* Get area default option */
1152
0
  options |= LSA_OPTIONS_NSSA_GET(area);
1153
  /* Extended Link Opaque LSA are only flooded within an area */
1154
0
  lsa_type = OSPF_OPAQUE_AREA_LSA;
1155
1156
  /*
1157
   * LSA ID is a variable number identifying different instances of
1158
   * Extended Link Opaque LSA from the same router see RFC 7684
1159
   */
1160
0
  tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_EXTENDED_LINK_LSA, exti->instance);
1161
0
  lsa_id.s_addr = htonl(tmp);
1162
1163
0
  osr_debug(
1164
0
    "EXT (%s) LSA[Type%u:%pI4]: Create an Opaque-LSA Extended Link Opaque LSA instance",
1165
0
    __func__, lsa_type, &lsa_id);
1166
1167
  /* Set opaque-LSA header fields. */
1168
0
  lsa_header_set(s, options, lsa_type, lsa_id, area->ospf->router_id);
1169
1170
  /* Set opaque-LSA body fields. */
1171
0
  ospf_ext_link_lsa_body_set(s, exti);
1172
1173
  /* Set length. */
1174
0
  length = stream_get_endp(s);
1175
0
  lsah->length = htons(length);
1176
1177
  /* Now, create an OSPF LSA instance. */
1178
0
  new = ospf_lsa_new_and_data(length);
1179
1180
  /* Segment Routing belongs only to default VRF */
1181
0
  new->vrf_id = VRF_DEFAULT;
1182
0
  new->area = area;
1183
0
  SET_FLAG(new->flags, OSPF_LSA_SELF);
1184
0
  memcpy(new->data, lsah, length);
1185
0
  stream_free(s);
1186
1187
0
  return new;
1188
0
}
1189
1190
/*
1191
 * Process the origination of an Extended Prefix Opaque LSA
1192
 * for every extended prefix TLV
1193
 */
1194
static int ospf_ext_pref_lsa_originate1(struct ospf_area *area,
1195
          struct ext_itf *exti)
1196
0
{
1197
0
  struct ospf_lsa *new;
1198
0
  int rc = -1;
1199
1200
1201
  /* Create new Opaque-LSA/Extended Prefix Opaque LSA instance. */
1202
0
  new = ospf_ext_pref_lsa_new(area, exti);
1203
0
  if (new == NULL) {
1204
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1205
0
        "EXT (%s): ospf_ext_pref_lsa_new() error", __func__);
1206
0
    return rc;
1207
0
  }
1208
1209
  /* Install this LSA into LSDB. */
1210
0
  if (ospf_lsa_install(area->ospf, NULL /*oi */, new) == NULL) {
1211
0
    flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1212
0
        "EXT (%s): ospf_lsa_install() error", __func__);
1213
0
    ospf_lsa_unlock(&new);
1214
0
    return rc;
1215
0
  }
1216
1217
  /* Now this Extended Prefix Opaque LSA info parameter entry has
1218
   * associated LSA.
1219
   */
1220
0
  SET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
1221
1222
  /* Update new LSA origination count. */
1223
0
  area->ospf->lsa_originate_count++;
1224
1225
  /* Flood new LSA through area. */
1226
0
  ospf_flood_through_area(area, NULL /*nbr */, new);
1227
1228
0
  osr_debug(
1229
0
    "EXT (%s): LSA[Type%u:%pI4]: Originate Opaque-LSAExtended Prefix Opaque LSA: Area(%pI4), Link(%s)",
1230
0
    __func__, new->data->type, &new->data->id,
1231
0
    &area->area_id, exti->ifp->name);
1232
0
  if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
1233
0
    ospf_lsa_header_dump(new->data);
1234
1235
0
  rc = 0;
1236
1237
0
  return rc;
1238
0
}
1239
1240
/*
1241
 * Process the origination of an Extended Link Opaque LSA
1242
 * for every extended link TLV
1243
 */
1244
static int ospf_ext_link_lsa_originate1(struct ospf_area *area,
1245
          struct ext_itf *exti)
1246
0
{
1247
0
  struct ospf_lsa *new;
1248
0
  int rc = -1;
1249
1250
  /* Create new Opaque-LSA/Extended Link Opaque LSA instance. */
1251
0
  new = ospf_ext_link_lsa_new(area, exti);
1252
0
  if (new == NULL) {
1253
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1254
0
        "EXT (%s): ospf_ext_link_lsa_new() error", __func__);
1255
0
    return rc;
1256
0
  }
1257
1258
  /* Install this LSA into LSDB. */
1259
0
  if (ospf_lsa_install(area->ospf, NULL /*oi */, new) == NULL) {
1260
0
    flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1261
0
        "EXT (%s): ospf_lsa_install() error", __func__);
1262
0
    ospf_lsa_unlock(&new);
1263
0
    return rc;
1264
0
  }
1265
1266
  /* Now this link-parameter entry has associated LSA. */
1267
0
  SET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
1268
1269
  /* Update new LSA origination count. */
1270
0
  area->ospf->lsa_originate_count++;
1271
1272
  /* Flood new LSA through area. */
1273
0
  ospf_flood_through_area(area, NULL /*nbr */, new);
1274
1275
0
  osr_debug(
1276
0
    "EXT (%s): LSA[Type%u:%pI4]: Originate Opaque-LSA Extended Link Opaque LSA: Area(%pI4), Link(%s)",
1277
0
    __func__, new->data->type, &new->data->id,
1278
0
    &area->area_id, exti->ifp->name);
1279
0
  if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
1280
0
    ospf_lsa_header_dump(new->data);
1281
1282
0
  rc = 0;
1283
1284
0
  return rc;
1285
0
}
1286
1287
/* Trigger the origination of Extended Prefix Opaque LSAs */
1288
static int ospf_ext_pref_lsa_originate(void *arg)
1289
0
{
1290
0
  struct ospf_area *area = (struct ospf_area *)arg;
1291
0
  struct listnode *node;
1292
0
  struct ext_itf *exti;
1293
0
  int rc = -1;
1294
1295
0
  if (!OspfEXT.enabled) {
1296
0
    zlog_info(
1297
0
      "EXT (%s): Segment Routing functionality is Disabled now",
1298
0
      __func__);
1299
0
    rc = 0; /* This is not an error case. */
1300
0
    return rc;
1301
0
  }
1302
0
  osr_debug("EXT (%s): Start Originate Prefix LSA for area %pI4",
1303
0
      __func__, &area->area_id);
1304
1305
  /* Check if Extended Prefix Opaque LSA is already engaged */
1306
0
  for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti)) {
1307
1308
    /* Process only Prefix SID */
1309
0
    if (exti->stype != PREF_SID)
1310
0
      continue;
1311
1312
    /* Process only Extended Prefix with valid Area ID */
1313
0
    if ((exti->area == NULL)
1314
0
        || (!IPV4_ADDR_SAME(&exti->area->area_id, &area->area_id)))
1315
0
      continue;
1316
1317
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED)) {
1318
0
      if (CHECK_FLAG(exti->flags,
1319
0
               EXT_LPFLG_LSA_FORCED_REFRESH)) {
1320
0
        flog_warn(
1321
0
          EC_OSPF_EXT_LSA_UNEXPECTED,
1322
0
          "EXT (%s): Refresh instead of Originate",
1323
0
          __func__);
1324
0
        UNSET_FLAG(exti->flags,
1325
0
             EXT_LPFLG_LSA_FORCED_REFRESH);
1326
0
        ospf_ext_pref_lsa_schedule(exti,
1327
0
                 REFRESH_THIS_LSA);
1328
0
      }
1329
0
      continue;
1330
0
    }
1331
1332
    /* Ok, let's try to originate an LSA */
1333
0
    osr_debug(
1334
0
      "EXT (%s): Let's finally re-originate the LSA 7.0.0.%u for Itf %s", __func__, exti->instance,
1335
0
      exti->ifp ? exti->ifp->name : "");
1336
0
    ospf_ext_pref_lsa_originate1(area, exti);
1337
0
  }
1338
1339
0
  rc = 0;
1340
0
  return rc;
1341
0
}
1342
1343
/* Trigger the origination of Extended Link Opaque LSAs */
1344
static int ospf_ext_link_lsa_originate(void *arg)
1345
0
{
1346
0
  struct ospf_area *area = (struct ospf_area *)arg;
1347
0
  struct listnode *node;
1348
0
  struct ext_itf *exti;
1349
0
  int rc = -1;
1350
1351
0
  if (!OspfEXT.enabled) {
1352
0
    zlog_info(
1353
0
      "EXT (%s): Segment Routing functionality is Disabled now",
1354
0
      __func__);
1355
0
    rc = 0; /* This is not an error case. */
1356
0
    return rc;
1357
0
  }
1358
1359
  /* Check if Extended Prefix Opaque LSA is already engaged */
1360
0
  for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti)) {
1361
    /* Process only Adjacency or LAN SID */
1362
0
    if (exti->stype == PREF_SID)
1363
0
      continue;
1364
1365
    /* Skip Inactive Extended Link */
1366
0
    if (!CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE))
1367
0
      continue;
1368
1369
    /* Process only Extended Link with valid Area ID */
1370
0
    if ((exti->area == NULL)
1371
0
        || (!IPV4_ADDR_SAME(&exti->area->area_id, &area->area_id)))
1372
0
      continue;
1373
1374
    /* Check if LSA not already engaged */
1375
0
    if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED)) {
1376
0
      if (CHECK_FLAG(exti->flags,
1377
0
               EXT_LPFLG_LSA_FORCED_REFRESH)) {
1378
0
        flog_warn(
1379
0
          EC_OSPF_EXT_LSA_UNEXPECTED,
1380
0
          "EXT (%s): Refresh instead of Originate",
1381
0
          __func__);
1382
0
        UNSET_FLAG(exti->flags,
1383
0
             EXT_LPFLG_LSA_FORCED_REFRESH);
1384
0
        ospf_ext_link_lsa_schedule(exti,
1385
0
                 REFRESH_THIS_LSA);
1386
0
      }
1387
0
      continue;
1388
0
    }
1389
1390
    /* Ok, let's try to originate an LSA */
1391
0
    osr_debug(
1392
0
      "EXT (%s): Let's finally reoriginate the LSA 8.0.0.%u for Itf %s through the Area %pI4", __func__,
1393
0
      exti->instance, exti->ifp ? exti->ifp->name : "-",
1394
0
      &area->area_id);
1395
0
    ospf_ext_link_lsa_originate1(area, exti);
1396
0
  }
1397
1398
0
  rc = 0;
1399
0
  return rc;
1400
0
}
1401
1402
/* Refresh an Extended Prefix Opaque LSA */
1403
static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa)
1404
0
{
1405
0
  struct ospf_lsa *new = NULL;
1406
0
  struct ospf_area *area = lsa->area;
1407
0
  struct ospf *top;
1408
0
  struct ext_itf *exti;
1409
1410
0
  if (!OspfEXT.enabled) {
1411
    /*
1412
     * This LSA must have flushed before due to Extended Prefix
1413
     * Opaque LSA status change.
1414
     * It seems a slip among routers in the routing domain.
1415
     */
1416
0
    zlog_info(
1417
0
      "EXT (%s): Segment Routing functionality is Disabled",
1418
0
      __func__);
1419
    /* Flush it anyway. */
1420
0
    lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1421
0
  }
1422
1423
  /* Lookup this lsa corresponding Extended parameters */
1424
0
  exti = lookup_ext_by_instance(lsa);
1425
0
  if (exti == NULL) {
1426
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1427
0
        "EXT (%s): Invalid parameter LSA ID", __func__);
1428
    /* Flush it anyway. */
1429
0
    lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1430
0
  }
1431
1432
  /* Check if Interface was not disable in the interval */
1433
0
  if ((exti != NULL) && !CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE)) {
1434
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1435
0
        "EXT (%s): Interface was Disabled: Flush it!",
1436
0
        __func__);
1437
    /* Flush it anyway. */
1438
0
    lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1439
0
  }
1440
1441
  /* If the lsa's age reached to MaxAge, start flushing procedure. */
1442
0
  if (IS_LSA_MAXAGE(lsa)) {
1443
0
    if (exti)
1444
0
      UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
1445
0
    ospf_opaque_lsa_flush_schedule(lsa);
1446
0
    return NULL;
1447
0
  }
1448
1449
  /* Create new Opaque-LSA/Extended Prefix Opaque LSA instance. */
1450
0
  new = ospf_ext_pref_lsa_new(area, exti);
1451
1452
0
  if (new == NULL) {
1453
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1454
0
        "EXT (%s): ospf_ext_pref_lsa_new() error", __func__);
1455
0
    return NULL;
1456
0
  }
1457
0
  new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1458
1459
  /*
1460
   * Install this LSA into LSDB
1461
   * Given "lsa" will be freed in the next function
1462
   * As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use
1463
   * ospf_lookup() to get ospf instance
1464
   */
1465
0
  if (area)
1466
0
    top = area->ospf;
1467
0
  else
1468
0
    top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1469
1470
0
  if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1471
0
    flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1472
0
        "EXT (%s): ospf_lsa_install() error", __func__);
1473
0
    ospf_lsa_unlock(&new);
1474
0
    return NULL;
1475
0
  }
1476
1477
  /* Flood updated LSA through the Prefix Area according to the RFC7684 */
1478
0
  ospf_flood_through_area(area, NULL /*nbr */, new);
1479
1480
  /* Debug logging. */
1481
0
  osr_debug("EXT (%s): LSA[Type%u:%pI4] Refresh Extended Prefix LSA",
1482
0
      __func__, new->data->type, &new->data->id);
1483
0
  if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
1484
0
    ospf_lsa_header_dump(new->data);
1485
1486
1487
0
  return new;
1488
0
}
1489
1490
/* Refresh an Extended Link Opaque LSA */
1491
static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa)
1492
0
{
1493
0
  struct ext_itf *exti;
1494
0
  struct ospf_area *area = lsa->area;
1495
0
  struct ospf *top = area->ospf;
1496
0
  struct ospf_lsa *new = NULL;
1497
1498
0
  if (!OspfEXT.enabled) {
1499
    /*
1500
     * This LSA must have flushed before due to OSPF-SR status
1501
     * change. It seems a slip among routers in the routing domain.
1502
     */
1503
0
    zlog_info("EXT (%s): Segment Routing functionality is Disabled",
1504
0
        __func__);
1505
    /* Flush it anyway. */
1506
0
    lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1507
0
  }
1508
1509
  /* Lookup this LSA corresponding Extended parameters */
1510
0
  exti = lookup_ext_by_instance(lsa);
1511
0
  if (exti == NULL) {
1512
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1513
0
        "EXT (%s): Invalid parameter LSA ID", __func__);
1514
    /* Flush it anyway. */
1515
0
    lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1516
0
  }
1517
1518
  /* Check if Interface was not disable in the interval */
1519
0
  if ((exti != NULL) && !CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE)) {
1520
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1521
0
        "EXT (%s): Interface was Disabled: Flush it!",
1522
0
        __func__);
1523
0
    lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
1524
0
  }
1525
1526
  /* If the lsa's age reached to MaxAge, start flushing procedure */
1527
0
  if (IS_LSA_MAXAGE(lsa)) {
1528
0
    if (exti)
1529
0
      UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
1530
0
    ospf_opaque_lsa_flush_schedule(lsa);
1531
0
    return NULL;
1532
0
  }
1533
1534
  /* Create new Opaque-LSA/Extended Link instance */
1535
0
  new = ospf_ext_link_lsa_new(area, exti);
1536
0
  if (new == NULL) {
1537
0
    flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1538
0
        "EXT (%s): Error creating new LSA", __func__);
1539
0
    return NULL;
1540
0
  }
1541
0
  new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1542
1543
  /* Install this LSA into LSDB. */
1544
  /* Given "lsa" will be freed in the next function */
1545
0
  if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1546
0
    flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1547
0
        "EXT (%s): Error installing new LSA", __func__);
1548
0
    ospf_lsa_unlock(&new);
1549
0
    return NULL;
1550
0
  }
1551
1552
  /* Flood updated LSA through the link Area according to the RFC7684 */
1553
0
  ospf_flood_through_area(area, NULL /*nbr */, new);
1554
1555
  /* Debug logging. */
1556
0
  osr_debug("EXT (%s): LSA[Type%u:%pI4]: Refresh Extended Link LSA",
1557
0
      __func__, new->data->type, &new->data->id);
1558
0
  if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
1559
0
    ospf_lsa_header_dump(new->data);
1560
1561
0
  return new;
1562
0
}
1563
1564
/* Schedule Extended Prefix Opaque LSA origination/refreshment/flushing */
1565
static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti,
1566
               enum lsa_opcode opcode)
1567
0
{
1568
0
  struct ospf_lsa lsa;
1569
0
  struct lsa_header lsah;
1570
0
  struct ospf *top;
1571
0
  uint32_t tmp;
1572
1573
0
  memset(&lsa, 0, sizeof(lsa));
1574
0
  memset(&lsah, 0, sizeof(lsah));
1575
1576
  /* Sanity Check */
1577
0
  if (exti == NULL)
1578
0
    return;
1579
1580
  /* Check if the corresponding link is ready to be flooded */
1581
0
  if (!(CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE)))
1582
0
    return;
1583
1584
0
  osr_debug("EXT (%s): Schedule %s%s%s LSA for interface %s", __func__,
1585
0
      opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
1586
0
      opcode == REFRESH_THIS_LSA ? "Refresh" : "",
1587
0
      opcode == FLUSH_THIS_LSA ? "Flush" : "",
1588
0
      exti->ifp ? exti->ifp->name : "-");
1589
1590
  /* Verify Area */
1591
0
  if (exti->area == NULL) {
1592
0
    osr_debug(
1593
0
      "EXT (%s): Area is not yet set. Try to use Backbone Area",
1594
0
      __func__);
1595
1596
0
    top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1597
0
    struct in_addr backbone = {.s_addr = INADDR_ANY};
1598
0
    exti->area = ospf_area_lookup_by_area_id(top, backbone);
1599
0
    if (exti->area == NULL) {
1600
0
      flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1601
0
          "EXT (%s): Unable to set Area", __func__);
1602
0
      return;
1603
0
    }
1604
0
  }
1605
  /* Set LSA header information */
1606
0
  lsa.area = exti->area;
1607
0
  lsa.data = &lsah;
1608
0
  lsah.type = OSPF_OPAQUE_AREA_LSA;
1609
0
  tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_EXTENDED_PREFIX_LSA, exti->instance);
1610
0
  lsah.id.s_addr = htonl(tmp);
1611
1612
0
  switch (opcode) {
1613
0
  case REORIGINATE_THIS_LSA:
1614
0
    ospf_opaque_lsa_reoriginate_schedule(
1615
0
      (void *)exti->area, OSPF_OPAQUE_AREA_LSA,
1616
0
      OPAQUE_TYPE_EXTENDED_PREFIX_LSA);
1617
0
    break;
1618
0
  case REFRESH_THIS_LSA:
1619
0
    ospf_opaque_lsa_refresh_schedule(&lsa);
1620
0
    break;
1621
0
  case FLUSH_THIS_LSA:
1622
0
    UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
1623
0
    ospf_opaque_lsa_flush_schedule(&lsa);
1624
0
    break;
1625
0
  }
1626
0
}
1627
1628
/* Schedule Extended Link Opaque LSA origination/refreshment/flushing */
1629
static void ospf_ext_link_lsa_schedule(struct ext_itf *exti,
1630
               enum lsa_opcode opcode)
1631
0
{
1632
0
  struct ospf_lsa lsa;
1633
0
  struct lsa_header lsah;
1634
0
  struct ospf *top;
1635
0
  uint32_t tmp;
1636
1637
0
  memset(&lsa, 0, sizeof(lsa));
1638
0
  memset(&lsah, 0, sizeof(lsah));
1639
1640
  /* Sanity Check */
1641
0
  if (exti == NULL)
1642
0
    return;
1643
1644
  /* Check if the corresponding link is ready to be flooded */
1645
0
  if (!(CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE)))
1646
0
    return;
1647
1648
0
  osr_debug("EXT (%s): Schedule %s%s%s LSA for interface %s", __func__,
1649
0
      opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
1650
0
      opcode == REFRESH_THIS_LSA ? "Refresh" : "",
1651
0
      opcode == FLUSH_THIS_LSA ? "Flush" : "",
1652
0
      exti->ifp ? exti->ifp->name : "-");
1653
1654
  /* Verify Area */
1655
0
  if (exti->area == NULL) {
1656
0
    osr_debug(
1657
0
      "EXT (%s): Area is not yet set. Try to use Backbone Area",
1658
0
      __func__);
1659
1660
0
    top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1661
0
    struct in_addr backbone = {.s_addr = INADDR_ANY};
1662
0
    exti->area = ospf_area_lookup_by_area_id(top, backbone);
1663
0
    if (exti->area == NULL) {
1664
0
      flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
1665
0
          "EXT (%s): Unable to set Area", __func__);
1666
0
      return;
1667
0
    }
1668
0
  }
1669
  /* Set LSA header information */
1670
0
  lsa.area = exti->area;
1671
0
  lsa.data = &lsah;
1672
0
  lsah.type = OSPF_OPAQUE_AREA_LSA;
1673
0
  tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_EXTENDED_LINK_LSA, exti->instance);
1674
0
  lsah.id.s_addr = htonl(tmp);
1675
1676
0
  switch (opcode) {
1677
0
  case REORIGINATE_THIS_LSA:
1678
0
    ospf_opaque_lsa_reoriginate_schedule(
1679
0
      (void *)exti->area, OSPF_OPAQUE_AREA_LSA,
1680
0
      OPAQUE_TYPE_EXTENDED_LINK_LSA);
1681
0
    break;
1682
0
  case REFRESH_THIS_LSA:
1683
0
    ospf_opaque_lsa_refresh_schedule(&lsa);
1684
0
    break;
1685
0
  case FLUSH_THIS_LSA:
1686
0
    ospf_opaque_lsa_flush_schedule(&lsa);
1687
0
    break;
1688
0
  }
1689
0
}
1690
1691
/* Schedule Extended Link or Prefix depending of the Type of LSA */
1692
static void ospf_ext_lsa_schedule(struct ext_itf *exti, enum lsa_opcode op)
1693
0
{
1694
1695
0
  if (exti->stype == PREF_SID)
1696
0
    ospf_ext_pref_lsa_schedule(exti, op);
1697
0
  else
1698
0
    ospf_ext_link_lsa_schedule(exti, op);
1699
0
}
1700
1701
/*
1702
 * ------------------------------------
1703
 * Following are vty show functions.
1704
 * ------------------------------------
1705
 */
1706
1707
#define check_tlv_size(size, msg)                                              \
1708
0
  do {                                                                   \
1709
0
    if (ntohs(tlvh->length) != size) {                             \
1710
0
      vty_out(vty, "  Wrong %s TLV size: %d(%d). Abort!\n",  \
1711
0
        msg, ntohs(tlvh->length), size);               \
1712
0
      return size + TLV_HDR_SIZE;                            \
1713
0
    }                                                              \
1714
0
  } while (0)
1715
1716
/* Cisco experimental SubTLV */
1717
static uint16_t show_vty_ext_link_rmt_itf_addr(struct vty *vty,
1718
                 struct tlv_header *tlvh)
1719
0
{
1720
0
  struct ext_subtlv_rmt_itf_addr *top =
1721
0
    (struct ext_subtlv_rmt_itf_addr *)tlvh;
1722
1723
0
  check_tlv_size(EXT_SUBTLV_RMT_ITF_ADDR_SIZE, "Remote Itf. Address");
1724
1725
0
  vty_out(vty,
1726
0
    "  Remote Interface Address Sub-TLV: Length %u\n  Address: %pI4\n",
1727
0
    ntohs(top->header.length), &top->value);
1728
1729
0
  return TLV_SIZE(tlvh);
1730
0
}
1731
1732
/* Adjacency SID SubTLV */
1733
static uint16_t show_vty_ext_link_adj_sid(struct vty *vty,
1734
            struct tlv_header *tlvh)
1735
0
{
1736
0
  struct ext_subtlv_adj_sid *top = (struct ext_subtlv_adj_sid *)tlvh;
1737
1738
0
  check_tlv_size(EXT_SUBTLV_ADJ_SID_SIZE, "Adjacency SID");
1739
1740
0
  vty_out(vty,
1741
0
    "  Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\t%s: %u\n",
1742
0
    ntohs(top->header.length), top->flags, top->mtid, top->weight,
1743
0
    CHECK_FLAG(top->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG) ? "Label"
1744
0
                     : "Index",
1745
0
    CHECK_FLAG(top->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG)
1746
0
      ? GET_LABEL(ntohl(top->value))
1747
0
      : ntohl(top->value));
1748
1749
0
  return TLV_SIZE(tlvh);
1750
0
}
1751
1752
/* LAN Adjacency SubTLV */
1753
static uint16_t show_vty_ext_link_lan_adj_sid(struct vty *vty,
1754
                struct tlv_header *tlvh)
1755
0
{
1756
0
  struct ext_subtlv_lan_adj_sid *top =
1757
0
    (struct ext_subtlv_lan_adj_sid *)tlvh;
1758
1759
0
  check_tlv_size(EXT_SUBTLV_LAN_ADJ_SID_SIZE, "Lan-Adjacency SID");
1760
1761
0
  vty_out(vty,
1762
0
    "  LAN-Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\tNeighbor ID: %pI4\n\t%s: %u\n",
1763
0
    ntohs(top->header.length), top->flags, top->mtid, top->weight,
1764
0
    &top->neighbor_id,
1765
0
    CHECK_FLAG(top->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG) ? "Label"
1766
0
                     : "Index",
1767
0
    CHECK_FLAG(top->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG)
1768
0
      ? GET_LABEL(ntohl(top->value))
1769
0
      : ntohl(top->value));
1770
1771
0
  return TLV_SIZE(tlvh);
1772
0
}
1773
1774
static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
1775
             size_t buf_size)
1776
0
{
1777
0
  if (TLV_SIZE(tlvh) > buf_size) {
1778
0
    vty_out(vty, "    TLV size %d exceeds buffer size. Abort!",
1779
0
      TLV_SIZE(tlvh));
1780
0
    return buf_size;
1781
0
  }
1782
1783
0
  vty_out(vty, "    Unknown TLV: [type(0x%x), length(0x%x)]\n",
1784
0
    ntohs(tlvh->type), ntohs(tlvh->length));
1785
1786
0
  return TLV_SIZE(tlvh);
1787
0
}
1788
1789
/* Extended Link Sub TLVs */
1790
static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext,
1791
           size_t buf_size)
1792
0
{
1793
0
  struct ext_tlv_link *top = (struct ext_tlv_link *)ext;
1794
0
  struct tlv_header *tlvh;
1795
0
  uint16_t length = ntohs(top->header.length);
1796
0
  uint16_t sum = 0;
1797
1798
  /* Verify that TLV length is valid against remaining buffer size */
1799
0
  if (length > buf_size) {
1800
0
    vty_out(vty,
1801
0
      "  Extended Link TLV size %d exceeds buffer size. Abort!\n",
1802
0
      length);
1803
0
    return buf_size;
1804
0
  }
1805
1806
0
  vty_out(vty,
1807
0
    "  Extended Link TLV: Length %u\n Link Type: 0x%x\n"
1808
0
    " Link ID: %pI4\n",
1809
0
    ntohs(top->header.length), top->link_type,
1810
0
    &top->link_id);
1811
0
  vty_out(vty, "  Link data: %pI4\n", &top->link_data);
1812
1813
  /* Skip Extended TLV and parse sub-TLVs */
1814
0
  length -= EXT_TLV_LINK_SIZE;
1815
0
  tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
1816
0
             + EXT_TLV_LINK_SIZE);
1817
0
  for (; sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) {
1818
0
    switch (ntohs(tlvh->type)) {
1819
0
    case EXT_SUBTLV_ADJ_SID:
1820
0
      sum += show_vty_ext_link_adj_sid(vty, tlvh);
1821
0
      break;
1822
0
    case EXT_SUBTLV_LAN_ADJ_SID:
1823
0
      sum += show_vty_ext_link_lan_adj_sid(vty, tlvh);
1824
0
      break;
1825
0
    case EXT_SUBTLV_RMT_ITF_ADDR:
1826
0
      sum += show_vty_ext_link_rmt_itf_addr(vty, tlvh);
1827
0
      break;
1828
0
    default:
1829
0
      sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
1830
0
      break;
1831
0
    }
1832
0
  }
1833
1834
0
  return sum + sizeof(struct ext_tlv_link);
1835
0
}
1836
1837
/* Extended Link TLVs */
1838
static void ospf_ext_link_show_info(struct vty *vty, struct json_object *json,
1839
            struct ospf_lsa *lsa)
1840
0
{
1841
0
  struct lsa_header *lsah = lsa->data;
1842
0
  struct tlv_header *tlvh;
1843
0
  uint16_t length = 0, sum = 0;
1844
1845
0
  if (json)
1846
0
    return;
1847
1848
  /* Initialize TLV browsing */
1849
0
  length = lsa->size - OSPF_LSA_HEADER_SIZE;
1850
1851
0
  for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
1852
0
       tlvh = TLV_HDR_NEXT(tlvh)) {
1853
0
    switch (ntohs(tlvh->type)) {
1854
0
    case EXT_TLV_LINK:
1855
0
      sum += show_vty_link_info(vty, tlvh, length - sum);
1856
0
      break;
1857
0
    default:
1858
0
      sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
1859
0
      break;
1860
0
    }
1861
0
  }
1862
0
}
1863
1864
/* Prefix SID SubTLV */
1865
static uint16_t show_vty_ext_pref_pref_sid(struct vty *vty,
1866
             struct tlv_header *tlvh)
1867
0
{
1868
0
  struct ext_subtlv_prefix_sid *top =
1869
0
    (struct ext_subtlv_prefix_sid *)tlvh;
1870
1871
0
  check_tlv_size(EXT_SUBTLV_PREFIX_SID_SIZE, "Prefix SID");
1872
1873
0
  vty_out(vty,
1874
0
    "  Prefix SID Sub-TLV: Length %u\n\tAlgorithm: %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\t%s: %u\n",
1875
0
    ntohs(top->header.length), top->algorithm, top->flags,
1876
0
    top->mtid,
1877
0
    CHECK_FLAG(top->flags, EXT_SUBTLV_PREFIX_SID_VFLG) ? "Label"
1878
0
                   : "Index",
1879
0
    CHECK_FLAG(top->flags, EXT_SUBTLV_PREFIX_SID_VFLG)
1880
0
      ? GET_LABEL(ntohl(top->value))
1881
0
      : ntohl(top->value));
1882
1883
0
  return TLV_SIZE(tlvh);
1884
0
}
1885
1886
/* Extended Prefix SubTLVs */
1887
static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext,
1888
           size_t buf_size)
1889
0
{
1890
0
  struct ext_tlv_prefix *top = (struct ext_tlv_prefix *)ext;
1891
0
  struct tlv_header *tlvh;
1892
0
  uint16_t length = ntohs(top->header.length);
1893
0
  uint16_t sum = 0;
1894
1895
  /* Verify that TLV length is valid against remaining buffer size */
1896
0
  if (length > buf_size) {
1897
0
    vty_out(vty,
1898
0
      "  Extended Link TLV size %d exceeds buffer size. Abort!\n",
1899
0
      length);
1900
0
    return buf_size;
1901
0
  }
1902
1903
0
  vty_out(vty,
1904
0
    "  Extended Prefix TLV: Length %u\n\tRoute Type: %u\n"
1905
0
    "\tAddress Family: 0x%x\n\tFlags: 0x%x\n\tAddress: %pI4/%u\n",
1906
0
    ntohs(top->header.length), top->route_type, top->af, top->flags,
1907
0
    &top->address, top->pref_length);
1908
1909
  /* Skip Extended Prefix TLV and parse sub-TLVs */
1910
0
  length -= EXT_TLV_PREFIX_SIZE;
1911
0
  tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
1912
0
             + EXT_TLV_PREFIX_SIZE);
1913
0
  for (; sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) {
1914
0
    switch (ntohs(tlvh->type)) {
1915
0
    case EXT_SUBTLV_PREFIX_SID:
1916
0
      sum += show_vty_ext_pref_pref_sid(vty, tlvh);
1917
0
      break;
1918
0
    default:
1919
0
      sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
1920
0
      break;
1921
0
    }
1922
0
  }
1923
1924
0
  return sum + sizeof(struct ext_tlv_prefix);
1925
0
}
1926
1927
/* Extended Prefix TLVs */
1928
static void ospf_ext_pref_show_info(struct vty *vty, struct json_object *json,
1929
            struct ospf_lsa *lsa)
1930
0
{
1931
0
  struct lsa_header *lsah = lsa->data;
1932
0
  struct tlv_header *tlvh;
1933
0
  uint16_t length = 0, sum = 0;
1934
1935
0
  if (json)
1936
0
    return;
1937
1938
  /* Initialize TLV browsing */
1939
0
  length = lsa->size - OSPF_LSA_HEADER_SIZE;
1940
1941
0
  for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
1942
0
       tlvh = TLV_HDR_NEXT(tlvh)) {
1943
0
    switch (ntohs(tlvh->type)) {
1944
0
    case EXT_TLV_PREFIX:
1945
0
      sum += show_vty_pref_info(vty, tlvh, length - sum);
1946
0
      break;
1947
0
    default:
1948
0
      sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
1949
0
      break;
1950
0
    }
1951
0
  }
1952
0
}