ospf_te.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:52k
源码类别:

网络

开发平台:

Unix_Linux

  1. /*
  2.  * This is an implementation of draft-katz-yeung-ospf-traffic-06.txt
  3.  * Copyright (C) 2001 KDD R&D Laboratories, Inc.
  4.  * http://www.kddlabs.co.jp/
  5.  *
  6.  * This file is part of GNU Zebra.
  7.  *
  8.  * GNU Zebra is free software; you can redistribute it and/or modify it
  9.  * under the terms of the GNU General Public License as published by the
  10.  * Free Software Foundation; either version 2, or (at your option) any
  11.  * later version.
  12.  * 
  13.  * GNU Zebra is distributed in the hope that it will be useful, but
  14.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
  20.  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  21.  * 02111-1307, USA.
  22.  */
  23. /***** MTYPE definition is not reflected to "memory.h" yet. *****/
  24. #define MTYPE_OSPF_MPLS_TE_LINKPARAMS 0
  25. #include <zebra.h>
  26. #ifdef HAVE_OSPF_TE
  27. #ifndef HAVE_OPAQUE_LSA
  28. #error "Wrong configure option"
  29. #endif /* HAVE_OPAQUE_LSA */
  30. #include "linklist.h"
  31. #include "prefix.h"
  32. #include "if.h"
  33. #include "table.h"
  34. #include "memory.h"
  35. #include "command.h"
  36. #include "vty.h"
  37. #include "stream.h"
  38. #include "log.h"
  39. #include "thread.h"
  40. #include "hash.h"
  41. #include "sockunion.h" /* for inet_aton() */
  42. #include "ospfd/ospfd.h"
  43. #include "ospfd/ospf_interface.h"
  44. #include "ospfd/ospf_ism.h"
  45. #include "ospfd/ospf_asbr.h"
  46. #include "ospfd/ospf_lsa.h"
  47. #include "ospfd/ospf_lsdb.h"
  48. #include "ospfd/ospf_neighbor.h"
  49. #include "ospfd/ospf_nsm.h"
  50. #include "ospfd/ospf_flood.h"
  51. #include "ospfd/ospf_packet.h"
  52. #include "ospfd/ospf_spf.h"
  53. #include "ospfd/ospf_dump.h"
  54. #include "ospfd/ospf_route.h"
  55. #include "ospfd/ospf_ase.h"
  56. #include "ospfd/ospf_zebra.h"
  57. #include "ospfd/ospf_te.h"
  58. /* Following structure are internal use only. */
  59. struct ospf_mpls_te
  60. {
  61.   enum { disabled, enabled } status;
  62.   /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */
  63.   list iflist;
  64.   /* Store Router-TLV in network byte order. */
  65.   struct te_tlv_router_addr router_addr;
  66. };
  67. struct mpls_te_link
  68. {
  69.   /*
  70.    * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field
  71.    * is subdivided into 8-bit "unused" field and 16-bit "instance" field.
  72.    * In this implementation, each Link-TLV has its own instance.
  73.    */
  74.   u_int32_t instance;
  75.   /* Reference pointer to a Zebra-interface. */
  76.   struct interface *ifp;
  77.   /* Area info in which this MPLS-TE link belongs to. */
  78.   struct ospf_area *area;
  79.   /* Flags to manage this link parameters. */
  80.   u_int32_t flags;
  81. #define LPFLG_LOOKUP_DONE 0x1
  82. #define LPFLG_LSA_ENGAGED 0x2
  83. #define LPFLG_LSA_FORCED_REFRESH 0x4
  84.   /* Store Link-TLV in network byte order. */
  85.   struct te_tlv_link link_header;
  86.   struct te_link_subtlv_link_type link_type;
  87.   struct te_link_subtlv_link_id link_id;
  88.   struct te_link_subtlv_lclif_ipaddr *lclif_ipaddr;
  89.   struct te_link_subtlv_rmtif_ipaddr *rmtif_ipaddr;
  90.   struct te_link_subtlv_te_metric te_metric;
  91.   struct te_link_subtlv_max_bw max_bw;
  92.   struct te_link_subtlv_max_rsv_bw max_rsv_bw;
  93.   struct te_link_subtlv_unrsv_bw unrsv_bw;
  94.   struct te_link_subtlv_rsc_clsclr rsc_clsclr;
  95. };
  96. /*
  97.  * Global variable to manage Opaque-LSA/MPLS-TE on this node.
  98.  * Note that all parameter values are stored in network byte order.
  99.  */
  100. static struct ospf_mpls_te OspfMplsTE;
  101. enum oifstate {
  102.   OI_ANY, OI_DOWN, OI_UP
  103. };
  104. enum sched_opcode {
  105.   REORIGINATE_PER_AREA, REFRESH_THIS_LSA, FLUSH_THIS_LSA
  106. };
  107. /*------------------------------------------------------------------------*
  108.  * Followings are initialize/terminate functions for MPLS-TE handling.
  109.  *------------------------------------------------------------------------*/
  110. static int ospf_mpls_te_new_if (struct interface *ifp);
  111. static int ospf_mpls_te_del_if (struct interface *ifp);
  112. static void ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_status);
  113. static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status);
  114. static void ospf_mpls_te_config_write_router (struct vty *vty);
  115. static void ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp);
  116. static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa);
  117. static int ospf_mpls_te_lsa_originate (void *arg);
  118. static void ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);
  119. static void ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, enum sched_opcode);
  120. static void del_mpls_te_link (void *val);
  121. static void ospf_mpls_te_register_vty (void);
  122. int
  123. ospf_mpls_te_init (void)
  124. {
  125.   int rc;
  126.   rc = ospf_register_opaque_functab (
  127.                 OSPF_OPAQUE_AREA_LSA,
  128.                 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
  129. ospf_mpls_te_new_if,
  130. ospf_mpls_te_del_if,
  131. ospf_mpls_te_ism_change,
  132. ospf_mpls_te_nsm_change,
  133. ospf_mpls_te_config_write_router,
  134. ospf_mpls_te_config_write_if,
  135. NULL,/* ospf_mpls_te_config_write_debug */
  136.                 ospf_mpls_te_show_info,
  137.                 ospf_mpls_te_lsa_originate,
  138.                 ospf_mpls_te_lsa_refresh,
  139. NULL,/* ospf_mpls_te_new_lsa_hook */
  140. NULL /* ospf_mpls_te_del_lsa_hook */);
  141.   if (rc != 0)
  142.     {
  143.       zlog_warn ("ospf_mpls_te_init: Failed to register functions");
  144.       goto out;
  145.     }
  146.   memset (&OspfMplsTE, 0, sizeof (struct ospf_mpls_te));
  147.   OspfMplsTE.status = disabled;
  148.   OspfMplsTE.iflist = list_new ();
  149.   OspfMplsTE.iflist->del = del_mpls_te_link;
  150.   ospf_mpls_te_register_vty ();
  151. out:
  152.   return rc;
  153. }
  154. void
  155. ospf_mpls_te_term (void)
  156. {
  157.   list_delete (OspfMplsTE.iflist);
  158.   OspfMplsTE.iflist = NULL;
  159.   OspfMplsTE.status = disabled;
  160.   ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA,
  161.                               OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
  162.   return;
  163. }
  164. /*------------------------------------------------------------------------*
  165.  * Followings are control functions for MPLS-TE parameters management.
  166.  *------------------------------------------------------------------------*/
  167. static void
  168. del_mpls_te_link (void *val)
  169. {
  170.   XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, val);
  171.   return;
  172. }
  173. static u_int32_t
  174. get_mpls_te_instance_value ()
  175. {
  176.   static u_int32_t seqno = 0;
  177.   if (LEGAL_TE_INSTANCE_RANGE (seqno + 1))
  178.     seqno += 1;
  179.   else
  180.     seqno  = 1; /* Avoid zero. */
  181.   return seqno;
  182. }
  183. static struct ospf_interface *
  184. lookup_oi_by_ifp (struct interface *ifp,
  185.                   struct ospf_area *area, enum oifstate oifstate)
  186. {
  187.   struct ospf_interface *oi = NULL;
  188.   struct route_node *rn;
  189.   for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
  190.     {
  191.       if ((oi = rn->info) == NULL)
  192.         continue;
  193.       switch (oifstate)
  194.         {
  195.         case OI_ANY:
  196.           break;
  197.         case OI_DOWN:
  198.           if (ospf_if_is_enable (oi))
  199.             continue;
  200.           break;
  201.         case OI_UP:
  202.           if (! ospf_if_is_enable (oi))
  203.             continue;
  204.           break;
  205.         default:
  206.           zlog_warn ("lookup_oi_by_ifp: Unknown oifstate: %x", oifstate);
  207.           goto out;
  208.         }
  209.       if (area == NULL || oi->area == area)
  210.         return oi;
  211.     }
  212. out:
  213.   return NULL;
  214. }
  215. static struct mpls_te_link *
  216. lookup_linkparams_by_ifp (struct interface *ifp)
  217. {
  218.   listnode node;
  219.   struct mpls_te_link *lp;
  220.   for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
  221.     if ((lp = getdata (node)) != NULL)
  222.       if (lp->ifp == ifp)
  223.         return lp;
  224.   return NULL;
  225. }
  226. static struct mpls_te_link *
  227. lookup_linkparams_by_instance (struct ospf_lsa *lsa)
  228. {
  229.   listnode node;
  230.   struct mpls_te_link *lp;
  231.   int key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
  232.   for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
  233.     if ((lp = getdata (node)) != NULL)
  234.       if (lp->instance == key)
  235.         return lp;
  236.   zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key);
  237.   return NULL;
  238. }
  239. static void
  240. ospf_mpls_te_foreach_area (
  241.   void (*func)(struct mpls_te_link *lp, enum sched_opcode),
  242.   enum sched_opcode sched_opcode)
  243. {
  244.   listnode node, node2;
  245.   struct mpls_te_link *lp;
  246.   struct ospf_area *area;
  247.   for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
  248.     {
  249.       if ((lp = getdata (node)) == NULL)
  250.         continue;
  251.       if ((area = lp->area) == NULL)
  252.         continue;
  253.       if (lp->flags & LPFLG_LOOKUP_DONE)
  254.         continue;
  255.       if (func != NULL)
  256.         (* func)(lp, sched_opcode);
  257.       for (node2 = nextnode (node); node2; nextnode (node2))
  258.         if ((lp = getdata (node2)) != NULL)
  259.           if (lp->area != NULL)
  260.             if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
  261.               lp->flags |= LPFLG_LOOKUP_DONE;
  262.     }
  263.   for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
  264.     if ((lp = getdata (node)) != NULL)
  265.       if (lp->area != NULL)
  266.         lp->flags &= ~LPFLG_LOOKUP_DONE;
  267.   return;
  268. }
  269. static void
  270. set_mpls_te_router_addr (struct in_addr ipv4)
  271. {
  272.   OspfMplsTE.router_addr.header.type   = htons (TE_TLV_ROUTER_ADDR);
  273.   OspfMplsTE.router_addr.header.length = htons (sizeof (ipv4));
  274.   OspfMplsTE.router_addr.value = ipv4;
  275.   return;
  276. }
  277. static void
  278. set_linkparams_link_header (struct mpls_te_link *lp)
  279. {
  280.   struct te_tlv_header *tlvh;
  281.   u_int16_t length = 0;
  282.   /* TE_LINK_SUBTLV_LINK_TYPE */
  283.   if (ntohs (lp->link_type.header.type) != 0)
  284.     length += TLV_SIZE (&lp->link_type.header);
  285.   /* TE_LINK_SUBTLV_LINK_ID */
  286.   if (ntohs (lp->link_id.header.type) != 0)
  287.     length += TLV_SIZE (&lp->link_id.header);
  288.   /* TE_LINK_SUBTLV_LCLIF_IPADDR */
  289.   if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL
  290.   &&  ntohs (tlvh->type) != 0)
  291.     length += TLV_SIZE (tlvh);
  292.   /* TE_LINK_SUBTLV_RMTIF_IPADDR */
  293.   if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL
  294.   &&  ntohs (tlvh->type) != 0)
  295.     length += TLV_SIZE (tlvh);
  296.   /* TE_LINK_SUBTLV_TE_METRIC */
  297.   if (ntohs (lp->te_metric.header.type) != 0)
  298.     length += TLV_SIZE (&lp->te_metric.header);
  299.   /* TE_LINK_SUBTLV_MAX_BW */
  300.   if (ntohs (lp->max_bw.header.type) != 0)
  301.     length += TLV_SIZE (&lp->max_bw.header);
  302.   /* TE_LINK_SUBTLV_MAX_RSV_BW */
  303.   if (ntohs (lp->max_rsv_bw.header.type) != 0)
  304.     length += TLV_SIZE (&lp->max_rsv_bw.header);
  305.   /* TE_LINK_SUBTLV_UNRSV_BW */
  306.   if (ntohs (lp->unrsv_bw.header.type) != 0)
  307.     length += TLV_SIZE (&lp->unrsv_bw.header);
  308.   /* TE_LINK_SUBTLV_RSC_CLSCLR */
  309.   if (ntohs (lp->rsc_clsclr.header.type) != 0)
  310.     length += TLV_SIZE (&lp->rsc_clsclr.header);
  311.   lp->link_header.header.type   = htons (TE_TLV_LINK);
  312.   lp->link_header.header.length = htons (length);
  313.   return;
  314. }
  315. static void
  316. set_linkparams_link_type (struct ospf_interface *oi, struct mpls_te_link *lp)
  317. {
  318.   lp->link_type.header.type   = htons (TE_LINK_SUBTLV_LINK_TYPE);
  319.   lp->link_type.header.length = htons (sizeof (lp->link_type.link_type.value));
  320.   switch (oi->type)
  321.     {
  322.     case OSPF_IFTYPE_POINTOPOINT:
  323.       lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP;
  324.       break;
  325.     case OSPF_IFTYPE_BROADCAST:
  326.     case OSPF_IFTYPE_NBMA:
  327.       lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA;
  328.       break;
  329.     default:
  330.       /* Not supported yet. *//* XXX */
  331.       lp->link_type.header.type = htons (0);
  332.       break;
  333.     }
  334.   return;
  335. }
  336. static void
  337. set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp)
  338. {
  339.   struct ospf_neighbor *nbr;
  340.   int done = 0;
  341.   lp->link_id.header.type   = htons (TE_LINK_SUBTLV_LINK_ID);
  342.   lp->link_id.header.length = htons (sizeof (lp->link_id.value));
  343.   /*
  344.    * The Link ID is identical to the contents of the Link ID field
  345.    * in the Router LSA for these link types.
  346.    */
  347.   switch (oi->type)
  348.     {
  349.     case OSPF_IFTYPE_POINTOPOINT:
  350.       /* Take the router ID of the neighbor. */
  351.       if ((nbr = ospf_nbr_lookup_ptop (oi))
  352.   && nbr->state == NSM_Full)
  353.         {
  354.           lp->link_id.value = nbr->router_id;
  355.           done = 1;
  356.         }
  357.       break;
  358.     case OSPF_IFTYPE_BROADCAST:
  359.     case OSPF_IFTYPE_NBMA:
  360.       /* Take the interface address of the designated router. */
  361.       if ((nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi))) == NULL)
  362.         break;
  363.       if (nbr->state == NSM_Full
  364.       || (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
  365.       &&  ospf_nbr_count (oi, NSM_Full) > 0))
  366.         {
  367.           lp->link_id.value = DR (oi);
  368.           done = 1;
  369.         }
  370.       break;
  371.     default:
  372.       /* Not supported yet. *//* XXX */
  373.       lp->link_id.header.type = htons (0);
  374.       break;
  375.     }
  376.   if (! done)
  377.     {
  378.       struct in_addr mask;
  379.       masklen2ip (oi->address->prefixlen, &mask);
  380.       lp->link_id.value.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
  381.      }
  382.   return;
  383. }
  384. static void
  385. set_linkparams_te_metric (struct mpls_te_link *lp, u_int32_t te_metric)
  386. {
  387.   lp->te_metric.header.type   = htons (TE_LINK_SUBTLV_TE_METRIC);
  388.   lp->te_metric.header.length = htons (sizeof (lp->te_metric.value));
  389.   lp->te_metric.value = htonl (te_metric);
  390.   return;
  391. }
  392. static void
  393. set_linkparams_max_bw (struct mpls_te_link *lp, float *fp)
  394. {
  395.   lp->max_bw.header.type   = htons (TE_LINK_SUBTLV_MAX_BW);
  396.   lp->max_bw.header.length = htons (sizeof (lp->max_bw.value));
  397.   htonf (fp, &lp->max_bw.value);
  398.   return;
  399. }
  400. static void
  401. set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float *fp)
  402. {
  403.   lp->max_rsv_bw.header.type   = htons (TE_LINK_SUBTLV_MAX_RSV_BW);
  404.   lp->max_rsv_bw.header.length = htons (sizeof (lp->max_rsv_bw.value));
  405.   htonf (fp, &lp->max_rsv_bw.value);
  406.   return;
  407. }
  408. static void
  409. set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float *fp)
  410. {
  411.   /* Note that TLV-length field is the size of array. */
  412.   lp->unrsv_bw.header.type   = htons (TE_LINK_SUBTLV_UNRSV_BW);
  413.   lp->unrsv_bw.header.length = htons (sizeof (lp->unrsv_bw.value));
  414.   htonf (fp, &lp->unrsv_bw.value [priority]);
  415.   return;
  416. }
  417. static void
  418. set_linkparams_rsc_clsclr (struct mpls_te_link *lp, u_int32_t classcolor)
  419. {
  420.   lp->rsc_clsclr.header.type   = htons (TE_LINK_SUBTLV_RSC_CLSCLR);
  421.   lp->rsc_clsclr.header.length = htons (sizeof (lp->rsc_clsclr.value));
  422.   lp->rsc_clsclr.value = htonl (classcolor);
  423.   return;
  424. }
  425. static void
  426. initialize_linkparams (struct mpls_te_link *lp)
  427. {
  428.   struct interface *ifp = lp->ifp;
  429.   struct ospf_interface *oi;
  430.   float fval;
  431.   int i;
  432.   if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL)
  433.     return;
  434.   /*
  435.    * Try to set initial values those can be derived from
  436.    * zebra-interface information.
  437.    */
  438.   set_linkparams_link_type (oi, lp);
  439.   /*
  440.    * Linux and *BSD kernel holds bandwidth parameter as an "int" type.
  441.    * We may have to reconsider, if "ifp->bandwidth" type changes to float.
  442.    */
  443.   fval = (float)((ifp->bandwidth ? ifp->bandwidth
  444.                                  : OSPF_DEFAULT_BANDWIDTH) * 1000 / 8);
  445.   set_linkparams_max_bw (lp, &fval);
  446.   set_linkparams_max_rsv_bw (lp, &fval);
  447.   for (i = 0; i < 8; i++)
  448.     set_linkparams_unrsv_bw (lp, i, &fval);
  449.   return;
  450. }
  451. static int
  452. is_mandated_params_set (struct mpls_te_link *lp)
  453. {
  454.   int rc = 0;
  455.   if (ntohs (OspfMplsTE.router_addr.header.type) == 0)
  456.     goto out;
  457.   if (ntohs (lp->link_type.header.type) == 0)
  458.     goto out;
  459.   if (ntohs (lp->link_id.header.type) == 0)
  460.     goto out;
  461.   rc = 1;
  462. out:
  463.   return rc;
  464. }
  465. /*------------------------------------------------------------------------*
  466.  * Followings are callback functions against generic Opaque-LSAs handling.
  467.  *------------------------------------------------------------------------*/
  468. static int
  469. ospf_mpls_te_new_if (struct interface *ifp)
  470. {
  471.   struct mpls_te_link *new;
  472.   int rc = -1;
  473.   if (lookup_linkparams_by_ifp (ifp) != NULL)
  474.     {
  475.       zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", ifp);
  476.       rc = 0; /* Do nothing here. */
  477.       goto out;
  478.     }
  479.   if ((new = XMALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS,
  480.                   sizeof (struct mpls_te_link))) == NULL)
  481.     {
  482.       zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", strerror (errno));
  483.       goto out;
  484.     }
  485.   memset (new, 0, sizeof (struct mpls_te_link));
  486.   new->area = NULL;
  487.   new->flags = 0;
  488.   new->instance = get_mpls_te_instance_value ();
  489.   new->ifp = ifp;
  490.   initialize_linkparams (new);
  491.   listnode_add (OspfMplsTE.iflist, new);
  492.   /* Schedule Opaque-LSA refresh. *//* XXX */
  493.   rc = 0;
  494. out:
  495.   return rc;
  496. }
  497. static int
  498. ospf_mpls_te_del_if (struct interface *ifp)
  499. {
  500.   struct mpls_te_link *lp;
  501.   int rc = -1;
  502.   if ((lp = lookup_linkparams_by_ifp (ifp)) != NULL)
  503.     {
  504.       list iflist = OspfMplsTE.iflist;
  505.       /* Dequeue listnode entry from the list. */
  506.       listnode_delete (iflist, lp);
  507.       /* Avoid misjudgement in the next lookup. */
  508.       if (listcount (iflist) == 0)
  509.         iflist->head = iflist->tail = NULL;
  510.       XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, lp);
  511.     }
  512.   /* Schedule Opaque-LSA refresh. *//* XXX */
  513.   rc = 0;
  514. /*out:*/
  515.   return rc;
  516. }
  517. static void
  518. ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state)
  519. {
  520.   struct te_link_subtlv_link_type old_type;
  521.   struct te_link_subtlv_link_id   old_id;
  522.   struct mpls_te_link *lp;
  523.   if ((lp = lookup_linkparams_by_ifp (oi->ifp)) == NULL)
  524.     {
  525.       zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi));
  526.       goto out;
  527.     }
  528.   if (oi->area == NULL || oi->area->ospf == NULL)
  529.     {
  530.       zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
  531. IF_NAME (oi));
  532.       goto out;
  533.     }
  534. #ifdef notyet
  535.   if ((lp->area != NULL
  536.   &&   ! IPV4_ADDR_SAME (&lp->area->area_id, &oi->area->area_id))
  537.   || (lp->area != NULL && oi->area == NULL))
  538.     {
  539.       /* How should we consider this case? */
  540.       zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A");
  541.       ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
  542.     }
  543. #endif
  544.   /* Keep Area information in conbination with linkparams. */
  545.   lp->area = oi->area;
  546.   switch (oi->state)
  547.     {
  548.     case ISM_PointToPoint:
  549.     case ISM_DROther:
  550.     case ISM_Backup:
  551.     case ISM_DR:
  552.       old_type = lp->link_type;
  553.       old_id   = lp->link_id;
  554.       set_linkparams_link_type (oi, lp);
  555.       set_linkparams_link_id (oi, lp);
  556.       if ((ntohs (old_type.header.type) != ntohs (lp->link_type.header.type)
  557.       ||   old_type.link_type.value     != lp->link_type.link_type.value)
  558.       ||  (ntohs (old_id.header.type)   != ntohs (lp->link_id.header.type)
  559.       ||   ntohl (old_id.value.s_addr)  != ntohl (lp->link_id.value.s_addr)))
  560.         {
  561.           if (lp->flags & LPFLG_LSA_ENGAGED)
  562.             ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
  563.           else
  564.             ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
  565.         }
  566.       break;
  567.     default:
  568.       lp->link_type.header.type = htons (0);
  569.       lp->link_id.header.type   = htons (0);
  570.       if (lp->flags & LPFLG_LSA_ENGAGED)
  571.         ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
  572.       break;
  573.     }
  574. out:
  575.   return;
  576. }
  577. static void
  578. ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state)
  579. {
  580.   /* So far, nothing to do here. */
  581.   return;
  582. }
  583. /*------------------------------------------------------------------------*
  584.  * Followings are OSPF protocol processing functions for MPLS-TE.
  585.  *------------------------------------------------------------------------*/
  586. static void
  587. build_tlv_header (struct stream *s, struct te_tlv_header *tlvh)
  588. {
  589.   stream_put (s, tlvh, sizeof (struct te_tlv_header));
  590.   return;
  591. }
  592. static void
  593. build_router_tlv (struct stream *s)
  594. {
  595.   struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header;
  596.   if (ntohs (tlvh->type) != 0)
  597.     {
  598.       build_tlv_header (s, tlvh);
  599.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  600.     }
  601.   return;
  602. }
  603. static void
  604. build_link_subtlv_link_type (struct stream *s, struct mpls_te_link *lp)
  605. {
  606.   struct te_tlv_header *tlvh = &lp->link_type.header;
  607.   if (ntohs (tlvh->type) != 0)
  608.     {
  609.       build_tlv_header (s, tlvh);
  610.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  611.     }
  612.   return;
  613. }
  614. static void
  615. build_link_subtlv_link_id (struct stream *s, struct mpls_te_link *lp)
  616. {
  617.   struct te_tlv_header *tlvh = &lp->link_id.header;
  618.   if (ntohs (tlvh->type) != 0)
  619.     {
  620.       build_tlv_header (s, tlvh);
  621.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  622.     }
  623.   return;
  624. }
  625. static void
  626. build_link_subtlv_lclif_ipaddr (struct stream *s, struct mpls_te_link *lp)
  627. {
  628.   struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->lclif_ipaddr;
  629.   if (tlvh != NULL && ntohs (tlvh->type) != 0)
  630.     {
  631.       build_tlv_header (s, tlvh);
  632.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  633.     }
  634.   return;
  635. }
  636. static void
  637. build_link_subtlv_rmtif_ipaddr (struct stream *s, struct mpls_te_link *lp)
  638. {
  639.   struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr;
  640.   if (tlvh != NULL && ntohs (tlvh->type) != 0)
  641.     {
  642.       build_tlv_header (s, tlvh);
  643.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  644.     }
  645.   return;
  646. }
  647. static void
  648. build_link_subtlv_te_metric (struct stream *s, struct mpls_te_link *lp)
  649. {
  650.   struct te_tlv_header *tlvh = &lp->te_metric.header;
  651.   if (ntohs (tlvh->type) != 0)
  652.     {
  653.       build_tlv_header (s, tlvh);
  654.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  655.     }
  656.   return;
  657. }
  658. static void
  659. build_link_subtlv_max_bw (struct stream *s, struct mpls_te_link *lp)
  660. {
  661.   struct te_tlv_header *tlvh = &lp->max_bw.header;
  662.   if (ntohs (tlvh->type) != 0)
  663.     {
  664.       build_tlv_header (s, tlvh);
  665.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  666.     }
  667.   return;
  668. }
  669. static void
  670. build_link_subtlv_max_rsv_bw (struct stream *s, struct mpls_te_link *lp)
  671. {
  672.   struct te_tlv_header *tlvh = &lp->max_rsv_bw.header;
  673.   if (ntohs (tlvh->type) != 0)
  674.     {
  675.       build_tlv_header (s, tlvh);
  676.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  677.     }
  678.   return;
  679. }
  680. static void
  681. build_link_subtlv_unrsv_bw (struct stream *s, struct mpls_te_link *lp)
  682. {
  683.   struct te_tlv_header *tlvh = &lp->unrsv_bw.header;
  684.   if (ntohs (tlvh->type) != 0)
  685.     {
  686.       build_tlv_header (s, tlvh);
  687.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  688.     }
  689.   return;
  690. }
  691. static void
  692. build_link_subtlv_rsc_clsclr (struct stream *s, struct mpls_te_link *lp)
  693. {
  694.   struct te_tlv_header *tlvh = &lp->rsc_clsclr.header;
  695.   if (ntohs (tlvh->type) != 0)
  696.     {
  697.       build_tlv_header (s, tlvh);
  698.       stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
  699.     }
  700.   return;
  701. }
  702. static void
  703. build_link_tlv (struct stream *s, struct mpls_te_link *lp)
  704. {
  705.   set_linkparams_link_header (lp);
  706.   build_tlv_header (s, &lp->link_header.header);
  707.   build_link_subtlv_link_type (s, lp);
  708.   build_link_subtlv_link_id (s, lp);
  709.   build_link_subtlv_lclif_ipaddr (s, lp);
  710.   build_link_subtlv_rmtif_ipaddr (s, lp);
  711.   build_link_subtlv_te_metric (s, lp);
  712.   build_link_subtlv_max_bw (s, lp);
  713.   build_link_subtlv_max_rsv_bw (s, lp);
  714.   build_link_subtlv_unrsv_bw (s, lp);
  715.   build_link_subtlv_rsc_clsclr (s, lp);
  716.   return;
  717. }
  718. static void
  719. ospf_mpls_te_lsa_body_set (struct stream *s, struct mpls_te_link *lp)
  720. {
  721.   /*
  722.    * The router address TLV is type 1, and ...
  723.    *                                      It must appear in exactly one
  724.    * Traffic Engineering LSA originated by a router.
  725.    */
  726.   build_router_tlv (s);
  727.   /*
  728.    * Only one Link TLV shall be carried in each LSA, allowing for fine
  729.    * granularity changes in topology.
  730.    */
  731.   build_link_tlv (s, lp);
  732.   return;
  733. }
  734. /* Create new opaque-LSA. */
  735. static struct ospf_lsa *
  736. ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp)
  737. {
  738.   struct stream *s;
  739.   struct lsa_header *lsah;
  740.   struct ospf_lsa *new = NULL;
  741.   u_char options, lsa_type;
  742.   struct in_addr lsa_id;
  743.   u_int32_t tmp;
  744.   u_int16_t length;
  745.   /* Create a stream for LSA. */
  746.   if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
  747.     {
  748.       zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?");
  749.       goto out;
  750.     }
  751.   lsah = (struct lsa_header *) STREAM_DATA (s);
  752.   options  = LSA_OPTIONS_GET (area);
  753. #ifdef HAVE_NSSA
  754.   options |= LSA_NSSA_GET (area);
  755. #endif /* HAVE_NSSA */
  756.   options |= OSPF_OPTION_O; /* Don't forget this :-) */
  757.   lsa_type = OSPF_OPAQUE_AREA_LSA;
  758.   tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
  759.   lsa_id.s_addr = htonl (tmp);
  760.   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
  761.     zlog_info ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type, inet_ntoa (lsa_id));
  762.   /* Set opaque-LSA header fields. */
  763.   lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id);
  764.   /* Set opaque-LSA body fields. */
  765.   ospf_mpls_te_lsa_body_set (s, lp);
  766.   /* Set length. */
  767.   length = stream_get_endp (s);
  768.   lsah->length = htons (length);
  769.   /* Now, create an OSPF LSA instance. */
  770.   if ((new = ospf_lsa_new ()) == NULL)
  771.     {
  772.       zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
  773.       stream_free (s);
  774.       goto out;
  775.     }
  776.   if ((new->data = ospf_lsa_data_new (length)) == NULL)
  777.     {
  778.       zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
  779.       ospf_lsa_free (new);
  780.       new = NULL;
  781.       stream_free (s);
  782.       goto out;
  783.     }
  784.   new->area = area;
  785.   SET_FLAG (new->flags, OSPF_LSA_SELF);
  786.   memcpy (new->data, lsah, length);
  787.   stream_free (s);
  788. out:
  789.   return new;
  790. }
  791. static int
  792. ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp)
  793. {
  794.   struct ospf_lsa *new;
  795.   int rc = -1;
  796.   /* Create new Opaque-LSA/MPLS-TE instance. */
  797.   if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
  798.     {
  799.       zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
  800.       goto out;
  801.     }
  802.   /* Install this LSA into LSDB. */
  803.   if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
  804.     {
  805.       zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
  806.       ospf_lsa_free (new);
  807.       goto out;
  808.     }
  809.   /* Now this linkparameter entry has associated LSA. */
  810.   lp->flags |= LPFLG_LSA_ENGAGED;
  811.   /* Update new LSA origination count. */
  812.   area->ospf->lsa_originate_count++;
  813.   /* Flood new LSA through area. */
  814.   ospf_flood_through_area (area, NULL/*nbr*/, new);
  815.   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
  816.     {
  817.       char area_id[INET_ADDRSTRLEN];
  818.       strcpy (area_id, inet_ntoa (area->area_id));
  819.       zlog_info ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name);
  820.       ospf_lsa_header_dump (new->data);
  821.     }
  822.   rc = 0;
  823. out:
  824.   return rc;
  825. }
  826. static int
  827. ospf_mpls_te_lsa_originate (void *arg)
  828. {
  829.   struct ospf_area *area = (struct ospf_area *) arg;
  830.   listnode node;
  831.   struct mpls_te_link *lp;
  832.   int rc = -1;
  833.   if (OspfMplsTE.status == disabled)
  834.     {
  835.       zlog_info ("ospf_mpls_te_lsa_originate: MPLS-TE is disabled now.");
  836.       rc = 0; /* This is not an error case. */
  837.       goto out;
  838.     }
  839.   for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
  840.     {
  841.       if ((lp = getdata (node)) == NULL)
  842.         continue;
  843.       if (lp->area == NULL)
  844.         continue;
  845.       if (! IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
  846.         continue;
  847.       if (lp->flags & LPFLG_LSA_ENGAGED)
  848.         {
  849.           if (lp->flags & LPFLG_LSA_FORCED_REFRESH)
  850.             {
  851.               lp->flags &= ~LPFLG_LSA_FORCED_REFRESH;
  852.               ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
  853.             }
  854.           continue;
  855.         }
  856.       if (! is_mandated_params_set (lp))
  857.         {
  858.           zlog_warn ("ospf_mpls_te_lsa_originate: Link(%s) lacks some mandated MPLS-TE parameters.", lp->ifp ? lp->ifp->name : "?");
  859.           continue;
  860.         }
  861.       /* Ok, let's try to originate an LSA for this area and Link. */
  862.       if (ospf_mpls_te_lsa_originate1 (area, lp) != 0)
  863.         goto out;
  864.     }
  865.   rc = 0;
  866. out:
  867.   return rc;
  868. }
  869. static void
  870. ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
  871. {
  872.   struct mpls_te_link *lp;
  873.   struct ospf_area *area = lsa->area;
  874.   struct ospf_lsa *new = NULL;
  875.   if (OspfMplsTE.status == disabled)
  876.     {
  877.       /*
  878.        * This LSA must have flushed before due to MPLS-TE status change.
  879.        * It seems a slip among routers in the routing domain.
  880.        */
  881.       zlog_info ("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now.");
  882.       lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
  883.     }
  884.   /* At first, resolve lsa/lp relationship. */
  885.   if ((lp = lookup_linkparams_by_instance (lsa)) == NULL)
  886.     {
  887.       zlog_warn ("ospf_mpls_te_lsa_refresh: Invalid parameter?");
  888.       lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
  889.     }
  890.   /* If the lsa's age reached to MaxAge, start flushing procedure. */
  891.   if (IS_LSA_MAXAGE (lsa))
  892.     {
  893.       lp->flags &= ~LPFLG_LSA_ENGAGED;
  894.       ospf_opaque_lsa_flush_schedule (lsa);
  895.       goto out;
  896.     }
  897.   /* Create new Opaque-LSA/MPLS-TE instance. */
  898.   if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
  899.     {
  900.       zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
  901.       goto out;
  902.     }
  903.   new->data->ls_seqnum = lsa_seqnum_increment (lsa);
  904.   /* Install this LSA into LSDB. */
  905.   /* Given "lsa" will be freed in the next function. */
  906.   if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
  907.     {
  908.       zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
  909.       ospf_lsa_free (new);
  910.       goto out;
  911.     }
  912.   /* Flood updated LSA through area. */
  913.   ospf_flood_through_area (area, NULL/*nbr*/, new);
  914.   /* Debug logging. */
  915.   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
  916.     {
  917.       zlog_info ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
  918.  new->data->type, inet_ntoa (new->data->id));
  919.       ospf_lsa_header_dump (new->data);
  920.     }
  921. out:
  922.   return;
  923. }
  924. static void
  925. ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp,
  926.                            enum sched_opcode opcode)
  927. {
  928.   struct ospf_lsa lsa;
  929.   struct lsa_header lsah;
  930.   u_int32_t tmp;
  931.   memset (&lsa, 0, sizeof (lsa));
  932.   memset (&lsah, 0, sizeof (lsah));
  933.   lsa.area = lp->area;
  934.   lsa.data = &lsah;
  935.   lsah.type = OSPF_OPAQUE_AREA_LSA;
  936.   tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
  937.   lsah.id.s_addr = htonl (tmp);
  938.   switch (opcode)
  939.     {
  940.     case REORIGINATE_PER_AREA:
  941.       ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area,
  942.           OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
  943.       break;
  944.     case REFRESH_THIS_LSA:
  945.       ospf_opaque_lsa_refresh_schedule (&lsa);
  946.       break;
  947.     case FLUSH_THIS_LSA:
  948.       lp->flags &= ~LPFLG_LSA_ENGAGED;
  949.       ospf_opaque_lsa_flush_schedule (&lsa);
  950.       break;
  951.     default:
  952.       zlog_warn ("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", opcode);
  953.       break;
  954.     }
  955.   return;
  956. }
  957. /*------------------------------------------------------------------------*
  958.  * Followings are vty session control functions.
  959.  *------------------------------------------------------------------------*/
  960. static u_int16_t
  961. show_vty_router_addr (struct vty *vty, struct te_tlv_header *tlvh)
  962. {
  963.   struct te_tlv_router_addr *top = (struct te_tlv_router_addr *) tlvh;
  964.   if (vty != NULL)
  965.     vty_out (vty, "  Router-Address: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
  966.   else
  967.     zlog_info ("    Router-Address: %s", inet_ntoa (top->value));
  968.   return TLV_SIZE (tlvh);
  969. }
  970. static u_int16_t
  971. show_vty_link_header (struct vty *vty, struct te_tlv_header *tlvh)
  972. {
  973.   struct te_tlv_link *top = (struct te_tlv_link *) tlvh;
  974.   if (vty != NULL)
  975.     vty_out (vty, "  Link: %u octets of data%s", ntohs (top->header.length), VTY_NEWLINE);
  976.   else
  977.     zlog_info ("    Link: %u octets of data", ntohs (top->header.length));
  978.   return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
  979. }
  980. static u_int16_t
  981. show_vty_link_subtlv_link_type (struct vty *vty, struct te_tlv_header *tlvh)
  982. {
  983.   struct te_link_subtlv_link_type *top;
  984.   const char *cp = "Unknown";
  985.   top = (struct te_link_subtlv_link_type *) tlvh;
  986.   switch (top->link_type.value)
  987.     {
  988.     case LINK_TYPE_SUBTLV_VALUE_PTP:
  989.       cp = "Point-to-point";
  990.       break;
  991.     case LINK_TYPE_SUBTLV_VALUE_MA:
  992.       cp = "Multiaccess";
  993.       break;
  994.     default:
  995.       break;
  996.     }
  997.   if (vty != NULL)
  998.     vty_out (vty, "  Link-Type: %s (%u)%s", cp, top->link_type.value, VTY_NEWLINE);
  999.   else
  1000.     zlog_info ("    Link-Type: %s (%u)", cp, top->link_type.value);
  1001.   return TLV_SIZE (tlvh);
  1002. }
  1003. static u_int16_t
  1004. show_vty_link_subtlv_link_id (struct vty *vty, struct te_tlv_header *tlvh)
  1005. {
  1006.   struct te_link_subtlv_link_id *top;
  1007.   top = (struct te_link_subtlv_link_id *) tlvh;
  1008.   if (vty != NULL)
  1009.     vty_out (vty, "  Link-ID: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
  1010.   else
  1011.     zlog_info ("    Link-ID: %s", inet_ntoa (top->value));
  1012.   return TLV_SIZE (tlvh);
  1013. }
  1014. static u_int16_t
  1015. show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
  1016. {
  1017.   struct te_link_subtlv_lclif_ipaddr *top;
  1018.   int i, n;
  1019.   top = (struct te_link_subtlv_lclif_ipaddr *) tlvh;
  1020.   n = ntohs (tlvh->length) / sizeof (top->value[0]);
  1021.   if (vty != NULL)
  1022.     vty_out (vty, "  Local Interface IP Address(es): %d%s", n, VTY_NEWLINE);
  1023.   else
  1024.     zlog_info ("    Local Interface IP Address(es): %d", n);
  1025.   for (i = 0; i < n; i++)
  1026.     {
  1027.       if (vty != NULL)
  1028.         vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
  1029.       else
  1030.         zlog_info ("      #%d: %s", i, inet_ntoa (top->value[i]));
  1031.     }
  1032.   return TLV_SIZE (tlvh);
  1033. }
  1034. static u_int16_t
  1035. show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
  1036. {
  1037.   struct te_link_subtlv_rmtif_ipaddr *top;
  1038.   int i, n;
  1039.   top = (struct te_link_subtlv_rmtif_ipaddr *) tlvh;
  1040.   n = ntohs (tlvh->length) / sizeof (top->value[0]);
  1041.   if (vty != NULL)
  1042.     vty_out (vty, "  Remote Interface IP Address(es): %d%s", n, VTY_NEWLINE);
  1043.   else
  1044.     zlog_info ("    Remote Interface IP Address(es): %d", n);
  1045.   for (i = 0; i < n; i++)
  1046.     {
  1047.       if (vty != NULL)
  1048.         vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
  1049.       else
  1050.         zlog_info ("      #%d: %s", i, inet_ntoa (top->value[i]));
  1051.     }
  1052.   return TLV_SIZE (tlvh);
  1053. }
  1054. static u_int16_t
  1055. show_vty_link_subtlv_te_metric (struct vty *vty, struct te_tlv_header *tlvh)
  1056. {
  1057.   struct te_link_subtlv_te_metric *top;
  1058.   top = (struct te_link_subtlv_te_metric *) tlvh;
  1059.   if (vty != NULL)
  1060.     vty_out (vty, "  Traffic Engineering Metric: %u%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
  1061.   else
  1062.     zlog_info ("    Traffic Engineering Metric: %u", (u_int32_t) ntohl (top->value));
  1063.   return TLV_SIZE (tlvh);
  1064. }
  1065. static u_int16_t
  1066. show_vty_link_subtlv_max_bw (struct vty *vty, struct te_tlv_header *tlvh)
  1067. {
  1068.   struct te_link_subtlv_max_bw *top;
  1069.   float fval;
  1070.   top = (struct te_link_subtlv_max_bw *) tlvh;
  1071.   ntohf (&top->value, &fval);
  1072.   if (vty != NULL)
  1073.     vty_out (vty, "  Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
  1074.   else
  1075.     zlog_info ("    Maximum Bandwidth: %g (Bytes/sec)", fval);
  1076.   return TLV_SIZE (tlvh);
  1077. }
  1078. static u_int16_t
  1079. show_vty_link_subtlv_max_rsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
  1080. {
  1081.   struct te_link_subtlv_max_rsv_bw *top;
  1082.   float fval;
  1083.   top = (struct te_link_subtlv_max_rsv_bw *) tlvh;
  1084.   ntohf (&top->value, &fval);
  1085.   if (vty != NULL)
  1086.     vty_out (vty, "  Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
  1087.   else
  1088.     zlog_info ("    Maximum Reservable Bandwidth: %g (Bytes/sec)", fval);
  1089.   return TLV_SIZE (tlvh);
  1090. }
  1091. static u_int16_t
  1092. show_vty_link_subtlv_unrsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
  1093. {
  1094.   struct te_link_subtlv_unrsv_bw *top;
  1095.   float fval;
  1096.   int i;
  1097.   top = (struct te_link_subtlv_unrsv_bw *) tlvh;
  1098.   for (i = 0; i < 8; i++)
  1099.     {
  1100.       ntohf (&top->value[i], &fval);
  1101.       if (vty != NULL)
  1102.         vty_out (vty, "  Unreserved Bandwidth (pri %d): %g (Bytes/sec)%s", i, fval, VTY_NEWLINE);
  1103.       else
  1104.         zlog_info ("    Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i, fval);
  1105.     }
  1106.   return TLV_SIZE (tlvh);
  1107. }
  1108. static u_int16_t
  1109. show_vty_link_subtlv_rsc_clsclr (struct vty *vty, struct te_tlv_header *tlvh)
  1110. {
  1111.   struct te_link_subtlv_rsc_clsclr *top;
  1112.   top = (struct te_link_subtlv_rsc_clsclr *) tlvh;
  1113.   if (vty != NULL)
  1114.     vty_out (vty, "  Resource class/color: 0x%x%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
  1115.   else
  1116.     zlog_info ("    Resource Class/Color: 0x%x", (u_int32_t) ntohl (top->value));
  1117.   return TLV_SIZE (tlvh);
  1118. }
  1119. static u_int16_t
  1120. show_vty_unknown_tlv (struct vty *vty, struct te_tlv_header *tlvh)
  1121. {
  1122.   if (vty != NULL)
  1123.     vty_out (vty, "  Unknown TLV: [type(0x%x), length(0x%x)]%s", ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
  1124.   else
  1125.     zlog_info ("    Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh->type), ntohs (tlvh->length));
  1126.   return TLV_SIZE (tlvh);
  1127. }
  1128. static u_int16_t
  1129. ospf_mpls_te_show_link_subtlv (struct vty *vty, struct te_tlv_header *tlvh0,
  1130.                                u_int16_t subtotal, u_int16_t total)
  1131. {
  1132.   struct te_tlv_header *tlvh, *next;
  1133.   u_int16_t sum = subtotal;
  1134.   for (tlvh = tlvh0; sum < total; tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
  1135.     {
  1136.       next = NULL;
  1137.       switch (ntohs (tlvh->type))
  1138.         {
  1139.         case TE_LINK_SUBTLV_LINK_TYPE:
  1140.           sum += show_vty_link_subtlv_link_type (vty, tlvh);
  1141.           break;
  1142.         case TE_LINK_SUBTLV_LINK_ID:
  1143.           sum += show_vty_link_subtlv_link_id (vty, tlvh);
  1144.           break;
  1145.         case TE_LINK_SUBTLV_LCLIF_IPADDR:
  1146.           sum += show_vty_link_subtlv_lclif_ipaddr (vty, tlvh);
  1147.           break;
  1148.         case TE_LINK_SUBTLV_RMTIF_IPADDR:
  1149.           sum += show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh);
  1150.           break;
  1151.         case TE_LINK_SUBTLV_TE_METRIC:
  1152.           sum += show_vty_link_subtlv_te_metric (vty, tlvh);
  1153.           break;
  1154.         case TE_LINK_SUBTLV_MAX_BW:
  1155.           sum += show_vty_link_subtlv_max_bw (vty, tlvh);
  1156.           break;
  1157.         case TE_LINK_SUBTLV_MAX_RSV_BW:
  1158.           sum += show_vty_link_subtlv_max_rsv_bw (vty, tlvh);
  1159.           break;
  1160.         case TE_LINK_SUBTLV_UNRSV_BW:
  1161.           sum += show_vty_link_subtlv_unrsv_bw (vty, tlvh);
  1162.           break;
  1163.         case TE_LINK_SUBTLV_RSC_CLSCLR:
  1164.           sum += show_vty_link_subtlv_rsc_clsclr (vty, tlvh);
  1165.           break;
  1166.         default:
  1167.           sum += show_vty_unknown_tlv (vty, tlvh);
  1168.           break;
  1169.         }
  1170.     }
  1171.   return sum;
  1172. }
  1173. static void
  1174. ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa)
  1175. {
  1176.   struct lsa_header *lsah = (struct lsa_header *) lsa->data;
  1177.   struct te_tlv_header *tlvh, *next;
  1178.   u_int16_t sum, total;
  1179.   u_int16_t (* subfunc)(struct vty *vty, struct te_tlv_header *tlvh,
  1180.                         u_int16_t subtotal, u_int16_t total) = NULL;
  1181.   sum = 0;
  1182.   total = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE;
  1183.   for (tlvh = TLV_HDR_TOP (lsah); sum < total;
  1184. tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
  1185.     {
  1186.       if (subfunc != NULL)
  1187.         {
  1188.           sum = (* subfunc)(vty, tlvh, sum, total);
  1189.   next = (struct te_tlv_header *)((char *) tlvh + sum);
  1190.           subfunc = NULL;
  1191.           continue;
  1192.         }
  1193.       next = NULL;
  1194.       switch (ntohs (tlvh->type))
  1195.         {
  1196.         case TE_TLV_ROUTER_ADDR:
  1197.           sum += show_vty_router_addr (vty, tlvh);
  1198.           break;
  1199.         case TE_TLV_LINK:
  1200.           sum += show_vty_link_header (vty, tlvh);
  1201.   subfunc = ospf_mpls_te_show_link_subtlv;
  1202.   next = tlvh + 1;
  1203.           break;
  1204.         default:
  1205.           sum += show_vty_unknown_tlv (vty, tlvh);
  1206.           break;
  1207.         }
  1208.     }
  1209.   return;
  1210. }
  1211. static void
  1212. ospf_mpls_te_config_write_router (struct vty *vty)
  1213. {
  1214.   if (OspfMplsTE.status == enabled)
  1215.     {
  1216.       vty_out (vty, "  mpls-te%s", VTY_NEWLINE);
  1217.       vty_out (vty, "  mpls-te router-address %s%s",
  1218.                inet_ntoa (OspfMplsTE.router_addr.value), VTY_NEWLINE);
  1219.     }
  1220.   return;
  1221. }
  1222. static void
  1223. ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp)
  1224. {
  1225.   struct mpls_te_link *lp;
  1226.   if ((OspfMplsTE.status == enabled)
  1227.   &&  (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0)
  1228.   &&  ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
  1229.     {
  1230.       float fval;
  1231.       int i;
  1232.       vty_out (vty, " mpls-te link metric %u%s",
  1233.                (u_int32_t) ntohl (lp->te_metric.value), VTY_NEWLINE);
  1234.       ntohf (&lp->max_bw.value, &fval);
  1235.       if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
  1236.         vty_out (vty, " mpls-te link max-bw %g%s", fval, VTY_NEWLINE);
  1237.       ntohf (&lp->max_rsv_bw.value, &fval);
  1238.       if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
  1239.         vty_out (vty, " mpls-te link max-rsv-bw %g%s", fval, VTY_NEWLINE);
  1240.       for (i = 0; i < 8; i++)
  1241.         {
  1242.           ntohf (&lp->unrsv_bw.value[i], &fval);
  1243.           if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
  1244.             vty_out (vty, " mpls-te link unrsv-bw %d %g%s",
  1245.                      i, fval, VTY_NEWLINE);
  1246.         }
  1247.       vty_out (vty, " mpls-te link rsc-clsclr 0x%x%s",
  1248.                (u_int32_t) ntohl (lp->rsc_clsclr.value), VTY_NEWLINE);
  1249.     }
  1250.   return;
  1251. }
  1252. /*------------------------------------------------------------------------*
  1253.  * Followings are vty command functions.
  1254.  *------------------------------------------------------------------------*/
  1255. DEFUN (mpls_te,
  1256.        mpls_te_cmd,
  1257.        "mpls-te",
  1258.        "Configure MPLS-TE parametersn"
  1259.        "Enable the MPLS-TE functionalityn")
  1260. {
  1261.   listnode node;
  1262.   struct mpls_te_link *lp;
  1263.   if (OspfMplsTE.status == enabled)
  1264.     return CMD_SUCCESS;
  1265.   if (IS_DEBUG_OSPF_EVENT)
  1266.     zlog_info ("MPLS-TE: OFF -> ON");
  1267.   OspfMplsTE.status = enabled;
  1268.   /*
  1269.    * Following code is intended to handle two cases;
  1270.    *
  1271.    * 1) MPLS-TE was disabled at startup time, but now become enabled.
  1272.    * 2) MPLS-TE was once enabled then disabled, and now enabled again.
  1273.    */
  1274.   for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
  1275.     if ((lp = getdata (node)) != NULL)
  1276.       initialize_linkparams (lp);
  1277.   ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
  1278.   return CMD_SUCCESS;
  1279. }
  1280. ALIAS (mpls_te,
  1281.        mpls_te_on_cmd,
  1282.        "mpls-te on",
  1283.        "Configure MPLS-TE parametersn"
  1284.        "Enable the MPLS-TE functionalityn");
  1285. DEFUN (no_mpls_te,
  1286.        no_mpls_te_cmd,
  1287.        "no mpls-te",
  1288.        NO_STR
  1289.        "Configure MPLS-TE parametersn"
  1290.        "Disable the MPLS-TE functionalityn")
  1291. {
  1292.   listnode node;
  1293.   struct mpls_te_link *lp;
  1294.   if (OspfMplsTE.status == disabled)
  1295.     return CMD_SUCCESS;
  1296.   if (IS_DEBUG_OSPF_EVENT)
  1297.     zlog_info ("MPLS-TE: ON -> OFF");
  1298.   OspfMplsTE.status = disabled;
  1299.   for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
  1300.     if ((lp = getdata (node)) != NULL)
  1301.       if (lp->area != NULL)
  1302.         if (lp->flags & LPFLG_LSA_ENGAGED)
  1303.           ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
  1304.   return CMD_SUCCESS;
  1305. }
  1306. DEFUN (mpls_te_router_addr,
  1307.        mpls_te_router_addr_cmd,
  1308.        "mpls-te router-address A.B.C.D",
  1309.        "MPLS-TE specific commandsn"
  1310.        "Stable IP address of the advertising routern"
  1311.        "MPLS-TE router address in IPv4 address formatn")
  1312. {
  1313.   struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
  1314.   struct in_addr value;
  1315.   if (! inet_aton (argv[0], &value))
  1316.     {
  1317.       vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE);
  1318.       return CMD_WARNING;
  1319.     }
  1320.   if (ntohs (ra->header.type) == 0
  1321.   ||  ntohl (ra->value.s_addr) != ntohl (value.s_addr))
  1322.     {
  1323.       listnode node;
  1324.       struct mpls_te_link *lp;
  1325.       int need_to_reoriginate = 0;
  1326.       set_mpls_te_router_addr (value);
  1327.       if (OspfMplsTE.status == disabled)
  1328.         goto out;
  1329.       for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
  1330.         {
  1331.           if ((lp = getdata (node)) == NULL)
  1332.             continue;
  1333.           if (lp->area == NULL)
  1334.             continue;
  1335.           if ((lp->flags & LPFLG_LSA_ENGAGED) == 0)
  1336.             {
  1337.               need_to_reoriginate = 1;
  1338.               break;
  1339.             }
  1340.         }
  1341.       for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
  1342.         {
  1343.           if ((lp = getdata (node)) == NULL)
  1344.             continue;
  1345.           if (lp->area == NULL)
  1346.             continue;
  1347.           if (need_to_reoriginate)
  1348.             lp->flags |= LPFLG_LSA_FORCED_REFRESH;
  1349.           else
  1350.             ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
  1351.         }
  1352.       if (need_to_reoriginate)
  1353.         ospf_mpls_te_foreach_area (
  1354.             ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
  1355.     }
  1356. out:
  1357.   return CMD_SUCCESS;
  1358. }
  1359. DEFUN (mpls_te_link_metric,
  1360.        mpls_te_link_metric_cmd,
  1361.        "mpls-te link metric <0-4294967295>",
  1362.        "MPLS-TE specific commandsn"
  1363.        "Configure MPLS-TE link parametersn"
  1364.        "Link metric for MPLS-TE purposen"
  1365.        "Metricn")
  1366. {
  1367.   struct interface *ifp = (struct interface *) vty->index;
  1368.   struct mpls_te_link *lp;
  1369.   u_int32_t value;
  1370.   if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
  1371.     {
  1372.       vty_out (vty, "mpls_te_link_metric: Something wrong!%s", VTY_NEWLINE);
  1373.       return CMD_WARNING;
  1374.     }
  1375.   value = strtoul (argv[0], NULL, 10);
  1376.   if (ntohs (lp->te_metric.header.type) == 0
  1377.   ||  ntohl (lp->te_metric.value) != value)
  1378.     {
  1379.       set_linkparams_te_metric (lp, value);
  1380.       if (OspfMplsTE.status == enabled)
  1381.         if (lp->area != NULL)
  1382.           {
  1383.             if (lp->flags & LPFLG_LSA_ENGAGED)
  1384.               ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
  1385.             else
  1386.               ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
  1387.           }
  1388.     }
  1389.   return CMD_SUCCESS;
  1390. }
  1391. DEFUN (mpls_te_link_maxbw,
  1392.        mpls_te_link_maxbw_cmd,
  1393.        "mpls-te link max-bw BANDWIDTH",
  1394.        "MPLS-TE specific commandsn"
  1395.        "Configure MPLS-TE link parametersn"
  1396.        "Maximum bandwidth that can be usedn"
  1397.        "Bytes/second (IEEE floating point format)n")
  1398. {
  1399.   struct interface *ifp = (struct interface *) vty->index;
  1400.   struct mpls_te_link *lp;
  1401.   float f1, f2;
  1402.   if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
  1403.     {
  1404.       vty_out (vty, "mpls_te_link_maxbw: Something wrong!%s", VTY_NEWLINE);
  1405.       return CMD_WARNING;
  1406.     }
  1407.   ntohf (&lp->max_bw.value, &f1);
  1408.   if (sscanf (argv[0], "%g", &f2) != 1)
  1409.     {
  1410.       vty_out (vty, "mpls_te_link_maxbw: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
  1411.       return CMD_WARNING;
  1412.     }
  1413.   if (ntohs (lp->max_bw.header.type) == 0
  1414.   ||  f1 != f2)
  1415.     {
  1416.       set_linkparams_max_bw (lp, &f2);
  1417.       if (OspfMplsTE.status == enabled)
  1418.         if (lp->area != NULL)
  1419.           {
  1420.             if (lp->flags & LPFLG_LSA_ENGAGED)
  1421.               ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
  1422.             else
  1423.               ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
  1424.           }
  1425.     }
  1426.   return CMD_SUCCESS;
  1427. }
  1428. DEFUN (mpls_te_link_max_rsv_bw,
  1429.        mpls_te_link_max_rsv_bw_cmd,
  1430.        "mpls-te link max-rsv-bw BANDWIDTH",
  1431.        "MPLS-TE specific commandsn"
  1432.        "Configure MPLS-TE link parametersn"
  1433.        "Maximum bandwidth that may be reservedn"
  1434.        "Bytes/second (IEEE floating point format)n")
  1435. {
  1436.   struct interface *ifp = (struct interface *) vty->index;
  1437.   struct mpls_te_link *lp;
  1438.   float f1, f2;
  1439.   if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
  1440.     {
  1441.       vty_out (vty, "mpls_te_link_max_rsv_bw: Something wrong!%s", VTY_NEWLINE);
  1442.       return CMD_WARNING;
  1443.     }
  1444.   ntohf (&lp->max_rsv_bw.value, &f1);
  1445.   if (sscanf (argv[0], "%g", &f2) != 1)
  1446.     {
  1447.       vty_out (vty, "mpls_te_link_max_rsv_bw: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
  1448.       return CMD_WARNING;
  1449.     }
  1450.   if (ntohs (lp->max_rsv_bw.header.type) == 0
  1451.   ||  f1 != f2)
  1452.     {
  1453.       set_linkparams_max_rsv_bw (lp, &f2);
  1454.       if (OspfMplsTE.status == enabled)
  1455.         if (lp->area != NULL)
  1456.           {
  1457.             if (lp->flags & LPFLG_LSA_ENGAGED)
  1458.               ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
  1459.             else
  1460.               ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
  1461.           }
  1462.     }
  1463.   return CMD_SUCCESS;
  1464. }
  1465. DEFUN (mpls_te_link_unrsv_bw,
  1466.        mpls_te_link_unrsv_bw_cmd,
  1467.        "mpls-te link unrsv-bw <0-7> BANDWIDTH",
  1468.        "MPLS-TE specific commandsn"
  1469.        "Configure MPLS-TE link parametersn"
  1470.        "Unreserved bandwidth at each priority leveln"
  1471.        "Priorityn"
  1472.        "Bytes/second (IEEE floating point format)n")
  1473. {
  1474.   struct interface *ifp = (struct interface *) vty->index;
  1475.   struct mpls_te_link *lp;
  1476.   int priority;
  1477.   float f1, f2;
  1478.   if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
  1479.     {
  1480.       vty_out (vty, "mpls_te_link_unrsv_bw: Something wrong!%s", VTY_NEWLINE);
  1481.       return CMD_WARNING;
  1482.     }
  1483.   /* We don't have to consider about range check here. */
  1484.   if (sscanf (argv[0], "%d", &priority) != 1)
  1485.     {
  1486.       vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
  1487.       return CMD_WARNING;
  1488.     }
  1489.   ntohf (&lp->unrsv_bw.value [priority], &f1);
  1490.   if (sscanf (argv[1], "%g", &f2) != 1)
  1491.     {
  1492.       vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
  1493.       return CMD_WARNING;
  1494.     }
  1495.   if (ntohs (lp->unrsv_bw.header.type) == 0
  1496.   ||  f1 != f2)
  1497.     {
  1498.       set_linkparams_unrsv_bw (lp, priority, &f2);
  1499.       if (OspfMplsTE.status == enabled)
  1500.         if (lp->area != NULL)
  1501.           {
  1502.             if (lp->flags & LPFLG_LSA_ENGAGED)
  1503.               ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
  1504.             else
  1505.               ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
  1506.           }
  1507.     }
  1508.   return CMD_SUCCESS;
  1509. }
  1510. DEFUN (mpls_te_link_rsc_clsclr,
  1511.        mpls_te_link_rsc_clsclr_cmd,
  1512.        "mpls-te link rsc-clsclr BITPATTERN",
  1513.        "MPLS-TE specific commandsn"
  1514.        "Configure MPLS-TE link parametersn"
  1515.        "Administrative group membershipn"
  1516.        "32-bit Hexadecimal value (ex. 0xa1)n")
  1517. {
  1518.   struct interface *ifp = (struct interface *) vty->index;
  1519.   struct mpls_te_link *lp;
  1520.   unsigned long value;
  1521.   if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
  1522.     {
  1523.       vty_out (vty, "mpls_te_link_rsc_clsclr: Something wrong!%s", VTY_NEWLINE);
  1524.       return CMD_WARNING;
  1525.     }
  1526.   if (sscanf (argv[0], "0x%lx", &value) != 1)
  1527.     {
  1528.       vty_out (vty, "mpls_te_link_rsc_clsclr: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
  1529.       return CMD_WARNING;
  1530.     }
  1531.   if (ntohs (lp->rsc_clsclr.header.type) == 0
  1532.   ||  ntohl (lp->rsc_clsclr.value) != value)
  1533.     {
  1534.       set_linkparams_rsc_clsclr (lp, value);
  1535.       if (OspfMplsTE.status == enabled)
  1536.         if (lp->area != NULL)
  1537.           {
  1538.             if (lp->flags & LPFLG_LSA_ENGAGED)
  1539.               ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
  1540.             else
  1541.               ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
  1542.           }
  1543.     }
  1544.   return CMD_SUCCESS;
  1545. }
  1546. DEFUN (show_mpls_te_router,
  1547.        show_mpls_te_router_cmd,
  1548.        "show mpls-te router",
  1549.        SHOW_STR
  1550.        "MPLS-TE informationn"
  1551.        "Router informationn")
  1552. {
  1553.   if (OspfMplsTE.status == enabled)
  1554.     {
  1555.       vty_out (vty, "--- MPLS-TE router parameters ---%s",
  1556.                VTY_NEWLINE);
  1557.       if (ntohs (OspfMplsTE.router_addr.header.type) != 0)
  1558.         show_vty_router_addr (vty, &OspfMplsTE.router_addr.header);
  1559.       else if (vty != NULL)
  1560.         vty_out (vty, "  N/A%s", VTY_NEWLINE);
  1561.     }
  1562.   return CMD_SUCCESS;
  1563. }
  1564. static void
  1565. show_mpls_te_link_sub (struct vty *vty, struct interface *ifp)
  1566. {
  1567.   struct mpls_te_link *lp;
  1568.   struct te_tlv_header *tlvh;
  1569.   if ((OspfMplsTE.status == enabled)
  1570.   &&  (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0)
  1571.   &&  ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
  1572.     {
  1573.       vty_out (vty, "-- MPLS-TE link parameters for %s --%s",
  1574.                ifp->name, VTY_NEWLINE);
  1575.       show_vty_link_subtlv_link_type (vty, &lp->link_type.header);
  1576.       show_vty_link_subtlv_link_id (vty, &lp->link_id.header);
  1577.       if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL)
  1578.         show_vty_link_subtlv_lclif_ipaddr (vty, tlvh);
  1579.       if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL)
  1580.         show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh);
  1581.       show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header);
  1582.       show_vty_link_subtlv_max_bw (vty, &lp->max_bw.header);
  1583.       show_vty_link_subtlv_max_rsv_bw (vty, &lp->max_rsv_bw.header);
  1584.       show_vty_link_subtlv_unrsv_bw (vty, &lp->unrsv_bw.header);
  1585.       show_vty_link_subtlv_rsc_clsclr (vty, &lp->rsc_clsclr.header);
  1586.     }
  1587.   else
  1588.     {
  1589.       vty_out (vty, "  %s: MPLS-TE is disabled on this interface%s",
  1590.                ifp->name, VTY_NEWLINE);
  1591.     }
  1592.   return;
  1593. }
  1594. DEFUN (show_mpls_te_link,
  1595.        show_mpls_te_link_cmd,
  1596.        "show mpls-te interface [INTERFACE]",
  1597.        SHOW_STR
  1598.        "MPLS-TE informationn"
  1599.        "Interface informationn"
  1600.        "Interface namen")
  1601. {
  1602.   struct interface *ifp;
  1603.   listnode node;
  1604.   /* Show All Interfaces. */
  1605.   if (argc == 0)
  1606.     for (node = listhead (iflist); node; nextnode (node))
  1607.       show_mpls_te_link_sub (vty, node->data);
  1608.   /* Interface name is specified. */
  1609.   else
  1610.     {
  1611.       if ((ifp = if_lookup_by_name (argv[0])) == NULL)
  1612.         vty_out (vty, "No such interface name%s", VTY_NEWLINE);
  1613.       else
  1614.         show_mpls_te_link_sub (vty, ifp);
  1615.     }
  1616.   return CMD_SUCCESS;
  1617. }
  1618. static void
  1619. ospf_mpls_te_register_vty (void)
  1620. {
  1621.   install_element (VIEW_NODE, &show_mpls_te_router_cmd);
  1622.   install_element (VIEW_NODE, &show_mpls_te_link_cmd);
  1623.   install_element (ENABLE_NODE, &show_mpls_te_router_cmd);
  1624.   install_element (ENABLE_NODE, &show_mpls_te_link_cmd);
  1625.   install_element (OSPF_NODE, &mpls_te_cmd);
  1626.   install_element (OSPF_NODE, &no_mpls_te_cmd);
  1627.   install_element (OSPF_NODE, &mpls_te_on_cmd);
  1628.   install_element (OSPF_NODE, &mpls_te_router_addr_cmd);
  1629.   install_element (INTERFACE_NODE, &mpls_te_link_metric_cmd);
  1630.   install_element (INTERFACE_NODE, &mpls_te_link_maxbw_cmd);
  1631.   install_element (INTERFACE_NODE, &mpls_te_link_max_rsv_bw_cmd);
  1632.   install_element (INTERFACE_NODE, &mpls_te_link_unrsv_bw_cmd);
  1633.   install_element (INTERFACE_NODE, &mpls_te_link_rsc_clsclr_cmd);
  1634.   return;
  1635. }
  1636. #endif /* HAVE_OSPF_TE */