back to topotato report
topotato coverage report
Current view: top level - ospfd - ospf_te.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 126 2180 5.8 %
Date: 2023-02-24 14:41:08 Functions: 11 95 11.6 %

          Line data    Source code
       1             : /*
       2             :  * This is an implementation of RFC3630
       3             :  * Copyright (C) 2001 KDD R&D Laboratories, Inc.
       4             :  * http://www.kddlabs.co.jp/
       5             :  *
       6             :  * Copyright (C) 2012 Orange Labs
       7             :  * http://www.orange.com
       8             :  *
       9             :  * This file is part of GNU Zebra.
      10             :  *
      11             :  * GNU Zebra is free software; you can redistribute it and/or modify it
      12             :  * under the terms of the GNU General Public License as published by the
      13             :  * Free Software Foundation; either version 2, or (at your option) any
      14             :  * later version.
      15             :  *
      16             :  * GNU Zebra is distributed in the hope that it will be useful, but
      17             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      19             :  * General Public License for more details.
      20             :  *
      21             :  * You should have received a copy of the GNU General Public License along
      22             :  * with this program; see the file COPYING; if not, write to the Free Software
      23             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      24             :  */
      25             : 
      26             : /* Add support of RFC7471 */
      27             : /* Add support of RFC5392, RFC6827 */
      28             : 
      29             : #include <zebra.h>
      30             : #include <math.h>
      31             : 
      32             : #include "linklist.h"
      33             : #include "prefix.h"
      34             : #include "vrf.h"
      35             : #include "if.h"
      36             : #include "table.h"
      37             : #include "memory.h"
      38             : #include "command.h"
      39             : #include "vty.h"
      40             : #include "stream.h"
      41             : #include "log.h"
      42             : #include "thread.h"
      43             : #include "hash.h"
      44             : #include "sockunion.h" /* for inet_aton() */
      45             : #include "network.h"
      46             : #include "link_state.h"
      47             : #include "zclient.h"
      48             : #include "printfrr.h"
      49             : 
      50             : #include "ospfd/ospfd.h"
      51             : #include "ospfd/ospf_interface.h"
      52             : #include "ospfd/ospf_ism.h"
      53             : #include "ospfd/ospf_asbr.h"
      54             : #include "ospfd/ospf_lsa.h"
      55             : #include "ospfd/ospf_lsdb.h"
      56             : #include "ospfd/ospf_neighbor.h"
      57             : #include "ospfd/ospf_nsm.h"
      58             : #include "ospfd/ospf_flood.h"
      59             : #include "ospfd/ospf_packet.h"
      60             : #include "ospfd/ospf_spf.h"
      61             : #include "ospfd/ospf_dump.h"
      62             : #include "ospfd/ospf_route.h"
      63             : #include "ospfd/ospf_ase.h"
      64             : #include "ospfd/ospf_zebra.h"
      65             : #include "ospfd/ospf_te.h"
      66             : #include "ospfd/ospf_sr.h"
      67             : #include "ospfd/ospf_ri.h"
      68             : #include "ospfd/ospf_ext.h"
      69             : #include "ospfd/ospf_vty.h"
      70             : #include "ospfd/ospf_errors.h"
      71             : 
      72             : /*
      73             :  * Global variable to manage Opaque-LSA/MPLS-TE on this node.
      74             :  * Note that all parameter values are stored in network byte order.
      75             :  */
      76             : struct ospf_mpls_te OspfMplsTE;
      77             : 
      78             : static const char *const mode2text[] = {"Off", "AS", "Area"};
      79             : 
      80             : 
      81             : /*------------------------------------------------------------------------*
      82             :  * Following are initialize/terminate functions for MPLS-TE handling.
      83             :  *------------------------------------------------------------------------*/
      84             : 
      85             : static int ospf_mpls_te_new_if(struct interface *ifp);
      86             : static int ospf_mpls_te_del_if(struct interface *ifp);
      87             : static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_status);
      88             : static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_status);
      89             : static void ospf_mpls_te_config_write_router(struct vty *vty);
      90             : static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json,
      91             :                                    struct ospf_lsa *lsa);
      92             : static int ospf_mpls_te_lsa_originate_area(void *arg);
      93             : static int ospf_mpls_te_lsa_inter_as_as(void *arg);
      94             : static int ospf_mpls_te_lsa_inter_as_area(void *arg);
      95             : static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa);
      96             : static int ospf_mpls_te_lsa_update(struct ospf_lsa *lsa);
      97             : static int ospf_mpls_te_lsa_delete(struct ospf_lsa *lsa);
      98             : 
      99             : static void del_mpls_te_link(void *val);
     100             : static void ospf_mpls_te_register_vty(void);
     101             : 
     102           4 : int ospf_mpls_te_init(void)
     103             : {
     104           4 :         int rc;
     105             : 
     106             :         /* Register Opaque AREA LSA Type 1 for Traffic Engineering */
     107           4 :         rc = ospf_register_opaque_functab(
     108             :                 OSPF_OPAQUE_AREA_LSA,
     109             :                 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
     110             :                 ospf_mpls_te_new_if,
     111             :                 ospf_mpls_te_del_if,
     112             :                 ospf_mpls_te_ism_change,
     113             :                 ospf_mpls_te_nsm_change,
     114             :                 ospf_mpls_te_config_write_router,
     115             :                 NULL, /* ospf_mpls_te_config_write_if */
     116             :                 NULL, /* ospf_mpls_te_config_write_debug */
     117             :                 ospf_mpls_te_show_info, ospf_mpls_te_lsa_originate_area,
     118             :                 ospf_mpls_te_lsa_refresh,
     119             :                 ospf_mpls_te_lsa_update, /* ospf_mpls_te_new_lsa_hook */
     120             :                 ospf_mpls_te_lsa_delete /* ospf_mpls_te_del_lsa_hook */);
     121           4 :         if (rc != 0) {
     122           0 :                 flog_warn(
     123             :                         EC_OSPF_OPAQUE_REGISTRATION,
     124             :                         "MPLS-TE (%s): Failed to register Traffic Engineering functions",
     125             :                         __func__);
     126           0 :                 return rc;
     127             :         }
     128             : 
     129             :         /*
     130             :          * Wee need also to register Opaque LSA Type 6 i.e. Inter-AS RFC5392 for
     131             :          * both AREA and AS at least to have the possibility to call the show()
     132             :          * function when looking to the opaque LSA of the OSPF database.
     133             :          */
     134           4 :         rc = ospf_register_opaque_functab(OSPF_OPAQUE_AREA_LSA,
     135             :                                           OPAQUE_TYPE_INTER_AS_LSA, NULL,
     136             :                                           NULL, NULL, NULL, NULL, NULL, NULL,
     137             :                                           ospf_mpls_te_show_info,
     138             :                                           ospf_mpls_te_lsa_inter_as_area,
     139             :                                           ospf_mpls_te_lsa_refresh, NULL, NULL);
     140           4 :         if (rc != 0) {
     141           0 :                 flog_warn(
     142             :                         EC_OSPF_OPAQUE_REGISTRATION,
     143             :                         "MPLS-TE (%s): Failed to register Inter-AS with Area scope",
     144             :                         __func__);
     145           0 :                 return rc;
     146             :         }
     147             : 
     148           4 :         rc = ospf_register_opaque_functab(OSPF_OPAQUE_AS_LSA,
     149             :                                           OPAQUE_TYPE_INTER_AS_LSA, NULL,
     150             :                                           NULL, NULL, NULL, NULL, NULL, NULL,
     151             :                                           ospf_mpls_te_show_info,
     152             :                                           ospf_mpls_te_lsa_inter_as_as,
     153             :                                           ospf_mpls_te_lsa_refresh, NULL, NULL);
     154           4 :         if (rc != 0) {
     155           0 :                 flog_warn(
     156             :                         EC_OSPF_OPAQUE_REGISTRATION,
     157             :                         "MPLS-TE (%s): Failed to register Inter-AS with AS scope",
     158             :                         __func__);
     159           0 :                 return rc;
     160             :         }
     161             : 
     162           4 :         memset(&OspfMplsTE, 0, sizeof(OspfMplsTE));
     163           4 :         OspfMplsTE.enabled = false;
     164           4 :         OspfMplsTE.export = false;
     165           4 :         OspfMplsTE.inter_as = Off;
     166           4 :         OspfMplsTE.iflist = list_new();
     167           4 :         OspfMplsTE.iflist->del = del_mpls_te_link;
     168             : 
     169           4 :         ospf_mpls_te_register_vty();
     170             : 
     171           4 :         return rc;
     172             : }
     173             : 
     174           0 : void ospf_mpls_te_term(void)
     175             : {
     176           0 :         list_delete(&OspfMplsTE.iflist);
     177             : 
     178           0 :         ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
     179             :                                    OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
     180           0 :         ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
     181             :                                    OPAQUE_TYPE_INTER_AS_LSA);
     182           0 :         ospf_delete_opaque_functab(OSPF_OPAQUE_AS_LSA,
     183             :                                    OPAQUE_TYPE_INTER_AS_LSA);
     184             : 
     185           0 :         OspfMplsTE.enabled = false;
     186           0 :         OspfMplsTE.inter_as = Off;
     187           0 :         OspfMplsTE.export = false;
     188             : 
     189           0 :         return;
     190             : }
     191             : 
     192           4 : void ospf_mpls_te_finish(void)
     193             : {
     194           4 :         OspfMplsTE.enabled = false;
     195           4 :         OspfMplsTE.inter_as = Off;
     196           4 :         OspfMplsTE.export = false;
     197           4 : }
     198             : 
     199             : /*------------------------------------------------------------------------*
     200             :  * Following are control functions for MPLS-TE parameters management.
     201             :  *------------------------------------------------------------------------*/
     202           0 : static void del_mpls_te_link(void *val)
     203             : {
     204           0 :         XFREE(MTYPE_OSPF_MPLS_TE, val);
     205           0 :         return;
     206             : }
     207             : 
     208          13 : static uint32_t get_mpls_te_instance_value(void)
     209             : {
     210          13 :         static uint32_t seqno = 0;
     211             : 
     212          13 :         if (seqno < MAX_LEGAL_TE_INSTANCE_NUM)
     213          13 :                 seqno += 1;
     214             :         else
     215           0 :                 seqno = 1; /* Avoid zero. */
     216             : 
     217          13 :         return seqno;
     218             : }
     219             : 
     220          70 : static struct mpls_te_link *lookup_linkparams_by_ifp(struct interface *ifp)
     221             : {
     222          70 :         struct listnode *node, *nnode;
     223          70 :         struct mpls_te_link *lp;
     224             : 
     225         198 :         for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
     226         115 :                 if (lp->ifp == ifp)
     227          57 :                         return lp;
     228             : 
     229             :         return NULL;
     230             : }
     231             : 
     232           0 : static struct mpls_te_link *lookup_linkparams_by_instance(struct ospf_lsa *lsa)
     233             : {
     234           0 :         struct listnode *node;
     235           0 :         struct mpls_te_link *lp;
     236           0 :         unsigned int key = GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr));
     237             : 
     238           0 :         for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp))
     239           0 :                 if (lp->instance == key)
     240           0 :                         return lp;
     241             : 
     242           0 :         ote_debug("MPLS-TE (%s): Entry not found: key(%x)", __func__, key);
     243             :         return NULL;
     244             : }
     245             : 
     246           0 : static void ospf_mpls_te_foreach_area(
     247             :         void (*func)(struct mpls_te_link *lp, enum lsa_opcode sched_opcode),
     248             :         enum lsa_opcode sched_opcode)
     249             : {
     250           0 :         struct listnode *node, *nnode;
     251           0 :         struct listnode *node2;
     252           0 :         struct mpls_te_link *lp;
     253           0 :         struct ospf_area *area;
     254             : 
     255           0 :         for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
     256             :                 /* Skip Inter-AS TEv2 Links */
     257           0 :                 if (IS_INTER_AS(lp->type))
     258           0 :                         continue;
     259           0 :                 if ((area = lp->area) == NULL)
     260           0 :                         continue;
     261           0 :                 if (CHECK_FLAG(lp->flags, LPFLG_LOOKUP_DONE))
     262           0 :                         continue;
     263             : 
     264           0 :                 if (func != NULL)
     265           0 :                         (*func)(lp, sched_opcode);
     266             : 
     267           0 :                 for (node2 = listnextnode(node); node2;
     268           0 :                      node2 = listnextnode(node2))
     269           0 :                         if ((lp = listgetdata(node2)) != NULL)
     270           0 :                                 if (lp->area != NULL)
     271           0 :                                         if (IPV4_ADDR_SAME(&lp->area->area_id,
     272             :                                                            &area->area_id))
     273           0 :                                                 SET_FLAG(lp->flags,
     274             :                                                          LPFLG_LOOKUP_DONE);
     275             :         }
     276             : 
     277           0 :         for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp))
     278           0 :                 if (lp->area != NULL)
     279           0 :                         UNSET_FLAG(lp->flags, LPFLG_LOOKUP_DONE);
     280             : 
     281           0 :         return;
     282             : }
     283             : 
     284           0 : static void set_mpls_te_router_addr(struct in_addr ipv4)
     285             : {
     286           0 :         OspfMplsTE.router_addr.header.type = htons(TE_TLV_ROUTER_ADDR);
     287           0 :         OspfMplsTE.router_addr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     288           0 :         OspfMplsTE.router_addr.value = ipv4;
     289           0 :         return;
     290             : }
     291             : 
     292           0 : static void set_linkparams_link_header(struct mpls_te_link *lp)
     293             : {
     294           0 :         uint16_t length = 0;
     295             : 
     296             :         /* TE_LINK_SUBTLV_LINK_TYPE */
     297           0 :         if (ntohs(lp->link_type.header.type) != 0)
     298           0 :                 length += TLV_SIZE(&lp->link_type.header);
     299             : 
     300             :         /* TE_LINK_SUBTLV_LINK_ID */
     301           0 :         if (ntohs(lp->link_id.header.type) != 0)
     302           0 :                 length += TLV_SIZE(&lp->link_id.header);
     303             : 
     304             :         /* TE_LINK_SUBTLV_LCLIF_IPADDR */
     305           0 :         if (lp->lclif_ipaddr.header.type != 0)
     306           0 :                 length += TLV_SIZE(&lp->lclif_ipaddr.header);
     307             : 
     308             :         /* TE_LINK_SUBTLV_RMTIF_IPADDR */
     309           0 :         if (lp->rmtif_ipaddr.header.type != 0)
     310           0 :                 length += TLV_SIZE(&lp->rmtif_ipaddr.header);
     311             : 
     312             :         /* TE_LINK_SUBTLV_TE_METRIC */
     313           0 :         if (ntohs(lp->te_metric.header.type) != 0)
     314           0 :                 length += TLV_SIZE(&lp->te_metric.header);
     315             : 
     316             :         /* TE_LINK_SUBTLV_MAX_BW */
     317           0 :         if (ntohs(lp->max_bw.header.type) != 0)
     318           0 :                 length += TLV_SIZE(&lp->max_bw.header);
     319             : 
     320             :         /* TE_LINK_SUBTLV_MAX_RSV_BW */
     321           0 :         if (ntohs(lp->max_rsv_bw.header.type) != 0)
     322           0 :                 length += TLV_SIZE(&lp->max_rsv_bw.header);
     323             : 
     324             :         /* TE_LINK_SUBTLV_UNRSV_BW */
     325           0 :         if (ntohs(lp->unrsv_bw.header.type) != 0)
     326           0 :                 length += TLV_SIZE(&lp->unrsv_bw.header);
     327             : 
     328             :         /* TE_LINK_SUBTLV_RSC_CLSCLR */
     329           0 :         if (ntohs(lp->rsc_clsclr.header.type) != 0)
     330           0 :                 length += TLV_SIZE(&lp->rsc_clsclr.header);
     331             : 
     332             :         /* TE_LINK_SUBTLV_LLRI */
     333           0 :         if (ntohs(lp->llri.header.type) != 0)
     334           0 :                 length += TLV_SIZE(&lp->llri.header);
     335             : 
     336             :         /* TE_LINK_SUBTLV_RIP */
     337           0 :         if (ntohs(lp->rip.header.type) != 0)
     338           0 :                 length += TLV_SIZE(&lp->rip.header);
     339             : 
     340             :         /* TE_LINK_SUBTLV_RAS */
     341           0 :         if (ntohs(lp->ras.header.type) != 0)
     342           0 :                 length += TLV_SIZE(&lp->ras.header);
     343             : 
     344             :         /* TE_LINK_SUBTLV_LRRID */
     345           0 :         if (ntohs(lp->lrrid.header.type) != 0)
     346           0 :                 length += TLV_SIZE(&lp->lrrid.header);
     347             : 
     348             :         /* TE_LINK_SUBTLV_AV_DELAY */
     349           0 :         if (ntohs(lp->av_delay.header.type) != 0)
     350           0 :                 length += TLV_SIZE(&lp->av_delay.header);
     351             : 
     352             :         /* TE_LINK_SUBTLV_MM_DELAY */
     353           0 :         if (ntohs(lp->mm_delay.header.type) != 0)
     354           0 :                 length += TLV_SIZE(&lp->mm_delay.header);
     355             : 
     356             :         /* TE_LINK_SUBTLV_DELAY_VAR */
     357           0 :         if (ntohs(lp->delay_var.header.type) != 0)
     358           0 :                 length += TLV_SIZE(&lp->delay_var.header);
     359             : 
     360             :         /* TE_LINK_SUBTLV_PKT_LOSS */
     361           0 :         if (ntohs(lp->pkt_loss.header.type) != 0)
     362           0 :                 length += TLV_SIZE(&lp->pkt_loss.header);
     363             : 
     364             :         /* TE_LINK_SUBTLV_RES_BW */
     365           0 :         if (ntohs(lp->res_bw.header.type) != 0)
     366           0 :                 length += TLV_SIZE(&lp->res_bw.header);
     367             : 
     368             :         /* TE_LINK_SUBTLV_AVA_BW */
     369           0 :         if (ntohs(lp->ava_bw.header.type) != 0)
     370           0 :                 length += TLV_SIZE(&lp->ava_bw.header);
     371             : 
     372             :         /* TE_LINK_SUBTLV_USE_BW */
     373           0 :         if (ntohs(lp->use_bw.header.type) != 0)
     374           0 :                 length += TLV_SIZE(&lp->use_bw.header);
     375             : 
     376           0 :         lp->link_header.header.type = htons(TE_TLV_LINK);
     377           0 :         lp->link_header.header.length = htons(length);
     378             : 
     379           0 :         return;
     380             : }
     381             : 
     382          15 : static void set_linkparams_link_type(struct ospf_interface *oi,
     383             :                                      struct mpls_te_link *lp)
     384             : {
     385          15 :         lp->link_type.header.type = htons(TE_LINK_SUBTLV_LINK_TYPE);
     386          15 :         lp->link_type.header.length = htons(TE_LINK_SUBTLV_TYPE_SIZE);
     387             : 
     388          15 :         switch (oi->type) {
     389           0 :         case OSPF_IFTYPE_POINTOPOINT:
     390           0 :                 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP;
     391           0 :                 break;
     392          15 :         case OSPF_IFTYPE_BROADCAST:
     393             :         case OSPF_IFTYPE_NBMA:
     394          15 :                 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA;
     395          15 :                 break;
     396             :         default:
     397             :                 /* Not supported yet. */ /* XXX */
     398           0 :                 lp->link_type.header.type = htons(0);
     399           0 :                 break;
     400             :         }
     401          15 :         return;
     402             : }
     403             : 
     404           8 : static void set_linkparams_link_id(struct mpls_te_link *lp,
     405             :                                    struct in_addr link_id)
     406             : {
     407             : 
     408           8 :         lp->link_id.header.type = htons(TE_LINK_SUBTLV_LINK_ID);
     409           8 :         lp->link_id.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     410           8 :         lp->link_id.value = link_id;
     411           8 :         return;
     412             : }
     413             : 
     414          15 : static void set_linkparams_lclif_ipaddr(struct mpls_te_link *lp,
     415             :                                         struct in_addr lclif)
     416             : {
     417             : 
     418          15 :         lp->lclif_ipaddr.header.type = htons(TE_LINK_SUBTLV_LCLIF_IPADDR);
     419          15 :         lp->lclif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     420          15 :         lp->lclif_ipaddr.value[0] = lclif;
     421          15 :         return;
     422             : }
     423             : 
     424           0 : static void set_linkparams_rmtif_ipaddr(struct mpls_te_link *lp,
     425             :                                         struct in_addr rmtif)
     426             : {
     427             : 
     428           0 :         lp->rmtif_ipaddr.header.type = htons(TE_LINK_SUBTLV_RMTIF_IPADDR);
     429           0 :         lp->rmtif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     430           0 :         lp->rmtif_ipaddr.value[0] = rmtif;
     431           0 :         return;
     432             : }
     433             : 
     434           0 : static void set_linkparams_te_metric(struct mpls_te_link *lp,
     435             :                                      uint32_t te_metric)
     436             : {
     437           0 :         lp->te_metric.header.type = htons(TE_LINK_SUBTLV_TE_METRIC);
     438           0 :         lp->te_metric.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     439           0 :         lp->te_metric.value = htonl(te_metric);
     440           0 :         return;
     441             : }
     442             : 
     443           0 : static void set_linkparams_max_bw(struct mpls_te_link *lp, float fp)
     444             : {
     445           0 :         lp->max_bw.header.type = htons(TE_LINK_SUBTLV_MAX_BW);
     446           0 :         lp->max_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     447           0 :         lp->max_bw.value = htonf(fp);
     448           0 :         return;
     449             : }
     450             : 
     451           0 : static void set_linkparams_max_rsv_bw(struct mpls_te_link *lp, float fp)
     452             : {
     453           0 :         lp->max_rsv_bw.header.type = htons(TE_LINK_SUBTLV_MAX_RSV_BW);
     454           0 :         lp->max_rsv_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     455           0 :         lp->max_rsv_bw.value = htonf(fp);
     456           0 :         return;
     457             : }
     458             : 
     459           0 : static void set_linkparams_unrsv_bw(struct mpls_te_link *lp, int priority,
     460             :                                     float fp)
     461             : {
     462             :         /* Note that TLV-length field is the size of array. */
     463           0 :         lp->unrsv_bw.header.type = htons(TE_LINK_SUBTLV_UNRSV_BW);
     464           0 :         lp->unrsv_bw.header.length = htons(TE_LINK_SUBTLV_UNRSV_SIZE);
     465           0 :         lp->unrsv_bw.value[priority] = htonf(fp);
     466           0 :         return;
     467             : }
     468             : 
     469           0 : static void set_linkparams_rsc_clsclr(struct mpls_te_link *lp,
     470             :                                       uint32_t classcolor)
     471             : {
     472           0 :         lp->rsc_clsclr.header.type = htons(TE_LINK_SUBTLV_RSC_CLSCLR);
     473           0 :         lp->rsc_clsclr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     474           0 :         lp->rsc_clsclr.value = htonl(classcolor);
     475           0 :         return;
     476             : }
     477             : 
     478           0 : static void set_linkparams_inter_as(struct mpls_te_link *lp,
     479             :                                     struct in_addr addr, uint32_t as)
     480             : {
     481             : 
     482             :         /* Set the Remote ASBR IP address and then the associated AS number */
     483           0 :         lp->rip.header.type = htons(TE_LINK_SUBTLV_RIP);
     484           0 :         lp->rip.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     485           0 :         lp->rip.value = addr;
     486             : 
     487           0 :         lp->ras.header.type = htons(TE_LINK_SUBTLV_RAS);
     488           0 :         lp->ras.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     489           0 :         lp->ras.value = htonl(as);
     490             : 
     491             :         /* Set Type & Flooding flag accordingly */
     492           0 :         lp->type = INTER_AS;
     493           0 :         if (OspfMplsTE.inter_as == AS)
     494           0 :                 SET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
     495             :         else
     496           0 :                 UNSET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
     497           0 : }
     498             : 
     499           0 : static void unset_linkparams_inter_as(struct mpls_te_link *lp)
     500             : {
     501             : 
     502             :         /* Reset the Remote ASBR IP address and then the associated AS number */
     503           0 :         lp->rip.header.type = htons(0);
     504           0 :         lp->rip.header.length = htons(0);
     505           0 :         lp->rip.value.s_addr = htonl(0);
     506             : 
     507           0 :         lp->ras.header.type = htons(0);
     508           0 :         lp->ras.header.length = htons(0);
     509           0 :         lp->ras.value = htonl(0);
     510             : 
     511             :         /* Reset Type & Flooding flag accordingly */
     512           0 :         lp->type = STD_TE;
     513           0 :         UNSET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
     514           0 : }
     515             : 
     516           0 : void set_linkparams_llri(struct mpls_te_link *lp, uint32_t local,
     517             :                          uint32_t remote)
     518             : {
     519             : 
     520           0 :         lp->llri.header.type = htons(TE_LINK_SUBTLV_LLRI);
     521           0 :         lp->llri.header.length = htons(TE_LINK_SUBTLV_LLRI_SIZE);
     522           0 :         lp->llri.local = htonl(local);
     523           0 :         lp->llri.remote = htonl(remote);
     524           0 : }
     525             : 
     526           0 : void set_linkparams_lrrid(struct mpls_te_link *lp, struct in_addr local,
     527             :                           struct in_addr remote)
     528             : {
     529             : 
     530           0 :         lp->lrrid.header.type = htons(TE_LINK_SUBTLV_LRRID);
     531           0 :         lp->lrrid.header.length = htons(TE_LINK_SUBTLV_LRRID_SIZE);
     532           0 :         lp->lrrid.local.s_addr = local.s_addr;
     533           0 :         lp->lrrid.remote.s_addr = remote.s_addr;
     534           0 : }
     535             : 
     536           0 : static void set_linkparams_av_delay(struct mpls_te_link *lp, uint32_t delay,
     537             :                                     uint8_t anormal)
     538             : {
     539           0 :         uint32_t tmp;
     540             :         /* Note that TLV-length field is the size of array. */
     541           0 :         lp->av_delay.header.type = htons(TE_LINK_SUBTLV_AV_DELAY);
     542           0 :         lp->av_delay.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     543           0 :         tmp = delay & TE_EXT_MASK;
     544           0 :         if (anormal)
     545             :                 tmp |= TE_EXT_ANORMAL;
     546           0 :         lp->av_delay.value = htonl(tmp);
     547           0 :         return;
     548             : }
     549             : 
     550           0 : static void set_linkparams_mm_delay(struct mpls_te_link *lp, uint32_t low,
     551             :                                     uint32_t high, uint8_t anormal)
     552             : {
     553           0 :         uint32_t tmp;
     554             :         /* Note that TLV-length field is the size of array. */
     555           0 :         lp->mm_delay.header.type = htons(TE_LINK_SUBTLV_MM_DELAY);
     556           0 :         lp->mm_delay.header.length = htons(TE_LINK_SUBTLV_MM_DELAY_SIZE);
     557           0 :         tmp = low & TE_EXT_MASK;
     558           0 :         if (anormal)
     559             :                 tmp |= TE_EXT_ANORMAL;
     560           0 :         lp->mm_delay.low = htonl(tmp);
     561           0 :         lp->mm_delay.high = htonl(high);
     562           0 :         return;
     563             : }
     564             : 
     565           0 : static void set_linkparams_delay_var(struct mpls_te_link *lp, uint32_t jitter)
     566             : {
     567             :         /* Note that TLV-length field is the size of array. */
     568           0 :         lp->delay_var.header.type = htons(TE_LINK_SUBTLV_DELAY_VAR);
     569           0 :         lp->delay_var.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     570           0 :         lp->delay_var.value = htonl(jitter & TE_EXT_MASK);
     571           0 :         return;
     572             : }
     573             : 
     574           0 : static void set_linkparams_pkt_loss(struct mpls_te_link *lp, uint32_t loss,
     575             :                                     uint8_t anormal)
     576             : {
     577           0 :         uint32_t tmp;
     578             :         /* Note that TLV-length field is the size of array. */
     579           0 :         lp->pkt_loss.header.type = htons(TE_LINK_SUBTLV_PKT_LOSS);
     580           0 :         lp->pkt_loss.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     581           0 :         tmp = loss & TE_EXT_MASK;
     582           0 :         if (anormal)
     583             :                 tmp |= TE_EXT_ANORMAL;
     584           0 :         lp->pkt_loss.value = htonl(tmp);
     585           0 :         return;
     586             : }
     587             : 
     588           0 : static void set_linkparams_res_bw(struct mpls_te_link *lp, float fp)
     589             : {
     590             :         /* Note that TLV-length field is the size of array. */
     591           0 :         lp->res_bw.header.type = htons(TE_LINK_SUBTLV_RES_BW);
     592           0 :         lp->res_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     593           0 :         lp->res_bw.value = htonf(fp);
     594           0 :         return;
     595             : }
     596             : 
     597           0 : static void set_linkparams_ava_bw(struct mpls_te_link *lp, float fp)
     598             : {
     599             :         /* Note that TLV-length field is the size of array. */
     600           0 :         lp->ava_bw.header.type = htons(TE_LINK_SUBTLV_AVA_BW);
     601           0 :         lp->ava_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     602           0 :         lp->ava_bw.value = htonf(fp);
     603           0 :         return;
     604             : }
     605             : 
     606           0 : static void set_linkparams_use_bw(struct mpls_te_link *lp, float fp)
     607             : {
     608             :         /* Note that TLV-length field is the size of array. */
     609           0 :         lp->use_bw.header.type = htons(TE_LINK_SUBTLV_USE_BW);
     610           0 :         lp->use_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
     611           0 :         lp->use_bw.value = htonf(fp);
     612           0 :         return;
     613             : }
     614             : 
     615             : /* Update TE parameters from Interface */
     616          13 : static void update_linkparams(struct mpls_te_link *lp)
     617             : {
     618          13 :         int i;
     619          13 :         struct interface *ifp;
     620             : 
     621             :         /* Get the Interface structure */
     622          13 :         if ((ifp = lp->ifp) == NULL) {
     623           0 :                 ote_debug(
     624             :                         "MPLS-TE (%s): Abort update TE parameters: no interface associated to Link Parameters",
     625             :                         __func__);
     626           0 :                 return;
     627             :         }
     628          13 :         if (!HAS_LINK_PARAMS(ifp)) {
     629          13 :                 ote_debug(
     630             :                         "MPLS-TE (%s): Abort update TE parameters: no Link Parameters for interface",
     631             :                         __func__);
     632          13 :                 return;
     633             :         }
     634             : 
     635             :         /* RFC3630 metrics */
     636           0 :         if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
     637           0 :                 set_linkparams_rsc_clsclr(lp, ifp->link_params->admin_grp);
     638             :         else
     639           0 :                 TLV_TYPE(lp->rsc_clsclr) = 0;
     640             : 
     641           0 :         if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
     642           0 :                 set_linkparams_max_bw(lp, ifp->link_params->max_bw);
     643             :         else
     644           0 :                 TLV_TYPE(lp->max_bw) = 0;
     645             : 
     646           0 :         if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW))
     647           0 :                 set_linkparams_max_rsv_bw(lp, ifp->link_params->max_rsv_bw);
     648             :         else
     649           0 :                 TLV_TYPE(lp->max_rsv_bw) = 0;
     650             : 
     651           0 :         if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW))
     652           0 :                 for (i = 0; i < MAX_CLASS_TYPE; i++)
     653           0 :                         set_linkparams_unrsv_bw(lp, i,
     654           0 :                                                 ifp->link_params->unrsv_bw[i]);
     655             :         else
     656           0 :                 TLV_TYPE(lp->unrsv_bw) = 0;
     657             : 
     658           0 :         if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC))
     659           0 :                 set_linkparams_te_metric(lp, ifp->link_params->te_metric);
     660             :         else
     661           0 :                 TLV_TYPE(lp->te_metric) = 0;
     662             : 
     663             :         /* TE metric Extensions */
     664           0 :         if (IS_PARAM_SET(ifp->link_params, LP_DELAY))
     665           0 :                 set_linkparams_av_delay(lp, ifp->link_params->av_delay, 0);
     666             :         else
     667           0 :                 TLV_TYPE(lp->av_delay) = 0;
     668             : 
     669           0 :         if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY))
     670           0 :                 set_linkparams_mm_delay(lp, ifp->link_params->min_delay,
     671             :                                         ifp->link_params->max_delay, 0);
     672             :         else
     673           0 :                 TLV_TYPE(lp->mm_delay) = 0;
     674             : 
     675           0 :         if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
     676           0 :                 set_linkparams_delay_var(lp, ifp->link_params->delay_var);
     677             :         else
     678           0 :                 TLV_TYPE(lp->delay_var) = 0;
     679             : 
     680           0 :         if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
     681           0 :                 set_linkparams_pkt_loss(lp, ifp->link_params->pkt_loss, 0);
     682             :         else
     683           0 :                 TLV_TYPE(lp->pkt_loss) = 0;
     684             : 
     685           0 :         if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
     686           0 :                 set_linkparams_res_bw(lp, ifp->link_params->res_bw);
     687             :         else
     688           0 :                 TLV_TYPE(lp->res_bw) = 0;
     689             : 
     690           0 :         if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
     691           0 :                 set_linkparams_ava_bw(lp, ifp->link_params->ava_bw);
     692             :         else
     693           0 :                 TLV_TYPE(lp->ava_bw) = 0;
     694             : 
     695           0 :         if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
     696           0 :                 set_linkparams_use_bw(lp, ifp->link_params->use_bw);
     697             :         else
     698           0 :                 TLV_TYPE(lp->use_bw) = 0;
     699             : 
     700             :         /* RFC5392 */
     701           0 :         if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) {
     702             :                 /* Flush LSA if it engaged and was previously a STD_TE one */
     703           0 :                 if (IS_STD_TE(lp->type)
     704           0 :                     && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
     705           0 :                         ote_debug(
     706             :                                 "MPLS-TE (%s): Update IF: Switch from Standard LSA to INTER-AS for %s[%d/%d]",
     707             :                                 __func__, ifp->name, lp->flags, lp->type);
     708             : 
     709           0 :                         ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
     710             :                         /* Then, switch it to INTER-AS */
     711           0 :                         if (OspfMplsTE.inter_as == AS) {
     712           0 :                                 lp->type = INTER_AS;
     713           0 :                                 SET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
     714             :                         } else {
     715           0 :                                 lp->type = INTER_AS;
     716           0 :                                 UNSET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
     717           0 :                                 lp->area = ospf_area_lookup_by_area_id(
     718             :                                         ospf_lookup_by_vrf_id(VRF_DEFAULT),
     719             :                                         OspfMplsTE.interas_areaid);
     720             :                         }
     721             :                 }
     722           0 :                 set_linkparams_inter_as(lp, ifp->link_params->rmt_ip,
     723           0 :                                         ifp->link_params->rmt_as);
     724             :         } else {
     725           0 :                 ote_debug(
     726             :                         "MPLS-TE (%s): Update IF: Switch from INTER-AS LSA to Standard for %s[%d/%d]",
     727             :                         __func__, ifp->name, lp->flags, lp->type);
     728             : 
     729             :                 /* reset inter-as TE params */
     730             :                 /* Flush LSA if it engaged and was previously an INTER_AS one */
     731           0 :                 if (IS_INTER_AS(lp->type)
     732           0 :                     && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
     733           0 :                         ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
     734             :                         /* Then, switch it to Standard TE */
     735           0 :                         lp->flags = STD_TE;
     736           0 :                         UNSET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
     737             :                 }
     738           0 :                 unset_linkparams_inter_as(lp);
     739             :         }
     740             : }
     741             : 
     742          13 : static void initialize_linkparams(struct mpls_te_link *lp)
     743             : {
     744          13 :         struct interface *ifp = lp->ifp;
     745          13 :         struct ospf_interface *oi = NULL;
     746          13 :         struct route_node *rn;
     747             : 
     748          13 :         ote_debug("MPLS-TE (%s): Initialize Link Parameters for interface %s",
     749             :                   __func__, ifp->name);
     750             : 
     751             :         /* Search OSPF Interface parameters for this interface */
     752          13 :         for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
     753             : 
     754           0 :                 if ((oi = rn->info) == NULL)
     755           0 :                         continue;
     756             : 
     757           0 :                 if (oi->ifp == ifp)
     758             :                         break;
     759             :         }
     760             : 
     761          13 :         if ((oi == NULL) || (oi->ifp != ifp)) {
     762          13 :                 ote_debug(
     763             :                         "MPLS-TE (%s): Could not find corresponding OSPF Interface for %s",
     764             :                         __func__, ifp->name);
     765          13 :                 return;
     766             :         }
     767             : 
     768             :         /*
     769             :          * Try to set initial values those can be derived from
     770             :          * zebra-interface information.
     771             :          */
     772           0 :         set_linkparams_link_type(oi, lp);
     773             : 
     774             :         /* Set local IP addr */
     775           0 :         set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
     776             : 
     777             :         /* Set Remote IP addr if Point to Point Interface */
     778           0 :         if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
     779           0 :                 struct prefix *pref = CONNECTED_PREFIX(oi->connected);
     780           0 :                 if (pref != NULL)
     781           0 :                         set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
     782             :         }
     783             : 
     784             :         /* Keep Area information in combination with link parameters. */
     785           0 :         lp->area = oi->area;
     786             : 
     787           0 :         return;
     788             : }
     789             : 
     790           0 : static int is_mandated_params_set(struct mpls_te_link *lp)
     791             : {
     792           0 :         int rc = 0;
     793             : 
     794           0 :         if (ntohs(OspfMplsTE.router_addr.header.type) == 0) {
     795           0 :                 flog_warn(EC_OSPF_TE_UNEXPECTED,
     796             :                           "MPLS-TE (%s): Missing Router Address", __func__);
     797           0 :                 return rc;
     798             :         }
     799             : 
     800           0 :         if (ntohs(lp->link_type.header.type) == 0) {
     801           0 :                 flog_warn(EC_OSPF_TE_UNEXPECTED,
     802             :                           "MPLS-TE (%s): Missing Link Type", __func__);
     803           0 :                 return rc;
     804             :         }
     805             : 
     806           0 :         if (!IS_INTER_AS(lp->type) && (ntohs(lp->link_id.header.type) == 0)) {
     807           0 :                 flog_warn(EC_OSPF_TE_UNEXPECTED, "MPLS-TE (%s) Missing Link ID",
     808             :                           __func__);
     809           0 :                 return rc;
     810             :         }
     811             : 
     812           0 :         rc = 1;
     813             :         return rc;
     814             : }
     815             : 
     816             : /*------------------------------------------------------------------------*
     817             :  * Following are callback functions against generic Opaque-LSAs handling.
     818             :  *------------------------------------------------------------------------*/
     819             : 
     820          13 : static int ospf_mpls_te_new_if(struct interface *ifp)
     821             : {
     822          13 :         struct mpls_te_link *new;
     823             : 
     824          13 :         ote_debug("MPLS-TE (%s): Add new %s interface %s to MPLS-TE list",
     825             :                   __func__, ifp->link_params ? "Active" : "Inactive",
     826             :                   ifp->name);
     827             : 
     828          13 :         if (lookup_linkparams_by_ifp(ifp) != NULL)
     829             :                 return 0;
     830             : 
     831          13 :         new = XCALLOC(MTYPE_OSPF_MPLS_TE, sizeof(struct mpls_te_link));
     832             : 
     833          13 :         new->instance = get_mpls_te_instance_value();
     834          13 :         new->ifp = ifp;
     835             :         /* By default TE-Link is RFC3630 compatible flooding in Area and not
     836             :          * active */
     837             :         /* This default behavior will be adapted with call to
     838             :          * ospf_mpls_te_update_if() */
     839          13 :         new->type = STD_TE;
     840          13 :         new->flags = LPFLG_LSA_INACTIVE;
     841             : 
     842             :         /* Initialize Link Parameters from Interface */
     843          13 :         initialize_linkparams(new);
     844             : 
     845             :         /* Set TE Parameters from Interface */
     846          13 :         update_linkparams(new);
     847             : 
     848             :         /* Add Link Parameters structure to the list */
     849          13 :         listnode_add(OspfMplsTE.iflist, new);
     850             : 
     851          13 :         ote_debug("MPLS-TE (%s): Add new LP context for %s[%d/%d]", __func__,
     852             :                   ifp->name, new->flags, new->type);
     853             : 
     854             :         /* Schedule Opaque-LSA refresh. */ /* XXX */
     855             :         return 0;
     856             : }
     857             : 
     858           0 : static int ospf_mpls_te_del_if(struct interface *ifp)
     859             : {
     860           0 :         struct mpls_te_link *lp;
     861           0 :         int rc = -1;
     862             : 
     863           0 :         if ((lp = lookup_linkparams_by_ifp(ifp)) != NULL) {
     864           0 :                 struct list *iflist = OspfMplsTE.iflist;
     865             : 
     866             :                 /* Dequeue listnode entry from the list. */
     867           0 :                 listnode_delete(iflist, lp);
     868             : 
     869           0 :                 XFREE(MTYPE_OSPF_MPLS_TE, lp);
     870             :         }
     871             : 
     872             :         /* Schedule Opaque-LSA refresh. */ /* XXX */
     873             : 
     874           0 :         rc = 0;
     875           0 :         return rc;
     876             : }
     877             : 
     878             : /* Main initialization / update function of the MPLS TE Link context */
     879             : 
     880             : /* Call when interface TE Link parameters are modified */
     881           0 : void ospf_mpls_te_update_if(struct interface *ifp)
     882             : {
     883           0 :         struct mpls_te_link *lp;
     884             : 
     885           0 :         ote_debug("MPLS-TE (%s): Update LSA parameters for interface %s [%s]",
     886             :                   __func__, ifp->name, HAS_LINK_PARAMS(ifp) ? "ON" : "OFF");
     887             : 
     888             :         /* Get Link context from interface */
     889           0 :         if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL) {
     890           0 :                 flog_warn(
     891             :                         EC_OSPF_TE_UNEXPECTED,
     892             :                         "MPLS-TE (%s): Did not find Link Parameters context for interface %s",
     893             :                         __func__, ifp->name);
     894           0 :                 return;
     895             :         }
     896             : 
     897             :         /* Fulfill MPLS-TE Link TLV from Interface TE Link parameters */
     898           0 :         if (HAS_LINK_PARAMS(ifp)) {
     899           0 :                 SET_FLAG(lp->flags, LPFLG_LSA_ACTIVE);
     900             : 
     901             :                 /* Update TE parameters */
     902           0 :                 update_linkparams(lp);
     903             : 
     904             :                 /* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is
     905             :                  * enabled */
     906           0 :                 if (OspfMplsTE.enabled)
     907           0 :                         if (lp->area != NULL) {
     908           0 :                                 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
     909           0 :                                         ospf_mpls_te_lsa_schedule(
     910             :                                                 lp, REFRESH_THIS_LSA);
     911             :                                 else
     912           0 :                                         ospf_mpls_te_lsa_schedule(
     913             :                                                 lp, REORIGINATE_THIS_LSA);
     914             :                         }
     915             :         } else {
     916             :                 /* If MPLS TE is disable on this interface, flush LSA if it is
     917             :                  * already engaged */
     918           0 :                 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
     919           0 :                         ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
     920             :                 else
     921             :                         /* Reset Activity flag */
     922           0 :                         lp->flags = LPFLG_LSA_INACTIVE;
     923             :         }
     924             : 
     925             :         return;
     926             : }
     927             : 
     928             : /*
     929             :  * Just add interface and set available information. Other information
     930             :  * and flooding of LSA will be done later when adjacency will be up
     931             :  * See ospf_mpls_te_nsm_change() after
     932             :  */
     933          49 : static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state)
     934             : {
     935             : 
     936          49 :         struct mpls_te_link *lp;
     937             : 
     938          49 :         lp = lookup_linkparams_by_ifp(oi->ifp);
     939          49 :         if (lp == NULL) {
     940           0 :                 flog_warn(
     941             :                         EC_OSPF_TE_UNEXPECTED,
     942             :                         "MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
     943             :                         __func__, IF_NAME(oi));
     944           0 :                 return;
     945             :         }
     946             : 
     947          49 :         if (oi->area == NULL || oi->area->ospf == NULL) {
     948           0 :                 flog_warn(
     949             :                         EC_OSPF_TE_UNEXPECTED,
     950             :                         "MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
     951             :                         __func__, IF_NAME(oi));
     952           0 :                 return;
     953             :         }
     954             : 
     955             :         /* Keep Area information in combination with linkparams. */
     956          49 :         lp->area = oi->area;
     957             : 
     958          49 :         switch (oi->state) {
     959             :         case ISM_PointToPoint:
     960             :         case ISM_DROther:
     961             :         case ISM_Backup:
     962             :         case ISM_DR:
     963             :                 /* Set Link type and Local IP addr */
     964          15 :                 set_linkparams_link_type(oi, lp);
     965          15 :                 set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
     966             : 
     967          15 :                 break;
     968          17 :         case ISM_Down:
     969             :                 /* Interface goes Down: Flush LSA if engaged */
     970          17 :                 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
     971           0 :                         ote_debug(
     972             :                                 "MPLS-TE (%s): Interface %s goes down: flush LSA",
     973             :                                 __func__, IF_NAME(oi));
     974           0 :                         ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
     975           0 :                         return;
     976             :                 }
     977             :                 break;
     978             :         default:
     979             :                 break;
     980             :         }
     981             : 
     982          49 :         ote_debug("MPLS-TE (%s): Update Link parameters for interface %s",
     983             :                   __func__, IF_NAME(oi));
     984             : 
     985             :         return;
     986             : }
     987             : 
     988             : /*
     989             :  * Complete TE info and schedule LSA flooding
     990             :  * Link-ID and Remote IP address must be set with neighbor info
     991             :  * which are only valid once NSM state is FULL
     992             :  */
     993          55 : static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_state)
     994             : {
     995          55 :         struct ospf_interface *oi = nbr->oi;
     996          55 :         struct mpls_te_link *lp;
     997             : 
     998             :         /* Process Neighbor only when its state is NSM Full */
     999          55 :         if (nbr->state != NSM_Full)
    1000             :                 return;
    1001             : 
    1002             :         /* Get interface information for Traffic Engineering */
    1003           8 :         lp = lookup_linkparams_by_ifp(oi->ifp);
    1004           8 :         if (lp == NULL) {
    1005           0 :                 flog_warn(
    1006             :                         EC_OSPF_TE_UNEXPECTED,
    1007             :                         "MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
    1008             :                         __func__, IF_NAME(oi));
    1009           0 :                 return;
    1010             :         }
    1011             : 
    1012           8 :         if (oi->area == NULL || oi->area->ospf == NULL) {
    1013           0 :                 flog_warn(
    1014             :                         EC_OSPF_TE_UNEXPECTED,
    1015             :                         "MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
    1016             :                         __func__, IF_NAME(oi));
    1017           0 :                 return;
    1018             :         }
    1019             : 
    1020             :         /* Flush TE Opaque LSA if Neighbor State goes Down or Deleted */
    1021           8 :         if (OspfMplsTE.enabled
    1022             :             && (nbr->state == NSM_Down || nbr->state == NSM_Deleted)) {
    1023             :                 if (CHECK_FLAG(lp->flags, EXT_LPFLG_LSA_ENGAGED)) {
    1024             :                         ote_debug(
    1025             :                                 "MPLS-TE (%s): Interface %s goes down: flush LSA",
    1026             :                                 __func__, IF_NAME(oi));
    1027             :                         ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
    1028             :                 }
    1029             :                 return;
    1030             :         }
    1031             : 
    1032             :         /* Keep Area information in combination with SR info. */
    1033           8 :         lp->area = oi->area;
    1034             : 
    1035             :         /*
    1036             :          * The Link ID is identical to the contents of the Link ID field
    1037             :          * in the Router LSA for these link types.
    1038             :          */
    1039           8 :         switch (oi->state) {
    1040           0 :         case ISM_PointToPoint:
    1041             :                 /* Set Link ID with neighbor Router ID */
    1042           0 :                 set_linkparams_link_id(lp, nbr->router_id);
    1043             :                 /* Set Remote IP address */
    1044           0 :                 set_linkparams_rmtif_ipaddr(lp, nbr->address.u.prefix4);
    1045           0 :                 break;
    1046             : 
    1047           8 :         case ISM_DR:
    1048             :         case ISM_DROther:
    1049             :         case ISM_Backup:
    1050             :                 /* Set Link ID with the Designated Router ID */
    1051           8 :                 set_linkparams_link_id(lp, DR(oi));
    1052           8 :                 break;
    1053             : 
    1054           0 :         case ISM_Down:
    1055             :                 /* State goes Down: Flush LSA if engaged */
    1056           0 :                 if (OspfMplsTE.enabled
    1057           0 :                     && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
    1058           0 :                         ote_debug(
    1059             :                                 "MPLS-TE (%s): Interface %s goes down: flush LSA",
    1060             :                                 __func__, IF_NAME(oi));
    1061           0 :                         ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
    1062             :                 }
    1063             :                 return;
    1064             :         default:
    1065             :                 break;
    1066             :         }
    1067             : 
    1068           8 :         ote_debug("MPLS-TE (%s): Add Link-ID %pI4 for interface %s ", __func__,
    1069             :                   &lp->link_id.value, oi->ifp->name);
    1070             : 
    1071             :         /* Try to Schedule LSA */
    1072           8 :         if (OspfMplsTE.enabled) {
    1073           0 :                 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
    1074           0 :                         ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
    1075             :                 else
    1076           0 :                         ospf_mpls_te_lsa_schedule(lp, REORIGINATE_THIS_LSA);
    1077             :         }
    1078             :         return;
    1079             : }
    1080             : 
    1081             : /*------------------------------------------------------------------------*
    1082             :  * Following are OSPF protocol processing functions for MPLS-TE LSA.
    1083             :  *------------------------------------------------------------------------*/
    1084             : 
    1085           0 : static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
    1086             : {
    1087           0 :         stream_put(s, tlvh, sizeof(struct tlv_header));
    1088           0 :         return;
    1089             : }
    1090             : 
    1091           0 : static void build_router_tlv(struct stream *s)
    1092             : {
    1093           0 :         struct tlv_header *tlvh = &OspfMplsTE.router_addr.header;
    1094           0 :         if (ntohs(tlvh->type) != 0) {
    1095           0 :                 build_tlv_header(s, tlvh);
    1096           0 :                 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
    1097             :         }
    1098           0 :         return;
    1099             : }
    1100             : 
    1101           0 : static void build_link_subtlv(struct stream *s, struct tlv_header *tlvh)
    1102             : {
    1103             : 
    1104           0 :         if ((tlvh != NULL) && (ntohs(tlvh->type) != 0)) {
    1105           0 :                 build_tlv_header(s, tlvh);
    1106           0 :                 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
    1107             :         }
    1108           0 :         return;
    1109             : }
    1110             : 
    1111           0 : static void build_link_tlv(struct stream *s, struct mpls_te_link *lp)
    1112             : {
    1113           0 :         set_linkparams_link_header(lp);
    1114           0 :         build_tlv_header(s, &lp->link_header.header);
    1115             : 
    1116           0 :         build_link_subtlv(s, &lp->link_type.header);
    1117           0 :         build_link_subtlv(s, &lp->link_id.header);
    1118           0 :         build_link_subtlv(s, &lp->lclif_ipaddr.header);
    1119           0 :         build_link_subtlv(s, &lp->rmtif_ipaddr.header);
    1120           0 :         build_link_subtlv(s, &lp->te_metric.header);
    1121           0 :         build_link_subtlv(s, &lp->max_bw.header);
    1122           0 :         build_link_subtlv(s, &lp->max_rsv_bw.header);
    1123           0 :         build_link_subtlv(s, &lp->unrsv_bw.header);
    1124           0 :         build_link_subtlv(s, &lp->rsc_clsclr.header);
    1125           0 :         build_link_subtlv(s, &lp->lrrid.header);
    1126           0 :         build_link_subtlv(s, &lp->llri.header);
    1127           0 :         build_link_subtlv(s, &lp->rip.header);
    1128           0 :         build_link_subtlv(s, &lp->ras.header);
    1129           0 :         build_link_subtlv(s, &lp->av_delay.header);
    1130           0 :         build_link_subtlv(s, &lp->mm_delay.header);
    1131           0 :         build_link_subtlv(s, &lp->delay_var.header);
    1132           0 :         build_link_subtlv(s, &lp->pkt_loss.header);
    1133           0 :         build_link_subtlv(s, &lp->res_bw.header);
    1134           0 :         build_link_subtlv(s, &lp->ava_bw.header);
    1135           0 :         build_link_subtlv(s, &lp->use_bw.header);
    1136             : 
    1137           0 :         return;
    1138             : }
    1139             : 
    1140           0 : static void ospf_mpls_te_lsa_body_set(struct stream *s, struct mpls_te_link *lp)
    1141             : {
    1142             :         /*
    1143             :          * The router address TLV is type 1, and ... It must appear in exactly
    1144             :          * one Traffic Engineering LSA originated by a router but not in
    1145             :          * Inter-AS TLV.
    1146             :          */
    1147           0 :         if (!IS_INTER_AS(lp->type))
    1148           0 :                 build_router_tlv(s);
    1149             : 
    1150             :         /*
    1151             :          * Only one Link TLV shall be carried in each LSA, allowing for fine
    1152             :          * granularity changes in topology.
    1153             :          */
    1154           0 :         build_link_tlv(s, lp);
    1155           0 :         return;
    1156             : }
    1157             : 
    1158             : /* Create new opaque-LSA. */
    1159           0 : static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf,
    1160             :                                              struct ospf_area *area,
    1161             :                                              struct mpls_te_link *lp)
    1162             : {
    1163           0 :         struct stream *s;
    1164           0 :         struct lsa_header *lsah;
    1165           0 :         struct ospf_lsa *new = NULL;
    1166           0 :         uint8_t options, lsa_type = 0;
    1167           0 :         struct in_addr lsa_id;
    1168           0 :         uint32_t tmp;
    1169           0 :         uint16_t length;
    1170             : 
    1171             :         /* Create a stream for LSA. */
    1172           0 :         s = stream_new(OSPF_MAX_LSA_SIZE);
    1173           0 :         lsah = (struct lsa_header *)STREAM_DATA(s);
    1174             : 
    1175           0 :         options = OSPF_OPTION_O; /* Don't forget this :-) */
    1176             : 
    1177             :         /* Set opaque-LSA header fields depending of the type of RFC */
    1178           0 :         if (IS_INTER_AS(lp->type)) {
    1179           0 :                 if (IS_FLOOD_AS(lp->flags)) {
    1180             :                         /* Enable AS external as we flood Inter-AS with Opaque
    1181             :                          * Type 11
    1182             :                          */
    1183             :                         options |= OSPF_OPTION_E;
    1184             :                         lsa_type = OSPF_OPAQUE_AS_LSA;
    1185             :                 } else {
    1186           0 :                         options |= LSA_OPTIONS_GET(
    1187             :                                 area); /* Get area default option */
    1188           0 :                         options |= LSA_OPTIONS_NSSA_GET(area);
    1189           0 :                         lsa_type = OSPF_OPAQUE_AREA_LSA;
    1190             :                 }
    1191           0 :                 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
    1192           0 :                 lsa_id.s_addr = htonl(tmp);
    1193             : 
    1194           0 :                 if (!ospf) {
    1195           0 :                         stream_free(s);
    1196           0 :                         return NULL;
    1197             :                 }
    1198             : 
    1199           0 :                 lsa_header_set(s, options, lsa_type, lsa_id, ospf->router_id);
    1200             :         } else {
    1201           0 :                 options |= LSA_OPTIONS_GET(area); /* Get area default option */
    1202           0 :                 options |= LSA_OPTIONS_NSSA_GET(area);
    1203           0 :                 lsa_type = OSPF_OPAQUE_AREA_LSA;
    1204           0 :                 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
    1205             :                                       lp->instance);
    1206           0 :                 lsa_id.s_addr = htonl(tmp);
    1207           0 :                 lsa_header_set(s, options, lsa_type, lsa_id,
    1208           0 :                                area->ospf->router_id);
    1209             :         }
    1210             : 
    1211           0 :         ote_debug(
    1212             :                 "MPLS-TE (%s): LSA[Type%d:%pI4]: Create an Opaque-LSA/MPLS-TE instance",
    1213             :                 __func__, lsa_type, &lsa_id);
    1214             : 
    1215             :         /* Set opaque-LSA body fields. */
    1216           0 :         ospf_mpls_te_lsa_body_set(s, lp);
    1217             : 
    1218             :         /* Set length. */
    1219           0 :         length = stream_get_endp(s);
    1220           0 :         lsah->length = htons(length);
    1221             : 
    1222             :         /* Now, create an OSPF LSA instance. */
    1223           0 :         new = ospf_lsa_new_and_data(length);
    1224             : 
    1225           0 :         new->vrf_id = ospf->vrf_id;
    1226           0 :         if (area && area->ospf)
    1227           0 :                 new->vrf_id = area->ospf->vrf_id;
    1228           0 :         new->area = area;
    1229           0 :         SET_FLAG(new->flags, OSPF_LSA_SELF);
    1230           0 :         memcpy(new->data, lsah, length);
    1231           0 :         stream_free(s);
    1232             : 
    1233           0 :         return new;
    1234             : }
    1235             : 
    1236           0 : static int ospf_mpls_te_lsa_originate1(struct ospf_area *area,
    1237             :                                        struct mpls_te_link *lp)
    1238             : {
    1239           0 :         struct ospf_lsa *new = NULL;
    1240           0 :         int rc = -1;
    1241             : 
    1242             :         /* Create new Opaque-LSA/MPLS-TE instance. */
    1243           0 :         new = ospf_mpls_te_lsa_new(area->ospf, area, lp);
    1244           0 :         if (new == NULL) {
    1245           0 :                 flog_warn(EC_OSPF_TE_UNEXPECTED,
    1246             :                           "MPLS-TE (%s): ospf_mpls_te_lsa_new() ?", __func__);
    1247           0 :                 return rc;
    1248             :         }
    1249             : 
    1250             :         /* Install this LSA into LSDB. */
    1251           0 :         if (ospf_lsa_install(area->ospf, NULL /*oi*/, new) == NULL) {
    1252           0 :                 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
    1253             :                           "MPLS-TE (%s): ospf_lsa_install() ?", __func__);
    1254           0 :                 ospf_lsa_unlock(&new);
    1255           0 :                 return rc;
    1256             :         }
    1257             : 
    1258             :         /* Now this link-parameter entry has associated LSA. */
    1259           0 :         SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
    1260             :         /* Update new LSA origination count. */
    1261           0 :         area->ospf->lsa_originate_count++;
    1262             : 
    1263             :         /* Flood new LSA through area. */
    1264           0 :         ospf_flood_through_area(area, NULL /*nbr*/, new);
    1265             : 
    1266           0 :         ote_debug(
    1267             :                 "MPLS-TE (%s): LSA[Type%d:%pI4]: Originate Opaque-LSA/MPLS-TE: Area(%pI4), Link(%s)",
    1268             :                 __func__, new->data->type, &new->data->id, &area->area_id,
    1269             :                 lp->ifp->name);
    1270           0 :         if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
    1271           0 :                 ospf_lsa_header_dump(new->data);
    1272             : 
    1273           0 :         rc = 0;
    1274             :         return rc;
    1275             : }
    1276             : 
    1277           0 : static int ospf_mpls_te_lsa_originate_area(void *arg)
    1278             : {
    1279           0 :         struct ospf_area *area = (struct ospf_area *)arg;
    1280           0 :         struct listnode *node, *nnode;
    1281           0 :         struct mpls_te_link *lp;
    1282           0 :         int rc = -1;
    1283             : 
    1284           0 :         if (!OspfMplsTE.enabled) {
    1285           0 :                 ote_debug("MPLS-TE (%s): MPLS-TE is disabled now.", __func__);
    1286           0 :                 rc = 0; /* This is not an error case. */
    1287           0 :                 return rc;
    1288             :         }
    1289             : 
    1290           0 :         for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
    1291             :                 /* Process only enabled LSA with area scope flooding */
    1292           0 :                 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)
    1293           0 :                     || IS_FLOOD_AS(lp->flags))
    1294           0 :                         continue;
    1295             : 
    1296           0 :                 if (lp->area == NULL)
    1297           0 :                         continue;
    1298             : 
    1299           0 :                 if (!IPV4_ADDR_SAME(&lp->area->area_id, &area->area_id))
    1300           0 :                         continue;
    1301             : 
    1302           0 :                 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
    1303           0 :                         if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
    1304           0 :                                 UNSET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
    1305           0 :                                 ote_debug(
    1306             :                                         "MPLS-TE (%s): Refresh instead of Originate",
    1307             :                                         __func__);
    1308           0 :                                 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
    1309             :                         }
    1310           0 :                         continue;
    1311             :                 }
    1312             : 
    1313           0 :                 if (!is_mandated_params_set(lp)) {
    1314           0 :                         ote_debug(
    1315             :                                 "MPLS-TE (%s): Link(%s) lacks some mandated MPLS-TE parameters.",
    1316             :                                 __func__, lp->ifp ? lp->ifp->name : "?");
    1317           0 :                         continue;
    1318             :                 }
    1319             : 
    1320             :                 /* Ok, let's try to originate an LSA for this area and Link. */
    1321           0 :                 ote_debug(
    1322             :                         "MPLS-TE (%s): Let's finally reoriginate the LSA %d through the Area %pI4 for Link %s",
    1323             :                         __func__, lp->instance, &area->area_id,
    1324             :                         lp->ifp ? lp->ifp->name : "?");
    1325           0 :                 if (ospf_mpls_te_lsa_originate1(area, lp) != 0)
    1326             :                         return rc;
    1327             :         }
    1328             : 
    1329           0 :         rc = 0;
    1330             :         return rc;
    1331             : }
    1332             : 
    1333           0 : static int ospf_mpls_te_lsa_originate2(struct ospf *top,
    1334             :                                        struct mpls_te_link *lp)
    1335             : {
    1336           0 :         struct ospf_lsa *new;
    1337           0 :         int rc = -1;
    1338             : 
    1339             :         /* Create new Opaque-LSA/Inter-AS instance. */
    1340           0 :         new = ospf_mpls_te_lsa_new(top, NULL, lp);
    1341           0 :         if (new == NULL) {
    1342           0 :                 flog_warn(EC_OSPF_LSA_UNEXPECTED,
    1343             :                           "MPLS-TE (%s): ospf_router_info_lsa_new() ?",
    1344             :                           __func__);
    1345           0 :                 return rc;
    1346             :         }
    1347           0 :         new->vrf_id = top->vrf_id;
    1348             : 
    1349             :         /* Install this LSA into LSDB. */
    1350           0 :         if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
    1351           0 :                 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
    1352             :                           "MPLS-TE (%s): ospf_lsa_install() ?", __func__);
    1353           0 :                 ospf_lsa_unlock(&new);
    1354           0 :                 return rc;
    1355             :         }
    1356             : 
    1357             :         /* Now this Router Info parameter entry has associated LSA. */
    1358           0 :         SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
    1359             :         /* Update new LSA origination count. */
    1360           0 :         top->lsa_originate_count++;
    1361             : 
    1362             :         /* Flood new LSA through AS. */
    1363           0 :         ospf_flood_through_as(top, NULL /*nbr */, new);
    1364             : 
    1365           0 :         ote_debug(
    1366             :                 "MPLS-TE (%s): LSA[Type%d:%pI4]: Originate Opaque-LSA/MPLS-TE Inter-AS",
    1367             :                 __func__, new->data->type, &new->data->id);
    1368           0 :         if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
    1369           0 :                 ospf_lsa_header_dump(new->data);
    1370             : 
    1371             : 
    1372           0 :         rc = 0;
    1373             :         return rc;
    1374             : }
    1375             : 
    1376           0 : static int ospf_mpls_te_lsa_originate_as(void *arg)
    1377             : {
    1378           0 :         struct ospf *top;
    1379           0 :         struct ospf_area *area;
    1380           0 :         struct listnode *node, *nnode;
    1381           0 :         struct mpls_te_link *lp;
    1382           0 :         int rc = -1;
    1383             : 
    1384           0 :         if ((!OspfMplsTE.enabled) || (OspfMplsTE.inter_as == Off)) {
    1385           0 :                 ote_debug("MPLS-TE (%s): Inter-AS is disabled for now",
    1386             :                           __func__);
    1387           0 :                 rc = 0; /* This is not an error case. */
    1388           0 :                 return rc;
    1389             :         }
    1390             : 
    1391           0 :         for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
    1392             :                 /* Process only enabled INTER_AS Links or Pseudo-Links */
    1393           0 :                 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)
    1394           0 :                     || !CHECK_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS)
    1395           0 :                     || !IS_INTER_AS(lp->type))
    1396           0 :                         continue;
    1397             : 
    1398           0 :                 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
    1399           0 :                         if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
    1400           0 :                                 UNSET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
    1401           0 :                                 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
    1402             :                         }
    1403           0 :                         continue;
    1404             :                 }
    1405             : 
    1406           0 :                 if (!is_mandated_params_set(lp)) {
    1407           0 :                         flog_warn(
    1408             :                                 EC_OSPF_TE_UNEXPECTED,
    1409             :                                 "MPLS-TE (%s): Link(%s) lacks some mandated MPLS-TE parameters.",
    1410             :                                 __func__, lp->ifp ? lp->ifp->name : "?");
    1411           0 :                         continue;
    1412             :                 }
    1413             : 
    1414             :                 /* Ok, let's try to originate an LSA for this AS and Link. */
    1415           0 :                 ote_debug(
    1416             :                         "MPLS-TE (%s): Let's finally re-originate the Inter-AS LSA %d through the %s for Link %s",
    1417             :                         __func__, lp->instance,
    1418             :                         IS_FLOOD_AS(lp->flags) ? "AS" : "Area",
    1419             :                         lp->ifp ? lp->ifp->name : "Unknown");
    1420             : 
    1421           0 :                 if (IS_FLOOD_AS(lp->flags)) {
    1422           0 :                         top = (struct ospf *)arg;
    1423           0 :                         ospf_mpls_te_lsa_originate2(top, lp);
    1424             :                 } else {
    1425           0 :                         area = (struct ospf_area *)arg;
    1426           0 :                         ospf_mpls_te_lsa_originate1(area, lp);
    1427             :                 }
    1428             :         }
    1429             : 
    1430           0 :         rc = 0;
    1431             :         return rc;
    1432             : }
    1433             : 
    1434             : /*
    1435             :  * As Inter-AS LSA must be registered with both AREA and AS flooding, and
    1436             :  * because all origination callback functions are call (disregarding the Opaque
    1437             :  * LSA type and Flooding scope) it is necessary to determine which flooding
    1438             :  * scope is associated with the LSA origination as parameter is of type void and
    1439             :  * must be cast to struct *ospf for AS flooding and to struct *ospf_area for
    1440             :  * Area flooding.
    1441             :  */
    1442           0 : static int ospf_mpls_te_lsa_inter_as_as(void *arg)
    1443             : {
    1444           0 :         if (OspfMplsTE.inter_as == AS)
    1445           0 :                 return ospf_mpls_te_lsa_originate_as(arg);
    1446             :         else
    1447             :                 return 0;
    1448             : }
    1449             : 
    1450           0 : static int ospf_mpls_te_lsa_inter_as_area(void *arg)
    1451             : {
    1452           0 :         if (OspfMplsTE.inter_as == Area)
    1453           0 :                 return ospf_mpls_te_lsa_originate_area(arg);
    1454             :         else
    1455             :                 return 0;
    1456             : }
    1457             : 
    1458           0 : static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
    1459             : {
    1460           0 :         struct mpls_te_link *lp;
    1461           0 :         struct ospf_area *area = lsa->area;
    1462           0 :         struct ospf *top;
    1463           0 :         struct ospf_lsa *new = NULL;
    1464             : 
    1465           0 :         if (!OspfMplsTE.enabled) {
    1466             :                 /*
    1467             :                  * This LSA must have flushed before due to MPLS-TE status
    1468             :                  * change.
    1469             :                  * It seems a slip among routers in the routing domain.
    1470             :                  */
    1471           0 :                 ote_debug("MPLS-TE (%s): MPLS-TE is disabled now", __func__);
    1472           0 :                 lsa->data->ls_age =
    1473           0 :                         htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
    1474             :         }
    1475             : 
    1476             :         /* At first, resolve lsa/lp relationship. */
    1477           0 :         if ((lp = lookup_linkparams_by_instance(lsa)) == NULL) {
    1478           0 :                 flog_warn(EC_OSPF_TE_UNEXPECTED,
    1479             :                           "MPLS-TE (%s): Invalid parameter?", __func__);
    1480           0 :                 lsa->data->ls_age =
    1481           0 :                         htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
    1482           0 :                 ospf_opaque_lsa_flush_schedule(lsa);
    1483           0 :                 return NULL;
    1484             :         }
    1485             : 
    1486             :         /* Check if lp was not disable in the interval */
    1487           0 :         if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)) {
    1488           0 :                 flog_warn(EC_OSPF_TE_UNEXPECTED,
    1489             :                           "MPLS-TE (%s): lp was disabled: Flush it!", __func__);
    1490           0 :                 lsa->data->ls_age =
    1491           0 :                         htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
    1492             :         }
    1493             : 
    1494             :         /* If the lsa's age reached to MaxAge, start flushing procedure. */
    1495           0 :         if (IS_LSA_MAXAGE(lsa)) {
    1496           0 :                 UNSET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
    1497           0 :                 ospf_opaque_lsa_flush_schedule(lsa);
    1498           0 :                 return NULL;
    1499             :         }
    1500           0 :         top = ospf_lookup_by_vrf_id(lsa->vrf_id);
    1501             :         /* Create new Opaque-LSA/MPLS-TE instance. */
    1502           0 :         new = ospf_mpls_te_lsa_new(top, area, lp);
    1503           0 :         if (new == NULL) {
    1504           0 :                 flog_warn(EC_OSPF_TE_UNEXPECTED,
    1505             :                           "MPLS-TE (%s): ospf_mpls_te_lsa_new() ?", __func__);
    1506           0 :                 return NULL;
    1507             :         }
    1508           0 :         new->data->ls_seqnum = lsa_seqnum_increment(lsa);
    1509             : 
    1510             :         /* Install this LSA into LSDB. */
    1511             :         /* Given "lsa" will be freed in the next function. */
    1512             :         /* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use
    1513             :          * ospf_lookup() to get ospf instance */
    1514           0 :         if (area)
    1515           0 :                 top = area->ospf;
    1516             : 
    1517           0 :         if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
    1518           0 :                 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
    1519             :                           "MPLS-TE (%s): ospf_lsa_install() ?", __func__);
    1520           0 :                 ospf_lsa_unlock(&new);
    1521           0 :                 return NULL;
    1522             :         }
    1523             : 
    1524             :         /* Flood updated LSA through AS or Area depending of the RFC of the link
    1525             :          */
    1526           0 :         if (IS_FLOOD_AS(lp->flags))
    1527           0 :                 ospf_flood_through_as(top, NULL, new);
    1528             :         else
    1529           0 :                 ospf_flood_through_area(area, NULL /*nbr*/, new);
    1530             : 
    1531             :         /* Debug logging. */
    1532           0 :         ote_debug("MPLS-TE (%s): LSA[Type%d:%pI4]: Refresh Opaque-LSA/MPLS-TE",
    1533             :                   __func__, new->data->type, &new->data->id);
    1534           0 :         if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
    1535           0 :                 ospf_lsa_header_dump(new->data);
    1536             : 
    1537           0 :         return new;
    1538             : }
    1539             : 
    1540           0 : void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, enum lsa_opcode opcode)
    1541             : {
    1542           0 :         struct ospf_lsa lsa;
    1543           0 :         struct lsa_header lsah;
    1544           0 :         struct ospf *top;
    1545           0 :         uint32_t tmp;
    1546             : 
    1547           0 :         memset(&lsa, 0, sizeof(lsa));
    1548           0 :         memset(&lsah, 0, sizeof(lsah));
    1549           0 :         top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    1550             : 
    1551             :         /* Check if the pseudo link is ready to flood */
    1552           0 :         if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE))
    1553           0 :                 return;
    1554             : 
    1555           0 :         ote_debug("MPLS-TE (%s): Schedule %s%s%s LSA for interface %s",
    1556             :                   __func__,
    1557             :                   opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
    1558             :                   opcode == REFRESH_THIS_LSA ? "Refresh" : "",
    1559             :                   opcode == FLUSH_THIS_LSA ? "Flush" : "",
    1560             :                   lp->ifp ? lp->ifp->name : "-");
    1561             : 
    1562           0 :         lsa.area = lp->area;
    1563           0 :         lsa.data = &lsah;
    1564           0 :         if (IS_FLOOD_AS(lp->flags)) {
    1565           0 :                 lsah.type = OSPF_OPAQUE_AS_LSA;
    1566           0 :                 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
    1567           0 :                 lsah.id.s_addr = htonl(tmp);
    1568             :         } else {
    1569           0 :                 lsah.type = OSPF_OPAQUE_AREA_LSA;
    1570           0 :                 if (IS_INTER_AS(lp->type)) {
    1571             :                         /* Set the area context if not know */
    1572           0 :                         if (lp->area == NULL)
    1573           0 :                                 lp->area = ospf_area_lookup_by_area_id(
    1574             :                                         top, OspfMplsTE.interas_areaid);
    1575             :                         /* Unable to set the area context. Abort! */
    1576           0 :                         if (lp->area == NULL) {
    1577           0 :                                 flog_warn(
    1578             :                                         EC_OSPF_TE_UNEXPECTED,
    1579             :                                         "MPLS-TE (%s): Area context is null. Abort !",
    1580             :                                         __func__);
    1581           0 :                                 return;
    1582             :                         }
    1583           0 :                         tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA,
    1584             :                                               lp->instance);
    1585             :                 } else
    1586           0 :                         tmp = SET_OPAQUE_LSID(
    1587             :                                 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
    1588             :                                 lp->instance);
    1589           0 :                 lsah.id.s_addr = htonl(tmp);
    1590             :         }
    1591             : 
    1592           0 :         switch (opcode) {
    1593           0 :         case REORIGINATE_THIS_LSA:
    1594           0 :                 if (IS_FLOOD_AS(lp->flags)) {
    1595           0 :                         ospf_opaque_lsa_reoriginate_schedule(
    1596             :                                 (void *)top, OSPF_OPAQUE_AS_LSA,
    1597             :                                 OPAQUE_TYPE_INTER_AS_LSA);
    1598             :                 } else {
    1599           0 :                         if (IS_INTER_AS(lp->type))
    1600           0 :                                 ospf_opaque_lsa_reoriginate_schedule(
    1601           0 :                                         (void *)lp->area, OSPF_OPAQUE_AREA_LSA,
    1602             :                                         OPAQUE_TYPE_INTER_AS_LSA);
    1603             :                         else
    1604           0 :                                 ospf_opaque_lsa_reoriginate_schedule(
    1605           0 :                                         (void *)lp->area, OSPF_OPAQUE_AREA_LSA,
    1606             :                                         OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
    1607             :                 }
    1608             :                 break;
    1609           0 :         case REFRESH_THIS_LSA:
    1610           0 :                 ospf_opaque_lsa_refresh_schedule(&lsa);
    1611           0 :                 break;
    1612           0 :         case FLUSH_THIS_LSA:
    1613             :                 /* Reset Activity flag */
    1614           0 :                 lp->flags = LPFLG_LSA_INACTIVE;
    1615           0 :                 ospf_opaque_lsa_flush_schedule(&lsa);
    1616           0 :                 break;
    1617           0 :         default:
    1618           0 :                 flog_warn(EC_OSPF_TE_UNEXPECTED,
    1619             :                           "MPLS-TE (%s): Unknown opcode (%u)", __func__,
    1620             :                           opcode);
    1621           0 :                 break;
    1622             :         }
    1623             : }
    1624             : 
    1625             : /**
    1626             :  * ------------------------------------------------------
    1627             :  * Following are Link State Data Base control functions.
    1628             :  * ------------------------------------------------------
    1629             :  */
    1630             : 
    1631             : /**
    1632             :  * Get Vertex from TED by the router which advertised the LSA. A new Vertex and
    1633             :  * associated Link State Node are created if Vertex is not found.
    1634             :  *
    1635             :  * @param ted   Link State Traffic Engineering Database
    1636             :  * @param lsa   OSPF Link State Advertisement
    1637             :  *
    1638             :  * @return      Link State Vertex
    1639             :  */
    1640           0 : static struct ls_vertex *get_vertex(struct ls_ted *ted, struct ospf_lsa *lsa)
    1641             : {
    1642           0 :         struct ls_node_id lnid;
    1643           0 :         struct ls_node *lnode;
    1644           0 :         struct ls_vertex *vertex;
    1645             : 
    1646             :         /* Sanity Check */
    1647           0 :         if (!ted || !lsa || !lsa->data || !lsa->area)
    1648             :                 return NULL;
    1649             : 
    1650             :         /* Search if a Link State Vertex already exist */
    1651           0 :         lnid.origin = OSPFv2;
    1652           0 :         lnid.id.ip.addr = lsa->data->adv_router;
    1653           0 :         lnid.id.ip.area_id = lsa->area->area_id;
    1654           0 :         vertex = ls_find_vertex_by_id(ted, lnid);
    1655             : 
    1656             :         /* Create Node & Vertex in the Link State Date Base if not found */
    1657           0 :         if (!vertex) {
    1658           0 :                 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
    1659             : 
    1660           0 :                 lnode = ls_node_new(lnid, inaddr_any, in6addr_any);
    1661           0 :                 snprintfrr(lnode->name, MAX_NAME_LENGTH, "%pI4",
    1662             :                            &lnid.id.ip.addr);
    1663           0 :                 vertex = ls_vertex_add(ted, lnode);
    1664             :         }
    1665             : 
    1666           0 :         if (IS_LSA_SELF(lsa))
    1667           0 :                 ted->self = vertex;
    1668             : 
    1669             :         return vertex;
    1670             : }
    1671             : 
    1672             : /**
    1673             :  * Get Edge from TED by Link State Attribute ID. A new Edge and associated Link
    1674             :  * State Attributes are created if not found.
    1675             :  *
    1676             :  * @param ted           Link State Traffic Engineering Database
    1677             :  * @param adv           Link State Node ID of router which advertised Edge
    1678             :  * @param link_id       Link State Attribute ID
    1679             :  *
    1680             :  * @return              Link State Edge
    1681             :  */
    1682           0 : static struct ls_edge *get_edge(struct ls_ted *ted, struct ls_node_id adv,
    1683             :                                 struct in_addr link_id)
    1684             : {
    1685           0 :         uint64_t key;
    1686           0 :         struct ls_edge *edge;
    1687           0 :         struct ls_attributes *attr;
    1688             : 
    1689             :         /* Search Edge that corresponds to the Link ID */
    1690           0 :         key = ((uint64_t)ntohl(link_id.s_addr)) & 0xffffffff;
    1691           0 :         edge = ls_find_edge_by_key(ted, key);
    1692             : 
    1693             :         /* Create new one if not exist */
    1694           0 :         if (!edge) {
    1695           0 :                 attr = ls_attributes_new(adv, link_id, in6addr_any, 0);
    1696           0 :                 edge = ls_edge_add(ted, attr);
    1697             :         }
    1698             : 
    1699           0 :         return edge;
    1700             : }
    1701             : 
    1702             : /**
    1703             :  * Export Link State information to consumer daemon through ZAPI Link State
    1704             :  * Opaque Message.
    1705             :  *
    1706             :  * @param type          Type of Link State Element i.e. Vertex, Edge or Subnet
    1707             :  * @param link_state    Pointer to Link State Vertex, Edge or Subnet
    1708             :  *
    1709             :  * @return              0 if success, -1 otherwise
    1710             :  */
    1711           0 : static int ospf_te_export(uint8_t type, void *link_state)
    1712             : {
    1713           0 :         struct ls_message msg = {};
    1714           0 :         int rc = 0;
    1715             : 
    1716           0 :         if (!OspfMplsTE.export)
    1717             :                 return rc;
    1718             : 
    1719           0 :         switch (type) {
    1720           0 :         case LS_MSG_TYPE_NODE:
    1721           0 :                 ls_vertex2msg(&msg, (struct ls_vertex *)link_state);
    1722           0 :                 rc = ls_send_msg(zclient, &msg, NULL);
    1723           0 :                 break;
    1724           0 :         case LS_MSG_TYPE_ATTRIBUTES:
    1725           0 :                 ls_edge2msg(&msg, (struct ls_edge *)link_state);
    1726           0 :                 rc = ls_send_msg(zclient, &msg, NULL);
    1727           0 :                 break;
    1728           0 :         case LS_MSG_TYPE_PREFIX:
    1729           0 :                 ls_subnet2msg(&msg, (struct ls_subnet *)link_state);
    1730           0 :                 rc = ls_send_msg(zclient, &msg, NULL);
    1731           0 :                 break;
    1732             :         default:
    1733             :                 rc = -1;
    1734             :                 break;
    1735             :         }
    1736             : 
    1737             :         return rc;
    1738             : }
    1739             : 
    1740             : /**
    1741             :  * Update Link State Edge & Attributes from the given Link State Attributes ID
    1742             :  * and metric. This function is called when parsing Router LSA.
    1743             :  *
    1744             :  * @param ted           Link State Traffic Engineering Database
    1745             :  * @param vertex        Vertex where the Edge is attached as source
    1746             :  * @param link_data     Link State Edge ID
    1747             :  * @param metric        Standard metric attached to this Edge
    1748             :  */
    1749           0 : static void ospf_te_update_link(struct ls_ted *ted, struct ls_vertex *vertex,
    1750             :                                 struct in_addr link_data, uint8_t metric)
    1751             : {
    1752           0 :         struct ls_edge *edge;
    1753           0 :         struct ls_attributes *attr;
    1754             : 
    1755             :         /* Sanity check */
    1756           0 :         if (!ted || !vertex || !vertex->node)
    1757             :                 return;
    1758             : 
    1759             :         /* Get Corresponding Edge from Link State Data Base */
    1760           0 :         edge = get_edge(ted, vertex->node->adv, link_data);
    1761           0 :         attr = edge->attributes;
    1762             : 
    1763             :         /* re-attached edge to vertex if needed */
    1764           0 :         if (!edge->source)
    1765           0 :                 edge->source = vertex;
    1766             : 
    1767             :         /* Check if it is just an LSA refresh */
    1768           0 :         if ((CHECK_FLAG(attr->flags, LS_ATTR_METRIC)
    1769           0 :              && (attr->metric == metric))) {
    1770           0 :                 edge->status = SYNC;
    1771           0 :                 return;
    1772             :         }
    1773             : 
    1774             :         /* Update metric value */
    1775           0 :         attr->metric = metric;
    1776           0 :         SET_FLAG(attr->flags, LS_ATTR_METRIC);
    1777           0 :         if (edge->status != NEW)
    1778           0 :                 edge->status = UPDATE;
    1779             : 
    1780           0 :         ote_debug("    |- %s Edge %pI4 with metric %d",
    1781             :                   edge->status == NEW ? "Add" : "Update", &attr->standard.local,
    1782             :                   attr->metric);
    1783             : 
    1784             :         /* Export Link State Edge */
    1785           0 :         ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
    1786           0 :         edge->status = SYNC;
    1787             : }
    1788             : 
    1789             : /**
    1790             :  * Update Link State Subnet & Prefix from the given prefix and metric. This
    1791             :  * function is called when parsing Router LSA.
    1792             :  *
    1793             :  * @param ted           Link State Traffic Engineering Database
    1794             :  * @param vertex        Vertex where the Edge is attached as source
    1795             :  * @param p             Prefix associated to the Subnet
    1796             :  * @param metric        Standard metric attached to this Edge
    1797             :  */
    1798           0 : static void ospf_te_update_subnet(struct ls_ted *ted, struct ls_vertex *vertex,
    1799             :                                   struct prefix p, uint8_t metric)
    1800             : {
    1801           0 :         struct ls_subnet *subnet;
    1802           0 :         struct ls_prefix *ls_pref;
    1803             : 
    1804             :         /* Search if there is a Subnet for this prefix */
    1805           0 :         subnet = ls_find_subnet(ted, p);
    1806             : 
    1807             :         /* If found a Subnet, check if it is attached to this Vertex */
    1808           0 :         if (subnet) {
    1809             :                 /* Re-attach the subnet to the vertex if necessary */
    1810           0 :                 if (subnet->vertex != vertex) {
    1811           0 :                         subnet->vertex = vertex;
    1812           0 :                         listnode_add_sort_nodup(vertex->prefixes, subnet);
    1813             :                 }
    1814             :                 /* Check if it is a simple refresh */
    1815           0 :                 ls_pref = subnet->ls_pref;
    1816           0 :                 if ((CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
    1817           0 :                     && (ls_pref->metric == metric)) {
    1818           0 :                         subnet->status = SYNC;
    1819           0 :                         return;
    1820             :                 }
    1821           0 :                 ls_pref->metric = metric;
    1822           0 :                 SET_FLAG(ls_pref->flags, LS_PREF_METRIC);
    1823           0 :                 subnet->status = UPDATE;
    1824             :         } else {
    1825             :                 /* Create new Link State Prefix  */
    1826           0 :                 ls_pref = ls_prefix_new(vertex->node->adv, p);
    1827           0 :                 ls_pref->metric = metric;
    1828           0 :                 SET_FLAG(ls_pref->flags, LS_PREF_METRIC);
    1829             :                 /* and add it to the TED */
    1830           0 :                 subnet = ls_subnet_add(ted, ls_pref);
    1831             :         }
    1832             : 
    1833           0 :         ote_debug("    |- %s subnet %pFX with metric %d",
    1834             :                   subnet->status == NEW ? "Add" : "Update", &subnet->key,
    1835             :                   ls_pref->metric);
    1836             : 
    1837             :         /* Export Link State Subnet */
    1838           0 :         ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
    1839           0 :         subnet->status = SYNC;
    1840             : }
    1841             : 
    1842             : /**
    1843             :  * Delete Subnet that correspond to the given IPv4 address and export deletion
    1844             :  * information before removal. Prefix length is fixed to IPV4_MAX_BITLEN.
    1845             :  *
    1846             :  * @param ted   Links State Database
    1847             :  * @param addr  IPv4 address
    1848             :  */
    1849           0 : static void ospf_te_delete_subnet(struct ls_ted *ted, struct in_addr addr)
    1850             : {
    1851           0 :         struct prefix p;
    1852           0 :         struct ls_subnet *subnet;
    1853             : 
    1854             :         /* Search subnet that correspond to the address/32 as prefix */
    1855           0 :         p.family = AF_INET;
    1856           0 :         p.prefixlen = IPV4_MAX_BITLEN;
    1857           0 :         p.u.prefix4 = addr;
    1858           0 :         subnet = ls_find_subnet(ted, p);
    1859             : 
    1860             :         /* Remove subnet if found */
    1861           0 :         if (subnet) {
    1862           0 :                 subnet->status = DELETE;
    1863           0 :                 ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
    1864           0 :                 ls_subnet_del_all(ted, subnet);
    1865             :         }
    1866           0 : }
    1867             : 
    1868             : /**
    1869             :  * Parse Router LSA. This function will create or update corresponding Vertex,
    1870             :  * Edge and Subnet. It also remove Edge and Subnet if they are marked as Orphan
    1871             :  * once Router LSA is parsed.
    1872             :  *
    1873             :  * @param ted   Link State Traffic Engineering Database
    1874             :  * @param lsa   OSPF Link State Advertisement
    1875             :  *
    1876             :  * @return      0 if success, -1 otherwise
    1877             :  */
    1878           0 : static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
    1879             : {
    1880           0 :         struct router_lsa *rl;
    1881           0 :         enum ls_node_type type;
    1882           0 :         struct ls_vertex *vertex;
    1883           0 :         struct ls_edge *edge;
    1884           0 :         struct ls_subnet *subnet;
    1885           0 :         struct listnode *node;
    1886           0 :         int len, links;
    1887             : 
    1888             :         /* Sanity Check */
    1889           0 :         if (!ted || !lsa || !lsa->data)
    1890             :                 return -1;
    1891             : 
    1892           0 :         ote_debug("MPLS-TE (%s): Parse Router LSA[%pI4] from Router[%pI4]",
    1893             :                   __func__, &lsa->data->id, &lsa->data->adv_router);
    1894             : 
    1895             :         /* Get vertex from LSA Advertise Router ID */
    1896           0 :         vertex = get_vertex(ted, lsa);
    1897             : 
    1898             :         /* Set Node type information if it has changed */
    1899           0 :         rl = (struct router_lsa *)lsa->data;
    1900           0 :         if (IS_ROUTER_LSA_VIRTUAL(rl))
    1901             :                 type = PSEUDO;
    1902           0 :         else if (IS_ROUTER_LSA_EXTERNAL(rl))
    1903             :                 type = ASBR;
    1904           0 :         else if (IS_ROUTER_LSA_BORDER(rl))
    1905             :                 type = ABR;
    1906             :         else
    1907           0 :                 type = STANDARD;
    1908             : 
    1909           0 :         if (vertex->status == NEW) {
    1910           0 :                 vertex->node->type = type;
    1911           0 :                 SET_FLAG(vertex->node->flags, LS_NODE_TYPE);
    1912           0 :         } else if (vertex->node->type != type) {
    1913           0 :                 vertex->node->type = type;
    1914           0 :                 vertex->status = UPDATE;
    1915             :         }
    1916             : 
    1917             :         /* Check if Vertex has been modified */
    1918           0 :         if (vertex->status != SYNC) {
    1919           0 :                 ote_debug("  |- %s Vertex %pI4",
    1920             :                           vertex->status == NEW ? "Add" : "Update",
    1921             :                           &vertex->node->router_id);
    1922             : 
    1923             :                 /* Vertex is out of sync: export it */
    1924           0 :                 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
    1925           0 :                 vertex->status = SYNC;
    1926             :         }
    1927             : 
    1928             :         /* Mark outgoing Edge and Subnet as ORPHAN to detect deletion */
    1929           0 :         for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge))
    1930           0 :                 edge->status = ORPHAN;
    1931             : 
    1932           0 :         for (ALL_LIST_ELEMENTS_RO(vertex->prefixes, node, subnet))
    1933           0 :                 subnet->status = ORPHAN;
    1934             : 
    1935             :         /* Then, process Link Information */
    1936           0 :         len = lsa->size - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE;
    1937           0 :         links = ntohs(rl->links);
    1938           0 :         for (int i = 0; i < links && len > 0; len -= 12, i++) {
    1939           0 :                 struct prefix p;
    1940           0 :                 uint32_t metric;
    1941             : 
    1942           0 :                 switch (rl->link[i].type) {
    1943           0 :                 case LSA_LINK_TYPE_POINTOPOINT:
    1944           0 :                         ospf_te_update_link(ted, vertex, rl->link[i].link_data,
    1945           0 :                                             ntohs(rl->link[i].metric));
    1946             :                         /* Add corresponding subnet */
    1947           0 :                         p.family = AF_INET;
    1948           0 :                         p.prefixlen = IPV4_MAX_BITLEN;
    1949           0 :                         p.u.prefix4 = rl->link[i].link_data;
    1950           0 :                         metric = ntohs(rl->link[i].metric);
    1951           0 :                         ospf_te_update_subnet(ted, vertex, p, metric);
    1952           0 :                         break;
    1953           0 :                 case LSA_LINK_TYPE_STUB:
    1954             :                         /* Keep only /32 prefix */
    1955           0 :                         p.prefixlen = ip_masklen(rl->link[i].link_data);
    1956           0 :                         if (p.prefixlen == IPV4_MAX_BITLEN) {
    1957           0 :                                 p.family = AF_INET;
    1958           0 :                                 p.u.prefix4 = rl->link[i].link_id;
    1959           0 :                                 metric = ntohs(rl->link[i].metric);
    1960           0 :                                 ospf_te_update_subnet(ted, vertex, p, metric);
    1961             :                         }
    1962             :                         break;
    1963             :                 default:
    1964             :                         break;
    1965             :                 }
    1966             :         }
    1967             :         /* Clean remaining Orphan Edges or Subnets */
    1968           0 :         if (OspfMplsTE.export)
    1969           0 :                 ls_vertex_clean(ted, vertex, zclient);
    1970             :         else
    1971           0 :                 ls_vertex_clean(ted, vertex, NULL);
    1972             : 
    1973             :         return 0;
    1974             : }
    1975             : 
    1976             : /**
    1977             :  * Delete Vertex, Edge and Subnet associated to this Router LSA. This function
    1978             :  * is called when the router received such LSA with MAX_AGE (Flush) or when the
    1979             :  * router stop OSPF.
    1980             :  *
    1981             :  * @param ted   Link State Traffic Engineering Database
    1982             :  * @param lsa   OSPF Link State Advertisement
    1983             :  *
    1984             :  * @return      0 if success, -1 otherwise
    1985             :  */
    1986           0 : static int ospf_te_delete_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
    1987             : {
    1988           0 :         struct ls_node_id lnid;
    1989           0 :         struct ls_vertex *vertex;
    1990             : 
    1991             :         /* Sanity Check */
    1992           0 :         if (!ted || !lsa || !lsa->data)
    1993             :                 return -1;
    1994             : 
    1995             :         /* Search Vertex that corresponds to this LSA */
    1996           0 :         lnid.origin = OSPFv2;
    1997           0 :         lnid.id.ip.addr = lsa->data->adv_router;
    1998           0 :         lnid.id.ip.area_id = lsa->area->area_id;
    1999           0 :         vertex = ls_find_vertex_by_id(ted, lnid);
    2000           0 :         if (!vertex)
    2001             :                 return -1;
    2002             : 
    2003           0 :         ote_debug("MPLS-TE (%s): Delete Vertex %pI4 from Router LSA[%pI4]",
    2004             :                   __func__, &vertex->node->router_id, &lsa->data->id);
    2005             : 
    2006             :         /* Export deleted vertex ... */
    2007           0 :         vertex->status = DELETE;
    2008           0 :         ospf_te_export(LS_MSG_TYPE_NODE, vertex);
    2009             : 
    2010             :         /* ... and remove Node & Vertex from Link State Date Base */
    2011           0 :         ls_vertex_del_all(ted, vertex);
    2012             : 
    2013           0 :         return 0;
    2014             : }
    2015             : 
    2016             : /**
    2017             :  * Create or update Remote Vertex that corresponds to the remote ASBR of the
    2018             :  * foreign network if Edge is associated to an Inter-AS LSA (Type 6).
    2019             :  *
    2020             :  * @param ted   Link State Traffic Engineering Database
    2021             :  * @param edge  Link State Edge
    2022             :  */
    2023           0 : static void ospf_te_update_remote_asbr(struct ls_ted *ted, struct ls_edge *edge)
    2024             : {
    2025           0 :         struct ls_node_id lnid;
    2026           0 :         struct ls_vertex *vertex;
    2027           0 :         struct ls_node *lnode;
    2028           0 :         struct ls_attributes *attr;
    2029           0 :         struct prefix p;
    2030             : 
    2031             :         /* Sanity Check */
    2032           0 :         if (!ted || !edge)
    2033           0 :                 return;
    2034             : 
    2035             :         /* Search if a Link State Vertex already exist */
    2036           0 :         attr = edge->attributes;
    2037           0 :         lnid.origin = OSPFv2;
    2038           0 :         lnid.id.ip.addr = attr->standard.remote_addr;
    2039           0 :         lnid.id.ip.area_id = attr->adv.id.ip.area_id;
    2040           0 :         vertex = ls_find_vertex_by_id(ted, lnid);
    2041             : 
    2042             :         /* Create Node & Vertex in the Link State Date Base if not found */
    2043           0 :         if (!vertex) {
    2044           0 :                 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
    2045             : 
    2046           0 :                 lnode = ls_node_new(lnid, inaddr_any, in6addr_any);
    2047           0 :                 snprintfrr(lnode->name, MAX_NAME_LENGTH, "%pI4",
    2048             :                            &lnid.id.ip.addr);
    2049           0 :                 vertex = ls_vertex_add(ted, lnode);
    2050             :         }
    2051             : 
    2052             :         /* Update Node information */
    2053           0 :         lnode = vertex->node;
    2054           0 :         if (CHECK_FLAG(lnode->flags, LS_NODE_TYPE)) {
    2055           0 :                 if (lnode->type != RMT_ASBR) {
    2056           0 :                         lnode->type = RMT_ASBR;
    2057           0 :                         if (vertex->status != NEW)
    2058           0 :                                 vertex->status = UPDATE;
    2059             :                 }
    2060             :         } else {
    2061           0 :                 lnode->type = RMT_ASBR;
    2062           0 :                 SET_FLAG(lnode->flags, LS_NODE_TYPE);
    2063           0 :                 if (vertex->status != NEW)
    2064           0 :                         vertex->status = UPDATE;
    2065             :         }
    2066           0 :         if (CHECK_FLAG(lnode->flags, LS_NODE_AS_NUMBER)) {
    2067           0 :                 if (lnode->as_number != attr->standard.remote_as) {
    2068           0 :                         lnode->as_number = attr->standard.remote_as;
    2069           0 :                         if (vertex->status != NEW)
    2070           0 :                                 vertex->status = UPDATE;
    2071             :                 }
    2072             :         } else {
    2073           0 :                 lnode->as_number = attr->standard.remote_as;
    2074           0 :                 SET_FLAG(lnode->flags, LS_NODE_AS_NUMBER);
    2075           0 :                 if (vertex->status != NEW)
    2076           0 :                         vertex->status = UPDATE;
    2077             :         }
    2078             : 
    2079             :         /* Export Link State Vertex if needed */
    2080           0 :         if (vertex->status == NEW  || vertex->status == UPDATE) {
    2081           0 :                 ote_debug("  |- %s Remote Vertex %pI4 for AS %u",
    2082             :                           vertex->status == NEW ? "Add" : "Update",
    2083             :                           &lnode->router_id, lnode->as_number);
    2084           0 :                 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
    2085           0 :                 vertex->status = SYNC;
    2086             :         }
    2087             : 
    2088             :         /* Update corresponding Subnets */
    2089           0 :         p.family = AF_INET;
    2090           0 :         p.prefixlen = IPV4_MAX_BITLEN;
    2091           0 :         p.u.prefix4 = attr->standard.local;
    2092           0 :         ospf_te_update_subnet(ted, edge->source, p, attr->standard.te_metric);
    2093             : 
    2094           0 :         p.family = AF_INET;
    2095           0 :         p.prefixlen = IPV4_MAX_BITLEN;
    2096           0 :         p.u.prefix4 = attr->standard.remote_addr;
    2097           0 :         ospf_te_update_subnet(ted, vertex, p, attr->standard.te_metric);
    2098             : 
    2099             :         /* Connect Edge to the remote Vertex */
    2100           0 :         if (edge->destination == NULL) {
    2101           0 :                 edge->destination = vertex;
    2102           0 :                 listnode_add_sort_nodup(vertex->incoming_edges, edge);
    2103             :         }
    2104             : 
    2105             :         /* Finally set type to ASBR the node that advertised this Edge ... */
    2106           0 :         vertex = edge->source;
    2107           0 :         lnode = vertex->node;
    2108           0 :         if (CHECK_FLAG(lnode->flags, LS_NODE_TYPE)) {
    2109           0 :                 if (lnode->type != ASBR) {
    2110           0 :                         lnode->type = ASBR;
    2111           0 :                         if (vertex->status != NEW)
    2112           0 :                                 vertex->status = UPDATE;
    2113             :                 }
    2114             :         } else {
    2115           0 :                 lnode->type = ASBR;
    2116           0 :                 SET_FLAG(lnode->flags, LS_NODE_TYPE);
    2117           0 :                 if (vertex->status != NEW)
    2118           0 :                         vertex->status = UPDATE;
    2119             :         }
    2120             : 
    2121             :         /* ... and Export it if needed */
    2122           0 :         if (vertex->status == NEW  || vertex->status == UPDATE) {
    2123           0 :                 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
    2124           0 :                 vertex->status = SYNC;
    2125             :         }
    2126             : }
    2127             : 
    2128             : /**
    2129             :  * Parse Opaque Traffic Engineering LSA (Type 1) TLVs and create or update the
    2130             :  * corresponding Link State Edge and Attributes. Vertex connections are also
    2131             :  * updated if needed based on the remote IP address of the Edge and existing
    2132             :  * reverse Edge.
    2133             :  *
    2134             :  * @param ted   Link State Traffic Engineering Database
    2135             :  * @param lsa   OSPF Link State Advertisement
    2136             :  *
    2137             :  * @return      0 if success, -1 otherwise
    2138             :  */
    2139           0 : static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
    2140             : {
    2141           0 :         struct ls_edge *edge;
    2142           0 :         struct ls_vertex *vertex;
    2143           0 :         struct ls_attributes *old, attr = {};
    2144           0 :         struct tlv_header *tlvh;
    2145           0 :         void *value;
    2146           0 :         uint16_t len, sum;
    2147           0 :         uint8_t lsa_id;
    2148             : 
    2149             :         /* Initialize Attribute */
    2150           0 :         attr.adv.origin = OSPFv2;
    2151           0 :         attr.adv.id.ip.addr = lsa->data->adv_router;
    2152           0 :         if (lsa->data->type != OSPF_OPAQUE_AS_LSA)
    2153           0 :                 attr.adv.id.ip.area_id = lsa->area->area_id;
    2154             : 
    2155             :         /* Initialize TLV browsing */
    2156           0 :         tlvh = TLV_HDR_TOP(lsa->data);
    2157           0 :         len = lsa->size - OSPF_LSA_HEADER_SIZE;
    2158             : 
    2159             :         /* Check if TE Router-ID TLV is present */
    2160           0 :         if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR) {
    2161             :                 /* if TE Router-ID is alone, we are done ... */
    2162           0 :                 if (len == TE_LINK_SUBTLV_DEF_SIZE)
    2163             :                         return 0;
    2164             : 
    2165             :                 /* ... otherwise, skip it */
    2166           0 :                 len -= TE_LINK_SUBTLV_DEF_SIZE + TLV_HDR_SIZE;
    2167           0 :                 tlvh = TLV_HDR_NEXT(tlvh);
    2168             :         }
    2169             : 
    2170             :         /* Check if we have a valid TE Link TLV */
    2171           0 :         if ((len == 0) || (ntohs(tlvh->type) != TE_TLV_LINK))
    2172             :                 return 0;
    2173             : 
    2174           0 :         sum = sizeof(struct tlv_header);
    2175             :         /* Browse sub-TLV and fulfill Link State Attributes */
    2176           0 :         for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
    2177           0 :                 uint32_t val32, tab32[2];
    2178           0 :                 float valf, tabf[8];
    2179           0 :                 struct in_addr addr;
    2180             : 
    2181           0 :                 value = TLV_DATA(tlvh);
    2182           0 :                 switch (ntohs(tlvh->type)) {
    2183           0 :                 case TE_LINK_SUBTLV_LCLIF_IPADDR:
    2184           0 :                         memcpy(&addr, value, TE_LINK_SUBTLV_DEF_SIZE);
    2185           0 :                         attr.standard.local = addr;
    2186           0 :                         SET_FLAG(attr.flags, LS_ATTR_LOCAL_ADDR);
    2187           0 :                         break;
    2188           0 :                 case TE_LINK_SUBTLV_RMTIF_IPADDR:
    2189           0 :                         memcpy(&addr, value, TE_LINK_SUBTLV_DEF_SIZE);
    2190           0 :                         attr.standard.remote = addr;
    2191           0 :                         SET_FLAG(attr.flags, LS_ATTR_NEIGH_ADDR);
    2192           0 :                         break;
    2193           0 :                 case TE_LINK_SUBTLV_TE_METRIC:
    2194           0 :                         memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
    2195           0 :                         attr.standard.te_metric = ntohl(val32);
    2196           0 :                         SET_FLAG(attr.flags, LS_ATTR_TE_METRIC);
    2197           0 :                         break;
    2198           0 :                 case TE_LINK_SUBTLV_MAX_BW:
    2199           0 :                         memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
    2200           0 :                         attr.standard.max_bw = ntohf(valf);
    2201           0 :                         SET_FLAG(attr.flags, LS_ATTR_MAX_BW);
    2202           0 :                         break;
    2203           0 :                 case TE_LINK_SUBTLV_MAX_RSV_BW:
    2204           0 :                         memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
    2205           0 :                         attr.standard.max_rsv_bw = ntohf(valf);
    2206           0 :                         SET_FLAG(attr.flags, LS_ATTR_MAX_RSV_BW);
    2207           0 :                         break;
    2208           0 :                 case TE_LINK_SUBTLV_UNRSV_BW:
    2209           0 :                         memcpy(tabf, value, TE_LINK_SUBTLV_UNRSV_SIZE);
    2210           0 :                         for (int i = 0; i < MAX_CLASS_TYPE; i++)
    2211           0 :                                 attr.standard.unrsv_bw[i] = ntohf(tabf[i]);
    2212           0 :                         SET_FLAG(attr.flags, LS_ATTR_UNRSV_BW);
    2213           0 :                         break;
    2214           0 :                 case TE_LINK_SUBTLV_RSC_CLSCLR:
    2215           0 :                         memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
    2216           0 :                         attr.standard.admin_group = ntohl(val32);
    2217           0 :                         SET_FLAG(attr.flags, LS_ATTR_ADM_GRP);
    2218           0 :                         break;
    2219           0 :                 case TE_LINK_SUBTLV_LLRI:
    2220           0 :                         memcpy(tab32, value, TE_LINK_SUBTLV_LLRI_SIZE);
    2221           0 :                         attr.standard.local_id = ntohl(tab32[0]);
    2222           0 :                         attr.standard.remote_id = ntohl(tab32[1]);
    2223           0 :                         SET_FLAG(attr.flags, LS_ATTR_LOCAL_ID);
    2224           0 :                         SET_FLAG(attr.flags, LS_ATTR_NEIGH_ID);
    2225           0 :                         break;
    2226           0 :                 case TE_LINK_SUBTLV_RIP:
    2227           0 :                         memcpy(&addr, value, TE_LINK_SUBTLV_DEF_SIZE);
    2228           0 :                         attr.standard.remote_addr = addr;
    2229           0 :                         SET_FLAG(attr.flags, LS_ATTR_REMOTE_ADDR);
    2230           0 :                         break;
    2231           0 :                 case TE_LINK_SUBTLV_RAS:
    2232           0 :                         memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
    2233           0 :                         attr.standard.remote_as = ntohl(val32);
    2234           0 :                         SET_FLAG(attr.flags, LS_ATTR_REMOTE_AS);
    2235           0 :                         break;
    2236           0 :                 case TE_LINK_SUBTLV_AV_DELAY:
    2237           0 :                         memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
    2238           0 :                         attr.extended.delay = ntohl(val32);
    2239           0 :                         SET_FLAG(attr.flags, LS_ATTR_DELAY);
    2240           0 :                         break;
    2241           0 :                 case TE_LINK_SUBTLV_MM_DELAY:
    2242           0 :                         memcpy(tab32, value, TE_LINK_SUBTLV_MM_DELAY_SIZE);
    2243           0 :                         attr.extended.min_delay = ntohl(tab32[0]);
    2244           0 :                         attr.extended.max_delay = ntohl(tab32[1]);
    2245           0 :                         SET_FLAG(attr.flags, LS_ATTR_MIN_MAX_DELAY);
    2246           0 :                         break;
    2247           0 :                 case TE_LINK_SUBTLV_DELAY_VAR:
    2248           0 :                         memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
    2249           0 :                         attr.extended.jitter = ntohl(val32);
    2250           0 :                         SET_FLAG(attr.flags, LS_ATTR_JITTER);
    2251           0 :                         break;
    2252           0 :                 case TE_LINK_SUBTLV_PKT_LOSS:
    2253           0 :                         memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
    2254           0 :                         attr.extended.pkt_loss = ntohl(val32);
    2255           0 :                         SET_FLAG(attr.flags, LS_ATTR_PACKET_LOSS);
    2256           0 :                         break;
    2257           0 :                 case TE_LINK_SUBTLV_RES_BW:
    2258           0 :                         memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
    2259           0 :                         attr.extended.rsv_bw = ntohf(valf);
    2260           0 :                         SET_FLAG(attr.flags, LS_ATTR_RSV_BW);
    2261           0 :                         break;
    2262           0 :                 case TE_LINK_SUBTLV_AVA_BW:
    2263           0 :                         memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
    2264           0 :                         attr.extended.ava_bw = ntohf(valf);
    2265           0 :                         SET_FLAG(attr.flags, LS_ATTR_AVA_BW);
    2266           0 :                         break;
    2267           0 :                 case TE_LINK_SUBTLV_USE_BW:
    2268           0 :                         memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
    2269           0 :                         attr.extended.used_bw = ntohf(valf);
    2270           0 :                         SET_FLAG(attr.flags, LS_ATTR_USE_BW);
    2271           0 :                         break;
    2272             :                 default:
    2273             :                         break;
    2274             :                 }
    2275           0 :                 sum += TLV_SIZE(tlvh);
    2276             :         }
    2277             : 
    2278             :         /* Get corresponding Edge from Link State Data Base */
    2279           0 :         edge = get_edge(ted, attr.adv, attr.standard.local);
    2280           0 :         old = edge->attributes;
    2281             : 
    2282           0 :         ote_debug("  |- Process Traffic Engineering LSA %pI4 for Edge %pI4",
    2283             :                   &lsa->data->id, &attr.standard.local);
    2284             : 
    2285             :         /* Update standard fields */
    2286           0 :         len = sizeof(struct ls_standard);
    2287           0 :         if ((attr.flags & 0x0FFFF) == (old->flags & 0x0FFFF)) {
    2288           0 :                 if (memcmp(&attr.standard, &old->standard, len) != 0) {
    2289           0 :                         memcpy(&old->standard, &attr.standard, len);
    2290           0 :                         if (edge->status != NEW)
    2291           0 :                                 edge->status = UPDATE;
    2292             :                 }
    2293             :         } else {
    2294           0 :                 memcpy(&old->standard, &attr.standard, len);
    2295           0 :                 old->flags |= attr.flags & 0x0FFFF;
    2296           0 :                 if (edge->status != NEW)
    2297           0 :                         edge->status = UPDATE;
    2298             :         }
    2299             :         /* Update extended fields */
    2300           0 :         len = sizeof(struct ls_extended);
    2301           0 :         if ((attr.flags & 0x0FF0000) == (old->flags & 0x0FF0000)) {
    2302           0 :                 if (memcmp(&attr.extended, &old->extended, len) != 0) {
    2303           0 :                         memcpy(&old->extended, &attr.extended, len);
    2304           0 :                         if (edge->status != NEW)
    2305           0 :                                 edge->status = UPDATE;
    2306             :                 }
    2307             :         } else {
    2308           0 :                 memcpy(&old->extended, &attr.extended, len);
    2309           0 :                 old->flags |= attr.flags & 0x0FF0000;
    2310           0 :                 if (edge->status != NEW)
    2311           0 :                         edge->status = UPDATE;
    2312             :         }
    2313             : 
    2314             :         /* If LSA is an Opaque Inter-AS, Add Node and Subnet */
    2315           0 :         lsa_id = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
    2316           0 :         if (lsa_id ==  OPAQUE_TYPE_INTER_AS_LSA)
    2317           0 :                 ospf_te_update_remote_asbr(ted, edge);
    2318             : 
    2319             :         /* Update remote Link if remote IP addr is known */
    2320           0 :         if (CHECK_FLAG(old->flags, LS_ATTR_NEIGH_ADDR)) {
    2321           0 :                 struct ls_edge *dst;
    2322             : 
    2323           0 :                 dst = ls_find_edge_by_destination(ted, old);
    2324             :                 /* Attach remote link if not set */
    2325           0 :                 if (dst && edge->source && dst->destination == NULL) {
    2326           0 :                         vertex = edge->source;
    2327           0 :                         if (vertex->incoming_edges)
    2328           0 :                                 listnode_add_sort_nodup(vertex->incoming_edges,
    2329             :                                                         dst);
    2330           0 :                         dst->destination = vertex;
    2331             :                 }
    2332             :                 /* and destination vertex to this edge */
    2333           0 :                 if (dst && dst->source && edge->destination == NULL) {
    2334           0 :                         vertex = dst->source;
    2335           0 :                         if (vertex->incoming_edges)
    2336           0 :                                 listnode_add_sort_nodup(vertex->incoming_edges,
    2337             :                                                         edge);
    2338           0 :                         edge->destination = vertex;
    2339             :                 }
    2340             :         }
    2341             : 
    2342             :         /* Export Link State Edge if needed */
    2343           0 :         if (edge->status == NEW || edge->status == UPDATE) {
    2344           0 :                 ote_debug("  |- %s TE info. for Edge %pI4",
    2345             :                           edge->status == NEW ? "Add" : "Update",
    2346             :                           &edge->attributes->standard.local);
    2347             : 
    2348           0 :                 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
    2349           0 :                 edge->status = SYNC;
    2350             :         }
    2351             : 
    2352             :         return 0;
    2353             : }
    2354             : 
    2355             : /**
    2356             :  * Delete Link State Attributes information that correspond to the Opaque
    2357             :  * Traffic Engineering LSA (Type 1) TLVs. Note that the Edge is not removed.
    2358             :  *
    2359             :  * @param ted   Link State Traffic Engineering Database
    2360             :  * @param lsa   OSPF Link State Advertisement
    2361             :  *
    2362             :  * @return      0 if success, -1 otherwise
    2363             :  */
    2364           0 : static int ospf_te_delete_te(struct ls_ted *ted, struct ospf_lsa *lsa)
    2365             : {
    2366           0 :         struct ls_edge *edge;
    2367           0 :         struct ls_attributes *attr;
    2368           0 :         struct tlv_header *tlvh;
    2369           0 :         struct in_addr addr;
    2370           0 :         uint64_t key = 0;
    2371           0 :         uint16_t len, sum;
    2372           0 :         uint8_t lsa_id;
    2373             : 
    2374             :         /* Initialize TLV browsing */
    2375           0 :         tlvh = TLV_HDR_TOP(lsa->data);
    2376             :         /* Skip Router TE ID if present */
    2377           0 :         if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR)
    2378           0 :                 tlvh = TLV_HDR_NEXT(tlvh);
    2379           0 :         len = TLV_BODY_SIZE(tlvh);
    2380           0 :         sum = sizeof(struct tlv_header);
    2381             : 
    2382             :         /* Browse sub-TLV to find Link ID */
    2383           0 :         for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
    2384           0 :                 if (ntohs(tlvh->type) == TE_LINK_SUBTLV_LCLIF_IPADDR) {
    2385           0 :                         memcpy(&addr, TLV_DATA(tlvh), TE_LINK_SUBTLV_DEF_SIZE);
    2386           0 :                         key = ((uint64_t)ntohl(addr.s_addr)) & 0xffffffff;
    2387           0 :                         break;
    2388             :                 }
    2389           0 :                 sum += TLV_SIZE(tlvh);
    2390             :         }
    2391           0 :         if (key == 0)
    2392             :                 return 0;
    2393             : 
    2394             :         /* Search Edge that corresponds to the Link ID */
    2395           0 :         edge = ls_find_edge_by_key(ted, key);
    2396           0 :         if (!edge || !edge->attributes)
    2397             :                 return 0;
    2398           0 :         attr = edge->attributes;
    2399             : 
    2400             :         /* First, remove Remote ASBR and associated Edge & Subnet if any */
    2401           0 :         lsa_id = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
    2402           0 :         if (lsa_id ==  OPAQUE_TYPE_INTER_AS_LSA) {
    2403           0 :                 ote_debug("  |- Delete remote ASBR, Edge and Subnet");
    2404             : 
    2405           0 :                 if (edge->destination) {
    2406           0 :                         edge->destination->status = DELETE;
    2407           0 :                         ospf_te_export(LS_MSG_TYPE_NODE, edge->destination);
    2408           0 :                         ls_vertex_del_all(ted, edge->destination);
    2409             :                 }
    2410             : 
    2411           0 :                 ospf_te_delete_subnet(ted, attr->standard.local);
    2412             : 
    2413           0 :                 edge->status = DELETE;
    2414           0 :                 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
    2415           0 :                 ls_edge_del_all(ted, edge);
    2416             : 
    2417           0 :                 return 0;
    2418             :         }
    2419             : 
    2420           0 :         ote_debug("  |- Delete TE info. for Edge %pI4",
    2421             :                   &edge->attributes->standard.local);
    2422             : 
    2423             :         /* Remove Link State Attributes TE information */
    2424           0 :         memset(&attr->standard, 0, sizeof(struct ls_standard));
    2425           0 :         attr->flags &= 0x0FFFF;
    2426           0 :         memset(&attr->extended, 0, sizeof(struct ls_extended));
    2427           0 :         attr->flags &= 0x0FF0000;
    2428           0 :         ls_attributes_srlg_del(attr);
    2429             : 
    2430             :         /* Export Edge that has been updated */
    2431           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)
    2432           0 :             || CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
    2433           0 :                 edge->status = UPDATE;
    2434           0 :                 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
    2435           0 :                 edge->status = SYNC;
    2436             :         } else {
    2437             :                 /* Remove completely the Edge if Segment Routing is not set */
    2438           0 :                 ospf_te_delete_subnet(ted, attr->standard.local);
    2439           0 :                 edge->status = DELETE;
    2440           0 :                 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
    2441           0 :                 ls_edge_del_all(ted, edge);
    2442             :         }
    2443             : 
    2444             :         return 0;
    2445             : }
    2446             : 
    2447             : /**
    2448             :  * Parse Opaque Router Information LSA (Type 4) TLVs and update the
    2449             :  * corresponding Link State Vertex with these information (Segment Routing).
    2450             :  *
    2451             :  * @param ted   Link State Traffic Engineering Database
    2452             :  * @param lsa   OSPF Link State Advertisement
    2453             :  *
    2454             :  * @return      0 if success, -1 otherwise
    2455             :  */
    2456           0 : static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
    2457             : {
    2458           0 :         struct ls_vertex *vertex;
    2459           0 :         struct ls_node *node;
    2460           0 :         struct lsa_header *lsah = lsa->data;
    2461           0 :         struct tlv_header *tlvh;
    2462           0 :         uint16_t len = 0, sum = 0;
    2463             : 
    2464             :         /* Get vertex / Node from LSA Advertised Router ID */
    2465           0 :         vertex = get_vertex(ted, lsa);
    2466           0 :         node = vertex->node;
    2467             : 
    2468           0 :         ote_debug("  |- Process Router Information LSA %pI4 for Vertex %pI4",
    2469             :                   &lsa->data->id, &node->router_id);
    2470             : 
    2471             :         /* Initialize TLV browsing */
    2472           0 :         len = lsa->size - OSPF_LSA_HEADER_SIZE;
    2473           0 :         for (tlvh = TLV_HDR_TOP(lsah); sum < len && tlvh;
    2474           0 :              tlvh = TLV_HDR_NEXT(tlvh)) {
    2475           0 :                 struct ri_sr_tlv_sr_algorithm *algo;
    2476           0 :                 struct ri_sr_tlv_sid_label_range *range;
    2477           0 :                 struct ri_sr_tlv_node_msd *msd;
    2478           0 :                 uint32_t size, lower;
    2479             : 
    2480           0 :                 switch (ntohs(tlvh->type)) {
    2481             :                 case RI_SR_TLV_SR_ALGORITHM:
    2482             :                         algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
    2483             : 
    2484           0 :                         for (int i = 0; i < ntohs(algo->header.length); i++) {
    2485           0 :                                 if (CHECK_FLAG(node->flags, LS_NODE_SR)
    2486           0 :                                     && (node->algo[i] == algo->value[i]))
    2487           0 :                                         continue;
    2488             : 
    2489           0 :                                 node->algo[i] = algo->value[i];
    2490           0 :                                 SET_FLAG(node->flags, LS_NODE_SR);
    2491           0 :                                 if (vertex->status != NEW)
    2492           0 :                                         vertex->status = UPDATE;
    2493             :                         }
    2494             : 
    2495             :                         /* Reset other Algorithms */
    2496           0 :                         for (int i = ntohs(algo->header.length); i < 2; i++) {
    2497           0 :                                 if (vertex->status != NEW
    2498           0 :                                     && node->algo[i] != SR_ALGORITHM_UNSET)
    2499           0 :                                         vertex->status = UPDATE;
    2500           0 :                                 node->algo[i] = SR_ALGORITHM_UNSET;
    2501             :                         }
    2502             : 
    2503             :                         break;
    2504             : 
    2505           0 :                 case RI_SR_TLV_SRGB_LABEL_RANGE:
    2506           0 :                         range = (struct ri_sr_tlv_sid_label_range *)tlvh;
    2507           0 :                         size = GET_RANGE_SIZE(ntohl(range->size));
    2508           0 :                         lower = GET_LABEL(ntohl(range->lower.value));
    2509           0 :                         if ((CHECK_FLAG(node->flags, LS_NODE_SR))
    2510           0 :                             && ((node->srgb.range_size == size)
    2511           0 :                                 && (node->srgb.lower_bound == lower)))
    2512             :                                 break;
    2513             : 
    2514           0 :                         node->srgb.range_size = size;
    2515           0 :                         node->srgb.lower_bound = lower;
    2516           0 :                         SET_FLAG(node->flags, LS_NODE_SR);
    2517           0 :                         if (vertex->status != NEW)
    2518           0 :                                 vertex->status = UPDATE;
    2519             : 
    2520             :                         break;
    2521             : 
    2522           0 :                 case RI_SR_TLV_SRLB_LABEL_RANGE:
    2523           0 :                         range = (struct ri_sr_tlv_sid_label_range *)tlvh;
    2524           0 :                         size = GET_RANGE_SIZE(ntohl(range->size));
    2525           0 :                         lower = GET_LABEL(ntohl(range->lower.value));
    2526           0 :                         if ((CHECK_FLAG(node->flags, LS_NODE_SRLB))
    2527           0 :                             && ((node->srlb.range_size == size)
    2528           0 :                                 && (node->srlb.lower_bound == lower)))
    2529             :                                 break;
    2530             : 
    2531           0 :                         node->srlb.range_size = size;
    2532           0 :                         node->srlb.lower_bound = lower;
    2533           0 :                         SET_FLAG(node->flags, LS_NODE_SRLB);
    2534           0 :                         if (vertex->status != NEW)
    2535           0 :                                 vertex->status = UPDATE;
    2536             : 
    2537             :                         break;
    2538             : 
    2539           0 :                 case RI_SR_TLV_NODE_MSD:
    2540           0 :                         msd = (struct ri_sr_tlv_node_msd *)tlvh;
    2541           0 :                         if ((CHECK_FLAG(node->flags, LS_NODE_MSD))
    2542           0 :                             && (node->msd == msd->value))
    2543             :                                 break;
    2544             : 
    2545           0 :                         node->msd = msd->value;
    2546           0 :                         SET_FLAG(node->flags, LS_NODE_MSD);
    2547           0 :                         if (vertex->status != NEW)
    2548           0 :                                 vertex->status = UPDATE;
    2549             : 
    2550             :                         break;
    2551             : 
    2552             :                 default:
    2553             :                         break;
    2554             :                 }
    2555           0 :                 sum += TLV_SIZE(tlvh);
    2556             :         }
    2557             : 
    2558             :         /* Vertex has been created or updated: export it */
    2559           0 :         if (vertex->status == NEW || vertex->status == UPDATE) {
    2560           0 :                 ote_debug("  |- %s SR info - SRGB[%d/%d] for Vertex %pI4",
    2561             :                           vertex->status == NEW ? "Add" : "Update",
    2562             :                           vertex->node->srgb.lower_bound,
    2563             :                           vertex->node->srgb.range_size,
    2564             :                           &vertex->node->router_id);
    2565             : 
    2566           0 :                 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
    2567           0 :                 vertex->status = SYNC;
    2568             :         }
    2569             : 
    2570           0 :         return 0;
    2571             : }
    2572             : 
    2573             : /**
    2574             :  * Delete Link State Node information (Segment Routing) that correspond to the
    2575             :  * Opaque Router Information LSA (Type 4) TLVs. Note that the Vertex is not
    2576             :  * removed.
    2577             :  *
    2578             :  * @param ted   Link State Traffic Engineering Database
    2579             :  * @param lsa   OSPF Link State Advertisement
    2580             :  *
    2581             :  * @return      0 if success, -1 otherwise
    2582             :  */
    2583           0 : static int ospf_te_delete_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
    2584             : {
    2585           0 :         struct ls_node_id lnid;
    2586           0 :         struct ls_vertex *vertex;
    2587           0 :         struct ls_node *node;
    2588             : 
    2589             :         /* Search if a Link State Vertex already exist */
    2590           0 :         lnid.origin = OSPFv2;
    2591           0 :         lnid.id.ip.addr = lsa->data->adv_router;
    2592           0 :         lnid.id.ip.area_id = lsa->area->area_id;
    2593           0 :         vertex = ls_find_vertex_by_id(ted, lnid);
    2594           0 :         if (!vertex)
    2595             :                 return -1;
    2596             : 
    2597             :         /* Remove Segment Routing Information if any */
    2598           0 :         node = vertex->node;
    2599           0 :         UNSET_FLAG(node->flags, LS_NODE_SR);
    2600           0 :         memset(&node->srgb, 0, sizeof(struct ls_srgb));
    2601           0 :         node->algo[0] = SR_ALGORITHM_UNSET;
    2602           0 :         node->algo[1] = SR_ALGORITHM_UNSET;
    2603           0 :         UNSET_FLAG(node->flags, LS_NODE_SRLB);
    2604           0 :         memset(&node->srlb, 0, sizeof(struct ls_srlb));
    2605           0 :         UNSET_FLAG(node->flags, LS_NODE_MSD);
    2606           0 :         node->msd = 0;
    2607           0 :         vertex->status = UPDATE;
    2608             : 
    2609           0 :         ote_debug("  |- Delete SR info. for Vertex %pI4",
    2610             :                   &vertex->node->router_id);
    2611             : 
    2612             :         /* Vertex has been updated: export it */
    2613           0 :         ospf_te_export(LS_MSG_TYPE_NODE, vertex);
    2614           0 :         vertex->status = SYNC;
    2615             : 
    2616           0 :         return 0;
    2617             : }
    2618             : 
    2619             : /**
    2620             :  * Parse Opaque Extended Prefix LSA (Type 7) TLVs and update the corresponding
    2621             :  * Link State Subnet with these information (Segment Routing ID).
    2622             :  *
    2623             :  * @param ted   Link State Traffic Engineering Database
    2624             :  * @param lsa   OSPF Link State Advertisement
    2625             :  *
    2626             :  * @return      0 if success, -1 otherwise
    2627             :  */
    2628           0 : static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
    2629             : {
    2630           0 :         struct ls_node_id lnid;
    2631           0 :         struct ls_subnet *subnet;
    2632           0 :         struct ls_prefix *ls_pref;
    2633           0 :         struct prefix pref;
    2634           0 :         struct ext_tlv_prefix *ext;
    2635           0 :         struct ext_subtlv_prefix_sid *pref_sid;
    2636           0 :         uint32_t label;
    2637             : 
    2638             :         /* Get corresponding Subnet from Link State Data Base */
    2639           0 :         ext = (struct ext_tlv_prefix *)TLV_HDR_TOP(lsa->data);
    2640           0 :         pref.family = AF_INET;
    2641           0 :         pref.prefixlen = ext->pref_length;
    2642           0 :         pref.u.prefix4 = ext->address;
    2643           0 :         subnet = ls_find_subnet(ted, pref);
    2644             : 
    2645             :         /* Create new Link State Prefix if not found */
    2646           0 :         if (!subnet) {
    2647           0 :                 lnid.origin = OSPFv2;
    2648           0 :                 lnid.id.ip.addr = lsa->data->adv_router;
    2649           0 :                 lnid.id.ip.area_id = lsa->area->area_id;
    2650           0 :                 ls_pref = ls_prefix_new(lnid, pref);
    2651             :                 /* and add it to the TED */
    2652           0 :                 subnet = ls_subnet_add(ted, ls_pref);
    2653             :         }
    2654             : 
    2655           0 :         ote_debug("  |- Process Extended Prefix LSA %pI4 for subnet %pFX",
    2656             :                   &lsa->data->id, &pref);
    2657             : 
    2658             :         /* Initialize TLV browsing */
    2659           0 :         ls_pref = subnet->ls_pref;
    2660           0 :         pref_sid = (struct ext_subtlv_prefix_sid *)((char *)(ext) + TLV_HDR_SIZE
    2661             :                                                     + EXT_TLV_PREFIX_SIZE);
    2662           0 :         label = CHECK_FLAG(pref_sid->flags, EXT_SUBTLV_PREFIX_SID_VFLG)
    2663           0 :                         ? GET_LABEL(ntohl(pref_sid->value))
    2664           0 :                         : ntohl(pref_sid->value);
    2665             : 
    2666             :         /* Check if it is a simple refresh */
    2667           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)
    2668           0 :             && ls_pref->sr.algo == pref_sid->algorithm
    2669           0 :             && ls_pref->sr.sid_flag == pref_sid->flags
    2670           0 :             && ls_pref->sr.sid == label)
    2671             :                 return 0;
    2672             : 
    2673             :         /* Fulfill SR information */
    2674           0 :         ls_pref->sr.algo = pref_sid->algorithm;
    2675           0 :         ls_pref->sr.sid_flag = pref_sid->flags;
    2676           0 :         ls_pref->sr.sid = label;
    2677           0 :         SET_FLAG(ls_pref->flags, LS_PREF_SR);
    2678           0 :         if (subnet->status != NEW)
    2679           0 :                 subnet->status = UPDATE;
    2680             : 
    2681             :         /* Export Subnet if needed */
    2682           0 :         if (subnet->status == NEW || subnet->status == UPDATE) {
    2683           0 :                 ote_debug("  |- %s SID %d to subnet %pFX",
    2684             :                           subnet->status == NEW ? "Add" : "Update",
    2685             :                           ls_pref->sr.sid, &ls_pref->pref);
    2686             : 
    2687           0 :                 ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
    2688           0 :                 subnet->status = SYNC;
    2689             :         }
    2690             : 
    2691             :         return 0;
    2692             : }
    2693             : 
    2694             : /**
    2695             :  * Delete Link State Subnet information (Segment Routing ID) that correspond to
    2696             :  * the Opaque Extended Prefix LSA (Type 7) TLVs. Note that the Subnet is not
    2697             :  * removed.
    2698             :  *
    2699             :  * @param ted   Link State Traffic Engineering Database
    2700             :  * @param lsa   OSPF Link State Advertisement
    2701             :  *
    2702             :  * @return      0 if success, -1 otherwise
    2703             :  */
    2704           0 : static int ospf_te_delete_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
    2705             : {
    2706           0 :         struct ls_subnet *subnet;
    2707           0 :         struct ls_prefix *ls_pref;
    2708           0 :         struct prefix pref;
    2709           0 :         struct ext_tlv_prefix *ext;
    2710             : 
    2711             :         /* Get corresponding Subnet from Link State Data Base */
    2712           0 :         ext = (struct ext_tlv_prefix *)TLV_HDR_TOP(lsa->data);
    2713           0 :         pref.family = AF_INET;
    2714           0 :         pref.prefixlen = ext->pref_length;
    2715           0 :         pref.u.prefix4 = ext->address;
    2716           0 :         subnet = ls_find_subnet(ted, pref);
    2717             : 
    2718             :         /* Check if there is a corresponding subnet */
    2719           0 :         if (!subnet)
    2720             :                 return -1;
    2721             : 
    2722           0 :         ote_debug("  |- Delete SID %d to subnet %pFX", subnet->ls_pref->sr.sid,
    2723             :                   &subnet->ls_pref->pref);
    2724             : 
    2725             :         /* Remove Segment Routing information */
    2726           0 :         ls_pref = subnet->ls_pref;
    2727           0 :         UNSET_FLAG(ls_pref->flags, LS_PREF_SR);
    2728           0 :         memset(&ls_pref->sr, 0, sizeof(struct ls_sid));
    2729           0 :         subnet->status = UPDATE;
    2730             : 
    2731             :         /* Subnet has been updated: export it */
    2732           0 :         ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
    2733           0 :         subnet->status = SYNC;
    2734             : 
    2735           0 :         return 0;
    2736             : }
    2737             : 
    2738             : /**
    2739             :  * Parse Opaque Extended Link LSA (Type 8) TLVs and update the corresponding
    2740             :  * Link State Edge with these information (Segment Routing Adjacency).
    2741             :  *
    2742             :  * @param ted   Link State Traffic Engineering Database
    2743             :  * @param lsa   OSPF Link State Advertisement
    2744             :  *
    2745             :  * @return      0 if success, -1 otherwise
    2746             :  */
    2747           0 : static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
    2748             : {
    2749           0 :         struct ls_node_id lnid;
    2750           0 :         struct tlv_header *tlvh;
    2751           0 :         struct ext_tlv_link *ext;
    2752           0 :         struct ls_edge *edge;
    2753           0 :         struct ls_attributes *atr;
    2754           0 :         uint16_t len = 0, sum = 0, i;
    2755           0 :         uint32_t label;
    2756             : 
    2757             :         /* Get corresponding Edge from Link State Data Base */
    2758           0 :         lnid.origin = OSPFv2;
    2759           0 :         lnid.id.ip.addr = lsa->data->adv_router;
    2760           0 :         lnid.id.ip.area_id = lsa->area->area_id;
    2761           0 :         ext = (struct ext_tlv_link *)TLV_HDR_TOP(lsa->data);
    2762           0 :         edge = get_edge(ted, lnid, ext->link_data);
    2763           0 :         atr = edge->attributes;
    2764             : 
    2765           0 :         ote_debug("  |- Process Extended Link LSA %pI4 for edge %pI4",
    2766             :                   &lsa->data->id, &edge->attributes->standard.local);
    2767             : 
    2768             :         /* Initialize TLV browsing */
    2769           0 :         len = TLV_BODY_SIZE(&ext->header) - EXT_TLV_LINK_SIZE;
    2770           0 :         tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
    2771             :                                      + EXT_TLV_LINK_SIZE);
    2772           0 :         for (; sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
    2773           0 :                 struct ext_subtlv_adj_sid *adj;
    2774           0 :                 struct ext_subtlv_lan_adj_sid *ladj;
    2775           0 :                 struct ext_subtlv_rmt_itf_addr *rmt;
    2776             : 
    2777           0 :                 switch (ntohs(tlvh->type)) {
    2778           0 :                 case EXT_SUBTLV_ADJ_SID:
    2779           0 :                         adj = (struct ext_subtlv_adj_sid *)tlvh;
    2780           0 :                         label = CHECK_FLAG(adj->flags,
    2781             :                                            EXT_SUBTLV_LINK_ADJ_SID_VFLG)
    2782           0 :                                         ? GET_LABEL(ntohl(adj->value))
    2783           0 :                                         : ntohl(adj->value);
    2784           0 :                         i = CHECK_FLAG(adj->flags,
    2785             :                                        EXT_SUBTLV_LINK_ADJ_SID_BFLG) ? 1 : 0;
    2786           0 :                         if (((i && CHECK_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID))
    2787           0 :                              || (!i && CHECK_FLAG(atr->flags, LS_ATTR_ADJ_SID)))
    2788           0 :                             && atr->adj_sid[i].flags == adj->flags
    2789           0 :                             && atr->adj_sid[i].sid == label
    2790           0 :                             && atr->adj_sid[i].weight == adj->weight)
    2791             :                                 break;
    2792             : 
    2793           0 :                         atr->adj_sid[i].flags = adj->flags;
    2794           0 :                         atr->adj_sid[i].sid = label;
    2795           0 :                         atr->adj_sid[i].weight = adj->weight;
    2796           0 :                         if (i == 0)
    2797           0 :                                 SET_FLAG(atr->flags, LS_ATTR_ADJ_SID);
    2798             :                         else
    2799           0 :                                 SET_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID);
    2800           0 :                         if (edge->status != NEW)
    2801           0 :                                 edge->status = UPDATE;
    2802             : 
    2803             :                         break;
    2804           0 :                 case EXT_SUBTLV_LAN_ADJ_SID:
    2805           0 :                         ladj = (struct ext_subtlv_lan_adj_sid *)tlvh;
    2806           0 :                         label = CHECK_FLAG(ladj->flags,
    2807             :                                            EXT_SUBTLV_LINK_ADJ_SID_VFLG)
    2808           0 :                                         ? GET_LABEL(ntohl(ladj->value))
    2809           0 :                                         : ntohl(ladj->value);
    2810           0 :                         i = CHECK_FLAG(ladj->flags,
    2811             :                                        EXT_SUBTLV_LINK_ADJ_SID_BFLG) ? 1 : 0;
    2812           0 :                         if (((i && CHECK_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID))
    2813           0 :                              || (!i && CHECK_FLAG(atr->flags, LS_ATTR_ADJ_SID)))
    2814           0 :                             && atr->adj_sid[i].flags == ladj->flags
    2815           0 :                             && atr->adj_sid[i].sid == label
    2816           0 :                             && atr->adj_sid[i].weight == ladj->weight
    2817           0 :                             && IPV4_ADDR_SAME(&atr->adj_sid[1].neighbor.addr,
    2818             :                                               &ladj->neighbor_id))
    2819             :                                 break;
    2820             : 
    2821           0 :                         atr->adj_sid[i].flags = ladj->flags;
    2822           0 :                         atr->adj_sid[i].sid = label;
    2823           0 :                         atr->adj_sid[i].weight = ladj->weight;
    2824           0 :                         atr->adj_sid[i].neighbor.addr = ladj->neighbor_id;
    2825           0 :                         if (i == 0)
    2826           0 :                                 SET_FLAG(atr->flags, LS_ATTR_ADJ_SID);
    2827             :                         else
    2828           0 :                                 SET_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID);
    2829           0 :                         if (edge->status != NEW)
    2830           0 :                                 edge->status = UPDATE;
    2831             : 
    2832             :                         break;
    2833           0 :                 case EXT_SUBTLV_RMT_ITF_ADDR:
    2834           0 :                         rmt = (struct ext_subtlv_rmt_itf_addr *)tlvh;
    2835           0 :                         if (CHECK_FLAG(atr->flags, LS_ATTR_NEIGH_ADDR)
    2836           0 :                             && IPV4_ADDR_SAME(&atr->standard.remote,
    2837             :                                               &rmt->value))
    2838             :                                 break;
    2839             : 
    2840           0 :                         atr->standard.remote = rmt->value;
    2841           0 :                         SET_FLAG(atr->flags, LS_ATTR_NEIGH_ADDR);
    2842           0 :                         if (edge->status != NEW)
    2843           0 :                                 edge->status = UPDATE;
    2844             : 
    2845             :                         break;
    2846             :                 default:
    2847             :                         break;
    2848             :                 }
    2849           0 :                 sum += TLV_SIZE(tlvh);
    2850             :         }
    2851             : 
    2852             :         /* Export Link State Edge if needed */
    2853           0 :         if (edge->status == NEW || edge->status == UPDATE) {
    2854           0 :                 ote_debug("  |- %s Adj-SID %d & %d to edge %pI4",
    2855             :                           edge->status == NEW ? "Add" : "Update",
    2856             :                           edge->attributes->adj_sid[0].sid,
    2857             :                           edge->attributes->adj_sid[1].sid,
    2858             :                           &edge->attributes->standard.local);
    2859             : 
    2860           0 :                 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
    2861           0 :                 edge->status = SYNC;
    2862             :         }
    2863             : 
    2864           0 :         return 0;
    2865             : }
    2866             : 
    2867             : /**
    2868             :  * Delete Link State Edge information (Segment Routing Adjacency) that
    2869             :  * correspond to the Opaque Extended Link LSA (Type 8) TLVs. Note that the Edge
    2870             :  * is not removed.
    2871             :  *
    2872             :  * @param ted   Link State Traffic Engineering Database
    2873             :  * @param lsa   OSPF Link State Advertisement
    2874             :  *
    2875             :  * @return      0 if success, -1 otherwise
    2876             :  */
    2877           0 : static int ospf_te_delete_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
    2878             : {
    2879           0 :         struct ls_edge *edge;
    2880           0 :         struct ls_attributes *atr;
    2881           0 :         struct ext_tlv_link *ext;
    2882           0 :         uint64_t key;
    2883             : 
    2884             :         /* Search for corresponding Edge from Link State Data Base */
    2885           0 :         ext = (struct ext_tlv_link *)TLV_HDR_TOP(lsa->data);
    2886           0 :         key = ((uint64_t)ntohl(ext->link_data.s_addr)) & 0xffffffff;
    2887           0 :         edge = ls_find_edge_by_key(ted, key);
    2888             : 
    2889             :         /* Check if there is a corresponding Edge */
    2890           0 :         if (!edge)
    2891             :                 return -1;
    2892             : 
    2893           0 :         ote_debug("  |- Delete Adj-SID %d to edge %pI4",
    2894             :                   edge->attributes->adj_sid[0].sid,
    2895             :                   &edge->attributes->standard.local);
    2896             : 
    2897             :         /* Remove Segment Routing information */
    2898           0 :         atr = edge->attributes;
    2899           0 :         UNSET_FLAG(atr->flags, LS_ATTR_ADJ_SID);
    2900           0 :         UNSET_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID);
    2901           0 :         memset(atr->adj_sid, 0, 2 * sizeof(struct ls_sid));
    2902           0 :         edge->status = UPDATE;
    2903             : 
    2904             :         /* Edge has been updated: export it */
    2905           0 :         ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
    2906           0 :         edge->status = SYNC;
    2907             : 
    2908           0 :         return 0;
    2909             : }
    2910             : 
    2911             : /**
    2912             :  * Parse Opaque LSA Type and call corresponding parser.
    2913             :  *
    2914             :  * @param ted   Link State Traffic Engineering Database
    2915             :  * @param lsa   OSPF Link State Advertisement
    2916             :  *
    2917             :  * @return      0 if success, -1 otherwise
    2918             :  */
    2919           0 : static int ospf_te_parse_opaque_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
    2920             : {
    2921           0 :         uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
    2922           0 :         int rc = -1;
    2923             : 
    2924           0 :         ote_debug("MPLS-TE (%s): Parse Opaque LSA[%pI4] from Router[%pI4]",
    2925             :                   __func__, &lsa->data->id, &lsa->data->adv_router);
    2926             : 
    2927           0 :         switch (key) {
    2928           0 :         case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
    2929             :         case OPAQUE_TYPE_INTER_AS_LSA:
    2930           0 :                 rc = ospf_te_parse_te(ted, lsa);
    2931           0 :                 break;
    2932           0 :         case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
    2933           0 :                 rc = ospf_te_parse_ri(ted, lsa);
    2934           0 :                 break;
    2935           0 :         case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
    2936           0 :                 rc = ospf_te_parse_ext_pref(ted, lsa);
    2937           0 :                 break;
    2938           0 :         case OPAQUE_TYPE_EXTENDED_LINK_LSA:
    2939           0 :                 rc = ospf_te_parse_ext_link(ted, lsa);
    2940           0 :                 break;
    2941             :         default:
    2942             :                 break;
    2943             :         }
    2944             : 
    2945           0 :         return rc;
    2946             : }
    2947             : 
    2948             : /**
    2949             :  * Parse Opaque LSA Type and call corresponding deletion function.
    2950             :  *
    2951             :  * @param ted   Link State Traffic Engineering Database
    2952             :  * @param lsa   OSPF Link State Advertisement
    2953             :  *
    2954             :  * @return      0 if success, -1 otherwise
    2955             :  */
    2956           0 : static int ospf_te_delete_opaque_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
    2957             : {
    2958           0 :         uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
    2959           0 :         int rc = -1;
    2960             : 
    2961           0 :         ote_debug("MPLS-TE (%s): Parse Opaque LSA[%pI4] from Router[%pI4]",
    2962             :                   __func__, &lsa->data->id, &lsa->data->adv_router);
    2963             : 
    2964           0 :         switch (key) {
    2965           0 :         case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
    2966             :         case OPAQUE_TYPE_INTER_AS_LSA:
    2967           0 :                 rc = ospf_te_delete_te(ted, lsa);
    2968           0 :                 break;
    2969           0 :         case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
    2970           0 :                 rc = ospf_te_delete_ri(ted, lsa);
    2971           0 :                 break;
    2972           0 :         case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
    2973           0 :                 rc = ospf_te_delete_ext_pref(ted, lsa);
    2974           0 :                 break;
    2975           0 :         case OPAQUE_TYPE_EXTENDED_LINK_LSA:
    2976           0 :                 rc = ospf_te_delete_ext_link(ted, lsa);
    2977           0 :                 break;
    2978             :         default:
    2979             :                 break;
    2980             :         }
    2981             : 
    2982           0 :         return rc;
    2983             : }
    2984             : 
    2985             : /**
    2986             :  * Update Traffic Engineering Database Elements that correspond to the received
    2987             :  * OSPF LSA. If LSA age is equal to MAX_AGE, call deletion function instead.
    2988             :  *
    2989             :  * @param lsa   OSPF Link State Advertisement
    2990             :  *
    2991             :  * @return      0 if success, -1 otherwise
    2992             :  */
    2993         159 : static int ospf_mpls_te_lsa_update(struct ospf_lsa *lsa)
    2994             : {
    2995             : 
    2996         159 :         uint8_t rc;
    2997             : 
    2998             :         /* Check that MPLS-TE is active */
    2999         159 :         if (!OspfMplsTE.enabled || !OspfMplsTE.ted)
    3000             :                 return 0;
    3001             : 
    3002             :         /* Sanity Check */
    3003           0 :         if (lsa == NULL) {
    3004           0 :                 flog_warn(EC_OSPF_LSA_NULL, "TE (%s): Abort! LSA is NULL",
    3005             :                           __func__);
    3006           0 :                 return -1;
    3007             :         }
    3008             : 
    3009             :         /* If LSA is MAX_AGE, remove corresponding Link State element */
    3010           0 :         if (IS_LSA_MAXAGE(lsa)) {
    3011           0 :                 switch (lsa->data->type) {
    3012           0 :                 case OSPF_ROUTER_LSA:
    3013           0 :                         rc = ospf_te_delete_router_lsa(OspfMplsTE.ted, lsa);
    3014           0 :                         break;
    3015           0 :                 case OSPF_OPAQUE_AREA_LSA:
    3016             :                 case OSPF_OPAQUE_AS_LSA:
    3017           0 :                         rc = ospf_te_delete_opaque_lsa(OspfMplsTE.ted, lsa);
    3018           0 :                         break;
    3019             :                 default:
    3020             :                         rc = 0;
    3021             :                         break;
    3022             :                 }
    3023             :         } else {
    3024             :                 /* Parse LSA to Update corresponding Link State element */
    3025           0 :                 switch (lsa->data->type) {
    3026           0 :                 case OSPF_ROUTER_LSA:
    3027           0 :                         rc = ospf_te_parse_router_lsa(OspfMplsTE.ted, lsa);
    3028           0 :                         break;
    3029           0 :                 case OSPF_OPAQUE_AREA_LSA:
    3030             :                 case OSPF_OPAQUE_AS_LSA:
    3031           0 :                         rc = ospf_te_parse_opaque_lsa(OspfMplsTE.ted, lsa);
    3032           0 :                         break;
    3033             :                 default:
    3034             :                         rc = 0;
    3035             :                         break;
    3036             :                 }
    3037             :         }
    3038             : 
    3039           0 :         return rc;
    3040             : }
    3041             : 
    3042             : /**
    3043             :  * Delete Traffic Engineering Database element from OSPF LSA. This function
    3044             :  * process only self LSA (i.e. advertised by the router) which reach MAX_AGE
    3045             :  * as LSA deleted by neighbor routers are Flushed (i.e. advertised with
    3046             :  * age == MAX_AGE) and processed by ospf_mpls_te_lsa_update() function.
    3047             :  *
    3048             :  * @param lsa   OSPF Link State Advertisement
    3049             :  *
    3050             :  * @return      0 if success, -1 otherwise
    3051             :  */
    3052         112 : static int ospf_mpls_te_lsa_delete(struct ospf_lsa *lsa)
    3053             : {
    3054             : 
    3055         112 :         uint8_t rc;
    3056             : 
    3057             :         /* Check that MPLS-TE is active */
    3058         112 :         if (!OspfMplsTE.enabled || !OspfMplsTE.ted)
    3059             :                 return 0;
    3060             : 
    3061             :         /* Sanity Check */
    3062           0 :         if (lsa == NULL) {
    3063           0 :                 flog_warn(EC_OSPF_LSA_NULL, "TE (%s): Abort! LSA is NULL",
    3064             :                           __func__);
    3065           0 :                 return -1;
    3066             :         }
    3067             : 
    3068             :         /*
    3069             :          * Process only self LSAs that reach MAX_AGE. Indeed, when the router
    3070             :          * need to update or refresh an LSA, it first removes the old LSA from
    3071             :          * the LSDB and then insert the new one. Thus, to avoid removing
    3072             :          * corresponding Link State element and loosing some parameters
    3073             :          * instead of just updating it, only self LSAs that reach MAX_AGE are
    3074             :          * processed here. Other LSAs are processed by ospf_mpls_te_lsa_update()
    3075             :          * and eventually removed when LSA age is MAX_AGE i.e. LSA is flushed
    3076             :          * by the originator.
    3077             :          */
    3078           0 :         if (!IS_LSA_SELF(lsa) || !IS_LSA_MAXAGE(lsa))
    3079           0 :                 return 0;
    3080             : 
    3081             :         /* Parse Link State information */
    3082           0 :         switch (lsa->data->type) {
    3083           0 :         case OSPF_ROUTER_LSA:
    3084           0 :                 rc = ospf_te_delete_router_lsa(OspfMplsTE.ted, lsa);
    3085           0 :                 break;
    3086           0 :         case OSPF_OPAQUE_AREA_LSA:
    3087             :         case OSPF_OPAQUE_AS_LSA:
    3088           0 :                 rc = ospf_te_delete_opaque_lsa(OspfMplsTE.ted, lsa);
    3089           0 :                 break;
    3090             :         default:
    3091             :                 rc = 0;
    3092             :                 break;
    3093             :         }
    3094             : 
    3095           0 :         return rc;
    3096             : }
    3097             : 
    3098             : /**
    3099             :  * Send the whole Link State Traffic Engineering Database to the consumer that
    3100             :  * request it through a ZAPI Link State Synchronous Opaque Message.
    3101             :  *
    3102             :  * @param info  ZAPI Opaque message
    3103             :  *
    3104             :  * @return      0 if success, -1 otherwise
    3105             :  */
    3106           0 : int ospf_te_sync_ted(struct zapi_opaque_reg_info dst)
    3107             : {
    3108           0 :         int rc = -1;
    3109             : 
    3110             :         /* Check that MPLS-TE and TE distribution are enabled */
    3111           0 :         if (!OspfMplsTE.enabled || !OspfMplsTE.export)
    3112             :                 return rc;
    3113             : 
    3114           0 :         rc = ls_sync_ted(OspfMplsTE.ted, zclient, &dst);
    3115             : 
    3116           0 :         return rc;
    3117             : }
    3118             : 
    3119             : /**
    3120             :  * Initialize Traffic Engineering Database from the various OSPF Link State
    3121             :  * Database (LSDB).
    3122             :  *
    3123             :  * @param ted   Link State Traffice Engineering Database
    3124             :  * @param ospf  OSPF main structure
    3125             :  */
    3126           0 : static void ospf_te_init_ted(struct ls_ted *ted, struct ospf *ospf)
    3127             : {
    3128           0 :         struct listnode *node, *nnode;
    3129           0 :         struct route_node *rn;
    3130           0 :         struct ospf_area *area;
    3131           0 :         struct ospf_lsa *lsa;
    3132             : 
    3133             :         /* Iterate over all areas. */
    3134           0 :         for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
    3135           0 :                 if (!area->lsdb)
    3136           0 :                         continue;
    3137             : 
    3138             :                 /* Parse all Router LSAs from the area LSDB */
    3139           0 :                 LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
    3140           0 :                         ospf_te_parse_router_lsa(ted, lsa);
    3141             : 
    3142             :                 /* Parse all Opaque LSAs from the area LSDB */
    3143           0 :                 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
    3144           0 :                         ospf_te_parse_opaque_lsa(ted, lsa);
    3145             :         }
    3146             : 
    3147             :         /* Parse AS-external opaque LSAs from OSPF LSDB */
    3148           0 :         if (ospf->lsdb) {
    3149           0 :                 LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
    3150           0 :                         ospf_te_parse_opaque_lsa(ted, lsa);
    3151             :         }
    3152             : 
    3153           0 : }
    3154             : 
    3155             : /*------------------------------------------------------------------------*
    3156             :  * Following are vty session control functions.
    3157             :  *------------------------------------------------------------------------*/
    3158             : #define check_tlv_size(size, msg)                                              \
    3159             :         do {                                                                   \
    3160             :                 if (ntohs(tlvh->length) > size) {                              \
    3161             :                         if (vty != NULL)                                       \
    3162             :                                 vty_out(vty, "  Wrong %s TLV size: %d(%d)\n",  \
    3163             :                                         msg, ntohs(tlvh->length), size);       \
    3164             :                         else                                                   \
    3165             :                                 zlog_debug("    Wrong %s TLV size: %d(%d)",    \
    3166             :                                            msg, ntohs(tlvh->length), size);    \
    3167             :                         return size + TLV_HDR_SIZE;                            \
    3168             :                 }                                                              \
    3169             :         } while (0)
    3170             : 
    3171           0 : static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh)
    3172             : {
    3173           0 :         struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh;
    3174             : 
    3175           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Router Address");
    3176             : 
    3177           0 :         if (vty != NULL)
    3178           0 :                 vty_out(vty, "  Router-Address: %pI4\n", &top->value);
    3179             :         else
    3180           0 :                 zlog_debug("    Router-Address: %pI4", &top->value);
    3181             : 
    3182           0 :         return TLV_SIZE(tlvh);
    3183             : }
    3184             : 
    3185           0 : static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh,
    3186             :                                      size_t buf_size)
    3187             : {
    3188           0 :         struct te_tlv_link *top = (struct te_tlv_link *)tlvh;
    3189             : 
    3190           0 :         if (TLV_SIZE(tlvh) > buf_size) {
    3191           0 :                 if (vty != NULL)
    3192           0 :                         vty_out(vty,
    3193             :                                 "    TLV size %d exceeds buffer size. Abort!",
    3194           0 :                                 TLV_SIZE(tlvh));
    3195             :                 else
    3196           0 :                         zlog_debug(
    3197             :                                 "    TLV size %d exceeds buffer size. Abort!",
    3198             :                                 TLV_SIZE(tlvh));
    3199           0 :                 return buf_size;
    3200             :         }
    3201             : 
    3202           0 :         if (vty != NULL)
    3203           0 :                 vty_out(vty, "  Link: %u octets of data\n",
    3204           0 :                         ntohs(top->header.length));
    3205             :         else
    3206           0 :                 zlog_debug("    Link: %u octets of data",
    3207             :                            ntohs(top->header.length));
    3208             : 
    3209             :         return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
    3210             : }
    3211             : 
    3212           0 : static uint16_t show_vty_link_subtlv_link_type(struct vty *vty,
    3213             :                                                struct tlv_header *tlvh)
    3214             : {
    3215           0 :         struct te_link_subtlv_link_type *top;
    3216           0 :         const char *cp = "Unknown";
    3217             : 
    3218           0 :         check_tlv_size(TE_LINK_SUBTLV_TYPE_SIZE, "Link Type");
    3219             : 
    3220           0 :         top = (struct te_link_subtlv_link_type *)tlvh;
    3221           0 :         switch (top->link_type.value) {
    3222           0 :         case LINK_TYPE_SUBTLV_VALUE_PTP:
    3223           0 :                 cp = "Point-to-point";
    3224           0 :                 break;
    3225           0 :         case LINK_TYPE_SUBTLV_VALUE_MA:
    3226           0 :                 cp = "Multiaccess";
    3227           0 :                 break;
    3228             :         default:
    3229             :                 break;
    3230             :         }
    3231             : 
    3232           0 :         if (vty != NULL)
    3233           0 :                 vty_out(vty, "  Link-Type: %s (%u)\n", cp,
    3234             :                         top->link_type.value);
    3235             :         else
    3236           0 :                 zlog_debug("    Link-Type: %s (%u)", cp, top->link_type.value);
    3237             : 
    3238           0 :         return TLV_SIZE(tlvh);
    3239             : }
    3240             : 
    3241           0 : static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
    3242             :                                              struct tlv_header *tlvh)
    3243             : {
    3244           0 :         struct te_link_subtlv_link_id *top;
    3245             : 
    3246           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link ID");
    3247             : 
    3248           0 :         top = (struct te_link_subtlv_link_id *)tlvh;
    3249           0 :         if (vty != NULL)
    3250           0 :                 vty_out(vty, "  Link-ID: %pI4\n", &top->value);
    3251             :         else
    3252           0 :                 zlog_debug("    Link-ID: %pI4", &top->value);
    3253             : 
    3254           0 :         return TLV_SIZE(tlvh);
    3255             : }
    3256             : 
    3257           0 : static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
    3258             :                                                   struct tlv_header *tlvh,
    3259             :                                                   size_t buf_size)
    3260             : {
    3261           0 :         struct te_link_subtlv_lclif_ipaddr *top;
    3262           0 :         int i, n;
    3263             : 
    3264           0 :         if (TLV_SIZE(tlvh) > buf_size) {
    3265           0 :                 if (vty != NULL)
    3266           0 :                         vty_out(vty,
    3267             :                                 "    TLV size %d exceeds buffer size. Abort!",
    3268           0 :                                 TLV_SIZE(tlvh));
    3269             :                 else
    3270           0 :                         zlog_debug(
    3271             :                                 "    TLV size %d exceeds buffer size. Abort!",
    3272             :                                 TLV_SIZE(tlvh));
    3273           0 :                 return buf_size;
    3274             :         }
    3275             : 
    3276           0 :         top = (struct te_link_subtlv_lclif_ipaddr *)tlvh;
    3277           0 :         n = ntohs(tlvh->length) / sizeof(top->value[0]);
    3278             : 
    3279           0 :         if (vty != NULL)
    3280           0 :                 vty_out(vty, "  Local Interface IP Address(es): %d\n", n);
    3281             :         else
    3282           0 :                 zlog_debug("    Local Interface IP Address(es): %d", n);
    3283             : 
    3284           0 :         for (i = 0; i < n; i++) {
    3285           0 :                 if (vty != NULL)
    3286           0 :                         vty_out(vty, "    #%d: %pI4\n", i, &top->value[i]);
    3287             :                 else
    3288           0 :                         zlog_debug("      #%d: %pI4", i, &top->value[i]);
    3289             :         }
    3290           0 :         return TLV_SIZE(tlvh);
    3291             : }
    3292             : 
    3293           0 : static uint16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
    3294             :                                                   struct tlv_header *tlvh,
    3295             :                                                   size_t buf_size)
    3296             : {
    3297           0 :         struct te_link_subtlv_rmtif_ipaddr *top;
    3298           0 :         int i, n;
    3299             : 
    3300           0 :         if (TLV_SIZE(tlvh) > buf_size) {
    3301           0 :                 if (vty != NULL)
    3302           0 :                         vty_out(vty,
    3303             :                                 "    TLV size %d exceeds buffer size. Abort!",
    3304           0 :                                 TLV_SIZE(tlvh));
    3305             :                 else
    3306           0 :                         zlog_debug(
    3307             :                                 "    TLV size %d exceeds buffer size. Abort!",
    3308             :                                 TLV_SIZE(tlvh));
    3309           0 :                 return buf_size;
    3310             :         }
    3311             : 
    3312           0 :         top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh;
    3313           0 :         n = ntohs(tlvh->length) / sizeof(top->value[0]);
    3314           0 :         if (vty != NULL)
    3315           0 :                 vty_out(vty, "  Remote Interface IP Address(es): %d\n", n);
    3316             :         else
    3317           0 :                 zlog_debug("    Remote Interface IP Address(es): %d", n);
    3318             : 
    3319           0 :         for (i = 0; i < n; i++) {
    3320           0 :                 if (vty != NULL)
    3321           0 :                         vty_out(vty, "    #%d: %pI4\n", i, &top->value[i]);
    3322             :                 else
    3323           0 :                         zlog_debug("      #%d: %pI4", i, &top->value[i]);
    3324             :         }
    3325           0 :         return TLV_SIZE(tlvh);
    3326             : }
    3327             : 
    3328           0 : static uint16_t show_vty_link_subtlv_te_metric(struct vty *vty,
    3329             :                                                struct tlv_header *tlvh)
    3330             : {
    3331           0 :         struct te_link_subtlv_te_metric *top;
    3332             : 
    3333           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "TE Metric");
    3334             : 
    3335           0 :         top = (struct te_link_subtlv_te_metric *)tlvh;
    3336           0 :         if (vty != NULL)
    3337           0 :                 vty_out(vty, "  Traffic Engineering Metric: %u\n",
    3338           0 :                         (uint32_t)ntohl(top->value));
    3339             :         else
    3340           0 :                 zlog_debug("    Traffic Engineering Metric: %u",
    3341             :                            (uint32_t)ntohl(top->value));
    3342             : 
    3343           0 :         return TLV_SIZE(tlvh);
    3344             : }
    3345             : 
    3346           0 : static uint16_t show_vty_link_subtlv_max_bw(struct vty *vty,
    3347             :                                             struct tlv_header *tlvh)
    3348             : {
    3349           0 :         struct te_link_subtlv_max_bw *top;
    3350           0 :         float fval;
    3351             : 
    3352           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Bandwidth");
    3353             : 
    3354           0 :         top = (struct te_link_subtlv_max_bw *)tlvh;
    3355           0 :         fval = ntohf(top->value);
    3356             : 
    3357           0 :         if (vty != NULL)
    3358           0 :                 vty_out(vty, "  Maximum Bandwidth: %g (Bytes/sec)\n", fval);
    3359             :         else
    3360           0 :                 zlog_debug("    Maximum Bandwidth: %g (Bytes/sec)", fval);
    3361             : 
    3362           0 :         return TLV_SIZE(tlvh);
    3363             : }
    3364             : 
    3365           0 : static uint16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
    3366             :                                                 struct tlv_header *tlvh)
    3367             : {
    3368           0 :         struct te_link_subtlv_max_rsv_bw *top;
    3369           0 :         float fval;
    3370             : 
    3371           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Reservable Bandwidth");
    3372             : 
    3373           0 :         top = (struct te_link_subtlv_max_rsv_bw *)tlvh;
    3374           0 :         fval = ntohf(top->value);
    3375             : 
    3376           0 :         if (vty != NULL)
    3377           0 :                 vty_out(vty, "  Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
    3378             :                         fval);
    3379             :         else
    3380           0 :                 zlog_debug("    Maximum Reservable Bandwidth: %g (Bytes/sec)",
    3381             :                            fval);
    3382             : 
    3383           0 :         return TLV_SIZE(tlvh);
    3384             : }
    3385             : 
    3386           0 : static uint16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
    3387             :                                               struct tlv_header *tlvh)
    3388             : {
    3389           0 :         struct te_link_subtlv_unrsv_bw *top;
    3390           0 :         float fval1, fval2;
    3391           0 :         int i;
    3392             : 
    3393           0 :         check_tlv_size(TE_LINK_SUBTLV_UNRSV_SIZE, "Unreserved Bandwidth");
    3394             : 
    3395           0 :         top = (struct te_link_subtlv_unrsv_bw *)tlvh;
    3396           0 :         if (vty != NULL)
    3397           0 :                 vty_out(vty,
    3398             :                         "  Unreserved Bandwidth per Class Type in Byte/s:\n");
    3399             :         else
    3400           0 :                 zlog_debug(
    3401             :                         "    Unreserved Bandwidth per Class Type in Byte/s:");
    3402           0 :         for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
    3403           0 :                 fval1 = ntohf(top->value[i]);
    3404           0 :                 fval2 = ntohf(top->value[i + 1]);
    3405             : 
    3406           0 :                 if (vty != NULL)
    3407           0 :                         vty_out(vty,
    3408             :                                 "    [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
    3409             :                                 i, fval1, i + 1, fval2);
    3410             :                 else
    3411           0 :                         zlog_debug(
    3412             :                                 "      [%d]: %g (Bytes/sec),  [%d]: %g (Bytes/sec)",
    3413             :                                 i, fval1, i + 1, fval2);
    3414             :         }
    3415             : 
    3416           0 :         return TLV_SIZE(tlvh);
    3417             : }
    3418             : 
    3419           0 : static uint16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
    3420             :                                                 struct tlv_header *tlvh)
    3421             : {
    3422           0 :         struct te_link_subtlv_rsc_clsclr *top;
    3423             : 
    3424           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Resource class/color");
    3425             : 
    3426           0 :         top = (struct te_link_subtlv_rsc_clsclr *)tlvh;
    3427           0 :         if (vty != NULL)
    3428           0 :                 vty_out(vty, "  Resource class/color: 0x%x\n",
    3429           0 :                         (uint32_t)ntohl(top->value));
    3430             :         else
    3431           0 :                 zlog_debug("    Resource Class/Color: 0x%x",
    3432             :                            (uint32_t)ntohl(top->value));
    3433             : 
    3434           0 :         return TLV_SIZE(tlvh);
    3435             : }
    3436             : 
    3437           0 : static uint16_t show_vty_link_subtlv_lrrid(struct vty *vty,
    3438             :                                            struct tlv_header *tlvh)
    3439             : {
    3440           0 :         struct te_link_subtlv_lrrid *top;
    3441             : 
    3442           0 :         check_tlv_size(TE_LINK_SUBTLV_LRRID_SIZE, "Local/Remote Router ID");
    3443             : 
    3444           0 :         top = (struct te_link_subtlv_lrrid *)tlvh;
    3445             : 
    3446           0 :         if (vty != NULL) {
    3447           0 :                 vty_out(vty, "  Local  TE Router ID: %pI4\n",
    3448             :                         &top->local);
    3449           0 :                 vty_out(vty, "  Remote TE Router ID: %pI4\n",
    3450             :                         &top->remote);
    3451             :         } else {
    3452           0 :                 zlog_debug("    Local  TE Router ID: %pI4",
    3453             :                            &top->local);
    3454           0 :                 zlog_debug("    Remote TE Router ID: %pI4",
    3455             :                            &top->remote);
    3456             :         }
    3457             : 
    3458           0 :         return TLV_SIZE(tlvh);
    3459             : }
    3460             : 
    3461           0 : static uint16_t show_vty_link_subtlv_llri(struct vty *vty,
    3462             :                                           struct tlv_header *tlvh)
    3463             : {
    3464           0 :         struct te_link_subtlv_llri *top;
    3465             : 
    3466           0 :         check_tlv_size(TE_LINK_SUBTLV_LLRI_SIZE, "Link Local/Remote ID");
    3467             : 
    3468           0 :         top = (struct te_link_subtlv_llri *)tlvh;
    3469             : 
    3470           0 :         if (vty != NULL) {
    3471           0 :                 vty_out(vty, "  Link Local  ID: %d\n",
    3472           0 :                         (uint32_t)ntohl(top->local));
    3473           0 :                 vty_out(vty, "  Link Remote ID: %d\n",
    3474           0 :                         (uint32_t)ntohl(top->remote));
    3475             :         } else {
    3476           0 :                 zlog_debug("    Link Local  ID: %d",
    3477             :                            (uint32_t)ntohl(top->local));
    3478           0 :                 zlog_debug("    Link Remote ID: %d",
    3479             :                            (uint32_t)ntohl(top->remote));
    3480             :         }
    3481             : 
    3482           0 :         return TLV_SIZE(tlvh);
    3483             : }
    3484             : 
    3485           0 : static uint16_t show_vty_link_subtlv_rip(struct vty *vty,
    3486             :                                          struct tlv_header *tlvh)
    3487             : {
    3488           0 :         struct te_link_subtlv_rip *top;
    3489             : 
    3490           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote ASBR Address");
    3491             : 
    3492           0 :         top = (struct te_link_subtlv_rip *)tlvh;
    3493             : 
    3494           0 :         if (vty != NULL)
    3495           0 :                 vty_out(vty, "  Inter-AS TE Remote ASBR IP address: %pI4\n",
    3496             :                         &top->value);
    3497             :         else
    3498           0 :                 zlog_debug("    Inter-AS TE Remote ASBR IP address: %pI4",
    3499             :                            &top->value);
    3500             : 
    3501           0 :         return TLV_SIZE(tlvh);
    3502             : }
    3503             : 
    3504           0 : static uint16_t show_vty_link_subtlv_ras(struct vty *vty,
    3505             :                                          struct tlv_header *tlvh)
    3506             : {
    3507           0 :         struct te_link_subtlv_ras *top;
    3508             : 
    3509           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote AS number");
    3510             : 
    3511           0 :         top = (struct te_link_subtlv_ras *)tlvh;
    3512             : 
    3513           0 :         if (vty != NULL)
    3514           0 :                 vty_out(vty, "  Inter-AS TE Remote AS number: %u\n",
    3515             :                         ntohl(top->value));
    3516             :         else
    3517           0 :                 zlog_debug("    Inter-AS TE Remote AS number: %u",
    3518             :                            ntohl(top->value));
    3519             : 
    3520           0 :         return TLV_SIZE(tlvh);
    3521             : }
    3522             : 
    3523           0 : static uint16_t show_vty_link_subtlv_av_delay(struct vty *vty,
    3524             :                                               struct tlv_header *tlvh)
    3525             : {
    3526           0 :         struct te_link_subtlv_av_delay *top;
    3527           0 :         uint32_t delay;
    3528           0 :         uint32_t anomalous;
    3529             : 
    3530           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Average Link Delay");
    3531             : 
    3532           0 :         top = (struct te_link_subtlv_av_delay *)tlvh;
    3533           0 :         delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
    3534           0 :         anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
    3535             : 
    3536           0 :         if (vty != NULL)
    3537           0 :                 vty_out(vty, "  %s Average Link Delay: %d (micro-sec)\n",
    3538             :                         anomalous ? "Anomalous" : "Normal", delay);
    3539             :         else
    3540           0 :                 zlog_debug("    %s Average Link Delay: %d (micro-sec)",
    3541             :                            anomalous ? "Anomalous" : "Normal", delay);
    3542             : 
    3543           0 :         return TLV_SIZE(tlvh);
    3544             : }
    3545             : 
    3546           0 : static uint16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
    3547             :                                               struct tlv_header *tlvh)
    3548             : {
    3549           0 :         struct te_link_subtlv_mm_delay *top;
    3550           0 :         uint32_t low, high;
    3551           0 :         uint32_t anomalous;
    3552             : 
    3553           0 :         check_tlv_size(TE_LINK_SUBTLV_MM_DELAY_SIZE, "Min/Max Link Delay");
    3554             : 
    3555           0 :         top = (struct te_link_subtlv_mm_delay *)tlvh;
    3556           0 :         low = (uint32_t)ntohl(top->low) & TE_EXT_MASK;
    3557           0 :         anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL;
    3558           0 :         high = (uint32_t)ntohl(top->high);
    3559             : 
    3560           0 :         if (vty != NULL)
    3561           0 :                 vty_out(vty, "  %s Min/Max Link Delay: %d/%d (micro-sec)\n",
    3562             :                         anomalous ? "Anomalous" : "Normal", low, high);
    3563             :         else
    3564           0 :                 zlog_debug("    %s Min/Max Link Delay: %d/%d (micro-sec)",
    3565             :                            anomalous ? "Anomalous" : "Normal", low, high);
    3566             : 
    3567           0 :         return TLV_SIZE(tlvh);
    3568             : }
    3569             : 
    3570           0 : static uint16_t show_vty_link_subtlv_delay_var(struct vty *vty,
    3571             :                                                struct tlv_header *tlvh)
    3572             : {
    3573           0 :         struct te_link_subtlv_delay_var *top;
    3574           0 :         uint32_t jitter;
    3575             : 
    3576           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Delay Variation");
    3577             : 
    3578           0 :         top = (struct te_link_subtlv_delay_var *)tlvh;
    3579           0 :         jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
    3580             : 
    3581           0 :         if (vty != NULL)
    3582           0 :                 vty_out(vty, "  Delay Variation: %d (micro-sec)\n", jitter);
    3583             :         else
    3584           0 :                 zlog_debug("    Delay Variation: %d (micro-sec)", jitter);
    3585             : 
    3586           0 :         return TLV_SIZE(tlvh);
    3587             : }
    3588             : 
    3589           0 : static uint16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
    3590             :                                               struct tlv_header *tlvh)
    3591             : {
    3592           0 :         struct te_link_subtlv_pkt_loss *top;
    3593           0 :         uint32_t loss;
    3594           0 :         uint32_t anomalous;
    3595           0 :         float fval;
    3596             : 
    3597           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Loss");
    3598             : 
    3599           0 :         top = (struct te_link_subtlv_pkt_loss *)tlvh;
    3600           0 :         loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
    3601           0 :         fval = (float)(loss * LOSS_PRECISION);
    3602           0 :         anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
    3603             : 
    3604           0 :         if (vty != NULL)
    3605           0 :                 vty_out(vty, "  %s Link Loss: %g (%%)\n",
    3606             :                         anomalous ? "Anomalous" : "Normal", fval);
    3607             :         else
    3608           0 :                 zlog_debug("    %s Link Loss: %g (%%)",
    3609             :                            anomalous ? "Anomalous" : "Normal", fval);
    3610             : 
    3611           0 :         return TLV_SIZE(tlvh);
    3612             : }
    3613             : 
    3614           0 : static uint16_t show_vty_link_subtlv_res_bw(struct vty *vty,
    3615             :                                             struct tlv_header *tlvh)
    3616             : {
    3617           0 :         struct te_link_subtlv_res_bw *top;
    3618           0 :         float fval;
    3619             : 
    3620           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Residual Bandwidth");
    3621             : 
    3622           0 :         top = (struct te_link_subtlv_res_bw *)tlvh;
    3623           0 :         fval = ntohf(top->value);
    3624             : 
    3625           0 :         if (vty != NULL)
    3626           0 :                 vty_out(vty,
    3627             :                         "  Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
    3628             :                         fval);
    3629             :         else
    3630           0 :                 zlog_debug(
    3631             :                         "    Unidirectional Residual Bandwidth: %g (Bytes/sec)",
    3632             :                         fval);
    3633             : 
    3634           0 :         return TLV_SIZE(tlvh);
    3635             : }
    3636             : 
    3637           0 : static uint16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
    3638             :                                             struct tlv_header *tlvh)
    3639             : {
    3640           0 :         struct te_link_subtlv_ava_bw *top;
    3641           0 :         float fval;
    3642             : 
    3643           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Available Bandwidth");
    3644             : 
    3645           0 :         top = (struct te_link_subtlv_ava_bw *)tlvh;
    3646           0 :         fval = ntohf(top->value);
    3647             : 
    3648           0 :         if (vty != NULL)
    3649           0 :                 vty_out(vty,
    3650             :                         "  Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
    3651             :                         fval);
    3652             :         else
    3653           0 :                 zlog_debug(
    3654             :                         "    Unidirectional Available Bandwidth: %g (Bytes/sec)",
    3655             :                         fval);
    3656             : 
    3657           0 :         return TLV_SIZE(tlvh);
    3658             : }
    3659             : 
    3660           0 : static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
    3661             :                                             struct tlv_header *tlvh)
    3662             : {
    3663           0 :         struct te_link_subtlv_use_bw *top;
    3664           0 :         float fval;
    3665             : 
    3666           0 :         check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Utilized Bandwidth");
    3667             : 
    3668           0 :         top = (struct te_link_subtlv_use_bw *)tlvh;
    3669           0 :         fval = ntohf(top->value);
    3670             : 
    3671           0 :         if (vty != NULL)
    3672           0 :                 vty_out(vty,
    3673             :                         "  Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
    3674             :                         fval);
    3675             :         else
    3676           0 :                 zlog_debug(
    3677             :                         "    Unidirectional Utilized Bandwidth: %g (Bytes/sec)",
    3678             :                         fval);
    3679             : 
    3680           0 :         return TLV_SIZE(tlvh);
    3681             : }
    3682             : 
    3683           0 : static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
    3684             :                                      size_t buf_size)
    3685             : {
    3686           0 :         if (TLV_SIZE(tlvh) > buf_size) {
    3687           0 :                 if (vty != NULL)
    3688           0 :                         vty_out(vty,
    3689             :                                 "    TLV size %d exceeds buffer size. Abort!",
    3690           0 :                                 TLV_SIZE(tlvh));
    3691             :                 else
    3692           0 :                         zlog_debug(
    3693             :                                 "    TLV size %d exceeds buffer size. Abort!",
    3694             :                                 TLV_SIZE(tlvh));
    3695           0 :                 return buf_size;
    3696             :         }
    3697             : 
    3698           0 :         if (vty != NULL)
    3699           0 :                 vty_out(vty, "  Unknown TLV: [type(0x%x), length(0x%x)]\n",
    3700           0 :                         ntohs(tlvh->type), ntohs(tlvh->length));
    3701             :         else
    3702           0 :                 zlog_debug("    Unknown TLV: [type(0x%x), length(0x%x)]",
    3703             :                            ntohs(tlvh->type), ntohs(tlvh->length));
    3704             : 
    3705           0 :         return TLV_SIZE(tlvh);
    3706             : }
    3707             : 
    3708           0 : static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
    3709             :                                               struct tlv_header *tlvh0,
    3710             :                                               uint16_t subtotal, uint16_t total)
    3711             : {
    3712           0 :         struct tlv_header *tlvh;
    3713           0 :         uint16_t sum = subtotal;
    3714             : 
    3715           0 :         for (tlvh = tlvh0; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
    3716           0 :                 switch (ntohs(tlvh->type)) {
    3717           0 :                 case TE_LINK_SUBTLV_LINK_TYPE:
    3718           0 :                         sum += show_vty_link_subtlv_link_type(vty, tlvh);
    3719           0 :                         break;
    3720           0 :                 case TE_LINK_SUBTLV_LINK_ID:
    3721           0 :                         sum += show_vty_link_subtlv_link_id(vty, tlvh);
    3722           0 :                         break;
    3723           0 :                 case TE_LINK_SUBTLV_LCLIF_IPADDR:
    3724           0 :                         sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh,
    3725           0 :                                                                  total - sum);
    3726           0 :                         break;
    3727           0 :                 case TE_LINK_SUBTLV_RMTIF_IPADDR:
    3728           0 :                         sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh,
    3729           0 :                                                                  total - sum);
    3730           0 :                         break;
    3731           0 :                 case TE_LINK_SUBTLV_TE_METRIC:
    3732           0 :                         sum += show_vty_link_subtlv_te_metric(vty, tlvh);
    3733           0 :                         break;
    3734           0 :                 case TE_LINK_SUBTLV_MAX_BW:
    3735           0 :                         sum += show_vty_link_subtlv_max_bw(vty, tlvh);
    3736           0 :                         break;
    3737           0 :                 case TE_LINK_SUBTLV_MAX_RSV_BW:
    3738           0 :                         sum += show_vty_link_subtlv_max_rsv_bw(vty, tlvh);
    3739           0 :                         break;
    3740           0 :                 case TE_LINK_SUBTLV_UNRSV_BW:
    3741           0 :                         sum += show_vty_link_subtlv_unrsv_bw(vty, tlvh);
    3742           0 :                         break;
    3743           0 :                 case TE_LINK_SUBTLV_RSC_CLSCLR:
    3744           0 :                         sum += show_vty_link_subtlv_rsc_clsclr(vty, tlvh);
    3745           0 :                         break;
    3746           0 :                 case TE_LINK_SUBTLV_LRRID:
    3747           0 :                         sum += show_vty_link_subtlv_lrrid(vty, tlvh);
    3748           0 :                         break;
    3749           0 :                 case TE_LINK_SUBTLV_LLRI:
    3750           0 :                         sum += show_vty_link_subtlv_llri(vty, tlvh);
    3751           0 :                         break;
    3752           0 :                 case TE_LINK_SUBTLV_RIP:
    3753           0 :                         sum += show_vty_link_subtlv_rip(vty, tlvh);
    3754           0 :                         break;
    3755           0 :                 case TE_LINK_SUBTLV_RAS:
    3756           0 :                         sum += show_vty_link_subtlv_ras(vty, tlvh);
    3757           0 :                         break;
    3758           0 :                 case TE_LINK_SUBTLV_AV_DELAY:
    3759           0 :                         sum += show_vty_link_subtlv_av_delay(vty, tlvh);
    3760           0 :                         break;
    3761           0 :                 case TE_LINK_SUBTLV_MM_DELAY:
    3762           0 :                         sum += show_vty_link_subtlv_mm_delay(vty, tlvh);
    3763           0 :                         break;
    3764           0 :                 case TE_LINK_SUBTLV_DELAY_VAR:
    3765           0 :                         sum += show_vty_link_subtlv_delay_var(vty, tlvh);
    3766           0 :                         break;
    3767           0 :                 case TE_LINK_SUBTLV_PKT_LOSS:
    3768           0 :                         sum += show_vty_link_subtlv_pkt_loss(vty, tlvh);
    3769           0 :                         break;
    3770           0 :                 case TE_LINK_SUBTLV_RES_BW:
    3771           0 :                         sum += show_vty_link_subtlv_res_bw(vty, tlvh);
    3772           0 :                         break;
    3773           0 :                 case TE_LINK_SUBTLV_AVA_BW:
    3774           0 :                         sum += show_vty_link_subtlv_ava_bw(vty, tlvh);
    3775           0 :                         break;
    3776           0 :                 case TE_LINK_SUBTLV_USE_BW:
    3777           0 :                         sum += show_vty_link_subtlv_use_bw(vty, tlvh);
    3778           0 :                         break;
    3779           0 :                 default:
    3780           0 :                         sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
    3781           0 :                         break;
    3782             :                 }
    3783             :         }
    3784           0 :         return sum;
    3785             : }
    3786             : 
    3787           0 : static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json,
    3788             :                                    struct ospf_lsa *lsa)
    3789             : {
    3790           0 :         struct lsa_header *lsah = lsa->data;
    3791           0 :         struct tlv_header *tlvh, *next;
    3792           0 :         uint16_t sum, total;
    3793           0 :         uint16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh,
    3794             :                             uint16_t subtotal, uint16_t total) = NULL;
    3795             : 
    3796           0 :         if (json)
    3797             :                 return;
    3798             : 
    3799           0 :         sum = 0;
    3800           0 :         total = lsa->size - OSPF_LSA_HEADER_SIZE;
    3801             : 
    3802           0 :         for (tlvh = TLV_HDR_TOP(lsah); sum < total && tlvh;
    3803           0 :              tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
    3804           0 :                 if (subfunc != NULL) {
    3805           0 :                         sum = (*subfunc)(vty, tlvh, sum, total);
    3806           0 :                         next = (struct tlv_header *)((char *)tlvh + sum);
    3807           0 :                         subfunc = NULL;
    3808           0 :                         continue;
    3809             :                 }
    3810             : 
    3811           0 :                 next = NULL;
    3812           0 :                 switch (ntohs(tlvh->type)) {
    3813           0 :                 case TE_TLV_ROUTER_ADDR:
    3814           0 :                         sum += show_vty_router_addr(vty, tlvh);
    3815           0 :                         break;
    3816           0 :                 case TE_TLV_LINK:
    3817           0 :                         sum += show_vty_link_header(vty, tlvh, total - sum);
    3818           0 :                         subfunc = ospf_mpls_te_show_link_subtlv;
    3819           0 :                         next = TLV_DATA(tlvh);
    3820           0 :                         break;
    3821           0 :                 default:
    3822           0 :                         sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
    3823           0 :                         break;
    3824             :                 }
    3825             :         }
    3826             :         return;
    3827             : }
    3828             : 
    3829           0 : static void ospf_mpls_te_config_write_router(struct vty *vty)
    3830             : {
    3831             : 
    3832           0 :         if (OspfMplsTE.enabled) {
    3833           0 :                 vty_out(vty, " mpls-te on\n");
    3834           0 :                 vty_out(vty, " mpls-te router-address %pI4\n",
    3835             :                         &OspfMplsTE.router_addr.value);
    3836             : 
    3837           0 :                 if (OspfMplsTE.inter_as == AS)
    3838           0 :                         vty_out(vty, " mpls-te inter-as as\n");
    3839           0 :                 if (OspfMplsTE.inter_as == Area)
    3840           0 :                         vty_out(vty, " mpls-te inter-as area %pI4 \n",
    3841             :                                 &OspfMplsTE.interas_areaid);
    3842           0 :                 if (OspfMplsTE.export)
    3843           0 :                         vty_out(vty, " mpls-te export\n");
    3844             :         }
    3845           0 :         return;
    3846             : }
    3847             : 
    3848             : /*------------------------------------------------------------------------*
    3849             :  * Following are vty command functions.
    3850             :  *------------------------------------------------------------------------*/
    3851             : 
    3852           0 : DEFUN (ospf_mpls_te_on,
    3853             :        ospf_mpls_te_on_cmd,
    3854             :        "mpls-te on",
    3855             :        MPLS_TE_STR
    3856             :        "Enable the MPLS-TE functionality\n")
    3857             : {
    3858           0 :         VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
    3859           0 :         struct listnode *node;
    3860           0 :         struct mpls_te_link *lp;
    3861             : 
    3862           0 :         if (OspfMplsTE.enabled)
    3863             :                 return CMD_SUCCESS;
    3864             : 
    3865           0 :         ote_debug("MPLS-TE: OFF -> ON");
    3866             : 
    3867           0 :         OspfMplsTE.enabled = true;
    3868             : 
    3869             :         /* Reoriginate RFC3630 & RFC6827 Links */
    3870           0 :         ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
    3871             :                                   REORIGINATE_THIS_LSA);
    3872             : 
    3873             :         /* Reoriginate LSA if INTER-AS is always on */
    3874           0 :         if (OspfMplsTE.inter_as != Off) {
    3875           0 :                 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) {
    3876           0 :                         if (IS_INTER_AS(lp->type)) {
    3877           0 :                                 ospf_mpls_te_lsa_schedule(lp,
    3878             :                                                           REORIGINATE_THIS_LSA);
    3879             :                         }
    3880             :                 }
    3881             :         }
    3882             : 
    3883             :         /* Create TED and initialize it */
    3884           0 :         OspfMplsTE.ted = ls_ted_new(1, "OSPF", 0);
    3885           0 :         if (!OspfMplsTE.ted) {
    3886           0 :                 vty_out(vty, "Unable to create Link State Data Base\n");
    3887           0 :                 return CMD_WARNING;
    3888             :         }
    3889           0 :         ospf_te_init_ted(OspfMplsTE.ted, ospf);
    3890             : 
    3891           0 :         return CMD_SUCCESS;
    3892             : }
    3893             : 
    3894           0 : DEFUN (no_ospf_mpls_te,
    3895             :        no_ospf_mpls_te_cmd,
    3896             :        "no mpls-te [on]",
    3897             :        NO_STR
    3898             :        MPLS_TE_STR
    3899             :        "Disable the MPLS-TE functionality\n")
    3900             : {
    3901           0 :         VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
    3902           0 :         struct listnode *node, *nnode;
    3903           0 :         struct mpls_te_link *lp;
    3904             : 
    3905           0 :         if (!OspfMplsTE.enabled)
    3906             :                 return CMD_SUCCESS;
    3907             : 
    3908           0 :         ote_debug("MPLS-TE: ON -> OFF");
    3909             : 
    3910             :         /* Remove TED */
    3911           0 :         ls_ted_del_all(&OspfMplsTE.ted);
    3912           0 :         OspfMplsTE.enabled = false;
    3913             : 
    3914             :         /* Flush all TE Opaque LSAs */
    3915           0 :         for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
    3916           0 :                 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
    3917           0 :                         ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
    3918             : 
    3919             :         /*
    3920             :          * This resets the OspfMplsTE.inter_as to its initial state.
    3921             :          * This is to avoid having an inter-as value different from
    3922             :          * Off when mpls-te gets restarted (after being removed)
    3923             :          */
    3924           0 :         OspfMplsTE.inter_as = Off;
    3925             : 
    3926           0 :         return CMD_SUCCESS;
    3927             : }
    3928             : 
    3929           0 : DEFUN (ospf_mpls_te_router_addr,
    3930             :        ospf_mpls_te_router_addr_cmd,
    3931             :        "mpls-te router-address A.B.C.D",
    3932             :        MPLS_TE_STR
    3933             :        "Stable IP address of the advertising router\n"
    3934             :        "MPLS-TE router address in IPv4 address format\n")
    3935             : {
    3936           0 :         VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
    3937           0 :         int idx_ipv4 = 2;
    3938           0 :         struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
    3939           0 :         struct in_addr value;
    3940             : 
    3941           0 :         if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
    3942           0 :                 vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
    3943           0 :                 return CMD_WARNING;
    3944             :         }
    3945             : 
    3946           0 :         if (ntohs(ra->header.type) == 0
    3947           0 :             || ntohl(ra->value.s_addr) != ntohl(value.s_addr)) {
    3948           0 :                 struct listnode *node, *nnode;
    3949           0 :                 struct mpls_te_link *lp;
    3950           0 :                 int need_to_reoriginate = 0;
    3951             : 
    3952           0 :                 set_mpls_te_router_addr(value);
    3953             : 
    3954           0 :                 if (!OspfMplsTE.enabled)
    3955             :                         return CMD_SUCCESS;
    3956             : 
    3957           0 :                 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
    3958           0 :                         if ((lp->area == NULL) || IS_FLOOD_AS(lp->flags))
    3959           0 :                                 continue;
    3960             : 
    3961           0 :                         if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
    3962             :                                 need_to_reoriginate = 1;
    3963             :                                 break;
    3964             :                         }
    3965             :                 }
    3966             : 
    3967           0 :                 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
    3968           0 :                         if ((lp->area == NULL) || IS_FLOOD_AS(lp->flags))
    3969           0 :                                 continue;
    3970             : 
    3971           0 :                         if (need_to_reoriginate)
    3972           0 :                                 SET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
    3973             :                         else
    3974           0 :                                 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
    3975             :                 }
    3976             : 
    3977           0 :                 if (need_to_reoriginate)
    3978           0 :                         ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
    3979             :                                                   REORIGINATE_THIS_LSA);
    3980             :         }
    3981             : 
    3982             :         return CMD_SUCCESS;
    3983             : }
    3984             : 
    3985           0 : static int set_inter_as_mode(struct vty *vty, const char *mode_name,
    3986             :                              const char *area_id)
    3987             : {
    3988           0 :         enum inter_as_mode mode;
    3989           0 :         struct listnode *node;
    3990           0 :         struct mpls_te_link *lp;
    3991           0 :         int format;
    3992             : 
    3993           0 :         if (OspfMplsTE.enabled) {
    3994             : 
    3995             :                 /* Read and Check inter_as mode */
    3996           0 :                 if (strcmp(mode_name, "as") == 0)
    3997             :                         mode = AS;
    3998           0 :                 else if (strcmp(mode_name, "area") == 0) {
    3999           0 :                         mode = Area;
    4000           0 :                         VTY_GET_OSPF_AREA_ID(OspfMplsTE.interas_areaid, format,
    4001             :                                              area_id);
    4002             :                 } else {
    4003           0 :                         vty_out(vty,
    4004             :                                 "Unknown mode. Please choose between as or area\n");
    4005           0 :                         return CMD_WARNING;
    4006             :                 }
    4007             : 
    4008           0 :                 ote_debug(
    4009             :                         "MPLS-TE (%s): Inter-AS enable with %s flooding support",
    4010             :                         __func__, mode2text[mode]);
    4011             : 
    4012             :                 /* Enable mode and re-originate LSA if needed */
    4013           0 :                 if ((OspfMplsTE.inter_as == Off)
    4014             :                     && (mode != OspfMplsTE.inter_as)) {
    4015           0 :                         OspfMplsTE.inter_as = mode;
    4016             :                         /* Re-originate all InterAS-TEv2 LSA */
    4017           0 :                         for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node,
    4018             :                                                   lp)) {
    4019           0 :                                 if (IS_INTER_AS(lp->type)) {
    4020           0 :                                         if (mode == AS)
    4021           0 :                                                 SET_FLAG(lp->flags,
    4022             :                                                          LPFLG_LSA_FLOOD_AS);
    4023             :                                         else
    4024           0 :                                                 UNSET_FLAG(lp->flags,
    4025             :                                                            LPFLG_LSA_FLOOD_AS);
    4026           0 :                                         ospf_mpls_te_lsa_schedule(
    4027             :                                                 lp, REORIGINATE_THIS_LSA);
    4028             :                                 }
    4029             :                         }
    4030             :                 } else {
    4031           0 :                         vty_out(vty,
    4032             :                                 "Please change Inter-AS support to disable first before going to mode %s\n",
    4033           0 :                                 mode2text[mode]);
    4034           0 :                         return CMD_WARNING;
    4035             :                 }
    4036             :         } else {
    4037           0 :                 vty_out(vty, "mpls-te has not been turned on\n");
    4038           0 :                 return CMD_WARNING;
    4039             :         }
    4040             :         return CMD_SUCCESS;
    4041             : }
    4042             : 
    4043             : 
    4044           0 : DEFUN (ospf_mpls_te_inter_as_as,
    4045             :        ospf_mpls_te_inter_as_cmd,
    4046             :        "mpls-te inter-as as",
    4047             :        MPLS_TE_STR
    4048             :        "Configure MPLS-TE Inter-AS support\n"
    4049             :        "AS native mode self originate INTER_AS LSA with Type 11 (as flooding scope)\n")
    4050             : {
    4051           0 :         return set_inter_as_mode(vty, "as", "");
    4052             : }
    4053             : 
    4054           0 : DEFUN (ospf_mpls_te_inter_as_area,
    4055             :        ospf_mpls_te_inter_as_area_cmd,
    4056             :        "mpls-te inter-as area <A.B.C.D|(0-4294967295)>",
    4057             :        MPLS_TE_STR
    4058             :        "Configure MPLS-TE Inter-AS support\n"
    4059             :        "AREA native mode self originate INTER_AS LSA with Type 10 (area flooding scope)\n"
    4060             :        "OSPF area ID in IP format\n"
    4061             :        "OSPF area ID as decimal value\n")
    4062             : {
    4063           0 :         int idx_ipv4_number = 3;
    4064           0 :         return set_inter_as_mode(vty, "area", argv[idx_ipv4_number]->arg);
    4065             : }
    4066             : 
    4067           0 : DEFUN (no_ospf_mpls_te_inter_as,
    4068             :        no_ospf_mpls_te_inter_as_cmd,
    4069             :        "no mpls-te inter-as",
    4070             :        NO_STR
    4071             :        MPLS_TE_STR
    4072             :        "Disable MPLS-TE Inter-AS support\n")
    4073             : {
    4074             : 
    4075           0 :         struct listnode *node, *nnode;
    4076           0 :         struct mpls_te_link *lp;
    4077             : 
    4078           0 :         ote_debug("MPLS-TE: Inter-AS support OFF");
    4079             : 
    4080           0 :         if ((OspfMplsTE.enabled) && (OspfMplsTE.inter_as != Off)) {
    4081             :                 /* Flush all Inter-AS LSA */
    4082           0 :                 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
    4083           0 :                         if (IS_INTER_AS(lp->type)
    4084           0 :                             && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
    4085           0 :                                 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
    4086             : 
    4087           0 :                 OspfMplsTE.inter_as = Off;
    4088             :         }
    4089             : 
    4090           0 :         return CMD_SUCCESS;
    4091             : }
    4092             : 
    4093           0 : DEFUN (ospf_mpls_te_export,
    4094             :        ospf_mpls_te_export_cmd,
    4095             :        "mpls-te export",
    4096             :        MPLS_TE_STR
    4097             :        "Export the MPLS-TE information as Link State\n")
    4098             : {
    4099             : 
    4100           0 :         VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
    4101             : 
    4102           0 :         if (OspfMplsTE.enabled) {
    4103           0 :                 if (ls_register(zclient, true) != 0) {
    4104           0 :                         vty_out(vty, "Unable to register Link State\n");
    4105           0 :                         return CMD_WARNING;
    4106             :                 }
    4107           0 :                 OspfMplsTE.export = true;
    4108             :         } else {
    4109           0 :                 vty_out(vty, "mpls-te has not been turned on\n");
    4110           0 :                 return CMD_WARNING;
    4111             :         }
    4112           0 :         return CMD_SUCCESS;
    4113             : }
    4114             : 
    4115             : 
    4116           0 : DEFUN (no_ospf_mpls_te_export,
    4117             :        no_ospf_mpls_te_export_cmd,
    4118             :        "no mpls-te export",
    4119             :        NO_STR
    4120             :        MPLS_TE_STR
    4121             :        "Stop export of the MPLS-TE information as Link State\n")
    4122             : {
    4123             : 
    4124           0 :         VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
    4125             : 
    4126           0 :         if (OspfMplsTE.export) {
    4127           0 :                 if (ls_unregister(zclient, true) != 0) {
    4128           0 :                         vty_out(vty, "Unable to unregister Link State\n");
    4129           0 :                         return CMD_WARNING;
    4130             :                 }
    4131           0 :                 OspfMplsTE.export = false;
    4132             :         }
    4133             :         return CMD_SUCCESS;
    4134             : }
    4135             : 
    4136           0 : DEFUN (show_ip_ospf_mpls_te_router,
    4137             :        show_ip_ospf_mpls_te_router_cmd,
    4138             :        "show ip ospf mpls-te router",
    4139             :        SHOW_STR
    4140             :        IP_STR
    4141             :        OSPF_STR
    4142             :        "MPLS-TE information\n"
    4143             :        "MPLS-TE Router parameters\n")
    4144             : {
    4145           0 :         if (OspfMplsTE.enabled) {
    4146           0 :                 vty_out(vty, "--- MPLS-TE router parameters ---\n");
    4147             : 
    4148           0 :                 if (ntohs(OspfMplsTE.router_addr.header.type) != 0)
    4149           0 :                         show_vty_router_addr(vty,
    4150             :                                              &OspfMplsTE.router_addr.header);
    4151             :                 else
    4152           0 :                         vty_out(vty, "  Router address is not set\n");
    4153           0 :                 vty_out(vty, "  Link State distribution is %s\n",
    4154           0 :                         OspfMplsTE.export ? "Active" : "Inactive");
    4155             :         }
    4156           0 :         return CMD_SUCCESS;
    4157             : }
    4158             : 
    4159           0 : static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp)
    4160             : {
    4161           0 :         struct mpls_te_link *lp;
    4162             : 
    4163           0 :         if ((OspfMplsTE.enabled) && HAS_LINK_PARAMS(ifp) && !if_is_loopback(ifp)
    4164           0 :             && if_is_up(ifp)
    4165           0 :             && ((lp = lookup_linkparams_by_ifp(ifp)) != NULL)) {
    4166             :                 /* Continue only if interface is not passive or support Inter-AS
    4167             :                  * TEv2 */
    4168           0 :                 if (!(ospf_oi_count(ifp) > 0)) {
    4169           0 :                         if (IS_INTER_AS(lp->type)) {
    4170           0 :                                 vty_out(vty,
    4171             :                                         "-- Inter-AS TEv2 link parameters for %s --\n",
    4172           0 :                                         ifp->name);
    4173             :                         } else {
    4174             :                                 /* MPLS-TE is not activate on this interface */
    4175             :                                 /* or this interface is passive and Inter-AS
    4176             :                                  * TEv2 is not activate */
    4177           0 :                                 vty_out(vty,
    4178             :                                         "  %s: MPLS-TE is disabled on this interface\n",
    4179           0 :                                         ifp->name);
    4180           0 :                                 return;
    4181             :                         }
    4182             :                 } else {
    4183           0 :                         vty_out(vty, "-- MPLS-TE link parameters for %s --\n",
    4184           0 :                                 ifp->name);
    4185             :                 }
    4186             : 
    4187           0 :                 if (TLV_TYPE(lp->link_type) != 0)
    4188           0 :                         show_vty_link_subtlv_link_type(vty,
    4189             :                                                        &lp->link_type.header);
    4190           0 :                 if (TLV_TYPE(lp->link_id) != 0)
    4191           0 :                         show_vty_link_subtlv_link_id(vty, &lp->link_id.header);
    4192           0 :                 if (TLV_TYPE(lp->lclif_ipaddr) != 0)
    4193           0 :                         show_vty_link_subtlv_lclif_ipaddr(
    4194             :                                 vty, &lp->lclif_ipaddr.header,
    4195           0 :                                 lp->lclif_ipaddr.header.length);
    4196           0 :                 if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
    4197           0 :                         show_vty_link_subtlv_rmtif_ipaddr(
    4198             :                                 vty, &lp->rmtif_ipaddr.header,
    4199           0 :                                 lp->rmtif_ipaddr.header.length);
    4200           0 :                 if (TLV_TYPE(lp->rip) != 0)
    4201           0 :                         show_vty_link_subtlv_rip(vty, &lp->rip.header);
    4202           0 :                 if (TLV_TYPE(lp->ras) != 0)
    4203           0 :                         show_vty_link_subtlv_ras(vty, &lp->ras.header);
    4204           0 :                 if (TLV_TYPE(lp->te_metric) != 0)
    4205           0 :                         show_vty_link_subtlv_te_metric(vty,
    4206             :                                                        &lp->te_metric.header);
    4207           0 :                 if (TLV_TYPE(lp->max_bw) != 0)
    4208           0 :                         show_vty_link_subtlv_max_bw(vty, &lp->max_bw.header);
    4209           0 :                 if (TLV_TYPE(lp->max_rsv_bw) != 0)
    4210           0 :                         show_vty_link_subtlv_max_rsv_bw(vty,
    4211             :                                                         &lp->max_rsv_bw.header);
    4212           0 :                 if (TLV_TYPE(lp->unrsv_bw) != 0)
    4213           0 :                         show_vty_link_subtlv_unrsv_bw(vty,
    4214             :                                                       &lp->unrsv_bw.header);
    4215           0 :                 if (TLV_TYPE(lp->rsc_clsclr) != 0)
    4216           0 :                         show_vty_link_subtlv_rsc_clsclr(vty,
    4217             :                                                         &lp->rsc_clsclr.header);
    4218           0 :                 if (TLV_TYPE(lp->av_delay) != 0)
    4219           0 :                         show_vty_link_subtlv_av_delay(vty,
    4220             :                                                       &lp->av_delay.header);
    4221           0 :                 if (TLV_TYPE(lp->mm_delay) != 0)
    4222           0 :                         show_vty_link_subtlv_mm_delay(vty,
    4223             :                                                       &lp->mm_delay.header);
    4224           0 :                 if (TLV_TYPE(lp->delay_var) != 0)
    4225           0 :                         show_vty_link_subtlv_delay_var(vty,
    4226             :                                                        &lp->delay_var.header);
    4227           0 :                 if (TLV_TYPE(lp->pkt_loss) != 0)
    4228           0 :                         show_vty_link_subtlv_pkt_loss(vty,
    4229             :                                                       &lp->pkt_loss.header);
    4230           0 :                 if (TLV_TYPE(lp->res_bw) != 0)
    4231           0 :                         show_vty_link_subtlv_res_bw(vty, &lp->res_bw.header);
    4232           0 :                 if (TLV_TYPE(lp->ava_bw) != 0)
    4233           0 :                         show_vty_link_subtlv_ava_bw(vty, &lp->ava_bw.header);
    4234           0 :                 if (TLV_TYPE(lp->use_bw) != 0)
    4235           0 :                         show_vty_link_subtlv_use_bw(vty, &lp->use_bw.header);
    4236           0 :                 vty_out(vty, "---------------\n\n");
    4237             :         } else {
    4238           0 :                 vty_out(vty, "  %s: MPLS-TE is disabled on this interface\n",
    4239           0 :                         ifp->name);
    4240             :         }
    4241             : 
    4242             :         return;
    4243             : }
    4244             : 
    4245           0 : DEFUN (show_ip_ospf_mpls_te_link,
    4246             :        show_ip_ospf_mpls_te_link_cmd,
    4247             :        "show ip ospf [vrf <NAME|all>] mpls-te interface [INTERFACE]",
    4248             :        SHOW_STR
    4249             :        IP_STR
    4250             :        OSPF_STR
    4251             :        VRF_CMD_HELP_STR
    4252             :        "All VRFs\n"
    4253             :        "MPLS-TE information\n"
    4254             :        "Interface information\n"
    4255             :        "Interface name\n")
    4256             : {
    4257           0 :         struct vrf *vrf;
    4258           0 :         int idx_interface = 0;
    4259           0 :         struct interface *ifp = NULL;
    4260           0 :         struct listnode *node;
    4261           0 :         char *vrf_name = NULL;
    4262           0 :         bool all_vrf = false;
    4263           0 :         int inst = 0;
    4264           0 :         int idx_vrf = 0;
    4265           0 :         struct ospf *ospf = NULL;
    4266             : 
    4267           0 :         if (argv_find(argv, argc, "vrf", &idx_vrf)) {
    4268           0 :                 vrf_name = argv[idx_vrf + 1]->arg;
    4269           0 :                 all_vrf = strmatch(vrf_name, "all");
    4270             :         }
    4271           0 :         argv_find(argv, argc, "INTERFACE", &idx_interface);
    4272             :         /* vrf input is provided could be all or specific vrf*/
    4273           0 :         if (vrf_name) {
    4274           0 :                 if (all_vrf) {
    4275           0 :                         for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
    4276           0 :                                 if (!ospf->oi_running)
    4277           0 :                                         continue;
    4278           0 :                                 vrf = vrf_lookup_by_id(ospf->vrf_id);
    4279           0 :                                 FOR_ALL_INTERFACES (vrf, ifp)
    4280           0 :                                         show_mpls_te_link_sub(vty, ifp);
    4281             :                         }
    4282             :                         return CMD_SUCCESS;
    4283             :                 }
    4284           0 :                 ospf = ospf_lookup_by_inst_name(inst, vrf_name);
    4285             :         } else
    4286           0 :                 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
    4287           0 :         if (ospf == NULL || !ospf->oi_running)
    4288             :                 return CMD_SUCCESS;
    4289             : 
    4290           0 :         vrf = vrf_lookup_by_id(ospf->vrf_id);
    4291           0 :         if (!vrf)
    4292             :                 return CMD_SUCCESS;
    4293           0 :         if (idx_interface) {
    4294           0 :                 ifp = if_lookup_by_name(
    4295           0 :                                         argv[idx_interface]->arg,
    4296             :                                         ospf->vrf_id);
    4297           0 :                 if (ifp == NULL) {
    4298           0 :                         vty_out(vty, "No such interface name in vrf %s\n",
    4299           0 :                                 vrf->name);
    4300           0 :                         return CMD_SUCCESS;
    4301             :                 }
    4302             :         }
    4303           0 :         if (!ifp) {
    4304           0 :                 FOR_ALL_INTERFACES (vrf, ifp)
    4305           0 :                         show_mpls_te_link_sub(vty, ifp);
    4306             :                 return CMD_SUCCESS;
    4307             :         }
    4308             : 
    4309           0 :         show_mpls_te_link_sub(vty, ifp);
    4310           0 :         return CMD_SUCCESS;
    4311             : }
    4312             : 
    4313           0 : DEFUN (show_ip_ospf_mpls_te_db,
    4314             :        show_ip_ospf_mpls_te_db_cmd,
    4315             :        "show ip ospf mpls-te database [<vertex [<self-originate|adv-router A.B.C.D>]|edge [A.B.C.D]|subnet [A.B.C.D/M]>] [verbose|json]",
    4316             :        SHOW_STR
    4317             :        IP_STR
    4318             :        OSPF_STR
    4319             :        "MPLS-TE information\n"
    4320             :        "MPLS-TE database\n"
    4321             :        "MPLS-TE Vertex\n"
    4322             :        "Self-originated MPLS-TE router\n"
    4323             :        "Advertised MPLS-TE router\n"
    4324             :        "MPLS-TE router ID (as an IP address)\n"
    4325             :        "MPLS-TE Edge\n"
    4326             :        "MPLS-TE Edge ID (as an IP address)\n"
    4327             :        "MPLS-TE Subnet\n"
    4328             :        "MPLS-TE Subnet ID (as an IP prefix)\n"
    4329             :        "Verbose output\n"
    4330             :        JSON_STR)
    4331             : {
    4332           0 :         int idx = 0;
    4333           0 :         struct in_addr ip_addr;
    4334           0 :         struct prefix pref;
    4335           0 :         struct ls_vertex *vertex;
    4336           0 :         struct ls_edge *edge;
    4337           0 :         struct ls_subnet *subnet;
    4338           0 :         uint64_t key;
    4339           0 :         bool verbose = false;
    4340           0 :         bool uj = use_json(argc, argv);
    4341           0 :         json_object *json = NULL;
    4342             : 
    4343           0 :         if (!OspfMplsTE.enabled || !OspfMplsTE.ted) {
    4344           0 :                 vty_out(vty, "MPLS-TE database is not enabled\n");
    4345           0 :                 return CMD_WARNING;
    4346             :         }
    4347             : 
    4348           0 :         if (uj)
    4349           0 :                 json = json_object_new_object();
    4350             : 
    4351           0 :         if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "verbose"))
    4352           0 :                 verbose = true;
    4353             : 
    4354           0 :         idx = 5;
    4355           0 :         if (argv_find(argv, argc, "vertex", &idx)) {
    4356             :                 /* Show Vertex */
    4357           0 :                 if (argv_find(argv, argc, "self-originate", &idx))
    4358           0 :                         vertex = OspfMplsTE.ted->self;
    4359           0 :                 else if (argv_find(argv, argc, "adv-router", &idx)) {
    4360           0 :                         if (!inet_aton(argv[idx + 1]->arg, &ip_addr)) {
    4361           0 :                                 vty_out(vty,
    4362             :                                         "Specified Router ID %s is invalid\n",
    4363           0 :                                         argv[idx + 1]->arg);
    4364           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    4365             :                         }
    4366             :                         /* Get the Vertex from the Link State Database */
    4367           0 :                         key = ((uint64_t)ntohl(ip_addr.s_addr)) & 0xffffffff;
    4368           0 :                         vertex = ls_find_vertex_by_key(OspfMplsTE.ted, key);
    4369           0 :                         if (!vertex) {
    4370           0 :                                 vty_out(vty, "No vertex found for ID %pI4\n",
    4371             :                                         &ip_addr);
    4372           0 :                                 return CMD_WARNING;
    4373             :                         }
    4374             :                 } else
    4375             :                         vertex = NULL;
    4376             : 
    4377           0 :                 if (vertex)
    4378           0 :                         ls_show_vertex(vertex, vty, json, verbose);
    4379             :                 else
    4380           0 :                         ls_show_vertices(OspfMplsTE.ted, vty, json, verbose);
    4381             : 
    4382           0 :         } else if (argv_find(argv, argc, "edge", &idx)) {
    4383             :                 /* Show Edge */
    4384           0 :                 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
    4385           0 :                         if (!inet_aton(argv[idx]->arg, &ip_addr)) {
    4386           0 :                                 vty_out(vty,
    4387             :                                         "Specified Edge ID %s is invalid\n",
    4388           0 :                                         argv[idx]->arg);
    4389           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    4390             :                         }
    4391             :                         /* Get the Edge from the Link State Database */
    4392           0 :                         key = ((uint64_t)ntohl(ip_addr.s_addr)) & 0xffffffff;
    4393           0 :                         edge = ls_find_edge_by_key(OspfMplsTE.ted, key);
    4394           0 :                         if (!edge) {
    4395           0 :                                 vty_out(vty, "No edge found for ID %pI4\n",
    4396             :                                         &ip_addr);
    4397           0 :                                 return CMD_WARNING;
    4398             :                         }
    4399             :                 } else
    4400             :                         edge = NULL;
    4401             : 
    4402           0 :                 if (edge)
    4403           0 :                         ls_show_edge(edge, vty, json, verbose);
    4404             :                 else
    4405           0 :                         ls_show_edges(OspfMplsTE.ted, vty, json, verbose);
    4406             : 
    4407           0 :         } else if (argv_find(argv, argc, "subnet", &idx)) {
    4408             :                 /* Show Subnet */
    4409           0 :                 if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
    4410           0 :                         if (!str2prefix(argv[idx]->arg, &pref)) {
    4411           0 :                                 vty_out(vty, "Invalid prefix format %s\n",
    4412           0 :                                         argv[idx]->arg);
    4413           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    4414             :                         }
    4415             :                         /* Get the Subnet from the Link State Database */
    4416           0 :                         subnet = ls_find_subnet(OspfMplsTE.ted, pref);
    4417           0 :                         if (!subnet) {
    4418           0 :                                 vty_out(vty, "No subnet found for ID %pFX\n",
    4419             :                                         &pref);
    4420           0 :                                 return CMD_WARNING;
    4421             :                         }
    4422             :                 } else
    4423             :                         subnet = NULL;
    4424             : 
    4425           0 :                 if (subnet)
    4426           0 :                         ls_show_subnet(subnet, vty, json, verbose);
    4427             :                 else
    4428           0 :                         ls_show_subnets(OspfMplsTE.ted, vty, json, verbose);
    4429             : 
    4430             :         } else {
    4431             :                 /* Show the complete TED */
    4432           0 :                 ls_show_ted(OspfMplsTE.ted, vty, json, verbose);
    4433             :         }
    4434             : 
    4435           0 :         if (uj)
    4436           0 :                 vty_json(vty, json);
    4437             :         return CMD_SUCCESS;
    4438             : }
    4439             : 
    4440           4 : static void ospf_mpls_te_register_vty(void)
    4441             : {
    4442           4 :         install_element(VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd);
    4443           4 :         install_element(VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd);
    4444           4 :         install_element(VIEW_NODE, &show_ip_ospf_mpls_te_db_cmd);
    4445             : 
    4446           4 :         install_element(OSPF_NODE, &ospf_mpls_te_on_cmd);
    4447           4 :         install_element(OSPF_NODE, &no_ospf_mpls_te_cmd);
    4448           4 :         install_element(OSPF_NODE, &ospf_mpls_te_router_addr_cmd);
    4449           4 :         install_element(OSPF_NODE, &ospf_mpls_te_inter_as_cmd);
    4450           4 :         install_element(OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd);
    4451           4 :         install_element(OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd);
    4452           4 :         install_element(OSPF_NODE, &ospf_mpls_te_export_cmd);
    4453           4 :         install_element(OSPF_NODE, &no_ospf_mpls_te_export_cmd);
    4454             : 
    4455           4 :         return;
    4456             : }

Generated by: LCOV version v1.16-topotato