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