Import Upstream version 1.2.2
[quagga-debian.git] / ospfd / ospf_te.c
1 /*
2  * This is an implementation of RFC3630
3  * Copyright (C) 2001 KDD R&D Laboratories, Inc.
4  * http://www.kddlabs.co.jp/
5  *
6  * Copyright (C) 2012 Orange Labs
7  * http://www.orange.com
8  *
9  * This file is part of GNU Zebra.
10  *
11  * GNU Zebra is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by the
13  * Free Software Foundation; either version 2, or (at your option) any
14  * later version.
15  * 
16  * GNU Zebra is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
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
27 /* Add support of RFC7471 */
28 /* Add support of RFC5392, RFC6827 */
29
30 #include <zebra.h>
31 #include <math.h>
32
33 #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() */
45 #include "network.h"
46
47 #include "ospfd/ospfd.h"
48 #include "ospfd/ospf_interface.h"
49 #include "ospfd/ospf_ism.h"
50 #include "ospfd/ospf_asbr.h"
51 #include "ospfd/ospf_lsa.h"
52 #include "ospfd/ospf_lsdb.h"
53 #include "ospfd/ospf_neighbor.h"
54 #include "ospfd/ospf_nsm.h"
55 #include "ospfd/ospf_flood.h"
56 #include "ospfd/ospf_packet.h"
57 #include "ospfd/ospf_spf.h"
58 #include "ospfd/ospf_dump.h"
59 #include "ospfd/ospf_route.h"
60 #include "ospfd/ospf_ase.h"
61 #include "ospfd/ospf_zebra.h"
62 #include "ospfd/ospf_te.h"
63 #include "ospfd/ospf_vty.h"
64
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  */
69 struct ospf_mpls_te OspfMplsTE;
70
71 const char *mode2text[] = { "Disable", "AS", "Area", "Emulate" };
72
73 enum oifstate
74 {
75   OI_ANY, OI_DOWN, OI_UP
76 };
77
78 /*------------------------------------------------------------------------*
79  * Followings are initialize/terminate functions for MPLS-TE handling.
80  *------------------------------------------------------------------------*/
81
82 static int ospf_mpls_te_new_if (struct interface *ifp);
83 static int ospf_mpls_te_del_if (struct interface *ifp);
84 static void ospf_mpls_te_ism_change (struct ospf_interface *oi,
85                                      int old_status);
86 static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status);
87 static void ospf_mpls_te_config_write_router (struct vty *vty);
88 static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa);
89 static int ospf_mpls_te_lsa_originate_area (void *arg);
90 static int ospf_mpls_te_lsa_originate_as (void *arg);
91 static struct ospf_lsa *ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);
92
93 static void del_mpls_te_link (void *val);
94 static void ospf_mpls_te_register_vty (void);
95
96 int
97 ospf_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,
109                 NULL,/*ospf_mpls_te_config_write_if */
110                 NULL,/* ospf_mpls_te_config_write_debug */
111                 ospf_mpls_te_show_info,
112                 ospf_mpls_te_lsa_originate_area,
113                 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     {
118       zlog_warn ("ospf_mpls_te_init: Failed to register Traffic Engineering functions");
119       goto out;
120     }
121
122   memset (&OspfMplsTE, 0, sizeof (struct ospf_mpls_te));
123   OspfMplsTE.status = disabled;
124   OspfMplsTE.inter_as = Disable;
125   OspfMplsTE.iflist = list_new ();
126   OspfMplsTE.iflist->del = del_mpls_te_link;
127
128   ospf_mpls_te_register_vty ();
129
130 out:
131   return rc;
132 }
133
134 /* Additional register for RFC5392 support */
135 static int
136 ospf_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
171 static int
172 ospf_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
190 void
191 ospf_mpls_te_term (void)
192 {
193   list_delete (OspfMplsTE.iflist);
194   OspfMplsTE.iflist = NULL;
195
196   ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA,
197                               OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
198   OspfMplsTE.status = disabled;
199
200   ospf_mpls_te_unregister ();
201   OspfMplsTE.inter_as = Disable;
202
203   return;
204 }
205
206 /*------------------------------------------------------------------------*
207  * Followings are control functions for MPLS-TE parameters management.
208  *------------------------------------------------------------------------*/
209
210 static void
211 del_mpls_te_link (void *val)
212 {
213   XFREE (MTYPE_OSPF_MPLS_TE, val);
214   return;
215 }
216
217 u_int32_t
218 get_mpls_te_instance_value (void)
219 {
220   static u_int32_t seqno = 0;
221
222   if (seqno < MAX_LEGAL_TE_INSTANCE_NUM )
223     seqno += 1;
224   else
225     seqno  = 1; /* Avoid zero. */
226
227   return seqno;
228 }
229
230 static struct ospf_interface *
231 lookup_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     }
262 out:
263   return NULL;
264 }
265
266 static struct mpls_te_link *
267 lookup_linkparams_by_ifp (struct interface *ifp)
268 {
269   struct listnode *node, *nnode;
270   struct mpls_te_link *lp;
271
272   for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
273     if (lp->ifp == ifp)
274       return lp;
275
276   return NULL;
277 }
278
279 static struct mpls_te_link *
280 lookup_linkparams_by_instance (struct ospf_lsa *lsa)
281 {
282   struct listnode *node;
283   struct mpls_te_link *lp;
284   unsigned int key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
285
286   for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
287     if (lp->instance == key)
288       return lp;
289
290   zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key);
291   return NULL;
292 }
293
294 static void
295 ospf_mpls_te_foreach_area (void (*func)
296                            (struct mpls_te_link * lp, opcode_t sched_opcode),
297                            opcode_t sched_opcode)
298 {
299   struct listnode *node, *nnode; 
300   struct listnode *node2;
301   struct mpls_te_link *lp;
302   struct ospf_area *area;
303
304   for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
305     {
306       /* Skip Inter-AS TEv2 Links */
307       if (IS_INTER_AS (lp->type))
308         continue;
309       if ((area = lp->area) == NULL)
310         continue;
311       if CHECK_FLAG (lp->flags, LPFLG_LOOKUP_DONE) continue;
312
313       if (func != NULL)
314         (* func)(lp, sched_opcode);
315
316       for (node2 = listnextnode (node); node2; node2 = listnextnode (node2))
317         if ((lp = listgetdata (node2)) != NULL)
318           if (lp->area != NULL)
319             if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
320               SET_FLAG (lp->flags, LPFLG_LOOKUP_DONE);
321     }
322
323   for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
324     if (lp->area != NULL)
325       UNSET_FLAG (lp->flags, LPFLG_LOOKUP_DONE);
326
327   return;
328 }
329
330 static void
331 set_mpls_te_router_addr (struct in_addr ipv4)
332 {
333   OspfMplsTE.router_addr.header.type   = htons (TE_TLV_ROUTER_ADDR);
334   OspfMplsTE.router_addr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
335   OspfMplsTE.router_addr.value = ipv4;
336   return;
337 }
338
339 static void
340 set_linkparams_link_header (struct mpls_te_link *lp)
341 {
342   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 */
353   if (lp->lclif_ipaddr.header.type != 0)
354     length += TLV_SIZE (&lp->lclif_ipaddr.header);
355
356   /* TE_LINK_SUBTLV_RMTIF_IPADDR */
357   if (lp->rmtif_ipaddr.header.type != 0)
358     length += TLV_SIZE (&lp->rmtif_ipaddr.header);
359
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
380   /* 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
424   lp->link_header.header.type   = htons (TE_TLV_LINK);
425   lp->link_header.header.length = htons (length);
426
427   return;
428 }
429
430 static void
431 set_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);
434   lp->link_type.header.length = htons (TE_LINK_SUBTLV_TYPE_SIZE);
435
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
453 static void
454 set_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);
460   lp->link_id.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
461
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. */
470       if ((nbr = ospf_nbr_lookup_ptop (oi)) && nbr->state == NSM_Full)
471         {
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))
484       &&  ospf_nbr_count (oi, NSM_Full) > 0))
485         {
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
505 static void
506 set_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
515 static void
516 set_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
525 static void
526 set_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);
529   lp->te_metric.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
530   lp->te_metric.value = htonl (te_metric);
531   return;
532 }
533
534 static void
535 set_linkparams_max_bw (struct mpls_te_link *lp, float fp)
536 {
537   lp->max_bw.header.type   = htons (TE_LINK_SUBTLV_MAX_BW);
538   lp->max_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
539   lp->max_bw.value = htonf (fp);
540   return;
541 }
542
543 static void
544 set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float fp)
545 {
546   lp->max_rsv_bw.header.type   = htons (TE_LINK_SUBTLV_MAX_RSV_BW);
547   lp->max_rsv_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
548   lp->max_rsv_bw.value = htonf (fp);
549   return;
550 }
551
552 static void
553 set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float fp)
554 {
555   /* Note that TLV-length field is the size of array. */
556   lp->unrsv_bw.header.type   = htons (TE_LINK_SUBTLV_UNRSV_BW);
557   lp->unrsv_bw.header.length = htons (TE_LINK_SUBTLV_UNRSV_SIZE);
558   lp->unrsv_bw.value [priority] = htonf (fp);
559   return;
560 }
561
562 static void
563 set_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);
566   lp->rsc_clsclr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE);
567   lp->rsc_clsclr.value = htonl (classcolor);
568   return;
569 }
570
571 static void
572 set_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
586 static void
587 unset_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
600 void
601 set_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
611 void
612 set_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
622 static void
623 set_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
636 static void
637 set_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
651 static void
652 set_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
661 static void
662 set_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
675 static void
676 set_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
685 static void
686 set_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
695 static void
696 set_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 */
706 static void
707 update_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
827 static void
828 initialize_linkparams (struct mpls_te_link *lp)
829 {
830   struct interface *ifp = lp->ifp;
831   struct ospf_interface *oi;
832
833   if (IS_DEBUG_OSPF_TE)
834     zlog_debug("MPLS-TE(initialize_linkparams) Initialize Link Parameters for interface %s",
835                 ifp->name);
836
837   if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL)
838     {
839       zlog_warn("MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s",
840                  ifp->name);
841       return;
842     }
843
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
850   /* Set local IP addr */
851   set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4);
852
853   /* 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     }
860
861   /* Keep Area information in combination with link parameters. */
862   lp->area = oi->area;
863
864   return;
865 }
866
867 static int
868 is_mandated_params_set (struct mpls_te_link *lp)
869 {
870   int rc = 0;
871
872   if (ntohs (OspfMplsTE.router_addr.header.type) == 0)
873     {
874       zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Router Address");
875     goto out;
876     }
877
878   if (ntohs (lp->link_type.header.type) == 0)
879     {
880       zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Link Type");
881     goto out;
882     }
883
884   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");
887     goto out;
888     }
889
890   rc = 1;
891 out:
892   return rc;
893 }
894
895 /*------------------------------------------------------------------------*
896  * Followings are callback functions against generic Opaque-LSAs handling.
897  *------------------------------------------------------------------------*/
898
899 static int
900 ospf_mpls_te_new_if (struct interface *ifp)
901 {
902   struct mpls_te_link *new;
903   int rc = -1;
904
905   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
909   if (lookup_linkparams_by_ifp (ifp) != NULL)
910     {
911       zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", (void *)ifp);
912       rc = 0; /* Do nothing here. */
913       goto out;
914     }
915
916   new = XCALLOC (MTYPE_OSPF_MPLS_TE, sizeof (struct mpls_te_link));
917   if (new == NULL)
918     {
919       zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno));
920       goto out;
921     }
922
923   new->instance = get_mpls_te_instance_value ();
924   new->ifp = ifp;
925   /* 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;
929
930   /* Initialize Link Parameters from Interface */
931   initialize_linkparams(new);
932
933   /* Set TE Parameters from Interface */
934   update_linkparams(new);
935
936   /* Add Link Parameters structure to the list */
937   listnode_add (OspfMplsTE.iflist, new);
938
939   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
943   /* Schedule Opaque-LSA refresh. *//* XXX */
944
945   rc = 0;
946 out:
947   return rc;
948 }
949
950 static int
951 ospf_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     {
958       struct list *iflist = OspfMplsTE.iflist;
959
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
967       XFREE (MTYPE_OSPF_MPLS_TE, lp);
968     }
969
970   /* Schedule Opaque-LSA refresh. *//* XXX */
971
972   rc = 0;
973 /*out:*/
974   return rc;
975 }
976
977 /* Main initialization / update function of the MPLS TE Link context */
978
979 /* Call when interface TE Link parameters are modified */
980 void
981 ospf_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
1027 static void
1028 ospf_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     }
1039
1040   if (oi->area == NULL || oi->area->ospf == NULL)
1041     {
1042       zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?", IF_NAME (oi));
1043       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? */
1051       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");
1053       ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
1054     }
1055 #endif
1056   /* Keep Area information in combination with linkparams. */
1057   lp->area = oi->area;
1058
1059   /* Keep interface MPLS-TE status */
1060   lp->flags = HAS_LINK_PARAMS(oi->ifp);
1061
1062   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
1071       /* Set Link type, Link ID, Local and Remote IP addr */
1072       set_linkparams_link_type (oi, lp);
1073       set_linkparams_link_id (oi, lp);
1074       set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4);
1075
1076       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 */
1087       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)
1090               || ntohl (old_id.value.s_addr) !=
1091               ntohl (lp->link_id.value.s_addr)))
1092         {
1093           if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
1094             ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1095           else
1096             ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA);
1097
1098         }
1099       break;
1100     default:
1101       lp->link_type.header.type = htons (0);
1102       lp->link_id.header.type   = htons (0);
1103
1104       if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
1105         ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
1106       break;
1107     }
1108
1109 out:
1110   return;
1111
1112 }
1113
1114 static void
1115 ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state)
1116 {
1117   /* Nothing to do here */
1118   return;
1119 }
1120
1121 /*------------------------------------------------------------------------*
1122  * Followings are OSPF protocol processing functions for MPLS-TE.
1123  *------------------------------------------------------------------------*/
1124
1125 static void
1126 build_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
1132 static void
1133 build_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
1144 static void
1145 build_link_subtlv (struct stream *s, struct te_tlv_header *tlvh)
1146     {
1147
1148   if ((tlvh != NULL) && (ntohs (tlvh->type) != 0))
1149     {
1150       build_tlv_header (s, tlvh);
1151       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
1152     }
1153   return;
1154 }
1155
1156 static void
1157 build_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
1162   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
1183   return;
1184 }
1185
1186 static void
1187 ospf_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. */
1205 static struct ospf_lsa *
1206 ospf_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;
1211   u_char options, lsa_type = 0;
1212   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
1224   options = OSPF_OPTION_O;      /* Don't forget this :-) */
1225
1226   /* 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     }
1256
1257   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1258     zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance",
1259                 lsa_type, inet_ntoa (lsa_id));
1260
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() ?");
1278       ospf_lsa_unlock (&new);
1279       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
1289 out:
1290   return new;
1291 }
1292
1293 static int
1294 ospf_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. */
1307   if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
1308     {
1309       zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
1310       ospf_lsa_unlock (&new);
1311       goto out;
1312     }
1313
1314   /* Now this link-parameter entry has associated LSA. */
1315   SET_FLAG (lp->flags, LPFLG_LSA_ENGAGED);
1316   /* Update new LSA origination count. */
1317   area->ospf->lsa_originate_count++;
1318
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));
1326       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);
1328       ospf_lsa_header_dump (new->data);
1329     }
1330
1331   rc = 0;
1332 out:
1333   return rc;
1334 }
1335
1336 static int
1337 ospf_mpls_te_lsa_originate_area (void *arg)
1338 {
1339   struct ospf_area *area = (struct ospf_area *) arg;
1340   struct listnode *node, *nnode;
1341   struct mpls_te_link *lp;
1342   int rc = -1;
1343
1344   if (OspfMplsTE.status == disabled)
1345     {
1346       zlog_info ("ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now.");
1347       rc = 0; /* This is not an error case. */
1348       goto out;
1349     }
1350
1351   for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
1352     {
1353       /* 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
1357       if (lp->area == NULL)
1358         continue;
1359
1360       if (! IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
1361         continue;
1362
1363       if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
1364         {
1365           if CHECK_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH)
1366             {
1367               UNSET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH);
1368               zlog_warn ("OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate");
1369               ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1370             }
1371           continue;
1372         }
1373       if (! is_mandated_params_set (lp))
1374         {
1375           zlog_warn ("ospf_mpls_te_lsa_originate_area: Link(%s) lacks some mandated MPLS-TE parameters.",
1376               lp->ifp ? lp->ifp->name : "?");
1377           continue;
1378         }
1379
1380       /* Ok, let's try to originate an LSA for this area and Link. */
1381       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 : "?");
1384       if (ospf_mpls_te_lsa_originate1 (area, lp) != 0)
1385         goto out;
1386     }
1387
1388   rc = 0;
1389 out:
1390   return rc;
1391 }
1392
1393 static int
1394 ospf_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;
1430 out:return rc;
1431 }
1432
1433 static int
1434 ospf_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;
1490 out:return rc;
1491 }
1492
1493 static struct ospf_lsa *
1494 ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
1495 {
1496   struct mpls_te_link *lp;
1497   struct ospf_area *area = lsa->area;
1498   struct ospf *top;
1499   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
1518   /* 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
1525   /* If the lsa's age reached to MaxAge, start flushing procedure. */
1526   if (IS_LSA_MAXAGE (lsa))
1527     {
1528       if (lp)
1529         UNSET_FLAG (lp->flags, LPFLG_LSA_ENGAGED);
1530       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. */
1544   /* 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)
1551     {
1552       zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
1553       ospf_lsa_unlock (&new);
1554       goto out;
1555     }
1556
1557   /* 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);
1562
1563   /* Debug logging. */
1564   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1565     {
1566       zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
1567                  new->data->type, inet_ntoa (new->data->id));
1568       ospf_lsa_header_dump (new->data);
1569     }
1570
1571 out:
1572   return new;
1573 }
1574
1575 void
1576 ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, opcode_t opcode)
1577 {
1578   struct ospf_lsa lsa;
1579   struct lsa_header lsah;
1580   struct ospf *top;
1581   u_int32_t tmp;
1582
1583   memset (&lsa, 0, sizeof (lsa));
1584   memset (&lsah, 0, sizeof (lsah));
1585   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   }
1592
1593   lsa.area = lp->area;
1594   lsa.data = &lsah;
1595   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     }
1621
1622   switch (opcode)
1623     {
1624     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         }
1642       break;
1643     case REFRESH_THIS_LSA:
1644       ospf_opaque_lsa_refresh_schedule (&lsa);
1645       break;
1646     case FLUSH_THIS_LSA:
1647       /* Reset Activity flag */
1648       lp->flags = LPFLG_LSA_INACTIVE;
1649       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
1659
1660 /*------------------------------------------------------------------------*
1661  * Followings are vty session control functions.
1662  *------------------------------------------------------------------------*/
1663
1664 static u_int16_t
1665 show_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)
1670     vty_out (vty, "  Router-Address: %s%s", inet_ntoa (top->value),
1671              VTY_NEWLINE);
1672   else
1673     zlog_debug ("    Router-Address: %s", inet_ntoa (top->value));
1674
1675   return TLV_SIZE (tlvh);
1676 }
1677
1678 static u_int16_t
1679 show_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)
1684     vty_out (vty, "  Link: %u octets of data%s", ntohs (top->header.length),
1685              VTY_NEWLINE);
1686   else
1687     zlog_debug ("    Link: %u octets of data", ntohs (top->header.length));
1688
1689   return TLV_HDR_SIZE;  /* Here is special, not "TLV_SIZE". */
1690 }
1691
1692 static u_int16_t
1693 show_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)
1712     vty_out (vty, "  Link-Type: %s (%u)%s", cp, top->link_type.value,
1713              VTY_NEWLINE);
1714   else
1715     zlog_debug ("    Link-Type: %s (%u)", cp, top->link_type.value);
1716
1717   return TLV_SIZE (tlvh);
1718 }
1719
1720 static u_int16_t
1721 show_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
1729     zlog_debug ("    Link-ID: %s", inet_ntoa (top->value));
1730
1731   return TLV_SIZE (tlvh);
1732 }
1733
1734 static u_int16_t
1735 show_vty_link_subtlv_lclif_ipaddr (struct vty *vty,
1736                                    struct te_tlv_header *tlvh)
1737 {
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
1747     zlog_debug ("    Local Interface IP Address(es): %d", n);
1748
1749   for (i = 0; i < n; i++)
1750     {
1751       if (vty != NULL)
1752         vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]),
1753                  VTY_NEWLINE);
1754       else
1755         zlog_debug ("      #%d: %s", i, inet_ntoa (top->value[i]));
1756     }
1757   return TLV_SIZE (tlvh);
1758 }
1759
1760 static u_int16_t
1761 show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty,
1762                                    struct te_tlv_header *tlvh)
1763 {
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
1772     zlog_debug ("    Remote Interface IP Address(es): %d", n);
1773
1774   for (i = 0; i < n; i++)
1775     {
1776       if (vty != NULL)
1777         vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]),
1778                  VTY_NEWLINE);
1779       else
1780         zlog_debug ("      #%d: %s", i, inet_ntoa (top->value[i]));
1781     }
1782   return TLV_SIZE (tlvh);
1783 }
1784
1785 static u_int16_t
1786 show_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)
1792     vty_out (vty, "  Traffic Engineering Metric: %u%s",
1793              (u_int32_t) ntohl (top->value), VTY_NEWLINE);
1794   else
1795     zlog_debug ("    Traffic Engineering Metric: %u",
1796                 (u_int32_t) ntohl (top->value));
1797
1798   return TLV_SIZE (tlvh);
1799 }
1800
1801 static u_int16_t
1802 show_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;
1808   fval = ntohf (top->value);
1809
1810   if (vty != NULL)
1811     vty_out (vty, "  Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
1812   else
1813     zlog_debug ("    Maximum Bandwidth: %g (Bytes/sec)", fval);
1814
1815   return TLV_SIZE (tlvh);
1816 }
1817
1818 static u_int16_t
1819 show_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;
1825   fval = ntohf (top->value);
1826
1827   if (vty != NULL)
1828     vty_out (vty, "  Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval,
1829              VTY_NEWLINE);
1830   else
1831     zlog_debug ("    Maximum Reservable Bandwidth: %g (Bytes/sec)", fval);
1832
1833   return TLV_SIZE (tlvh);
1834 }
1835
1836 static u_int16_t
1837 show_vty_link_subtlv_unrsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
1838 {
1839   struct te_link_subtlv_unrsv_bw *top;
1840   float fval1, fval2;
1841   int i;
1842
1843   top = (struct te_link_subtlv_unrsv_bw *) tlvh;
1844   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)
1849     {
1850       fval1 = ntohf (top->value[i]);
1851       fval2 = ntohf (top->value[i+1]);
1852
1853       if (vty != NULL)
1854         vty_out(vty, "    [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)%s",
1855                 i, fval1, i+1, fval2, VTY_NEWLINE);
1856       else
1857         zlog_debug ("      [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)",
1858                     i, fval1, i+1, fval2);
1859     }
1860
1861   return TLV_SIZE (tlvh);
1862 }
1863
1864 static u_int16_t
1865 show_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)
1871     vty_out (vty, "  Resource class/color: 0x%x%s",
1872              (u_int32_t) ntohl (top->value), VTY_NEWLINE);
1873   else
1874     zlog_debug ("    Resource Class/Color: 0x%x",
1875                 (u_int32_t) ntohl (top->value));
1876
1877   return TLV_SIZE (tlvh);
1878 }
1879
1880 static u_int16_t
1881 show_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
1903 static u_int16_t
1904 show_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
1926 static u_int16_t
1927 show_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
1943 static u_int16_t
1944 show_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
1959 static u_int16_t
1960 show_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
1980 static u_int16_t
1981 show_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
2002 static u_int16_t
2003 show_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
2019 static u_int16_t
2020 show_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
2042 static u_int16_t
2043 show_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
2061 static u_int16_t
2062 show_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
2080 static u_int16_t
2081 show_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);
2095
2096   return TLV_SIZE (tlvh);
2097 }
2098
2099 static u_int16_t
2100 show_vty_unknown_tlv (struct vty *vty, struct te_tlv_header *tlvh)
2101 {
2102   if (vty != NULL)
2103     vty_out (vty, "  Unknown TLV: [type(0x%x), length(0x%x)]%s",
2104              ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
2105   else
2106     zlog_debug ("    Unknown TLV: [type(0x%x), length(0x%x)]",
2107                 ntohs (tlvh->type), ntohs (tlvh->length));
2108
2109   return TLV_SIZE (tlvh);
2110 }
2111
2112 static u_int16_t
2113 ospf_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;
2151         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;
2184         default:
2185           sum += show_vty_unknown_tlv (vty, tlvh);
2186           break;
2187         }
2188     }
2189   return sum;
2190 }
2191
2192 static void
2193 ospf_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
2234 static void
2235 ospf_mpls_te_config_write_router (struct vty *vty)
2236 {
2237
2238   if (OspfMplsTE.status == enabled)
2239     {
2240       vty_out (vty, "  mpls-te on%s", VTY_NEWLINE);
2241       vty_out (vty, "  mpls-te router-address %s%s",
2242                inet_ntoa (OspfMplsTE.router_addr.value), VTY_NEWLINE);
2243     }
2244
2245   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);
2250
2251   return;
2252 }
2253
2254 /*------------------------------------------------------------------------*
2255  * Followings are vty command functions.
2256  *------------------------------------------------------------------------*/
2257
2258 DEFUN (ospf_mpls_te_on,
2259        ospf_mpls_te_on_cmd,
2260        "mpls-te on",
2261        MPLS_TE_STR
2262        "Enable the MPLS-TE functionality\n")
2263 {
2264   struct listnode *node;
2265   struct mpls_te_link *lp;
2266
2267   if (OspfMplsTE.status == enabled)
2268     return CMD_SUCCESS;
2269
2270   if (IS_DEBUG_OSPF_EVENT)
2271     zlog_debug ("MPLS-TE: OFF -> ON");
2272
2273   OspfMplsTE.status = enabled;
2274
2275   /* Reoriginate RFC3630 & RFC6827 Links */
2276   ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA);
2277
2278   /* 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     }
2289
2290   return CMD_SUCCESS;
2291 }
2292
2293 DEFUN (no_ospf_mpls_te,
2294        no_ospf_mpls_te_cmd,
2295        "no mpls-te",
2296        NO_STR
2297        "Disable the MPLS-TE functionality\n")
2298 {
2299   struct listnode *node, *nnode;
2300   struct mpls_te_link *lp;
2301
2302   if (OspfMplsTE.status == disabled)
2303     return CMD_SUCCESS;
2304
2305   if (IS_DEBUG_OSPF_EVENT)
2306     zlog_debug ("MPLS-TE: ON -> OFF");
2307
2308   OspfMplsTE.status = disabled;
2309
2310   for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
2311     if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)
2312         ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
2313
2314   return CMD_SUCCESS;
2315 }
2316
2317 DEFUN (ospf_mpls_te_router_addr,
2318        ospf_mpls_te_router_addr_cmd,
2319        "mpls-te router-address A.B.C.D",
2320        MPLS_TE_STR
2321        "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
2334       || ntohl (ra->value.s_addr) != ntohl (value.s_addr))
2335     {
2336       struct listnode *node, *nnode;
2337       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
2345       for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
2346         {
2347           if ((lp->area == NULL) || IS_FLOOD_AS (lp->type))
2348             continue;
2349
2350           if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED))
2351             {
2352               need_to_reoriginate = 1;
2353               break;
2354             }
2355         }
2356       
2357       for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
2358         {
2359           if ((lp->area == NULL) || IS_FLOOD_AS (lp->type))
2360             continue;
2361
2362           if (need_to_reoriginate)
2363             SET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH);
2364           else
2365             ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
2366         }
2367
2368       if (need_to_reoriginate)
2369         ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA);
2370     }
2371 out:
2372   return CMD_SUCCESS;
2373 }
2374
2375 static int
2376 set_inter_as_mode (struct vty *vty, const char *mode_name,
2377                    const char *area_id)
2378 {
2379   enum inter_as_mode mode;
2380   struct listnode *node;
2381   struct mpls_te_link *lp;
2382   int format;
2383
2384   if (OspfMplsTE.status == enabled)
2385     {
2386
2387       /* 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         }
2401
2402       if (IS_DEBUG_OSPF_EVENT)
2403         zlog_debug ("MPLS-TE: Inter-AS enable with %s flooding support",
2404                     mode2text[mode]);
2405
2406       /* 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         }
2437     }
2438   return CMD_SUCCESS;
2439 }
2440
2441 DEFUN (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")
2447 {
2448   return set_inter_as_mode (vty, "as", "");
2449 }
2450
2451 DEFUN (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
2463 DEFUN (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;
2472   struct mpls_te_link *lp;
2473
2474   if (IS_DEBUG_OSPF_EVENT)
2475     zlog_debug ("MPLS-TE: Inter-AS support OFF");
2476
2477   if ((OspfMplsTE.status == enabled) && (OspfMplsTE.inter_as != Disable))
2478     {
2479       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);
2484     }
2485
2486   /* Deregister the Callbacks for Inter-AS suport */
2487   ospf_mpls_te_unregister ();
2488
2489   return CMD_SUCCESS;
2490 }
2491
2492 DEFUN (show_ip_ospf_mpls_te_router,
2493        show_ip_ospf_mpls_te_router_cmd,
2494        "show ip ospf mpls-te router",
2495        SHOW_STR
2496        IP_STR
2497        OSPF_STR
2498        "MPLS-TE information\n"
2499        "MPLS-TE Router parameters\n")
2500 {
2501   if (OspfMplsTE.status == enabled)
2502     {
2503       vty_out (vty, "--- MPLS-TE router parameters ---%s", VTY_NEWLINE);
2504
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
2513 static void
2514 show_mpls_te_link_sub (struct vty *vty, struct interface *ifp)
2515 {
2516   struct mpls_te_link *lp;
2517
2518   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))
2523     {
2524       /* 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         {
2543       vty_out (vty, "-- MPLS-TE link parameters for %s --%s",
2544                ifp->name, VTY_NEWLINE);
2545         }
2546
2547       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);
2584     }
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
2594 DEFUN (show_ip_ospf_mpls_te_link,
2595        show_ip_ospf_mpls_te_link_cmd,
2596        "show ip ospf mpls-te interface [INTERFACE]",
2597        SHOW_STR
2598        IP_STR
2599        OSPF_STR
2600        "MPLS-TE information\n"
2601        "Interface information\n"
2602        "Interface name\n")
2603 {
2604   struct interface *ifp;
2605   struct listnode *node, *nnode;
2606
2607   /* Show All Interfaces. */
2608   if (argc == 0)
2609     {
2610       for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
2611         show_mpls_te_link_sub (vty, ifp);
2612     }
2613   /* 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
2625 static void
2626 ospf_mpls_te_register_vty (void)
2627 {
2628   install_element (VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd);
2629   install_element (VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd);
2630
2631   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);
2637
2638   return;
2639 }