2 * Link State Database - link_state.c
4 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
6 * Copyright (C) 2020 Orange http://www.orange.com
8 * This file is part of Free Range Routing (FRR).
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
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.
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
31 #include "termtable.h"
41 #include "link_state.h"
43 /* Link State Memory allocation */
44 DEFINE_MTYPE_STATIC(LIB
, LS_DB
, "Link State Database");
47 * Link State Node management functions
49 int ls_node_id_same(struct ls_node_id i1
, struct ls_node_id i2
)
51 if (i1
.origin
!= i2
.origin
)
54 if (i1
.origin
== UNKNOWN
)
57 if (i1
.origin
== ISIS_L1
|| i1
.origin
== ISIS_L2
) {
58 if (memcmp(i1
.id
.iso
.sys_id
, i2
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
)
60 || (i1
.id
.iso
.level
!= i2
.id
.iso
.level
))
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
))
71 struct ls_node
*ls_node_new(struct ls_node_id adv
, struct in_addr rid
,
76 if (adv
.origin
== UNKNOWN
)
79 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
81 if (!IPV4_NET0(rid
.s_addr
)) {
83 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
85 if (adv
.origin
== OSPFv2
|| adv
.origin
== STATIC
86 || adv
.origin
== DIRECT
) {
87 new->router_id
= adv
.id
.ip
.addr
;
88 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
91 if (!IN6_IS_ADDR_UNSPECIFIED(&rid6
)) {
92 new->router_id6
= rid6
;
93 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID6
);
98 void ls_node_del(struct ls_node
*node
)
103 XFREE(MTYPE_LS_DB
, node
);
106 int ls_node_same(struct ls_node
*n1
, struct ls_node
*n2
)
108 /* First, check pointer */
109 if ((n1
&& !n2
) || (!n1
&& n2
))
115 /* Then, verify Flags and Origin */
116 if (n1
->flags
!= n2
->flags
)
119 if (!ls_node_id_same(n1
->adv
, n2
->adv
))
122 /* Finally, check each individual parameters that are valid */
123 if (CHECK_FLAG(n1
->flags
, LS_NODE_NAME
)
124 && (strncmp(n1
->name
, n2
->name
, MAX_NAME_LENGTH
) != 0))
126 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID
)
127 && !IPV4_ADDR_SAME(&n1
->router_id
, &n2
->router_id
))
129 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID6
)
130 && !IPV6_ADDR_SAME(&n1
->router_id6
, &n2
->router_id6
))
132 if (CHECK_FLAG(n1
->flags
, LS_NODE_FLAG
)
133 && (n1
->node_flag
!= n2
->node_flag
))
135 if (CHECK_FLAG(n1
->flags
, LS_NODE_TYPE
) && (n1
->type
!= n2
->type
))
137 if (CHECK_FLAG(n1
->flags
, LS_NODE_AS_NUMBER
)
138 && (n1
->as_number
!= n2
->as_number
))
140 if (CHECK_FLAG(n1
->flags
, LS_NODE_SR
)) {
141 if (n1
->srgb
.flag
!= n2
->srgb
.flag
142 || n1
->srgb
.lower_bound
!= n2
->srgb
.lower_bound
143 || n1
->srgb
.range_size
!= n2
->srgb
.range_size
)
145 if ((n1
->algo
[0] != n2
->algo
[0])
146 || (n1
->algo
[1] != n2
->algo
[1]))
148 if (CHECK_FLAG(n1
->flags
, LS_NODE_SRLB
)
149 && ((n1
->srlb
.lower_bound
!= n2
->srlb
.lower_bound
150 || n1
->srlb
.range_size
!= n2
->srlb
.range_size
)))
152 if (CHECK_FLAG(n1
->flags
, LS_NODE_MSD
) && (n1
->msd
!= n2
->msd
))
156 /* OK, n1 & n2 are equal */
161 * Link State Attributes management functions
163 struct ls_attributes
*ls_attributes_new(struct ls_node_id adv
,
164 struct in_addr local
,
165 struct in6_addr local6
,
168 struct ls_attributes
*new;
170 if (adv
.origin
== UNKNOWN
)
173 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
175 if (!IPV4_NET0(local
.s_addr
)) {
176 new->standard
.local
= local
;
177 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
);
179 if (!IN6_IS_ADDR_UNSPECIFIED(&local6
)) {
180 new->standard
.local6
= local6
;
181 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR6
);
184 new->standard
.local_id
= local_id
;
185 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ID
);
188 /* Check that almost one identifier is set */
189 if (!CHECK_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
| LS_ATTR_LOCAL_ADDR6
190 | LS_ATTR_LOCAL_ID
)) {
191 XFREE(MTYPE_LS_DB
, new);
195 admin_group_init(&new->ext_admin_group
);
200 void ls_attributes_srlg_del(struct ls_attributes
*attr
)
206 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
210 UNSET_FLAG(attr
->flags
, LS_ATTR_SRLG
);
213 void ls_attributes_del(struct ls_attributes
*attr
)
218 ls_attributes_srlg_del(attr
);
220 admin_group_term(&attr
->ext_admin_group
);
222 XFREE(MTYPE_LS_DB
, attr
);
225 int ls_attributes_same(struct ls_attributes
*l1
, struct ls_attributes
*l2
)
227 /* First, check pointer */
228 if ((l1
&& !l2
) || (!l1
&& l2
))
234 /* Then, verify Flags and Origin */
235 if (l1
->flags
!= l2
->flags
)
238 if (!ls_node_id_same(l1
->adv
, l2
->adv
))
241 /* Finally, check each individual parameters that are valid */
242 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NAME
)
243 && strncmp(l1
->name
, l2
->name
, MAX_NAME_LENGTH
) != 0)
245 if (CHECK_FLAG(l1
->flags
, LS_ATTR_METRIC
) && (l1
->metric
!= l2
->metric
))
247 if (CHECK_FLAG(l1
->flags
, LS_ATTR_TE_METRIC
)
248 && (l1
->standard
.te_metric
!= l2
->standard
.te_metric
))
250 if (CHECK_FLAG(l1
->flags
, LS_ATTR_ADM_GRP
)
251 && (l1
->standard
.admin_group
!= l2
->standard
.admin_group
))
253 if (CHECK_FLAG(l1
->flags
, LS_ATTR_EXT_ADM_GRP
) &&
254 !admin_group_cmp(&l1
->ext_admin_group
, &l2
->ext_admin_group
))
256 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR
)
257 && !IPV4_ADDR_SAME(&l1
->standard
.local
, &l2
->standard
.local
))
259 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR
)
260 && !IPV4_ADDR_SAME(&l1
->standard
.remote
, &l2
->standard
.remote
))
262 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR6
)
263 && !IPV6_ADDR_SAME(&l1
->standard
.local6
, &l2
->standard
.local6
))
265 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR6
)
266 && !IPV6_ADDR_SAME(&l1
->standard
.remote6
, &l2
->standard
.remote6
))
268 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ID
)
269 && (l1
->standard
.local_id
!= l2
->standard
.local_id
))
271 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ID
)
272 && (l1
->standard
.remote_id
!= l2
->standard
.remote_id
))
274 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_BW
)
275 && (l1
->standard
.max_bw
!= l2
->standard
.max_bw
))
277 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_RSV_BW
)
278 && (l1
->standard
.max_rsv_bw
!= l2
->standard
.max_rsv_bw
))
280 if (CHECK_FLAG(l1
->flags
, LS_ATTR_UNRSV_BW
)
281 && memcmp(&l1
->standard
.unrsv_bw
, &l2
->standard
.unrsv_bw
, 32) != 0)
283 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_AS
)
284 && (l1
->standard
.remote_as
!= l2
->standard
.remote_as
))
286 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR
)
287 && !IPV4_ADDR_SAME(&l1
->standard
.remote_addr
,
288 &l2
->standard
.remote_addr
))
290 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR6
)
291 && !IPV6_ADDR_SAME(&l1
->standard
.remote_addr6
,
292 &l2
->standard
.remote_addr6
))
294 if (CHECK_FLAG(l1
->flags
, LS_ATTR_DELAY
)
295 && (l1
->extended
.delay
!= l2
->extended
.delay
))
297 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MIN_MAX_DELAY
)
298 && ((l1
->extended
.min_delay
!= l2
->extended
.min_delay
)
299 || (l1
->extended
.max_delay
!= l2
->extended
.max_delay
)))
301 if (CHECK_FLAG(l1
->flags
, LS_ATTR_JITTER
)
302 && (l1
->extended
.jitter
!= l2
->extended
.jitter
))
304 if (CHECK_FLAG(l1
->flags
, LS_ATTR_PACKET_LOSS
)
305 && (l1
->extended
.pkt_loss
!= l2
->extended
.pkt_loss
))
307 if (CHECK_FLAG(l1
->flags
, LS_ATTR_AVA_BW
)
308 && (l1
->extended
.ava_bw
!= l2
->extended
.ava_bw
))
310 if (CHECK_FLAG(l1
->flags
, LS_ATTR_RSV_BW
)
311 && (l1
->extended
.rsv_bw
!= l2
->extended
.rsv_bw
))
313 if (CHECK_FLAG(l1
->flags
, LS_ATTR_USE_BW
)
314 && (l1
->extended
.used_bw
!= l2
->extended
.used_bw
))
316 for (int i
= 0; i
< LS_ADJ_MAX
; i
++) {
317 if (!CHECK_FLAG(l1
->flags
, (LS_ATTR_ADJ_SID
<< i
)))
319 if ((l1
->adj_sid
[i
].sid
!= l2
->adj_sid
[i
].sid
)
320 || (l1
->adj_sid
[i
].flags
!= l2
->adj_sid
[i
].flags
)
321 || (l1
->adj_sid
[i
].weight
!= l2
->adj_sid
[i
].weight
))
323 if (((l1
->adv
.origin
== ISIS_L1
) || (l1
->adv
.origin
== ISIS_L2
))
324 && (memcmp(&l1
->adj_sid
[i
].neighbor
.sysid
,
325 &l2
->adj_sid
[i
].neighbor
.sysid
, ISO_SYS_ID_LEN
)
328 if (((l1
->adv
.origin
== OSPFv2
) || (l1
->adv
.origin
== STATIC
)
329 || (l1
->adv
.origin
== DIRECT
))
330 && (i
< ADJ_PRI_IPV6
)
331 && (!IPV4_ADDR_SAME(&l1
->adj_sid
[i
].neighbor
.addr
,
332 &l2
->adj_sid
[i
].neighbor
.addr
)))
335 if (CHECK_FLAG(l1
->flags
, LS_ATTR_SRLG
)
336 && ((l1
->srlg_len
!= l2
->srlg_len
)
337 || memcmp(l1
->srlgs
, l2
->srlgs
,
338 l1
->srlg_len
* sizeof(uint32_t))
342 /* OK, l1 & l2 are equal */
347 * Link State prefix management functions
349 struct ls_prefix
*ls_prefix_new(struct ls_node_id adv
, struct prefix p
)
351 struct ls_prefix
*new;
353 if (adv
.origin
== UNKNOWN
)
356 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
363 void ls_prefix_del(struct ls_prefix
*pref
)
368 XFREE(MTYPE_LS_DB
, pref
);
371 int ls_prefix_same(struct ls_prefix
*p1
, struct ls_prefix
*p2
)
373 /* First, check pointer */
374 if ((p1
&& !p2
) || (!p1
&& p2
))
380 /* Then, verify Flags and Origin */
381 if (p1
->flags
!= p2
->flags
)
384 if (!ls_node_id_same(p1
->adv
, p2
->adv
))
387 /* Finally, check each individual parameters that are valid */
388 if (prefix_same(&p1
->pref
, &p2
->pref
) == 0)
390 if (CHECK_FLAG(p1
->flags
, LS_PREF_IGP_FLAG
)
391 && (p1
->igp_flag
!= p2
->igp_flag
))
393 if (CHECK_FLAG(p1
->flags
, LS_PREF_ROUTE_TAG
)
394 && (p1
->route_tag
!= p2
->route_tag
))
396 if (CHECK_FLAG(p1
->flags
, LS_PREF_EXTENDED_TAG
)
397 && (p1
->extended_tag
!= p2
->extended_tag
))
399 if (CHECK_FLAG(p1
->flags
, LS_PREF_METRIC
) && (p1
->metric
!= p2
->metric
))
401 if (CHECK_FLAG(p1
->flags
, LS_PREF_SR
)) {
402 if ((p1
->sr
.algo
!= p2
->sr
.algo
) || (p1
->sr
.sid
!= p2
->sr
.sid
)
403 || (p1
->sr
.sid_flag
!= p2
->sr
.sid_flag
))
407 /* OK, p1 & p2 are equal */
412 * Link State Vertices management functions
414 uint64_t sysid_to_key(const uint8_t sysid
[ISO_SYS_ID_LEN
])
418 #if BYTE_ORDER == LITTLE_ENDIAN
419 uint8_t *byte
= (uint8_t *)&key
;
421 for (int i
= 0; i
< ISO_SYS_ID_LEN
; i
++)
422 byte
[i
] = sysid
[ISO_SYS_ID_LEN
- i
- 1];
427 memcpy(&key
, sysid
, ISO_SYS_ID_LEN
);
433 struct ls_vertex
*ls_vertex_add(struct ls_ted
*ted
, struct ls_node
*node
)
435 struct ls_vertex
*new;
438 if ((ted
== NULL
) || (node
== NULL
))
441 /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
442 switch (node
->adv
.origin
) {
446 key
= ((uint64_t)ntohl(node
->adv
.id
.ip
.addr
.s_addr
))
451 key
= sysid_to_key(node
->adv
.id
.iso
.sys_id
);
458 /* Check that key is valid */
462 /* Create Vertex and add it to the TED */
463 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_vertex
));
471 new->incoming_edges
= list_new();
472 new->incoming_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
473 new->outgoing_edges
= list_new();
474 new->outgoing_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
475 new->prefixes
= list_new();
476 new->prefixes
->cmp
= (int (*)(void *, void *))subnet_cmp
;
477 vertices_add(&ted
->vertices
, new);
482 void ls_vertex_del(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
484 struct listnode
*node
, *nnode
;
485 struct ls_edge
*edge
;
486 struct ls_subnet
*subnet
;
491 /* Remove outgoing Edges and list */
492 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
))
493 ls_edge_del_all(ted
, edge
);
494 list_delete(&vertex
->outgoing_edges
);
496 /* Disconnect incoming Edges and remove list */
497 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
498 ls_disconnect(vertex
, edge
, false);
499 if (edge
->source
== NULL
)
500 ls_edge_del_all(ted
, edge
);
502 list_delete(&vertex
->incoming_edges
);
504 /* Remove subnet and list */
505 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
))
506 ls_subnet_del_all(ted
, subnet
);
507 list_delete(&vertex
->prefixes
);
509 /* Then remove Vertex from Link State Data Base and free memory */
510 vertices_del(&ted
->vertices
, vertex
);
511 XFREE(MTYPE_LS_DB
, vertex
);
515 void ls_vertex_del_all(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
520 /* First remove associated Link State Node */
521 ls_node_del(vertex
->node
);
523 /* Then, Vertex itself */
524 ls_vertex_del(ted
, vertex
);
527 struct ls_vertex
*ls_vertex_update(struct ls_ted
*ted
, struct ls_node
*node
)
529 struct ls_vertex
*old
;
534 old
= ls_find_vertex_by_id(ted
, node
->adv
);
536 if (!ls_node_same(old
->node
, node
)) {
537 ls_node_del(old
->node
);
540 old
->status
= UPDATE
;
544 return ls_vertex_add(ted
, node
);
547 struct ls_vertex
*ls_find_vertex_by_key(struct ls_ted
*ted
, const uint64_t key
)
549 struct ls_vertex vertex
= {};
555 return vertices_find(&ted
->vertices
, &vertex
);
558 struct ls_vertex
*ls_find_vertex_by_id(struct ls_ted
*ted
,
559 struct ls_node_id nid
)
561 struct ls_vertex vertex
= {};
564 switch (nid
.origin
) {
569 ((uint64_t)ntohl(nid
.id
.ip
.addr
.s_addr
)) & 0xffffffff;
573 vertex
.key
= sysid_to_key(nid
.id
.iso
.sys_id
);
579 return vertices_find(&ted
->vertices
, &vertex
);
582 int ls_vertex_same(struct ls_vertex
*v1
, struct ls_vertex
*v2
)
584 if ((v1
&& !v2
) || (!v1
&& v2
))
590 if (v1
->key
!= v2
->key
)
593 if (v1
->node
== v2
->node
)
596 return ls_node_same(v1
->node
, v2
->node
);
599 void ls_vertex_clean(struct ls_ted
*ted
, struct ls_vertex
*vertex
,
600 struct zclient
*zclient
)
602 struct listnode
*node
, *nnode
;
603 struct ls_edge
*edge
;
604 struct ls_subnet
*subnet
;
605 struct ls_message msg
;
607 /* Remove Orphan Edge ... */
608 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
)) {
609 if (edge
->status
== ORPHAN
) {
611 edge
->status
= DELETE
;
612 ls_edge2msg(&msg
, edge
);
613 ls_send_msg(zclient
, &msg
, NULL
);
615 ls_edge_del_all(ted
, edge
);
618 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
619 if (edge
->status
== ORPHAN
) {
621 edge
->status
= DELETE
;
622 ls_edge2msg(&msg
, edge
);
623 ls_send_msg(zclient
, &msg
, NULL
);
625 ls_edge_del_all(ted
, edge
);
629 /* ... and Subnet from the Vertex */
630 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
)) {
631 if (subnet
->status
== ORPHAN
) {
633 subnet
->status
= DELETE
;
634 ls_subnet2msg(&msg
, subnet
);
635 ls_send_msg(zclient
, &msg
, NULL
);
637 ls_subnet_del_all(ted
, subnet
);
643 * Link State Edges management functions
647 * This function allows to connect the Edge to the vertices present in the TED.
648 * A temporary vertex that corresponds to the source of this Edge i.e. the
649 * advertised router, is created if not found in the Data Base. If a Edge that
650 * corresponds to the reverse path is found, the Edge is attached to the
651 * destination vertex as destination and reverse Edge is attached to the source
654 * @param ted Link State Data Base
655 * @param edge Link State Edge to be attached
657 static void ls_edge_connect_to(struct ls_ted
*ted
, struct ls_edge
*edge
)
659 struct ls_vertex
*vertex
= NULL
;
660 struct ls_node
*node
;
662 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
664 /* First, search if there is a Vertex that correspond to the Node ID */
665 vertex
= ls_find_vertex_by_id(ted
, edge
->attributes
->adv
);
666 if (vertex
== NULL
) {
667 /* Create a new temporary Node & Vertex if not found */
668 node
= ls_node_new(edge
->attributes
->adv
, inaddr_any
,
670 vertex
= ls_vertex_add(ted
, node
);
672 /* and attach the edge as source to the vertex */
673 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
674 edge
->source
= vertex
;
676 /* Then search if there is a reverse Edge */
677 dst
= ls_find_edge_by_destination(ted
, edge
->attributes
);
678 /* attach the destination edge to the vertex */
680 listnode_add_sort_nodup(vertex
->incoming_edges
, dst
);
681 dst
->destination
= vertex
;
682 /* and destination vertex to this edge */
683 vertex
= dst
->source
;
684 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
685 edge
->destination
= vertex
;
689 static uint64_t get_edge_key(struct ls_attributes
*attr
, bool dst
)
692 struct ls_standard
*std
;
697 std
= &attr
->standard
;
700 /* Key is the IPv4 remote address */
701 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
702 key
= ((uint64_t)ntohl(std
->remote
.s_addr
))
704 /* or the 64 bits LSB of IPv6 remote address */
705 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
706 key
= ((uint64_t)ntohl(std
->remote6
.s6_addr32
[2]) << 32
707 | (uint64_t)ntohl(std
->remote6
.s6_addr32
[3]));
708 /* of remote identifier if no IP addresses are defined */
709 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
710 key
= (((uint64_t)std
->remote_id
) & 0xffffffff)
711 | ((uint64_t)std
->local_id
<< 32);
713 /* Key is the IPv4 local address */
714 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
715 key
= ((uint64_t)ntohl(std
->local
.s_addr
)) & 0xffffffff;
716 /* or the 64 bits LSB of IPv6 local address */
717 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
718 key
= ((uint64_t)ntohl(std
->local6
.s6_addr32
[2]) << 32
719 | (uint64_t)ntohl(std
->local6
.s6_addr32
[3]));
720 /* of local identifier if no IP addresses are defined */
721 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
722 key
= (((uint64_t)std
->local_id
) & 0xffffffff)
723 | ((uint64_t)std
->remote_id
<< 32);
729 struct ls_edge
*ls_edge_add(struct ls_ted
*ted
,
730 struct ls_attributes
*attributes
)
735 if (attributes
== NULL
)
738 key
= get_edge_key(attributes
, false);
742 /* Create Edge and add it to the TED */
743 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_edge
));
745 new->attributes
= attributes
;
749 edges_add(&ted
->edges
, new);
751 /* Finally, connect Edge to Vertices */
752 ls_edge_connect_to(ted
, new);
757 struct ls_edge
*ls_find_edge_by_key(struct ls_ted
*ted
, const uint64_t key
)
759 struct ls_edge edge
= {};
765 return edges_find(&ted
->edges
, &edge
);
768 struct ls_edge
*ls_find_edge_by_source(struct ls_ted
*ted
,
769 struct ls_attributes
*attributes
)
771 struct ls_edge edge
= {};
773 if (attributes
== NULL
)
776 edge
.key
= get_edge_key(attributes
, false);
780 return edges_find(&ted
->edges
, &edge
);
783 struct ls_edge
*ls_find_edge_by_destination(struct ls_ted
*ted
,
784 struct ls_attributes
*attributes
)
786 struct ls_edge edge
= {};
788 if (attributes
== NULL
)
791 edge
.key
= get_edge_key(attributes
, true);
795 return edges_find(&ted
->edges
, &edge
);
798 struct ls_edge
*ls_edge_update(struct ls_ted
*ted
,
799 struct ls_attributes
*attributes
)
803 if (attributes
== NULL
)
806 /* First, search for an existing Edge */
807 old
= ls_find_edge_by_source(ted
, attributes
);
809 /* Check if attributes are similar */
810 if (!ls_attributes_same(old
->attributes
, attributes
)) {
811 ls_attributes_del(old
->attributes
);
812 old
->attributes
= attributes
;
814 old
->status
= UPDATE
;
818 /* If not found, add new Edge from the attributes */
819 return ls_edge_add(ted
, attributes
);
822 int ls_edge_same(struct ls_edge
*e1
, struct ls_edge
*e2
)
824 if ((e1
&& !e2
) || (!e1
&& e2
))
830 if (e1
->key
!= e2
->key
)
833 if (e1
->attributes
== e2
->attributes
)
836 return ls_attributes_same(e1
->attributes
, e2
->attributes
);
839 void ls_edge_del(struct ls_ted
*ted
, struct ls_edge
*edge
)
844 /* Fist disconnect Edge from Vertices */
845 ls_disconnect_edge(edge
);
846 /* Then remove it from the Data Base */
847 edges_del(&ted
->edges
, edge
);
848 XFREE(MTYPE_LS_DB
, edge
);
851 void ls_edge_del_all(struct ls_ted
*ted
, struct ls_edge
*edge
)
856 /* Remove associated Link State Attributes */
857 ls_attributes_del(edge
->attributes
);
858 /* Then Edge itself */
859 ls_edge_del(ted
, edge
);
863 * Link State Subnet Management functions.
865 struct ls_subnet
*ls_subnet_add(struct ls_ted
*ted
,
866 struct ls_prefix
*ls_pref
)
868 struct ls_subnet
*new;
869 struct ls_vertex
*vertex
;
870 struct ls_node
*node
;
871 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
876 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_subnet
));
877 new->ls_pref
= ls_pref
;
878 new->key
= ls_pref
->pref
;
883 vertex
= ls_find_vertex_by_id(ted
, ls_pref
->adv
);
884 if (vertex
== NULL
) {
885 /* Create a new temporary Node & Vertex if not found */
886 node
= ls_node_new(ls_pref
->adv
, inaddr_any
, in6addr_any
);
887 vertex
= ls_vertex_add(ted
, node
);
889 /* And attach the subnet to the corresponding Vertex */
890 new->vertex
= vertex
;
891 listnode_add_sort_nodup(vertex
->prefixes
, new);
893 subnets_add(&ted
->subnets
, new);
898 struct ls_subnet
*ls_subnet_update(struct ls_ted
*ted
, struct ls_prefix
*pref
)
900 struct ls_subnet
*old
;
905 old
= ls_find_subnet(ted
, pref
->pref
);
907 if (!ls_prefix_same(old
->ls_pref
, pref
)) {
908 ls_prefix_del(old
->ls_pref
);
911 old
->status
= UPDATE
;
915 return ls_subnet_add(ted
, pref
);
918 int ls_subnet_same(struct ls_subnet
*s1
, struct ls_subnet
*s2
)
920 if ((s1
&& !s2
) || (!s1
&& s2
))
926 if (!prefix_same(&s1
->key
, &s2
->key
))
929 if (s1
->ls_pref
== s2
->ls_pref
)
932 return ls_prefix_same(s1
->ls_pref
, s2
->ls_pref
);
935 void ls_subnet_del(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
940 /* First, disconnect Subnet from associated Vertex */
941 listnode_delete(subnet
->vertex
->prefixes
, subnet
);
942 /* Then delete Subnet */
943 subnets_del(&ted
->subnets
, subnet
);
944 XFREE(MTYPE_LS_DB
, subnet
);
947 void ls_subnet_del_all(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
952 /* First, remove associated Link State Subnet */
953 ls_prefix_del(subnet
->ls_pref
);
954 /* Then, delete Subnet itself */
955 ls_subnet_del(ted
, subnet
);
958 struct ls_subnet
*ls_find_subnet(struct ls_ted
*ted
, const struct prefix prefix
)
960 struct ls_subnet subnet
= {};
963 return subnets_find(&ted
->subnets
, &subnet
);
967 * Link State TED management functions
969 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
974 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
976 /* Set basic information for this ted */
978 new->as_number
= as_number
;
979 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
981 /* Initialize the various RB tree */
982 vertices_init(&new->vertices
);
983 edges_init(&new->edges
);
984 subnets_init(&new->subnets
);
989 void ls_ted_del(struct ls_ted
*ted
)
994 /* Check that TED is empty */
995 if (vertices_count(&ted
->vertices
) || edges_count(&ted
->edges
)
996 || subnets_count(&ted
->subnets
))
999 /* Release RB Tree */
1000 vertices_fini(&ted
->vertices
);
1001 edges_fini(&ted
->edges
);
1002 subnets_fini(&ted
->subnets
);
1004 XFREE(MTYPE_LS_DB
, ted
);
1007 void ls_ted_del_all(struct ls_ted
**ted
)
1009 struct ls_vertex
*vertex
;
1010 struct ls_edge
*edge
;
1011 struct ls_subnet
*subnet
;
1016 /* First remove Vertices, Edges and Subnets and associated Link State */
1017 frr_each_safe (vertices
, &(*ted
)->vertices
, vertex
)
1018 ls_vertex_del_all(*ted
, vertex
);
1019 frr_each_safe (edges
, &(*ted
)->edges
, edge
)
1020 ls_edge_del_all(*ted
, edge
);
1021 frr_each_safe (subnets
, &(*ted
)->subnets
, subnet
)
1022 ls_subnet_del_all(*ted
, subnet
);
1024 /* then remove TED itself */
1029 void ls_ted_clean(struct ls_ted
*ted
)
1031 struct ls_vertex
*vertex
;
1032 struct ls_edge
*edge
;
1033 struct ls_subnet
*subnet
;
1038 /* First, start with Vertices */
1039 frr_each_safe (vertices
, &ted
->vertices
, vertex
)
1040 if (vertex
->status
== ORPHAN
)
1041 ls_vertex_del_all(ted
, vertex
);
1044 frr_each_safe (edges
, &ted
->edges
, edge
)
1045 if (edge
->status
== ORPHAN
)
1046 ls_edge_del_all(ted
, edge
);
1049 frr_each_safe (subnets
, &ted
->subnets
, subnet
)
1050 if (subnet
->status
== ORPHAN
)
1051 ls_subnet_del_all(ted
, subnet
);
1055 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1057 if (vertex
== NULL
|| edge
== NULL
)
1061 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
1062 edge
->source
= vertex
;
1064 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
1065 edge
->destination
= vertex
;
1069 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1072 if (vertex
== NULL
|| edge
== NULL
)
1076 listnode_delete(vertex
->outgoing_edges
, edge
);
1077 edge
->source
= NULL
;
1079 listnode_delete(vertex
->incoming_edges
, edge
);
1080 edge
->destination
= NULL
;
1084 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
1085 struct ls_edge
*edge
)
1091 edge
->destination
= dst
;
1094 listnode_add_sort_nodup(src
->outgoing_edges
, edge
);
1097 listnode_add_sort_nodup(dst
->incoming_edges
, edge
);
1100 void ls_disconnect_edge(struct ls_edge
*edge
)
1105 ls_disconnect(edge
->source
, edge
, true);
1106 ls_disconnect(edge
->destination
, edge
, false);
1108 /* Mark this Edge as ORPHAN for future cleanup */
1109 edge
->status
= ORPHAN
;
1113 * Link State Message management functions
1116 int ls_register(struct zclient
*zclient
, bool server
)
1121 rc
= zclient_register_opaque(zclient
, LINK_STATE_SYNC
);
1123 rc
= zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
1128 int ls_unregister(struct zclient
*zclient
, bool server
)
1133 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_SYNC
);
1135 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_UPDATE
);
1140 int ls_request_sync(struct zclient
*zclient
)
1145 /* Check buffer size */
1146 if (STREAM_SIZE(zclient
->obuf
)
1147 < (ZEBRA_HEADER_SIZE
+ 3 * sizeof(uint32_t)))
1153 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1155 /* Set type and flags */
1156 stream_putl(s
, LINK_STATE_SYNC
);
1157 stream_putw(s
, flags
);
1158 /* Send destination client info */
1159 stream_putc(s
, zclient
->redist_default
);
1160 stream_putw(s
, zclient
->instance
);
1161 stream_putl(s
, zclient
->session_id
);
1163 /* Put length into the header at the start of the stream. */
1164 stream_putw_at(s
, 0, stream_get_endp(s
));
1166 return zclient_send_message(zclient
);
1169 static struct ls_node
*ls_parse_node(struct stream
*s
)
1171 struct ls_node
*node
;
1174 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
1176 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
1177 STREAM_GETW(s
, node
->flags
);
1178 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1179 STREAM_GETC(s
, len
);
1180 STREAM_GET(node
->name
, s
, len
);
1182 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1183 node
->router_id
.s_addr
= stream_get_ipv4(s
);
1184 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1185 STREAM_GET(&node
->router_id6
, s
, IPV6_MAX_BYTELEN
);
1186 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1187 STREAM_GETC(s
, node
->node_flag
);
1188 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1189 STREAM_GETC(s
, node
->type
);
1190 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1191 STREAM_GETL(s
, node
->as_number
);
1192 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1193 STREAM_GETL(s
, node
->srgb
.lower_bound
);
1194 STREAM_GETL(s
, node
->srgb
.range_size
);
1195 STREAM_GETC(s
, node
->srgb
.flag
);
1196 STREAM_GET(node
->algo
, s
, 2);
1198 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1199 STREAM_GETL(s
, node
->srlb
.lower_bound
);
1200 STREAM_GETL(s
, node
->srlb
.range_size
);
1202 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1203 STREAM_GETC(s
, node
->msd
);
1208 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
1209 XFREE(MTYPE_LS_DB
, node
);
1213 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
1215 struct ls_attributes
*attr
;
1216 uint8_t nb_ext_adm_grp
;
1217 uint32_t bitmap_data
;
1220 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
1221 admin_group_init(&attr
->ext_admin_group
);
1224 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
1225 STREAM_GETL(s
, attr
->flags
);
1226 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1227 STREAM_GETC(s
, len
);
1228 STREAM_GET(attr
->name
, s
, len
);
1230 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1231 STREAM_GETL(s
, attr
->metric
);
1232 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1233 STREAM_GETL(s
, attr
->standard
.te_metric
);
1234 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1235 STREAM_GETL(s
, attr
->standard
.admin_group
);
1236 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
1237 /* Extended Administrative Group */
1238 STREAM_GETC(s
, nb_ext_adm_grp
);
1239 for (size_t i
= 0; i
< nb_ext_adm_grp
; i
++) {
1240 STREAM_GETL(s
, bitmap_data
);
1241 admin_group_bulk_set(&attr
->ext_admin_group
,
1245 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1246 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
1247 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1248 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
1249 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1250 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
1251 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1252 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
1253 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1254 STREAM_GETL(s
, attr
->standard
.local_id
);
1255 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1256 STREAM_GETL(s
, attr
->standard
.remote_id
);
1257 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1258 STREAM_GETF(s
, attr
->standard
.max_bw
);
1259 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1260 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
1261 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1262 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1263 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
1264 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1265 STREAM_GETL(s
, attr
->standard
.remote_as
);
1266 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1267 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
1268 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1269 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
1270 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1271 STREAM_GETL(s
, attr
->extended
.delay
);
1272 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1273 STREAM_GETL(s
, attr
->extended
.min_delay
);
1274 STREAM_GETL(s
, attr
->extended
.max_delay
);
1276 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1277 STREAM_GETL(s
, attr
->extended
.jitter
);
1278 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1279 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
1280 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1281 STREAM_GETF(s
, attr
->extended
.ava_bw
);
1282 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1283 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
1284 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1285 STREAM_GETF(s
, attr
->extended
.used_bw
);
1286 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1287 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1288 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1289 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1290 attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
=
1293 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1294 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1295 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1296 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1297 attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
=
1300 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1301 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1302 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1303 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1304 STREAM_GET(attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
, s
,
1307 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1308 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1309 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1310 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1311 STREAM_GET(attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
, s
,
1314 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1315 STREAM_GETC(s
, len
);
1316 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
1317 attr
->srlg_len
= len
;
1318 for (len
= 0; len
< attr
->srlg_len
; len
++)
1319 STREAM_GETL(s
, attr
->srlgs
[len
]);
1325 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1327 /* Clean memory allocation */
1328 if (attr
->srlgs
!= NULL
)
1329 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
1330 XFREE(MTYPE_LS_DB
, attr
);
1335 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
1337 struct ls_prefix
*ls_pref
;
1340 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
1342 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
1343 STREAM_GETW(s
, ls_pref
->flags
);
1344 STREAM_GETC(s
, ls_pref
->pref
.family
);
1345 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
1346 len
= prefix_blen(&ls_pref
->pref
);
1347 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
1348 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1349 STREAM_GETC(s
, ls_pref
->igp_flag
);
1350 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1351 STREAM_GETL(s
, ls_pref
->route_tag
);
1352 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1353 STREAM_GETQ(s
, ls_pref
->extended_tag
);
1354 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1355 STREAM_GETL(s
, ls_pref
->metric
);
1356 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1357 STREAM_GETL(s
, ls_pref
->sr
.sid
);
1358 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
1359 STREAM_GETC(s
, ls_pref
->sr
.algo
);
1365 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
1366 XFREE(MTYPE_LS_DB
, ls_pref
);
1370 struct ls_message
*ls_parse_msg(struct stream
*s
)
1372 struct ls_message
*msg
;
1374 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1376 /* Read LS Message header */
1377 STREAM_GETC(s
, msg
->event
);
1378 STREAM_GETC(s
, msg
->type
);
1380 /* Read Message Payload */
1381 switch (msg
->type
) {
1382 case LS_MSG_TYPE_NODE
:
1383 msg
->data
.node
= ls_parse_node(s
);
1385 case LS_MSG_TYPE_ATTRIBUTES
:
1386 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
1387 msg
->data
.attr
= ls_parse_attributes(s
);
1389 case LS_MSG_TYPE_PREFIX
:
1390 msg
->data
.prefix
= ls_parse_prefix(s
);
1393 zlog_err("Unsupported Payload");
1394 goto stream_failure
;
1397 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
1398 || msg
->data
.prefix
== NULL
)
1399 goto stream_failure
;
1404 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
1405 XFREE(MTYPE_LS_DB
, msg
);
1409 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
1413 /* Push Advertise node information first */
1414 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
1416 /* Push Flags & Origin then Node information if there are present */
1417 stream_putw(s
, node
->flags
);
1418 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1419 len
= strlen(node
->name
);
1420 stream_putc(s
, len
+ 1);
1421 stream_put(s
, node
->name
, len
);
1422 stream_putc(s
, '\0');
1424 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1425 stream_put_ipv4(s
, node
->router_id
.s_addr
);
1426 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1427 stream_put(s
, &node
->router_id6
, IPV6_MAX_BYTELEN
);
1428 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1429 stream_putc(s
, node
->node_flag
);
1430 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1431 stream_putc(s
, node
->type
);
1432 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1433 stream_putl(s
, node
->as_number
);
1434 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1435 stream_putl(s
, node
->srgb
.lower_bound
);
1436 stream_putl(s
, node
->srgb
.range_size
);
1437 stream_putc(s
, node
->srgb
.flag
);
1438 stream_put(s
, node
->algo
, 2);
1440 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1441 stream_putl(s
, node
->srlb
.lower_bound
);
1442 stream_putl(s
, node
->srlb
.range_size
);
1444 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1445 stream_putc(s
, node
->msd
);
1450 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
1452 size_t len
, nb_ext_adm_grp
;
1454 /* Push Advertise node information first */
1455 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
1457 /* Push Flags & Origin then LS attributes if there are present */
1458 stream_putl(s
, attr
->flags
);
1459 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1460 len
= strlen(attr
->name
);
1461 stream_putc(s
, len
+ 1);
1462 stream_put(s
, attr
->name
, len
);
1463 stream_putc(s
, '\0');
1465 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1466 stream_putl(s
, attr
->metric
);
1467 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1468 stream_putl(s
, attr
->standard
.te_metric
);
1469 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1470 stream_putl(s
, attr
->standard
.admin_group
);
1471 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
1472 /* Extended Administrative Group */
1473 nb_ext_adm_grp
= admin_group_nb_words(&attr
->ext_admin_group
);
1474 stream_putc(s
, nb_ext_adm_grp
);
1475 for (size_t i
= 0; i
< nb_ext_adm_grp
; i
++)
1476 stream_putl(s
, admin_group_get_offset(
1477 &attr
->ext_admin_group
, i
));
1479 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1480 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
1481 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1482 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
1483 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1484 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
1485 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1486 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
1487 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1488 stream_putl(s
, attr
->standard
.local_id
);
1489 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1490 stream_putl(s
, attr
->standard
.remote_id
);
1491 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1492 stream_putf(s
, attr
->standard
.max_bw
);
1493 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1494 stream_putf(s
, attr
->standard
.max_rsv_bw
);
1495 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1496 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1497 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
1498 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1499 stream_putl(s
, attr
->standard
.remote_as
);
1500 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1501 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
1502 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1503 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
1504 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1505 stream_putl(s
, attr
->extended
.delay
);
1506 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1507 stream_putl(s
, attr
->extended
.min_delay
);
1508 stream_putl(s
, attr
->extended
.max_delay
);
1510 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1511 stream_putl(s
, attr
->extended
.jitter
);
1512 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1513 stream_putl(s
, attr
->extended
.pkt_loss
);
1514 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1515 stream_putf(s
, attr
->extended
.ava_bw
);
1516 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1517 stream_putf(s
, attr
->extended
.rsv_bw
);
1518 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1519 stream_putf(s
, attr
->extended
.used_bw
);
1520 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1521 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1522 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1523 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1525 s
, attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
);
1527 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1528 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1529 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1530 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1532 s
, attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
);
1534 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1535 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1536 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1537 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1538 stream_put(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
,
1541 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1542 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1543 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1544 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1545 stream_put(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
,
1548 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1549 stream_putc(s
, attr
->srlg_len
);
1550 for (len
= 0; len
< attr
->srlg_len
; len
++)
1551 stream_putl(s
, attr
->srlgs
[len
]);
1557 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1561 /* Push Advertise node information first */
1562 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1564 /* Push Flags, Origin & Prefix then information if there are present */
1565 stream_putw(s
, ls_pref
->flags
);
1566 stream_putc(s
, ls_pref
->pref
.family
);
1567 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1568 len
= prefix_blen(&ls_pref
->pref
);
1569 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1570 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1571 stream_putc(s
, ls_pref
->igp_flag
);
1572 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1573 stream_putl(s
, ls_pref
->route_tag
);
1574 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1575 stream_putq(s
, ls_pref
->extended_tag
);
1576 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1577 stream_putl(s
, ls_pref
->metric
);
1578 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1579 stream_putl(s
, ls_pref
->sr
.sid
);
1580 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1581 stream_putc(s
, ls_pref
->sr
.algo
);
1587 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1590 /* Prepare Link State header */
1591 stream_putc(s
, msg
->event
);
1592 stream_putc(s
, msg
->type
);
1594 /* Add Message Payload */
1595 switch (msg
->type
) {
1596 case LS_MSG_TYPE_NODE
:
1597 return ls_format_node(s
, msg
->data
.node
);
1598 case LS_MSG_TYPE_ATTRIBUTES
:
1599 /* Add remote node first */
1600 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1601 return ls_format_attributes(s
, msg
->data
.attr
);
1602 case LS_MSG_TYPE_PREFIX
:
1603 return ls_format_prefix(s
, msg
->data
.prefix
);
1605 zlog_warn("Unsupported Payload");
1612 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1613 struct zapi_opaque_reg_info
*dst
)
1618 /* Check if we have a valid message */
1619 if (msg
->event
== LS_MSG_EVENT_UNDEF
)
1622 /* Check buffer size */
1623 if (STREAM_SIZE(zclient
->obuf
) <
1624 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1630 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1632 /* Set sub-type, flags and destination for unicast message */
1633 stream_putl(s
, LINK_STATE_UPDATE
);
1635 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1636 stream_putw(s
, flags
);
1637 /* Send destination client info */
1638 stream_putc(s
, dst
->proto
);
1639 stream_putw(s
, dst
->instance
);
1640 stream_putl(s
, dst
->session_id
);
1642 stream_putw(s
, flags
);
1645 /* Format Link State message */
1646 if (ls_format_msg(s
, msg
) < 0) {
1651 /* Put length into the header at the start of the stream. */
1652 stream_putw_at(s
, 0, stream_get_endp(s
));
1654 return zclient_send_message(zclient
);
1656 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1657 struct ls_vertex
*vertex
)
1659 /* Allocate space if needed */
1661 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1663 memset(msg
, 0, sizeof(*msg
));
1665 msg
->type
= LS_MSG_TYPE_NODE
;
1666 switch (vertex
->status
) {
1668 msg
->event
= LS_MSG_EVENT_ADD
;
1671 msg
->event
= LS_MSG_EVENT_UPDATE
;
1674 msg
->event
= LS_MSG_EVENT_DELETE
;
1677 msg
->event
= LS_MSG_EVENT_SYNC
;
1681 msg
->event
= LS_MSG_EVENT_UNDEF
;
1684 msg
->data
.node
= vertex
->node
;
1685 msg
->remote_id
.origin
= UNKNOWN
;
1690 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1692 /* Allocate space if needed */
1694 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1696 memset(msg
, 0, sizeof(*msg
));
1698 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1699 switch (edge
->status
) {
1701 msg
->event
= LS_MSG_EVENT_ADD
;
1704 msg
->event
= LS_MSG_EVENT_UPDATE
;
1707 msg
->event
= LS_MSG_EVENT_DELETE
;
1710 msg
->event
= LS_MSG_EVENT_SYNC
;
1714 msg
->event
= LS_MSG_EVENT_UNDEF
;
1717 msg
->data
.attr
= edge
->attributes
;
1718 if (edge
->destination
!= NULL
)
1719 msg
->remote_id
= edge
->destination
->node
->adv
;
1721 msg
->remote_id
.origin
= UNKNOWN
;
1726 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1727 struct ls_subnet
*subnet
)
1729 /* Allocate space if needed */
1731 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1733 memset(msg
, 0, sizeof(*msg
));
1735 msg
->type
= LS_MSG_TYPE_PREFIX
;
1736 switch (subnet
->status
) {
1738 msg
->event
= LS_MSG_EVENT_ADD
;
1741 msg
->event
= LS_MSG_EVENT_UPDATE
;
1744 msg
->event
= LS_MSG_EVENT_DELETE
;
1747 msg
->event
= LS_MSG_EVENT_SYNC
;
1751 msg
->event
= LS_MSG_EVENT_UNDEF
;
1754 msg
->data
.prefix
= subnet
->ls_pref
;
1755 msg
->remote_id
.origin
= UNKNOWN
;
1760 struct ls_vertex
*ls_msg2vertex(struct ls_ted
*ted
, struct ls_message
*msg
,
1763 struct ls_node
*node
= (struct ls_node
*)msg
->data
.node
;
1764 struct ls_vertex
*vertex
= NULL
;
1766 switch (msg
->event
) {
1767 case LS_MSG_EVENT_SYNC
:
1768 vertex
= ls_vertex_add(ted
, node
);
1770 vertex
->status
= SYNC
;
1772 case LS_MSG_EVENT_ADD
:
1773 vertex
= ls_vertex_add(ted
, node
);
1775 vertex
->status
= NEW
;
1777 case LS_MSG_EVENT_UPDATE
:
1778 vertex
= ls_vertex_update(ted
, node
);
1780 vertex
->status
= UPDATE
;
1782 case LS_MSG_EVENT_DELETE
:
1783 vertex
= ls_find_vertex_by_id(ted
, node
->adv
);
1786 ls_vertex_del_all(ted
, vertex
);
1788 vertex
->status
= DELETE
;
1799 struct ls_edge
*ls_msg2edge(struct ls_ted
*ted
, struct ls_message
*msg
,
1802 struct ls_attributes
*attr
= (struct ls_attributes
*)msg
->data
.attr
;
1803 struct ls_edge
*edge
= NULL
;
1805 switch (msg
->event
) {
1806 case LS_MSG_EVENT_SYNC
:
1807 edge
= ls_edge_add(ted
, attr
);
1809 edge
->status
= SYNC
;
1811 case LS_MSG_EVENT_ADD
:
1812 edge
= ls_edge_add(ted
, attr
);
1816 case LS_MSG_EVENT_UPDATE
:
1817 edge
= ls_edge_update(ted
, attr
);
1819 edge
->status
= UPDATE
;
1821 case LS_MSG_EVENT_DELETE
:
1822 edge
= ls_find_edge_by_source(ted
, attr
);
1825 ls_edge_del_all(ted
, edge
);
1828 edge
->status
= DELETE
;
1839 struct ls_subnet
*ls_msg2subnet(struct ls_ted
*ted
, struct ls_message
*msg
,
1842 struct ls_prefix
*pref
= (struct ls_prefix
*)msg
->data
.prefix
;
1843 struct ls_subnet
*subnet
= NULL
;
1845 switch (msg
->event
) {
1846 case LS_MSG_EVENT_SYNC
:
1847 subnet
= ls_subnet_add(ted
, pref
);
1849 subnet
->status
= SYNC
;
1851 case LS_MSG_EVENT_ADD
:
1852 subnet
= ls_subnet_add(ted
, pref
);
1854 subnet
->status
= NEW
;
1856 case LS_MSG_EVENT_UPDATE
:
1857 subnet
= ls_subnet_update(ted
, pref
);
1859 subnet
->status
= UPDATE
;
1861 case LS_MSG_EVENT_DELETE
:
1862 subnet
= ls_find_subnet(ted
, pref
->pref
);
1865 ls_subnet_del_all(ted
, subnet
);
1867 subnet
->status
= DELETE
;
1878 struct ls_element
*ls_msg2ted(struct ls_ted
*ted
, struct ls_message
*msg
,
1881 struct ls_element
*lse
= NULL
;
1883 switch (msg
->type
) {
1884 case LS_MSG_TYPE_NODE
:
1885 lse
= (struct ls_element
*)ls_msg2vertex(ted
, msg
, delete);
1887 case LS_MSG_TYPE_ATTRIBUTES
:
1888 lse
= (struct ls_element
*)ls_msg2edge(ted
, msg
, delete);
1890 case LS_MSG_TYPE_PREFIX
:
1891 lse
= (struct ls_element
*)ls_msg2subnet(ted
, msg
, delete);
1901 struct ls_element
*ls_stream2ted(struct ls_ted
*ted
, struct stream
*s
,
1904 struct ls_message
*msg
;
1905 struct ls_element
*lse
= NULL
;
1907 msg
= ls_parse_msg(s
);
1909 lse
= ls_msg2ted(ted
, msg
, delete);
1916 void ls_delete_msg(struct ls_message
*msg
)
1921 XFREE(MTYPE_LS_DB
, msg
);
1924 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1925 struct zapi_opaque_reg_info
*dst
)
1927 struct ls_vertex
*vertex
;
1928 struct ls_edge
*edge
;
1929 struct ls_subnet
*subnet
;
1930 struct ls_message msg
;
1932 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1933 frr_each(vertices
, &ted
->vertices
, vertex
) {
1934 ls_vertex2msg(&msg
, vertex
);
1935 ls_send_msg(zclient
, &msg
, dst
);
1937 frr_each(edges
, &ted
->edges
, edge
) {
1938 ls_edge2msg(&msg
, edge
);
1939 ls_send_msg(zclient
, &msg
, dst
);
1941 frr_each(subnets
, &ted
->subnets
, subnet
) {
1942 ls_subnet2msg(&msg
, subnet
);
1943 ls_send_msg(zclient
, &msg
, dst
);
1949 * Link State Show functions
1951 static const char *const origin2txt
[] = {
1960 static const char *const type2txt
[] = {
1969 static const char *const status2txt
[] = {
1978 static const char *ls_node_id_to_text(struct ls_node_id lnid
, char *str
,
1981 if (lnid
.origin
== ISIS_L1
|| lnid
.origin
== ISIS_L2
) {
1984 id
= lnid
.id
.iso
.sys_id
;
1985 snprintfrr(str
, size
, "%02x%02x.%02x%02x.%02x%02x", id
[0],
1986 id
[1], id
[2], id
[3], id
[4], id
[5]);
1988 snprintfrr(str
, size
, "%pI4", &lnid
.id
.ip
.addr
);
1993 static void ls_show_vertex_vty(struct ls_vertex
*vertex
, struct vty
*vty
,
1996 struct listnode
*node
;
1997 struct ls_node
*lsn
;
1998 struct ls_edge
*edge
;
1999 struct ls_attributes
*attr
;
2000 struct ls_subnet
*subnet
;
2010 sbuf_init(&sbuf
, NULL
, 0);
2012 sbuf_push(&sbuf
, 2, "Vertex (%" PRIu64
"): %s", vertex
->key
, lsn
->name
);
2013 sbuf_push(&sbuf
, 0, "\tRouter Id: %pI4", &lsn
->router_id
);
2014 sbuf_push(&sbuf
, 0, "\tOrigin: %s", origin2txt
[lsn
->adv
.origin
]);
2015 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[vertex
->status
]);
2019 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
2020 listcount(vertex
->outgoing_edges
),
2021 listcount(vertex
->incoming_edges
),
2022 listcount(vertex
->prefixes
));
2026 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2027 sbuf_push(&sbuf
, 4, "Type: %s\n", type2txt
[lsn
->type
]);
2028 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2029 sbuf_push(&sbuf
, 4, "AS number: %u\n", lsn
->as_number
);
2030 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2031 sbuf_push(&sbuf
, 4, "Segment Routing Capabilities:\n");
2032 upper
= lsn
->srgb
.lower_bound
+ lsn
->srgb
.range_size
- 1;
2033 sbuf_push(&sbuf
, 8, "SRGB: [%d/%d]", lsn
->srgb
.lower_bound
,
2035 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2036 upper
= lsn
->srlb
.lower_bound
+ lsn
->srlb
.range_size
2038 sbuf_push(&sbuf
, 0, "\tSRLB: [%d/%d]",
2039 lsn
->srlb
.lower_bound
, upper
);
2041 sbuf_push(&sbuf
, 0, "\tAlgo: ");
2042 for (int i
= 0; i
< 2; i
++) {
2043 if (lsn
->algo
[i
] == 255)
2047 lsn
->algo
[i
] == 0 ? "SPF " : "S-SPF ");
2049 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2050 sbuf_push(&sbuf
, 0, "\tMSD: %d", lsn
->msd
);
2051 sbuf_push(&sbuf
, 0, "\n");
2054 sbuf_push(&sbuf
, 4, "Outgoing Edges: %d\n",
2055 listcount(vertex
->outgoing_edges
));
2056 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, node
, edge
)) {
2057 if (edge
->destination
) {
2058 lsn
= edge
->destination
->node
;
2059 sbuf_push(&sbuf
, 6, "To:\t%s(%pI4)", lsn
->name
,
2062 sbuf_push(&sbuf
, 6, "To:\t- (0.0.0.0)");
2064 attr
= edge
->attributes
;
2065 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2066 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2067 &attr
->standard
.local
,
2068 &attr
->standard
.remote
);
2069 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2070 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2071 &attr
->standard
.local6
,
2072 &attr
->standard
.remote6
);
2075 sbuf_push(&sbuf
, 4, "Incoming Edges: %d\n",
2076 listcount(vertex
->incoming_edges
));
2077 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, node
, edge
)) {
2079 lsn
= edge
->source
->node
;
2080 sbuf_push(&sbuf
, 6, "From:\t%s(%pI4)", lsn
->name
,
2083 sbuf_push(&sbuf
, 6, "From:\t- (0.0.0.0)");
2085 attr
= edge
->attributes
;
2086 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2087 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2088 &attr
->standard
.local
,
2089 &attr
->standard
.remote
);
2090 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2091 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2092 &attr
->standard
.local6
,
2093 &attr
->standard
.remote6
);
2096 sbuf_push(&sbuf
, 4, "Subnets: %d\n", listcount(vertex
->prefixes
));
2097 for (ALL_LIST_ELEMENTS_RO(vertex
->prefixes
, node
, subnet
))
2098 sbuf_push(&sbuf
, 6, "Prefix:\t%pFX\n", &subnet
->key
);
2101 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2105 static void ls_show_vertex_json(struct ls_vertex
*vertex
,
2106 struct json_object
*json
)
2108 struct ls_node
*lsn
;
2109 json_object
*jsr
, *jalgo
, *jobj
;
2110 char buf
[INET6_BUFSIZ
];
2118 json_object_int_add(json
, "vertex-id", vertex
->key
);
2119 json_object_string_add(json
, "status", status2txt
[vertex
->status
]);
2120 json_object_string_add(json
, "origin", origin2txt
[lsn
->adv
.origin
]);
2121 if (CHECK_FLAG(lsn
->flags
, LS_NODE_NAME
))
2122 json_object_string_add(json
, "name", lsn
->name
);
2123 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID
)) {
2124 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &lsn
->router_id
);
2125 json_object_string_add(json
, "router-id", buf
);
2127 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID6
)) {
2128 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &lsn
->router_id6
);
2129 json_object_string_add(json
, "router-id-v6", buf
);
2131 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2132 json_object_string_add(json
, "vertex-type",
2133 type2txt
[lsn
->type
]);
2134 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2135 json_object_int_add(json
, "asn", lsn
->as_number
);
2136 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2137 jsr
= json_object_new_object();
2138 json_object_object_add(json
, "segment-routing", jsr
);
2139 json_object_int_add(jsr
, "srgb-size", lsn
->srgb
.range_size
);
2140 json_object_int_add(jsr
, "srgb-lower", lsn
->srgb
.lower_bound
);
2141 jalgo
= json_object_new_array();
2142 json_object_object_add(jsr
, "algorithms", jalgo
);
2143 for (int i
= 0; i
< 2; i
++) {
2144 if (lsn
->algo
[i
] == 255)
2146 jobj
= json_object_new_object();
2148 snprintfrr(buf
, 2, "%u", i
);
2149 json_object_string_add(
2150 jobj
, buf
, lsn
->algo
[i
] == 0 ? "SPF" : "S-SPF");
2151 json_object_array_add(jalgo
, jobj
);
2153 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2154 json_object_int_add(jsr
, "srlb-size",
2155 lsn
->srlb
.range_size
);
2156 json_object_int_add(jsr
, "srlb-lower",
2157 lsn
->srlb
.lower_bound
);
2159 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2160 json_object_int_add(jsr
, "msd", lsn
->msd
);
2164 void ls_show_vertex(struct ls_vertex
*vertex
, struct vty
*vty
,
2165 struct json_object
*json
, bool verbose
)
2168 ls_show_vertex_json(vertex
, json
);
2170 ls_show_vertex_vty(vertex
, vty
, verbose
);
2173 void ls_show_vertices(struct ls_ted
*ted
, struct vty
*vty
,
2174 struct json_object
*json
, bool verbose
)
2176 struct ls_vertex
*vertex
;
2177 json_object
*jnodes
, *jnode
;
2180 jnodes
= json_object_new_array();
2181 json_object_object_add(json
, "vertices", jnodes
);
2182 frr_each (vertices
, &ted
->vertices
, vertex
) {
2183 jnode
= json_object_new_object();
2184 ls_show_vertex(vertex
, NULL
, jnode
, verbose
);
2185 json_object_array_add(jnodes
, jnode
);
2188 frr_each (vertices
, &ted
->vertices
, vertex
)
2189 ls_show_vertex(vertex
, vty
, NULL
, verbose
);
2193 static void ls_show_edge_vty(struct ls_edge
*edge
, struct vty
*vty
,
2196 char admin_group_buf
[ADMIN_GROUP_PRINT_MAX_SIZE
];
2197 struct ls_attributes
*attr
;
2199 char buf
[INET6_BUFSIZ
];
2202 attr
= edge
->attributes
;
2203 sbuf_init(&sbuf
, NULL
, 0);
2205 sbuf_push(&sbuf
, 2, "Edge (%" PRIu64
"): ", edge
->key
);
2206 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2207 sbuf_push(&sbuf
, 0, "%pI4", &attr
->standard
.local
);
2208 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2209 sbuf_push(&sbuf
, 0, "%pI6", &attr
->standard
.local6
);
2211 sbuf_push(&sbuf
, 0, "%u/%u", attr
->standard
.local_id
,
2212 attr
->standard
.remote_id
);
2213 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2214 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2215 sbuf_push(&sbuf
, 0, "\tMetric: %u", attr
->metric
);
2216 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[edge
->status
]);
2221 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[attr
->adv
.origin
]);
2222 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2223 sbuf_push(&sbuf
, 4, "Name: %s\n", attr
->name
);
2224 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2225 sbuf_push(&sbuf
, 4, "TE Metric: %u\n",
2226 attr
->standard
.te_metric
);
2227 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2228 sbuf_push(&sbuf
, 4, "Admin Group: 0x%x\n",
2229 attr
->standard
.admin_group
);
2230 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
) &&
2231 admin_group_nb_words(&attr
->ext_admin_group
) != 0) {
2233 sbuf_push(&sbuf
, indent
, "Ext Admin Group: %s\n",
2235 admin_group_buf
, ADMIN_GROUP_PRINT_MAX_SIZE
,
2236 indent
+ strlen("Ext Admin Group: "),
2237 &attr
->ext_admin_group
));
2238 if (admin_group_buf
[0] != '\0' &&
2239 (sbuf
.pos
+ strlen(admin_group_buf
) +
2240 SBUF_DEFAULT_SIZE
/ 2) < sbuf
.size
)
2241 sbuf_push(&sbuf
, indent
+ 2, "Bit positions: %s\n",
2244 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2245 sbuf_push(&sbuf
, 4, "Local IPv4 address: %pI4\n",
2246 &attr
->standard
.local
);
2247 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
2248 sbuf_push(&sbuf
, 4, "Remote IPv4 address: %pI4\n",
2249 &attr
->standard
.remote
);
2250 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2251 sbuf_push(&sbuf
, 4, "Local IPv6 address: %pI6\n",
2252 &attr
->standard
.local6
);
2253 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
2254 sbuf_push(&sbuf
, 4, "Remote IPv6 address: %pI6\n",
2255 &attr
->standard
.remote6
);
2256 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2257 sbuf_push(&sbuf
, 4, "Local Identifier: %u\n",
2258 attr
->standard
.local_id
);
2259 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2260 sbuf_push(&sbuf
, 4, "Remote Identifier: %u\n",
2261 attr
->standard
.remote_id
);
2262 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2263 sbuf_push(&sbuf
, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2264 attr
->standard
.max_bw
);
2265 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2267 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2268 attr
->standard
.max_rsv_bw
);
2269 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2270 sbuf_push(&sbuf
, 4, "Unreserved Bandwidth per Class Type\n");
2271 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2)
2273 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2274 i
, attr
->standard
.unrsv_bw
[i
], i
+ 1,
2275 attr
->standard
.unrsv_bw
[i
+ 1]);
2277 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2278 sbuf_push(&sbuf
, 4, "Remote AS: %u\n",
2279 attr
->standard
.remote_as
);
2280 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
2281 sbuf_push(&sbuf
, 4, "Remote ASBR IPv4 address: %pI4\n",
2282 &attr
->standard
.remote_addr
);
2283 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
2284 sbuf_push(&sbuf
, 4, "Remote ASBR IPv6 address: %pI6\n",
2285 &attr
->standard
.remote_addr6
);
2286 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2287 sbuf_push(&sbuf
, 4, "Average Link Delay: %d (micro-sec)\n",
2288 attr
->extended
.delay
);
2289 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
))
2290 sbuf_push(&sbuf
, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2291 attr
->extended
.min_delay
, attr
->extended
.max_delay
);
2292 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2293 sbuf_push(&sbuf
, 4, "Delay Variation: %d (micro-sec)\n",
2294 attr
->extended
.jitter
);
2295 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2296 sbuf_push(&sbuf
, 4, "Link Loss: %g (%%)\n",
2297 (float)(attr
->extended
.pkt_loss
* LOSS_PRECISION
));
2298 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2299 sbuf_push(&sbuf
, 4, "Available Bandwidth: %g (Bytes/s)\n",
2300 attr
->extended
.ava_bw
);
2301 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2302 sbuf_push(&sbuf
, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2303 attr
->extended
.rsv_bw
);
2304 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2305 sbuf_push(&sbuf
, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2306 attr
->extended
.used_bw
);
2307 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2308 sbuf_push(&sbuf
, 4, "IPv4 Adjacency-SID: %u",
2309 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2310 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2311 attr
->adj_sid
[ADJ_PRI_IPV4
].flags
,
2312 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2314 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2315 sbuf_push(&sbuf
, 4, "IPv4 Bck. Adjacency-SID: %u",
2316 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2317 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2318 attr
->adj_sid
[ADJ_BCK_IPV4
].flags
,
2319 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2321 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2322 sbuf_push(&sbuf
, 4, "IPv6 Adjacency-SID: %u",
2323 attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
2324 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2325 attr
->adj_sid
[ADJ_PRI_IPV6
].flags
,
2326 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2328 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2329 sbuf_push(&sbuf
, 4, "IPv6 Bck. Adjacency-SID: %u",
2330 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2331 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2332 attr
->adj_sid
[ADJ_BCK_IPV6
].flags
,
2333 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2335 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2336 sbuf_push(&sbuf
, 4, "SRLGs: %d", attr
->srlg_len
);
2337 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2339 sbuf_push(&sbuf
, 8, "\n%u", attr
->srlgs
[i
]);
2341 sbuf_push(&sbuf
, 8, ", %u", attr
->srlgs
[i
]);
2343 sbuf_push(&sbuf
, 0, "\n");
2347 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2351 static void ls_show_edge_json(struct ls_edge
*edge
, struct json_object
*json
)
2353 struct ls_attributes
*attr
;
2354 struct json_object
*jte
, *jbw
, *jobj
, *jsr
= NULL
, *jsrlg
, *js_ext_ag
,
2355 *js_ext_ag_arr_word
,
2357 char buf
[INET6_BUFSIZ
];
2358 char buf_ag
[strlen("0xffffffff") + 1];
2362 attr
= edge
->attributes
;
2364 json_object_int_add(json
, "edge-id", edge
->key
);
2365 json_object_string_add(json
, "status", status2txt
[edge
->status
]);
2366 json_object_string_add(json
, "origin", origin2txt
[attr
->adv
.origin
]);
2367 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2368 json_object_string_add(json
, "advertised-router", buf
);
2370 json_object_int_add(json
, "local-vertex-id", edge
->source
->key
);
2371 if (edge
->destination
)
2372 json_object_int_add(json
, "remote-vertex-id",
2373 edge
->destination
->key
);
2374 json_object_int_add(json
, "metric", attr
->metric
);
2375 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2376 json_object_string_add(json
, "name", attr
->name
);
2377 jte
= json_object_new_object();
2378 json_object_object_add(json
, "edge-attributes", jte
);
2379 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2380 json_object_int_add(jte
, "te-metric", attr
->standard
.te_metric
);
2381 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2382 json_object_int_add(jte
, "admin-group",
2383 attr
->standard
.admin_group
);
2384 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
2385 js_ext_ag
= json_object_new_object();
2386 json_object_object_add(jte
, "extAdminGroup", js_ext_ag
);
2387 js_ext_ag_arr_word
= json_object_new_array();
2388 json_object_object_add(js_ext_ag
, "words", js_ext_ag_arr_word
);
2389 js_ext_ag_arr_bit
= json_object_new_array();
2390 json_object_object_add(js_ext_ag
, "bitPositions",
2392 for (i
= 0; i
< admin_group_nb_words(&attr
->ext_admin_group
);
2394 bitmap
= admin_group_get_offset(&attr
->ext_admin_group
,
2396 snprintf(buf_ag
, sizeof(buf_ag
), "0x%08x", bitmap
);
2397 json_object_array_add(js_ext_ag_arr_word
,
2398 json_object_new_string(buf_ag
));
2401 i
< (admin_group_size(&attr
->ext_admin_group
) * WORD_SIZE
);
2403 if (admin_group_get(&attr
->ext_admin_group
, i
))
2404 json_object_array_add(js_ext_ag_arr_bit
,
2405 json_object_new_int(i
));
2408 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
2409 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.local
);
2410 json_object_string_add(jte
, "local-address", buf
);
2412 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
2413 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.remote
);
2414 json_object_string_add(jte
, "remote-address", buf
);
2416 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
2417 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.local6
);
2418 json_object_string_add(jte
, "local-address-v6", buf
);
2420 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
2421 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.remote6
);
2422 json_object_string_add(jte
, "remote-address-v6", buf
);
2424 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2425 json_object_int_add(jte
, "local-identifier",
2426 attr
->standard
.local_id
);
2427 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2428 json_object_int_add(jte
, "remote-identifier",
2429 attr
->standard
.remote_id
);
2430 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2431 json_object_double_add(jte
, "max-link-bandwidth",
2432 attr
->standard
.max_bw
);
2433 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2434 json_object_double_add(jte
, "max-resv-link-bandwidth",
2435 attr
->standard
.max_rsv_bw
);
2436 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2437 jbw
= json_object_new_array();
2438 json_object_object_add(jte
, "unreserved-bandwidth", jbw
);
2439 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
++) {
2440 jobj
= json_object_new_object();
2441 snprintfrr(buf
, 13, "class-type-%u", i
);
2442 json_object_double_add(jobj
, buf
,
2443 attr
->standard
.unrsv_bw
[i
]);
2444 json_object_array_add(jbw
, jobj
);
2447 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2448 json_object_int_add(jte
, "remote-asn",
2449 attr
->standard
.remote_as
);
2450 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
)) {
2451 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4",
2452 &attr
->standard
.remote_addr
);
2453 json_object_string_add(jte
, "remote-as-address", buf
);
2455 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
)) {
2456 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6",
2457 &attr
->standard
.remote_addr6
);
2458 json_object_string_add(jte
, "remote-as-address-v6", buf
);
2460 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2461 json_object_int_add(jte
, "delay", attr
->extended
.delay
);
2462 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
2463 json_object_int_add(jte
, "min-delay", attr
->extended
.min_delay
);
2464 json_object_int_add(jte
, "max-delay", attr
->extended
.max_delay
);
2466 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2467 json_object_int_add(jte
, "jitter", attr
->extended
.jitter
);
2468 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2469 json_object_double_add(
2470 jte
, "loss", attr
->extended
.pkt_loss
* LOSS_PRECISION
);
2471 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2472 json_object_double_add(jte
, "available-bandwidth",
2473 attr
->extended
.ava_bw
);
2474 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2475 json_object_double_add(jte
, "residual-bandwidth",
2476 attr
->extended
.rsv_bw
);
2477 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2478 json_object_double_add(jte
, "utilized-bandwidth",
2479 attr
->extended
.used_bw
);
2480 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2481 jsrlg
= json_object_new_array();
2482 json_object_object_add(jte
, "srlgs", jsrlg
);
2483 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2484 jobj
= json_object_new_object();
2485 json_object_int_add(jobj
, "srlg", attr
->srlgs
[i
]);
2486 json_object_array_add(jsrlg
, jobj
);
2489 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2490 jsr
= json_object_new_array();
2491 json_object_object_add(json
, "segment-routing", jsr
);
2492 jobj
= json_object_new_object();
2493 json_object_int_add(jobj
, "adj-sid",
2494 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2495 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
2496 json_object_string_add(jobj
, "flags", buf
);
2497 json_object_int_add(jobj
, "weight",
2498 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2499 json_object_array_add(jsr
, jobj
);
2501 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2503 jsr
= json_object_new_array();
2504 json_object_object_add(json
, "segment-routing", jsr
);
2506 jobj
= json_object_new_object();
2507 json_object_int_add(jobj
, "adj-sid",
2508 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2509 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
2510 json_object_string_add(jobj
, "flags", buf
);
2511 json_object_int_add(jobj
, "weight",
2512 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2513 json_object_array_add(jsr
, jobj
);
2515 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2516 jsr
= json_object_new_array();
2517 json_object_object_add(json
, "segment-routing", jsr
);
2518 jobj
= json_object_new_object();
2519 json_object_int_add(jobj
, "adj-sid",
2520 attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
2521 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
2522 json_object_string_add(jobj
, "flags", buf
);
2523 json_object_int_add(jobj
, "weight",
2524 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2525 json_object_array_add(jsr
, jobj
);
2527 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2529 jsr
= json_object_new_array();
2530 json_object_object_add(json
, "segment-routing", jsr
);
2532 jobj
= json_object_new_object();
2533 json_object_int_add(jobj
, "adj-sid",
2534 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2535 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
2536 json_object_string_add(jobj
, "flags", buf
);
2537 json_object_int_add(jobj
, "weight",
2538 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2539 json_object_array_add(jsr
, jobj
);
2543 void ls_show_edge(struct ls_edge
*edge
, struct vty
*vty
,
2544 struct json_object
*json
, bool verbose
)
2551 ls_show_edge_json(edge
, json
);
2553 ls_show_edge_vty(edge
, vty
, verbose
);
2556 void ls_show_edges(struct ls_ted
*ted
, struct vty
*vty
,
2557 struct json_object
*json
, bool verbose
)
2559 struct ls_edge
*edge
;
2560 json_object
*jedges
, *jedge
;
2563 jedges
= json_object_new_array();
2564 json_object_object_add(json
, "edges", jedges
);
2565 frr_each (edges
, &ted
->edges
, edge
) {
2566 jedge
= json_object_new_object();
2567 ls_show_edge(edge
, NULL
, jedge
, verbose
);
2568 json_object_array_add(jedges
, jedge
);
2571 frr_each (edges
, &ted
->edges
, edge
)
2572 ls_show_edge(edge
, vty
, NULL
, verbose
);
2576 static void ls_show_subnet_vty(struct ls_subnet
*subnet
, struct vty
*vty
,
2579 struct ls_prefix
*pref
;
2581 char buf
[INET6_BUFSIZ
];
2583 pref
= subnet
->ls_pref
;
2584 sbuf_init(&sbuf
, NULL
, 0);
2586 sbuf_push(&sbuf
, 2, "Subnet: %pFX", &subnet
->key
);
2587 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2588 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2589 sbuf_push(&sbuf
, 0, "\tMetric: %d", pref
->metric
);
2590 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[subnet
->status
]);
2595 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[pref
->adv
.origin
]);
2596 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
))
2597 sbuf_push(&sbuf
, 4, "Flags: %d\n", pref
->igp_flag
);
2599 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2600 sbuf_push(&sbuf
, 4, "Tag: %d\n", pref
->route_tag
);
2602 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2603 sbuf_push(&sbuf
, 4, "Extended Tag: %" PRIu64
"\n",
2604 pref
->extended_tag
);
2606 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
))
2607 sbuf_push(&sbuf
, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2608 pref
->sr
.sid
, pref
->sr
.algo
, pref
->sr
.sid_flag
);
2611 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2615 static void ls_show_subnet_json(struct ls_subnet
*subnet
,
2616 struct json_object
*json
)
2618 struct ls_prefix
*pref
;
2620 char buf
[INET6_BUFSIZ
];
2622 pref
= subnet
->ls_pref
;
2624 snprintfrr(buf
, INET6_BUFSIZ
, "%pFX", &subnet
->key
);
2625 json_object_string_add(json
, "subnet-id", buf
);
2626 json_object_string_add(json
, "status", status2txt
[subnet
->status
]);
2627 json_object_string_add(json
, "origin", origin2txt
[pref
->adv
.origin
]);
2628 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2629 json_object_string_add(json
, "advertised-router", buf
);
2631 json_object_int_add(json
, "vertex-id", subnet
->vertex
->key
);
2632 json_object_int_add(json
, "metric", pref
->metric
);
2633 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
)) {
2634 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->igp_flag
);
2635 json_object_string_add(json
, "flags", buf
);
2637 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2638 json_object_int_add(json
, "tag", pref
->route_tag
);
2639 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2640 json_object_int_add(json
, "extended-tag", pref
->extended_tag
);
2641 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
)) {
2642 jsr
= json_object_new_object();
2643 json_object_object_add(json
, "segment-routing", jsr
);
2644 json_object_int_add(jsr
, "pref-sid", pref
->sr
.sid
);
2645 json_object_int_add(jsr
, "algo", pref
->sr
.algo
);
2646 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->sr
.sid_flag
);
2647 json_object_string_add(jsr
, "flags", buf
);
2651 void ls_show_subnet(struct ls_subnet
*subnet
, struct vty
*vty
,
2652 struct json_object
*json
, bool verbose
)
2659 ls_show_subnet_json(subnet
, json
);
2661 ls_show_subnet_vty(subnet
, vty
, verbose
);
2664 void ls_show_subnets(struct ls_ted
*ted
, struct vty
*vty
,
2665 struct json_object
*json
, bool verbose
)
2667 struct ls_subnet
*subnet
;
2668 json_object
*jsubs
, *jsub
;
2671 jsubs
= json_object_new_array();
2672 json_object_object_add(json
, "subnets", jsubs
);
2673 frr_each (subnets
, &ted
->subnets
, subnet
) {
2674 jsub
= json_object_new_object();
2675 ls_show_subnet(subnet
, NULL
, jsub
, verbose
);
2676 json_object_array_add(jsubs
, jsub
);
2679 frr_each (subnets
, &ted
->subnets
, subnet
)
2680 ls_show_subnet(subnet
, vty
, NULL
, verbose
);
2684 void ls_show_ted(struct ls_ted
*ted
, struct vty
*vty
, struct json_object
*json
,
2690 jted
= json_object_new_object();
2691 json_object_object_add(json
, "ted", jted
);
2692 json_object_string_add(jted
, "name", ted
->name
);
2693 json_object_int_add(jted
, "key", ted
->key
);
2694 json_object_int_add(jted
, "verticesCount",
2695 vertices_count(&ted
->vertices
));
2696 json_object_int_add(jted
, "edgesCount",
2697 edges_count(&ted
->edges
));
2698 json_object_int_add(jted
, "subnetsCount",
2699 subnets_count(&ted
->subnets
));
2700 ls_show_vertices(ted
, NULL
, jted
, verbose
);
2701 ls_show_edges(ted
, NULL
, jted
, verbose
);
2702 ls_show_subnets(ted
, NULL
, jted
, verbose
);
2708 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2709 ted
->name
, ted
->key
);
2710 ls_show_vertices(ted
, vty
, NULL
, verbose
);
2711 ls_show_edges(ted
, vty
, NULL
, verbose
);
2712 ls_show_subnets(ted
, vty
, NULL
, verbose
);
2714 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2715 vertices_count(&ted
->vertices
),
2716 edges_count(&ted
->edges
), subnets_count(&ted
->subnets
));
2720 void ls_dump_ted(struct ls_ted
*ted
)
2722 struct ls_vertex
*vertex
;
2723 struct ls_edge
*edge
;
2724 struct ls_subnet
*subnet
;
2725 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
2727 zlog_debug("(%s) Ted init", __func__
);
2729 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2730 frr_each (vertices
, &ted
->vertices
, vertex
) {
2731 zlog_debug(" Ted node (%s %pI4 %s)",
2732 vertex
->node
->name
[0] ? vertex
->node
->name
2734 &vertex
->node
->router_id
,
2735 origin2txt
[vertex
->node
->adv
.origin
]);
2736 struct listnode
*lst_node
;
2737 struct ls_edge
*vertex_edge
;
2739 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
2742 " inc edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2744 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2745 &vertex_edge
->attributes
->standard
.local
,
2746 &vertex_edge
->attributes
->standard
.remote
);
2748 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
2751 " out edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2753 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2754 &vertex_edge
->attributes
->standard
.local
,
2755 &vertex_edge
->attributes
->standard
.remote
);
2758 frr_each (edges
, &ted
->edges
, edge
) {
2759 zlog_debug(" Ted edge key:%" PRIu64
"src:%pI4 dst:%pI4", edge
->key
,
2760 edge
->source
? &edge
->source
->node
->router_id
2763 ? &edge
->destination
->node
->router_id
2766 frr_each (subnets
, &ted
->subnets
, subnet
) {
2767 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2768 &subnet
->ls_pref
->pref
,
2769 &subnet
->vertex
->node
->adv
.id
.ip
.addr
);
2771 zlog_debug("(%s) Ted end", __func__
);