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