back to topotato report
topotato coverage report
Current view: top level - lib - link_state.c (source / functions) Hit Total Coverage
Test: test_bgp_minimum_holdtime.py::TestBGPMinimumHoldtime Lines: 1 1592 0.1 %
Date: 2023-02-24 18:37:25 Functions: 2 83 2.4 %

          Line data    Source code
       1             : /*
       2             :  * Link State Database - link_state.c
       3             :  *
       4             :  * Author: Olivier Dugeon <olivier.dugeon@orange.com>
       5             :  *
       6             :  * Copyright (C) 2020 Orange http://www.orange.com
       7             :  *
       8             :  * This file is part of Free Range Routing (FRR).
       9             :  *
      10             :  * FRR is free software; you can redistribute it and/or modify it
      11             :  * under the terms of the GNU General Public License as published by the
      12             :  * Free Software Foundation; either version 2, or (at your option) any
      13             :  * later version.
      14             :  *
      15             :  * FRR is distributed in the hope that it will be useful, but
      16             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :  * General Public License for more details.
      19             :  *
      20             :  * You should have received a copy of the GNU General Public License along
      21             :  * with this program; see the file COPYING; if not, write to the Free Software
      22             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      23             :  */
      24             : 
      25             : #include <zebra.h>
      26             : 
      27             : #include "if.h"
      28             : #include "linklist.h"
      29             : #include "log.h"
      30             : #include "command.h"
      31             : #include "termtable.h"
      32             : #include "memory.h"
      33             : #include "prefix.h"
      34             : #include "table.h"
      35             : #include "vty.h"
      36             : #include "zclient.h"
      37             : #include "stream.h"
      38             : #include "sbuf.h"
      39             : #include "printfrr.h"
      40             : #include <lib/json.h>
      41             : #include "link_state.h"
      42             : 
      43             : /* Link State Memory allocation */
      44          12 : DEFINE_MTYPE_STATIC(LIB, LS_DB, "Link State Database");
      45             : 
      46             : /**
      47             :  *  Link State Node management functions
      48             :  */
      49           0 : int ls_node_id_same(struct ls_node_id i1, struct ls_node_id i2)
      50             : {
      51           0 :         if (i1.origin != i2.origin)
      52             :                 return 0;
      53             : 
      54           0 :         if (i1.origin == UNKNOWN)
      55             :                 return 1;
      56             : 
      57           0 :         if (i1.origin == ISIS_L1 || i1.origin == ISIS_L2) {
      58           0 :                 if (memcmp(i1.id.iso.sys_id, i2.id.iso.sys_id, ISO_SYS_ID_LEN)
      59             :                             != 0
      60           0 :                     || (i1.id.iso.level != i2.id.iso.level))
      61           0 :                         return 0;
      62             :         } else {
      63             :                 if (!IPV4_ADDR_SAME(&i1.id.ip.addr, &i2.id.ip.addr)
      64             :                     || !IPV4_ADDR_SAME(&i1.id.ip.area_id, &i2.id.ip.area_id))
      65             :                         return 1;
      66             :         }
      67             : 
      68             :         return 1;
      69             : }
      70             : 
      71           0 : struct ls_node *ls_node_new(struct ls_node_id adv, struct in_addr rid,
      72             :                             struct in6_addr rid6)
      73             : {
      74           0 :         struct ls_node *new;
      75             : 
      76           0 :         if (adv.origin == UNKNOWN)
      77             :                 return NULL;
      78             : 
      79           0 :         new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_node));
      80           0 :         new->adv = adv;
      81           0 :         if (!IPV4_NET0(rid.s_addr)) {
      82           0 :                 new->router_id = rid;
      83           0 :                 SET_FLAG(new->flags, LS_NODE_ROUTER_ID);
      84             :         } else {
      85           0 :                 if (adv.origin == OSPFv2 || adv.origin == STATIC
      86           0 :                     || adv.origin == DIRECT) {
      87           0 :                         new->router_id = adv.id.ip.addr;
      88           0 :                         SET_FLAG(new->flags, LS_NODE_ROUTER_ID);
      89             :                 }
      90             :         }
      91           0 :         if (!IN6_IS_ADDR_UNSPECIFIED(&rid6)) {
      92           0 :                 new->router_id6 = rid6;
      93           0 :                 SET_FLAG(new->flags, LS_NODE_ROUTER_ID6);
      94             :         }
      95             :         return new;
      96             : }
      97             : 
      98           0 : void ls_node_del(struct ls_node *node)
      99             : {
     100           0 :         if (!node)
     101             :                 return;
     102             : 
     103           0 :         XFREE(MTYPE_LS_DB, node);
     104             : }
     105             : 
     106           0 : int ls_node_same(struct ls_node *n1, struct ls_node *n2)
     107             : {
     108             :         /* First, check pointer */
     109           0 :         if ((n1 && !n2) || (!n1 && n2))
     110             :                 return 0;
     111             : 
     112           0 :         if (n1 == n2)
     113             :                 return 1;
     114             : 
     115             :         /* Then, verify Flags and Origin */
     116           0 :         if (n1->flags != n2->flags)
     117             :                 return 0;
     118             : 
     119           0 :         if (!ls_node_id_same(n1->adv, n2->adv))
     120             :                 return 0;
     121             : 
     122             :         /* Finally, check each individual parameters that are valid */
     123           0 :         if (CHECK_FLAG(n1->flags, LS_NODE_NAME)
     124           0 :             && (strncmp(n1->name, n2->name, MAX_NAME_LENGTH) != 0))
     125             :                 return 0;
     126           0 :         if (CHECK_FLAG(n1->flags, LS_NODE_ROUTER_ID)
     127           0 :             && !IPV4_ADDR_SAME(&n1->router_id, &n2->router_id))
     128             :                 return 0;
     129           0 :         if (CHECK_FLAG(n1->flags, LS_NODE_ROUTER_ID6)
     130           0 :             && !IPV6_ADDR_SAME(&n1->router_id6, &n2->router_id6))
     131             :                 return 0;
     132           0 :         if (CHECK_FLAG(n1->flags, LS_NODE_FLAG)
     133           0 :             && (n1->node_flag != n2->node_flag))
     134             :                 return 0;
     135           0 :         if (CHECK_FLAG(n1->flags, LS_NODE_TYPE) && (n1->type != n2->type))
     136             :                 return 0;
     137           0 :         if (CHECK_FLAG(n1->flags, LS_NODE_AS_NUMBER)
     138           0 :             && (n1->as_number != n2->as_number))
     139             :                 return 0;
     140           0 :         if (CHECK_FLAG(n1->flags, LS_NODE_SR)) {
     141           0 :                 if (n1->srgb.flag != n2->srgb.flag
     142           0 :                     || n1->srgb.lower_bound != n2->srgb.lower_bound
     143           0 :                     || n1->srgb.range_size != n2->srgb.range_size)
     144             :                         return 0;
     145           0 :                 if ((n1->algo[0] != n2->algo[0])
     146           0 :                     || (n1->algo[1] != n2->algo[1]))
     147             :                         return 0;
     148           0 :                 if (CHECK_FLAG(n1->flags, LS_NODE_SRLB)
     149           0 :                     && ((n1->srlb.lower_bound != n2->srlb.lower_bound
     150           0 :                          || n1->srlb.range_size != n2->srlb.range_size)))
     151             :                         return 0;
     152           0 :                 if (CHECK_FLAG(n1->flags, LS_NODE_MSD) && (n1->msd != n2->msd))
     153             :                         return 0;
     154             :         }
     155             : 
     156             :         /* OK, n1 & n2 are equal */
     157             :         return 1;
     158             : }
     159             : 
     160             : /**
     161             :  *  Link State Attributes management functions
     162             :  */
     163           0 : struct ls_attributes *ls_attributes_new(struct ls_node_id adv,
     164             :                                         struct in_addr local,
     165             :                                         struct in6_addr local6,
     166             :                                         uint32_t local_id)
     167             : {
     168           0 :         struct ls_attributes *new;
     169             : 
     170           0 :         if (adv.origin == UNKNOWN)
     171             :                 return NULL;
     172             : 
     173           0 :         new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_attributes));
     174           0 :         new->adv = adv;
     175           0 :         if (!IPV4_NET0(local.s_addr)) {
     176           0 :                 new->standard.local = local;
     177           0 :                 SET_FLAG(new->flags, LS_ATTR_LOCAL_ADDR);
     178             :         }
     179           0 :         if (!IN6_IS_ADDR_UNSPECIFIED(&local6)) {
     180           0 :                 new->standard.local6 = local6;
     181           0 :                 SET_FLAG(new->flags, LS_ATTR_LOCAL_ADDR6);
     182             :         }
     183           0 :         if (local_id != 0) {
     184           0 :                 new->standard.local_id = local_id;
     185           0 :                 SET_FLAG(new->flags, LS_ATTR_LOCAL_ID);
     186             :         }
     187             : 
     188             :         /* Check that almost one identifier is set */
     189           0 :         if (!CHECK_FLAG(new->flags, LS_ATTR_LOCAL_ADDR | LS_ATTR_LOCAL_ADDR6
     190             :             | LS_ATTR_LOCAL_ID)) {
     191           0 :                 XFREE(MTYPE_LS_DB, new);
     192           0 :                 return NULL;
     193             :         }
     194             : 
     195             :         return new;
     196             : }
     197             : 
     198           0 : void ls_attributes_srlg_del(struct ls_attributes *attr)
     199             : {
     200           0 :         if (!attr)
     201             :                 return;
     202             : 
     203           0 :         if (attr->srlgs)
     204           0 :                 XFREE(MTYPE_LS_DB, attr->srlgs);
     205             : 
     206           0 :         attr->srlgs = NULL;
     207           0 :         attr->srlg_len = 0;
     208           0 :         UNSET_FLAG(attr->flags, LS_ATTR_SRLG);
     209             : }
     210             : 
     211           0 : void ls_attributes_del(struct ls_attributes *attr)
     212             : {
     213           0 :         if (!attr)
     214             :                 return;
     215             : 
     216           0 :         ls_attributes_srlg_del(attr);
     217             : 
     218           0 :         XFREE(MTYPE_LS_DB, attr);
     219             : }
     220             : 
     221           0 : int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2)
     222             : {
     223             :         /* First, check pointer */
     224           0 :         if ((l1 && !l2) || (!l1 && l2))
     225             :                 return 0;
     226             : 
     227           0 :         if (l1 == l2)
     228             :                 return 1;
     229             : 
     230             :         /* Then, verify Flags and Origin */
     231           0 :         if (l1->flags != l2->flags)
     232             :                 return 0;
     233             : 
     234           0 :         if (!ls_node_id_same(l1->adv, l2->adv))
     235             :                 return 0;
     236             : 
     237             :         /* Finally, check each individual parameters that are valid */
     238           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_NAME)
     239           0 :             && strncmp(l1->name, l2->name, MAX_NAME_LENGTH) != 0)
     240             :                 return 0;
     241           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_METRIC) && (l1->metric != l2->metric))
     242             :                 return 0;
     243           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_TE_METRIC)
     244           0 :             && (l1->standard.te_metric != l2->standard.te_metric))
     245             :                 return 0;
     246           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_ADM_GRP)
     247           0 :             && (l1->standard.admin_group != l2->standard.admin_group))
     248             :                 return 0;
     249           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_LOCAL_ADDR)
     250           0 :             && !IPV4_ADDR_SAME(&l1->standard.local, &l2->standard.local))
     251             :                 return 0;
     252           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_NEIGH_ADDR)
     253           0 :             && !IPV4_ADDR_SAME(&l1->standard.remote, &l2->standard.remote))
     254             :                 return 0;
     255           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_LOCAL_ADDR6)
     256           0 :             && !IPV6_ADDR_SAME(&l1->standard.local6, &l2->standard.local6))
     257             :                 return 0;
     258           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_NEIGH_ADDR6)
     259           0 :             && !IPV6_ADDR_SAME(&l1->standard.remote6, &l2->standard.remote6))
     260             :                 return 0;
     261           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_LOCAL_ID)
     262           0 :             && (l1->standard.local_id != l2->standard.local_id))
     263             :                 return 0;
     264           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_NEIGH_ID)
     265           0 :             && (l1->standard.remote_id != l2->standard.remote_id))
     266             :                 return 0;
     267           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_MAX_BW)
     268           0 :             && (l1->standard.max_bw != l2->standard.max_bw))
     269             :                 return 0;
     270           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_MAX_RSV_BW)
     271           0 :             && (l1->standard.max_rsv_bw != l2->standard.max_rsv_bw))
     272             :                 return 0;
     273           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_UNRSV_BW)
     274           0 :             && memcmp(&l1->standard.unrsv_bw, &l2->standard.unrsv_bw, 32) != 0)
     275             :                 return 0;
     276           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_REMOTE_AS)
     277           0 :             && (l1->standard.remote_as != l2->standard.remote_as))
     278             :                 return 0;
     279           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_REMOTE_ADDR)
     280           0 :             && !IPV4_ADDR_SAME(&l1->standard.remote_addr,
     281             :                                &l2->standard.remote_addr))
     282             :                 return 0;
     283           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_REMOTE_ADDR6)
     284           0 :             && !IPV6_ADDR_SAME(&l1->standard.remote_addr6,
     285             :                                &l2->standard.remote_addr6))
     286             :                 return 0;
     287           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_DELAY)
     288           0 :             && (l1->extended.delay != l2->extended.delay))
     289             :                 return 0;
     290           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_MIN_MAX_DELAY)
     291           0 :             && ((l1->extended.min_delay != l2->extended.min_delay)
     292           0 :                 || (l1->extended.max_delay != l2->extended.max_delay)))
     293             :                 return 0;
     294           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_JITTER)
     295           0 :             && (l1->extended.jitter != l2->extended.jitter))
     296             :                 return 0;
     297           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_PACKET_LOSS)
     298           0 :             && (l1->extended.pkt_loss != l2->extended.pkt_loss))
     299             :                 return 0;
     300           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_AVA_BW)
     301           0 :             && (l1->extended.ava_bw != l2->extended.ava_bw))
     302             :                 return 0;
     303           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_RSV_BW)
     304           0 :             && (l1->extended.rsv_bw != l2->extended.rsv_bw))
     305             :                 return 0;
     306           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_USE_BW)
     307           0 :             && (l1->extended.used_bw != l2->extended.used_bw))
     308             :                 return 0;
     309           0 :         for (int i = 0; i < LS_ADJ_MAX; i++) {
     310           0 :                 if (!CHECK_FLAG(l1->flags, (LS_ATTR_ADJ_SID << i)))
     311           0 :                         continue;
     312           0 :                 if ((l1->adj_sid[i].sid != l2->adj_sid[i].sid)
     313           0 :                     || (l1->adj_sid[i].flags != l2->adj_sid[i].flags)
     314           0 :                     || (l1->adj_sid[i].weight != l2->adj_sid[i].weight))
     315             :                         return 0;
     316           0 :                 if (((l1->adv.origin == ISIS_L1) || (l1->adv.origin == ISIS_L2))
     317           0 :                     && (memcmp(&l1->adj_sid[i].neighbor.sysid,
     318           0 :                                &l2->adj_sid[i].neighbor.sysid, ISO_SYS_ID_LEN)
     319             :                         != 0))
     320             :                         return 0;
     321           0 :                 if (((l1->adv.origin == OSPFv2) || (l1->adv.origin == STATIC)
     322           0 :                      || (l1->adv.origin == DIRECT))
     323           0 :                     && (i < ADJ_PRI_IPV6)
     324           0 :                     && (!IPV4_ADDR_SAME(&l1->adj_sid[i].neighbor.addr,
     325             :                                         &l2->adj_sid[i].neighbor.addr)))
     326             :                         return 0;
     327             :         }
     328           0 :         if (CHECK_FLAG(l1->flags, LS_ATTR_SRLG)
     329           0 :             && ((l1->srlg_len != l2->srlg_len)
     330           0 :                 || memcmp(l1->srlgs, l2->srlgs,
     331           0 :                           l1->srlg_len * sizeof(uint32_t))
     332             :                            != 0))
     333             :                 return 0;
     334             : 
     335             :         /* OK, l1 & l2 are equal */
     336             :         return 1;
     337             : }
     338             : 
     339             : /**
     340             :  *  Link State prefix management functions
     341             :  */
     342           0 : struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p)
     343             : {
     344           0 :         struct ls_prefix *new;
     345             : 
     346           0 :         if (adv.origin == UNKNOWN)
     347             :                 return NULL;
     348             : 
     349           0 :         new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix));
     350           0 :         new->adv = adv;
     351           0 :         new->pref = p;
     352             : 
     353           0 :         return new;
     354             : }
     355             : 
     356           0 : void ls_prefix_del(struct ls_prefix *pref)
     357             : {
     358           0 :         if (!pref)
     359             :                 return;
     360             : 
     361           0 :         XFREE(MTYPE_LS_DB, pref);
     362             : }
     363             : 
     364           0 : int ls_prefix_same(struct ls_prefix *p1, struct ls_prefix *p2)
     365             : {
     366             :         /* First, check pointer */
     367           0 :         if ((p1 && !p2) || (!p1 && p2))
     368             :                 return 0;
     369             : 
     370           0 :         if (p1 == p2)
     371             :                 return 1;
     372             : 
     373             :         /* Then, verify Flags and Origin */
     374           0 :         if (p1->flags != p2->flags)
     375             :                 return 0;
     376             : 
     377           0 :         if (!ls_node_id_same(p1->adv, p2->adv))
     378             :                 return 0;
     379             : 
     380             :         /* Finally, check each individual parameters that are valid */
     381           0 :         if (prefix_same(&p1->pref, &p2->pref) == 0)
     382             :                 return 0;
     383           0 :         if (CHECK_FLAG(p1->flags, LS_PREF_IGP_FLAG)
     384           0 :             && (p1->igp_flag != p2->igp_flag))
     385             :                 return 0;
     386           0 :         if (CHECK_FLAG(p1->flags, LS_PREF_ROUTE_TAG)
     387           0 :             && (p1->route_tag != p2->route_tag))
     388             :                 return 0;
     389           0 :         if (CHECK_FLAG(p1->flags, LS_PREF_EXTENDED_TAG)
     390           0 :             && (p1->extended_tag != p2->extended_tag))
     391             :                 return 0;
     392           0 :         if (CHECK_FLAG(p1->flags, LS_PREF_METRIC) && (p1->metric != p2->metric))
     393             :                 return 0;
     394           0 :         if (CHECK_FLAG(p1->flags, LS_PREF_SR)) {
     395           0 :                 if ((p1->sr.algo != p2->sr.algo) || (p1->sr.sid != p2->sr.sid)
     396           0 :                     || (p1->sr.sid_flag != p2->sr.sid_flag))
     397             :                         return 0;
     398             :         }
     399             : 
     400             :         /* OK, p1 & p2 are equal */
     401             :         return 1;
     402             : }
     403             : 
     404             : /**
     405             :  *  Link State Vertices management functions
     406             :  */
     407           0 : uint64_t sysid_to_key(const uint8_t sysid[ISO_SYS_ID_LEN])
     408             : {
     409           0 :         uint64_t key = 0;
     410             : 
     411             : #if BYTE_ORDER == LITTLE_ENDIAN
     412           0 :         uint8_t *byte = (uint8_t *)&key;
     413             : 
     414           0 :         for (int i = 0; i < ISO_SYS_ID_LEN; i++)
     415           0 :                 byte[i] = sysid[ISO_SYS_ID_LEN - i - 1];
     416             : 
     417           0 :         byte[6] = 0;
     418           0 :         byte[7] = 0;
     419             : #else
     420             :         memcpy(&key, sysid, ISO_SYS_ID_LEN);
     421             : #endif
     422             : 
     423           0 :         return key;
     424             : }
     425             : 
     426           0 : struct ls_vertex *ls_vertex_add(struct ls_ted *ted, struct ls_node *node)
     427             : {
     428           0 :         struct ls_vertex *new;
     429           0 :         uint64_t key = 0;
     430             : 
     431           0 :         if ((ted == NULL) || (node == NULL))
     432             :                 return NULL;
     433             : 
     434             :         /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
     435           0 :         switch (node->adv.origin) {
     436           0 :         case OSPFv2:
     437             :         case STATIC:
     438             :         case DIRECT:
     439           0 :                 key = ((uint64_t)ntohl(node->adv.id.ip.addr.s_addr))
     440             :                       & 0xffffffff;
     441           0 :                 break;
     442           0 :         case ISIS_L1:
     443             :         case ISIS_L2:
     444           0 :                 key = sysid_to_key(node->adv.id.iso.sys_id);
     445           0 :                 break;
     446             :         case UNKNOWN:
     447             :                 key = 0;
     448             :                 break;
     449             :         }
     450             : 
     451             :         /* Check that key is valid */
     452           0 :         if (key == 0)
     453           0 :                 return NULL;
     454             : 
     455             :         /* Create Vertex and add it to the TED */
     456           0 :         new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_vertex));
     457           0 :         if (!new)
     458             :                 return NULL;
     459             : 
     460           0 :         new->key = key;
     461           0 :         new->node = node;
     462           0 :         new->status = NEW;
     463           0 :         new->type = VERTEX;
     464           0 :         new->incoming_edges = list_new();
     465           0 :         new->incoming_edges->cmp = (int (*)(void *, void *))edge_cmp;
     466           0 :         new->outgoing_edges = list_new();
     467           0 :         new->outgoing_edges->cmp = (int (*)(void *, void *))edge_cmp;
     468           0 :         new->prefixes = list_new();
     469           0 :         new->prefixes->cmp = (int (*)(void *, void *))subnet_cmp;
     470           0 :         vertices_add(&ted->vertices, new);
     471             : 
     472           0 :         return new;
     473             : }
     474             : 
     475           0 : void ls_vertex_del(struct ls_ted *ted, struct ls_vertex *vertex)
     476             : {
     477           0 :         struct listnode *node, *nnode;
     478           0 :         struct ls_edge *edge;
     479           0 :         struct ls_subnet *subnet;
     480             : 
     481           0 :         if (!ted || !vertex)
     482             :                 return;
     483             : 
     484             :         /* Remove outgoing Edges and list */
     485           0 :         for (ALL_LIST_ELEMENTS(vertex->outgoing_edges, node, nnode, edge))
     486           0 :                 ls_edge_del_all(ted, edge);
     487           0 :         list_delete(&vertex->outgoing_edges);
     488             : 
     489             :         /* Disconnect incoming Edges and remove list */
     490           0 :         for (ALL_LIST_ELEMENTS(vertex->incoming_edges, node, nnode, edge)) {
     491           0 :                 ls_disconnect(vertex, edge, false);
     492           0 :                 if (edge->source == NULL)
     493           0 :                         ls_edge_del_all(ted, edge);
     494             :         }
     495           0 :         list_delete(&vertex->incoming_edges);
     496             : 
     497             :         /* Remove subnet and list */
     498           0 :         for (ALL_LIST_ELEMENTS(vertex->prefixes, node, nnode, subnet))
     499           0 :                 ls_subnet_del_all(ted, subnet);
     500           0 :         list_delete(&vertex->prefixes);
     501             : 
     502             :         /* Then remove Vertex from Link State Data Base and free memory */
     503           0 :         vertices_del(&ted->vertices, vertex);
     504           0 :         XFREE(MTYPE_LS_DB, vertex);
     505           0 :         vertex = NULL;
     506             : }
     507             : 
     508           0 : void ls_vertex_del_all(struct ls_ted *ted, struct ls_vertex *vertex)
     509             : {
     510           0 :         if (!ted || !vertex)
     511             :                 return;
     512             : 
     513             :         /* First remove associated Link State Node */
     514           0 :         ls_node_del(vertex->node);
     515             : 
     516             :         /* Then, Vertex itself */
     517           0 :         ls_vertex_del(ted, vertex);
     518             : }
     519             : 
     520           0 : struct ls_vertex *ls_vertex_update(struct ls_ted *ted, struct ls_node *node)
     521             : {
     522           0 :         struct ls_vertex *old;
     523             : 
     524           0 :         if (node == NULL)
     525             :                 return NULL;
     526             : 
     527           0 :         old = ls_find_vertex_by_id(ted, node->adv);
     528           0 :         if (old) {
     529           0 :                 if (!ls_node_same(old->node, node)) {
     530           0 :                         ls_node_del(old->node);
     531           0 :                         old->node = node;
     532             :                 }
     533           0 :                 old->status = UPDATE;
     534           0 :                 return old;
     535             :         }
     536             : 
     537           0 :         return ls_vertex_add(ted, node);
     538             : }
     539             : 
     540           0 : struct ls_vertex *ls_find_vertex_by_key(struct ls_ted *ted, const uint64_t key)
     541             : {
     542           0 :         struct ls_vertex vertex = {};
     543             : 
     544           0 :         if (key == 0)
     545             :                 return NULL;
     546             : 
     547           0 :         vertex.key = key;
     548           0 :         return vertices_find(&ted->vertices, &vertex);
     549             : }
     550             : 
     551           0 : struct ls_vertex *ls_find_vertex_by_id(struct ls_ted *ted,
     552             :                                        struct ls_node_id nid)
     553             : {
     554           0 :         struct ls_vertex vertex = {};
     555             : 
     556           0 :         vertex.key = 0;
     557           0 :         switch (nid.origin) {
     558           0 :         case OSPFv2:
     559             :         case STATIC:
     560             :         case DIRECT:
     561           0 :                 vertex.key =
     562           0 :                         ((uint64_t)ntohl(nid.id.ip.addr.s_addr)) & 0xffffffff;
     563           0 :                 break;
     564           0 :         case ISIS_L1:
     565             :         case ISIS_L2:
     566           0 :                 vertex.key = sysid_to_key(nid.id.iso.sys_id);
     567           0 :                 break;
     568             :         case UNKNOWN:
     569             :                 return NULL;
     570             :         }
     571             : 
     572           0 :         return vertices_find(&ted->vertices, &vertex);
     573             : }
     574             : 
     575           0 : int ls_vertex_same(struct ls_vertex *v1, struct ls_vertex *v2)
     576             : {
     577           0 :         if ((v1 && !v2) || (!v1 && v2))
     578             :                 return 0;
     579             : 
     580           0 :         if (!v1 && !v2)
     581             :                 return 1;
     582             : 
     583           0 :         if (v1->key != v2->key)
     584             :                 return 0;
     585             : 
     586           0 :         if (v1->node == v2->node)
     587             :                 return 1;
     588             : 
     589           0 :         return ls_node_same(v1->node, v2->node);
     590             : }
     591             : 
     592           0 : void ls_vertex_clean(struct ls_ted *ted, struct ls_vertex *vertex,
     593             :                      struct zclient *zclient)
     594             : {
     595           0 :         struct listnode *node, *nnode;
     596           0 :         struct ls_edge *edge;
     597           0 :         struct ls_subnet *subnet;
     598           0 :         struct ls_message msg;
     599             : 
     600             :         /* Remove Orphan Edge ... */
     601           0 :         for (ALL_LIST_ELEMENTS(vertex->outgoing_edges, node, nnode, edge)) {
     602           0 :                 if (edge->status == ORPHAN) {
     603           0 :                         if (zclient) {
     604           0 :                                 edge->status = DELETE;
     605           0 :                                 ls_edge2msg(&msg, edge);
     606           0 :                                 ls_send_msg(zclient, &msg, NULL);
     607             :                         }
     608           0 :                         ls_edge_del_all(ted, edge);
     609             :                 }
     610             :         }
     611           0 :         for (ALL_LIST_ELEMENTS(vertex->incoming_edges, node, nnode, edge)) {
     612           0 :                 if (edge->status == ORPHAN) {
     613           0 :                         if (zclient) {
     614           0 :                                 edge->status = DELETE;
     615           0 :                                 ls_edge2msg(&msg, edge);
     616           0 :                                 ls_send_msg(zclient, &msg, NULL);
     617             :                         }
     618           0 :                         ls_edge_del_all(ted, edge);
     619             :                 }
     620             :         }
     621             : 
     622             :         /* ... and Subnet from the Vertex */
     623           0 :         for (ALL_LIST_ELEMENTS(vertex->prefixes, node, nnode, subnet)) {
     624           0 :                 if (subnet->status == ORPHAN) {
     625           0 :                         if (zclient) {
     626           0 :                                 subnet->status = DELETE;
     627           0 :                                 ls_subnet2msg(&msg, subnet);
     628           0 :                                 ls_send_msg(zclient, &msg, NULL);
     629             :                         }
     630           0 :                         ls_subnet_del_all(ted, subnet);
     631             :                 }
     632             :         }
     633           0 : }
     634             : 
     635             : /**
     636             :  * Link State Edges management functions
     637             :  */
     638             : 
     639             : /**
     640             :  * This function allows to connect the Edge to the vertices present in the TED.
     641             :  * A temporary vertex that corresponds to the source of this Edge i.e. the
     642             :  * advertised router, is created if not found in the Data Base. If a Edge that
     643             :  * corresponds to the reverse path is found, the Edge is attached to the
     644             :  * destination vertex as destination and reverse Edge is attached to the source
     645             :  * vertex as source.
     646             :  *
     647             :  * @param ted   Link State Data Base
     648             :  * @param edge  Link State Edge to be attached
     649             :  */
     650           0 : static void ls_edge_connect_to(struct ls_ted *ted, struct ls_edge *edge)
     651             : {
     652           0 :         struct ls_vertex *vertex = NULL;
     653           0 :         struct ls_node *node;
     654           0 :         struct ls_edge *dst;
     655           0 :         const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
     656             : 
     657             :         /* First, search if there is a Vertex that correspond to the Node ID */
     658           0 :         vertex = ls_find_vertex_by_id(ted, edge->attributes->adv);
     659           0 :         if (vertex == NULL) {
     660             :                 /* Create a new temporary Node & Vertex if not found */
     661           0 :                 node = ls_node_new(edge->attributes->adv, inaddr_any,
     662             :                                    in6addr_any);
     663           0 :                 vertex = ls_vertex_add(ted, node);
     664             :         }
     665             :         /* and attach the edge as source to the vertex */
     666           0 :         listnode_add_sort_nodup(vertex->outgoing_edges, edge);
     667           0 :         edge->source = vertex;
     668             : 
     669             :         /* Then search if there is a reverse Edge */
     670           0 :         dst = ls_find_edge_by_destination(ted, edge->attributes);
     671             :         /* attach the destination edge to the vertex */
     672           0 :         if (dst) {
     673           0 :                 listnode_add_sort_nodup(vertex->incoming_edges, dst);
     674           0 :                 dst->destination = vertex;
     675             :                 /* and destination vertex to this edge */
     676           0 :                 vertex = dst->source;
     677           0 :                 listnode_add_sort_nodup(vertex->incoming_edges, edge);
     678           0 :                 edge->destination = vertex;
     679             :         }
     680           0 : }
     681             : 
     682           0 : static uint64_t get_edge_key(struct ls_attributes *attr, bool dst)
     683             : {
     684           0 :         uint64_t key = 0;
     685           0 :         struct ls_standard *std;
     686             : 
     687           0 :         if (!attr)
     688             :                 return key;
     689             : 
     690           0 :         std = &attr->standard;
     691             : 
     692           0 :         if (dst) {
     693             :                 /* Key is the IPv4 remote address */
     694           0 :                 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
     695           0 :                         key = ((uint64_t)ntohl(std->remote.s_addr))
     696             :                               & 0xffffffff;
     697             :                 /* or the 64 bits LSB of IPv6 remote address */
     698           0 :                 else if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
     699           0 :                         key = ((uint64_t)ntohl(std->remote6.s6_addr32[2]) << 32
     700           0 :                                | (uint64_t)ntohl(std->remote6.s6_addr32[3]));
     701             :                 /* of remote identifier if no IP addresses are defined */
     702           0 :                 else if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
     703           0 :                         key = (((uint64_t)std->remote_id) & 0xffffffff)
     704           0 :                               | ((uint64_t)std->local_id << 32);
     705             :         } else {
     706             :                 /* Key is the IPv4 local address */
     707           0 :                 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
     708           0 :                         key = ((uint64_t)ntohl(std->local.s_addr)) & 0xffffffff;
     709             :                 /* or the 64 bits LSB of IPv6 local address */
     710           0 :                 else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
     711           0 :                         key = ((uint64_t)ntohl(std->local6.s6_addr32[2]) << 32
     712           0 :                                | (uint64_t)ntohl(std->local6.s6_addr32[3]));
     713             :                 /* of local identifier if no IP addresses are defined */
     714           0 :                 else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
     715           0 :                         key = (((uint64_t)std->local_id) & 0xffffffff)
     716           0 :                               | ((uint64_t)std->remote_id << 32);
     717             :         }
     718             : 
     719             :         return key;
     720             : }
     721             : 
     722           0 : struct ls_edge *ls_edge_add(struct ls_ted *ted,
     723             :                             struct ls_attributes *attributes)
     724             : {
     725           0 :         struct ls_edge *new;
     726           0 :         uint64_t key = 0;
     727             : 
     728           0 :         if (attributes == NULL)
     729             :                 return NULL;
     730             : 
     731           0 :         key = get_edge_key(attributes, false);
     732           0 :         if (key == 0)
     733             :                 return NULL;
     734             : 
     735             :         /* Create Edge and add it to the TED */
     736           0 :         new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_edge));
     737             : 
     738           0 :         new->attributes = attributes;
     739           0 :         new->key = key;
     740           0 :         new->status = NEW;
     741           0 :         new->type = EDGE;
     742           0 :         edges_add(&ted->edges, new);
     743             : 
     744             :         /* Finally, connect Edge to Vertices */
     745           0 :         ls_edge_connect_to(ted, new);
     746             : 
     747           0 :         return new;
     748             : }
     749             : 
     750           0 : struct ls_edge *ls_find_edge_by_key(struct ls_ted *ted, const uint64_t key)
     751             : {
     752           0 :         struct ls_edge edge = {};
     753             : 
     754           0 :         if (key == 0)
     755             :                 return NULL;
     756             : 
     757           0 :         edge.key = key;
     758           0 :         return edges_find(&ted->edges, &edge);
     759             : }
     760             : 
     761           0 : struct ls_edge *ls_find_edge_by_source(struct ls_ted *ted,
     762             :                                        struct ls_attributes *attributes)
     763             : {
     764           0 :         struct ls_edge edge = {};
     765             : 
     766           0 :         if (attributes == NULL)
     767             :                 return NULL;
     768             : 
     769           0 :         edge.key = get_edge_key(attributes, false);
     770           0 :         if (edge.key == 0)
     771             :                 return NULL;
     772             : 
     773           0 :         return edges_find(&ted->edges, &edge);
     774             : }
     775             : 
     776           0 : struct ls_edge *ls_find_edge_by_destination(struct ls_ted *ted,
     777             :                                             struct ls_attributes *attributes)
     778             : {
     779           0 :         struct ls_edge edge = {};
     780             : 
     781           0 :         if (attributes == NULL)
     782             :                 return NULL;
     783             : 
     784           0 :         edge.key = get_edge_key(attributes, true);
     785           0 :         if (edge.key == 0)
     786             :                 return NULL;
     787             : 
     788           0 :         return edges_find(&ted->edges, &edge);
     789             : }
     790             : 
     791           0 : struct ls_edge *ls_edge_update(struct ls_ted *ted,
     792             :                                struct ls_attributes *attributes)
     793             : {
     794           0 :         struct ls_edge *old;
     795             : 
     796           0 :         if (attributes == NULL)
     797             :                 return NULL;
     798             : 
     799             :         /* First, search for an existing Edge */
     800           0 :         old = ls_find_edge_by_source(ted, attributes);
     801           0 :         if (old) {
     802             :                 /* Check if attributes are similar */
     803           0 :                 if (!ls_attributes_same(old->attributes, attributes)) {
     804           0 :                         ls_attributes_del(old->attributes);
     805           0 :                         old->attributes = attributes;
     806             :                 }
     807           0 :                 old->status = UPDATE;
     808           0 :                 return old;
     809             :         }
     810             : 
     811             :         /* If not found, add new Edge from the attributes */
     812           0 :         return ls_edge_add(ted, attributes);
     813             : }
     814             : 
     815           0 : int ls_edge_same(struct ls_edge *e1, struct ls_edge *e2)
     816             : {
     817           0 :         if ((e1 && !e2) || (!e1 && e2))
     818             :                 return 0;
     819             : 
     820           0 :         if (!e1 && !e2)
     821             :                 return 1;
     822             : 
     823           0 :         if (e1->key != e2->key)
     824             :                 return 0;
     825             : 
     826           0 :         if (e1->attributes == e2->attributes)
     827             :                 return 1;
     828             : 
     829           0 :         return ls_attributes_same(e1->attributes, e2->attributes);
     830             : }
     831             : 
     832           0 : void ls_edge_del(struct ls_ted *ted, struct ls_edge *edge)
     833             : {
     834           0 :         if (!ted || !edge)
     835             :                 return;
     836             : 
     837             :         /* Fist disconnect Edge from Vertices */
     838           0 :         ls_disconnect_edge(edge);
     839             :         /* Then remove it from the Data Base */
     840           0 :         edges_del(&ted->edges, edge);
     841           0 :         XFREE(MTYPE_LS_DB, edge);
     842             : }
     843             : 
     844           0 : void ls_edge_del_all(struct ls_ted *ted, struct ls_edge *edge)
     845             : {
     846           0 :         if (!ted || !edge)
     847             :                 return;
     848             : 
     849             :         /* Remove associated Link State Attributes */
     850           0 :         ls_attributes_del(edge->attributes);
     851             :         /* Then Edge itself */
     852           0 :         ls_edge_del(ted, edge);
     853             : }
     854             : 
     855             : /**
     856             :  * Link State Subnet Management functions.
     857             :  */
     858           0 : struct ls_subnet *ls_subnet_add(struct ls_ted *ted,
     859             :                                 struct ls_prefix *ls_pref)
     860             : {
     861           0 :         struct ls_subnet *new;
     862           0 :         struct ls_vertex *vertex;
     863           0 :         struct ls_node *node;
     864           0 :         const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
     865             : 
     866           0 :         if (ls_pref == NULL)
     867             :                 return NULL;
     868             : 
     869           0 :         new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_subnet));
     870           0 :         new->ls_pref = ls_pref;
     871           0 :         new->key = ls_pref->pref;
     872           0 :         new->status = NEW;
     873           0 :         new->type = SUBNET;
     874             : 
     875             :         /* Find Vertex */
     876           0 :         vertex = ls_find_vertex_by_id(ted, ls_pref->adv);
     877           0 :         if (vertex == NULL) {
     878             :                 /* Create a new temporary Node & Vertex if not found */
     879           0 :                 node = ls_node_new(ls_pref->adv, inaddr_any, in6addr_any);
     880           0 :                 vertex = ls_vertex_add(ted, node);
     881             :         }
     882             :         /* And attach the subnet to the corresponding Vertex */
     883           0 :         new->vertex = vertex;
     884           0 :         listnode_add_sort_nodup(vertex->prefixes, new);
     885             : 
     886           0 :         subnets_add(&ted->subnets, new);
     887             : 
     888           0 :         return new;
     889             : }
     890             : 
     891           0 : struct ls_subnet *ls_subnet_update(struct ls_ted *ted, struct ls_prefix *pref)
     892             : {
     893           0 :         struct ls_subnet *old;
     894             : 
     895           0 :         if (pref == NULL)
     896             :                 return NULL;
     897             : 
     898           0 :         old = ls_find_subnet(ted, pref->pref);
     899           0 :         if (old) {
     900           0 :                 if (!ls_prefix_same(old->ls_pref, pref)) {
     901           0 :                         ls_prefix_del(old->ls_pref);
     902           0 :                         old->ls_pref = pref;
     903             :                 }
     904           0 :                 old->status = UPDATE;
     905           0 :                 return old;
     906             :         }
     907             : 
     908           0 :         return ls_subnet_add(ted, pref);
     909             : }
     910             : 
     911           0 : int ls_subnet_same(struct ls_subnet *s1, struct ls_subnet *s2)
     912             : {
     913           0 :         if ((s1 && !s2) || (!s1 && s2))
     914             :                 return 0;
     915             : 
     916           0 :         if (!s1 && !s2)
     917             :                 return 1;
     918             : 
     919           0 :         if (!prefix_same(&s1->key, &s2->key))
     920             :                 return 0;
     921             : 
     922           0 :         if (s1->ls_pref == s2->ls_pref)
     923             :                 return 1;
     924             : 
     925           0 :         return ls_prefix_same(s1->ls_pref, s2->ls_pref);
     926             : }
     927             : 
     928           0 : void ls_subnet_del(struct ls_ted *ted, struct ls_subnet *subnet)
     929             : {
     930           0 :         if (!ted || !subnet)
     931             :                 return;
     932             : 
     933             :         /* First, disconnect Subnet from associated Vertex */
     934           0 :         listnode_delete(subnet->vertex->prefixes, subnet);
     935             :         /* Then delete Subnet */
     936           0 :         subnets_del(&ted->subnets, subnet);
     937           0 :         XFREE(MTYPE_LS_DB, subnet);
     938             : }
     939             : 
     940           0 : void ls_subnet_del_all(struct ls_ted *ted, struct ls_subnet *subnet)
     941             : {
     942           0 :         if (!ted || !subnet)
     943             :                 return;
     944             : 
     945             :         /* First, remove associated Link State Subnet */
     946           0 :         ls_prefix_del(subnet->ls_pref);
     947             :         /* Then, delete Subnet itself */
     948           0 :         ls_subnet_del(ted, subnet);
     949             : }
     950             : 
     951           0 : struct ls_subnet *ls_find_subnet(struct ls_ted *ted, const struct prefix prefix)
     952             : {
     953           0 :         struct ls_subnet subnet = {};
     954             : 
     955           0 :         subnet.key = prefix;
     956           0 :         return subnets_find(&ted->subnets, &subnet);
     957             : }
     958             : 
     959             : /**
     960             :  * Link State TED management functions
     961             :  */
     962           0 : struct ls_ted *ls_ted_new(const uint32_t key, const char *name,
     963             :                           uint32_t as_number)
     964             : {
     965           0 :         struct ls_ted *new;
     966             : 
     967           0 :         new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_ted));
     968             : 
     969             :         /* Set basic information for this ted */
     970           0 :         new->key = key;
     971           0 :         new->as_number = as_number;
     972           0 :         strlcpy(new->name, name, MAX_NAME_LENGTH);
     973             : 
     974             :         /* Initialize the various RB tree */
     975           0 :         vertices_init(&new->vertices);
     976           0 :         edges_init(&new->edges);
     977           0 :         subnets_init(&new->subnets);
     978             : 
     979           0 :         return new;
     980             : }
     981             : 
     982           0 : void ls_ted_del(struct ls_ted *ted)
     983             : {
     984           0 :         if (ted == NULL)
     985             :                 return;
     986             : 
     987             :         /* Check that TED is empty */
     988           0 :         if (vertices_count(&ted->vertices) || edges_count(&ted->edges)
     989           0 :             || subnets_count(&ted->subnets))
     990             :                 return;
     991             : 
     992             :         /* Release RB Tree */
     993           0 :         vertices_fini(&ted->vertices);
     994           0 :         edges_fini(&ted->edges);
     995           0 :         subnets_fini(&ted->subnets);
     996             : 
     997           0 :         XFREE(MTYPE_LS_DB, ted);
     998             : }
     999             : 
    1000           0 : void ls_ted_del_all(struct ls_ted **ted)
    1001             : {
    1002           0 :         struct ls_vertex *vertex;
    1003           0 :         struct ls_edge *edge;
    1004           0 :         struct ls_subnet *subnet;
    1005             : 
    1006           0 :         if (*ted == NULL)
    1007             :                 return;
    1008             : 
    1009             :         /* First remove Vertices, Edges and Subnets and associated Link State */
    1010           0 :         frr_each_safe (vertices, &(*ted)->vertices, vertex)
    1011           0 :                 ls_vertex_del_all(*ted, vertex);
    1012           0 :         frr_each_safe (edges, &(*ted)->edges, edge)
    1013           0 :                 ls_edge_del_all(*ted, edge);
    1014           0 :         frr_each_safe (subnets, &(*ted)->subnets, subnet)
    1015           0 :                 ls_subnet_del_all(*ted, subnet);
    1016             : 
    1017             :         /* then remove TED itself */
    1018           0 :         ls_ted_del(*ted);
    1019           0 :         *ted = NULL;
    1020             : }
    1021             : 
    1022           0 : void ls_ted_clean(struct ls_ted *ted)
    1023             : {
    1024           0 :         struct ls_vertex *vertex;
    1025           0 :         struct ls_edge *edge;
    1026           0 :         struct ls_subnet *subnet;
    1027             : 
    1028           0 :         if (ted == NULL)
    1029             :                 return;
    1030             : 
    1031             :         /* First, start with Vertices */
    1032           0 :         frr_each_safe (vertices, &ted->vertices, vertex)
    1033           0 :                 if (vertex->status == ORPHAN)
    1034           0 :                         ls_vertex_del_all(ted, vertex);
    1035             : 
    1036             :         /* Then Edges */
    1037           0 :         frr_each_safe (edges, &ted->edges, edge)
    1038           0 :                 if (edge->status == ORPHAN)
    1039           0 :                         ls_edge_del_all(ted, edge);
    1040             : 
    1041             :         /* and Subnets */
    1042           0 :         frr_each_safe (subnets, &ted->subnets, subnet)
    1043           0 :                 if (subnet->status == ORPHAN)
    1044           0 :                         ls_subnet_del_all(ted, subnet);
    1045             : 
    1046             : }
    1047             : 
    1048           0 : void ls_connect(struct ls_vertex *vertex, struct ls_edge *edge, bool source)
    1049             : {
    1050           0 :         if (vertex == NULL || edge == NULL)
    1051             :                 return;
    1052             : 
    1053           0 :         if (source) {
    1054           0 :                 listnode_add_sort_nodup(vertex->outgoing_edges, edge);
    1055           0 :                 edge->source = vertex;
    1056             :         } else {
    1057           0 :                 listnode_add_sort_nodup(vertex->incoming_edges, edge);
    1058           0 :                 edge->destination = vertex;
    1059             :         }
    1060             : }
    1061             : 
    1062           0 : void ls_disconnect(struct ls_vertex *vertex, struct ls_edge *edge, bool source)
    1063             : {
    1064             : 
    1065           0 :         if (vertex == NULL || edge == NULL)
    1066             :                 return;
    1067             : 
    1068           0 :         if (source) {
    1069           0 :                 listnode_delete(vertex->outgoing_edges, edge);
    1070           0 :                 edge->source = NULL;
    1071             :         } else {
    1072           0 :                 listnode_delete(vertex->incoming_edges, edge);
    1073           0 :                 edge->destination = NULL;
    1074             :         }
    1075             : }
    1076             : 
    1077           0 : void ls_connect_vertices(struct ls_vertex *src, struct ls_vertex *dst,
    1078             :                          struct ls_edge *edge)
    1079             : {
    1080           0 :         if (edge == NULL)
    1081             :                 return;
    1082             : 
    1083           0 :         edge->source = src;
    1084           0 :         edge->destination = dst;
    1085             : 
    1086           0 :         if (src != NULL)
    1087           0 :                 listnode_add_sort_nodup(src->outgoing_edges, edge);
    1088             : 
    1089           0 :         if (dst != NULL)
    1090           0 :                 listnode_add_sort_nodup(dst->incoming_edges, edge);
    1091             : }
    1092             : 
    1093           0 : void ls_disconnect_edge(struct ls_edge *edge)
    1094             : {
    1095           0 :         if (edge == NULL)
    1096             :                 return;
    1097             : 
    1098           0 :         ls_disconnect(edge->source, edge, true);
    1099           0 :         ls_disconnect(edge->destination, edge, false);
    1100             : 
    1101             :         /* Mark this Edge as ORPHAN for future cleanup */
    1102           0 :         edge->status = ORPHAN;
    1103             : }
    1104             : 
    1105             : /**
    1106             :  * Link State Message management functions
    1107             :  */
    1108             : 
    1109           0 : int ls_register(struct zclient *zclient, bool server)
    1110             : {
    1111           0 :         int rc;
    1112             : 
    1113           0 :         if (server)
    1114           0 :                 rc = zclient_register_opaque(zclient, LINK_STATE_SYNC);
    1115             :         else
    1116           0 :                 rc = zclient_register_opaque(zclient, LINK_STATE_UPDATE);
    1117             : 
    1118           0 :         return rc;
    1119             : }
    1120             : 
    1121           0 : int ls_unregister(struct zclient *zclient, bool server)
    1122             : {
    1123           0 :         int rc;
    1124             : 
    1125           0 :         if (server)
    1126           0 :                 rc = zclient_unregister_opaque(zclient, LINK_STATE_SYNC);
    1127             :         else
    1128           0 :                 rc = zclient_unregister_opaque(zclient, LINK_STATE_UPDATE);
    1129             : 
    1130           0 :         return rc;
    1131             : }
    1132             : 
    1133           0 : int ls_request_sync(struct zclient *zclient)
    1134             : {
    1135           0 :         struct stream *s;
    1136           0 :         uint16_t flags = 0;
    1137             : 
    1138             :         /* Check buffer size */
    1139           0 :         if (STREAM_SIZE(zclient->obuf)
    1140             :             < (ZEBRA_HEADER_SIZE + 3 * sizeof(uint32_t)))
    1141             :                 return -1;
    1142             : 
    1143           0 :         s = zclient->obuf;
    1144           0 :         stream_reset(s);
    1145             : 
    1146           0 :         zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
    1147             : 
    1148             :         /* Set type and flags */
    1149           0 :         stream_putl(s, LINK_STATE_SYNC);
    1150           0 :         stream_putw(s, flags);
    1151             :         /* Send destination client info */
    1152           0 :         stream_putc(s, zclient->redist_default);
    1153           0 :         stream_putw(s, zclient->instance);
    1154           0 :         stream_putl(s, zclient->session_id);
    1155             : 
    1156             :         /* Put length into the header at the start of the stream. */
    1157           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1158             : 
    1159           0 :         return zclient_send_message(zclient);
    1160             : }
    1161             : 
    1162           0 : static struct ls_node *ls_parse_node(struct stream *s)
    1163             : {
    1164           0 :         struct ls_node *node;
    1165           0 :         size_t len;
    1166             : 
    1167           0 :         node = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_node));
    1168             : 
    1169           0 :         STREAM_GET(&node->adv, s, sizeof(struct ls_node_id));
    1170           0 :         STREAM_GETW(s, node->flags);
    1171           0 :         if (CHECK_FLAG(node->flags, LS_NODE_NAME)) {
    1172           0 :                 STREAM_GETC(s, len);
    1173           0 :                 STREAM_GET(node->name, s, len);
    1174             :         }
    1175           0 :         if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
    1176           0 :                 node->router_id.s_addr = stream_get_ipv4(s);
    1177           0 :         if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
    1178           0 :                 STREAM_GET(&node->router_id6, s, IPV6_MAX_BYTELEN);
    1179           0 :         if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
    1180           0 :                 STREAM_GETC(s, node->node_flag);
    1181           0 :         if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
    1182           0 :                 STREAM_GETC(s, node->type);
    1183           0 :         if (CHECK_FLAG(node->flags, LS_NODE_AS_NUMBER))
    1184           0 :                 STREAM_GETL(s, node->as_number);
    1185           0 :         if (CHECK_FLAG(node->flags, LS_NODE_SR)) {
    1186           0 :                 STREAM_GETL(s, node->srgb.lower_bound);
    1187           0 :                 STREAM_GETL(s, node->srgb.range_size);
    1188           0 :                 STREAM_GETC(s, node->srgb.flag);
    1189           0 :                 STREAM_GET(node->algo, s, 2);
    1190             :         }
    1191           0 :         if (CHECK_FLAG(node->flags, LS_NODE_SRLB)) {
    1192           0 :                 STREAM_GETL(s, node->srlb.lower_bound);
    1193           0 :                 STREAM_GETL(s, node->srlb.range_size);
    1194             :         }
    1195           0 :         if (CHECK_FLAG(node->flags, LS_NODE_MSD))
    1196           0 :                 STREAM_GETC(s, node->msd);
    1197             : 
    1198             :         return node;
    1199             : 
    1200           0 : stream_failure:
    1201           0 :         zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__);
    1202           0 :         XFREE(MTYPE_LS_DB, node);
    1203           0 :         return NULL;
    1204             : }
    1205             : 
    1206           0 : static struct ls_attributes *ls_parse_attributes(struct stream *s)
    1207             : {
    1208           0 :         struct ls_attributes *attr;
    1209           0 :         size_t len;
    1210             : 
    1211           0 :         attr = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_attributes));
    1212           0 :         attr->srlgs = NULL;
    1213             : 
    1214           0 :         STREAM_GET(&attr->adv, s, sizeof(struct ls_node_id));
    1215           0 :         STREAM_GETL(s, attr->flags);
    1216           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NAME)) {
    1217           0 :                 STREAM_GETC(s, len);
    1218           0 :                 STREAM_GET(attr->name, s, len);
    1219             :         }
    1220           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_METRIC))
    1221           0 :                 STREAM_GETL(s, attr->metric);
    1222           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
    1223           0 :                 STREAM_GETL(s, attr->standard.te_metric);
    1224           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
    1225           0 :                 STREAM_GETL(s, attr->standard.admin_group);
    1226           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
    1227           0 :                 attr->standard.local.s_addr = stream_get_ipv4(s);
    1228           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
    1229           0 :                 attr->standard.remote.s_addr = stream_get_ipv4(s);
    1230           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
    1231           0 :                 STREAM_GET(&attr->standard.local6, s, IPV6_MAX_BYTELEN);
    1232           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
    1233           0 :                 STREAM_GET(&attr->standard.remote6, s, IPV6_MAX_BYTELEN);
    1234           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
    1235           0 :                 STREAM_GETL(s, attr->standard.local_id);
    1236           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
    1237           0 :                 STREAM_GETL(s, attr->standard.remote_id);
    1238           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
    1239           0 :                 STREAM_GETF(s, attr->standard.max_bw);
    1240           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
    1241           0 :                 STREAM_GETF(s, attr->standard.max_rsv_bw);
    1242           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW))
    1243           0 :                 for (len = 0; len < MAX_CLASS_TYPE; len++)
    1244           0 :                         STREAM_GETF(s, attr->standard.unrsv_bw[len]);
    1245           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
    1246           0 :                 STREAM_GETL(s, attr->standard.remote_as);
    1247           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
    1248           0 :                 attr->standard.remote_addr.s_addr = stream_get_ipv4(s);
    1249           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
    1250           0 :                 STREAM_GET(&attr->standard.remote_addr6, s, IPV6_MAX_BYTELEN);
    1251           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
    1252           0 :                 STREAM_GETL(s, attr->extended.delay);
    1253           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
    1254           0 :                 STREAM_GETL(s, attr->extended.min_delay);
    1255           0 :                 STREAM_GETL(s, attr->extended.max_delay);
    1256             :         }
    1257           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
    1258           0 :                 STREAM_GETL(s, attr->extended.jitter);
    1259           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
    1260           0 :                 STREAM_GETL(s, attr->extended.pkt_loss);
    1261           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
    1262           0 :                 STREAM_GETF(s, attr->extended.ava_bw);
    1263           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
    1264           0 :                 STREAM_GETF(s, attr->extended.rsv_bw);
    1265           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
    1266           0 :                 STREAM_GETF(s, attr->extended.used_bw);
    1267           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
    1268           0 :                 STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
    1269           0 :                 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
    1270           0 :                 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
    1271           0 :                 attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr =
    1272           0 :                         stream_get_ipv4(s);
    1273             :         }
    1274           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
    1275           0 :                 STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
    1276           0 :                 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
    1277           0 :                 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
    1278           0 :                 attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr =
    1279           0 :                         stream_get_ipv4(s);
    1280             :         }
    1281           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
    1282           0 :                 STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
    1283           0 :                 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
    1284           0 :                 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
    1285           0 :                 STREAM_GET(attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid, s,
    1286             :                            ISO_SYS_ID_LEN);
    1287             :         }
    1288           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
    1289           0 :                 STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
    1290           0 :                 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
    1291           0 :                 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
    1292           0 :                 STREAM_GET(attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid, s,
    1293             :                            ISO_SYS_ID_LEN);
    1294             :         }
    1295           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
    1296           0 :                 STREAM_GETC(s, len);
    1297           0 :                 attr->srlgs = XCALLOC(MTYPE_LS_DB, len*sizeof(uint32_t));
    1298           0 :                 attr->srlg_len = len;
    1299           0 :                 for (len = 0; len < attr->srlg_len; len++)
    1300           0 :                         STREAM_GETL(s, attr->srlgs[len]);
    1301             :         }
    1302             : 
    1303             :         return attr;
    1304             : 
    1305           0 : stream_failure:
    1306           0 :         zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
    1307             :                  __func__);
    1308             :         /* Clean memory allocation */
    1309           0 :         if (attr->srlgs != NULL)
    1310           0 :                 XFREE(MTYPE_LS_DB, attr->srlgs);
    1311           0 :         XFREE(MTYPE_LS_DB, attr);
    1312           0 :         return NULL;
    1313             : 
    1314             : }
    1315             : 
    1316           0 : static struct ls_prefix *ls_parse_prefix(struct stream *s)
    1317             : {
    1318           0 :         struct ls_prefix *ls_pref;
    1319           0 :         size_t len;
    1320             : 
    1321           0 :         ls_pref = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix));
    1322             : 
    1323           0 :         STREAM_GET(&ls_pref->adv, s, sizeof(struct ls_node_id));
    1324           0 :         STREAM_GETW(s, ls_pref->flags);
    1325           0 :         STREAM_GETC(s, ls_pref->pref.family);
    1326           0 :         STREAM_GETW(s, ls_pref->pref.prefixlen);
    1327           0 :         len = prefix_blen(&ls_pref->pref);
    1328           0 :         STREAM_GET(&ls_pref->pref.u.prefix, s, len);
    1329           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_IGP_FLAG))
    1330           0 :                 STREAM_GETC(s, ls_pref->igp_flag);
    1331           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_ROUTE_TAG))
    1332           0 :                 STREAM_GETL(s, ls_pref->route_tag);
    1333           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_EXTENDED_TAG))
    1334           0 :                 STREAM_GETQ(s, ls_pref->extended_tag);
    1335           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
    1336           0 :                 STREAM_GETL(s, ls_pref->metric);
    1337           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)) {
    1338           0 :                 STREAM_GETL(s, ls_pref->sr.sid);
    1339           0 :                 STREAM_GETC(s, ls_pref->sr.sid_flag);
    1340           0 :                 STREAM_GETC(s, ls_pref->sr.algo);
    1341             :         }
    1342             : 
    1343             :         return ls_pref;
    1344             : 
    1345           0 : stream_failure:
    1346           0 :         zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__);
    1347           0 :         XFREE(MTYPE_LS_DB, ls_pref);
    1348           0 :         return NULL;
    1349             : }
    1350             : 
    1351           0 : struct ls_message *ls_parse_msg(struct stream *s)
    1352             : {
    1353           0 :         struct ls_message *msg;
    1354             : 
    1355           0 :         msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
    1356             : 
    1357             :         /* Read LS Message header */
    1358           0 :         STREAM_GETC(s, msg->event);
    1359           0 :         STREAM_GETC(s, msg->type);
    1360             : 
    1361             :         /* Read Message Payload */
    1362           0 :         switch (msg->type) {
    1363           0 :         case LS_MSG_TYPE_NODE:
    1364           0 :                 msg->data.node = ls_parse_node(s);
    1365           0 :                 break;
    1366           0 :         case LS_MSG_TYPE_ATTRIBUTES:
    1367           0 :                 STREAM_GET(&msg->remote_id, s, sizeof(struct ls_node_id));
    1368           0 :                 msg->data.attr = ls_parse_attributes(s);
    1369           0 :                 break;
    1370           0 :         case LS_MSG_TYPE_PREFIX:
    1371           0 :                 msg->data.prefix = ls_parse_prefix(s);
    1372           0 :                 break;
    1373           0 :         default:
    1374           0 :                 zlog_err("Unsupported Payload");
    1375           0 :                 goto stream_failure;
    1376             :         }
    1377             : 
    1378           0 :         if (msg->data.node == NULL || msg->data.attr == NULL
    1379             :             || msg->data.prefix == NULL)
    1380           0 :                 goto stream_failure;
    1381             : 
    1382             :         return msg;
    1383             : 
    1384           0 : stream_failure:
    1385           0 :         zlog_err("LS(%s): Could not parse LS message. Abort!", __func__);
    1386           0 :         XFREE(MTYPE_LS_DB, msg);
    1387           0 :         return NULL;
    1388             : }
    1389             : 
    1390           0 : static int ls_format_node(struct stream *s, struct ls_node *node)
    1391             : {
    1392           0 :         size_t len;
    1393             : 
    1394             :         /* Push Advertise node information first */
    1395           0 :         stream_put(s, &node->adv, sizeof(struct ls_node_id));
    1396             : 
    1397             :         /* Push Flags & Origin then Node information if there are present */
    1398           0 :         stream_putw(s, node->flags);
    1399           0 :         if (CHECK_FLAG(node->flags, LS_NODE_NAME)) {
    1400           0 :                 len = strlen(node->name);
    1401           0 :                 stream_putc(s, len + 1);
    1402           0 :                 stream_put(s, node->name, len);
    1403           0 :                 stream_putc(s, '\0');
    1404             :         }
    1405           0 :         if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
    1406           0 :                 stream_put_ipv4(s, node->router_id.s_addr);
    1407           0 :         if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
    1408           0 :                 stream_put(s, &node->router_id6, IPV6_MAX_BYTELEN);
    1409           0 :         if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
    1410           0 :                 stream_putc(s, node->node_flag);
    1411           0 :         if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
    1412           0 :                 stream_putc(s, node->type);
    1413           0 :         if (CHECK_FLAG(node->flags, LS_NODE_AS_NUMBER))
    1414           0 :                 stream_putl(s, node->as_number);
    1415           0 :         if (CHECK_FLAG(node->flags, LS_NODE_SR)) {
    1416           0 :                 stream_putl(s, node->srgb.lower_bound);
    1417           0 :                 stream_putl(s, node->srgb.range_size);
    1418           0 :                 stream_putc(s, node->srgb.flag);
    1419           0 :                 stream_put(s, node->algo, 2);
    1420             :         }
    1421           0 :         if (CHECK_FLAG(node->flags, LS_NODE_SRLB)) {
    1422           0 :                 stream_putl(s, node->srlb.lower_bound);
    1423           0 :                 stream_putl(s, node->srlb.range_size);
    1424             :         }
    1425           0 :         if (CHECK_FLAG(node->flags, LS_NODE_MSD))
    1426           0 :                 stream_putc(s, node->msd);
    1427             : 
    1428           0 :         return 0;
    1429             : }
    1430             : 
    1431           0 : static int ls_format_attributes(struct stream *s, struct ls_attributes *attr)
    1432             : {
    1433           0 :         size_t len;
    1434             : 
    1435             :         /* Push Advertise node information first */
    1436           0 :         stream_put(s, &attr->adv, sizeof(struct ls_node_id));
    1437             : 
    1438             :         /* Push Flags & Origin then LS attributes if there are present */
    1439           0 :         stream_putl(s, attr->flags);
    1440           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NAME)) {
    1441           0 :                 len = strlen(attr->name);
    1442           0 :                 stream_putc(s, len + 1);
    1443           0 :                 stream_put(s, attr->name, len);
    1444           0 :                 stream_putc(s, '\0');
    1445             :         }
    1446           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_METRIC))
    1447           0 :                 stream_putl(s, attr->metric);
    1448           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
    1449           0 :                 stream_putl(s, attr->standard.te_metric);
    1450           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
    1451           0 :                 stream_putl(s, attr->standard.admin_group);
    1452           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
    1453           0 :                 stream_put_ipv4(s, attr->standard.local.s_addr);
    1454           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
    1455           0 :                 stream_put_ipv4(s, attr->standard.remote.s_addr);
    1456           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
    1457           0 :                 stream_put(s, &attr->standard.local6, IPV6_MAX_BYTELEN);
    1458           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
    1459           0 :                 stream_put(s, &attr->standard.remote6, IPV6_MAX_BYTELEN);
    1460           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
    1461           0 :                 stream_putl(s, attr->standard.local_id);
    1462           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
    1463           0 :                 stream_putl(s, attr->standard.remote_id);
    1464           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
    1465           0 :                 stream_putf(s, attr->standard.max_bw);
    1466           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
    1467           0 :                 stream_putf(s, attr->standard.max_rsv_bw);
    1468           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW))
    1469           0 :                 for (len = 0; len < MAX_CLASS_TYPE; len++)
    1470           0 :                         stream_putf(s, attr->standard.unrsv_bw[len]);
    1471           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
    1472           0 :                 stream_putl(s, attr->standard.remote_as);
    1473           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
    1474           0 :                 stream_put_ipv4(s, attr->standard.remote_addr.s_addr);
    1475           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
    1476           0 :                 stream_put(s, &attr->standard.remote_addr6, IPV6_MAX_BYTELEN);
    1477           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
    1478           0 :                 stream_putl(s, attr->extended.delay);
    1479           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
    1480           0 :                 stream_putl(s, attr->extended.min_delay);
    1481           0 :                 stream_putl(s, attr->extended.max_delay);
    1482             :         }
    1483           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
    1484           0 :                 stream_putl(s, attr->extended.jitter);
    1485           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
    1486           0 :                 stream_putl(s, attr->extended.pkt_loss);
    1487           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
    1488           0 :                 stream_putf(s, attr->extended.ava_bw);
    1489           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
    1490           0 :                 stream_putf(s, attr->extended.rsv_bw);
    1491           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
    1492           0 :                 stream_putf(s, attr->extended.used_bw);
    1493           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
    1494           0 :                 stream_putl(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
    1495           0 :                 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
    1496           0 :                 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
    1497           0 :                 stream_put_ipv4(
    1498             :                         s, attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr);
    1499             :         }
    1500           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
    1501           0 :                 stream_putl(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
    1502           0 :                 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
    1503           0 :                 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
    1504           0 :                 stream_put_ipv4(
    1505             :                         s, attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr);
    1506             :         }
    1507           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
    1508           0 :                 stream_putl(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
    1509           0 :                 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
    1510           0 :                 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
    1511           0 :                 stream_put(s, attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid,
    1512             :                            ISO_SYS_ID_LEN);
    1513             :         }
    1514           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
    1515           0 :                 stream_putl(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
    1516           0 :                 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
    1517           0 :                 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
    1518           0 :                 stream_put(s, attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid,
    1519             :                            ISO_SYS_ID_LEN);
    1520             :         }
    1521           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
    1522           0 :                 stream_putc(s, attr->srlg_len);
    1523           0 :                 for (len = 0; len < attr->srlg_len; len++)
    1524           0 :                         stream_putl(s, attr->srlgs[len]);
    1525             :         }
    1526             : 
    1527           0 :         return 0;
    1528             : }
    1529             : 
    1530           0 : static int ls_format_prefix(struct stream *s, struct ls_prefix *ls_pref)
    1531             : {
    1532           0 :         size_t len;
    1533             : 
    1534             :         /* Push Advertise node information first */
    1535           0 :         stream_put(s, &ls_pref->adv, sizeof(struct ls_node_id));
    1536             : 
    1537             :         /* Push Flags, Origin & Prefix then information if there are present */
    1538           0 :         stream_putw(s, ls_pref->flags);
    1539           0 :         stream_putc(s, ls_pref->pref.family);
    1540           0 :         stream_putw(s, ls_pref->pref.prefixlen);
    1541           0 :         len = prefix_blen(&ls_pref->pref);
    1542           0 :         stream_put(s, &ls_pref->pref.u.prefix, len);
    1543           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_IGP_FLAG))
    1544           0 :                 stream_putc(s, ls_pref->igp_flag);
    1545           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_ROUTE_TAG))
    1546           0 :                 stream_putl(s, ls_pref->route_tag);
    1547           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_EXTENDED_TAG))
    1548           0 :                 stream_putq(s, ls_pref->extended_tag);
    1549           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
    1550           0 :                 stream_putl(s, ls_pref->metric);
    1551           0 :         if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)) {
    1552           0 :                 stream_putl(s, ls_pref->sr.sid);
    1553           0 :                 stream_putc(s, ls_pref->sr.sid_flag);
    1554           0 :                 stream_putc(s, ls_pref->sr.algo);
    1555             :         }
    1556             : 
    1557           0 :         return 0;
    1558             : }
    1559             : 
    1560           0 : static int ls_format_msg(struct stream *s, struct ls_message *msg)
    1561             : {
    1562             : 
    1563             :         /* Prepare Link State header */
    1564           0 :         stream_putc(s, msg->event);
    1565           0 :         stream_putc(s, msg->type);
    1566             : 
    1567             :         /* Add Message Payload */
    1568           0 :         switch (msg->type) {
    1569           0 :         case LS_MSG_TYPE_NODE:
    1570           0 :                 return ls_format_node(s, msg->data.node);
    1571           0 :         case LS_MSG_TYPE_ATTRIBUTES:
    1572             :                 /* Add remote node first */
    1573           0 :                 stream_put(s, &msg->remote_id, sizeof(struct ls_node_id));
    1574           0 :                 return ls_format_attributes(s, msg->data.attr);
    1575           0 :         case LS_MSG_TYPE_PREFIX:
    1576           0 :                 return ls_format_prefix(s, msg->data.prefix);
    1577           0 :         default:
    1578           0 :                 zlog_warn("Unsupported Payload");
    1579           0 :                 break;
    1580             :         }
    1581             : 
    1582           0 :         return -1;
    1583             : }
    1584             : 
    1585           0 : int ls_send_msg(struct zclient *zclient, struct ls_message *msg,
    1586             :                 struct zapi_opaque_reg_info *dst)
    1587             : {
    1588           0 :         struct stream *s;
    1589           0 :         uint16_t flags = 0;
    1590             : 
    1591             :         /* Check if we have a valid message */
    1592           0 :         if (msg->event == LS_MSG_EVENT_UNDEF)
    1593             :                 return -1;
    1594             : 
    1595             :         /* Check buffer size */
    1596           0 :         if (STREAM_SIZE(zclient->obuf) <
    1597             :             (ZEBRA_HEADER_SIZE + sizeof(uint32_t) + sizeof(msg)))
    1598             :                 return -1;
    1599             : 
    1600           0 :         s = zclient->obuf;
    1601           0 :         stream_reset(s);
    1602             : 
    1603           0 :         zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
    1604             : 
    1605             :         /* Set sub-type, flags and destination for unicast message */
    1606           0 :         stream_putl(s, LINK_STATE_UPDATE);
    1607           0 :         if (dst != NULL) {
    1608           0 :                 SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
    1609           0 :                 stream_putw(s, flags);
    1610             :                 /* Send destination client info */
    1611           0 :                 stream_putc(s, dst->proto);
    1612           0 :                 stream_putw(s, dst->instance);
    1613           0 :                 stream_putl(s, dst->session_id);
    1614             :         } else {
    1615           0 :                 stream_putw(s, flags);
    1616             :         }
    1617             : 
    1618             :         /* Format Link State message */
    1619           0 :         if (ls_format_msg(s, msg) < 0) {
    1620           0 :                 stream_reset(s);
    1621           0 :                 return -1;
    1622             :         }
    1623             : 
    1624             :         /* Put length into the header at the start of the stream. */
    1625           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1626             : 
    1627           0 :         return zclient_send_message(zclient);
    1628             : }
    1629           0 : struct ls_message *ls_vertex2msg(struct ls_message *msg,
    1630             :                                  struct ls_vertex *vertex)
    1631             : {
    1632             :         /* Allocate space if needed */
    1633           0 :         if (msg == NULL)
    1634           0 :                 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
    1635             :         else
    1636           0 :                 memset(msg, 0, sizeof(*msg));
    1637             : 
    1638           0 :         msg->type = LS_MSG_TYPE_NODE;
    1639           0 :         switch (vertex->status) {
    1640           0 :         case NEW:
    1641           0 :                 msg->event = LS_MSG_EVENT_ADD;
    1642           0 :                 break;
    1643           0 :         case UPDATE:
    1644           0 :                 msg->event = LS_MSG_EVENT_UPDATE;
    1645           0 :                 break;
    1646           0 :         case DELETE:
    1647           0 :                 msg->event = LS_MSG_EVENT_DELETE;
    1648           0 :                 break;
    1649           0 :         case SYNC:
    1650           0 :                 msg->event = LS_MSG_EVENT_SYNC;
    1651           0 :                 break;
    1652           0 :         case UNSET:
    1653             :         case ORPHAN:
    1654           0 :                 msg->event = LS_MSG_EVENT_UNDEF;
    1655           0 :                 break;
    1656             :         }
    1657           0 :         msg->data.node = vertex->node;
    1658           0 :         msg->remote_id.origin = UNKNOWN;
    1659             : 
    1660           0 :         return msg;
    1661             : }
    1662             : 
    1663           0 : struct ls_message *ls_edge2msg(struct ls_message *msg, struct ls_edge *edge)
    1664             : {
    1665             :         /* Allocate space if needed */
    1666           0 :         if (msg == NULL)
    1667           0 :                 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
    1668             :         else
    1669           0 :                 memset(msg, 0, sizeof(*msg));
    1670             : 
    1671           0 :         msg->type = LS_MSG_TYPE_ATTRIBUTES;
    1672           0 :         switch (edge->status) {
    1673           0 :         case NEW:
    1674           0 :                 msg->event = LS_MSG_EVENT_ADD;
    1675           0 :                 break;
    1676           0 :         case UPDATE:
    1677           0 :                 msg->event = LS_MSG_EVENT_UPDATE;
    1678           0 :                 break;
    1679           0 :         case DELETE:
    1680           0 :                 msg->event = LS_MSG_EVENT_DELETE;
    1681           0 :                 break;
    1682           0 :         case SYNC:
    1683           0 :                 msg->event = LS_MSG_EVENT_SYNC;
    1684           0 :                 break;
    1685           0 :         case UNSET:
    1686             :         case ORPHAN:
    1687           0 :                 msg->event = LS_MSG_EVENT_UNDEF;
    1688           0 :                 break;
    1689             :         }
    1690           0 :         msg->data.attr = edge->attributes;
    1691           0 :         if (edge->destination != NULL)
    1692           0 :                 msg->remote_id = edge->destination->node->adv;
    1693             :         else
    1694           0 :                 msg->remote_id.origin = UNKNOWN;
    1695             : 
    1696           0 :         return msg;
    1697             : }
    1698             : 
    1699           0 : struct ls_message *ls_subnet2msg(struct ls_message *msg,
    1700             :                                  struct ls_subnet *subnet)
    1701             : {
    1702             :         /* Allocate space if needed */
    1703           0 :         if (msg == NULL)
    1704           0 :                 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
    1705             :         else
    1706           0 :                 memset(msg, 0, sizeof(*msg));
    1707             : 
    1708           0 :         msg->type = LS_MSG_TYPE_PREFIX;
    1709           0 :         switch (subnet->status) {
    1710           0 :         case NEW:
    1711           0 :                 msg->event = LS_MSG_EVENT_ADD;
    1712           0 :                 break;
    1713           0 :         case UPDATE:
    1714           0 :                 msg->event = LS_MSG_EVENT_UPDATE;
    1715           0 :                 break;
    1716           0 :         case DELETE:
    1717           0 :                 msg->event = LS_MSG_EVENT_DELETE;
    1718           0 :                 break;
    1719           0 :         case SYNC:
    1720           0 :                 msg->event = LS_MSG_EVENT_SYNC;
    1721           0 :                 break;
    1722           0 :         case UNSET:
    1723             :         case ORPHAN:
    1724           0 :                 msg->event = LS_MSG_EVENT_UNDEF;
    1725           0 :                 break;
    1726             :         }
    1727           0 :         msg->data.prefix = subnet->ls_pref;
    1728           0 :         msg->remote_id.origin = UNKNOWN;
    1729             : 
    1730           0 :         return msg;
    1731             : }
    1732             : 
    1733           0 : struct ls_vertex *ls_msg2vertex(struct ls_ted *ted, struct ls_message *msg,
    1734             :                                 bool delete)
    1735             : {
    1736           0 :         struct ls_node *node = (struct ls_node *)msg->data.node;
    1737           0 :         struct ls_vertex *vertex = NULL;
    1738             : 
    1739           0 :         switch (msg->event) {
    1740           0 :         case LS_MSG_EVENT_SYNC:
    1741           0 :                 vertex = ls_vertex_add(ted, node);
    1742           0 :                 if (vertex)
    1743           0 :                         vertex->status = SYNC;
    1744             :                 break;
    1745           0 :         case LS_MSG_EVENT_ADD:
    1746           0 :                 vertex = ls_vertex_add(ted, node);
    1747           0 :                 if (vertex)
    1748           0 :                         vertex->status = NEW;
    1749             :                 break;
    1750           0 :         case LS_MSG_EVENT_UPDATE:
    1751           0 :                 vertex = ls_vertex_update(ted, node);
    1752           0 :                 if (vertex)
    1753           0 :                         vertex->status = UPDATE;
    1754             :                 break;
    1755           0 :         case LS_MSG_EVENT_DELETE:
    1756           0 :                 vertex = ls_find_vertex_by_id(ted, node->adv);
    1757           0 :                 if (vertex) {
    1758           0 :                         if (delete)
    1759           0 :                                 ls_vertex_del_all(ted, vertex);
    1760             :                         else
    1761           0 :                                 vertex->status = DELETE;
    1762             :                 }
    1763             :                 break;
    1764             :         default:
    1765             :                 vertex = NULL;
    1766             :                 break;
    1767             :         }
    1768             : 
    1769           0 :         return vertex;
    1770             : }
    1771             : 
    1772           0 : struct ls_edge *ls_msg2edge(struct ls_ted *ted, struct ls_message *msg,
    1773             :                             bool delete)
    1774             : {
    1775           0 :         struct ls_attributes *attr = (struct ls_attributes *)msg->data.attr;
    1776           0 :         struct ls_edge *edge = NULL;
    1777             : 
    1778           0 :         switch (msg->event) {
    1779           0 :         case LS_MSG_EVENT_SYNC:
    1780           0 :                 edge = ls_edge_add(ted, attr);
    1781           0 :                 if (edge)
    1782           0 :                         edge->status = SYNC;
    1783             :                 break;
    1784           0 :         case LS_MSG_EVENT_ADD:
    1785           0 :                 edge = ls_edge_add(ted, attr);
    1786           0 :                 if (edge)
    1787           0 :                         edge->status = NEW;
    1788             :                 break;
    1789           0 :         case LS_MSG_EVENT_UPDATE:
    1790           0 :                 edge = ls_edge_update(ted, attr);
    1791           0 :                 if (edge)
    1792           0 :                         edge->status = UPDATE;
    1793             :                 break;
    1794           0 :         case LS_MSG_EVENT_DELETE:
    1795           0 :                 edge = ls_find_edge_by_source(ted, attr);
    1796           0 :                 if (edge) {
    1797           0 :                         if (delete) {
    1798           0 :                                 ls_edge_del_all(ted, edge);
    1799           0 :                                 edge = NULL;
    1800             :                         } else
    1801           0 :                                 edge->status = DELETE;
    1802             :                 }
    1803             :                 break;
    1804             :         default:
    1805             :                 edge = NULL;
    1806             :                 break;
    1807             :         }
    1808             : 
    1809           0 :         return edge;
    1810             : }
    1811             : 
    1812           0 : struct ls_subnet *ls_msg2subnet(struct ls_ted *ted, struct ls_message *msg,
    1813             :                                 bool delete)
    1814             : {
    1815           0 :         struct ls_prefix *pref = (struct ls_prefix *)msg->data.prefix;
    1816           0 :         struct ls_subnet *subnet = NULL;
    1817             : 
    1818           0 :         switch (msg->event) {
    1819           0 :         case LS_MSG_EVENT_SYNC:
    1820           0 :                 subnet = ls_subnet_add(ted, pref);
    1821           0 :                 if (subnet)
    1822           0 :                         subnet->status = SYNC;
    1823             :                 break;
    1824           0 :         case LS_MSG_EVENT_ADD:
    1825           0 :                 subnet = ls_subnet_add(ted, pref);
    1826           0 :                 if (subnet)
    1827           0 :                         subnet->status = NEW;
    1828             :                 break;
    1829           0 :         case LS_MSG_EVENT_UPDATE:
    1830           0 :                 subnet = ls_subnet_update(ted, pref);
    1831           0 :                 if (subnet)
    1832           0 :                         subnet->status = UPDATE;
    1833             :                 break;
    1834           0 :         case LS_MSG_EVENT_DELETE:
    1835           0 :                 subnet = ls_find_subnet(ted, pref->pref);
    1836           0 :                 if (subnet) {
    1837           0 :                         if (delete)
    1838           0 :                                 ls_subnet_del_all(ted, subnet);
    1839             :                         else
    1840           0 :                                 subnet->status = DELETE;
    1841             :                 }
    1842             :                 break;
    1843             :         default:
    1844             :                 subnet = NULL;
    1845             :                 break;
    1846             :         }
    1847             : 
    1848           0 :         return subnet;
    1849             : }
    1850             : 
    1851           0 : struct ls_element *ls_msg2ted(struct ls_ted *ted, struct ls_message *msg,
    1852             :                                bool delete)
    1853             : {
    1854           0 :         struct ls_element *lse = NULL;
    1855             : 
    1856           0 :         switch (msg->type) {
    1857           0 :         case LS_MSG_TYPE_NODE:
    1858           0 :                 lse = (struct ls_element *)ls_msg2vertex(ted, msg, delete);
    1859           0 :                 break;
    1860           0 :         case LS_MSG_TYPE_ATTRIBUTES:
    1861           0 :                 lse = (struct ls_element *)ls_msg2edge(ted, msg, delete);
    1862           0 :                 break;
    1863           0 :         case LS_MSG_TYPE_PREFIX:
    1864           0 :                 lse = (struct ls_element *)ls_msg2subnet(ted, msg, delete);
    1865           0 :                 break;
    1866             :         default:
    1867             :                 lse = NULL;
    1868             :                 break;
    1869             :         }
    1870             : 
    1871           0 :         return lse;
    1872             : }
    1873             : 
    1874           0 : struct ls_element *ls_stream2ted(struct ls_ted *ted, struct stream *s,
    1875             :                                   bool delete)
    1876             : {
    1877           0 :         struct ls_message *msg;
    1878           0 :         struct ls_element *lse = NULL;
    1879             : 
    1880           0 :         msg = ls_parse_msg(s);
    1881           0 :         if (msg) {
    1882           0 :                 lse = ls_msg2ted(ted, msg, delete);
    1883           0 :                 ls_delete_msg(msg);
    1884             :         }
    1885             : 
    1886           0 :         return lse;
    1887             : }
    1888             : 
    1889           0 : void ls_delete_msg(struct ls_message *msg)
    1890             : {
    1891           0 :         if (msg == NULL)
    1892             :                 return;
    1893             : 
    1894           0 :         XFREE(MTYPE_LS_DB, msg);
    1895             : }
    1896             : 
    1897           0 : int ls_sync_ted(struct ls_ted *ted, struct zclient *zclient,
    1898             :                 struct zapi_opaque_reg_info *dst)
    1899             : {
    1900           0 :         struct ls_vertex *vertex;
    1901           0 :         struct ls_edge *edge;
    1902           0 :         struct ls_subnet *subnet;
    1903           0 :         struct ls_message msg;
    1904             : 
    1905             :         /* Loop TED, start sending Node, then Attributes and finally Prefix */
    1906           0 :         frr_each(vertices, &ted->vertices, vertex) {
    1907           0 :                 ls_vertex2msg(&msg, vertex);
    1908           0 :                 ls_send_msg(zclient, &msg, dst);
    1909             :         }
    1910           0 :         frr_each(edges, &ted->edges, edge) {
    1911           0 :                 ls_edge2msg(&msg, edge);
    1912           0 :                 ls_send_msg(zclient, &msg, dst);
    1913             :         }
    1914           0 :         frr_each(subnets, &ted->subnets, subnet) {
    1915           0 :                 ls_subnet2msg(&msg, subnet);
    1916           0 :                 ls_send_msg(zclient, &msg, dst);
    1917             :         }
    1918           0 :         return 0;
    1919             : }
    1920             : 
    1921             : /**
    1922             :  *  Link State Show functions
    1923             :  */
    1924             : static const char *const origin2txt[] = {
    1925             :         "Unknown",
    1926             :         "ISIS_L1",
    1927             :         "ISIS_L2",
    1928             :         "OSPFv2",
    1929             :         "Direct",
    1930             :         "Static"
    1931             : };
    1932             : 
    1933             : static const char *const type2txt[] = {
    1934             :         "Unknown",
    1935             :         "Standard",
    1936             :         "ABR",
    1937             :         "ASBR",
    1938             :         "Remote ASBR",
    1939             :         "Pseudo"
    1940             : };
    1941             : 
    1942             : static const char *const status2txt[] = {
    1943             :         "Unknown",
    1944             :         "New",
    1945             :         "Update",
    1946             :         "Delete",
    1947             :         "Sync",
    1948             :         "Orphan"
    1949             : };
    1950             : 
    1951           0 : static const char *ls_node_id_to_text(struct ls_node_id lnid, char *str,
    1952             :                                       size_t size)
    1953             : {
    1954           0 :         if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2) {
    1955           0 :                 uint8_t *id;
    1956             : 
    1957           0 :                 id = lnid.id.iso.sys_id;
    1958           0 :                 snprintfrr(str, size, "%02x%02x.%02x%02x.%02x%02x", id[0],
    1959           0 :                            id[1], id[2], id[3], id[4], id[5]);
    1960             :         } else
    1961           0 :                 snprintfrr(str, size, "%pI4", &lnid.id.ip.addr);
    1962             : 
    1963           0 :         return str;
    1964             : }
    1965             : 
    1966           0 : static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
    1967             :                                bool verbose)
    1968             : {
    1969           0 :         struct listnode *node;
    1970           0 :         struct ls_node *lsn;
    1971           0 :         struct ls_edge *edge;
    1972           0 :         struct ls_attributes *attr;
    1973           0 :         struct ls_subnet *subnet;
    1974           0 :         struct sbuf sbuf;
    1975           0 :         uint32_t upper;
    1976             : 
    1977             :         /* Sanity Check */
    1978           0 :         if (!vertex)
    1979           0 :                 return;
    1980             : 
    1981           0 :         lsn = vertex->node;
    1982             : 
    1983           0 :         sbuf_init(&sbuf, NULL, 0);
    1984             : 
    1985           0 :         sbuf_push(&sbuf, 2, "Vertex (%" PRIu64 "): %s", vertex->key, lsn->name);
    1986           0 :         sbuf_push(&sbuf, 0, "\tRouter Id: %pI4", &lsn->router_id);
    1987           0 :         sbuf_push(&sbuf, 0, "\tOrigin: %s", origin2txt[lsn->adv.origin]);
    1988           0 :         sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[vertex->status]);
    1989           0 :         if (!verbose) {
    1990           0 :                 sbuf_push(
    1991             :                         &sbuf, 0,
    1992             :                         "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
    1993           0 :                         listcount(vertex->outgoing_edges),
    1994           0 :                         listcount(vertex->incoming_edges),
    1995           0 :                         listcount(vertex->prefixes));
    1996           0 :                 goto end;
    1997             :         }
    1998             : 
    1999           0 :         if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
    2000           0 :                 sbuf_push(&sbuf, 4, "Type: %s\n", type2txt[lsn->type]);
    2001           0 :         if (CHECK_FLAG(lsn->flags, LS_NODE_AS_NUMBER))
    2002           0 :                 sbuf_push(&sbuf, 4, "AS number: %u\n", lsn->as_number);
    2003           0 :         if (CHECK_FLAG(lsn->flags, LS_NODE_SR)) {
    2004           0 :                 sbuf_push(&sbuf, 4, "Segment Routing Capabilities:\n");
    2005           0 :                 upper = lsn->srgb.lower_bound + lsn->srgb.range_size - 1;
    2006           0 :                 sbuf_push(&sbuf, 8, "SRGB: [%d/%d]", lsn->srgb.lower_bound,
    2007             :                           upper);
    2008           0 :                 if (CHECK_FLAG(lsn->flags, LS_NODE_SRLB)) {
    2009           0 :                         upper = lsn->srlb.lower_bound + lsn->srlb.range_size
    2010             :                                 - 1;
    2011           0 :                         sbuf_push(&sbuf, 0, "\tSRLB: [%d/%d]",
    2012             :                                   lsn->srlb.lower_bound, upper);
    2013             :                 }
    2014           0 :                 sbuf_push(&sbuf, 0, "\tAlgo: ");
    2015           0 :                 for (int i = 0; i < 2; i++) {
    2016           0 :                         if (lsn->algo[i] == 255)
    2017           0 :                                 continue;
    2018             : 
    2019           0 :                         sbuf_push(&sbuf, 0,
    2020             :                                   lsn->algo[i] == 0 ? "SPF " : "S-SPF ");
    2021             :                 }
    2022           0 :                 if (CHECK_FLAG(lsn->flags, LS_NODE_MSD))
    2023           0 :                         sbuf_push(&sbuf, 0, "\tMSD: %d", lsn->msd);
    2024           0 :                 sbuf_push(&sbuf, 0, "\n");
    2025             :         }
    2026             : 
    2027           0 :         sbuf_push(&sbuf, 4, "Outgoing Edges: %d\n",
    2028           0 :                   listcount(vertex->outgoing_edges));
    2029           0 :         for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge)) {
    2030           0 :                 if (edge->destination) {
    2031           0 :                         lsn = edge->destination->node;
    2032           0 :                         sbuf_push(&sbuf, 6, "To:\t%s(%pI4)", lsn->name,
    2033             :                                   &lsn->router_id);
    2034             :                 } else {
    2035           0 :                         sbuf_push(&sbuf, 6, "To:\t- (0.0.0.0)");
    2036             :                 }
    2037           0 :                 attr = edge->attributes;
    2038           0 :                 if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
    2039           0 :                         sbuf_push(&sbuf, 0, "\tLocal:  %pI4\tRemote: %pI4\n",
    2040             :                                   &attr->standard.local,
    2041             :                                   &attr->standard.remote);
    2042           0 :                 else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
    2043           0 :                         sbuf_push(&sbuf, 0, "\tLocal:  %pI6\tRemote: %pI6\n",
    2044             :                                   &attr->standard.local6,
    2045             :                                   &attr->standard.remote6);
    2046             :         }
    2047             : 
    2048           0 :         sbuf_push(&sbuf, 4, "Incoming Edges: %d\n",
    2049           0 :                   listcount(vertex->incoming_edges));
    2050           0 :         for (ALL_LIST_ELEMENTS_RO(vertex->incoming_edges, node, edge)) {
    2051           0 :                 if (edge->source) {
    2052           0 :                         lsn = edge->source->node;
    2053           0 :                         sbuf_push(&sbuf, 6, "From:\t%s(%pI4)", lsn->name,
    2054             :                                   &lsn->router_id);
    2055             :                 } else {
    2056           0 :                         sbuf_push(&sbuf, 6, "From:\t- (0.0.0.0)");
    2057             :                 }
    2058           0 :                 attr = edge->attributes;
    2059           0 :                 if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
    2060           0 :                         sbuf_push(&sbuf, 0, "\tLocal:  %pI4\tRemote: %pI4\n",
    2061             :                                   &attr->standard.local,
    2062             :                                   &attr->standard.remote);
    2063           0 :                 else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
    2064           0 :                         sbuf_push(&sbuf, 0, "\tLocal:  %pI6\tRemote: %pI6\n",
    2065             :                                   &attr->standard.local6,
    2066             :                                   &attr->standard.remote6);
    2067             :         }
    2068             : 
    2069           0 :         sbuf_push(&sbuf, 4, "Subnets: %d\n", listcount(vertex->prefixes));
    2070           0 :         for (ALL_LIST_ELEMENTS_RO(vertex->prefixes, node, subnet))
    2071           0 :                 sbuf_push(&sbuf, 6, "Prefix:\t%pFX\n", &subnet->key);
    2072             : 
    2073           0 : end:
    2074           0 :         vty_out(vty, "%s\n", sbuf_buf(&sbuf));
    2075           0 :         sbuf_free(&sbuf);
    2076             : }
    2077             : 
    2078           0 : static void ls_show_vertex_json(struct ls_vertex *vertex,
    2079             :                                 struct json_object *json)
    2080             : {
    2081           0 :         struct ls_node *lsn;
    2082           0 :         json_object *jsr, *jalgo, *jobj;
    2083           0 :         char buf[INET6_BUFSIZ];
    2084             : 
    2085             :         /* Sanity Check */
    2086           0 :         if (!vertex)
    2087           0 :                 return;
    2088             : 
    2089           0 :         lsn = vertex->node;
    2090             : 
    2091           0 :         json_object_int_add(json, "vertex-id", vertex->key);
    2092           0 :         json_object_string_add(json, "status", status2txt[vertex->status]);
    2093           0 :         json_object_string_add(json, "origin", origin2txt[lsn->adv.origin]);
    2094           0 :         if (CHECK_FLAG(lsn->flags, LS_NODE_NAME))
    2095           0 :                 json_object_string_add(json, "name", lsn->name);
    2096           0 :         if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID)) {
    2097           0 :                 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &lsn->router_id);
    2098           0 :                 json_object_string_add(json, "router-id", buf);
    2099             :         }
    2100           0 :         if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID6)) {
    2101           0 :                 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &lsn->router_id6);
    2102           0 :                 json_object_string_add(json, "router-id-v6", buf);
    2103             :         }
    2104           0 :         if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
    2105           0 :                 json_object_string_add(json, "vertex-type",
    2106           0 :                                        type2txt[lsn->type]);
    2107           0 :         if (CHECK_FLAG(lsn->flags, LS_NODE_AS_NUMBER))
    2108           0 :                 json_object_int_add(json, "asn", lsn->as_number);
    2109           0 :         if (CHECK_FLAG(lsn->flags, LS_NODE_SR)) {
    2110           0 :                 jsr = json_object_new_object();
    2111           0 :                 json_object_object_add(json, "segment-routing", jsr);
    2112           0 :                 json_object_int_add(jsr, "srgb-size", lsn->srgb.range_size);
    2113           0 :                 json_object_int_add(jsr, "srgb-lower", lsn->srgb.lower_bound);
    2114           0 :                 jalgo = json_object_new_array();
    2115           0 :                 json_object_object_add(jsr, "algorithms", jalgo);
    2116           0 :                 for (int i = 0; i < 2; i++) {
    2117           0 :                         if (lsn->algo[i] == 255)
    2118           0 :                                 continue;
    2119           0 :                         jobj = json_object_new_object();
    2120             : 
    2121           0 :                         snprintfrr(buf, 2, "%u", i);
    2122           0 :                         json_object_string_add(
    2123           0 :                                 jobj, buf, lsn->algo[i] == 0 ? "SPF" : "S-SPF");
    2124           0 :                         json_object_array_add(jalgo, jobj);
    2125             :                 }
    2126           0 :                 if (CHECK_FLAG(lsn->flags, LS_NODE_SRLB)) {
    2127           0 :                         json_object_int_add(jsr, "srlb-size",
    2128           0 :                                             lsn->srlb.range_size);
    2129           0 :                         json_object_int_add(jsr, "srlb-lower",
    2130           0 :                                             lsn->srlb.lower_bound);
    2131             :                 }
    2132           0 :                 if (CHECK_FLAG(lsn->flags, LS_NODE_MSD))
    2133           0 :                         json_object_int_add(jsr, "msd", lsn->msd);
    2134             :         }
    2135             : }
    2136             : 
    2137           0 : void ls_show_vertex(struct ls_vertex *vertex, struct vty *vty,
    2138             :                     struct json_object *json, bool verbose)
    2139             : {
    2140           0 :         if (json)
    2141           0 :                 ls_show_vertex_json(vertex, json);
    2142           0 :         else if (vty)
    2143           0 :                 ls_show_vertex_vty(vertex, vty, verbose);
    2144           0 : }
    2145             : 
    2146           0 : void ls_show_vertices(struct ls_ted *ted, struct vty *vty,
    2147             :                       struct json_object *json, bool verbose)
    2148             : {
    2149           0 :         struct ls_vertex *vertex;
    2150           0 :         json_object *jnodes, *jnode;
    2151             : 
    2152           0 :         if (json) {
    2153           0 :                 jnodes = json_object_new_array();
    2154           0 :                 json_object_object_add(json, "vertices", jnodes);
    2155           0 :                 frr_each (vertices, &ted->vertices, vertex) {
    2156           0 :                         jnode = json_object_new_object();
    2157           0 :                         ls_show_vertex(vertex, NULL, jnode, verbose);
    2158           0 :                         json_object_array_add(jnodes, jnode);
    2159             :                 }
    2160           0 :         } else if (vty) {
    2161           0 :                 frr_each (vertices, &ted->vertices, vertex)
    2162           0 :                         ls_show_vertex(vertex, vty, NULL, verbose);
    2163             :         }
    2164           0 : }
    2165             : 
    2166           0 : static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty,
    2167             :                              bool verbose)
    2168             : {
    2169           0 :         struct ls_attributes *attr;
    2170           0 :         struct sbuf sbuf;
    2171           0 :         char buf[INET6_BUFSIZ];
    2172             : 
    2173           0 :         attr = edge->attributes;
    2174           0 :         sbuf_init(&sbuf, NULL, 0);
    2175             : 
    2176           0 :         sbuf_push(&sbuf, 2, "Edge (%" PRIu64 "): ", edge->key);
    2177           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
    2178           0 :                 sbuf_push(&sbuf, 0, "%pI4", &attr->standard.local);
    2179           0 :         else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
    2180           0 :                 sbuf_push(&sbuf, 0, "%pI6", &attr->standard.local6);
    2181             :         else
    2182           0 :                 sbuf_push(&sbuf, 0, "%u/%u", attr->standard.local_id,
    2183             :                           attr->standard.remote_id);
    2184           0 :         ls_node_id_to_text(attr->adv, buf, INET6_BUFSIZ);
    2185           0 :         sbuf_push(&sbuf, 0, "\tAdv. Vertex: %s", buf);
    2186           0 :         sbuf_push(&sbuf, 0, "\tMetric: %u", attr->metric);
    2187           0 :         sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[edge->status]);
    2188             : 
    2189           0 :         if (!verbose)
    2190           0 :                 goto end;
    2191             : 
    2192           0 :         sbuf_push(&sbuf, 4, "Origin: %s\n", origin2txt[attr->adv.origin]);
    2193           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NAME))
    2194           0 :                 sbuf_push(&sbuf, 4, "Name: %s\n", attr->name);
    2195           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
    2196           0 :                 sbuf_push(&sbuf, 4, "TE Metric: %u\n",
    2197             :                           attr->standard.te_metric);
    2198           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
    2199           0 :                 sbuf_push(&sbuf, 4, "Admin Group: 0x%x\n",
    2200             :                           attr->standard.admin_group);
    2201           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
    2202           0 :                 sbuf_push(&sbuf, 4, "Local IPv4 address: %pI4\n",
    2203             :                           &attr->standard.local);
    2204           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
    2205           0 :                 sbuf_push(&sbuf, 4, "Remote IPv4 address: %pI4\n",
    2206             :                           &attr->standard.remote);
    2207           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
    2208           0 :                 sbuf_push(&sbuf, 4, "Local IPv6 address: %pI6\n",
    2209             :                           &attr->standard.local6);
    2210           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
    2211           0 :                 sbuf_push(&sbuf, 4, "Remote IPv6 address: %pI6\n",
    2212             :                           &attr->standard.remote6);
    2213           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
    2214           0 :                 sbuf_push(&sbuf, 4, "Local Identifier: %u\n",
    2215             :                           attr->standard.local_id);
    2216           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
    2217           0 :                 sbuf_push(&sbuf, 4, "Remote Identifier: %u\n",
    2218             :                           attr->standard.remote_id);
    2219           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
    2220           0 :                 sbuf_push(&sbuf, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
    2221           0 :                           attr->standard.max_bw);
    2222           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
    2223           0 :                 sbuf_push(&sbuf, 4,
    2224             :                           "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
    2225           0 :                           attr->standard.max_rsv_bw);
    2226           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW)) {
    2227           0 :                 sbuf_push(&sbuf, 4, "Unreserved Bandwidth per Class Type\n");
    2228           0 :                 for (int i = 0; i < MAX_CLASS_TYPE; i += 2)
    2229           0 :                         sbuf_push(&sbuf, 8,
    2230             :                                   "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
    2231           0 :                                   i, attr->standard.unrsv_bw[i], i + 1,
    2232           0 :                                   attr->standard.unrsv_bw[i + 1]);
    2233             :         }
    2234           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
    2235           0 :                 sbuf_push(&sbuf, 4, "Remote AS: %u\n",
    2236             :                           attr->standard.remote_as);
    2237           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
    2238           0 :                 sbuf_push(&sbuf, 4, "Remote ASBR IPv4 address: %pI4\n",
    2239             :                           &attr->standard.remote_addr);
    2240           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
    2241           0 :                 sbuf_push(&sbuf, 4, "Remote ASBR IPv6 address: %pI6\n",
    2242             :                           &attr->standard.remote_addr6);
    2243           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
    2244           0 :                 sbuf_push(&sbuf, 4, "Average Link Delay: %d (micro-sec)\n",
    2245             :                           attr->extended.delay);
    2246           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY))
    2247           0 :                 sbuf_push(&sbuf, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
    2248             :                           attr->extended.min_delay, attr->extended.max_delay);
    2249           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
    2250           0 :                 sbuf_push(&sbuf, 4, "Delay Variation: %d (micro-sec)\n",
    2251             :                           attr->extended.jitter);
    2252           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
    2253           0 :                 sbuf_push(&sbuf, 4, "Link Loss: %g (%%)\n",
    2254           0 :                           (float)(attr->extended.pkt_loss * LOSS_PRECISION));
    2255           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
    2256           0 :                 sbuf_push(&sbuf, 4, "Available Bandwidth: %g (Bytes/s)\n",
    2257           0 :                           attr->extended.ava_bw);
    2258           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
    2259           0 :                 sbuf_push(&sbuf, 4, "Residual Bandwidth: %g (Bytes/s)\n",
    2260           0 :                           attr->extended.rsv_bw);
    2261           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
    2262           0 :                 sbuf_push(&sbuf, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
    2263           0 :                           attr->extended.used_bw);
    2264           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
    2265           0 :                 sbuf_push(&sbuf, 4, "IPv4 Adjacency-SID: %u",
    2266             :                           attr->adj_sid[ADJ_PRI_IPV4].sid);
    2267           0 :                 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
    2268           0 :                           attr->adj_sid[ADJ_PRI_IPV4].flags,
    2269           0 :                           attr->adj_sid[ADJ_PRI_IPV4].weight);
    2270             :         }
    2271           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
    2272           0 :                 sbuf_push(&sbuf, 4, "IPv4 Bck. Adjacency-SID: %u",
    2273             :                           attr->adj_sid[ADJ_BCK_IPV4].sid);
    2274           0 :                 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
    2275           0 :                           attr->adj_sid[ADJ_BCK_IPV4].flags,
    2276           0 :                           attr->adj_sid[ADJ_BCK_IPV4].weight);
    2277             :         }
    2278           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
    2279           0 :                 sbuf_push(&sbuf, 4, "IPv6 Adjacency-SID: %u",
    2280             :                           attr->adj_sid[ADJ_PRI_IPV6].sid);
    2281           0 :                 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
    2282           0 :                           attr->adj_sid[ADJ_PRI_IPV6].flags,
    2283           0 :                           attr->adj_sid[ADJ_PRI_IPV6].weight);
    2284             :         }
    2285           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
    2286           0 :                 sbuf_push(&sbuf, 4, "IPv6 Bck. Adjacency-SID: %u",
    2287             :                           attr->adj_sid[ADJ_BCK_IPV6].sid);
    2288           0 :                 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
    2289           0 :                           attr->adj_sid[ADJ_BCK_IPV6].flags,
    2290           0 :                           attr->adj_sid[ADJ_BCK_IPV6].weight);
    2291             :         }
    2292           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
    2293           0 :                 sbuf_push(&sbuf, 4, "SRLGs: %d", attr->srlg_len);
    2294           0 :                 for (int i = 1; i < attr->srlg_len; i++) {
    2295           0 :                         if (i % 8)
    2296           0 :                                 sbuf_push(&sbuf, 8, "\n%u", attr->srlgs[i]);
    2297             :                         else
    2298           0 :                                 sbuf_push(&sbuf, 8, ", %u", attr->srlgs[i]);
    2299             :                 }
    2300           0 :                 sbuf_push(&sbuf, 0, "\n");
    2301             :         }
    2302             : 
    2303           0 : end:
    2304           0 :         vty_out(vty, "%s\n", sbuf_buf(&sbuf));
    2305           0 :         sbuf_free(&sbuf);
    2306           0 : }
    2307             : 
    2308           0 : static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
    2309             : {
    2310           0 :         struct ls_attributes *attr;
    2311           0 :         struct json_object *jte, *jbw, *jobj, *jsr = NULL, *jsrlg;
    2312           0 :         char buf[INET6_BUFSIZ];
    2313             : 
    2314           0 :         attr = edge->attributes;
    2315             : 
    2316           0 :         json_object_int_add(json, "edge-id", edge->key);
    2317           0 :         json_object_string_add(json, "status", status2txt[edge->status]);
    2318           0 :         json_object_string_add(json, "origin", origin2txt[attr->adv.origin]);
    2319           0 :         ls_node_id_to_text(attr->adv, buf, INET6_BUFSIZ);
    2320           0 :         json_object_string_add(json, "advertised-router", buf);
    2321           0 :         if (edge->source)
    2322           0 :                 json_object_int_add(json, "local-vertex-id", edge->source->key);
    2323           0 :         if (edge->destination)
    2324           0 :                 json_object_int_add(json, "remote-vertex-id",
    2325           0 :                                     edge->destination->key);
    2326           0 :         json_object_int_add(json, "metric", attr->metric);
    2327           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NAME))
    2328           0 :                 json_object_string_add(json, "name", attr->name);
    2329           0 :         jte = json_object_new_object();
    2330           0 :         json_object_object_add(json, "edge-attributes", jte);
    2331           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
    2332           0 :                 json_object_int_add(jte, "te-metric", attr->standard.te_metric);
    2333           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
    2334           0 :                 json_object_int_add(jte, "admin-group",
    2335           0 :                                     attr->standard.admin_group);
    2336           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)) {
    2337           0 :                 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &attr->standard.local);
    2338           0 :                 json_object_string_add(jte, "local-address", buf);
    2339             :         }
    2340           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR)) {
    2341           0 :                 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &attr->standard.remote);
    2342           0 :                 json_object_string_add(jte, "remote-address", buf);
    2343             :         }
    2344           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)) {
    2345           0 :                 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &attr->standard.local6);
    2346           0 :                 json_object_string_add(jte, "local-address-v6", buf);
    2347             :         }
    2348           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6)) {
    2349           0 :                 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &attr->standard.remote6);
    2350           0 :                 json_object_string_add(jte, "remote-address-v6", buf);
    2351             :         }
    2352           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
    2353           0 :                 json_object_int_add(jte, "local-identifier",
    2354           0 :                                     attr->standard.local_id);
    2355           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
    2356           0 :                 json_object_int_add(jte, "remote-identifier",
    2357           0 :                                     attr->standard.remote_id);
    2358           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
    2359           0 :                 json_object_double_add(jte, "max-link-bandwidth",
    2360           0 :                                        attr->standard.max_bw);
    2361           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
    2362           0 :                 json_object_double_add(jte, "max-resv-link-bandwidth",
    2363           0 :                                        attr->standard.max_rsv_bw);
    2364           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW)) {
    2365           0 :                 jbw = json_object_new_array();
    2366           0 :                 json_object_object_add(jte, "unreserved-bandwidth", jbw);
    2367           0 :                 for (int i = 0; i < MAX_CLASS_TYPE; i++) {
    2368           0 :                         jobj = json_object_new_object();
    2369           0 :                         snprintfrr(buf, 13, "class-type-%u", i);
    2370           0 :                         json_object_double_add(jobj, buf,
    2371           0 :                                                attr->standard.unrsv_bw[i]);
    2372           0 :                         json_object_array_add(jbw, jobj);
    2373             :                 }
    2374             :         }
    2375           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
    2376           0 :                 json_object_int_add(jte, "remote-asn",
    2377           0 :                                     attr->standard.remote_as);
    2378           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR)) {
    2379           0 :                 snprintfrr(buf, INET6_BUFSIZ, "%pI4",
    2380             :                            &attr->standard.remote_addr);
    2381           0 :                 json_object_string_add(jte, "remote-as-address", buf);
    2382             :         }
    2383           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6)) {
    2384           0 :                 snprintfrr(buf, INET6_BUFSIZ, "%pI6",
    2385             :                            &attr->standard.remote_addr6);
    2386           0 :                 json_object_string_add(jte, "remote-as-address-v6", buf);
    2387             :         }
    2388           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
    2389           0 :                 json_object_int_add(jte, "delay", attr->extended.delay);
    2390           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
    2391           0 :                 json_object_int_add(jte, "min-delay", attr->extended.min_delay);
    2392           0 :                 json_object_int_add(jte, "max-delay", attr->extended.max_delay);
    2393             :         }
    2394           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
    2395           0 :                 json_object_int_add(jte, "jitter", attr->extended.jitter);
    2396           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
    2397           0 :                 json_object_double_add(
    2398           0 :                         jte, "loss", attr->extended.pkt_loss * LOSS_PRECISION);
    2399           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
    2400           0 :                 json_object_double_add(jte, "available-bandwidth",
    2401           0 :                                        attr->extended.ava_bw);
    2402           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
    2403           0 :                 json_object_double_add(jte, "residual-bandwidth",
    2404           0 :                                        attr->extended.rsv_bw);
    2405           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
    2406           0 :                 json_object_double_add(jte, "utilized-bandwidth",
    2407           0 :                                        attr->extended.used_bw);
    2408           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
    2409           0 :                 jsrlg = json_object_new_array();
    2410           0 :                 json_object_object_add(jte, "srlgs", jsrlg);
    2411           0 :                 for (int i = 1; i < attr->srlg_len; i++) {
    2412           0 :                         jobj = json_object_new_object();
    2413           0 :                         json_object_int_add(jobj, "srlg", attr->srlgs[i]);
    2414           0 :                         json_object_array_add(jsrlg, jobj);
    2415             :                 }
    2416             :         }
    2417           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
    2418           0 :                 jsr = json_object_new_array();
    2419           0 :                 json_object_object_add(json, "segment-routing", jsr);
    2420           0 :                 jobj = json_object_new_object();
    2421           0 :                 json_object_int_add(jobj, "adj-sid",
    2422           0 :                                     attr->adj_sid[ADJ_PRI_IPV4].sid);
    2423           0 :                 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV4].flags);
    2424           0 :                 json_object_string_add(jobj, "flags", buf);
    2425           0 :                 json_object_int_add(jobj, "weight",
    2426           0 :                                     attr->adj_sid[ADJ_PRI_IPV4].weight);
    2427           0 :                 json_object_array_add(jsr, jobj);
    2428             :         }
    2429           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
    2430           0 :                 if (!jsr) {
    2431           0 :                         jsr = json_object_new_array();
    2432           0 :                         json_object_object_add(json, "segment-routing", jsr);
    2433             :                 }
    2434           0 :                 jobj = json_object_new_object();
    2435           0 :                 json_object_int_add(jobj, "adj-sid",
    2436           0 :                                     attr->adj_sid[ADJ_BCK_IPV4].sid);
    2437           0 :                 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV4].flags);
    2438           0 :                 json_object_string_add(jobj, "flags", buf);
    2439           0 :                 json_object_int_add(jobj, "weight",
    2440           0 :                                     attr->adj_sid[ADJ_BCK_IPV4].weight);
    2441           0 :                 json_object_array_add(jsr, jobj);
    2442             :         }
    2443           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
    2444           0 :                 jsr = json_object_new_array();
    2445           0 :                 json_object_object_add(json, "segment-routing", jsr);
    2446           0 :                 jobj = json_object_new_object();
    2447           0 :                 json_object_int_add(jobj, "adj-sid",
    2448           0 :                                     attr->adj_sid[ADJ_PRI_IPV6].sid);
    2449           0 :                 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV6].flags);
    2450           0 :                 json_object_string_add(jobj, "flags", buf);
    2451           0 :                 json_object_int_add(jobj, "weight",
    2452           0 :                                     attr->adj_sid[ADJ_PRI_IPV6].weight);
    2453           0 :                 json_object_array_add(jsr, jobj);
    2454             :         }
    2455           0 :         if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
    2456           0 :                 if (!jsr) {
    2457           0 :                         jsr = json_object_new_array();
    2458           0 :                         json_object_object_add(json, "segment-routing", jsr);
    2459             :                 }
    2460           0 :                 jobj = json_object_new_object();
    2461           0 :                 json_object_int_add(jobj, "adj-sid",
    2462           0 :                                     attr->adj_sid[ADJ_BCK_IPV6].sid);
    2463           0 :                 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV6].flags);
    2464           0 :                 json_object_string_add(jobj, "flags", buf);
    2465           0 :                 json_object_int_add(jobj, "weight",
    2466           0 :                                     attr->adj_sid[ADJ_BCK_IPV6].weight);
    2467           0 :                 json_object_array_add(jsr, jobj);
    2468             :         }
    2469           0 : }
    2470             : 
    2471           0 : void ls_show_edge(struct ls_edge *edge, struct vty *vty,
    2472             :                   struct json_object *json, bool verbose)
    2473             : {
    2474             :         /* Sanity Check */
    2475           0 :         if (!edge)
    2476             :                 return;
    2477             : 
    2478           0 :         if (json)
    2479           0 :                 ls_show_edge_json(edge, json);
    2480           0 :         else if (vty)
    2481           0 :                 ls_show_edge_vty(edge, vty, verbose);
    2482             : }
    2483             : 
    2484           0 : void ls_show_edges(struct ls_ted *ted, struct vty *vty,
    2485             :                    struct json_object *json, bool verbose)
    2486             : {
    2487           0 :         struct ls_edge *edge;
    2488           0 :         json_object *jedges, *jedge;
    2489             : 
    2490           0 :         if (json) {
    2491           0 :                 jedges = json_object_new_array();
    2492           0 :                 json_object_object_add(json, "edges", jedges);
    2493           0 :                 frr_each (edges, &ted->edges, edge) {
    2494           0 :                         jedge = json_object_new_object();
    2495           0 :                         ls_show_edge(edge, NULL, jedge, verbose);
    2496           0 :                         json_object_array_add(jedges, jedge);
    2497             :                 }
    2498           0 :         } else if (vty) {
    2499           0 :                 frr_each (edges, &ted->edges, edge)
    2500           0 :                         ls_show_edge(edge, vty, NULL, verbose);
    2501             :         }
    2502           0 : }
    2503             : 
    2504           0 : static void ls_show_subnet_vty(struct ls_subnet *subnet, struct vty *vty,
    2505             :                                bool verbose)
    2506             : {
    2507           0 :         struct ls_prefix *pref;
    2508           0 :         struct sbuf sbuf;
    2509           0 :         char buf[INET6_BUFSIZ];
    2510             : 
    2511           0 :         pref = subnet->ls_pref;
    2512           0 :         sbuf_init(&sbuf, NULL, 0);
    2513             : 
    2514           0 :         sbuf_push(&sbuf, 2, "Subnet: %pFX", &subnet->key);
    2515           0 :         ls_node_id_to_text(pref->adv, buf, INET6_BUFSIZ);
    2516           0 :         sbuf_push(&sbuf, 0, "\tAdv. Vertex: %s", buf);
    2517           0 :         sbuf_push(&sbuf, 0, "\tMetric: %d", pref->metric);
    2518           0 :         sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[subnet->status]);
    2519             : 
    2520           0 :         if (!verbose)
    2521           0 :                 goto end;
    2522             : 
    2523           0 :         sbuf_push(&sbuf, 4, "Origin: %s\n", origin2txt[pref->adv.origin]);
    2524           0 :         if (CHECK_FLAG(pref->flags, LS_PREF_IGP_FLAG))
    2525           0 :                 sbuf_push(&sbuf, 4, "Flags: %d\n", pref->igp_flag);
    2526             : 
    2527           0 :         if (CHECK_FLAG(pref->flags, LS_PREF_ROUTE_TAG))
    2528           0 :                 sbuf_push(&sbuf, 4, "Tag: %d\n", pref->route_tag);
    2529             : 
    2530           0 :         if (CHECK_FLAG(pref->flags, LS_PREF_EXTENDED_TAG))
    2531           0 :                 sbuf_push(&sbuf, 4, "Extended Tag: %" PRIu64 "\n",
    2532             :                           pref->extended_tag);
    2533             : 
    2534           0 :         if (CHECK_FLAG(pref->flags, LS_PREF_SR))
    2535           0 :                 sbuf_push(&sbuf, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
    2536           0 :                           pref->sr.sid, pref->sr.algo, pref->sr.sid_flag);
    2537             : 
    2538           0 : end:
    2539           0 :         vty_out(vty, "%s\n", sbuf_buf(&sbuf));
    2540           0 :         sbuf_free(&sbuf);
    2541           0 : }
    2542             : 
    2543           0 : static void ls_show_subnet_json(struct ls_subnet *subnet,
    2544             :                                 struct json_object *json)
    2545             : {
    2546           0 :         struct ls_prefix *pref;
    2547           0 :         json_object *jsr;
    2548           0 :         char buf[INET6_BUFSIZ];
    2549             : 
    2550           0 :         pref = subnet->ls_pref;
    2551             : 
    2552           0 :         snprintfrr(buf, INET6_BUFSIZ, "%pFX", &subnet->key);
    2553           0 :         json_object_string_add(json, "subnet-id", buf);
    2554           0 :         json_object_string_add(json, "status", status2txt[subnet->status]);
    2555           0 :         json_object_string_add(json, "origin", origin2txt[pref->adv.origin]);
    2556           0 :         ls_node_id_to_text(pref->adv, buf, INET6_BUFSIZ);
    2557           0 :         json_object_string_add(json, "advertised-router", buf);
    2558           0 :         if (subnet->vertex)
    2559           0 :                 json_object_int_add(json, "vertex-id", subnet->vertex->key);
    2560           0 :         json_object_int_add(json, "metric", pref->metric);
    2561           0 :         if (CHECK_FLAG(pref->flags, LS_PREF_IGP_FLAG)) {
    2562           0 :                 snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->igp_flag);
    2563           0 :                 json_object_string_add(json, "flags", buf);
    2564             :         }
    2565           0 :         if (CHECK_FLAG(pref->flags, LS_PREF_ROUTE_TAG))
    2566           0 :                 json_object_int_add(json, "tag", pref->route_tag);
    2567           0 :         if (CHECK_FLAG(pref->flags, LS_PREF_EXTENDED_TAG))
    2568           0 :                 json_object_int_add(json, "extended-tag", pref->extended_tag);
    2569           0 :         if (CHECK_FLAG(pref->flags, LS_PREF_SR)) {
    2570           0 :                 jsr = json_object_new_object();
    2571           0 :                 json_object_object_add(json, "segment-routing", jsr);
    2572           0 :                 json_object_int_add(jsr, "pref-sid", pref->sr.sid);
    2573           0 :                 json_object_int_add(jsr, "algo", pref->sr.algo);
    2574           0 :                 snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->sr.sid_flag);
    2575           0 :                 json_object_string_add(jsr, "flags", buf);
    2576             :         }
    2577           0 : }
    2578             : 
    2579           0 : void ls_show_subnet(struct ls_subnet *subnet, struct vty *vty,
    2580             :                     struct json_object *json, bool verbose)
    2581             : {
    2582             :         /* Sanity Check */
    2583           0 :         if (!subnet)
    2584             :                 return;
    2585             : 
    2586           0 :         if (json)
    2587           0 :                 ls_show_subnet_json(subnet, json);
    2588           0 :         else if (vty)
    2589           0 :                 ls_show_subnet_vty(subnet, vty, verbose);
    2590             : }
    2591             : 
    2592           0 : void ls_show_subnets(struct ls_ted *ted, struct vty *vty,
    2593             :                      struct json_object *json, bool verbose)
    2594             : {
    2595           0 :         struct ls_subnet *subnet;
    2596           0 :         json_object *jsubs, *jsub;
    2597             : 
    2598           0 :         if (json) {
    2599           0 :                 jsubs = json_object_new_array();
    2600           0 :                 json_object_object_add(json, "subnets", jsubs);
    2601           0 :                 frr_each (subnets, &ted->subnets, subnet) {
    2602           0 :                         jsub = json_object_new_object();
    2603           0 :                         ls_show_subnet(subnet, NULL, jsub, verbose);
    2604           0 :                         json_object_array_add(jsubs, jsub);
    2605             :                 }
    2606           0 :         } else if (vty) {
    2607           0 :                 frr_each (subnets, &ted->subnets, subnet)
    2608           0 :                         ls_show_subnet(subnet, vty, NULL, verbose);
    2609             :         }
    2610           0 : }
    2611             : 
    2612           0 : void ls_show_ted(struct ls_ted *ted, struct vty *vty, struct json_object *json,
    2613             :                  bool verbose)
    2614             : {
    2615           0 :         json_object *jted;
    2616             : 
    2617           0 :         if (json) {
    2618           0 :                 jted = json_object_new_object();
    2619           0 :                 json_object_object_add(json, "ted", jted);
    2620           0 :                 json_object_string_add(jted, "name", ted->name);
    2621           0 :                 json_object_int_add(jted, "key", ted->key);
    2622           0 :                 json_object_int_add(jted, "verticesCount",
    2623           0 :                                     vertices_count(&ted->vertices));
    2624           0 :                 json_object_int_add(jted, "edgesCount",
    2625           0 :                                     edges_count(&ted->edges));
    2626           0 :                 json_object_int_add(jted, "subnetsCount",
    2627           0 :                                     subnets_count(&ted->subnets));
    2628           0 :                 ls_show_vertices(ted, NULL, jted, verbose);
    2629           0 :                 ls_show_edges(ted, NULL, jted, verbose);
    2630           0 :                 ls_show_subnets(ted, NULL, jted, verbose);
    2631           0 :                 return;
    2632             :         }
    2633             : 
    2634           0 :         if (vty) {
    2635           0 :                 vty_out(vty,
    2636             :                         "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
    2637           0 :                         ted->name, ted->key);
    2638           0 :                 ls_show_vertices(ted, vty, NULL, verbose);
    2639           0 :                 ls_show_edges(ted, vty, NULL, verbose);
    2640           0 :                 ls_show_subnets(ted, vty, NULL, verbose);
    2641           0 :                 vty_out(vty,
    2642             :                         "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
    2643           0 :                         vertices_count(&ted->vertices),
    2644           0 :                         edges_count(&ted->edges), subnets_count(&ted->subnets));
    2645             :         }
    2646             : }
    2647             : 
    2648           0 : void ls_dump_ted(struct ls_ted *ted)
    2649             : {
    2650           0 :         struct ls_vertex *vertex;
    2651           0 :         struct ls_edge *edge;
    2652           0 :         struct ls_subnet *subnet;
    2653           0 :         const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
    2654             : 
    2655           0 :         zlog_debug("(%s) Ted init", __func__);
    2656             : 
    2657             :         /* Loop TED, start printing Node, then Attributes and finally Prefix */
    2658           0 :         frr_each (vertices, &ted->vertices, vertex) {
    2659           0 :                 zlog_debug("    Ted node (%s %pI4 %s)",
    2660             :                            vertex->node->name[0] ? vertex->node->name
    2661             :                                                  : "no name node",
    2662             :                            &vertex->node->router_id,
    2663             :                            origin2txt[vertex->node->adv.origin]);
    2664           0 :                 struct listnode *lst_node;
    2665           0 :                 struct ls_edge *vertex_edge;
    2666             : 
    2667           0 :                 for (ALL_LIST_ELEMENTS_RO(vertex->incoming_edges, lst_node,
    2668             :                                           vertex_edge)) {
    2669           0 :                         zlog_debug(
    2670             :                                 "        inc edge key:%" PRIu64 " attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
    2671             :                                 vertex_edge->key,
    2672             :                                 &vertex_edge->attributes->adv.id.ip.addr,
    2673             :                                 &vertex_edge->attributes->standard.local,
    2674             :                                 &vertex_edge->attributes->standard.remote);
    2675             :                 }
    2676           0 :                 for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, lst_node,
    2677             :                                           vertex_edge)) {
    2678           0 :                         zlog_debug(
    2679             :                                 "        out edge key:%" PRIu64 " attr key:%pI4  loc:(%pI4) rmt:(%pI4)",
    2680             :                                 vertex_edge->key,
    2681             :                                 &vertex_edge->attributes->adv.id.ip.addr,
    2682             :                                 &vertex_edge->attributes->standard.local,
    2683             :                                 &vertex_edge->attributes->standard.remote);
    2684             :                 }
    2685             :         }
    2686           0 :         frr_each (edges, &ted->edges, edge) {
    2687           0 :                 zlog_debug("    Ted edge key:%" PRIu64 "src:%pI4 dst:%pI4", edge->key,
    2688             :                            edge->source ? &edge->source->node->router_id
    2689             :                                         : &inaddr_any,
    2690             :                            edge->destination
    2691             :                                    ? &edge->destination->node->router_id
    2692             :                                    : &inaddr_any);
    2693             :         }
    2694           0 :         frr_each (subnets, &ted->subnets, subnet) {
    2695           0 :                 zlog_debug("    Ted subnet key:%pFX vertex:%pI4",
    2696             :                            &subnet->ls_pref->pref,
    2697             :                            &subnet->vertex->node->adv.id.ip.addr);
    2698             :         }
    2699           0 :         zlog_debug("(%s) Ted end", __func__);
    2700           0 : }

Generated by: LCOV version v1.16-topotato