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