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