Annotation of embedaddon/quagga/ospfd/ospf_te.c, revision 1.1.1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>