1 /*
2  * This is an implementation of RFC3630
3  * Copyright (C) 2001 KDD R&D Laboratories, Inc.
4  * http://www.kddlabs.co.jp/
5  *
6  * Copyright (C) 2012 Orange Labs
7  * http://www.orange.com
8  *
9  * This file is part of GNU Zebra.
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 Zebra 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 /* Add support of RFC7471 */
27 /* Add support of RFC5392, RFC6827 */
28 
29 #include <zebra.h>
30 #include <math.h>
31 
32 #include "linklist.h"
33 #include "prefix.h"
34 #include "vrf.h"
35 #include "if.h"
36 #include "table.h"
37 #include "memory.h"
38 #include "command.h"
39 #include "vty.h"
40 #include "stream.h"
41 #include "log.h"
42 #include "thread.h"
43 #include "hash.h"
44 #include "sockunion.h" /* for inet_aton() */
45 #include "network.h"
46 
47 #include "ospfd/ospfd.h"
48 #include "ospfd/ospf_interface.h"
49 #include "ospfd/ospf_ism.h"
50 #include "ospfd/ospf_asbr.h"
51 #include "ospfd/ospf_lsa.h"
52 #include "ospfd/ospf_lsdb.h"
53 #include "ospfd/ospf_neighbor.h"
54 #include "ospfd/ospf_nsm.h"
55 #include "ospfd/ospf_flood.h"
56 #include "ospfd/ospf_packet.h"
57 #include "ospfd/ospf_spf.h"
58 #include "ospfd/ospf_dump.h"
59 #include "ospfd/ospf_route.h"
60 #include "ospfd/ospf_ase.h"
61 #include "ospfd/ospf_zebra.h"
62 #include "ospfd/ospf_te.h"
63 #include "ospfd/ospf_vty.h"
64 #include "ospfd/ospf_errors.h"
65 
66 /*
67  * Global variable to manage Opaque-LSA/MPLS-TE on this node.
68  * Note that all parameter values are stored in network byte order.
69  */
70 struct ospf_mpls_te OspfMplsTE;
71 
72 static const char *const mode2text[] = {"Off", "AS", "Area"};
73 
74 /*------------------------------------------------------------------------*
75  * Followings are initialize/terminate functions for MPLS-TE handling.
76  *------------------------------------------------------------------------*/
77 
78 static int ospf_mpls_te_new_if(struct interface *ifp);
79 static int ospf_mpls_te_del_if(struct interface *ifp);
80 static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_status);
81 static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_status);
82 static void ospf_mpls_te_config_write_router(struct vty *vty);
83 static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa);
84 static int ospf_mpls_te_lsa_originate_area(void *arg);
85 static int ospf_mpls_te_lsa_originate_as(void *arg);
86 static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa);
87 
88 static void del_mpls_te_link(void *val);
89 static void ospf_mpls_te_register_vty(void);
90 
ospf_mpls_te_init(void)91 int ospf_mpls_te_init(void)
92 {
93 	int rc;
94 
95 	rc = ospf_register_opaque_functab(
96 		OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
97 		ospf_mpls_te_new_if, ospf_mpls_te_del_if,
98 		ospf_mpls_te_ism_change, ospf_mpls_te_nsm_change,
99 		ospf_mpls_te_config_write_router,
100 		NULL, /*ospf_mpls_te_config_write_if */
101 		NULL, /* ospf_mpls_te_config_write_debug */
102 		ospf_mpls_te_show_info, ospf_mpls_te_lsa_originate_area,
103 		ospf_mpls_te_lsa_refresh, NULL, /* ospf_mpls_te_new_lsa_hook */
104 		NULL /* ospf_mpls_te_del_lsa_hook */);
105 	if (rc != 0) {
106 		flog_warn(
107 			EC_OSPF_OPAQUE_REGISTRATION,
108 			"ospf_mpls_te_init: Failed to register Traffic Engineering functions");
109 		return rc;
110 	}
111 
112 	memset(&OspfMplsTE, 0, sizeof(struct ospf_mpls_te));
113 	OspfMplsTE.enabled = false;
114 	OspfMplsTE.inter_as = Off;
115 	OspfMplsTE.iflist = list_new();
116 	OspfMplsTE.iflist->del = del_mpls_te_link;
117 
118 	ospf_mpls_te_register_vty();
119 
120 	return rc;
121 }
122 
123 /* Additional register for RFC5392 support */
ospf_mpls_te_register(enum inter_as_mode mode)124 static int ospf_mpls_te_register(enum inter_as_mode mode)
125 {
126 	int rc = 0;
127 	uint8_t scope;
128 
129 	if (OspfMplsTE.inter_as != Off)
130 		return rc;
131 
132 	if (mode == AS)
133 		scope = OSPF_OPAQUE_AS_LSA;
134 	else
135 		scope = OSPF_OPAQUE_AREA_LSA;
136 
137 	rc = ospf_register_opaque_functab(scope, OPAQUE_TYPE_INTER_AS_LSA, NULL,
138 					  NULL, NULL, NULL, NULL, NULL, NULL,
139 					  ospf_mpls_te_show_info,
140 					  ospf_mpls_te_lsa_originate_as,
141 					  ospf_mpls_te_lsa_refresh, NULL, NULL);
142 
143 	if (rc != 0) {
144 		flog_warn(
145 			EC_OSPF_OPAQUE_REGISTRATION,
146 			"ospf_router_info_init: Failed to register Inter-AS functions");
147 		return rc;
148 	}
149 
150 	return rc;
151 }
152 
ospf_mpls_te_unregister(void)153 static int ospf_mpls_te_unregister(void)
154 {
155 	uint8_t scope;
156 
157 	if (OspfMplsTE.inter_as == Off)
158 		return 0;
159 
160 	if (OspfMplsTE.inter_as == AS)
161 		scope = OSPF_OPAQUE_AS_LSA;
162 	else
163 		scope = OSPF_OPAQUE_AREA_LSA;
164 
165 	ospf_delete_opaque_functab(scope, OPAQUE_TYPE_INTER_AS_LSA);
166 
167 	return 0;
168 }
169 
ospf_mpls_te_term(void)170 void ospf_mpls_te_term(void)
171 {
172 	list_delete(&OspfMplsTE.iflist);
173 
174 	ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
175 				   OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
176 
177 	OspfMplsTE.enabled = false;
178 
179 	ospf_mpls_te_unregister();
180 	OspfMplsTE.inter_as = Off;
181 
182 	return;
183 }
184 
ospf_mpls_te_finish(void)185 void ospf_mpls_te_finish(void)
186 {
187 	// list_delete_all_node(OspfMplsTE.iflist);
188 
189 	OspfMplsTE.enabled = false;
190 	ospf_mpls_te_unregister();
191 	OspfMplsTE.inter_as = Off;
192 }
193 
194 /*------------------------------------------------------------------------*
195  * Followings are control functions for MPLS-TE parameters management.
196  *------------------------------------------------------------------------*/
197 
del_mpls_te_link(void * val)198 static void del_mpls_te_link(void *val)
199 {
200 	XFREE(MTYPE_OSPF_MPLS_TE, val);
201 	return;
202 }
203 
get_mpls_te_instance_value(void)204 static uint32_t get_mpls_te_instance_value(void)
205 {
206 	static uint32_t seqno = 0;
207 
208 	if (seqno < MAX_LEGAL_TE_INSTANCE_NUM)
209 		seqno += 1;
210 	else
211 		seqno = 1; /* Avoid zero. */
212 
213 	return seqno;
214 }
215 
lookup_linkparams_by_ifp(struct interface * ifp)216 static struct mpls_te_link *lookup_linkparams_by_ifp(struct interface *ifp)
217 {
218 	struct listnode *node, *nnode;
219 	struct mpls_te_link *lp;
220 
221 	for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
222 		if (lp->ifp == ifp)
223 			return lp;
224 
225 	return NULL;
226 }
227 
lookup_linkparams_by_instance(struct ospf_lsa * lsa)228 static struct mpls_te_link *lookup_linkparams_by_instance(struct ospf_lsa *lsa)
229 {
230 	struct listnode *node;
231 	struct mpls_te_link *lp;
232 	unsigned int key = GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr));
233 
234 	for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp))
235 		if (lp->instance == key)
236 			return lp;
237 
238 	zlog_info("lookup_linkparams_by_instance: Entry not found: key(%x)",
239 		  key);
240 	return NULL;
241 }
242 
ospf_mpls_te_foreach_area(void (* func)(struct mpls_te_link * lp,enum lsa_opcode sched_opcode),enum lsa_opcode sched_opcode)243 static void ospf_mpls_te_foreach_area(
244 	void (*func)(struct mpls_te_link *lp, enum lsa_opcode sched_opcode),
245 	enum lsa_opcode sched_opcode)
246 {
247 	struct listnode *node, *nnode;
248 	struct listnode *node2;
249 	struct mpls_te_link *lp;
250 	struct ospf_area *area;
251 
252 	for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
253 		/* Skip Inter-AS TEv2 Links */
254 		if (IS_INTER_AS(lp->type))
255 			continue;
256 		if ((area = lp->area) == NULL)
257 			continue;
258 		if (CHECK_FLAG(lp->flags, LPFLG_LOOKUP_DONE))
259 			continue;
260 
261 		if (func != NULL)
262 			(*func)(lp, sched_opcode);
263 
264 		for (node2 = listnextnode(node); node2;
265 		     node2 = listnextnode(node2))
266 			if ((lp = listgetdata(node2)) != NULL)
267 				if (lp->area != NULL)
268 					if (IPV4_ADDR_SAME(&lp->area->area_id,
269 							   &area->area_id))
270 						SET_FLAG(lp->flags,
271 							 LPFLG_LOOKUP_DONE);
272 	}
273 
274 	for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp))
275 		if (lp->area != NULL)
276 			UNSET_FLAG(lp->flags, LPFLG_LOOKUP_DONE);
277 
278 	return;
279 }
280 
set_mpls_te_router_addr(struct in_addr ipv4)281 static void set_mpls_te_router_addr(struct in_addr ipv4)
282 {
283 	OspfMplsTE.router_addr.header.type = htons(TE_TLV_ROUTER_ADDR);
284 	OspfMplsTE.router_addr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
285 	OspfMplsTE.router_addr.value = ipv4;
286 	return;
287 }
288 
set_linkparams_link_header(struct mpls_te_link * lp)289 static void set_linkparams_link_header(struct mpls_te_link *lp)
290 {
291 	uint16_t length = 0;
292 
293 	/* TE_LINK_SUBTLV_LINK_TYPE */
294 	if (ntohs(lp->link_type.header.type) != 0)
295 		length += TLV_SIZE(&lp->link_type.header);
296 
297 	/* TE_LINK_SUBTLV_LINK_ID */
298 	if (ntohs(lp->link_id.header.type) != 0)
299 		length += TLV_SIZE(&lp->link_id.header);
300 
301 	/* TE_LINK_SUBTLV_LCLIF_IPADDR */
302 	if (lp->lclif_ipaddr.header.type != 0)
303 		length += TLV_SIZE(&lp->lclif_ipaddr.header);
304 
305 	/* TE_LINK_SUBTLV_RMTIF_IPADDR */
306 	if (lp->rmtif_ipaddr.header.type != 0)
307 		length += TLV_SIZE(&lp->rmtif_ipaddr.header);
308 
309 	/* TE_LINK_SUBTLV_TE_METRIC */
310 	if (ntohs(lp->te_metric.header.type) != 0)
311 		length += TLV_SIZE(&lp->te_metric.header);
312 
313 	/* TE_LINK_SUBTLV_MAX_BW */
314 	if (ntohs(lp->max_bw.header.type) != 0)
315 		length += TLV_SIZE(&lp->max_bw.header);
316 
317 	/* TE_LINK_SUBTLV_MAX_RSV_BW */
318 	if (ntohs(lp->max_rsv_bw.header.type) != 0)
319 		length += TLV_SIZE(&lp->max_rsv_bw.header);
320 
321 	/* TE_LINK_SUBTLV_UNRSV_BW */
322 	if (ntohs(lp->unrsv_bw.header.type) != 0)
323 		length += TLV_SIZE(&lp->unrsv_bw.header);
324 
325 	/* TE_LINK_SUBTLV_RSC_CLSCLR */
326 	if (ntohs(lp->rsc_clsclr.header.type) != 0)
327 		length += TLV_SIZE(&lp->rsc_clsclr.header);
328 
329 	/* TE_LINK_SUBTLV_LLRI */
330 	if (ntohs(lp->llri.header.type) != 0)
331 		length += TLV_SIZE(&lp->llri.header);
332 
333 	/* TE_LINK_SUBTLV_RIP */
334 	if (ntohs(lp->rip.header.type) != 0)
335 		length += TLV_SIZE(&lp->rip.header);
336 
337 	/* TE_LINK_SUBTLV_RAS */
338 	if (ntohs(lp->ras.header.type) != 0)
339 		length += TLV_SIZE(&lp->ras.header);
340 
341 	/* TE_LINK_SUBTLV_LRRID */
342 	if (ntohs(lp->lrrid.header.type) != 0)
343 		length += TLV_SIZE(&lp->lrrid.header);
344 
345 	/* TE_LINK_SUBTLV_AV_DELAY */
346 	if (ntohs(lp->av_delay.header.type) != 0)
347 		length += TLV_SIZE(&lp->av_delay.header);
348 
349 	/* TE_LINK_SUBTLV_MM_DELAY */
350 	if (ntohs(lp->mm_delay.header.type) != 0)
351 		length += TLV_SIZE(&lp->mm_delay.header);
352 
353 	/* TE_LINK_SUBTLV_DELAY_VAR */
354 	if (ntohs(lp->delay_var.header.type) != 0)
355 		length += TLV_SIZE(&lp->delay_var.header);
356 
357 	/* TE_LINK_SUBTLV_PKT_LOSS */
358 	if (ntohs(lp->pkt_loss.header.type) != 0)
359 		length += TLV_SIZE(&lp->pkt_loss.header);
360 
361 	/* TE_LINK_SUBTLV_RES_BW */
362 	if (ntohs(lp->res_bw.header.type) != 0)
363 		length += TLV_SIZE(&lp->res_bw.header);
364 
365 	/* TE_LINK_SUBTLV_AVA_BW */
366 	if (ntohs(lp->ava_bw.header.type) != 0)
367 		length += TLV_SIZE(&lp->ava_bw.header);
368 
369 	/* TE_LINK_SUBTLV_USE_BW */
370 	if (ntohs(lp->use_bw.header.type) != 0)
371 		length += TLV_SIZE(&lp->use_bw.header);
372 
373 	lp->link_header.header.type = htons(TE_TLV_LINK);
374 	lp->link_header.header.length = htons(length);
375 
376 	return;
377 }
378 
set_linkparams_link_type(struct ospf_interface * oi,struct mpls_te_link * lp)379 static void set_linkparams_link_type(struct ospf_interface *oi,
380 				     struct mpls_te_link *lp)
381 {
382 	lp->link_type.header.type = htons(TE_LINK_SUBTLV_LINK_TYPE);
383 	lp->link_type.header.length = htons(TE_LINK_SUBTLV_TYPE_SIZE);
384 
385 	switch (oi->type) {
386 	case OSPF_IFTYPE_POINTOPOINT:
387 		lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP;
388 		break;
389 	case OSPF_IFTYPE_BROADCAST:
390 	case OSPF_IFTYPE_NBMA:
391 		lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA;
392 		break;
393 	default:
394 		/* Not supported yet. */ /* XXX */
395 		lp->link_type.header.type = htons(0);
396 		break;
397 	}
398 	return;
399 }
400 
set_linkparams_link_id(struct mpls_te_link * lp,struct in_addr link_id)401 static void set_linkparams_link_id(struct mpls_te_link *lp,
402 				   struct in_addr link_id)
403 {
404 
405 	lp->link_id.header.type = htons(TE_LINK_SUBTLV_LINK_ID);
406 	lp->link_id.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
407 	lp->link_id.value = link_id;
408 	return;
409 }
410 
set_linkparams_lclif_ipaddr(struct mpls_te_link * lp,struct in_addr lclif)411 static void set_linkparams_lclif_ipaddr(struct mpls_te_link *lp,
412 					struct in_addr lclif)
413 {
414 
415 	lp->lclif_ipaddr.header.type = htons(TE_LINK_SUBTLV_LCLIF_IPADDR);
416 	lp->lclif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
417 	lp->lclif_ipaddr.value[0] = lclif;
418 	return;
419 }
420 
set_linkparams_rmtif_ipaddr(struct mpls_te_link * lp,struct in_addr rmtif)421 static void set_linkparams_rmtif_ipaddr(struct mpls_te_link *lp,
422 					struct in_addr rmtif)
423 {
424 
425 	lp->rmtif_ipaddr.header.type = htons(TE_LINK_SUBTLV_RMTIF_IPADDR);
426 	lp->rmtif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
427 	lp->rmtif_ipaddr.value[0] = rmtif;
428 	return;
429 }
430 
set_linkparams_te_metric(struct mpls_te_link * lp,uint32_t te_metric)431 static void set_linkparams_te_metric(struct mpls_te_link *lp,
432 				     uint32_t te_metric)
433 {
434 	lp->te_metric.header.type = htons(TE_LINK_SUBTLV_TE_METRIC);
435 	lp->te_metric.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
436 	lp->te_metric.value = htonl(te_metric);
437 	return;
438 }
439 
set_linkparams_max_bw(struct mpls_te_link * lp,float fp)440 static void set_linkparams_max_bw(struct mpls_te_link *lp, float fp)
441 {
442 	lp->max_bw.header.type = htons(TE_LINK_SUBTLV_MAX_BW);
443 	lp->max_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
444 	lp->max_bw.value = htonf(fp);
445 	return;
446 }
447 
set_linkparams_max_rsv_bw(struct mpls_te_link * lp,float fp)448 static void set_linkparams_max_rsv_bw(struct mpls_te_link *lp, float fp)
449 {
450 	lp->max_rsv_bw.header.type = htons(TE_LINK_SUBTLV_MAX_RSV_BW);
451 	lp->max_rsv_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
452 	lp->max_rsv_bw.value = htonf(fp);
453 	return;
454 }
455 
set_linkparams_unrsv_bw(struct mpls_te_link * lp,int priority,float fp)456 static void set_linkparams_unrsv_bw(struct mpls_te_link *lp, int priority,
457 				    float fp)
458 {
459 	/* Note that TLV-length field is the size of array. */
460 	lp->unrsv_bw.header.type = htons(TE_LINK_SUBTLV_UNRSV_BW);
461 	lp->unrsv_bw.header.length = htons(TE_LINK_SUBTLV_UNRSV_SIZE);
462 	lp->unrsv_bw.value[priority] = htonf(fp);
463 	return;
464 }
465 
set_linkparams_rsc_clsclr(struct mpls_te_link * lp,uint32_t classcolor)466 static void set_linkparams_rsc_clsclr(struct mpls_te_link *lp,
467 				      uint32_t classcolor)
468 {
469 	lp->rsc_clsclr.header.type = htons(TE_LINK_SUBTLV_RSC_CLSCLR);
470 	lp->rsc_clsclr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
471 	lp->rsc_clsclr.value = htonl(classcolor);
472 	return;
473 }
474 
set_linkparams_inter_as(struct mpls_te_link * lp,struct in_addr addr,uint32_t as)475 static void set_linkparams_inter_as(struct mpls_te_link *lp,
476 				    struct in_addr addr, uint32_t as)
477 {
478 
479 	/* Set the Remote ASBR IP address and then the associated AS number */
480 	lp->rip.header.type = htons(TE_LINK_SUBTLV_RIP);
481 	lp->rip.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
482 	lp->rip.value = addr;
483 
484 	lp->ras.header.type = htons(TE_LINK_SUBTLV_RAS);
485 	lp->ras.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
486 	lp->ras.value = htonl(as);
487 }
488 
unset_linkparams_inter_as(struct mpls_te_link * lp)489 static void unset_linkparams_inter_as(struct mpls_te_link *lp)
490 {
491 
492 	/* Reset the Remote ASBR IP address and then the associated AS number */
493 	lp->rip.header.type = htons(0);
494 	lp->rip.header.length = htons(0);
495 	lp->rip.value.s_addr = htonl(0);
496 
497 	lp->ras.header.type = htons(0);
498 	lp->ras.header.length = htons(0);
499 	lp->ras.value = htonl(0);
500 }
501 
set_linkparams_llri(struct mpls_te_link * lp,uint32_t local,uint32_t remote)502 void set_linkparams_llri(struct mpls_te_link *lp, uint32_t local,
503 			 uint32_t remote)
504 {
505 
506 	lp->llri.header.type = htons(TE_LINK_SUBTLV_LLRI);
507 	lp->llri.header.length = htons(TE_LINK_SUBTLV_LLRI_SIZE);
508 	lp->llri.local = htonl(local);
509 	lp->llri.remote = htonl(remote);
510 }
511 
set_linkparams_lrrid(struct mpls_te_link * lp,struct in_addr local,struct in_addr remote)512 void set_linkparams_lrrid(struct mpls_te_link *lp, struct in_addr local,
513 			  struct in_addr remote)
514 {
515 
516 	lp->lrrid.header.type = htons(TE_LINK_SUBTLV_LRRID);
517 	lp->lrrid.header.length = htons(TE_LINK_SUBTLV_LRRID_SIZE);
518 	lp->lrrid.local.s_addr = local.s_addr;
519 	lp->lrrid.remote.s_addr = remote.s_addr;
520 }
521 
set_linkparams_av_delay(struct mpls_te_link * lp,uint32_t delay,uint8_t anormal)522 static void set_linkparams_av_delay(struct mpls_te_link *lp, uint32_t delay,
523 				    uint8_t anormal)
524 {
525 	uint32_t tmp;
526 	/* Note that TLV-length field is the size of array. */
527 	lp->av_delay.header.type = htons(TE_LINK_SUBTLV_AV_DELAY);
528 	lp->av_delay.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
529 	tmp = delay & TE_EXT_MASK;
530 	if (anormal)
531 		tmp |= TE_EXT_ANORMAL;
532 	lp->av_delay.value = htonl(tmp);
533 	return;
534 }
535 
set_linkparams_mm_delay(struct mpls_te_link * lp,uint32_t low,uint32_t high,uint8_t anormal)536 static void set_linkparams_mm_delay(struct mpls_te_link *lp, uint32_t low,
537 				    uint32_t high, uint8_t anormal)
538 {
539 	uint32_t tmp;
540 	/* Note that TLV-length field is the size of array. */
541 	lp->mm_delay.header.type = htons(TE_LINK_SUBTLV_MM_DELAY);
542 	lp->mm_delay.header.length = htons(TE_LINK_SUBTLV_MM_DELAY_SIZE);
543 	tmp = low & TE_EXT_MASK;
544 	if (anormal)
545 		tmp |= TE_EXT_ANORMAL;
546 	lp->mm_delay.low = htonl(tmp);
547 	lp->mm_delay.high = htonl(high);
548 	return;
549 }
550 
set_linkparams_delay_var(struct mpls_te_link * lp,uint32_t jitter)551 static void set_linkparams_delay_var(struct mpls_te_link *lp, uint32_t jitter)
552 {
553 	/* Note that TLV-length field is the size of array. */
554 	lp->delay_var.header.type = htons(TE_LINK_SUBTLV_DELAY_VAR);
555 	lp->delay_var.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
556 	lp->delay_var.value = htonl(jitter & TE_EXT_MASK);
557 	return;
558 }
559 
set_linkparams_pkt_loss(struct mpls_te_link * lp,uint32_t loss,uint8_t anormal)560 static void set_linkparams_pkt_loss(struct mpls_te_link *lp, uint32_t loss,
561 				    uint8_t anormal)
562 {
563 	uint32_t tmp;
564 	/* Note that TLV-length field is the size of array. */
565 	lp->pkt_loss.header.type = htons(TE_LINK_SUBTLV_PKT_LOSS);
566 	lp->pkt_loss.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
567 	tmp = loss & TE_EXT_MASK;
568 	if (anormal)
569 		tmp |= TE_EXT_ANORMAL;
570 	lp->pkt_loss.value = htonl(tmp);
571 	return;
572 }
573 
set_linkparams_res_bw(struct mpls_te_link * lp,float fp)574 static void set_linkparams_res_bw(struct mpls_te_link *lp, float fp)
575 {
576 	/* Note that TLV-length field is the size of array. */
577 	lp->res_bw.header.type = htons(TE_LINK_SUBTLV_RES_BW);
578 	lp->res_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
579 	lp->res_bw.value = htonf(fp);
580 	return;
581 }
582 
set_linkparams_ava_bw(struct mpls_te_link * lp,float fp)583 static void set_linkparams_ava_bw(struct mpls_te_link *lp, float fp)
584 {
585 	/* Note that TLV-length field is the size of array. */
586 	lp->ava_bw.header.type = htons(TE_LINK_SUBTLV_AVA_BW);
587 	lp->ava_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
588 	lp->ava_bw.value = htonf(fp);
589 	return;
590 }
591 
set_linkparams_use_bw(struct mpls_te_link * lp,float fp)592 static void set_linkparams_use_bw(struct mpls_te_link *lp, float fp)
593 {
594 	/* Note that TLV-length field is the size of array. */
595 	lp->use_bw.header.type = htons(TE_LINK_SUBTLV_USE_BW);
596 	lp->use_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
597 	lp->use_bw.value = htonf(fp);
598 	return;
599 }
600 
601 /* Update TE parameters from Interface */
update_linkparams(struct mpls_te_link * lp)602 static void update_linkparams(struct mpls_te_link *lp)
603 {
604 	int i;
605 	struct interface *ifp;
606 
607 	/* Get the Interface structure */
608 	if ((ifp = lp->ifp) == NULL) {
609 		if (IS_DEBUG_OSPF_TE)
610 			zlog_debug(
611 				"OSPF MPLS-TE: Abort update TE parameters: no interface associated to Link Parameters");
612 		return;
613 	}
614 	if (!HAS_LINK_PARAMS(ifp)) {
615 		if (IS_DEBUG_OSPF_TE)
616 			zlog_debug(
617 				"OSPF MPLS-TE: Abort update TE parameters: no Link Parameters for interface");
618 		return;
619 	}
620 
621 	/* RFC3630 metrics */
622 	if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
623 		set_linkparams_rsc_clsclr(lp, ifp->link_params->admin_grp);
624 	else
625 		TLV_TYPE(lp->rsc_clsclr) = 0;
626 
627 	if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
628 		set_linkparams_max_bw(lp, ifp->link_params->max_bw);
629 	else
630 		TLV_TYPE(lp->max_bw) = 0;
631 
632 	if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW))
633 		set_linkparams_max_rsv_bw(lp, ifp->link_params->max_rsv_bw);
634 	else
635 		TLV_TYPE(lp->max_rsv_bw) = 0;
636 
637 	if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW))
638 		for (i = 0; i < MAX_CLASS_TYPE; i++)
639 			set_linkparams_unrsv_bw(lp, i,
640 						ifp->link_params->unrsv_bw[i]);
641 	else
642 		TLV_TYPE(lp->unrsv_bw) = 0;
643 
644 	if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC))
645 		set_linkparams_te_metric(lp, ifp->link_params->te_metric);
646 	else
647 		TLV_TYPE(lp->te_metric) = 0;
648 
649 	/* TE metric Extensions */
650 	if (IS_PARAM_SET(ifp->link_params, LP_DELAY))
651 		set_linkparams_av_delay(lp, ifp->link_params->av_delay, 0);
652 	else
653 		TLV_TYPE(lp->av_delay) = 0;
654 
655 	if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY))
656 		set_linkparams_mm_delay(lp, ifp->link_params->min_delay,
657 					ifp->link_params->max_delay, 0);
658 	else
659 		TLV_TYPE(lp->mm_delay) = 0;
660 
661 	if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
662 		set_linkparams_delay_var(lp, ifp->link_params->delay_var);
663 	else
664 		TLV_TYPE(lp->delay_var) = 0;
665 
666 	if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
667 		set_linkparams_pkt_loss(lp, ifp->link_params->pkt_loss, 0);
668 	else
669 		TLV_TYPE(lp->pkt_loss) = 0;
670 
671 	if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
672 		set_linkparams_res_bw(lp, ifp->link_params->res_bw);
673 	else
674 		TLV_TYPE(lp->res_bw) = 0;
675 
676 	if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
677 		set_linkparams_ava_bw(lp, ifp->link_params->ava_bw);
678 	else
679 		TLV_TYPE(lp->ava_bw) = 0;
680 
681 	if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
682 		set_linkparams_use_bw(lp, ifp->link_params->use_bw);
683 	else
684 		TLV_TYPE(lp->use_bw) = 0;
685 
686 	/* RFC5392 */
687 	if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) {
688 		/* Flush LSA if it engaged and was previously a STD_TE one */
689 		if (IS_STD_TE(lp->type)
690 		    && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
691 			if (IS_DEBUG_OSPF_TE)
692 				zlog_debug(
693 					"OSPF MPLS-TE Update IF: Switch from Standard LSA to INTER-AS for %s[%d/%d]",
694 					ifp->name, lp->flags, lp->type);
695 
696 			ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
697 			/* Then, switch it to INTER-AS */
698 			if (OspfMplsTE.inter_as == AS)
699 				lp->flags = INTER_AS | FLOOD_AS;
700 			else {
701 				lp->flags = INTER_AS | FLOOD_AREA;
702 				lp->area = ospf_area_lookup_by_area_id(
703 					ospf_lookup_by_vrf_id(VRF_DEFAULT),
704 					OspfMplsTE.interas_areaid);
705 			}
706 		}
707 		set_linkparams_inter_as(lp, ifp->link_params->rmt_ip,
708 					ifp->link_params->rmt_as);
709 	} else {
710 		if (IS_DEBUG_OSPF_TE)
711 			zlog_debug(
712 				"OSPF MPLS-TE Update IF: Switch from INTER-AS LSA to Standard for %s[%d/%d]",
713 				ifp->name, lp->flags, lp->type);
714 
715 		/* reset inter-as TE params */
716 		/* Flush LSA if it engaged and was previously an INTER_AS one */
717 		if (IS_INTER_AS(lp->type)
718 		    && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
719 			ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
720 			/* Then, switch it to Standard TE */
721 			lp->flags = STD_TE | FLOOD_AREA;
722 		}
723 		unset_linkparams_inter_as(lp);
724 	}
725 }
726 
initialize_linkparams(struct mpls_te_link * lp)727 static void initialize_linkparams(struct mpls_te_link *lp)
728 {
729 	struct interface *ifp = lp->ifp;
730 	struct ospf_interface *oi = NULL;
731 	struct route_node *rn;
732 
733 	if (IS_DEBUG_OSPF_TE)
734 		zlog_debug(
735 			"MPLS-TE(initialize_linkparams) Initialize Link Parameters for interface %s",
736 			ifp->name);
737 
738 	/* Search OSPF Interface parameters for this interface */
739 	for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
740 
741 		if ((oi = rn->info) == NULL)
742 			continue;
743 
744 		if (oi->ifp == ifp)
745 			break;
746 	}
747 
748 	if ((oi == NULL) || (oi->ifp != ifp)) {
749 		if (IS_DEBUG_OSPF_TE)
750 			zlog_debug(
751 				"MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s",
752 				ifp->name);
753 		return;
754 	}
755 
756 	/*
757 	 * Try to set initial values those can be derived from
758 	 * zebra-interface information.
759 	 */
760 	set_linkparams_link_type(oi, lp);
761 
762 	/* Set local IP addr */
763 	set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
764 
765 	/* Set Remote IP addr if Point to Point Interface */
766 	if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
767 		struct prefix *pref = CONNECTED_PREFIX(oi->connected);
768 		if (pref != NULL)
769 			set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
770 	}
771 
772 	/* Keep Area information in combination with link parameters. */
773 	lp->area = oi->area;
774 
775 	return;
776 }
777 
is_mandated_params_set(struct mpls_te_link * lp)778 static int is_mandated_params_set(struct mpls_te_link *lp)
779 {
780 	int rc = 0;
781 
782 	if (ntohs(OspfMplsTE.router_addr.header.type) == 0) {
783 		flog_warn(
784 			EC_OSPF_TE_UNEXPECTED,
785 			"MPLS-TE(is_mandated_params_set) Missing Router Address");
786 		return rc;
787 	}
788 
789 	if (ntohs(lp->link_type.header.type) == 0) {
790 		flog_warn(EC_OSPF_TE_UNEXPECTED,
791 			  "MPLS-TE(is_mandated_params_set) Missing Link Type");
792 		return rc;
793 	}
794 
795 	if (!IS_INTER_AS(lp->type) && (ntohs(lp->link_id.header.type) == 0)) {
796 		flog_warn(EC_OSPF_TE_UNEXPECTED,
797 			  "MPLS-TE(is_mandated_params_set) Missing Link ID");
798 		return rc;
799 	}
800 
801 	rc = 1;
802 	return rc;
803 }
804 
805 /*------------------------------------------------------------------------*
806  * Followings are callback functions against generic Opaque-LSAs handling.
807  *------------------------------------------------------------------------*/
808 
ospf_mpls_te_new_if(struct interface * ifp)809 static int ospf_mpls_te_new_if(struct interface *ifp)
810 {
811 	struct mpls_te_link *new;
812 
813 	if (IS_DEBUG_OSPF_TE)
814 		zlog_debug(
815 			"MPLS-TE(ospf_mpls_te_new_if) Add new %s interface %s to MPLS-TE list",
816 			ifp->link_params ? "Active" : "Inactive", ifp->name);
817 
818 	if (lookup_linkparams_by_ifp(ifp) != NULL)
819 		return 0;
820 
821 	new = XCALLOC(MTYPE_OSPF_MPLS_TE, sizeof(struct mpls_te_link));
822 
823 	new->instance = get_mpls_te_instance_value();
824 	new->ifp = ifp;
825 	/* By default TE-Link is RFC3630 compatible flooding in Area and not
826 	 * active */
827 	/* This default behavior will be adapted with call to
828 	 * ospf_mpls_te_update_if() */
829 	new->type = STD_TE | FLOOD_AREA;
830 	new->flags = LPFLG_LSA_INACTIVE;
831 
832 	/* Initialize Link Parameters from Interface */
833 	initialize_linkparams(new);
834 
835 	/* Set TE Parameters from Interface */
836 	update_linkparams(new);
837 
838 	/* Add Link Parameters structure to the list */
839 	listnode_add(OspfMplsTE.iflist, new);
840 
841 	if (IS_DEBUG_OSPF_TE)
842 		zlog_debug(
843 			"OSPF MPLS-TE New IF: Add new LP context for %s[%d/%d]",
844 			ifp->name, new->flags, new->type);
845 
846 	/* Schedule Opaque-LSA refresh. */ /* XXX */
847 	return 0;
848 }
849 
ospf_mpls_te_del_if(struct interface * ifp)850 static int ospf_mpls_te_del_if(struct interface *ifp)
851 {
852 	struct mpls_te_link *lp;
853 	int rc = -1;
854 
855 	if ((lp = lookup_linkparams_by_ifp(ifp)) != NULL) {
856 		struct list *iflist = OspfMplsTE.iflist;
857 
858 		/* Dequeue listnode entry from the list. */
859 		listnode_delete(iflist, lp);
860 
861 		XFREE(MTYPE_OSPF_MPLS_TE, lp);
862 	}
863 
864 	/* Schedule Opaque-LSA refresh. */ /* XXX */
865 
866 	rc = 0;
867 	return rc;
868 }
869 
870 /* Main initialization / update function of the MPLS TE Link context */
871 
872 /* Call when interface TE Link parameters are modified */
ospf_mpls_te_update_if(struct interface * ifp)873 void ospf_mpls_te_update_if(struct interface *ifp)
874 {
875 	struct mpls_te_link *lp;
876 
877 	if (IS_DEBUG_OSPF_TE)
878 		zlog_debug(
879 			"OSPF MPLS-TE: Update LSA parameters for interface %s [%s]",
880 			ifp->name, HAS_LINK_PARAMS(ifp) ? "ON" : "OFF");
881 
882 	/* Get Link context from interface */
883 	if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL) {
884 		flog_warn(
885 			EC_OSPF_TE_UNEXPECTED,
886 			"OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s",
887 			ifp->name);
888 		return;
889 	}
890 
891 	/* Fulfill MPLS-TE Link TLV from Interface TE Link parameters */
892 	if (HAS_LINK_PARAMS(ifp)) {
893 		SET_FLAG(lp->flags, LPFLG_LSA_ACTIVE);
894 
895 		/* Update TE parameters */
896 		update_linkparams(lp);
897 
898 		/* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is
899 		 * enabled */
900 		if (OspfMplsTE.enabled)
901 			if (lp->area != NULL) {
902 				if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
903 					ospf_mpls_te_lsa_schedule(
904 						lp, REFRESH_THIS_LSA);
905 				else
906 					ospf_mpls_te_lsa_schedule(
907 						lp, REORIGINATE_THIS_LSA);
908 			}
909 	} else {
910 		/* If MPLS TE is disable on this interface, flush LSA if it is
911 		 * already engaged */
912 		if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
913 			ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
914 		else
915 			/* Reset Activity flag */
916 			lp->flags = LPFLG_LSA_INACTIVE;
917 	}
918 
919 	return;
920 }
921 
922 /*
923  * Just add interface and set available information. Other information
924  * and flooding of LSA will be done later when adjacency will be up
925  * See ospf_mpls_te_nsm_change() after
926  */
ospf_mpls_te_ism_change(struct ospf_interface * oi,int old_state)927 static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state)
928 {
929 
930 	struct mpls_te_link *lp;
931 
932 	lp = lookup_linkparams_by_ifp(oi->ifp);
933 	if (lp == NULL) {
934 		flog_warn(
935 			EC_OSPF_TE_UNEXPECTED,
936 			"MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
937 			__func__, IF_NAME(oi));
938 		return;
939 	}
940 
941 	if (oi->area == NULL || oi->area->ospf == NULL) {
942 		flog_warn(
943 			EC_OSPF_TE_UNEXPECTED,
944 			"MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
945 			__func__, IF_NAME(oi));
946 		return;
947 	}
948 
949 	/* Keep Area information in combination with linkparams. */
950 	lp->area = oi->area;
951 
952 	/* Keep interface MPLS-TE status */
953 	lp->flags = HAS_LINK_PARAMS(oi->ifp);
954 
955 	switch (oi->state) {
956 	case ISM_PointToPoint:
957 	case ISM_DROther:
958 	case ISM_Backup:
959 	case ISM_DR:
960 		/* Set Link type and Local IP addr */
961 		set_linkparams_link_type(oi, lp);
962 		set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
963 
964 		break;
965 	default:
966 		/* State is undefined: Flush LSA if engaged */
967 		if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
968 			ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
969 		break;
970 	}
971 
972 	if (IS_DEBUG_OSPF_TE)
973 		zlog_debug(
974 			"MPLS-TE(%s): Update Link parameters for interface %s",
975 			__func__, IF_NAME(oi));
976 
977 	return;
978 }
979 
980 /*
981  * Complete TE info and schedule LSA flooding
982  * Link-ID and Remote IP address must be set with neighbor info
983  * which are only valid once NSM state is FULL
984  */
ospf_mpls_te_nsm_change(struct ospf_neighbor * nbr,int old_state)985 static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_state)
986 {
987 	struct ospf_interface *oi = nbr->oi;
988 	struct mpls_te_link *lp;
989 
990 	/* Process Neighbor only when its state is NSM Full */
991 	if (nbr->state != NSM_Full)
992 		return;
993 
994 	/* Get interface information for Traffic Engineering */
995 	lp = lookup_linkparams_by_ifp(oi->ifp);
996 	if (lp == NULL) {
997 		flog_warn(
998 			EC_OSPF_TE_UNEXPECTED,
999 			"MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
1000 			__func__, IF_NAME(oi));
1001 		return;
1002 	}
1003 
1004 	if (oi->area == NULL || oi->area->ospf == NULL) {
1005 		flog_warn(
1006 			EC_OSPF_TE_UNEXPECTED,
1007 			"MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
1008 			__func__, IF_NAME(oi));
1009 		return;
1010 	}
1011 
1012 	/* Keep Area information in combination with SR info. */
1013 	lp->area = oi->area;
1014 
1015 	/* Keep interface MPLS-TE status */
1016 	lp->flags = HAS_LINK_PARAMS(oi->ifp);
1017 
1018 	/*
1019 	 * The Link ID is identical to the contents of the Link ID field
1020 	 * in the Router LSA for these link types.
1021 	 */
1022 	switch (oi->state) {
1023 	case ISM_PointToPoint:
1024 		/* Set Link ID with neighbor Router ID */
1025 		set_linkparams_link_id(lp, nbr->router_id);
1026 		/* Set Remote IP address */
1027 		set_linkparams_rmtif_ipaddr(lp, nbr->address.u.prefix4);
1028 		break;
1029 
1030 	case ISM_DR:
1031 	case ISM_DROther:
1032 	case ISM_Backup:
1033 		/* Set Link ID with the Designated Router ID */
1034 		set_linkparams_link_id(lp, DR(oi));
1035 		break;
1036 
1037 	default:
1038 		/* State is undefined: Flush LSA if engaged */
1039 		if (OspfMplsTE.enabled &&
1040 			CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
1041 			ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
1042 		return;
1043 	}
1044 
1045 	if (IS_DEBUG_OSPF_TE)
1046 		zlog_debug(
1047 			"MPLS-TE (%s): Add Link-ID %s for interface %s ",
1048 			__func__, inet_ntoa(lp->link_id.value), oi->ifp->name);
1049 
1050 	/* Try to Schedule LSA */
1051 	if (OspfMplsTE.enabled) {
1052 		if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
1053 			ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
1054 		else
1055 			ospf_mpls_te_lsa_schedule(lp, REORIGINATE_THIS_LSA);
1056 	}
1057 	return;
1058 }
1059 
1060 /*------------------------------------------------------------------------*
1061  * Followings are OSPF protocol processing functions for MPLS-TE.
1062  *------------------------------------------------------------------------*/
1063 
build_tlv_header(struct stream * s,struct tlv_header * tlvh)1064 static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
1065 {
1066 	stream_put(s, tlvh, sizeof(struct tlv_header));
1067 	return;
1068 }
1069 
build_router_tlv(struct stream * s)1070 static void build_router_tlv(struct stream *s)
1071 {
1072 	struct tlv_header *tlvh = &OspfMplsTE.router_addr.header;
1073 	if (ntohs(tlvh->type) != 0) {
1074 		build_tlv_header(s, tlvh);
1075 		stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
1076 	}
1077 	return;
1078 }
1079 
build_link_subtlv(struct stream * s,struct tlv_header * tlvh)1080 static void build_link_subtlv(struct stream *s, struct tlv_header *tlvh)
1081 {
1082 
1083 	if ((tlvh != NULL) && (ntohs(tlvh->type) != 0)) {
1084 		build_tlv_header(s, tlvh);
1085 		stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
1086 	}
1087 	return;
1088 }
1089 
build_link_tlv(struct stream * s,struct mpls_te_link * lp)1090 static void build_link_tlv(struct stream *s, struct mpls_te_link *lp)
1091 {
1092 	set_linkparams_link_header(lp);
1093 	build_tlv_header(s, &lp->link_header.header);
1094 
1095 	build_link_subtlv(s, &lp->link_type.header);
1096 	build_link_subtlv(s, &lp->link_id.header);
1097 	build_link_subtlv(s, &lp->lclif_ipaddr.header);
1098 	build_link_subtlv(s, &lp->rmtif_ipaddr.header);
1099 	build_link_subtlv(s, &lp->te_metric.header);
1100 	build_link_subtlv(s, &lp->max_bw.header);
1101 	build_link_subtlv(s, &lp->max_rsv_bw.header);
1102 	build_link_subtlv(s, &lp->unrsv_bw.header);
1103 	build_link_subtlv(s, &lp->rsc_clsclr.header);
1104 	build_link_subtlv(s, &lp->lrrid.header);
1105 	build_link_subtlv(s, &lp->llri.header);
1106 	build_link_subtlv(s, &lp->rip.header);
1107 	build_link_subtlv(s, &lp->ras.header);
1108 	build_link_subtlv(s, &lp->av_delay.header);
1109 	build_link_subtlv(s, &lp->mm_delay.header);
1110 	build_link_subtlv(s, &lp->delay_var.header);
1111 	build_link_subtlv(s, &lp->pkt_loss.header);
1112 	build_link_subtlv(s, &lp->res_bw.header);
1113 	build_link_subtlv(s, &lp->ava_bw.header);
1114 	build_link_subtlv(s, &lp->use_bw.header);
1115 
1116 	return;
1117 }
1118 
ospf_mpls_te_lsa_body_set(struct stream * s,struct mpls_te_link * lp)1119 static void ospf_mpls_te_lsa_body_set(struct stream *s, struct mpls_te_link *lp)
1120 {
1121 	/*
1122 	 * The router address TLV is type 1, and ...
1123 	 *                                      It must appear in exactly one
1124 	 * Traffic Engineering LSA originated by a router.
1125 	 */
1126 	build_router_tlv(s);
1127 
1128 	/*
1129 	 * Only one Link TLV shall be carried in each LSA, allowing for fine
1130 	 * granularity changes in topology.
1131 	 */
1132 	build_link_tlv(s, lp);
1133 	return;
1134 }
1135 
1136 /* Create new opaque-LSA. */
ospf_mpls_te_lsa_new(struct ospf * ospf,struct ospf_area * area,struct mpls_te_link * lp)1137 static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf,
1138 					     struct ospf_area *area,
1139 					     struct mpls_te_link *lp)
1140 {
1141 	struct stream *s;
1142 	struct lsa_header *lsah;
1143 	struct ospf_lsa *new = NULL;
1144 	uint8_t options, lsa_type = 0;
1145 	struct in_addr lsa_id;
1146 	uint32_t tmp;
1147 	uint16_t length;
1148 
1149 	/* Create a stream for LSA. */
1150 	s = stream_new(OSPF_MAX_LSA_SIZE);
1151 	lsah = (struct lsa_header *)STREAM_DATA(s);
1152 
1153 	options = OSPF_OPTION_O; /* Don't forget this :-) */
1154 
1155 	/* Set opaque-LSA header fields depending of the type of RFC */
1156 	if (IS_INTER_AS(lp->type)) {
1157 		if (IS_FLOOD_AS(lp->type)) {
1158 			/* Enable AS external as we flood Inter-AS with Opaque
1159 			 * Type 11
1160 			 */
1161 			options |= OSPF_OPTION_E;
1162 			lsa_type = OSPF_OPAQUE_AS_LSA;
1163 		} else {
1164 			options |= LSA_OPTIONS_GET(
1165 				area); /* Get area default option */
1166 			options |= LSA_OPTIONS_NSSA_GET(area);
1167 			lsa_type = OSPF_OPAQUE_AREA_LSA;
1168 		}
1169 		tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
1170 		lsa_id.s_addr = htonl(tmp);
1171 
1172 		if (!ospf) {
1173 			stream_free(s);
1174 			return NULL;
1175 		}
1176 
1177 		lsa_header_set(s, options, lsa_type, lsa_id, ospf->router_id);
1178 	} else {
1179 		options |= LSA_OPTIONS_GET(area); /* Get area default option */
1180 		options |= LSA_OPTIONS_NSSA_GET(area);
1181 		lsa_type = OSPF_OPAQUE_AREA_LSA;
1182 		tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
1183 				      lp->instance);
1184 		lsa_id.s_addr = htonl(tmp);
1185 		lsa_header_set(s, options, lsa_type, lsa_id,
1186 			       area->ospf->router_id);
1187 	}
1188 
1189 	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
1190 		zlog_debug(
1191 			"LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance",
1192 			lsa_type, inet_ntoa(lsa_id));
1193 
1194 	/* Set opaque-LSA body fields. */
1195 	ospf_mpls_te_lsa_body_set(s, lp);
1196 
1197 	/* Set length. */
1198 	length = stream_get_endp(s);
1199 	lsah->length = htons(length);
1200 
1201 	/* Now, create an OSPF LSA instance. */
1202 	new = ospf_lsa_new_and_data(length);
1203 
1204 	new->vrf_id = ospf->vrf_id;
1205 	if (area && area->ospf)
1206 		new->vrf_id = area->ospf->vrf_id;
1207 	new->area = area;
1208 	SET_FLAG(new->flags, OSPF_LSA_SELF);
1209 	memcpy(new->data, lsah, length);
1210 	stream_free(s);
1211 
1212 	return new;
1213 }
1214 
ospf_mpls_te_lsa_originate1(struct ospf_area * area,struct mpls_te_link * lp)1215 static int ospf_mpls_te_lsa_originate1(struct ospf_area *area,
1216 				       struct mpls_te_link *lp)
1217 {
1218 	struct ospf_lsa *new = NULL;
1219 	int rc = -1;
1220 
1221 	/* Create new Opaque-LSA/MPLS-TE instance. */
1222 	new = ospf_mpls_te_lsa_new(area->ospf, area, lp);
1223 	if (new == NULL) {
1224 		flog_warn(
1225 			EC_OSPF_TE_UNEXPECTED,
1226 			"ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
1227 		return rc;
1228 	}
1229 
1230 	/* Install this LSA into LSDB. */
1231 	if (ospf_lsa_install(area->ospf, NULL /*oi*/, new) == NULL) {
1232 		flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1233 			  "ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
1234 		ospf_lsa_unlock(&new);
1235 		return rc;
1236 	}
1237 
1238 	/* Now this link-parameter entry has associated LSA. */
1239 	SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
1240 	/* Update new LSA origination count. */
1241 	area->ospf->lsa_originate_count++;
1242 
1243 	/* Flood new LSA through area. */
1244 	ospf_flood_through_area(area, NULL /*nbr*/, new);
1245 
1246 	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1247 		char area_id[INET_ADDRSTRLEN];
1248 		strlcpy(area_id, inet_ntoa(area->area_id), sizeof(area_id));
1249 		zlog_debug(
1250 			"LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)",
1251 			new->data->type, inet_ntoa(new->data->id), area_id,
1252 			lp->ifp->name);
1253 		ospf_lsa_header_dump(new->data);
1254 	}
1255 
1256 	rc = 0;
1257 	return rc;
1258 }
1259 
ospf_mpls_te_lsa_originate_area(void * arg)1260 static int ospf_mpls_te_lsa_originate_area(void *arg)
1261 {
1262 	struct ospf_area *area = (struct ospf_area *)arg;
1263 	struct listnode *node, *nnode;
1264 	struct mpls_te_link *lp;
1265 	int rc = -1;
1266 
1267 	if (!OspfMplsTE.enabled) {
1268 		zlog_info(
1269 			"ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now.");
1270 		rc = 0; /* This is not an error case. */
1271 		return rc;
1272 	}
1273 
1274 	for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
1275 		/* Process only enabled LSA with area scope flooding */
1276 		if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)
1277 		    || IS_FLOOD_AS(lp->type))
1278 			continue;
1279 
1280 		if (lp->area == NULL)
1281 			continue;
1282 
1283 		if (!IPV4_ADDR_SAME(&lp->area->area_id, &area->area_id))
1284 			continue;
1285 
1286 		if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
1287 			if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
1288 				UNSET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
1289 				zlog_info(
1290 					"OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate");
1291 				ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
1292 			}
1293 			continue;
1294 		}
1295 
1296 		if (!is_mandated_params_set(lp)) {
1297 			zlog_info(
1298 				"ospf_mpls_te_lsa_originate_area: Link(%s) lacks some mandated MPLS-TE parameters.",
1299 				lp->ifp ? lp->ifp->name : "?");
1300 			continue;
1301 		}
1302 
1303 		/* Ok, let's try to originate an LSA for this area and Link. */
1304 		if (IS_DEBUG_OSPF_TE)
1305 			zlog_debug(
1306 				"MPLS-TE(ospf_mpls_te_lsa_originate_area) Let's finally reoriginate the LSA %d through the Area %s for Link %s",
1307 				lp->instance, inet_ntoa(area->area_id),
1308 				lp->ifp ? lp->ifp->name : "?");
1309 		if (ospf_mpls_te_lsa_originate1(area, lp) != 0)
1310 			return rc;
1311 	}
1312 
1313 	rc = 0;
1314 	return rc;
1315 }
1316 
ospf_mpls_te_lsa_originate2(struct ospf * top,struct mpls_te_link * lp)1317 static int ospf_mpls_te_lsa_originate2(struct ospf *top,
1318 				       struct mpls_te_link *lp)
1319 {
1320 	struct ospf_lsa *new;
1321 	int rc = -1;
1322 
1323 	/* Create new Opaque-LSA/Inter-AS instance. */
1324 	new = ospf_mpls_te_lsa_new(top, NULL, lp);
1325 	if (new == NULL) {
1326 		flog_warn(
1327 			EC_OSPF_LSA_UNEXPECTED,
1328 			"ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?");
1329 		return rc;
1330 	}
1331 	new->vrf_id = top->vrf_id;
1332 
1333 	/* Install this LSA into LSDB. */
1334 	if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1335 		flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1336 			  "ospf_mpls_te_lsa_originate2: ospf_lsa_install() ?");
1337 		ospf_lsa_unlock(&new);
1338 		return rc;
1339 	}
1340 
1341 	/* Now this Router Info parameter entry has associated LSA. */
1342 	SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
1343 	/* Update new LSA origination count. */
1344 	top->lsa_originate_count++;
1345 
1346 	/* Flood new LSA through AS. */
1347 	ospf_flood_through_as(top, NULL /*nbr */, new);
1348 
1349 	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1350 		zlog_debug(
1351 			"LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE Inter-AS",
1352 			new->data->type, inet_ntoa(new->data->id));
1353 		ospf_lsa_header_dump(new->data);
1354 	}
1355 
1356 	rc = 0;
1357 	return rc;
1358 }
1359 
ospf_mpls_te_lsa_originate_as(void * arg)1360 static int ospf_mpls_te_lsa_originate_as(void *arg)
1361 {
1362 	struct ospf *top;
1363 	struct ospf_area *area;
1364 	struct listnode *node, *nnode;
1365 	struct mpls_te_link *lp;
1366 	int rc = -1;
1367 
1368 	if ((!OspfMplsTE.enabled) || (OspfMplsTE.inter_as == Off)) {
1369 		zlog_info(
1370 			"ospf_mpls_te_lsa_originate_as: MPLS-TE Inter-AS is disabled for now.");
1371 		rc = 0; /* This is not an error case. */
1372 		return rc;
1373 	}
1374 
1375 	for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
1376 		/* Process only enabled INTER_AS Links or Pseudo-Links */
1377 		if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)
1378 		    || !IS_INTER_AS(lp->type))
1379 			continue;
1380 
1381 		if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
1382 			if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
1383 				UNSET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
1384 				ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
1385 			}
1386 			continue;
1387 		}
1388 
1389 		if (!is_mandated_params_set(lp)) {
1390 			flog_warn(
1391 				EC_OSPF_TE_UNEXPECTED,
1392 				"ospf_mpls_te_lsa_originate_as: Link(%s) lacks some mandated MPLS-TE parameters.",
1393 				lp->ifp ? lp->ifp->name : "?");
1394 			continue;
1395 		}
1396 
1397 		/* Ok, let's try to originate an LSA for this AS and Link. */
1398 		if (IS_DEBUG_OSPF_TE)
1399 			zlog_debug(
1400 				"MPLS-TE(ospf_mpls_te_lsa_originate_as) Let's finally re-originate the Inter-AS LSA %d through the %s for Link %s",
1401 				lp->instance,
1402 				IS_FLOOD_AS(lp->type) ? "AS" : "Area",
1403 				lp->ifp ? lp->ifp->name : "Unknown");
1404 
1405 		if (IS_FLOOD_AS(lp->type)) {
1406 			top = (struct ospf *)arg;
1407 			ospf_mpls_te_lsa_originate2(top, lp);
1408 		} else {
1409 			area = (struct ospf_area *)arg;
1410 			ospf_mpls_te_lsa_originate1(area, lp);
1411 		}
1412 	}
1413 
1414 	rc = 0;
1415 	return rc;
1416 }
1417 
ospf_mpls_te_lsa_refresh(struct ospf_lsa * lsa)1418 static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
1419 {
1420 	struct mpls_te_link *lp;
1421 	struct ospf_area *area = lsa->area;
1422 	struct ospf *top;
1423 	struct ospf_lsa *new = NULL;
1424 
1425 	if (!OspfMplsTE.enabled) {
1426 		/*
1427 		 * This LSA must have flushed before due to MPLS-TE status
1428 		 * change.
1429 		 * It seems a slip among routers in the routing domain.
1430 		 */
1431 		zlog_info("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now.");
1432 		lsa->data->ls_age =
1433 			htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1434 	}
1435 
1436 	/* At first, resolve lsa/lp relationship. */
1437 	if ((lp = lookup_linkparams_by_instance(lsa)) == NULL) {
1438 		flog_warn(EC_OSPF_TE_UNEXPECTED,
1439 			  "ospf_mpls_te_lsa_refresh: Invalid parameter?");
1440 		lsa->data->ls_age =
1441 			htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1442 		ospf_opaque_lsa_flush_schedule(lsa);
1443 		return NULL;
1444 	}
1445 
1446 	/* Check if lp was not disable in the interval */
1447 	if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)) {
1448 		flog_warn(
1449 			EC_OSPF_TE_UNEXPECTED,
1450 			"ospf_mpls_te_lsa_refresh: lp was disabled: Flush it!");
1451 		lsa->data->ls_age =
1452 			htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1453 	}
1454 
1455 	/* If the lsa's age reached to MaxAge, start flushing procedure. */
1456 	if (IS_LSA_MAXAGE(lsa)) {
1457 		UNSET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
1458 		ospf_opaque_lsa_flush_schedule(lsa);
1459 		return NULL;
1460 	}
1461 	top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1462 	/* Create new Opaque-LSA/MPLS-TE instance. */
1463 	new = ospf_mpls_te_lsa_new(top, area, lp);
1464 	if (new == NULL) {
1465 		flog_warn(EC_OSPF_TE_UNEXPECTED,
1466 			  "ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
1467 		return NULL;
1468 	}
1469 	new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1470 
1471 	/* Install this LSA into LSDB. */
1472 	/* Given "lsa" will be freed in the next function. */
1473 	/* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use
1474 	 * ospf_lookup() to get ospf instance */
1475 	if (area)
1476 		top = area->ospf;
1477 
1478 	if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1479 		flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1480 			  "ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
1481 		ospf_lsa_unlock(&new);
1482 		return NULL;
1483 	}
1484 
1485 	/* Flood updated LSA through AS or Area depending of the RFC of the link
1486 	 */
1487 	if (IS_FLOOD_AS(lp->type))
1488 		ospf_flood_through_as(top, NULL, new);
1489 	else
1490 		ospf_flood_through_area(area, NULL /*nbr*/, new);
1491 
1492 	/* Debug logging. */
1493 	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1494 		zlog_debug("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
1495 			   new->data->type, inet_ntoa(new->data->id));
1496 		ospf_lsa_header_dump(new->data);
1497 	}
1498 
1499 	return new;
1500 }
1501 
ospf_mpls_te_lsa_schedule(struct mpls_te_link * lp,enum lsa_opcode opcode)1502 void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, enum lsa_opcode opcode)
1503 {
1504 	struct ospf_lsa lsa;
1505 	struct lsa_header lsah;
1506 	struct ospf *top;
1507 	uint32_t tmp;
1508 
1509 	memset(&lsa, 0, sizeof(lsa));
1510 	memset(&lsah, 0, sizeof(lsah));
1511 	top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1512 
1513 	/* Check if the pseudo link is ready to flood */
1514 	if (!(CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE))
1515 	    || !(IS_FLOOD_AREA(lp->type) || IS_FLOOD_AS(lp->type))) {
1516 		return;
1517 	}
1518 
1519 	lsa.area = lp->area;
1520 	lsa.data = &lsah;
1521 	if (IS_FLOOD_AS(lp->type)) {
1522 		lsah.type = OSPF_OPAQUE_AS_LSA;
1523 		tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
1524 		lsah.id.s_addr = htonl(tmp);
1525 	} else {
1526 		lsah.type = OSPF_OPAQUE_AREA_LSA;
1527 		if (IS_INTER_AS(lp->type)) {
1528 			/* Set the area context if not know */
1529 			if (lp->area == NULL)
1530 				lp->area = ospf_area_lookup_by_area_id(
1531 					top, OspfMplsTE.interas_areaid);
1532 			/* Unable to set the area context. Abort! */
1533 			if (lp->area == NULL) {
1534 				flog_warn(
1535 					EC_OSPF_TE_UNEXPECTED,
1536 					"MPLS-TE(ospf_mpls_te_lsa_schedule) Area context is null. Abort !");
1537 				return;
1538 			}
1539 			tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA,
1540 					      lp->instance);
1541 		} else
1542 			tmp = SET_OPAQUE_LSID(
1543 				OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
1544 				lp->instance);
1545 		lsah.id.s_addr = htonl(tmp);
1546 	}
1547 
1548 	switch (opcode) {
1549 	case REORIGINATE_THIS_LSA:
1550 		if (IS_FLOOD_AS(lp->type)) {
1551 			ospf_opaque_lsa_reoriginate_schedule(
1552 				(void *)top, OSPF_OPAQUE_AS_LSA,
1553 				OPAQUE_TYPE_INTER_AS_LSA);
1554 			break;
1555 		}
1556 
1557 		if (IS_FLOOD_AREA(lp->type)) {
1558 			if (IS_INTER_AS(lp->type))
1559 				ospf_opaque_lsa_reoriginate_schedule(
1560 					(void *)lp->area, OSPF_OPAQUE_AREA_LSA,
1561 					OPAQUE_TYPE_INTER_AS_LSA);
1562 			else
1563 				ospf_opaque_lsa_reoriginate_schedule(
1564 					(void *)lp->area, OSPF_OPAQUE_AREA_LSA,
1565 					OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
1566 			break;
1567 		}
1568 		break;
1569 	case REFRESH_THIS_LSA:
1570 		ospf_opaque_lsa_refresh_schedule(&lsa);
1571 		break;
1572 	case FLUSH_THIS_LSA:
1573 		/* Reset Activity flag */
1574 		lp->flags = LPFLG_LSA_INACTIVE;
1575 		ospf_opaque_lsa_flush_schedule(&lsa);
1576 		break;
1577 	default:
1578 		flog_warn(EC_OSPF_TE_UNEXPECTED,
1579 			  "ospf_mpls_te_lsa_schedule: Unknown opcode (%u)",
1580 			  opcode);
1581 		break;
1582 	}
1583 
1584 	return;
1585 }
1586 
1587 
1588 /*------------------------------------------------------------------------*
1589  * Followings are vty session control functions.
1590  *------------------------------------------------------------------------*/
1591 
show_vty_router_addr(struct vty * vty,struct tlv_header * tlvh)1592 static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh)
1593 {
1594 	struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh;
1595 
1596 	if (vty != NULL)
1597 		vty_out(vty, "  Router-Address: %s\n", inet_ntoa(top->value));
1598 	else
1599 		zlog_debug("    Router-Address: %s", inet_ntoa(top->value));
1600 
1601 	return TLV_SIZE(tlvh);
1602 }
1603 
show_vty_link_header(struct vty * vty,struct tlv_header * tlvh)1604 static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh)
1605 {
1606 	struct te_tlv_link *top = (struct te_tlv_link *)tlvh;
1607 
1608 	if (vty != NULL)
1609 		vty_out(vty, "  Link: %u octets of data\n",
1610 			ntohs(top->header.length));
1611 	else
1612 		zlog_debug("    Link: %u octets of data",
1613 			   ntohs(top->header.length));
1614 
1615 	return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
1616 }
1617 
show_vty_link_subtlv_link_type(struct vty * vty,struct tlv_header * tlvh)1618 static uint16_t show_vty_link_subtlv_link_type(struct vty *vty,
1619 					       struct tlv_header *tlvh)
1620 {
1621 	struct te_link_subtlv_link_type *top;
1622 	const char *cp = "Unknown";
1623 
1624 	top = (struct te_link_subtlv_link_type *)tlvh;
1625 	switch (top->link_type.value) {
1626 	case LINK_TYPE_SUBTLV_VALUE_PTP:
1627 		cp = "Point-to-point";
1628 		break;
1629 	case LINK_TYPE_SUBTLV_VALUE_MA:
1630 		cp = "Multiaccess";
1631 		break;
1632 	default:
1633 		break;
1634 	}
1635 
1636 	if (vty != NULL)
1637 		vty_out(vty, "  Link-Type: %s (%u)\n", cp,
1638 			top->link_type.value);
1639 	else
1640 		zlog_debug("    Link-Type: %s (%u)", cp, top->link_type.value);
1641 
1642 	return TLV_SIZE(tlvh);
1643 }
1644 
show_vty_link_subtlv_link_id(struct vty * vty,struct tlv_header * tlvh)1645 static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
1646 					     struct tlv_header *tlvh)
1647 {
1648 	struct te_link_subtlv_link_id *top;
1649 
1650 	top = (struct te_link_subtlv_link_id *)tlvh;
1651 	if (vty != NULL)
1652 		vty_out(vty, "  Link-ID: %s\n", inet_ntoa(top->value));
1653 	else
1654 		zlog_debug("    Link-ID: %s", inet_ntoa(top->value));
1655 
1656 	return TLV_SIZE(tlvh);
1657 }
1658 
show_vty_link_subtlv_lclif_ipaddr(struct vty * vty,struct tlv_header * tlvh)1659 static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
1660 						  struct tlv_header *tlvh)
1661 {
1662 	struct te_link_subtlv_lclif_ipaddr *top;
1663 	int i, n;
1664 
1665 	top = (struct te_link_subtlv_lclif_ipaddr *)tlvh;
1666 	n = ntohs(tlvh->length) / sizeof(top->value[0]);
1667 
1668 	if (vty != NULL)
1669 		vty_out(vty, "  Local Interface IP Address(es): %d\n", n);
1670 	else
1671 		zlog_debug("    Local Interface IP Address(es): %d", n);
1672 
1673 	for (i = 0; i < n; i++) {
1674 		if (vty != NULL)
1675 			vty_out(vty, "    #%d: %s\n", i,
1676 				inet_ntoa(top->value[i]));
1677 		else
1678 			zlog_debug("      #%d: %s", i,
1679 				   inet_ntoa(top->value[i]));
1680 	}
1681 	return TLV_SIZE(tlvh);
1682 }
1683 
show_vty_link_subtlv_rmtif_ipaddr(struct vty * vty,struct tlv_header * tlvh)1684 static uint16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
1685 						  struct tlv_header *tlvh)
1686 {
1687 	struct te_link_subtlv_rmtif_ipaddr *top;
1688 	int i, n;
1689 
1690 	top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh;
1691 	n = ntohs(tlvh->length) / sizeof(top->value[0]);
1692 	if (vty != NULL)
1693 		vty_out(vty, "  Remote Interface IP Address(es): %d\n", n);
1694 	else
1695 		zlog_debug("    Remote Interface IP Address(es): %d", n);
1696 
1697 	for (i = 0; i < n; i++) {
1698 		if (vty != NULL)
1699 			vty_out(vty, "    #%d: %s\n", i,
1700 				inet_ntoa(top->value[i]));
1701 		else
1702 			zlog_debug("      #%d: %s", i,
1703 				   inet_ntoa(top->value[i]));
1704 	}
1705 	return TLV_SIZE(tlvh);
1706 }
1707 
show_vty_link_subtlv_te_metric(struct vty * vty,struct tlv_header * tlvh)1708 static uint16_t show_vty_link_subtlv_te_metric(struct vty *vty,
1709 					       struct tlv_header *tlvh)
1710 {
1711 	struct te_link_subtlv_te_metric *top;
1712 
1713 	top = (struct te_link_subtlv_te_metric *)tlvh;
1714 	if (vty != NULL)
1715 		vty_out(vty, "  Traffic Engineering Metric: %u\n",
1716 			(uint32_t)ntohl(top->value));
1717 	else
1718 		zlog_debug("    Traffic Engineering Metric: %u",
1719 			   (uint32_t)ntohl(top->value));
1720 
1721 	return TLV_SIZE(tlvh);
1722 }
1723 
show_vty_link_subtlv_max_bw(struct vty * vty,struct tlv_header * tlvh)1724 static uint16_t show_vty_link_subtlv_max_bw(struct vty *vty,
1725 					    struct tlv_header *tlvh)
1726 {
1727 	struct te_link_subtlv_max_bw *top;
1728 	float fval;
1729 
1730 	top = (struct te_link_subtlv_max_bw *)tlvh;
1731 	fval = ntohf(top->value);
1732 
1733 	if (vty != NULL)
1734 		vty_out(vty, "  Maximum Bandwidth: %g (Bytes/sec)\n", fval);
1735 	else
1736 		zlog_debug("    Maximum Bandwidth: %g (Bytes/sec)", fval);
1737 
1738 	return TLV_SIZE(tlvh);
1739 }
1740 
show_vty_link_subtlv_max_rsv_bw(struct vty * vty,struct tlv_header * tlvh)1741 static uint16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
1742 						struct tlv_header *tlvh)
1743 {
1744 	struct te_link_subtlv_max_rsv_bw *top;
1745 	float fval;
1746 
1747 	top = (struct te_link_subtlv_max_rsv_bw *)tlvh;
1748 	fval = ntohf(top->value);
1749 
1750 	if (vty != NULL)
1751 		vty_out(vty, "  Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
1752 			fval);
1753 	else
1754 		zlog_debug("    Maximum Reservable Bandwidth: %g (Bytes/sec)",
1755 			   fval);
1756 
1757 	return TLV_SIZE(tlvh);
1758 }
1759 
show_vty_link_subtlv_unrsv_bw(struct vty * vty,struct tlv_header * tlvh)1760 static uint16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
1761 					      struct tlv_header *tlvh)
1762 {
1763 	struct te_link_subtlv_unrsv_bw *top;
1764 	float fval1, fval2;
1765 	int i;
1766 
1767 	top = (struct te_link_subtlv_unrsv_bw *)tlvh;
1768 	if (vty != NULL)
1769 		vty_out(vty,
1770 			"  Unreserved Bandwidth per Class Type in Byte/s:\n");
1771 	else
1772 		zlog_debug(
1773 			"    Unreserved Bandwidth per Class Type in Byte/s:");
1774 	for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
1775 		fval1 = ntohf(top->value[i]);
1776 		fval2 = ntohf(top->value[i + 1]);
1777 
1778 		if (vty != NULL)
1779 			vty_out(vty,
1780 				"    [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
1781 				i, fval1, i + 1, fval2);
1782 		else
1783 			zlog_debug(
1784 				"      [%d]: %g (Bytes/sec),  [%d]: %g (Bytes/sec)",
1785 				i, fval1, i + 1, fval2);
1786 	}
1787 
1788 	return TLV_SIZE(tlvh);
1789 }
1790 
show_vty_link_subtlv_rsc_clsclr(struct vty * vty,struct tlv_header * tlvh)1791 static uint16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
1792 						struct tlv_header *tlvh)
1793 {
1794 	struct te_link_subtlv_rsc_clsclr *top;
1795 
1796 	top = (struct te_link_subtlv_rsc_clsclr *)tlvh;
1797 	if (vty != NULL)
1798 		vty_out(vty, "  Resource class/color: 0x%x\n",
1799 			(uint32_t)ntohl(top->value));
1800 	else
1801 		zlog_debug("    Resource Class/Color: 0x%x",
1802 			   (uint32_t)ntohl(top->value));
1803 
1804 	return TLV_SIZE(tlvh);
1805 }
1806 
show_vty_link_subtlv_lrrid(struct vty * vty,struct tlv_header * tlvh)1807 static uint16_t show_vty_link_subtlv_lrrid(struct vty *vty,
1808 					   struct tlv_header *tlvh)
1809 {
1810 	struct te_link_subtlv_lrrid *top;
1811 
1812 	top = (struct te_link_subtlv_lrrid *)tlvh;
1813 
1814 	if (vty != NULL) {
1815 		vty_out(vty, "  Local  TE Router ID: %s\n",
1816 			inet_ntoa(top->local));
1817 		vty_out(vty, "  Remote TE Router ID: %s\n",
1818 			inet_ntoa(top->remote));
1819 	} else {
1820 		zlog_debug("    Local  TE Router ID: %s",
1821 			   inet_ntoa(top->local));
1822 		zlog_debug("    Remote TE Router ID: %s",
1823 			   inet_ntoa(top->remote));
1824 	}
1825 
1826 	return TLV_SIZE(tlvh);
1827 }
1828 
show_vty_link_subtlv_llri(struct vty * vty,struct tlv_header * tlvh)1829 static uint16_t show_vty_link_subtlv_llri(struct vty *vty,
1830 					  struct tlv_header *tlvh)
1831 {
1832 	struct te_link_subtlv_llri *top;
1833 
1834 	top = (struct te_link_subtlv_llri *)tlvh;
1835 
1836 	if (vty != NULL) {
1837 		vty_out(vty, "  Link Local  ID: %d\n",
1838 			(uint32_t)ntohl(top->local));
1839 		vty_out(vty, "  Link Remote ID: %d\n",
1840 			(uint32_t)ntohl(top->remote));
1841 	} else {
1842 		zlog_debug("    Link Local  ID: %d",
1843 			   (uint32_t)ntohl(top->local));
1844 		zlog_debug("    Link Remote ID: %d",
1845 			   (uint32_t)ntohl(top->remote));
1846 	}
1847 
1848 	return TLV_SIZE(tlvh);
1849 }
1850 
show_vty_link_subtlv_rip(struct vty * vty,struct tlv_header * tlvh)1851 static uint16_t show_vty_link_subtlv_rip(struct vty *vty,
1852 					 struct tlv_header *tlvh)
1853 {
1854 	struct te_link_subtlv_rip *top;
1855 
1856 	top = (struct te_link_subtlv_rip *)tlvh;
1857 
1858 	if (vty != NULL)
1859 		vty_out(vty, "  Inter-AS TE Remote ASBR IP address: %s\n",
1860 			inet_ntoa(top->value));
1861 	else
1862 		zlog_debug("    Inter-AS TE Remote ASBR IP address: %s",
1863 			   inet_ntoa(top->value));
1864 
1865 	return TLV_SIZE(tlvh);
1866 }
1867 
show_vty_link_subtlv_ras(struct vty * vty,struct tlv_header * tlvh)1868 static uint16_t show_vty_link_subtlv_ras(struct vty *vty,
1869 					 struct tlv_header *tlvh)
1870 {
1871 	struct te_link_subtlv_ras *top;
1872 
1873 	top = (struct te_link_subtlv_ras *)tlvh;
1874 
1875 	if (vty != NULL)
1876 		vty_out(vty, "  Inter-AS TE Remote AS number: %u\n",
1877 			ntohl(top->value));
1878 	else
1879 		zlog_debug("    Inter-AS TE Remote AS number: %u",
1880 			   ntohl(top->value));
1881 
1882 	return TLV_SIZE(tlvh);
1883 }
1884 
show_vty_link_subtlv_av_delay(struct vty * vty,struct tlv_header * tlvh)1885 static uint16_t show_vty_link_subtlv_av_delay(struct vty *vty,
1886 					      struct tlv_header *tlvh)
1887 {
1888 	struct te_link_subtlv_av_delay *top;
1889 	uint32_t delay;
1890 	uint32_t anomalous;
1891 
1892 	top = (struct te_link_subtlv_av_delay *)tlvh;
1893 	delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
1894 	anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
1895 
1896 	if (vty != NULL)
1897 		vty_out(vty, "  %s Average Link Delay: %d (micro-sec)\n",
1898 			anomalous ? "Anomalous" : "Normal", delay);
1899 	else
1900 		zlog_debug("    %s Average Link Delay: %d (micro-sec)",
1901 			   anomalous ? "Anomalous" : "Normal", delay);
1902 
1903 	return TLV_SIZE(tlvh);
1904 }
1905 
show_vty_link_subtlv_mm_delay(struct vty * vty,struct tlv_header * tlvh)1906 static uint16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
1907 					      struct tlv_header *tlvh)
1908 {
1909 	struct te_link_subtlv_mm_delay *top;
1910 	uint32_t low, high;
1911 	uint32_t anomalous;
1912 
1913 	top = (struct te_link_subtlv_mm_delay *)tlvh;
1914 	low = (uint32_t)ntohl(top->low) & TE_EXT_MASK;
1915 	anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL;
1916 	high = (uint32_t)ntohl(top->high);
1917 
1918 	if (vty != NULL)
1919 		vty_out(vty, "  %s Min/Max Link Delay: %d/%d (micro-sec)\n",
1920 			anomalous ? "Anomalous" : "Normal", low, high);
1921 	else
1922 		zlog_debug("    %s Min/Max Link Delay: %d/%d (micro-sec)",
1923 			   anomalous ? "Anomalous" : "Normal", low, high);
1924 
1925 	return TLV_SIZE(tlvh);
1926 }
1927 
show_vty_link_subtlv_delay_var(struct vty * vty,struct tlv_header * tlvh)1928 static uint16_t show_vty_link_subtlv_delay_var(struct vty *vty,
1929 					       struct tlv_header *tlvh)
1930 {
1931 	struct te_link_subtlv_delay_var *top;
1932 	uint32_t jitter;
1933 
1934 	top = (struct te_link_subtlv_delay_var *)tlvh;
1935 	jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
1936 
1937 	if (vty != NULL)
1938 		vty_out(vty, "  Delay Variation: %d (micro-sec)\n", jitter);
1939 	else
1940 		zlog_debug("    Delay Variation: %d (micro-sec)", jitter);
1941 
1942 	return TLV_SIZE(tlvh);
1943 }
1944 
show_vty_link_subtlv_pkt_loss(struct vty * vty,struct tlv_header * tlvh)1945 static uint16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
1946 					      struct tlv_header *tlvh)
1947 {
1948 	struct te_link_subtlv_pkt_loss *top;
1949 	uint32_t loss;
1950 	uint32_t anomalous;
1951 	float fval;
1952 
1953 	top = (struct te_link_subtlv_pkt_loss *)tlvh;
1954 	loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
1955 	fval = (float)(loss * LOSS_PRECISION);
1956 	anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
1957 
1958 	if (vty != NULL)
1959 		vty_out(vty, "  %s Link Loss: %g (%%)\n",
1960 			anomalous ? "Anomalous" : "Normal", fval);
1961 	else
1962 		zlog_debug("    %s Link Loss: %g (%%)",
1963 			   anomalous ? "Anomalous" : "Normal", fval);
1964 
1965 	return TLV_SIZE(tlvh);
1966 }
1967 
show_vty_link_subtlv_res_bw(struct vty * vty,struct tlv_header * tlvh)1968 static uint16_t show_vty_link_subtlv_res_bw(struct vty *vty,
1969 					    struct tlv_header *tlvh)
1970 {
1971 	struct te_link_subtlv_res_bw *top;
1972 	float fval;
1973 
1974 	top = (struct te_link_subtlv_res_bw *)tlvh;
1975 	fval = ntohf(top->value);
1976 
1977 	if (vty != NULL)
1978 		vty_out(vty,
1979 			"  Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
1980 			fval);
1981 	else
1982 		zlog_debug(
1983 			"    Unidirectional Residual Bandwidth: %g (Bytes/sec)",
1984 			fval);
1985 
1986 	return TLV_SIZE(tlvh);
1987 }
1988 
show_vty_link_subtlv_ava_bw(struct vty * vty,struct tlv_header * tlvh)1989 static uint16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
1990 					    struct tlv_header *tlvh)
1991 {
1992 	struct te_link_subtlv_ava_bw *top;
1993 	float fval;
1994 
1995 	top = (struct te_link_subtlv_ava_bw *)tlvh;
1996 	fval = ntohf(top->value);
1997 
1998 	if (vty != NULL)
1999 		vty_out(vty,
2000 			"  Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
2001 			fval);
2002 	else
2003 		zlog_debug(
2004 			"    Unidirectional Available Bandwidth: %g (Bytes/sec)",
2005 			fval);
2006 
2007 	return TLV_SIZE(tlvh);
2008 }
2009 
show_vty_link_subtlv_use_bw(struct vty * vty,struct tlv_header * tlvh)2010 static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
2011 					    struct tlv_header *tlvh)
2012 {
2013 	struct te_link_subtlv_use_bw *top;
2014 	float fval;
2015 
2016 	top = (struct te_link_subtlv_use_bw *)tlvh;
2017 	fval = ntohf(top->value);
2018 
2019 	if (vty != NULL)
2020 		vty_out(vty,
2021 			"  Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
2022 			fval);
2023 	else
2024 		zlog_debug(
2025 			"    Unidirectional Utilized Bandwidth: %g (Bytes/sec)",
2026 			fval);
2027 
2028 	return TLV_SIZE(tlvh);
2029 }
2030 
show_vty_unknown_tlv(struct vty * vty,struct tlv_header * tlvh)2031 static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
2032 {
2033 	if (vty != NULL)
2034 		vty_out(vty, "  Unknown TLV: [type(0x%x), length(0x%x)]\n",
2035 			ntohs(tlvh->type), ntohs(tlvh->length));
2036 	else
2037 		zlog_debug("    Unknown TLV: [type(0x%x), length(0x%x)]",
2038 			   ntohs(tlvh->type), ntohs(tlvh->length));
2039 
2040 	return TLV_SIZE(tlvh);
2041 }
2042 
ospf_mpls_te_show_link_subtlv(struct vty * vty,struct tlv_header * tlvh0,uint16_t subtotal,uint16_t total)2043 static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
2044 					      struct tlv_header *tlvh0,
2045 					      uint16_t subtotal, uint16_t total)
2046 {
2047 	struct tlv_header *tlvh;
2048 	uint16_t sum = subtotal;
2049 
2050 	for (tlvh = tlvh0; sum < total;
2051 	     tlvh = TLV_HDR_NEXT(tlvh)) {
2052 		switch (ntohs(tlvh->type)) {
2053 		case TE_LINK_SUBTLV_LINK_TYPE:
2054 			sum += show_vty_link_subtlv_link_type(vty, tlvh);
2055 			break;
2056 		case TE_LINK_SUBTLV_LINK_ID:
2057 			sum += show_vty_link_subtlv_link_id(vty, tlvh);
2058 			break;
2059 		case TE_LINK_SUBTLV_LCLIF_IPADDR:
2060 			sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh);
2061 			break;
2062 		case TE_LINK_SUBTLV_RMTIF_IPADDR:
2063 			sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh);
2064 			break;
2065 		case TE_LINK_SUBTLV_TE_METRIC:
2066 			sum += show_vty_link_subtlv_te_metric(vty, tlvh);
2067 			break;
2068 		case TE_LINK_SUBTLV_MAX_BW:
2069 			sum += show_vty_link_subtlv_max_bw(vty, tlvh);
2070 			break;
2071 		case TE_LINK_SUBTLV_MAX_RSV_BW:
2072 			sum += show_vty_link_subtlv_max_rsv_bw(vty, tlvh);
2073 			break;
2074 		case TE_LINK_SUBTLV_UNRSV_BW:
2075 			sum += show_vty_link_subtlv_unrsv_bw(vty, tlvh);
2076 			break;
2077 		case TE_LINK_SUBTLV_RSC_CLSCLR:
2078 			sum += show_vty_link_subtlv_rsc_clsclr(vty, tlvh);
2079 			break;
2080 		case TE_LINK_SUBTLV_LRRID:
2081 			sum += show_vty_link_subtlv_lrrid(vty, tlvh);
2082 			break;
2083 		case TE_LINK_SUBTLV_LLRI:
2084 			sum += show_vty_link_subtlv_llri(vty, tlvh);
2085 			break;
2086 		case TE_LINK_SUBTLV_RIP:
2087 			sum += show_vty_link_subtlv_rip(vty, tlvh);
2088 			break;
2089 		case TE_LINK_SUBTLV_RAS:
2090 			sum += show_vty_link_subtlv_ras(vty, tlvh);
2091 			break;
2092 		case TE_LINK_SUBTLV_AV_DELAY:
2093 			sum += show_vty_link_subtlv_av_delay(vty, tlvh);
2094 			break;
2095 		case TE_LINK_SUBTLV_MM_DELAY:
2096 			sum += show_vty_link_subtlv_mm_delay(vty, tlvh);
2097 			break;
2098 		case TE_LINK_SUBTLV_DELAY_VAR:
2099 			sum += show_vty_link_subtlv_delay_var(vty, tlvh);
2100 			break;
2101 		case TE_LINK_SUBTLV_PKT_LOSS:
2102 			sum += show_vty_link_subtlv_pkt_loss(vty, tlvh);
2103 			break;
2104 		case TE_LINK_SUBTLV_RES_BW:
2105 			sum += show_vty_link_subtlv_res_bw(vty, tlvh);
2106 			break;
2107 		case TE_LINK_SUBTLV_AVA_BW:
2108 			sum += show_vty_link_subtlv_ava_bw(vty, tlvh);
2109 			break;
2110 		case TE_LINK_SUBTLV_USE_BW:
2111 			sum += show_vty_link_subtlv_use_bw(vty, tlvh);
2112 			break;
2113 		default:
2114 			sum += show_vty_unknown_tlv(vty, tlvh);
2115 			break;
2116 		}
2117 	}
2118 	return sum;
2119 }
2120 
ospf_mpls_te_show_info(struct vty * vty,struct ospf_lsa * lsa)2121 static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
2122 {
2123 	struct lsa_header *lsah = lsa->data;
2124 	struct tlv_header *tlvh, *next;
2125 	uint16_t sum, total;
2126 	uint16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh,
2127 			    uint16_t subtotal, uint16_t total) = NULL;
2128 
2129 	sum = 0;
2130 	total = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
2131 
2132 	for (tlvh = TLV_HDR_TOP(lsah); sum < total;
2133 	     tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
2134 		if (subfunc != NULL) {
2135 			sum = (*subfunc)(vty, tlvh, sum, total);
2136 			next = (struct tlv_header *)((char *)tlvh + sum);
2137 			subfunc = NULL;
2138 			continue;
2139 		}
2140 
2141 		next = NULL;
2142 		switch (ntohs(tlvh->type)) {
2143 		case TE_TLV_ROUTER_ADDR:
2144 			sum += show_vty_router_addr(vty, tlvh);
2145 			break;
2146 		case TE_TLV_LINK:
2147 			sum += show_vty_link_header(vty, tlvh);
2148 			subfunc = ospf_mpls_te_show_link_subtlv;
2149 			next = TLV_DATA(tlvh);
2150 			break;
2151 		default:
2152 			sum += show_vty_unknown_tlv(vty, tlvh);
2153 			break;
2154 		}
2155 	}
2156 	return;
2157 }
2158 
ospf_mpls_te_config_write_router(struct vty * vty)2159 static void ospf_mpls_te_config_write_router(struct vty *vty)
2160 {
2161 
2162 	if (OspfMplsTE.enabled) {
2163 		vty_out(vty, " mpls-te on\n");
2164 		vty_out(vty, " mpls-te router-address %s\n",
2165 			inet_ntoa(OspfMplsTE.router_addr.value));
2166 	}
2167 
2168 	if (OspfMplsTE.inter_as == AS)
2169 		vty_out(vty, "  mpls-te inter-as as\n");
2170 	if (OspfMplsTE.inter_as == Area)
2171 		vty_out(vty, "  mpls-te inter-as area %s \n",
2172 			inet_ntoa(OspfMplsTE.interas_areaid));
2173 
2174 	return;
2175 }
2176 
2177 /*------------------------------------------------------------------------*
2178  * Followings are vty command functions.
2179  *------------------------------------------------------------------------*/
2180 
2181 DEFUN (ospf_mpls_te_on,
2182        ospf_mpls_te_on_cmd,
2183        "mpls-te on",
2184        MPLS_TE_STR
2185        "Enable the MPLS-TE functionality\n")
2186 {
2187 	VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
2188 	struct listnode *node;
2189 	struct mpls_te_link *lp;
2190 
2191 	if (OspfMplsTE.enabled)
2192 		return CMD_SUCCESS;
2193 
2194 	if (IS_DEBUG_OSPF_EVENT)
2195 		zlog_debug("MPLS-TE: OFF -> ON");
2196 
2197 	OspfMplsTE.enabled = true;
2198 
2199 	/* Reoriginate RFC3630 & RFC6827 Links */
2200 	ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
2201 				  REORIGINATE_THIS_LSA);
2202 
2203 	/* Reoriginate LSA if INTER-AS is always on */
2204 	if (OspfMplsTE.inter_as != Off) {
2205 		for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) {
2206 			if (IS_INTER_AS(lp->type)) {
2207 				ospf_mpls_te_lsa_schedule(lp,
2208 							  REORIGINATE_THIS_LSA);
2209 			}
2210 		}
2211 	}
2212 
2213 	return CMD_SUCCESS;
2214 }
2215 
2216 DEFUN (no_ospf_mpls_te,
2217        no_ospf_mpls_te_cmd,
2218        "no mpls-te [on]",
2219        NO_STR
2220        MPLS_TE_STR
2221        "Disable the MPLS-TE functionality\n")
2222 {
2223 	VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
2224 	struct listnode *node, *nnode;
2225 	struct mpls_te_link *lp;
2226 
2227 	if (!OspfMplsTE.enabled)
2228 		return CMD_SUCCESS;
2229 
2230 	if (IS_DEBUG_OSPF_EVENT)
2231 		zlog_debug("MPLS-TE: ON -> OFF");
2232 
2233 	OspfMplsTE.enabled = false;
2234 
2235 	for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
2236 		if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
2237 			ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
2238 
2239 	/*
2240 	 * This resets the OspfMplsTE.inter_as to its initial state.
2241 	 * This is to avoid having an inter-as value different from
2242 	 * Off when mpls-te gets restarted (after being removed)
2243 	 */
2244 	if (OspfMplsTE.inter_as != Off) {
2245 		/* Deregister the Callbacks for Inter-AS support */
2246 		ospf_mpls_te_unregister();
2247 		OspfMplsTE.inter_as = Off;
2248 	}
2249 
2250 	return CMD_SUCCESS;
2251 }
2252 
2253 
2254 DEFUN (ospf_mpls_te_router_addr,
2255        ospf_mpls_te_router_addr_cmd,
2256        "mpls-te router-address A.B.C.D",
2257        MPLS_TE_STR
2258        "Stable IP address of the advertising router\n"
2259        "MPLS-TE router address in IPv4 address format\n")
2260 {
2261 	VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
2262 	int idx_ipv4 = 2;
2263 	struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
2264 	struct in_addr value;
2265 
2266 	if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
2267 		vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
2268 		return CMD_WARNING;
2269 	}
2270 
2271 	if (ntohs(ra->header.type) == 0
2272 	    || ntohl(ra->value.s_addr) != ntohl(value.s_addr)) {
2273 		struct listnode *node, *nnode;
2274 		struct mpls_te_link *lp;
2275 		int need_to_reoriginate = 0;
2276 
2277 		set_mpls_te_router_addr(value);
2278 
2279 		if (!OspfMplsTE.enabled)
2280 			return CMD_SUCCESS;
2281 
2282 		for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
2283 			if ((lp->area == NULL) || IS_FLOOD_AS(lp->type))
2284 				continue;
2285 
2286 			if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
2287 				need_to_reoriginate = 1;
2288 				break;
2289 			}
2290 		}
2291 
2292 		for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
2293 			if ((lp->area == NULL) || IS_FLOOD_AS(lp->type))
2294 				continue;
2295 
2296 			if (need_to_reoriginate)
2297 				SET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
2298 			else
2299 				ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
2300 		}
2301 
2302 		if (need_to_reoriginate)
2303 			ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
2304 						  REORIGINATE_THIS_LSA);
2305 	}
2306 
2307 	return CMD_SUCCESS;
2308 }
2309 
set_inter_as_mode(struct vty * vty,const char * mode_name,const char * area_id)2310 static int set_inter_as_mode(struct vty *vty, const char *mode_name,
2311 			     const char *area_id)
2312 {
2313 	enum inter_as_mode mode;
2314 	struct listnode *node;
2315 	struct mpls_te_link *lp;
2316 	int format;
2317 
2318 	if (OspfMplsTE.enabled) {
2319 
2320 		/* Read and Check inter_as mode */
2321 		if (strcmp(mode_name, "as") == 0)
2322 			mode = AS;
2323 		else if (strcmp(mode_name, "area") == 0) {
2324 			mode = Area;
2325 			VTY_GET_OSPF_AREA_ID(OspfMplsTE.interas_areaid, format,
2326 					     area_id);
2327 		} else {
2328 			vty_out(vty,
2329 				"Unknown mode. Please choose between as or area\n");
2330 			return CMD_WARNING;
2331 		}
2332 
2333 		if (IS_DEBUG_OSPF_EVENT)
2334 			zlog_debug(
2335 				"MPLS-TE: Inter-AS enable with %s flooding support",
2336 				mode2text[mode]);
2337 
2338 		/* Register new callbacks regarding the flooding scope (AS or
2339 		 * Area) */
2340 		if (ospf_mpls_te_register(mode) < 0) {
2341 			vty_out(vty,
2342 				"Internal error: Unable to register Inter-AS functions\n");
2343 			return CMD_WARNING;
2344 		}
2345 
2346 		/* Enable mode and re-originate LSA if needed */
2347 		if ((OspfMplsTE.inter_as == Off)
2348 		    && (mode != OspfMplsTE.inter_as)) {
2349 			OspfMplsTE.inter_as = mode;
2350 			/* Re-originate all InterAS-TEv2 LSA */
2351 			for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node,
2352 						  lp)) {
2353 				if (IS_INTER_AS(lp->type)) {
2354 					if (mode == AS)
2355 						lp->type |= FLOOD_AS;
2356 					else
2357 						lp->type |= FLOOD_AREA;
2358 					ospf_mpls_te_lsa_schedule(
2359 						lp, REORIGINATE_THIS_LSA);
2360 				}
2361 			}
2362 		} else {
2363 			vty_out(vty,
2364 				"Please change Inter-AS support to disable first before going to mode %s\n",
2365 				mode2text[mode]);
2366 			return CMD_WARNING;
2367 		}
2368 	} else {
2369 		vty_out(vty, "mpls-te has not been turned on\n");
2370 		return CMD_WARNING;
2371 	}
2372 	return CMD_SUCCESS;
2373 }
2374 
2375 
2376 DEFUN (ospf_mpls_te_inter_as_as,
2377        ospf_mpls_te_inter_as_cmd,
2378        "mpls-te inter-as as",
2379        MPLS_TE_STR
2380        "Configure MPLS-TE Inter-AS support\n"
2381        "AS native mode self originate INTER_AS LSA with Type 11 (as flooding scope)\n")
2382 {
2383 	return set_inter_as_mode(vty, "as", "");
2384 }
2385 
2386 DEFUN (ospf_mpls_te_inter_as_area,
2387        ospf_mpls_te_inter_as_area_cmd,
2388        "mpls-te inter-as area <A.B.C.D|(0-4294967295)>",
2389        MPLS_TE_STR
2390        "Configure MPLS-TE Inter-AS support\n"
2391        "AREA native mode self originate INTER_AS LSA with Type 10 (area flooding scope)\n"
2392        "OSPF area ID in IP format\n"
2393        "OSPF area ID as decimal value\n")
2394 {
2395 	int idx_ipv4_number = 3;
2396 	return set_inter_as_mode(vty, "area", argv[idx_ipv4_number]->arg);
2397 }
2398 
2399 DEFUN (no_ospf_mpls_te_inter_as,
2400        no_ospf_mpls_te_inter_as_cmd,
2401        "no mpls-te inter-as",
2402        NO_STR
2403        MPLS_TE_STR
2404        "Disable MPLS-TE Inter-AS support\n")
2405 {
2406 
2407 	struct listnode *node, *nnode;
2408 	struct mpls_te_link *lp;
2409 
2410 	if (IS_DEBUG_OSPF_EVENT)
2411 		zlog_debug("MPLS-TE: Inter-AS support OFF");
2412 
2413 	if ((OspfMplsTE.enabled) && (OspfMplsTE.inter_as != Off)) {
2414 		/* Flush all Inter-AS LSA */
2415 		for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
2416 			if (IS_INTER_AS(lp->type)
2417 			    && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
2418 				ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
2419 
2420 		/* Deregister the Callbacks for Inter-AS support */
2421 		ospf_mpls_te_unregister();
2422 		OspfMplsTE.inter_as = Off;
2423 	}
2424 
2425 	return CMD_SUCCESS;
2426 }
2427 
2428 DEFUN (show_ip_ospf_mpls_te_router,
2429        show_ip_ospf_mpls_te_router_cmd,
2430        "show ip ospf mpls-te router",
2431        SHOW_STR
2432        IP_STR
2433        OSPF_STR
2434        "MPLS-TE information\n"
2435        "MPLS-TE Router parameters\n")
2436 {
2437 	if (OspfMplsTE.enabled) {
2438 		vty_out(vty, "--- MPLS-TE router parameters ---\n");
2439 
2440 		if (ntohs(OspfMplsTE.router_addr.header.type) != 0)
2441 			show_vty_router_addr(vty,
2442 					     &OspfMplsTE.router_addr.header);
2443 		else
2444 			vty_out(vty, "  N/A\n");
2445 	}
2446 	return CMD_SUCCESS;
2447 }
2448 
show_mpls_te_link_sub(struct vty * vty,struct interface * ifp)2449 static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp)
2450 {
2451 	struct mpls_te_link *lp;
2452 
2453 	if ((OspfMplsTE.enabled) && HAS_LINK_PARAMS(ifp) && !if_is_loopback(ifp)
2454 	    && if_is_up(ifp)
2455 	    && ((lp = lookup_linkparams_by_ifp(ifp)) != NULL)) {
2456 		/* Continue only if interface is not passive or support Inter-AS
2457 		 * TEv2 */
2458 		if (!(ospf_oi_count(ifp) > 0)) {
2459 			if (IS_INTER_AS(lp->type)) {
2460 				vty_out(vty,
2461 					"-- Inter-AS TEv2 link parameters for %s --\n",
2462 					ifp->name);
2463 			} else {
2464 				/* MPLS-TE is not activate on this interface */
2465 				/* or this interface is passive and Inter-AS
2466 				 * TEv2 is not activate */
2467 				vty_out(vty,
2468 					"  %s: MPLS-TE is disabled on this interface\n",
2469 					ifp->name);
2470 				return;
2471 			}
2472 		} else {
2473 			vty_out(vty, "-- MPLS-TE link parameters for %s --\n",
2474 				ifp->name);
2475 		}
2476 
2477 		if (TLV_TYPE(lp->link_type) != 0)
2478 			show_vty_link_subtlv_link_type(vty,
2479 						       &lp->link_type.header);
2480 		if (TLV_TYPE(lp->link_id) != 0)
2481 			show_vty_link_subtlv_link_id(vty, &lp->link_id.header);
2482 		if (TLV_TYPE(lp->lclif_ipaddr) != 0)
2483 			show_vty_link_subtlv_lclif_ipaddr(
2484 				vty, &lp->lclif_ipaddr.header);
2485 		if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
2486 			show_vty_link_subtlv_rmtif_ipaddr(
2487 				vty, &lp->rmtif_ipaddr.header);
2488 		if (TLV_TYPE(lp->rip) != 0)
2489 			show_vty_link_subtlv_rip(vty, &lp->rip.header);
2490 		if (TLV_TYPE(lp->ras) != 0)
2491 			show_vty_link_subtlv_ras(vty, &lp->ras.header);
2492 		if (TLV_TYPE(lp->te_metric) != 0)
2493 			show_vty_link_subtlv_te_metric(vty,
2494 						       &lp->te_metric.header);
2495 		if (TLV_TYPE(lp->max_bw) != 0)
2496 			show_vty_link_subtlv_max_bw(vty, &lp->max_bw.header);
2497 		if (TLV_TYPE(lp->max_rsv_bw) != 0)
2498 			show_vty_link_subtlv_max_rsv_bw(vty,
2499 							&lp->max_rsv_bw.header);
2500 		if (TLV_TYPE(lp->unrsv_bw) != 0)
2501 			show_vty_link_subtlv_unrsv_bw(vty,
2502 						      &lp->unrsv_bw.header);
2503 		if (TLV_TYPE(lp->rsc_clsclr) != 0)
2504 			show_vty_link_subtlv_rsc_clsclr(vty,
2505 							&lp->rsc_clsclr.header);
2506 		if (TLV_TYPE(lp->av_delay) != 0)
2507 			show_vty_link_subtlv_av_delay(vty,
2508 						      &lp->av_delay.header);
2509 		if (TLV_TYPE(lp->mm_delay) != 0)
2510 			show_vty_link_subtlv_mm_delay(vty,
2511 						      &lp->mm_delay.header);
2512 		if (TLV_TYPE(lp->delay_var) != 0)
2513 			show_vty_link_subtlv_delay_var(vty,
2514 						       &lp->delay_var.header);
2515 		if (TLV_TYPE(lp->pkt_loss) != 0)
2516 			show_vty_link_subtlv_pkt_loss(vty,
2517 						      &lp->pkt_loss.header);
2518 		if (TLV_TYPE(lp->res_bw) != 0)
2519 			show_vty_link_subtlv_res_bw(vty, &lp->res_bw.header);
2520 		if (TLV_TYPE(lp->ava_bw) != 0)
2521 			show_vty_link_subtlv_ava_bw(vty, &lp->ava_bw.header);
2522 		if (TLV_TYPE(lp->use_bw) != 0)
2523 			show_vty_link_subtlv_use_bw(vty, &lp->use_bw.header);
2524 		vty_out(vty, "---------------\n\n");
2525 	} else {
2526 		vty_out(vty, "  %s: MPLS-TE is disabled on this interface\n",
2527 			ifp->name);
2528 	}
2529 
2530 	return;
2531 }
2532 
2533 DEFUN (show_ip_ospf_mpls_te_link,
2534        show_ip_ospf_mpls_te_link_cmd,
2535        "show ip ospf [vrf <NAME|all>] mpls-te interface [INTERFACE]",
2536        SHOW_STR
2537        IP_STR
2538        OSPF_STR
2539        VRF_CMD_HELP_STR
2540        "All VRFs\n"
2541        "MPLS-TE information\n"
2542        "Interface information\n"
2543        "Interface name\n")
2544 {
2545 	struct vrf *vrf;
2546 	int idx_interface = 0;
2547 	struct interface *ifp = NULL;
2548 	struct listnode *node;
2549 	char *vrf_name = NULL;
2550 	bool all_vrf = false;
2551 	int inst = 0;
2552 	int idx_vrf = 0;
2553 	struct ospf *ospf = NULL;
2554 
2555 	if (argv_find(argv, argc, "vrf", &idx_vrf)) {
2556 		vrf_name = argv[idx_vrf + 1]->arg;
2557 		all_vrf = strmatch(vrf_name, "all");
2558 	}
2559 	argv_find(argv, argc, "INTERFACE", &idx_interface);
2560 	/* vrf input is provided could be all or specific vrf*/
2561 	if (vrf_name) {
2562 		if (all_vrf) {
2563 			for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
2564 				if (!ospf->oi_running)
2565 					continue;
2566 				vrf = vrf_lookup_by_id(ospf->vrf_id);
2567 				FOR_ALL_INTERFACES (vrf, ifp)
2568 					show_mpls_te_link_sub(vty, ifp);
2569 			}
2570 			return CMD_SUCCESS;
2571 		}
2572 		ospf = ospf_lookup_by_inst_name(inst, vrf_name);
2573 	} else
2574 		ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2575 	if (ospf == NULL || !ospf->oi_running)
2576 		return CMD_SUCCESS;
2577 
2578 	vrf = vrf_lookup_by_id(ospf->vrf_id);
2579 	if (!vrf)
2580 		return CMD_SUCCESS;
2581 	if (idx_interface) {
2582 		ifp = if_lookup_by_name(
2583 					argv[idx_interface]->arg,
2584 					ospf->vrf_id);
2585 		if (ifp == NULL) {
2586 			vty_out(vty, "No such interface name in vrf %s\n",
2587 				vrf->name);
2588 			return CMD_SUCCESS;
2589 		}
2590 	}
2591 	if (!ifp) {
2592 		FOR_ALL_INTERFACES (vrf, ifp)
2593 			show_mpls_te_link_sub(vty, ifp);
2594 		return CMD_SUCCESS;
2595 	}
2596 
2597 	show_mpls_te_link_sub(vty, ifp);
2598 	return CMD_SUCCESS;
2599 }
2600 
ospf_mpls_te_register_vty(void)2601 static void ospf_mpls_te_register_vty(void)
2602 {
2603 	install_element(VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd);
2604 	install_element(VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd);
2605 
2606 	install_element(OSPF_NODE, &ospf_mpls_te_on_cmd);
2607 	install_element(OSPF_NODE, &no_ospf_mpls_te_cmd);
2608 	install_element(OSPF_NODE, &ospf_mpls_te_router_addr_cmd);
2609 	install_element(OSPF_NODE, &ospf_mpls_te_inter_as_cmd);
2610 	install_element(OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd);
2611 	install_element(OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd);
2612 
2613 	return;
2614 }
2615