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

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

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