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