blob: 47771a155beeb9ada9a9c6d9d56dd326603077d6 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
Olivier Dugeon29a14012016-04-19 18:42:40 +02002 * This is an implementation of RFC3630
paul718e3742002-12-13 20:15:29 +00003 * Copyright (C) 2001 KDD R&D Laboratories, Inc.
4 * http://www.kddlabs.co.jp/
5 *
Olivier Dugeon29a14012016-04-19 18:42:40 +02006 * Copyright (C) 2012 Orange Labs
7 * http://www.orange.com
8 *
paul718e3742002-12-13 20:15:29 +00009 * 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
22 * along with GNU Zebra; see the file COPYING. If not, write to the Free
23 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 * 02111-1307, USA.
25 */
26
Olivier Dugeon29a14012016-04-19 18:42:40 +020027/* Add support of RFC7471 */
28/* Add support of RFC5392, RFC6827 */
paul718e3742002-12-13 20:15:29 +000029
30#include <zebra.h>
Olivier Dugeon29a14012016-04-19 18:42:40 +020031#include <math.h>
paul718e3742002-12-13 20:15:29 +000032
paul718e3742002-12-13 20:15:29 +000033#include "linklist.h"
34#include "prefix.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() */
Paul Jakma43595012015-05-19 18:50:49 +010045#include "network.h"
paul718e3742002-12-13 20:15:29 +000046
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"
Olivier Dugeon29a14012016-04-19 18:42:40 +020063#include "ospfd/ospf_vty.h"
paul718e3742002-12-13 20:15:29 +000064
65/*
66 * Global variable to manage Opaque-LSA/MPLS-TE on this node.
67 * Note that all parameter values are stored in network byte order.
68 */
Olivier Dugeon29a14012016-04-19 18:42:40 +020069struct ospf_mpls_te OspfMplsTE;
paul718e3742002-12-13 20:15:29 +000070
Olivier Dugeon29a14012016-04-19 18:42:40 +020071const char *mode2text[] = { "Disable", "AS", "Area", "Emulate" };
72
73enum oifstate
74{
paul718e3742002-12-13 20:15:29 +000075 OI_ANY, OI_DOWN, OI_UP
76};
77
paul718e3742002-12-13 20:15:29 +000078/*------------------------------------------------------------------------*
79 * Followings are initialize/terminate functions for MPLS-TE handling.
80 *------------------------------------------------------------------------*/
81
82static int ospf_mpls_te_new_if (struct interface *ifp);
83static int ospf_mpls_te_del_if (struct interface *ifp);
Olivier Dugeon29a14012016-04-19 18:42:40 +020084static void ospf_mpls_te_ism_change (struct ospf_interface *oi,
85 int old_status);
paul718e3742002-12-13 20:15:29 +000086static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status);
87static void ospf_mpls_te_config_write_router (struct vty *vty);
paul718e3742002-12-13 20:15:29 +000088static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa);
Olivier Dugeon29a14012016-04-19 18:42:40 +020089static int ospf_mpls_te_lsa_originate_area (void *arg);
90static int ospf_mpls_te_lsa_originate_as (void *arg);
Paul Jakma072990e2011-04-11 16:28:16 +010091static struct ospf_lsa *ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);
paul718e3742002-12-13 20:15:29 +000092
93static void del_mpls_te_link (void *val);
94static void ospf_mpls_te_register_vty (void);
95
96int
97ospf_mpls_te_init (void)
98{
99 int rc;
100
101 rc = ospf_register_opaque_functab (
102 OSPF_OPAQUE_AREA_LSA,
103 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
104 ospf_mpls_te_new_if,
105 ospf_mpls_te_del_if,
106 ospf_mpls_te_ism_change,
107 ospf_mpls_te_nsm_change,
108 ospf_mpls_te_config_write_router,
Olivier Dugeon29a14012016-04-19 18:42:40 +0200109 NULL,/*ospf_mpls_te_config_write_if */
paul718e3742002-12-13 20:15:29 +0000110 NULL,/* ospf_mpls_te_config_write_debug */
111 ospf_mpls_te_show_info,
Olivier Dugeon29a14012016-04-19 18:42:40 +0200112 ospf_mpls_te_lsa_originate_area,
paul718e3742002-12-13 20:15:29 +0000113 ospf_mpls_te_lsa_refresh,
114 NULL,/* ospf_mpls_te_new_lsa_hook */
115 NULL /* ospf_mpls_te_del_lsa_hook */);
116 if (rc != 0)
117 {
Olivier Dugeon29a14012016-04-19 18:42:40 +0200118 zlog_warn ("ospf_mpls_te_init: Failed to register Traffic Engineering functions");
paul718e3742002-12-13 20:15:29 +0000119 goto out;
120 }
121
122 memset (&OspfMplsTE, 0, sizeof (struct ospf_mpls_te));
123 OspfMplsTE.status = disabled;
Olivier Dugeon29a14012016-04-19 18:42:40 +0200124 OspfMplsTE.inter_as = Disable;
paul718e3742002-12-13 20:15:29 +0000125 OspfMplsTE.iflist = list_new ();
126 OspfMplsTE.iflist->del = del_mpls_te_link;
127
128 ospf_mpls_te_register_vty ();
129
130out:
131 return rc;
132}
133
Olivier Dugeon29a14012016-04-19 18:42:40 +0200134/* Additional register for RFC5392 support */
135static int
136ospf_mpls_te_register (enum inter_as_mode mode)
137{
138 int rc;
139 u_int8_t scope;
140
141 if (OspfMplsTE.inter_as != Disable)
142 return 0;
143
144 if (mode == AS)
145 scope = OSPF_OPAQUE_AS_LSA;
146 else
147 scope = OSPF_OPAQUE_AREA_LSA;
148
149 rc = ospf_register_opaque_functab (scope,
150 OPAQUE_TYPE_INTER_AS_LSA,
151 NULL,
152 NULL,
153 NULL,
154 NULL,
155 NULL,
156 NULL,
157 NULL,
158 ospf_mpls_te_show_info,
159 ospf_mpls_te_lsa_originate_as,
160 ospf_mpls_te_lsa_refresh, NULL, NULL);
161
162 if (rc != 0)
163 {
164 zlog_warn ("ospf_router_info_init: Failed to register Inter-AS functions");
165 return rc;
166 }
167
168 return 0;
169}
170
171static int
172ospf_mpls_te_unregister ()
173{
174 u_int8_t scope;
175
176 if (OspfMplsTE.inter_as == Disable)
177 return 0;
178
179 if (OspfMplsTE.inter_as == AS)
180 scope = OSPF_OPAQUE_AS_LSA;
181 else
182 scope = OSPF_OPAQUE_AREA_LSA;
183
184 ospf_delete_opaque_functab (scope, OPAQUE_TYPE_INTER_AS_LSA);
185
186 return 0;
187
188}
189
paul718e3742002-12-13 20:15:29 +0000190void
191ospf_mpls_te_term (void)
192{
193 list_delete (OspfMplsTE.iflist);
paul718e3742002-12-13 20:15:29 +0000194 OspfMplsTE.iflist = NULL;
paul718e3742002-12-13 20:15:29 +0000195
196 ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA,
197 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
Olivier Dugeon29a14012016-04-19 18:42:40 +0200198 OspfMplsTE.status = disabled;
199
200 ospf_mpls_te_unregister ();
201 OspfMplsTE.inter_as = Disable;
202
paul718e3742002-12-13 20:15:29 +0000203 return;
204}
205
206/*------------------------------------------------------------------------*
207 * Followings are control functions for MPLS-TE parameters management.
208 *------------------------------------------------------------------------*/
209
210static void
211del_mpls_te_link (void *val)
212{
Olivier Dugeon29a14012016-04-19 18:42:40 +0200213 XFREE (MTYPE_OSPF_MPLS_TE, val);
paul718e3742002-12-13 20:15:29 +0000214 return;
215}
216
Olivier Dugeon29a14012016-04-19 18:42:40 +0200217u_int32_t
paul4dadc292005-05-06 21:37:42 +0000218get_mpls_te_instance_value (void)
paul718e3742002-12-13 20:15:29 +0000219{
220 static u_int32_t seqno = 0;
221
Andrew Certain703819a2012-12-04 13:36:41 -0800222 if (seqno < MAX_LEGAL_TE_INSTANCE_NUM )
paul718e3742002-12-13 20:15:29 +0000223 seqno += 1;
224 else
225 seqno = 1; /* Avoid zero. */
226
227 return seqno;
228}
229
230static struct ospf_interface *
231lookup_oi_by_ifp (struct interface *ifp,
232 struct ospf_area *area, enum oifstate oifstate)
233{
234 struct ospf_interface *oi = NULL;
235 struct route_node *rn;
236
237 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
238 {
239 if ((oi = rn->info) == NULL)
240 continue;
241
242 switch (oifstate)
243 {
244 case OI_ANY:
245 break;
246 case OI_DOWN:
247 if (ospf_if_is_enable (oi))
248 continue;
249 break;
250 case OI_UP:
251 if (! ospf_if_is_enable (oi))
252 continue;
253 break;
254 default:
255 zlog_warn ("lookup_oi_by_ifp: Unknown oifstate: %x", oifstate);
256 goto out;
257 }
258
259 if (area == NULL || oi->area == area)
260 return oi;
261 }
262out:
263 return NULL;
264}
265
266static struct mpls_te_link *
267lookup_linkparams_by_ifp (struct interface *ifp)
268{
paul1eb8ef22005-04-07 07:30:20 +0000269 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000270 struct mpls_te_link *lp;
271
paul1eb8ef22005-04-07 07:30:20 +0000272 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul87d6f872004-09-24 08:01:38 +0000273 if (lp->ifp == ifp)
274 return lp;
paul718e3742002-12-13 20:15:29 +0000275
276 return NULL;
277}
278
279static struct mpls_te_link *
280lookup_linkparams_by_instance (struct ospf_lsa *lsa)
281{
paul87d6f872004-09-24 08:01:38 +0000282 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000283 struct mpls_te_link *lp;
paul6c835672004-10-11 11:00:30 +0000284 unsigned int key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
paul718e3742002-12-13 20:15:29 +0000285
paul1eb8ef22005-04-07 07:30:20 +0000286 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
paul87d6f872004-09-24 08:01:38 +0000287 if (lp->instance == key)
288 return lp;
paul718e3742002-12-13 20:15:29 +0000289
290 zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key);
291 return NULL;
292}
293
294static void
Olivier Dugeon29a14012016-04-19 18:42:40 +0200295ospf_mpls_te_foreach_area (void (*func)
296 (struct mpls_te_link * lp, opcode_t sched_opcode),
297 opcode_t sched_opcode)
paul718e3742002-12-13 20:15:29 +0000298{
paul1eb8ef22005-04-07 07:30:20 +0000299 struct listnode *node, *nnode;
300 struct listnode *node2;
paul718e3742002-12-13 20:15:29 +0000301 struct mpls_te_link *lp;
302 struct ospf_area *area;
303
paul1eb8ef22005-04-07 07:30:20 +0000304 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul718e3742002-12-13 20:15:29 +0000305 {
Olivier Dugeon29a14012016-04-19 18:42:40 +0200306 /* Skip Inter-AS TEv2 Links */
307 if (IS_INTER_AS (lp->type))
308 continue;
paul718e3742002-12-13 20:15:29 +0000309 if ((area = lp->area) == NULL)
310 continue;
Olivier Dugeon29a14012016-04-19 18:42:40 +0200311 if CHECK_FLAG (lp->flags, LPFLG_LOOKUP_DONE) continue;
paul718e3742002-12-13 20:15:29 +0000312
313 if (func != NULL)
314 (* func)(lp, sched_opcode);
315
paul1eb8ef22005-04-07 07:30:20 +0000316 for (node2 = listnextnode (node); node2; node2 = listnextnode (node2))
317 if ((lp = listgetdata (node2)) != NULL)
paul718e3742002-12-13 20:15:29 +0000318 if (lp->area != NULL)
319 if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
Olivier Dugeon29a14012016-04-19 18:42:40 +0200320 SET_FLAG (lp->flags, LPFLG_LOOKUP_DONE);
paul718e3742002-12-13 20:15:29 +0000321 }
322
paul1eb8ef22005-04-07 07:30:20 +0000323 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
paul87d6f872004-09-24 08:01:38 +0000324 if (lp->area != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +0200325 UNSET_FLAG (lp->flags, LPFLG_LOOKUP_DONE);
paul718e3742002-12-13 20:15:29 +0000326
327 return;
328}
329
330static void
331set_mpls_te_router_addr (struct in_addr ipv4)
332{
333 OspfMplsTE.router_addr.header.type = htons (TE_TLV_ROUTER_ADDR);
Olivier Dugeon29a14012016-04-19 18:42:40 +0200334 OspfMplsTE.router_addr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
paul718e3742002-12-13 20:15:29 +0000335 OspfMplsTE.router_addr.value = ipv4;
336 return;
337}
338
339static void
340set_linkparams_link_header (struct mpls_te_link *lp)
341{
paul718e3742002-12-13 20:15:29 +0000342 u_int16_t length = 0;
343
344 /* TE_LINK_SUBTLV_LINK_TYPE */
345 if (ntohs (lp->link_type.header.type) != 0)
346 length += TLV_SIZE (&lp->link_type.header);
347
348 /* TE_LINK_SUBTLV_LINK_ID */
349 if (ntohs (lp->link_id.header.type) != 0)
350 length += TLV_SIZE (&lp->link_id.header);
351
352 /* TE_LINK_SUBTLV_LCLIF_IPADDR */
Olivier Dugeon29a14012016-04-19 18:42:40 +0200353 if (lp->lclif_ipaddr.header.type != 0)
354 length += TLV_SIZE (&lp->lclif_ipaddr.header);
paul718e3742002-12-13 20:15:29 +0000355
356 /* TE_LINK_SUBTLV_RMTIF_IPADDR */
Olivier Dugeon29a14012016-04-19 18:42:40 +0200357 if (lp->rmtif_ipaddr.header.type != 0)
358 length += TLV_SIZE (&lp->rmtif_ipaddr.header);
paul718e3742002-12-13 20:15:29 +0000359
360 /* TE_LINK_SUBTLV_TE_METRIC */
361 if (ntohs (lp->te_metric.header.type) != 0)
362 length += TLV_SIZE (&lp->te_metric.header);
363
364 /* TE_LINK_SUBTLV_MAX_BW */
365 if (ntohs (lp->max_bw.header.type) != 0)
366 length += TLV_SIZE (&lp->max_bw.header);
367
368 /* TE_LINK_SUBTLV_MAX_RSV_BW */
369 if (ntohs (lp->max_rsv_bw.header.type) != 0)
370 length += TLV_SIZE (&lp->max_rsv_bw.header);
371
372 /* TE_LINK_SUBTLV_UNRSV_BW */
373 if (ntohs (lp->unrsv_bw.header.type) != 0)
374 length += TLV_SIZE (&lp->unrsv_bw.header);
375
376 /* TE_LINK_SUBTLV_RSC_CLSCLR */
377 if (ntohs (lp->rsc_clsclr.header.type) != 0)
378 length += TLV_SIZE (&lp->rsc_clsclr.header);
379
Olivier Dugeon29a14012016-04-19 18:42:40 +0200380 /* TE_LINK_SUBTLV_LLRI */
381 if (ntohs (lp->llri.header.type) != 0)
382 length += TLV_SIZE (&lp->llri.header);
383
384 /* TE_LINK_SUBTLV_RIP */
385 if (ntohs (lp->rip.header.type) != 0)
386 length += TLV_SIZE (&lp->rip.header);
387
388 /* TE_LINK_SUBTLV_RAS */
389 if (ntohs (lp->ras.header.type) != 0)
390 length += TLV_SIZE (&lp->ras.header);
391
392 /* TE_LINK_SUBTLV_LRRID */
393 if (ntohs (lp->lrrid.header.type) != 0)
394 length += TLV_SIZE (&lp->lrrid.header);
395
396 /* TE_LINK_SUBTLV_AV_DELAY */
397 if (ntohs (lp->av_delay.header.type) != 0)
398 length += TLV_SIZE (&lp->av_delay.header);
399
400 /* TE_LINK_SUBTLV_MM_DELAY */
401 if (ntohs (lp->mm_delay.header.type) != 0)
402 length += TLV_SIZE (&lp->mm_delay.header);
403
404 /* TE_LINK_SUBTLV_DELAY_VAR */
405 if (ntohs (lp->delay_var.header.type) != 0)
406 length += TLV_SIZE (&lp->delay_var.header);
407
408 /* TE_LINK_SUBTLV_PKT_LOSS */
409 if (ntohs (lp->pkt_loss.header.type) != 0)
410 length += TLV_SIZE (&lp->pkt_loss.header);
411
412 /* TE_LINK_SUBTLV_RES_BW */
413 if (ntohs (lp->res_bw.header.type) != 0)
414 length += TLV_SIZE (&lp->res_bw.header);
415
416 /* TE_LINK_SUBTLV_AVA_BW */
417 if (ntohs (lp->ava_bw.header.type) != 0)
418 length += TLV_SIZE (&lp->ava_bw.header);
419
420 /* TE_LINK_SUBTLV_USE_BW */
421 if (ntohs (lp->use_bw.header.type) != 0)
422 length += TLV_SIZE (&lp->use_bw.header);
423
paul718e3742002-12-13 20:15:29 +0000424 lp->link_header.header.type = htons (TE_TLV_LINK);
425 lp->link_header.header.length = htons (length);
426
427 return;
428}
429
430static void
431set_linkparams_link_type (struct ospf_interface *oi, struct mpls_te_link *lp)
432{
433 lp->link_type.header.type = htons (TE_LINK_SUBTLV_LINK_TYPE);
Olivier Dugeon29a14012016-04-19 18:42:40 +0200434 lp->link_type.header.length = htons (TE_LINK_SUBTLV_TYPE_SIZE);
paul718e3742002-12-13 20:15:29 +0000435
436 switch (oi->type)
437 {
438 case OSPF_IFTYPE_POINTOPOINT:
439 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP;
440 break;
441 case OSPF_IFTYPE_BROADCAST:
442 case OSPF_IFTYPE_NBMA:
443 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA;
444 break;
445 default:
446 /* Not supported yet. *//* XXX */
447 lp->link_type.header.type = htons (0);
448 break;
449 }
450 return;
451}
452
453static void
454set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp)
455{
456 struct ospf_neighbor *nbr;
457 int done = 0;
458
459 lp->link_id.header.type = htons (TE_LINK_SUBTLV_LINK_ID);
Olivier Dugeon29a14012016-04-19 18:42:40 +0200460 lp->link_id.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
paul718e3742002-12-13 20:15:29 +0000461
462 /*
463 * The Link ID is identical to the contents of the Link ID field
464 * in the Router LSA for these link types.
465 */
466 switch (oi->type)
467 {
468 case OSPF_IFTYPE_POINTOPOINT:
469 /* Take the router ID of the neighbor. */
Olivier Dugeon29a14012016-04-19 18:42:40 +0200470 if ((nbr = ospf_nbr_lookup_ptop (oi)) && nbr->state == NSM_Full)
paul718e3742002-12-13 20:15:29 +0000471 {
472 lp->link_id.value = nbr->router_id;
473 done = 1;
474 }
475 break;
476 case OSPF_IFTYPE_BROADCAST:
477 case OSPF_IFTYPE_NBMA:
478 /* Take the interface address of the designated router. */
479 if ((nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi))) == NULL)
480 break;
481
482 if (nbr->state == NSM_Full
483 || (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
pauld4a53d52003-07-12 21:30:57 +0000484 && ospf_nbr_count (oi, NSM_Full) > 0))
paul718e3742002-12-13 20:15:29 +0000485 {
486 lp->link_id.value = DR (oi);
487 done = 1;
488 }
489 break;
490 default:
491 /* Not supported yet. *//* XXX */
492 lp->link_id.header.type = htons (0);
493 break;
494 }
495
496 if (! done)
497 {
498 struct in_addr mask;
499 masklen2ip (oi->address->prefixlen, &mask);
500 lp->link_id.value.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
501 }
502 return;
503}
504
505static void
Olivier Dugeon29a14012016-04-19 18:42:40 +0200506set_linkparams_lclif_ipaddr (struct mpls_te_link *lp, struct in_addr lclif)
507{
508
509 lp->lclif_ipaddr.header.type = htons (TE_LINK_SUBTLV_LCLIF_IPADDR);
510 lp->lclif_ipaddr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
511 lp->lclif_ipaddr.value[0] = lclif;
512 return;
513}
514
515static void
516set_linkparams_rmtif_ipaddr (struct mpls_te_link *lp, struct in_addr rmtif)
517{
518
519 lp->rmtif_ipaddr.header.type = htons (TE_LINK_SUBTLV_RMTIF_IPADDR);
520 lp->rmtif_ipaddr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
521 lp->rmtif_ipaddr.value[0] = rmtif;
522 return;
523}
524
525static void
paul718e3742002-12-13 20:15:29 +0000526set_linkparams_te_metric (struct mpls_te_link *lp, u_int32_t te_metric)
527{
528 lp->te_metric.header.type = htons (TE_LINK_SUBTLV_TE_METRIC);
Olivier Dugeon29a14012016-04-19 18:42:40 +0200529 lp->te_metric.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
paul718e3742002-12-13 20:15:29 +0000530 lp->te_metric.value = htonl (te_metric);
531 return;
532}
533
534static void
Paul Jakma43595012015-05-19 18:50:49 +0100535set_linkparams_max_bw (struct mpls_te_link *lp, float fp)
paul718e3742002-12-13 20:15:29 +0000536{
537 lp->max_bw.header.type = htons (TE_LINK_SUBTLV_MAX_BW);
Olivier Dugeon29a14012016-04-19 18:42:40 +0200538 lp->max_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
Paul Jakma43595012015-05-19 18:50:49 +0100539 lp->max_bw.value = htonf (fp);
paul718e3742002-12-13 20:15:29 +0000540 return;
541}
542
543static void
Paul Jakma43595012015-05-19 18:50:49 +0100544set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float fp)
paul718e3742002-12-13 20:15:29 +0000545{
546 lp->max_rsv_bw.header.type = htons (TE_LINK_SUBTLV_MAX_RSV_BW);
Olivier Dugeon29a14012016-04-19 18:42:40 +0200547 lp->max_rsv_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
Paul Jakma43595012015-05-19 18:50:49 +0100548 lp->max_rsv_bw.value = htonf (fp);
paul718e3742002-12-13 20:15:29 +0000549 return;
550}
551
552static void
Paul Jakma43595012015-05-19 18:50:49 +0100553set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float fp)
paul718e3742002-12-13 20:15:29 +0000554{
555 /* Note that TLV-length field is the size of array. */
556 lp->unrsv_bw.header.type = htons (TE_LINK_SUBTLV_UNRSV_BW);
Olivier Dugeon29a14012016-04-19 18:42:40 +0200557 lp->unrsv_bw.header.length = htons (TE_LINK_SUBTLV_UNRSV_SIZE);
Paul Jakma43595012015-05-19 18:50:49 +0100558 lp->unrsv_bw.value [priority] = htonf (fp);
paul718e3742002-12-13 20:15:29 +0000559 return;
560}
561
562static void
563set_linkparams_rsc_clsclr (struct mpls_te_link *lp, u_int32_t classcolor)
564{
565 lp->rsc_clsclr.header.type = htons (TE_LINK_SUBTLV_RSC_CLSCLR);
Olivier Dugeon29a14012016-04-19 18:42:40 +0200566 lp->rsc_clsclr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
paul718e3742002-12-13 20:15:29 +0000567 lp->rsc_clsclr.value = htonl (classcolor);
568 return;
569}
570
571static void
Olivier Dugeon29a14012016-04-19 18:42:40 +0200572set_linkparams_inter_as (struct mpls_te_link *lp, struct in_addr addr,
573 u_int32_t as)
574{
575
576 /* Set the Remote ASBR IP address and then the associated AS number */
577 lp->rip.header.type = htons (TE_LINK_SUBTLV_RIP);
578 lp->rip.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
579 lp->rip.value = addr;
580
581 lp->ras.header.type = htons (TE_LINK_SUBTLV_RAS);
582 lp->ras.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
583 lp->ras.value = htonl (as);
584}
585
586static void
587unset_linkparams_inter_as (struct mpls_te_link *lp)
588{
589
590 /* Reset the Remote ASBR IP address and then the associated AS number */
591 lp->rip.header.type = htons (0);
592 lp->rip.header.length = htons (0);
593 lp->rip.value.s_addr = htonl (0);
594
595 lp->ras.header.type = htons (0);
596 lp->ras.header.length = htons (0);
597 lp->ras.value = htonl (0);
598}
599
600void
601set_linkparams_llri (struct mpls_te_link *lp, u_int32_t local,
602 u_int32_t remote)
603{
604
605 lp->llri.header.type = htons (TE_LINK_SUBTLV_LLRI);
606 lp->llri.header.length = htons (TE_LINK_SUBTLV_LLRI_SIZE);
607 lp->llri.local = htonl (local);
608 lp->llri.remote = htonl (remote);
609}
610
611void
612set_linkparams_lrrid (struct mpls_te_link *lp, struct in_addr local,
613 struct in_addr remote)
614{
615
616 lp->lrrid.header.type = htons (TE_LINK_SUBTLV_LRRID);
617 lp->lrrid.header.length = htons (TE_LINK_SUBTLV_LRRID_SIZE);
618 lp->lrrid.local.s_addr = local.s_addr;
619 lp->lrrid.remote.s_addr = remote.s_addr;
620}
621
622static void
623set_linkparams_av_delay (struct mpls_te_link *lp, u_int32_t delay, u_char anormal)
624{
625 u_int32_t tmp;
626 /* Note that TLV-length field is the size of array. */
627 lp->av_delay.header.type = htons (TE_LINK_SUBTLV_AV_DELAY);
628 lp->av_delay.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
629 tmp = delay & TE_EXT_MASK;
630 if (anormal)
631 tmp |= TE_EXT_ANORMAL;
632 lp->av_delay.value = htonl (tmp);
633 return;
634}
635
636static void
637set_linkparams_mm_delay (struct mpls_te_link *lp, u_int32_t low, u_int32_t high, u_char anormal)
638{
639 u_int32_t tmp;
640 /* Note that TLV-length field is the size of array. */
641 lp->mm_delay.header.type = htons (TE_LINK_SUBTLV_MM_DELAY);
642 lp->mm_delay.header.length = htons (TE_LINK_SUBTLV_MM_DELAY_SIZE);
643 tmp = low & TE_EXT_MASK;
644 if (anormal)
645 tmp |= TE_EXT_ANORMAL;
646 lp->mm_delay.low = htonl (tmp);
647 lp->mm_delay.high = htonl (high);
648 return;
649}
650
651static void
652set_linkparams_delay_var (struct mpls_te_link *lp, u_int32_t jitter)
653{
654 /* Note that TLV-length field is the size of array. */
655 lp->delay_var.header.type = htons (TE_LINK_SUBTLV_DELAY_VAR);
656 lp->delay_var.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
657 lp->delay_var.value = htonl (jitter & TE_EXT_MASK);
658 return;
659}
660
661static void
662set_linkparams_pkt_loss (struct mpls_te_link *lp, u_int32_t loss, u_char anormal)
663{
664 u_int32_t tmp;
665 /* Note that TLV-length field is the size of array. */
666 lp->pkt_loss.header.type = htons (TE_LINK_SUBTLV_PKT_LOSS);
667 lp->pkt_loss.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
668 tmp = loss & TE_EXT_MASK;
669 if (anormal)
670 tmp |= TE_EXT_ANORMAL;
671 lp->pkt_loss.value = htonl (tmp);
672 return;
673}
674
675static void
676set_linkparams_res_bw (struct mpls_te_link *lp, float fp)
677{
678 /* Note that TLV-length field is the size of array. */
679 lp->res_bw.header.type = htons (TE_LINK_SUBTLV_RES_BW);
680 lp->res_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
681 lp->res_bw.value = htonf (fp);
682 return;
683}
684
685static void
686set_linkparams_ava_bw (struct mpls_te_link *lp, float fp)
687{
688 /* Note that TLV-length field is the size of array. */
689 lp->ava_bw.header.type = htons (TE_LINK_SUBTLV_AVA_BW);
690 lp->ava_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
691 lp->ava_bw.value = htonf (fp);
692 return;
693}
694
695static void
696set_linkparams_use_bw (struct mpls_te_link *lp, float fp)
697{
698 /* Note that TLV-length field is the size of array. */
699 lp->use_bw.header.type = htons (TE_LINK_SUBTLV_USE_BW);
700 lp->use_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
701 lp->use_bw.value = htonf (fp);
702 return;
703}
704
705/* Update TE parameters from Interface */
706static void
707update_linkparams(struct mpls_te_link *lp)
708{
709 int i;
710 struct interface *ifp;
711
712 /* Get the Interface structure */
713 if ((ifp = lp->ifp) == NULL)
714 {
715 zlog_warn("OSPF MPLS-TE: Abort update TE parameters: no interface associated to Link Parameters");
716 return;
717 }
718 if (!HAS_LINK_PARAMS(ifp))
719 {
720 zlog_warn("OSPF MPLS-TE: Abort update TE parameters: no Link Parameters for interface");
721 return;
722 }
723
724 /* RFC3630 metrics */
725 if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
726 set_linkparams_rsc_clsclr (lp, ifp->link_params->admin_grp);
727 else
728 TLV_TYPE(lp->rsc_clsclr) = 0;
729
730 if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
731 set_linkparams_max_bw (lp, ifp->link_params->max_bw);
732 else
733 TLV_TYPE(lp->max_bw) = 0;
734
735 if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW))
736 set_linkparams_max_rsv_bw (lp, ifp->link_params->max_rsv_bw);
737 else
738 TLV_TYPE(lp->max_rsv_bw) = 0;
739
740 if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW))
741 for (i = 0; i < MAX_CLASS_TYPE; i++)
742 set_linkparams_unrsv_bw (lp, i, ifp->link_params->unrsv_bw[i]);
743 else
744 TLV_TYPE(lp->unrsv_bw) = 0;
745
746 if (IS_PARAM_SET(ifp->link_params, LP_TE))
747 set_linkparams_te_metric(lp, ifp->link_params->te_metric);
748 else
749 TLV_TYPE(lp->te_metric) = 0;
750
751 /* TE metric Extensions */
752 if (IS_PARAM_SET(ifp->link_params, LP_DELAY))
753 set_linkparams_av_delay(lp, ifp->link_params->av_delay, 0);
754 else
755 TLV_TYPE(lp->av_delay) = 0;
756
757 if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY))
758 set_linkparams_mm_delay(lp, ifp->link_params->min_delay, ifp->link_params->max_delay, 0);
759 else
760 TLV_TYPE(lp->mm_delay) = 0;
761
762 if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
763 set_linkparams_delay_var(lp, ifp->link_params->delay_var);
764 else
765 TLV_TYPE(lp->delay_var) = 0;
766
767 if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
768 set_linkparams_pkt_loss(lp, ifp->link_params->pkt_loss, 0);
769 else
770 TLV_TYPE(lp->pkt_loss) = 0;
771
772 if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
773 set_linkparams_res_bw(lp, ifp->link_params->res_bw);
774 else
775 TLV_TYPE(lp->res_bw) = 0;
776
777 if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
778 set_linkparams_ava_bw(lp, ifp->link_params->ava_bw);
779 else
780 TLV_TYPE(lp->ava_bw) = 0;
781
782 if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
783 set_linkparams_use_bw(lp, ifp->link_params->use_bw);
784 else
785 TLV_TYPE(lp->use_bw) = 0;
786
787 /* RFC5392 */
788 if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS))
789 {
790 /* Flush LSA if it engaged and was previously a STD_TE one */
791 if (IS_STD_TE(lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED))
792 {
793 if (IS_DEBUG_OSPF_TE)
794 zlog_debug("OSPF MPLS-TE Update IF: Switch from Standard LSA to INTER-AS for %s[%d/%d]",
795 ifp->name, lp->flags, lp->type);
796
797 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
798 /* Then, switch it to INTER-AS */
799 if (OspfMplsTE.inter_as == AS)
800 lp->flags = INTER_AS | FLOOD_AS;
801 else
802 {
803 lp->flags = INTER_AS | FLOOD_AREA;
804 lp->area = ospf_area_lookup_by_area_id (ospf_lookup(), OspfMplsTE.interas_areaid);
805 }
806 }
807 set_linkparams_inter_as(lp, ifp->link_params->rmt_ip, ifp->link_params->rmt_as);
808 }
809 else
810 {
811 if (IS_DEBUG_OSPF_TE)
812 zlog_debug("OSPF MPLS-TE Update IF: Switch from INTER-AS LSA to Standard for %s[%d/%d]",
813 ifp->name, lp->flags, lp->type);
814
815 /* reset inter-as TE params */
816 /* Flush LSA if it engaged and was previously an INTER_AS one */
817 if (IS_INTER_AS(lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED))
818 {
819 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
820 /* Then, switch it to Standard TE */
821 lp->flags = STD_TE | FLOOD_AREA;
822 }
823 unset_linkparams_inter_as (lp);
824 }
825}
826
827static void
paul718e3742002-12-13 20:15:29 +0000828initialize_linkparams (struct mpls_te_link *lp)
829{
830 struct interface *ifp = lp->ifp;
831 struct ospf_interface *oi;
Olivier Dugeon29a14012016-04-19 18:42:40 +0200832
833 if (IS_DEBUG_OSPF_TE)
834 zlog_debug("MPLS-TE(initialize_linkparams) Initialize Link Parameters for interface %s",
835 ifp->name);
paul718e3742002-12-13 20:15:29 +0000836
837 if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +0200838 {
839 zlog_warn("MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s",
840 ifp->name);
841 return;
842 }
paul718e3742002-12-13 20:15:29 +0000843
844 /*
845 * Try to set initial values those can be derived from
846 * zebra-interface information.
847 */
848 set_linkparams_link_type (oi, lp);
849
Olivier Dugeon29a14012016-04-19 18:42:40 +0200850 /* Set local IP addr */
851 set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4);
paul718e3742002-12-13 20:15:29 +0000852
Olivier Dugeon29a14012016-04-19 18:42:40 +0200853 /* Set Remote IP addr if Point to Point Interface */
854 if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP)
855 {
856 struct prefix *pref = CONNECTED_PREFIX(oi->connected);
857 if (pref != NULL)
858 set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
859 }
paul718e3742002-12-13 20:15:29 +0000860
Olivier Dugeon29a14012016-04-19 18:42:40 +0200861 /* Keep Area information in combination with link parameters. */
862 lp->area = oi->area;
paul718e3742002-12-13 20:15:29 +0000863
864 return;
865}
866
867static int
868is_mandated_params_set (struct mpls_te_link *lp)
869{
870 int rc = 0;
871
872 if (ntohs (OspfMplsTE.router_addr.header.type) == 0)
Olivier Dugeon29a14012016-04-19 18:42:40 +0200873 {
874 zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Router Address");
paul718e3742002-12-13 20:15:29 +0000875 goto out;
Olivier Dugeon29a14012016-04-19 18:42:40 +0200876 }
paul718e3742002-12-13 20:15:29 +0000877
878 if (ntohs (lp->link_type.header.type) == 0)
Olivier Dugeon29a14012016-04-19 18:42:40 +0200879 {
880 zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Link Type");
paul718e3742002-12-13 20:15:29 +0000881 goto out;
Olivier Dugeon29a14012016-04-19 18:42:40 +0200882 }
paul718e3742002-12-13 20:15:29 +0000883
Olivier Dugeon29a14012016-04-19 18:42:40 +0200884 if (!IS_INTER_AS (lp->type) && (ntohs (lp->link_id.header.type) == 0))
885 {
886 zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Link ID");
paul718e3742002-12-13 20:15:29 +0000887 goto out;
Olivier Dugeon29a14012016-04-19 18:42:40 +0200888 }
paul718e3742002-12-13 20:15:29 +0000889
890 rc = 1;
891out:
892 return rc;
893}
894
895/*------------------------------------------------------------------------*
896 * Followings are callback functions against generic Opaque-LSAs handling.
897 *------------------------------------------------------------------------*/
898
899static int
900ospf_mpls_te_new_if (struct interface *ifp)
901{
902 struct mpls_te_link *new;
903 int rc = -1;
904
Olivier Dugeon29a14012016-04-19 18:42:40 +0200905 if (IS_DEBUG_OSPF_TE)
906 zlog_debug ("MPLS-TE(ospf_mpls_te_new_if) Add new %s interface %s to MPLS-TE list",
907 ifp->link_params ? "Active" : "Inactive", ifp->name);
908
paul718e3742002-12-13 20:15:29 +0000909 if (lookup_linkparams_by_ifp (ifp) != NULL)
910 {
David Lampartereed3c482015-03-03 08:51:53 +0100911 zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", (void *)ifp);
paul718e3742002-12-13 20:15:29 +0000912 rc = 0; /* Do nothing here. */
913 goto out;
914 }
915
Olivier Dugeon29a14012016-04-19 18:42:40 +0200916 new = XCALLOC (MTYPE_OSPF_MPLS_TE, sizeof (struct mpls_te_link));
Stephen Hemminger393deb92008-08-18 14:13:29 -0700917 if (new == NULL)
paul718e3742002-12-13 20:15:29 +0000918 {
ajs6099b3b2004-11-20 02:06:59 +0000919 zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000920 goto out;
921 }
paul718e3742002-12-13 20:15:29 +0000922
paul718e3742002-12-13 20:15:29 +0000923 new->instance = get_mpls_te_instance_value ();
924 new->ifp = ifp;
Olivier Dugeon29a14012016-04-19 18:42:40 +0200925 /* By default TE-Link is RFC3630 compatible flooding in Area and not active */
926 /* This default behavior will be adapted with call to ospf_mpls_te_update_if() */
927 new->type = STD_TE | FLOOD_AREA;
928 new->flags = LPFLG_LSA_INACTIVE;
paul718e3742002-12-13 20:15:29 +0000929
Olivier Dugeon29a14012016-04-19 18:42:40 +0200930 /* Initialize Link Parameters from Interface */
931 initialize_linkparams(new);
paul718e3742002-12-13 20:15:29 +0000932
Olivier Dugeon29a14012016-04-19 18:42:40 +0200933 /* Set TE Parameters from Interface */
934 update_linkparams(new);
935
936 /* Add Link Parameters structure to the list */
paul718e3742002-12-13 20:15:29 +0000937 listnode_add (OspfMplsTE.iflist, new);
938
Olivier Dugeon29a14012016-04-19 18:42:40 +0200939 if (IS_DEBUG_OSPF_TE)
940 zlog_debug("OSPF MPLS-TE New IF: Add new LP context for %s[%d/%d]",
941 ifp->name, new->flags, new->type);
942
paul718e3742002-12-13 20:15:29 +0000943 /* Schedule Opaque-LSA refresh. *//* XXX */
944
945 rc = 0;
946out:
947 return rc;
948}
949
950static int
951ospf_mpls_te_del_if (struct interface *ifp)
952{
953 struct mpls_te_link *lp;
954 int rc = -1;
955
956 if ((lp = lookup_linkparams_by_ifp (ifp)) != NULL)
957 {
paul87d6f872004-09-24 08:01:38 +0000958 struct list *iflist = OspfMplsTE.iflist;
paul718e3742002-12-13 20:15:29 +0000959
960 /* Dequeue listnode entry from the list. */
961 listnode_delete (iflist, lp);
962
963 /* Avoid misjudgement in the next lookup. */
964 if (listcount (iflist) == 0)
965 iflist->head = iflist->tail = NULL;
966
Olivier Dugeon29a14012016-04-19 18:42:40 +0200967 XFREE (MTYPE_OSPF_MPLS_TE, lp);
paul718e3742002-12-13 20:15:29 +0000968 }
969
970 /* Schedule Opaque-LSA refresh. *//* XXX */
971
972 rc = 0;
973/*out:*/
974 return rc;
975}
976
Olivier Dugeon29a14012016-04-19 18:42:40 +0200977/* Main initialization / update function of the MPLS TE Link context */
978
979/* Call when interface TE Link parameters are modified */
980void
981ospf_mpls_te_update_if (struct interface *ifp)
982{
983 struct mpls_te_link *lp;
984
985 if (IS_DEBUG_OSPF_TE)
986 zlog_debug ("OSPF MPLS-TE: Update LSA parameters for interface %s [%s]",
987 ifp->name, HAS_LINK_PARAMS(ifp) ? "ON" : "OFF");
988
989 /* Get Link context from interface */
990 if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL)
991 {
992 zlog_warn ("OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s", ifp->name);
993 return;
994 }
995
996 /* Fulfill MPLS-TE Link TLV from Interface TE Link parameters */
997 if (HAS_LINK_PARAMS(ifp))
998 {
999 SET_FLAG (lp->flags, LPFLG_LSA_ACTIVE);
1000
1001 /* Update TE parameters */
1002 update_linkparams(lp);
1003
1004 /* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is enabled */
1005 if (OspfMplsTE.status == enabled)
1006 if (lp->area != NULL)
1007 {
1008 if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
1009 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1010 else
1011 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA);
1012 }
1013 }
1014 else
1015 {
1016 /* If MPLS TE is disable on this interface, flush LSA if it is already engaged */
1017 if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
1018 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
1019 else
1020 /* Reset Activity flag */
1021 lp->flags = LPFLG_LSA_INACTIVE;
1022 }
1023
1024 return;
1025}
1026
paul718e3742002-12-13 20:15:29 +00001027static void
1028ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state)
1029{
1030 struct te_link_subtlv_link_type old_type;
1031 struct te_link_subtlv_link_id old_id;
1032 struct mpls_te_link *lp;
1033
1034 if ((lp = lookup_linkparams_by_ifp (oi->ifp)) == NULL)
1035 {
1036 zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi));
1037 goto out;
1038 }
Olivier Dugeon29a14012016-04-19 18:42:40 +02001039
pauld4a53d52003-07-12 21:30:57 +00001040 if (oi->area == NULL || oi->area->ospf == NULL)
paul718e3742002-12-13 20:15:29 +00001041 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02001042 zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?", IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00001043 goto out;
1044 }
1045#ifdef notyet
1046 if ((lp->area != NULL
1047 && ! IPV4_ADDR_SAME (&lp->area->area_id, &oi->area->area_id))
1048 || (lp->area != NULL && oi->area == NULL))
1049 {
1050 /* How should we consider this case? */
Olivier Dugeon29a14012016-04-19 18:42:40 +02001051 zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs",
1052 IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A");
paul718e3742002-12-13 20:15:29 +00001053 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
1054 }
1055#endif
Olivier Dugeon29a14012016-04-19 18:42:40 +02001056 /* Keep Area information in combination with linkparams. */
paul718e3742002-12-13 20:15:29 +00001057 lp->area = oi->area;
1058
Olivier Dugeon29a14012016-04-19 18:42:40 +02001059 /* Keep interface MPLS-TE status */
1060 lp->flags = HAS_LINK_PARAMS(oi->ifp);
1061
paul718e3742002-12-13 20:15:29 +00001062 switch (oi->state)
1063 {
1064 case ISM_PointToPoint:
1065 case ISM_DROther:
1066 case ISM_Backup:
1067 case ISM_DR:
1068 old_type = lp->link_type;
1069 old_id = lp->link_id;
1070
Olivier Dugeon29a14012016-04-19 18:42:40 +02001071 /* Set Link type, Link ID, Local and Remote IP addr */
paul718e3742002-12-13 20:15:29 +00001072 set_linkparams_link_type (oi, lp);
1073 set_linkparams_link_id (oi, lp);
Olivier Dugeon29a14012016-04-19 18:42:40 +02001074 set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4);
paul718e3742002-12-13 20:15:29 +00001075
Olivier Dugeon29a14012016-04-19 18:42:40 +02001076 if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP)
1077 {
1078 struct prefix *pref = CONNECTED_PREFIX(oi->connected);
1079 if (pref != NULL)
1080 set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
1081 }
1082
1083 /* Update TE parameters */
1084 update_linkparams(lp);
1085
1086 /* Try to Schedule LSA */
paul718e3742002-12-13 20:15:29 +00001087 if ((ntohs (old_type.header.type) != ntohs (lp->link_type.header.type)
1088 || old_type.link_type.value != lp->link_type.link_type.value)
1089 || (ntohs (old_id.header.type) != ntohs (lp->link_id.header.type)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001090 || ntohl (old_id.value.s_addr) !=
1091 ntohl (lp->link_id.value.s_addr)))
paul718e3742002-12-13 20:15:29 +00001092 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02001093 if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
paul718e3742002-12-13 20:15:29 +00001094 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1095 else
Olivier Dugeon29a14012016-04-19 18:42:40 +02001096 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA);
1097
paul718e3742002-12-13 20:15:29 +00001098 }
1099 break;
1100 default:
1101 lp->link_type.header.type = htons (0);
1102 lp->link_id.header.type = htons (0);
1103
Olivier Dugeon29a14012016-04-19 18:42:40 +02001104 if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
paul718e3742002-12-13 20:15:29 +00001105 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
1106 break;
1107 }
1108
1109out:
1110 return;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001111
paul718e3742002-12-13 20:15:29 +00001112}
1113
1114static void
1115ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state)
1116{
Olivier Dugeon29a14012016-04-19 18:42:40 +02001117 /* Nothing to do here */
paul718e3742002-12-13 20:15:29 +00001118 return;
1119}
1120
1121/*------------------------------------------------------------------------*
1122 * Followings are OSPF protocol processing functions for MPLS-TE.
1123 *------------------------------------------------------------------------*/
1124
1125static void
1126build_tlv_header (struct stream *s, struct te_tlv_header *tlvh)
1127{
1128 stream_put (s, tlvh, sizeof (struct te_tlv_header));
1129 return;
1130}
1131
1132static void
1133build_router_tlv (struct stream *s)
1134{
1135 struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header;
1136 if (ntohs (tlvh->type) != 0)
1137 {
1138 build_tlv_header (s, tlvh);
1139 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
1140 }
1141 return;
1142}
1143
1144static void
Olivier Dugeon29a14012016-04-19 18:42:40 +02001145build_link_subtlv (struct stream *s, struct te_tlv_header *tlvh)
paul718e3742002-12-13 20:15:29 +00001146 {
paul718e3742002-12-13 20:15:29 +00001147
Olivier Dugeon29a14012016-04-19 18:42:40 +02001148 if ((tlvh != NULL) && (ntohs (tlvh->type) != 0))
paul718e3742002-12-13 20:15:29 +00001149 {
1150 build_tlv_header (s, tlvh);
1151 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
1152 }
1153 return;
1154}
1155
1156static void
1157build_link_tlv (struct stream *s, struct mpls_te_link *lp)
1158{
1159 set_linkparams_link_header (lp);
1160 build_tlv_header (s, &lp->link_header.header);
1161
Olivier Dugeon29a14012016-04-19 18:42:40 +02001162 build_link_subtlv (s, &lp->link_type.header);
1163 build_link_subtlv (s, &lp->link_id.header);
1164 build_link_subtlv (s, &lp->lclif_ipaddr.header);
1165 build_link_subtlv (s, &lp->rmtif_ipaddr.header);
1166 build_link_subtlv (s, &lp->te_metric.header);
1167 build_link_subtlv (s, &lp->max_bw.header);
1168 build_link_subtlv (s, &lp->max_rsv_bw.header);
1169 build_link_subtlv (s, &lp->unrsv_bw.header);
1170 build_link_subtlv (s, &lp->rsc_clsclr.header);
1171 build_link_subtlv (s, &lp->lrrid.header);
1172 build_link_subtlv (s, &lp->llri.header);
1173 build_link_subtlv (s, &lp->rip.header);
1174 build_link_subtlv (s, &lp->ras.header);
1175 build_link_subtlv (s, &lp->av_delay.header);
1176 build_link_subtlv (s, &lp->mm_delay.header);
1177 build_link_subtlv (s, &lp->delay_var.header);
1178 build_link_subtlv (s, &lp->pkt_loss.header);
1179 build_link_subtlv (s, &lp->res_bw.header);
1180 build_link_subtlv (s, &lp->ava_bw.header);
1181 build_link_subtlv (s, &lp->res_bw.header);
1182
paul718e3742002-12-13 20:15:29 +00001183 return;
1184}
1185
1186static void
1187ospf_mpls_te_lsa_body_set (struct stream *s, struct mpls_te_link *lp)
1188{
1189 /*
1190 * The router address TLV is type 1, and ...
1191 * It must appear in exactly one
1192 * Traffic Engineering LSA originated by a router.
1193 */
1194 build_router_tlv (s);
1195
1196 /*
1197 * Only one Link TLV shall be carried in each LSA, allowing for fine
1198 * granularity changes in topology.
1199 */
1200 build_link_tlv (s, lp);
1201 return;
1202}
1203
1204/* Create new opaque-LSA. */
1205static struct ospf_lsa *
1206ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp)
1207{
1208 struct stream *s;
1209 struct lsa_header *lsah;
1210 struct ospf_lsa *new = NULL;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001211 u_char options, lsa_type = 0;
paul718e3742002-12-13 20:15:29 +00001212 struct in_addr lsa_id;
1213 u_int32_t tmp;
1214 u_int16_t length;
1215
1216 /* Create a stream for LSA. */
1217 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
1218 {
1219 zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?");
1220 goto out;
1221 }
1222 lsah = (struct lsa_header *) STREAM_DATA (s);
1223
Olivier Dugeon29a14012016-04-19 18:42:40 +02001224 options = OSPF_OPTION_O; /* Don't forget this :-) */
paul718e3742002-12-13 20:15:29 +00001225
Olivier Dugeon29a14012016-04-19 18:42:40 +02001226 /* Set opaque-LSA header fields depending of the type of RFC */
1227 if (IS_INTER_AS (lp->type))
1228 {
1229 if IS_FLOOD_AS (lp->type)
1230 {
1231 options |= OSPF_OPTION_E; /* Enable AS external as we flood Inter-AS with Opaque Type 11 */
1232 lsa_type = OSPF_OPAQUE_AS_LSA;
1233 }
1234 else
1235 {
1236 options |= LSA_OPTIONS_GET (area); /* Get area default option */
1237 options |= LSA_OPTIONS_NSSA_GET (area);
1238 lsa_type = OSPF_OPAQUE_AREA_LSA;
1239 }
1240 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
1241 lsa_id.s_addr = htonl (tmp);
1242
1243 struct ospf *top = ospf_lookup ();
1244
1245 lsa_header_set (s, options, lsa_type, lsa_id, top->router_id);
1246 }
1247 else
1248 {
1249 options |= LSA_OPTIONS_GET (area); /* Get area default option */
1250 options |= LSA_OPTIONS_NSSA_GET (area);
1251 lsa_type = OSPF_OPAQUE_AREA_LSA;
1252 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
1253 lsa_id.s_addr = htonl (tmp);
1254 lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id);
1255 }
paul718e3742002-12-13 20:15:29 +00001256
1257 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
Olivier Dugeon29a14012016-04-19 18:42:40 +02001258 zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance",
1259 lsa_type, inet_ntoa (lsa_id));
paul718e3742002-12-13 20:15:29 +00001260
1261 /* Set opaque-LSA body fields. */
1262 ospf_mpls_te_lsa_body_set (s, lp);
1263
1264 /* Set length. */
1265 length = stream_get_endp (s);
1266 lsah->length = htons (length);
1267
1268 /* Now, create an OSPF LSA instance. */
1269 if ((new = ospf_lsa_new ()) == NULL)
1270 {
1271 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
1272 stream_free (s);
1273 goto out;
1274 }
1275 if ((new->data = ospf_lsa_data_new (length)) == NULL)
1276 {
1277 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001278 ospf_lsa_unlock (&new);
paul718e3742002-12-13 20:15:29 +00001279 new = NULL;
1280 stream_free (s);
1281 goto out;
1282 }
1283
1284 new->area = area;
1285 SET_FLAG (new->flags, OSPF_LSA_SELF);
1286 memcpy (new->data, lsah, length);
1287 stream_free (s);
1288
1289out:
1290 return new;
1291}
1292
1293static int
1294ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp)
1295{
1296 struct ospf_lsa *new;
1297 int rc = -1;
1298
1299 /* Create new Opaque-LSA/MPLS-TE instance. */
1300 if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
1301 {
1302 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
1303 goto out;
1304 }
1305
1306 /* Install this LSA into LSDB. */
pauld4a53d52003-07-12 21:30:57 +00001307 if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
paul718e3742002-12-13 20:15:29 +00001308 {
1309 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001310 ospf_lsa_unlock (&new);
paul718e3742002-12-13 20:15:29 +00001311 goto out;
1312 }
1313
Olivier Dugeon29a14012016-04-19 18:42:40 +02001314 /* Now this link-parameter entry has associated LSA. */
1315 SET_FLAG (lp->flags, LPFLG_LSA_ENGAGED);
paul718e3742002-12-13 20:15:29 +00001316 /* Update new LSA origination count. */
pauld4a53d52003-07-12 21:30:57 +00001317 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +00001318
1319 /* Flood new LSA through area. */
1320 ospf_flood_through_area (area, NULL/*nbr*/, new);
1321
1322 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1323 {
1324 char area_id[INET_ADDRSTRLEN];
1325 strcpy (area_id, inet_ntoa (area->area_id));
Olivier Dugeon29a14012016-04-19 18:42:40 +02001326 zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)",
1327 new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name);
paul718e3742002-12-13 20:15:29 +00001328 ospf_lsa_header_dump (new->data);
1329 }
1330
1331 rc = 0;
1332out:
1333 return rc;
1334}
1335
1336static int
Olivier Dugeon29a14012016-04-19 18:42:40 +02001337ospf_mpls_te_lsa_originate_area (void *arg)
paul718e3742002-12-13 20:15:29 +00001338{
1339 struct ospf_area *area = (struct ospf_area *) arg;
paul1eb8ef22005-04-07 07:30:20 +00001340 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001341 struct mpls_te_link *lp;
1342 int rc = -1;
1343
1344 if (OspfMplsTE.status == disabled)
1345 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02001346 zlog_info ("ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now.");
paul718e3742002-12-13 20:15:29 +00001347 rc = 0; /* This is not an error case. */
1348 goto out;
1349 }
1350
paul1eb8ef22005-04-07 07:30:20 +00001351 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul718e3742002-12-13 20:15:29 +00001352 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02001353 /* Process only enabled LSA with area scope flooding */
1354 if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE) || IS_FLOOD_AS (lp->type))
1355 continue;
1356
paul718e3742002-12-13 20:15:29 +00001357 if (lp->area == NULL)
1358 continue;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001359
paul718e3742002-12-13 20:15:29 +00001360 if (! IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
1361 continue;
1362
Olivier Dugeon29a14012016-04-19 18:42:40 +02001363 if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
paul718e3742002-12-13 20:15:29 +00001364 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02001365 if CHECK_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH)
paul718e3742002-12-13 20:15:29 +00001366 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02001367 UNSET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH);
1368 zlog_warn ("OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate");
paul718e3742002-12-13 20:15:29 +00001369 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1370 }
1371 continue;
1372 }
1373 if (! is_mandated_params_set (lp))
1374 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02001375 zlog_warn ("ospf_mpls_te_lsa_originate_area: Link(%s) lacks some mandated MPLS-TE parameters.",
1376 lp->ifp ? lp->ifp->name : "?");
paul718e3742002-12-13 20:15:29 +00001377 continue;
1378 }
1379
1380 /* Ok, let's try to originate an LSA for this area and Link. */
Olivier Dugeon29a14012016-04-19 18:42:40 +02001381 if (IS_DEBUG_OSPF_TE)
1382 zlog_debug ("MPLS-TE(ospf_mpls_te_lsa_originate_area) Let's finally reoriginate the LSA %d through the Area %s for Link %s",
1383 lp->instance, inet_ntoa (area->area_id), lp->ifp ? lp->ifp->name : "?");
paul718e3742002-12-13 20:15:29 +00001384 if (ospf_mpls_te_lsa_originate1 (area, lp) != 0)
1385 goto out;
1386 }
1387
1388 rc = 0;
1389out:
1390 return rc;
1391}
1392
Olivier Dugeon29a14012016-04-19 18:42:40 +02001393static int
1394ospf_mpls_te_lsa_originate2 (struct ospf *top, struct mpls_te_link *lp)
1395{
1396 struct ospf_lsa *new;
1397 int rc = -1;
1398
1399 /* Create new Opaque-LSA/Inter-AS instance. */
1400 if ((new = ospf_mpls_te_lsa_new (NULL, lp)) == NULL)
1401 {
1402 zlog_warn ("ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?");
1403 goto out;
1404 }
1405
1406 /* Install this LSA into LSDB. */
1407 if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
1408 {
1409 zlog_warn ("ospf_mpls_te_lsa_originate2: ospf_lsa_install() ?");
1410 ospf_lsa_unlock (&new);
1411 goto out;
1412 }
1413
1414 /* Now this Router Info parameter entry has associated LSA. */
1415 SET_FLAG (lp->flags, LPFLG_LSA_ENGAGED);
1416 /* Update new LSA origination count. */
1417 top->lsa_originate_count++;
1418
1419 /* Flood new LSA through AS. */
1420 ospf_flood_through_as (top, NULL /*nbr */ , new);
1421
1422 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1423 {
1424 zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE Inter-AS",
1425 new->data->type, inet_ntoa (new->data->id));
1426 ospf_lsa_header_dump (new->data);
1427 }
1428
1429 rc = 0;
1430out:return rc;
1431}
1432
1433static int
1434ospf_mpls_te_lsa_originate_as (void *arg)
1435{
1436 struct ospf *top;
1437 struct ospf_area *area;
1438 struct listnode *node, *nnode;
1439 struct mpls_te_link *lp;
1440 int rc = -1;
1441
1442 if ((OspfMplsTE.status == disabled) || (OspfMplsTE.inter_as == Disable))
1443 {
1444 zlog_info
1445 ("ospf_mpls_te_lsa_originate_as: MPLS-TE Inter-AS is disabled for now.");
1446 rc = 0; /* This is not an error case. */
1447 goto out;
1448 }
1449
1450 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
1451 {
1452 /* Process only enabled INTER_AS Links or Pseudo-Links */
1453 if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE) || !IS_INTER_AS (lp->type))
1454 continue;
1455
1456 if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
1457 {
1458 if CHECK_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH)
1459 {
1460 UNSET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH);
1461 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1462 }
1463 continue;
1464 }
1465 if (!is_mandated_params_set (lp))
1466 {
1467 zlog_warn ("ospf_mpls_te_lsa_originate_as: Link(%s) lacks some mandated MPLS-TE parameters.",
1468 lp->ifp ? lp->ifp->name : "?");
1469 continue;
1470 }
1471
1472 /* Ok, let's try to originate an LSA for this AS and Link. */
1473 if (IS_DEBUG_OSPF_TE)
1474 zlog_debug ("MPLS-TE(ospf_mpls_te_lsa_originate_as) Let's finally re-originate the Inter-AS LSA %d through the %s for Link %s",
1475 lp->instance, IS_FLOOD_AS (lp->type) ? "AS" : "Area", lp->ifp ? lp->ifp->name : "Unknown");
1476
1477 if (IS_FLOOD_AS (lp->type))
1478 {
1479 top = (struct ospf *) arg;
1480 rc = ospf_mpls_te_lsa_originate2 (top, lp);
1481 }
1482 else
1483 {
1484 area = (struct ospf_area *) arg;
1485 rc = ospf_mpls_te_lsa_originate1 (area, lp);
1486 }
1487 }
1488
1489 rc = 0;
1490out:return rc;
1491}
1492
Paul Jakma072990e2011-04-11 16:28:16 +01001493static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001494ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
1495{
1496 struct mpls_te_link *lp;
1497 struct ospf_area *area = lsa->area;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001498 struct ospf *top;
paul718e3742002-12-13 20:15:29 +00001499 struct ospf_lsa *new = NULL;
1500
1501 if (OspfMplsTE.status == disabled)
1502 {
1503 /*
1504 * This LSA must have flushed before due to MPLS-TE status change.
1505 * It seems a slip among routers in the routing domain.
1506 */
1507 zlog_info ("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now.");
1508 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1509 }
1510
1511 /* At first, resolve lsa/lp relationship. */
1512 if ((lp = lookup_linkparams_by_instance (lsa)) == NULL)
1513 {
1514 zlog_warn ("ospf_mpls_te_lsa_refresh: Invalid parameter?");
1515 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1516 }
1517
Olivier Dugeon29a14012016-04-19 18:42:40 +02001518 /* Check if lp was not disable in the interval */
1519 if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE))
1520 {
1521 zlog_warn ("ospf_mpls_te_lsa_refresh: lp was disabled: Flush it!");
1522 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1523 }
1524
paul718e3742002-12-13 20:15:29 +00001525 /* If the lsa's age reached to MaxAge, start flushing procedure. */
1526 if (IS_LSA_MAXAGE (lsa))
1527 {
Remi Gacognea11e0122013-09-08 13:48:34 +00001528 if (lp)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001529 UNSET_FLAG (lp->flags, LPFLG_LSA_ENGAGED);
paul718e3742002-12-13 20:15:29 +00001530 ospf_opaque_lsa_flush_schedule (lsa);
1531 goto out;
1532 }
1533
1534 /* Create new Opaque-LSA/MPLS-TE instance. */
1535 if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
1536 {
1537 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
1538 goto out;
1539 }
1540 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1541
1542 /* Install this LSA into LSDB. */
1543 /* Given "lsa" will be freed in the next function. */
Olivier Dugeon29a14012016-04-19 18:42:40 +02001544 /* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use ospf_lookup() to get ospf instance */
1545 if (area)
1546 top = area->ospf;
1547 else
1548 top = ospf_lookup ();
1549
1550 if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
paul718e3742002-12-13 20:15:29 +00001551 {
1552 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001553 ospf_lsa_unlock (&new);
paul718e3742002-12-13 20:15:29 +00001554 goto out;
1555 }
1556
Olivier Dugeon29a14012016-04-19 18:42:40 +02001557 /* Flood updated LSA through AS or Area depending of the RFC of the link */
1558 if (IS_FLOOD_AS (lp->type))
1559 ospf_flood_through_as (top, NULL, new);
1560 else
1561 ospf_flood_through_area (area, NULL/*nbr*/, new);
paul718e3742002-12-13 20:15:29 +00001562
1563 /* Debug logging. */
1564 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1565 {
ajs2a42e282004-12-08 18:43:03 +00001566 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
paul718e3742002-12-13 20:15:29 +00001567 new->data->type, inet_ntoa (new->data->id));
1568 ospf_lsa_header_dump (new->data);
1569 }
1570
1571out:
Paul Jakma072990e2011-04-11 16:28:16 +01001572 return new;
paul718e3742002-12-13 20:15:29 +00001573}
1574
Olivier Dugeon29a14012016-04-19 18:42:40 +02001575void
1576ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, opcode_t opcode)
paul718e3742002-12-13 20:15:29 +00001577{
1578 struct ospf_lsa lsa;
1579 struct lsa_header lsah;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001580 struct ospf *top;
paul718e3742002-12-13 20:15:29 +00001581 u_int32_t tmp;
1582
1583 memset (&lsa, 0, sizeof (lsa));
1584 memset (&lsah, 0, sizeof (lsah));
Olivier Dugeon29a14012016-04-19 18:42:40 +02001585 top = ospf_lookup ();
1586
1587 /* Check if the pseudo link is ready to flood */
1588 if (!(CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE))
1589 || !(IS_FLOOD_AREA (lp->type) || IS_FLOOD_AS (lp->type))) {
1590 return;
1591 }
paul718e3742002-12-13 20:15:29 +00001592
1593 lsa.area = lp->area;
1594 lsa.data = &lsah;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001595 if (IS_FLOOD_AS (lp->type))
1596 {
1597 lsah.type = OSPF_OPAQUE_AS_LSA;
1598 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
1599 lsah.id.s_addr = htonl (tmp);
1600 }
1601 else
1602 {
1603 lsah.type = OSPF_OPAQUE_AREA_LSA;
1604 if (IS_INTER_AS (lp->type))
1605 {
1606 /* Set the area context if not know */
1607 if (lp->area == NULL)
1608 lp->area = ospf_area_lookup_by_area_id (top, OspfMplsTE.interas_areaid);
1609 /* Unable to set the area context. Abort! */
1610 if (lp->area == NULL)
1611 {
1612 zlog_warn ("MPLS-TE(ospf_mpls_te_lsa_schedule) Area context is null. Abort !");
1613 return;
1614 }
1615 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
1616 }
1617 else
1618 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
1619 lsah.id.s_addr = htonl (tmp);
1620 }
paul718e3742002-12-13 20:15:29 +00001621
1622 switch (opcode)
1623 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02001624 case REORIGINATE_THIS_LSA:
1625 if (IS_FLOOD_AS (lp->type))
1626 {
1627 ospf_opaque_lsa_reoriginate_schedule ((void *) top, OSPF_OPAQUE_AS_LSA,
1628 OPAQUE_TYPE_INTER_AS_LSA);
1629 break;
1630 }
1631
1632 if (IS_FLOOD_AREA (lp->type))
1633 {
1634 if (IS_INTER_AS (lp->type))
1635 ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area, OSPF_OPAQUE_AREA_LSA,
1636 OPAQUE_TYPE_INTER_AS_LSA);
1637 else
1638 ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area, OSPF_OPAQUE_AREA_LSA,
1639 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
1640 break;
1641 }
paul718e3742002-12-13 20:15:29 +00001642 break;
1643 case REFRESH_THIS_LSA:
1644 ospf_opaque_lsa_refresh_schedule (&lsa);
1645 break;
1646 case FLUSH_THIS_LSA:
Olivier Dugeon29a14012016-04-19 18:42:40 +02001647 /* Reset Activity flag */
1648 lp->flags = LPFLG_LSA_INACTIVE;
paul718e3742002-12-13 20:15:29 +00001649 ospf_opaque_lsa_flush_schedule (&lsa);
1650 break;
1651 default:
1652 zlog_warn ("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", opcode);
1653 break;
1654 }
1655
1656 return;
1657}
1658
Olivier Dugeon29a14012016-04-19 18:42:40 +02001659
paul718e3742002-12-13 20:15:29 +00001660/*------------------------------------------------------------------------*
1661 * Followings are vty session control functions.
1662 *------------------------------------------------------------------------*/
1663
1664static u_int16_t
1665show_vty_router_addr (struct vty *vty, struct te_tlv_header *tlvh)
1666{
1667 struct te_tlv_router_addr *top = (struct te_tlv_router_addr *) tlvh;
1668
1669 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001670 vty_out (vty, " Router-Address: %s%s", inet_ntoa (top->value),
1671 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001672 else
ajs2a42e282004-12-08 18:43:03 +00001673 zlog_debug (" Router-Address: %s", inet_ntoa (top->value));
paul718e3742002-12-13 20:15:29 +00001674
1675 return TLV_SIZE (tlvh);
1676}
1677
1678static u_int16_t
1679show_vty_link_header (struct vty *vty, struct te_tlv_header *tlvh)
1680{
1681 struct te_tlv_link *top = (struct te_tlv_link *) tlvh;
1682
1683 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001684 vty_out (vty, " Link: %u octets of data%s", ntohs (top->header.length),
1685 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001686 else
ajs2a42e282004-12-08 18:43:03 +00001687 zlog_debug (" Link: %u octets of data", ntohs (top->header.length));
paul718e3742002-12-13 20:15:29 +00001688
1689 return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
1690}
1691
1692static u_int16_t
1693show_vty_link_subtlv_link_type (struct vty *vty, struct te_tlv_header *tlvh)
1694{
1695 struct te_link_subtlv_link_type *top;
1696 const char *cp = "Unknown";
1697
1698 top = (struct te_link_subtlv_link_type *) tlvh;
1699 switch (top->link_type.value)
1700 {
1701 case LINK_TYPE_SUBTLV_VALUE_PTP:
1702 cp = "Point-to-point";
1703 break;
1704 case LINK_TYPE_SUBTLV_VALUE_MA:
1705 cp = "Multiaccess";
1706 break;
1707 default:
1708 break;
1709 }
1710
1711 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001712 vty_out (vty, " Link-Type: %s (%u)%s", cp, top->link_type.value,
1713 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001714 else
ajs2a42e282004-12-08 18:43:03 +00001715 zlog_debug (" Link-Type: %s (%u)", cp, top->link_type.value);
paul718e3742002-12-13 20:15:29 +00001716
1717 return TLV_SIZE (tlvh);
1718}
1719
1720static u_int16_t
1721show_vty_link_subtlv_link_id (struct vty *vty, struct te_tlv_header *tlvh)
1722{
1723 struct te_link_subtlv_link_id *top;
1724
1725 top = (struct te_link_subtlv_link_id *) tlvh;
1726 if (vty != NULL)
1727 vty_out (vty, " Link-ID: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
1728 else
ajs2a42e282004-12-08 18:43:03 +00001729 zlog_debug (" Link-ID: %s", inet_ntoa (top->value));
paul718e3742002-12-13 20:15:29 +00001730
1731 return TLV_SIZE (tlvh);
1732}
1733
1734static u_int16_t
Olivier Dugeon29a14012016-04-19 18:42:40 +02001735show_vty_link_subtlv_lclif_ipaddr (struct vty *vty,
1736 struct te_tlv_header *tlvh)
paul718e3742002-12-13 20:15:29 +00001737{
1738 struct te_link_subtlv_lclif_ipaddr *top;
1739 int i, n;
1740
1741 top = (struct te_link_subtlv_lclif_ipaddr *) tlvh;
1742 n = ntohs (tlvh->length) / sizeof (top->value[0]);
1743
1744 if (vty != NULL)
1745 vty_out (vty, " Local Interface IP Address(es): %d%s", n, VTY_NEWLINE);
1746 else
ajs2a42e282004-12-08 18:43:03 +00001747 zlog_debug (" Local Interface IP Address(es): %d", n);
paul718e3742002-12-13 20:15:29 +00001748
1749 for (i = 0; i < n; i++)
1750 {
1751 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001752 vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]),
1753 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001754 else
ajs2a42e282004-12-08 18:43:03 +00001755 zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i]));
paul718e3742002-12-13 20:15:29 +00001756 }
1757 return TLV_SIZE (tlvh);
1758}
1759
1760static u_int16_t
Olivier Dugeon29a14012016-04-19 18:42:40 +02001761show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty,
1762 struct te_tlv_header *tlvh)
paul718e3742002-12-13 20:15:29 +00001763{
1764 struct te_link_subtlv_rmtif_ipaddr *top;
1765 int i, n;
1766
1767 top = (struct te_link_subtlv_rmtif_ipaddr *) tlvh;
1768 n = ntohs (tlvh->length) / sizeof (top->value[0]);
1769 if (vty != NULL)
1770 vty_out (vty, " Remote Interface IP Address(es): %d%s", n, VTY_NEWLINE);
1771 else
ajs2a42e282004-12-08 18:43:03 +00001772 zlog_debug (" Remote Interface IP Address(es): %d", n);
paul718e3742002-12-13 20:15:29 +00001773
1774 for (i = 0; i < n; i++)
1775 {
1776 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001777 vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]),
1778 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001779 else
ajs2a42e282004-12-08 18:43:03 +00001780 zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i]));
paul718e3742002-12-13 20:15:29 +00001781 }
1782 return TLV_SIZE (tlvh);
1783}
1784
1785static u_int16_t
1786show_vty_link_subtlv_te_metric (struct vty *vty, struct te_tlv_header *tlvh)
1787{
1788 struct te_link_subtlv_te_metric *top;
1789
1790 top = (struct te_link_subtlv_te_metric *) tlvh;
1791 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001792 vty_out (vty, " Traffic Engineering Metric: %u%s",
1793 (u_int32_t) ntohl (top->value), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001794 else
Olivier Dugeon29a14012016-04-19 18:42:40 +02001795 zlog_debug (" Traffic Engineering Metric: %u",
1796 (u_int32_t) ntohl (top->value));
paul718e3742002-12-13 20:15:29 +00001797
1798 return TLV_SIZE (tlvh);
1799}
1800
1801static u_int16_t
1802show_vty_link_subtlv_max_bw (struct vty *vty, struct te_tlv_header *tlvh)
1803{
1804 struct te_link_subtlv_max_bw *top;
1805 float fval;
1806
1807 top = (struct te_link_subtlv_max_bw *) tlvh;
Paul Jakma43595012015-05-19 18:50:49 +01001808 fval = ntohf (top->value);
paul718e3742002-12-13 20:15:29 +00001809
1810 if (vty != NULL)
1811 vty_out (vty, " Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
1812 else
ajs2a42e282004-12-08 18:43:03 +00001813 zlog_debug (" Maximum Bandwidth: %g (Bytes/sec)", fval);
paul718e3742002-12-13 20:15:29 +00001814
1815 return TLV_SIZE (tlvh);
1816}
1817
1818static u_int16_t
1819show_vty_link_subtlv_max_rsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
1820{
1821 struct te_link_subtlv_max_rsv_bw *top;
1822 float fval;
1823
1824 top = (struct te_link_subtlv_max_rsv_bw *) tlvh;
Paul Jakma43595012015-05-19 18:50:49 +01001825 fval = ntohf (top->value);
paul718e3742002-12-13 20:15:29 +00001826
1827 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001828 vty_out (vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval,
1829 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001830 else
ajs2a42e282004-12-08 18:43:03 +00001831 zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval);
paul718e3742002-12-13 20:15:29 +00001832
1833 return TLV_SIZE (tlvh);
1834}
1835
1836static u_int16_t
1837show_vty_link_subtlv_unrsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
1838{
1839 struct te_link_subtlv_unrsv_bw *top;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001840 float fval1, fval2;
paul718e3742002-12-13 20:15:29 +00001841 int i;
1842
1843 top = (struct te_link_subtlv_unrsv_bw *) tlvh;
Olivier Dugeon29a14012016-04-19 18:42:40 +02001844 if (vty != NULL)
1845 vty_out (vty, " Unreserved Bandwidth per Class Type in Byte/s:%s", VTY_NEWLINE);
1846 else
1847 zlog_debug (" Unreserved Bandwidth per Class Type in Byte/s:");
1848 for (i = 0; i < MAX_CLASS_TYPE; i+=2)
paul718e3742002-12-13 20:15:29 +00001849 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02001850 fval1 = ntohf (top->value[i]);
1851 fval2 = ntohf (top->value[i+1]);
1852
paul718e3742002-12-13 20:15:29 +00001853 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001854 vty_out(vty, " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)%s",
1855 i, fval1, i+1, fval2, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001856 else
Olivier Dugeon29a14012016-04-19 18:42:40 +02001857 zlog_debug (" [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)",
1858 i, fval1, i+1, fval2);
paul718e3742002-12-13 20:15:29 +00001859 }
1860
1861 return TLV_SIZE (tlvh);
1862}
1863
1864static u_int16_t
1865show_vty_link_subtlv_rsc_clsclr (struct vty *vty, struct te_tlv_header *tlvh)
1866{
1867 struct te_link_subtlv_rsc_clsclr *top;
1868
1869 top = (struct te_link_subtlv_rsc_clsclr *) tlvh;
1870 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02001871 vty_out (vty, " Resource class/color: 0x%x%s",
1872 (u_int32_t) ntohl (top->value), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001873 else
Olivier Dugeon29a14012016-04-19 18:42:40 +02001874 zlog_debug (" Resource Class/Color: 0x%x",
1875 (u_int32_t) ntohl (top->value));
1876
1877 return TLV_SIZE (tlvh);
1878}
1879
1880static u_int16_t
1881show_vty_link_subtlv_lrrid (struct vty *vty, struct te_tlv_header *tlvh)
1882{
1883 struct te_link_subtlv_lrrid *top;
1884
1885 top = (struct te_link_subtlv_lrrid *) tlvh;
1886
1887 if (vty != NULL)
1888 {
1889 vty_out (vty, " Local TE Router ID: %s%s", inet_ntoa (top->local),
1890 VTY_NEWLINE);
1891 vty_out (vty, " Remote TE Router ID: %s%s", inet_ntoa (top->remote),
1892 VTY_NEWLINE);
1893 }
1894 else
1895 {
1896 zlog_debug (" Local TE Router ID: %s", inet_ntoa (top->local));
1897 zlog_debug (" Remote TE Router ID: %s", inet_ntoa (top->remote));
1898 }
1899
1900 return TLV_SIZE (tlvh);
1901}
1902
1903static u_int16_t
1904show_vty_link_subtlv_llri (struct vty *vty, struct te_tlv_header *tlvh)
1905{
1906 struct te_link_subtlv_llri *top;
1907
1908 top = (struct te_link_subtlv_llri *) tlvh;
1909
1910 if (vty != NULL)
1911 {
1912 vty_out (vty, " Link Local ID: %d%s", (u_int32_t) ntohl (top->local),
1913 VTY_NEWLINE);
1914 vty_out (vty, " Link Remote ID: %d%s", (u_int32_t) ntohl (top->remote),
1915 VTY_NEWLINE);
1916 }
1917 else
1918 {
1919 zlog_debug (" Link Local ID: %d", (u_int32_t) ntohl (top->local));
1920 zlog_debug (" Link Remote ID: %d", (u_int32_t) ntohl (top->remote));
1921 }
1922
1923 return TLV_SIZE (tlvh);
1924}
1925
1926static u_int16_t
1927show_vty_link_subtlv_rip (struct vty *vty, struct te_tlv_header *tlvh)
1928{
1929 struct te_link_subtlv_rip *top;
1930
1931 top = (struct te_link_subtlv_rip *) tlvh;
1932
1933 if (vty != NULL)
1934 vty_out (vty, " Inter-AS TE Remote ASBR IP address: %s%s",
1935 inet_ntoa (top->value), VTY_NEWLINE);
1936 else
1937 zlog_debug (" Inter-AS TE Remote ASBR IP address: %s",
1938 inet_ntoa (top->value));
1939
1940 return TLV_SIZE (tlvh);
1941}
1942
1943static u_int16_t
1944show_vty_link_subtlv_ras (struct vty *vty, struct te_tlv_header *tlvh)
1945{
1946 struct te_link_subtlv_ras *top;
1947
1948 top = (struct te_link_subtlv_ras *) tlvh;
1949
1950 if (vty != NULL)
1951 vty_out (vty, " Inter-AS TE Remote AS number: %u%s", ntohl (top->value),
1952 VTY_NEWLINE);
1953 else
1954 zlog_debug (" Inter-AS TE Remote AS number: %u", ntohl (top->value));
1955
1956 return TLV_SIZE (tlvh);
1957}
1958
1959static u_int16_t
1960show_vty_link_subtlv_av_delay (struct vty *vty, struct te_tlv_header *tlvh)
1961{
1962 struct te_link_subtlv_av_delay *top;
1963 u_int32_t delay;
1964 u_int32_t anomalous;
1965
1966 top = (struct te_link_subtlv_av_delay *) tlvh;
1967 delay = (u_int32_t) ntohl (top->value) & TE_EXT_MASK;
1968 anomalous = (u_int32_t) ntohl (top->value) & TE_EXT_ANORMAL;
1969
1970 if (vty != NULL)
1971 vty_out (vty, " %s Average Link Delay: %d (micro-sec)%s",
1972 anomalous ? "Anomalous" : "Normal", delay, VTY_NEWLINE);
1973 else
1974 zlog_debug (" %s Average Link Delay: %d (micro-sec)",
1975 anomalous ? "Anomalous" : "Normal", delay);
1976
1977 return TLV_SIZE (tlvh);
1978}
1979
1980static u_int16_t
1981show_vty_link_subtlv_mm_delay (struct vty *vty, struct te_tlv_header *tlvh)
1982{
1983 struct te_link_subtlv_mm_delay *top;
1984 u_int32_t low, high;
1985 u_int32_t anomalous;
1986
1987 top = (struct te_link_subtlv_mm_delay *) tlvh;
1988 low = (u_int32_t) ntohl (top->low) & TE_EXT_MASK;
1989 anomalous = (u_int32_t) ntohl (top->low) & TE_EXT_ANORMAL;
1990 high = (u_int32_t) ntohl (top->high);
1991
1992 if (vty != NULL)
1993 vty_out (vty, " %s Min/Max Link Delay: %d/%d (micro-sec)%s",
1994 anomalous ? "Anomalous" : "Normal", low, high, VTY_NEWLINE);
1995 else
1996 zlog_debug (" %s Min/Max Link Delay: %d/%d (micro-sec)",
1997 anomalous ? "Anomalous" : "Normal", low, high);
1998
1999 return TLV_SIZE (tlvh);
2000}
2001
2002static u_int16_t
2003show_vty_link_subtlv_delay_var (struct vty *vty, struct te_tlv_header *tlvh)
2004{
2005 struct te_link_subtlv_delay_var *top;
2006 u_int32_t jitter;
2007
2008 top = (struct te_link_subtlv_delay_var *) tlvh;
2009 jitter = (u_int32_t) ntohl (top->value) & TE_EXT_MASK;
2010
2011 if (vty != NULL)
2012 vty_out (vty, " Delay Variation: %d (micro-sec)%s", jitter, VTY_NEWLINE);
2013 else
2014 zlog_debug (" Delay Variation: %d (micro-sec)", jitter);
2015
2016 return TLV_SIZE (tlvh);
2017}
2018
2019static u_int16_t
2020show_vty_link_subtlv_pkt_loss (struct vty *vty, struct te_tlv_header *tlvh)
2021{
2022 struct te_link_subtlv_pkt_loss *top;
2023 u_int32_t loss;
2024 u_int32_t anomalous;
2025 float fval;
2026
2027 top = (struct te_link_subtlv_pkt_loss *) tlvh;
2028 loss = (u_int32_t) ntohl (top->value) & TE_EXT_MASK;
2029 fval = (float) (loss * LOSS_PRECISION);
2030 anomalous = (u_int32_t) ntohl (top->value) & TE_EXT_ANORMAL;
2031
2032 if (vty != NULL)
2033 vty_out (vty, " %s Link Loss: %g (%%)%s", anomalous ? "Anomalous" : "Normal",
2034 fval, VTY_NEWLINE);
2035 else
2036 zlog_debug (" %s Link Loss: %g (%%)", anomalous ? "Anomalous" : "Normal",
2037 fval);
2038
2039 return TLV_SIZE (tlvh);
2040}
2041
2042static u_int16_t
2043show_vty_link_subtlv_res_bw (struct vty *vty, struct te_tlv_header *tlvh)
2044{
2045 struct te_link_subtlv_res_bw *top;
2046 float fval;
2047
2048 top = (struct te_link_subtlv_res_bw *) tlvh;
2049 fval = ntohf (top->value);
2050
2051 if (vty != NULL)
2052 vty_out (vty, " Unidirectional Residual Bandwidth: %g (Bytes/sec)%s",
2053 fval, VTY_NEWLINE);
2054 else
2055 zlog_debug (" Unidirectional Residual Bandwidth: %g (Bytes/sec)",
2056 fval);
2057
2058 return TLV_SIZE (tlvh);
2059}
2060
2061static u_int16_t
2062show_vty_link_subtlv_ava_bw (struct vty *vty, struct te_tlv_header *tlvh)
2063{
2064 struct te_link_subtlv_ava_bw *top;
2065 float fval;
2066
2067 top = (struct te_link_subtlv_ava_bw *) tlvh;
2068 fval = ntohf (top->value);
2069
2070 if (vty != NULL)
2071 vty_out (vty, " Unidirectional Available Bandwidth: %g (Bytes/sec)%s",
2072 fval, VTY_NEWLINE);
2073 else
2074 zlog_debug (" Unidirectional Available Bandwidth: %g (Bytes/sec)",
2075 fval);
2076
2077 return TLV_SIZE (tlvh);
2078}
2079
2080static u_int16_t
2081show_vty_link_subtlv_use_bw (struct vty *vty, struct te_tlv_header *tlvh)
2082{
2083 struct te_link_subtlv_use_bw *top;
2084 float fval;
2085
2086 top = (struct te_link_subtlv_use_bw *) tlvh;
2087 fval = ntohf (top->value);
2088
2089 if (vty != NULL)
2090 vty_out (vty, " Unidirectional Utilized Bandwidth: %g (Bytes/sec)%s",
2091 fval, VTY_NEWLINE);
2092 else
2093 zlog_debug (" Unidirectional Utilized Bandwidth: %g (Bytes/sec)",
2094 fval);
paul718e3742002-12-13 20:15:29 +00002095
2096 return TLV_SIZE (tlvh);
2097}
2098
2099static u_int16_t
2100show_vty_unknown_tlv (struct vty *vty, struct te_tlv_header *tlvh)
2101{
2102 if (vty != NULL)
Olivier Dugeon29a14012016-04-19 18:42:40 +02002103 vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]%s",
2104 ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002105 else
Olivier Dugeon29a14012016-04-19 18:42:40 +02002106 zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]",
2107 ntohs (tlvh->type), ntohs (tlvh->length));
paul718e3742002-12-13 20:15:29 +00002108
2109 return TLV_SIZE (tlvh);
2110}
2111
2112static u_int16_t
2113ospf_mpls_te_show_link_subtlv (struct vty *vty, struct te_tlv_header *tlvh0,
2114 u_int16_t subtotal, u_int16_t total)
2115{
2116 struct te_tlv_header *tlvh, *next;
2117 u_int16_t sum = subtotal;
2118
2119 for (tlvh = tlvh0; sum < total; tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
2120 {
2121 next = NULL;
2122 switch (ntohs (tlvh->type))
2123 {
2124 case TE_LINK_SUBTLV_LINK_TYPE:
2125 sum += show_vty_link_subtlv_link_type (vty, tlvh);
2126 break;
2127 case TE_LINK_SUBTLV_LINK_ID:
2128 sum += show_vty_link_subtlv_link_id (vty, tlvh);
2129 break;
2130 case TE_LINK_SUBTLV_LCLIF_IPADDR:
2131 sum += show_vty_link_subtlv_lclif_ipaddr (vty, tlvh);
2132 break;
2133 case TE_LINK_SUBTLV_RMTIF_IPADDR:
2134 sum += show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh);
2135 break;
2136 case TE_LINK_SUBTLV_TE_METRIC:
2137 sum += show_vty_link_subtlv_te_metric (vty, tlvh);
2138 break;
2139 case TE_LINK_SUBTLV_MAX_BW:
2140 sum += show_vty_link_subtlv_max_bw (vty, tlvh);
2141 break;
2142 case TE_LINK_SUBTLV_MAX_RSV_BW:
2143 sum += show_vty_link_subtlv_max_rsv_bw (vty, tlvh);
2144 break;
2145 case TE_LINK_SUBTLV_UNRSV_BW:
2146 sum += show_vty_link_subtlv_unrsv_bw (vty, tlvh);
2147 break;
2148 case TE_LINK_SUBTLV_RSC_CLSCLR:
2149 sum += show_vty_link_subtlv_rsc_clsclr (vty, tlvh);
2150 break;
Olivier Dugeon29a14012016-04-19 18:42:40 +02002151 case TE_LINK_SUBTLV_LRRID:
2152 sum += show_vty_link_subtlv_lrrid (vty, tlvh);
2153 break;
2154 case TE_LINK_SUBTLV_LLRI:
2155 sum += show_vty_link_subtlv_llri (vty, tlvh);
2156 break;
2157 case TE_LINK_SUBTLV_RIP:
2158 sum += show_vty_link_subtlv_rip (vty, tlvh);
2159 break;
2160 case TE_LINK_SUBTLV_RAS:
2161 sum += show_vty_link_subtlv_ras (vty, tlvh);
2162 break;
2163 case TE_LINK_SUBTLV_AV_DELAY:
2164 sum += show_vty_link_subtlv_av_delay (vty, tlvh);
2165 break;
2166 case TE_LINK_SUBTLV_MM_DELAY:
2167 sum += show_vty_link_subtlv_mm_delay (vty, tlvh);
2168 break;
2169 case TE_LINK_SUBTLV_DELAY_VAR:
2170 sum += show_vty_link_subtlv_delay_var (vty, tlvh);
2171 break;
2172 case TE_LINK_SUBTLV_PKT_LOSS:
2173 sum += show_vty_link_subtlv_pkt_loss (vty, tlvh);
2174 break;
2175 case TE_LINK_SUBTLV_RES_BW:
2176 sum += show_vty_link_subtlv_res_bw (vty, tlvh);
2177 break;
2178 case TE_LINK_SUBTLV_AVA_BW:
2179 sum += show_vty_link_subtlv_ava_bw (vty, tlvh);
2180 break;
2181 case TE_LINK_SUBTLV_USE_BW:
2182 sum += show_vty_link_subtlv_use_bw (vty, tlvh);
2183 break;
paul718e3742002-12-13 20:15:29 +00002184 default:
2185 sum += show_vty_unknown_tlv (vty, tlvh);
2186 break;
2187 }
2188 }
2189 return sum;
2190}
2191
2192static void
2193ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa)
2194{
2195 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
2196 struct te_tlv_header *tlvh, *next;
2197 u_int16_t sum, total;
2198 u_int16_t (* subfunc)(struct vty *vty, struct te_tlv_header *tlvh,
2199 u_int16_t subtotal, u_int16_t total) = NULL;
2200
2201 sum = 0;
2202 total = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE;
2203
2204 for (tlvh = TLV_HDR_TOP (lsah); sum < total;
2205 tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
2206 {
2207 if (subfunc != NULL)
2208 {
2209 sum = (* subfunc)(vty, tlvh, sum, total);
2210 next = (struct te_tlv_header *)((char *) tlvh + sum);
2211 subfunc = NULL;
2212 continue;
2213 }
2214
2215 next = NULL;
2216 switch (ntohs (tlvh->type))
2217 {
2218 case TE_TLV_ROUTER_ADDR:
2219 sum += show_vty_router_addr (vty, tlvh);
2220 break;
2221 case TE_TLV_LINK:
2222 sum += show_vty_link_header (vty, tlvh);
2223 subfunc = ospf_mpls_te_show_link_subtlv;
2224 next = tlvh + 1;
2225 break;
2226 default:
2227 sum += show_vty_unknown_tlv (vty, tlvh);
2228 break;
2229 }
2230 }
2231 return;
2232}
2233
2234static void
2235ospf_mpls_te_config_write_router (struct vty *vty)
2236{
Olivier Dugeon29a14012016-04-19 18:42:40 +02002237
paul718e3742002-12-13 20:15:29 +00002238 if (OspfMplsTE.status == enabled)
2239 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02002240 vty_out (vty, " mpls-te on%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002241 vty_out (vty, " mpls-te router-address %s%s",
2242 inet_ntoa (OspfMplsTE.router_addr.value), VTY_NEWLINE);
2243 }
paul718e3742002-12-13 20:15:29 +00002244
Olivier Dugeon29a14012016-04-19 18:42:40 +02002245 if (OspfMplsTE.inter_as == AS)
2246 vty_out (vty, " mpls-te inter-as as%s", VTY_NEWLINE);
2247 if (OspfMplsTE.inter_as == Area)
2248 vty_out (vty, " mpls-te inter-as area %s %s",
2249 inet_ntoa (OspfMplsTE.interas_areaid), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002250
paul718e3742002-12-13 20:15:29 +00002251 return;
2252}
2253
2254/*------------------------------------------------------------------------*
2255 * Followings are vty command functions.
2256 *------------------------------------------------------------------------*/
2257
Olivier Dugeon29a14012016-04-19 18:42:40 +02002258DEFUN (ospf_mpls_te_on,
2259 ospf_mpls_te_on_cmd,
2260 "mpls-te on",
2261 MPLS_TE_STR
paul718e3742002-12-13 20:15:29 +00002262 "Enable the MPLS-TE functionality\n")
2263{
Olivier Dugeon29a14012016-04-19 18:42:40 +02002264 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002265 struct mpls_te_link *lp;
2266
2267 if (OspfMplsTE.status == enabled)
2268 return CMD_SUCCESS;
2269
2270 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002271 zlog_debug ("MPLS-TE: OFF -> ON");
paul718e3742002-12-13 20:15:29 +00002272
2273 OspfMplsTE.status = enabled;
2274
Olivier Dugeon29a14012016-04-19 18:42:40 +02002275 /* Reoriginate RFC3630 & RFC6827 Links */
2276 ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA);
paul718e3742002-12-13 20:15:29 +00002277
Olivier Dugeon29a14012016-04-19 18:42:40 +02002278 /* Reoriginate LSA if INTER-AS is always on */
2279 if (OspfMplsTE.inter_as != Disable)
2280 {
2281 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
2282 {
2283 if (IS_INTER_AS (lp->type))
2284 {
2285 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA);
2286 }
2287 }
2288 }
paul718e3742002-12-13 20:15:29 +00002289
2290 return CMD_SUCCESS;
2291}
2292
Olivier Dugeon29a14012016-04-19 18:42:40 +02002293DEFUN (no_ospf_mpls_te,
2294 no_ospf_mpls_te_cmd,
paul718e3742002-12-13 20:15:29 +00002295 "no mpls-te",
2296 NO_STR
paul718e3742002-12-13 20:15:29 +00002297 "Disable the MPLS-TE functionality\n")
2298{
paul1eb8ef22005-04-07 07:30:20 +00002299 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002300 struct mpls_te_link *lp;
2301
2302 if (OspfMplsTE.status == disabled)
2303 return CMD_SUCCESS;
2304
2305 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002306 zlog_debug ("MPLS-TE: ON -> OFF");
paul718e3742002-12-13 20:15:29 +00002307
2308 OspfMplsTE.status = disabled;
2309
paul1eb8ef22005-04-07 07:30:20 +00002310 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
Olivier Dugeon29a14012016-04-19 18:42:40 +02002311 if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
paul1eb8ef22005-04-07 07:30:20 +00002312 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
paul718e3742002-12-13 20:15:29 +00002313
2314 return CMD_SUCCESS;
2315}
2316
Olivier Dugeon29a14012016-04-19 18:42:40 +02002317DEFUN (ospf_mpls_te_router_addr,
2318 ospf_mpls_te_router_addr_cmd,
paul718e3742002-12-13 20:15:29 +00002319 "mpls-te router-address A.B.C.D",
Olivier Dugeon29a14012016-04-19 18:42:40 +02002320 MPLS_TE_STR
paul718e3742002-12-13 20:15:29 +00002321 "Stable IP address of the advertising router\n"
2322 "MPLS-TE router address in IPv4 address format\n")
2323{
2324 struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
2325 struct in_addr value;
2326
2327 if (! inet_aton (argv[0], &value))
2328 {
2329 vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE);
2330 return CMD_WARNING;
2331 }
2332
2333 if (ntohs (ra->header.type) == 0
paul87d6f872004-09-24 08:01:38 +00002334 || ntohl (ra->value.s_addr) != ntohl (value.s_addr))
paul718e3742002-12-13 20:15:29 +00002335 {
paul1eb8ef22005-04-07 07:30:20 +00002336 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002337 struct mpls_te_link *lp;
2338 int need_to_reoriginate = 0;
2339
2340 set_mpls_te_router_addr (value);
2341
2342 if (OspfMplsTE.status == disabled)
2343 goto out;
2344
paul1eb8ef22005-04-07 07:30:20 +00002345 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul718e3742002-12-13 20:15:29 +00002346 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02002347 if ((lp->area == NULL) || IS_FLOOD_AS (lp->type))
paul718e3742002-12-13 20:15:29 +00002348 continue;
2349
Olivier Dugeon29a14012016-04-19 18:42:40 +02002350 if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED))
paul718e3742002-12-13 20:15:29 +00002351 {
2352 need_to_reoriginate = 1;
2353 break;
2354 }
2355 }
paul1eb8ef22005-04-07 07:30:20 +00002356
2357 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul718e3742002-12-13 20:15:29 +00002358 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02002359 if ((lp->area == NULL) || IS_FLOOD_AS (lp->type))
paul718e3742002-12-13 20:15:29 +00002360 continue;
2361
2362 if (need_to_reoriginate)
Olivier Dugeon29a14012016-04-19 18:42:40 +02002363 SET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH);
paul718e3742002-12-13 20:15:29 +00002364 else
2365 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
2366 }
2367
2368 if (need_to_reoriginate)
Olivier Dugeon29a14012016-04-19 18:42:40 +02002369 ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA);
paul718e3742002-12-13 20:15:29 +00002370 }
2371out:
2372 return CMD_SUCCESS;
2373}
2374
Olivier Dugeon29a14012016-04-19 18:42:40 +02002375static int
2376set_inter_as_mode (struct vty *vty, const char *mode_name,
2377 const char *area_id)
paul718e3742002-12-13 20:15:29 +00002378{
Olivier Dugeon29a14012016-04-19 18:42:40 +02002379 enum inter_as_mode mode;
2380 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002381 struct mpls_te_link *lp;
Olivier Dugeon29a14012016-04-19 18:42:40 +02002382 int format;
paul718e3742002-12-13 20:15:29 +00002383
Olivier Dugeon29a14012016-04-19 18:42:40 +02002384 if (OspfMplsTE.status == enabled)
paul718e3742002-12-13 20:15:29 +00002385 {
paul718e3742002-12-13 20:15:29 +00002386
Olivier Dugeon29a14012016-04-19 18:42:40 +02002387 /* Read and Check inter_as mode */
2388 if (strcmp (mode_name, "as") == 0)
2389 mode = AS;
2390 else if (strcmp (mode_name, "area") == 0)
2391 {
2392 mode = Area;
2393 VTY_GET_OSPF_AREA_ID (OspfMplsTE.interas_areaid, format, area_id);
2394 }
2395 else
2396 {
2397 vty_out (vty, "Unknown mode. Please choose between as or area%s",
2398 VTY_NEWLINE);
2399 return CMD_WARNING;
2400 }
paul718e3742002-12-13 20:15:29 +00002401
Olivier Dugeon29a14012016-04-19 18:42:40 +02002402 if (IS_DEBUG_OSPF_EVENT)
2403 zlog_debug ("MPLS-TE: Inter-AS enable with %s flooding support",
2404 mode2text[mode]);
paul718e3742002-12-13 20:15:29 +00002405
Olivier Dugeon29a14012016-04-19 18:42:40 +02002406 /* Register new callbacks regarding the flooding scope (AS or Area) */
2407 if (ospf_mpls_te_register (mode) < 0)
2408 {
2409 vty_out (vty, "Internal error: Unable to register Inter-AS functions%s",
2410 VTY_NEWLINE);
2411 return CMD_WARNING;
2412 }
2413
2414 /* Enable mode and re-originate LSA if needed */
2415 if ((OspfMplsTE.inter_as == Disable) && (mode != OspfMplsTE.inter_as))
2416 {
2417 OspfMplsTE.inter_as = mode;
2418 /* Re-originate all InterAS-TEv2 LSA */
2419 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
2420 {
2421 if (IS_INTER_AS (lp->type))
2422 {
2423 if (mode == AS)
2424 lp->type |= FLOOD_AS;
2425 else
2426 lp->type |= FLOOD_AREA;
2427 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA);
2428 }
2429 }
2430 }
2431 else
2432 {
2433 vty_out (vty, "Please change Inter-AS support to disable first before going to mode %s%s",
2434 mode2text[mode], VTY_NEWLINE);
2435 return CMD_WARNING;
2436 }
paul718e3742002-12-13 20:15:29 +00002437 }
2438 return CMD_SUCCESS;
2439}
2440
Olivier Dugeon29a14012016-04-19 18:42:40 +02002441DEFUN (ospf_mpls_te_inter_as_as,
2442 ospf_mpls_te_inter_as_cmd,
2443 "mpls-te inter-as as",
2444 MPLS_TE_STR
2445 "Configure MPLS-TE Inter-AS support\n"
2446 "AS native mode self originate INTER_AS LSA with Type 11 (as flooding scope)\n")
paul718e3742002-12-13 20:15:29 +00002447{
Olivier Dugeon29a14012016-04-19 18:42:40 +02002448 return set_inter_as_mode (vty, "as", "");
2449}
2450
2451DEFUN (ospf_mpls_te_inter_as_area,
2452 ospf_mpls_te_inter_as_area_cmd,
2453 "mpls-te inter-as area (A.B.C.D|<0-4294967295>)",
2454 MPLS_TE_STR
2455 "Configure MPLS-TE Inter-AS support\n"
2456 "AREA native mode self originate INTER_AS LSA with Type 10 (area flooding scope)\n"
2457 "OSPF area ID in IP format\n"
2458 "OSPF area ID as decimal value\n")
2459{
2460 return set_inter_as_mode (vty, "area", argv[0]);
2461}
2462
2463DEFUN (no_ospf_mpls_te_inter_as,
2464 no_ospf_mpls_te_inter_as_cmd,
2465 "no mpls-te inter-as",
2466 NO_STR
2467 MPLS_TE_STR
2468 "Disable MPLS-TE Inter-AS support\n")
2469{
2470
2471 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002472 struct mpls_te_link *lp;
paul718e3742002-12-13 20:15:29 +00002473
Olivier Dugeon29a14012016-04-19 18:42:40 +02002474 if (IS_DEBUG_OSPF_EVENT)
2475 zlog_debug ("MPLS-TE: Inter-AS support OFF");
2476
2477 if ((OspfMplsTE.status == enabled) && (OspfMplsTE.inter_as != Disable))
paul718e3742002-12-13 20:15:29 +00002478 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02002479 OspfMplsTE.inter_as = Disable;
2480 /* Flush all Inter-AS LSA */
2481 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
2482 if (IS_INTER_AS (lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED))
2483 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
paul718e3742002-12-13 20:15:29 +00002484 }
2485
Olivier Dugeon29a14012016-04-19 18:42:40 +02002486 /* Deregister the Callbacks for Inter-AS suport */
2487 ospf_mpls_te_unregister ();
paul718e3742002-12-13 20:15:29 +00002488
paul718e3742002-12-13 20:15:29 +00002489 return CMD_SUCCESS;
2490}
2491
Olivier Dugeon29a14012016-04-19 18:42:40 +02002492DEFUN (show_ip_ospf_mpls_te_router,
2493 show_ip_ospf_mpls_te_router_cmd,
2494 "show ip ospf mpls-te router",
paul718e3742002-12-13 20:15:29 +00002495 SHOW_STR
Olivier Dugeon29a14012016-04-19 18:42:40 +02002496 IP_STR
2497 OSPF_STR
paul718e3742002-12-13 20:15:29 +00002498 "MPLS-TE information\n"
Olivier Dugeon29a14012016-04-19 18:42:40 +02002499 "MPLS-TE Router parameters\n")
paul718e3742002-12-13 20:15:29 +00002500{
2501 if (OspfMplsTE.status == enabled)
2502 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02002503 vty_out (vty, "--- MPLS-TE router parameters ---%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002504
2505 if (ntohs (OspfMplsTE.router_addr.header.type) != 0)
2506 show_vty_router_addr (vty, &OspfMplsTE.router_addr.header);
2507 else if (vty != NULL)
2508 vty_out (vty, " N/A%s", VTY_NEWLINE);
2509 }
2510 return CMD_SUCCESS;
2511}
2512
2513static void
2514show_mpls_te_link_sub (struct vty *vty, struct interface *ifp)
2515{
2516 struct mpls_te_link *lp;
paul718e3742002-12-13 20:15:29 +00002517
Olivier Dugeon29a14012016-04-19 18:42:40 +02002518 if ((OspfMplsTE.status == enabled)
2519 && HAS_LINK_PARAMS(ifp)
2520 && !if_is_loopback (ifp)
2521 && if_is_up (ifp)
2522 && ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
paul718e3742002-12-13 20:15:29 +00002523 {
Olivier Dugeon29a14012016-04-19 18:42:40 +02002524 /* Continue only if interface is not passive or support Inter-AS TEv2 */
2525 if (!(ospf_oi_count (ifp) > 0))
2526 {
2527 if (IS_INTER_AS (lp->type))
2528 {
2529 vty_out (vty, "-- Inter-AS TEv2 link parameters for %s --%s",
2530 ifp->name, VTY_NEWLINE);
2531 }
2532 else
2533 {
2534 /* MPLS-TE is not activate on this interface */
2535 /* or this interface is passive and Inter-AS TEv2 is not activate */
2536 vty_out (vty, " %s: MPLS-TE is disabled on this interface%s",
2537 ifp->name, VTY_NEWLINE);
2538 return;
2539 }
2540 }
2541 else
2542 {
paul718e3742002-12-13 20:15:29 +00002543 vty_out (vty, "-- MPLS-TE link parameters for %s --%s",
2544 ifp->name, VTY_NEWLINE);
Olivier Dugeon29a14012016-04-19 18:42:40 +02002545 }
paul718e3742002-12-13 20:15:29 +00002546
Olivier Dugeon29a14012016-04-19 18:42:40 +02002547 if (TLV_TYPE(lp->link_type) != 0)
2548 show_vty_link_subtlv_link_type (vty, &lp->link_type.header);
2549 if (TLV_TYPE(lp->link_id) != 0)
2550 show_vty_link_subtlv_link_id (vty, &lp->link_id.header);
2551 if (TLV_TYPE(lp->lclif_ipaddr) != 0)
2552 show_vty_link_subtlv_lclif_ipaddr (vty, &lp->lclif_ipaddr.header);
2553 if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
2554 show_vty_link_subtlv_rmtif_ipaddr (vty, &lp->rmtif_ipaddr.header);
2555 if (TLV_TYPE(lp->rip) != 0)
2556 show_vty_link_subtlv_rip (vty, &lp->rip.header);
2557 if (TLV_TYPE(lp->ras) != 0)
2558 show_vty_link_subtlv_ras (vty, &lp->ras.header);
2559 if (TLV_TYPE(lp->te_metric) != 0)
2560 show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header);
2561 if (TLV_TYPE(lp->max_bw) != 0)
2562 show_vty_link_subtlv_max_bw (vty, &lp->max_bw.header);
2563 if (TLV_TYPE(lp->max_rsv_bw) != 0)
2564 show_vty_link_subtlv_max_rsv_bw (vty, &lp->max_rsv_bw.header);
2565 if (TLV_TYPE(lp->unrsv_bw) != 0)
2566 show_vty_link_subtlv_unrsv_bw (vty, &lp->unrsv_bw.header);
2567 if (TLV_TYPE(lp->rsc_clsclr) != 0)
2568 show_vty_link_subtlv_rsc_clsclr (vty, &lp->rsc_clsclr.header);
2569 if (TLV_TYPE(lp->av_delay) != 0)
2570 show_vty_link_subtlv_av_delay (vty, &lp->av_delay.header);
2571 if (TLV_TYPE(lp->mm_delay) != 0)
2572 show_vty_link_subtlv_mm_delay (vty, &lp->mm_delay.header);
2573 if (TLV_TYPE(lp->delay_var) != 0)
2574 show_vty_link_subtlv_delay_var (vty, &lp->delay_var.header);
2575 if (TLV_TYPE(lp->pkt_loss) != 0)
2576 show_vty_link_subtlv_pkt_loss (vty, &lp->pkt_loss.header);
2577 if (TLV_TYPE(lp->res_bw) != 0)
2578 show_vty_link_subtlv_res_bw (vty, &lp->res_bw.header);
2579 if (TLV_TYPE(lp->ava_bw) != 0)
2580 show_vty_link_subtlv_ava_bw (vty, &lp->ava_bw.header);
2581 if (TLV_TYPE(lp->use_bw) != 0)
2582 show_vty_link_subtlv_use_bw (vty, &lp->use_bw.header);
2583 vty_out (vty, "---------------%s%s", VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002584 }
2585 else
2586 {
2587 vty_out (vty, " %s: MPLS-TE is disabled on this interface%s",
2588 ifp->name, VTY_NEWLINE);
2589 }
2590
2591 return;
2592}
2593
Olivier Dugeon29a14012016-04-19 18:42:40 +02002594DEFUN (show_ip_ospf_mpls_te_link,
2595 show_ip_ospf_mpls_te_link_cmd,
2596 "show ip ospf mpls-te interface [INTERFACE]",
paul718e3742002-12-13 20:15:29 +00002597 SHOW_STR
Olivier Dugeon29a14012016-04-19 18:42:40 +02002598 IP_STR
2599 OSPF_STR
paul718e3742002-12-13 20:15:29 +00002600 "MPLS-TE information\n"
2601 "Interface information\n"
2602 "Interface name\n")
2603{
2604 struct interface *ifp;
paul1eb8ef22005-04-07 07:30:20 +00002605 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002606
2607 /* Show All Interfaces. */
2608 if (argc == 0)
hassoeb1ce602004-10-08 08:17:22 +00002609 {
paul1eb8ef22005-04-07 07:30:20 +00002610 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
2611 show_mpls_te_link_sub (vty, ifp);
hassoeb1ce602004-10-08 08:17:22 +00002612 }
paul718e3742002-12-13 20:15:29 +00002613 /* Interface name is specified. */
2614 else
2615 {
2616 if ((ifp = if_lookup_by_name (argv[0])) == NULL)
2617 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
2618 else
2619 show_mpls_te_link_sub (vty, ifp);
2620 }
2621
2622 return CMD_SUCCESS;
2623}
2624
2625static void
2626ospf_mpls_te_register_vty (void)
2627{
Olivier Dugeon29a14012016-04-19 18:42:40 +02002628 install_element (VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd);
2629 install_element (VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd);
paul718e3742002-12-13 20:15:29 +00002630
Olivier Dugeon29a14012016-04-19 18:42:40 +02002631 install_element (OSPF_NODE, &ospf_mpls_te_on_cmd);
2632 install_element (OSPF_NODE, &no_ospf_mpls_te_cmd);
2633 install_element (OSPF_NODE, &ospf_mpls_te_router_addr_cmd);
2634 install_element (OSPF_NODE, &ospf_mpls_te_inter_as_cmd);
2635 install_element (OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd);
2636 install_element (OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd);
paul718e3742002-12-13 20:15:29 +00002637
2638 return;
2639}