1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Link State Database - link_state.c
5 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
7 * Copyright (C) 2020 Orange http://www.orange.com
9 * This file is part of Free Range Routing (FRR).
18 #include "termtable.h"
28 #include "link_state.h"
30 /* Link State Memory allocation */
31 DEFINE_MTYPE_STATIC(LIB
, LS_DB
, "Link State Database");
34 * Link State Node management functions
36 int ls_node_id_same(struct ls_node_id i1
, struct ls_node_id i2
)
38 if (i1
.origin
!= i2
.origin
)
41 if (i1
.origin
== UNKNOWN
)
44 if (i1
.origin
== ISIS_L1
|| i1
.origin
== ISIS_L2
) {
45 if (memcmp(i1
.id
.iso
.sys_id
, i2
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
)
47 || (i1
.id
.iso
.level
!= i2
.id
.iso
.level
))
50 if (!IPV4_ADDR_SAME(&i1
.id
.ip
.addr
, &i2
.id
.ip
.addr
)
51 || !IPV4_ADDR_SAME(&i1
.id
.ip
.area_id
, &i2
.id
.ip
.area_id
))
58 struct ls_node
*ls_node_new(struct ls_node_id adv
, struct in_addr rid
,
63 if (adv
.origin
== UNKNOWN
)
66 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
68 if (!IPV4_NET0(rid
.s_addr
)) {
70 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
72 if (adv
.origin
== OSPFv2
|| adv
.origin
== STATIC
73 || adv
.origin
== DIRECT
) {
74 new->router_id
= adv
.id
.ip
.addr
;
75 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
78 if (!IN6_IS_ADDR_UNSPECIFIED(&rid6
)) {
79 new->router_id6
= rid6
;
80 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID6
);
85 void ls_node_del(struct ls_node
*node
)
90 XFREE(MTYPE_LS_DB
, node
);
93 int ls_node_same(struct ls_node
*n1
, struct ls_node
*n2
)
95 /* First, check pointer */
96 if ((n1
&& !n2
) || (!n1
&& n2
))
102 /* Then, verify Flags and Origin */
103 if (n1
->flags
!= n2
->flags
)
106 if (!ls_node_id_same(n1
->adv
, n2
->adv
))
109 /* Finally, check each individual parameters that are valid */
110 if (CHECK_FLAG(n1
->flags
, LS_NODE_NAME
)
111 && (strncmp(n1
->name
, n2
->name
, MAX_NAME_LENGTH
) != 0))
113 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID
)
114 && !IPV4_ADDR_SAME(&n1
->router_id
, &n2
->router_id
))
116 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID6
)
117 && !IPV6_ADDR_SAME(&n1
->router_id6
, &n2
->router_id6
))
119 if (CHECK_FLAG(n1
->flags
, LS_NODE_FLAG
)
120 && (n1
->node_flag
!= n2
->node_flag
))
122 if (CHECK_FLAG(n1
->flags
, LS_NODE_TYPE
) && (n1
->type
!= n2
->type
))
124 if (CHECK_FLAG(n1
->flags
, LS_NODE_AS_NUMBER
)
125 && (n1
->as_number
!= n2
->as_number
))
127 if (CHECK_FLAG(n1
->flags
, LS_NODE_SR
)) {
128 if (n1
->srgb
.flag
!= n2
->srgb
.flag
129 || n1
->srgb
.lower_bound
!= n2
->srgb
.lower_bound
130 || n1
->srgb
.range_size
!= n2
->srgb
.range_size
)
132 if ((n1
->algo
[0] != n2
->algo
[0])
133 || (n1
->algo
[1] != n2
->algo
[1]))
135 if (CHECK_FLAG(n1
->flags
, LS_NODE_SRLB
)
136 && ((n1
->srlb
.lower_bound
!= n2
->srlb
.lower_bound
137 || n1
->srlb
.range_size
!= n2
->srlb
.range_size
)))
139 if (CHECK_FLAG(n1
->flags
, LS_NODE_MSD
) && (n1
->msd
!= n2
->msd
))
143 /* OK, n1 & n2 are equal */
148 * Link State Attributes management functions
150 struct ls_attributes
*ls_attributes_new(struct ls_node_id adv
,
151 struct in_addr local
,
152 struct in6_addr local6
,
155 struct ls_attributes
*new;
157 if (adv
.origin
== UNKNOWN
)
160 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
162 if (!IPV4_NET0(local
.s_addr
)) {
163 new->standard
.local
= local
;
164 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
);
166 if (!IN6_IS_ADDR_UNSPECIFIED(&local6
)) {
167 new->standard
.local6
= local6
;
168 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR6
);
171 new->standard
.local_id
= local_id
;
172 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ID
);
175 /* Check that almost one identifier is set */
176 if (!CHECK_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
| LS_ATTR_LOCAL_ADDR6
177 | LS_ATTR_LOCAL_ID
)) {
178 XFREE(MTYPE_LS_DB
, new);
182 admin_group_init(&new->ext_admin_group
);
187 void ls_attributes_srlg_del(struct ls_attributes
*attr
)
193 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
197 UNSET_FLAG(attr
->flags
, LS_ATTR_SRLG
);
200 void ls_attributes_del(struct ls_attributes
*attr
)
205 ls_attributes_srlg_del(attr
);
207 admin_group_term(&attr
->ext_admin_group
);
209 XFREE(MTYPE_LS_DB
, attr
);
212 int ls_attributes_same(struct ls_attributes
*l1
, struct ls_attributes
*l2
)
214 /* First, check pointer */
215 if ((l1
&& !l2
) || (!l1
&& l2
))
221 /* Then, verify Flags and Origin */
222 if (l1
->flags
!= l2
->flags
)
225 if (!ls_node_id_same(l1
->adv
, l2
->adv
))
228 /* Finally, check each individual parameters that are valid */
229 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NAME
)
230 && strncmp(l1
->name
, l2
->name
, MAX_NAME_LENGTH
) != 0)
232 if (CHECK_FLAG(l1
->flags
, LS_ATTR_METRIC
) && (l1
->metric
!= l2
->metric
))
234 if (CHECK_FLAG(l1
->flags
, LS_ATTR_TE_METRIC
)
235 && (l1
->standard
.te_metric
!= l2
->standard
.te_metric
))
237 if (CHECK_FLAG(l1
->flags
, LS_ATTR_ADM_GRP
)
238 && (l1
->standard
.admin_group
!= l2
->standard
.admin_group
))
240 if (CHECK_FLAG(l1
->flags
, LS_ATTR_EXT_ADM_GRP
) &&
241 !admin_group_cmp(&l1
->ext_admin_group
, &l2
->ext_admin_group
))
243 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR
)
244 && !IPV4_ADDR_SAME(&l1
->standard
.local
, &l2
->standard
.local
))
246 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR
)
247 && !IPV4_ADDR_SAME(&l1
->standard
.remote
, &l2
->standard
.remote
))
249 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR6
)
250 && !IPV6_ADDR_SAME(&l1
->standard
.local6
, &l2
->standard
.local6
))
252 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR6
)
253 && !IPV6_ADDR_SAME(&l1
->standard
.remote6
, &l2
->standard
.remote6
))
255 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ID
)
256 && (l1
->standard
.local_id
!= l2
->standard
.local_id
))
258 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ID
)
259 && (l1
->standard
.remote_id
!= l2
->standard
.remote_id
))
261 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_BW
)
262 && (l1
->standard
.max_bw
!= l2
->standard
.max_bw
))
264 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_RSV_BW
)
265 && (l1
->standard
.max_rsv_bw
!= l2
->standard
.max_rsv_bw
))
267 if (CHECK_FLAG(l1
->flags
, LS_ATTR_UNRSV_BW
)
268 && memcmp(&l1
->standard
.unrsv_bw
, &l2
->standard
.unrsv_bw
, 32) != 0)
270 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_AS
)
271 && (l1
->standard
.remote_as
!= l2
->standard
.remote_as
))
273 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR
)
274 && !IPV4_ADDR_SAME(&l1
->standard
.remote_addr
,
275 &l2
->standard
.remote_addr
))
277 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR6
)
278 && !IPV6_ADDR_SAME(&l1
->standard
.remote_addr6
,
279 &l2
->standard
.remote_addr6
))
281 if (CHECK_FLAG(l1
->flags
, LS_ATTR_DELAY
)
282 && (l1
->extended
.delay
!= l2
->extended
.delay
))
284 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MIN_MAX_DELAY
)
285 && ((l1
->extended
.min_delay
!= l2
->extended
.min_delay
)
286 || (l1
->extended
.max_delay
!= l2
->extended
.max_delay
)))
288 if (CHECK_FLAG(l1
->flags
, LS_ATTR_JITTER
)
289 && (l1
->extended
.jitter
!= l2
->extended
.jitter
))
291 if (CHECK_FLAG(l1
->flags
, LS_ATTR_PACKET_LOSS
)
292 && (l1
->extended
.pkt_loss
!= l2
->extended
.pkt_loss
))
294 if (CHECK_FLAG(l1
->flags
, LS_ATTR_AVA_BW
)
295 && (l1
->extended
.ava_bw
!= l2
->extended
.ava_bw
))
297 if (CHECK_FLAG(l1
->flags
, LS_ATTR_RSV_BW
)
298 && (l1
->extended
.rsv_bw
!= l2
->extended
.rsv_bw
))
300 if (CHECK_FLAG(l1
->flags
, LS_ATTR_USE_BW
)
301 && (l1
->extended
.used_bw
!= l2
->extended
.used_bw
))
303 for (int i
= 0; i
< LS_ADJ_MAX
; i
++) {
304 if (!CHECK_FLAG(l1
->flags
, (LS_ATTR_ADJ_SID
<< i
)))
306 if ((l1
->adj_sid
[i
].sid
!= l2
->adj_sid
[i
].sid
)
307 || (l1
->adj_sid
[i
].flags
!= l2
->adj_sid
[i
].flags
)
308 || (l1
->adj_sid
[i
].weight
!= l2
->adj_sid
[i
].weight
))
310 if (((l1
->adv
.origin
== ISIS_L1
) || (l1
->adv
.origin
== ISIS_L2
))
311 && (memcmp(&l1
->adj_sid
[i
].neighbor
.sysid
,
312 &l2
->adj_sid
[i
].neighbor
.sysid
, ISO_SYS_ID_LEN
)
315 if (((l1
->adv
.origin
== OSPFv2
) || (l1
->adv
.origin
== STATIC
)
316 || (l1
->adv
.origin
== DIRECT
))
317 && (i
< ADJ_PRI_IPV6
)
318 && (!IPV4_ADDR_SAME(&l1
->adj_sid
[i
].neighbor
.addr
,
319 &l2
->adj_sid
[i
].neighbor
.addr
)))
322 if (CHECK_FLAG(l1
->flags
, LS_ATTR_SRLG
)
323 && ((l1
->srlg_len
!= l2
->srlg_len
)
324 || memcmp(l1
->srlgs
, l2
->srlgs
,
325 l1
->srlg_len
* sizeof(uint32_t))
329 /* OK, l1 & l2 are equal */
334 * Link State prefix management functions
336 struct ls_prefix
*ls_prefix_new(struct ls_node_id adv
, struct prefix p
)
338 struct ls_prefix
*new;
340 if (adv
.origin
== UNKNOWN
)
343 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
350 void ls_prefix_del(struct ls_prefix
*pref
)
355 XFREE(MTYPE_LS_DB
, pref
);
358 int ls_prefix_same(struct ls_prefix
*p1
, struct ls_prefix
*p2
)
360 /* First, check pointer */
361 if ((p1
&& !p2
) || (!p1
&& p2
))
367 /* Then, verify Flags and Origin */
368 if (p1
->flags
!= p2
->flags
)
371 if (!ls_node_id_same(p1
->adv
, p2
->adv
))
374 /* Finally, check each individual parameters that are valid */
375 if (prefix_same(&p1
->pref
, &p2
->pref
) == 0)
377 if (CHECK_FLAG(p1
->flags
, LS_PREF_IGP_FLAG
)
378 && (p1
->igp_flag
!= p2
->igp_flag
))
380 if (CHECK_FLAG(p1
->flags
, LS_PREF_ROUTE_TAG
)
381 && (p1
->route_tag
!= p2
->route_tag
))
383 if (CHECK_FLAG(p1
->flags
, LS_PREF_EXTENDED_TAG
)
384 && (p1
->extended_tag
!= p2
->extended_tag
))
386 if (CHECK_FLAG(p1
->flags
, LS_PREF_METRIC
) && (p1
->metric
!= p2
->metric
))
388 if (CHECK_FLAG(p1
->flags
, LS_PREF_SR
)) {
389 if ((p1
->sr
.algo
!= p2
->sr
.algo
) || (p1
->sr
.sid
!= p2
->sr
.sid
)
390 || (p1
->sr
.sid_flag
!= p2
->sr
.sid_flag
))
394 /* OK, p1 & p2 are equal */
399 * Link State Vertices management functions
401 uint64_t sysid_to_key(const uint8_t sysid
[ISO_SYS_ID_LEN
])
405 #if BYTE_ORDER == LITTLE_ENDIAN
406 uint8_t *byte
= (uint8_t *)&key
;
408 for (int i
= 0; i
< ISO_SYS_ID_LEN
; i
++)
409 byte
[i
] = sysid
[ISO_SYS_ID_LEN
- i
- 1];
414 memcpy(&key
, sysid
, ISO_SYS_ID_LEN
);
420 struct ls_vertex
*ls_vertex_add(struct ls_ted
*ted
, struct ls_node
*node
)
422 struct ls_vertex
*new;
425 if ((ted
== NULL
) || (node
== NULL
))
428 /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
429 switch (node
->adv
.origin
) {
433 key
= ((uint64_t)ntohl(node
->adv
.id
.ip
.addr
.s_addr
))
438 key
= sysid_to_key(node
->adv
.id
.iso
.sys_id
);
445 /* Check that key is valid */
449 /* Create Vertex and add it to the TED */
450 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_vertex
));
458 new->incoming_edges
= list_new();
459 new->incoming_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
460 new->outgoing_edges
= list_new();
461 new->outgoing_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
462 new->prefixes
= list_new();
463 new->prefixes
->cmp
= (int (*)(void *, void *))subnet_cmp
;
464 vertices_add(&ted
->vertices
, new);
469 void ls_vertex_del(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
471 struct listnode
*node
, *nnode
;
472 struct ls_edge
*edge
;
473 struct ls_subnet
*subnet
;
478 /* Remove outgoing Edges and list */
479 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
))
480 ls_edge_del_all(ted
, edge
);
481 list_delete(&vertex
->outgoing_edges
);
483 /* Disconnect incoming Edges and remove list */
484 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
485 ls_disconnect(vertex
, edge
, false);
486 if (edge
->source
== NULL
)
487 ls_edge_del_all(ted
, edge
);
489 list_delete(&vertex
->incoming_edges
);
491 /* Remove subnet and list */
492 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
))
493 ls_subnet_del_all(ted
, subnet
);
494 list_delete(&vertex
->prefixes
);
496 /* Then remove Vertex from Link State Data Base and free memory */
497 vertices_del(&ted
->vertices
, vertex
);
498 XFREE(MTYPE_LS_DB
, vertex
);
502 void ls_vertex_del_all(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
507 /* First remove associated Link State Node */
508 ls_node_del(vertex
->node
);
510 /* Then, Vertex itself */
511 ls_vertex_del(ted
, vertex
);
514 struct ls_vertex
*ls_vertex_update(struct ls_ted
*ted
, struct ls_node
*node
)
516 struct ls_vertex
*old
;
521 old
= ls_find_vertex_by_id(ted
, node
->adv
);
523 if (!ls_node_same(old
->node
, node
)) {
524 ls_node_del(old
->node
);
527 old
->status
= UPDATE
;
531 return ls_vertex_add(ted
, node
);
534 struct ls_vertex
*ls_find_vertex_by_key(struct ls_ted
*ted
, const uint64_t key
)
536 struct ls_vertex vertex
= {};
542 return vertices_find(&ted
->vertices
, &vertex
);
545 struct ls_vertex
*ls_find_vertex_by_id(struct ls_ted
*ted
,
546 struct ls_node_id nid
)
548 struct ls_vertex vertex
= {};
551 switch (nid
.origin
) {
556 ((uint64_t)ntohl(nid
.id
.ip
.addr
.s_addr
)) & 0xffffffff;
560 vertex
.key
= sysid_to_key(nid
.id
.iso
.sys_id
);
566 return vertices_find(&ted
->vertices
, &vertex
);
569 int ls_vertex_same(struct ls_vertex
*v1
, struct ls_vertex
*v2
)
571 if ((v1
&& !v2
) || (!v1
&& v2
))
577 if (v1
->key
!= v2
->key
)
580 if (v1
->node
== v2
->node
)
583 return ls_node_same(v1
->node
, v2
->node
);
586 void ls_vertex_clean(struct ls_ted
*ted
, struct ls_vertex
*vertex
,
587 struct zclient
*zclient
)
589 struct listnode
*node
, *nnode
;
590 struct ls_edge
*edge
;
591 struct ls_subnet
*subnet
;
592 struct ls_message msg
;
594 /* Remove Orphan Edge ... */
595 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
)) {
596 if (edge
->status
== ORPHAN
) {
598 edge
->status
= DELETE
;
599 ls_edge2msg(&msg
, edge
);
600 ls_send_msg(zclient
, &msg
, NULL
);
602 ls_edge_del_all(ted
, edge
);
605 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
606 if (edge
->status
== ORPHAN
) {
608 edge
->status
= DELETE
;
609 ls_edge2msg(&msg
, edge
);
610 ls_send_msg(zclient
, &msg
, NULL
);
612 ls_edge_del_all(ted
, edge
);
616 /* ... and Subnet from the Vertex */
617 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
)) {
618 if (subnet
->status
== ORPHAN
) {
620 subnet
->status
= DELETE
;
621 ls_subnet2msg(&msg
, subnet
);
622 ls_send_msg(zclient
, &msg
, NULL
);
624 ls_subnet_del_all(ted
, subnet
);
630 * Link State Edges management functions
634 * This function allows to connect the Edge to the vertices present in the TED.
635 * A temporary vertex that corresponds to the source of this Edge i.e. the
636 * advertised router, is created if not found in the Data Base. If a Edge that
637 * corresponds to the reverse path is found, the Edge is attached to the
638 * destination vertex as destination and reverse Edge is attached to the source
641 * @param ted Link State Data Base
642 * @param edge Link State Edge to be attached
644 static void ls_edge_connect_to(struct ls_ted
*ted
, struct ls_edge
*edge
)
646 struct ls_vertex
*vertex
= NULL
;
647 struct ls_node
*node
;
649 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
651 /* First, search if there is a Vertex that correspond to the Node ID */
652 vertex
= ls_find_vertex_by_id(ted
, edge
->attributes
->adv
);
653 if (vertex
== NULL
) {
654 /* Create a new temporary Node & Vertex if not found */
655 node
= ls_node_new(edge
->attributes
->adv
, inaddr_any
,
657 vertex
= ls_vertex_add(ted
, node
);
659 /* and attach the edge as source to the vertex */
660 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
661 edge
->source
= vertex
;
663 /* Then search if there is a reverse Edge */
664 dst
= ls_find_edge_by_destination(ted
, edge
->attributes
);
665 /* attach the destination edge to the vertex */
667 listnode_add_sort_nodup(vertex
->incoming_edges
, dst
);
668 dst
->destination
= vertex
;
669 /* and destination vertex to this edge */
670 vertex
= dst
->source
;
671 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
672 edge
->destination
= vertex
;
676 static uint64_t get_edge_key(struct ls_attributes
*attr
, bool dst
)
679 struct ls_standard
*std
;
684 std
= &attr
->standard
;
687 /* Key is the IPv4 remote address */
688 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
689 key
= ((uint64_t)ntohl(std
->remote
.s_addr
))
691 /* or the 64 bits LSB of IPv6 remote address */
692 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
693 key
= ((uint64_t)ntohl(std
->remote6
.s6_addr32
[2]) << 32
694 | (uint64_t)ntohl(std
->remote6
.s6_addr32
[3]));
695 /* of remote identifier if no IP addresses are defined */
696 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
697 key
= (((uint64_t)std
->remote_id
) & 0xffffffff)
698 | ((uint64_t)std
->local_id
<< 32);
700 /* Key is the IPv4 local address */
701 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
702 key
= ((uint64_t)ntohl(std
->local
.s_addr
)) & 0xffffffff;
703 /* or the 64 bits LSB of IPv6 local address */
704 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
705 key
= ((uint64_t)ntohl(std
->local6
.s6_addr32
[2]) << 32
706 | (uint64_t)ntohl(std
->local6
.s6_addr32
[3]));
707 /* of local identifier if no IP addresses are defined */
708 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
709 key
= (((uint64_t)std
->local_id
) & 0xffffffff)
710 | ((uint64_t)std
->remote_id
<< 32);
716 struct ls_edge
*ls_edge_add(struct ls_ted
*ted
,
717 struct ls_attributes
*attributes
)
722 if (attributes
== NULL
)
725 key
= get_edge_key(attributes
, false);
729 /* Create Edge and add it to the TED */
730 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_edge
));
732 new->attributes
= attributes
;
736 edges_add(&ted
->edges
, new);
738 /* Finally, connect Edge to Vertices */
739 ls_edge_connect_to(ted
, new);
744 struct ls_edge
*ls_find_edge_by_key(struct ls_ted
*ted
, const uint64_t key
)
746 struct ls_edge edge
= {};
752 return edges_find(&ted
->edges
, &edge
);
755 struct ls_edge
*ls_find_edge_by_source(struct ls_ted
*ted
,
756 struct ls_attributes
*attributes
)
758 struct ls_edge edge
= {};
760 if (attributes
== NULL
)
763 edge
.key
= get_edge_key(attributes
, false);
767 return edges_find(&ted
->edges
, &edge
);
770 struct ls_edge
*ls_find_edge_by_destination(struct ls_ted
*ted
,
771 struct ls_attributes
*attributes
)
773 struct ls_edge edge
= {};
775 if (attributes
== NULL
)
778 edge
.key
= get_edge_key(attributes
, true);
782 return edges_find(&ted
->edges
, &edge
);
785 struct ls_edge
*ls_edge_update(struct ls_ted
*ted
,
786 struct ls_attributes
*attributes
)
790 if (attributes
== NULL
)
793 /* First, search for an existing Edge */
794 old
= ls_find_edge_by_source(ted
, attributes
);
796 /* Check if attributes are similar */
797 if (!ls_attributes_same(old
->attributes
, attributes
)) {
798 ls_attributes_del(old
->attributes
);
799 old
->attributes
= attributes
;
801 old
->status
= UPDATE
;
805 /* If not found, add new Edge from the attributes */
806 return ls_edge_add(ted
, attributes
);
809 int ls_edge_same(struct ls_edge
*e1
, struct ls_edge
*e2
)
811 if ((e1
&& !e2
) || (!e1
&& e2
))
817 if (e1
->key
!= e2
->key
)
820 if (e1
->attributes
== e2
->attributes
)
823 return ls_attributes_same(e1
->attributes
, e2
->attributes
);
826 void ls_edge_del(struct ls_ted
*ted
, struct ls_edge
*edge
)
831 /* Fist disconnect Edge from Vertices */
832 ls_disconnect_edge(edge
);
833 /* Then remove it from the Data Base */
834 edges_del(&ted
->edges
, edge
);
835 XFREE(MTYPE_LS_DB
, edge
);
838 void ls_edge_del_all(struct ls_ted
*ted
, struct ls_edge
*edge
)
843 /* Remove associated Link State Attributes */
844 ls_attributes_del(edge
->attributes
);
845 /* Then Edge itself */
846 ls_edge_del(ted
, edge
);
850 * Link State Subnet Management functions.
852 struct ls_subnet
*ls_subnet_add(struct ls_ted
*ted
,
853 struct ls_prefix
*ls_pref
)
855 struct ls_subnet
*new;
856 struct ls_vertex
*vertex
;
857 struct ls_node
*node
;
858 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
863 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_subnet
));
864 new->ls_pref
= ls_pref
;
865 new->key
= ls_pref
->pref
;
870 vertex
= ls_find_vertex_by_id(ted
, ls_pref
->adv
);
871 if (vertex
== NULL
) {
872 /* Create a new temporary Node & Vertex if not found */
873 node
= ls_node_new(ls_pref
->adv
, inaddr_any
, in6addr_any
);
874 vertex
= ls_vertex_add(ted
, node
);
876 /* And attach the subnet to the corresponding Vertex */
877 new->vertex
= vertex
;
878 listnode_add_sort_nodup(vertex
->prefixes
, new);
880 subnets_add(&ted
->subnets
, new);
885 struct ls_subnet
*ls_subnet_update(struct ls_ted
*ted
, struct ls_prefix
*pref
)
887 struct ls_subnet
*old
;
892 old
= ls_find_subnet(ted
, pref
->pref
);
894 if (!ls_prefix_same(old
->ls_pref
, pref
)) {
895 ls_prefix_del(old
->ls_pref
);
898 old
->status
= UPDATE
;
902 return ls_subnet_add(ted
, pref
);
905 int ls_subnet_same(struct ls_subnet
*s1
, struct ls_subnet
*s2
)
907 if ((s1
&& !s2
) || (!s1
&& s2
))
913 if (!prefix_same(&s1
->key
, &s2
->key
))
916 if (s1
->ls_pref
== s2
->ls_pref
)
919 return ls_prefix_same(s1
->ls_pref
, s2
->ls_pref
);
922 void ls_subnet_del(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
927 /* First, disconnect Subnet from associated Vertex */
928 listnode_delete(subnet
->vertex
->prefixes
, subnet
);
929 /* Then delete Subnet */
930 subnets_del(&ted
->subnets
, subnet
);
931 XFREE(MTYPE_LS_DB
, subnet
);
934 void ls_subnet_del_all(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
939 /* First, remove associated Link State Subnet */
940 ls_prefix_del(subnet
->ls_pref
);
941 /* Then, delete Subnet itself */
942 ls_subnet_del(ted
, subnet
);
945 struct ls_subnet
*ls_find_subnet(struct ls_ted
*ted
, const struct prefix prefix
)
947 struct ls_subnet subnet
= {};
950 return subnets_find(&ted
->subnets
, &subnet
);
954 * Link State TED management functions
956 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
961 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
963 /* Set basic information for this ted */
965 new->as_number
= as_number
;
966 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
968 /* Initialize the various RB tree */
969 vertices_init(&new->vertices
);
970 edges_init(&new->edges
);
971 subnets_init(&new->subnets
);
976 void ls_ted_del(struct ls_ted
*ted
)
981 /* Check that TED is empty */
982 if (vertices_count(&ted
->vertices
) || edges_count(&ted
->edges
)
983 || subnets_count(&ted
->subnets
))
986 /* Release RB Tree */
987 vertices_fini(&ted
->vertices
);
988 edges_fini(&ted
->edges
);
989 subnets_fini(&ted
->subnets
);
991 XFREE(MTYPE_LS_DB
, ted
);
994 void ls_ted_del_all(struct ls_ted
**ted
)
996 struct ls_vertex
*vertex
;
997 struct ls_edge
*edge
;
998 struct ls_subnet
*subnet
;
1003 /* First remove Vertices, Edges and Subnets and associated Link State */
1004 frr_each_safe (vertices
, &(*ted
)->vertices
, vertex
)
1005 ls_vertex_del_all(*ted
, vertex
);
1006 frr_each_safe (edges
, &(*ted
)->edges
, edge
)
1007 ls_edge_del_all(*ted
, edge
);
1008 frr_each_safe (subnets
, &(*ted
)->subnets
, subnet
)
1009 ls_subnet_del_all(*ted
, subnet
);
1011 /* then remove TED itself */
1016 void ls_ted_clean(struct ls_ted
*ted
)
1018 struct ls_vertex
*vertex
;
1019 struct ls_edge
*edge
;
1020 struct ls_subnet
*subnet
;
1025 /* First, start with Vertices */
1026 frr_each_safe (vertices
, &ted
->vertices
, vertex
)
1027 if (vertex
->status
== ORPHAN
)
1028 ls_vertex_del_all(ted
, vertex
);
1031 frr_each_safe (edges
, &ted
->edges
, edge
)
1032 if (edge
->status
== ORPHAN
)
1033 ls_edge_del_all(ted
, edge
);
1036 frr_each_safe (subnets
, &ted
->subnets
, subnet
)
1037 if (subnet
->status
== ORPHAN
)
1038 ls_subnet_del_all(ted
, subnet
);
1042 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1044 if (vertex
== NULL
|| edge
== NULL
)
1048 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
1049 edge
->source
= vertex
;
1051 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
1052 edge
->destination
= vertex
;
1056 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1059 if (vertex
== NULL
|| edge
== NULL
)
1063 listnode_delete(vertex
->outgoing_edges
, edge
);
1064 edge
->source
= NULL
;
1066 listnode_delete(vertex
->incoming_edges
, edge
);
1067 edge
->destination
= NULL
;
1071 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
1072 struct ls_edge
*edge
)
1078 edge
->destination
= dst
;
1081 listnode_add_sort_nodup(src
->outgoing_edges
, edge
);
1084 listnode_add_sort_nodup(dst
->incoming_edges
, edge
);
1087 void ls_disconnect_edge(struct ls_edge
*edge
)
1092 ls_disconnect(edge
->source
, edge
, true);
1093 ls_disconnect(edge
->destination
, edge
, false);
1095 /* Mark this Edge as ORPHAN for future cleanup */
1096 edge
->status
= ORPHAN
;
1100 * Link State Message management functions
1103 int ls_register(struct zclient
*zclient
, bool server
)
1108 rc
= zclient_register_opaque(zclient
, LINK_STATE_SYNC
);
1110 rc
= zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
1115 int ls_unregister(struct zclient
*zclient
, bool server
)
1120 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_SYNC
);
1122 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_UPDATE
);
1127 int ls_request_sync(struct zclient
*zclient
)
1132 /* Check buffer size */
1133 if (STREAM_SIZE(zclient
->obuf
)
1134 < (ZEBRA_HEADER_SIZE
+ 3 * sizeof(uint32_t)))
1140 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1142 /* Set type and flags */
1143 stream_putl(s
, LINK_STATE_SYNC
);
1144 stream_putw(s
, flags
);
1145 /* Send destination client info */
1146 stream_putc(s
, zclient
->redist_default
);
1147 stream_putw(s
, zclient
->instance
);
1148 stream_putl(s
, zclient
->session_id
);
1150 /* Put length into the header at the start of the stream. */
1151 stream_putw_at(s
, 0, stream_get_endp(s
));
1153 return zclient_send_message(zclient
);
1156 static struct ls_node
*ls_parse_node(struct stream
*s
)
1158 struct ls_node
*node
;
1161 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
1163 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
1164 STREAM_GETW(s
, node
->flags
);
1165 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1166 STREAM_GETC(s
, len
);
1167 STREAM_GET(node
->name
, s
, len
);
1169 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1170 node
->router_id
.s_addr
= stream_get_ipv4(s
);
1171 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1172 STREAM_GET(&node
->router_id6
, s
, IPV6_MAX_BYTELEN
);
1173 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1174 STREAM_GETC(s
, node
->node_flag
);
1175 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1176 STREAM_GETC(s
, node
->type
);
1177 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1178 STREAM_GETL(s
, node
->as_number
);
1179 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1180 STREAM_GETL(s
, node
->srgb
.lower_bound
);
1181 STREAM_GETL(s
, node
->srgb
.range_size
);
1182 STREAM_GETC(s
, node
->srgb
.flag
);
1183 STREAM_GET(node
->algo
, s
, 2);
1185 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1186 STREAM_GETL(s
, node
->srlb
.lower_bound
);
1187 STREAM_GETL(s
, node
->srlb
.range_size
);
1189 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1190 STREAM_GETC(s
, node
->msd
);
1195 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
1196 XFREE(MTYPE_LS_DB
, node
);
1200 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
1202 struct ls_attributes
*attr
;
1203 uint8_t nb_ext_adm_grp
;
1204 uint32_t bitmap_data
;
1207 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
1208 admin_group_init(&attr
->ext_admin_group
);
1211 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
1212 STREAM_GETL(s
, attr
->flags
);
1213 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1214 STREAM_GETC(s
, len
);
1215 STREAM_GET(attr
->name
, s
, len
);
1217 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1218 STREAM_GETL(s
, attr
->metric
);
1219 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1220 STREAM_GETL(s
, attr
->standard
.te_metric
);
1221 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1222 STREAM_GETL(s
, attr
->standard
.admin_group
);
1223 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
1224 /* Extended Administrative Group */
1225 STREAM_GETC(s
, nb_ext_adm_grp
);
1226 for (size_t i
= 0; i
< nb_ext_adm_grp
; i
++) {
1227 STREAM_GETL(s
, bitmap_data
);
1228 admin_group_bulk_set(&attr
->ext_admin_group
,
1232 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1233 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
1234 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1235 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
1236 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1237 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
1238 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1239 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
1240 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1241 STREAM_GETL(s
, attr
->standard
.local_id
);
1242 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1243 STREAM_GETL(s
, attr
->standard
.remote_id
);
1244 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1245 STREAM_GETF(s
, attr
->standard
.max_bw
);
1246 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1247 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
1248 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1249 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1250 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
1251 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1252 STREAM_GETL(s
, attr
->standard
.remote_as
);
1253 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1254 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
1255 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1256 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
1257 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1258 STREAM_GETL(s
, attr
->extended
.delay
);
1259 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1260 STREAM_GETL(s
, attr
->extended
.min_delay
);
1261 STREAM_GETL(s
, attr
->extended
.max_delay
);
1263 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1264 STREAM_GETL(s
, attr
->extended
.jitter
);
1265 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1266 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
1267 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1268 STREAM_GETF(s
, attr
->extended
.ava_bw
);
1269 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1270 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
1271 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1272 STREAM_GETF(s
, attr
->extended
.used_bw
);
1273 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1274 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1275 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1276 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1277 attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
=
1280 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1281 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1282 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1283 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1284 attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
=
1287 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1288 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1289 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1290 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1291 STREAM_GET(attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
, s
,
1294 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1295 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1296 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1297 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1298 STREAM_GET(attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
, s
,
1301 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1302 STREAM_GETC(s
, len
);
1303 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
1304 attr
->srlg_len
= len
;
1305 for (len
= 0; len
< attr
->srlg_len
; len
++)
1306 STREAM_GETL(s
, attr
->srlgs
[len
]);
1312 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1314 /* Clean memory allocation */
1315 if (attr
->srlgs
!= NULL
)
1316 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
1317 XFREE(MTYPE_LS_DB
, attr
);
1322 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
1324 struct ls_prefix
*ls_pref
;
1327 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
1329 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
1330 STREAM_GETW(s
, ls_pref
->flags
);
1331 STREAM_GETC(s
, ls_pref
->pref
.family
);
1332 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
1333 len
= prefix_blen(&ls_pref
->pref
);
1334 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
1335 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1336 STREAM_GETC(s
, ls_pref
->igp_flag
);
1337 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1338 STREAM_GETL(s
, ls_pref
->route_tag
);
1339 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1340 STREAM_GETQ(s
, ls_pref
->extended_tag
);
1341 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1342 STREAM_GETL(s
, ls_pref
->metric
);
1343 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1344 STREAM_GETL(s
, ls_pref
->sr
.sid
);
1345 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
1346 STREAM_GETC(s
, ls_pref
->sr
.algo
);
1352 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
1353 XFREE(MTYPE_LS_DB
, ls_pref
);
1357 struct ls_message
*ls_parse_msg(struct stream
*s
)
1359 struct ls_message
*msg
;
1361 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1363 /* Read LS Message header */
1364 STREAM_GETC(s
, msg
->event
);
1365 STREAM_GETC(s
, msg
->type
);
1367 /* Read Message Payload */
1368 switch (msg
->type
) {
1369 case LS_MSG_TYPE_NODE
:
1370 msg
->data
.node
= ls_parse_node(s
);
1372 case LS_MSG_TYPE_ATTRIBUTES
:
1373 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
1374 msg
->data
.attr
= ls_parse_attributes(s
);
1376 case LS_MSG_TYPE_PREFIX
:
1377 msg
->data
.prefix
= ls_parse_prefix(s
);
1380 zlog_err("Unsupported Payload");
1381 goto stream_failure
;
1384 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
1385 || msg
->data
.prefix
== NULL
)
1386 goto stream_failure
;
1391 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
1392 XFREE(MTYPE_LS_DB
, msg
);
1396 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
1400 /* Push Advertise node information first */
1401 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
1403 /* Push Flags & Origin then Node information if there are present */
1404 stream_putw(s
, node
->flags
);
1405 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1406 len
= strlen(node
->name
);
1407 stream_putc(s
, len
+ 1);
1408 stream_put(s
, node
->name
, len
);
1409 stream_putc(s
, '\0');
1411 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1412 stream_put_ipv4(s
, node
->router_id
.s_addr
);
1413 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1414 stream_put(s
, &node
->router_id6
, IPV6_MAX_BYTELEN
);
1415 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1416 stream_putc(s
, node
->node_flag
);
1417 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1418 stream_putc(s
, node
->type
);
1419 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1420 stream_putl(s
, node
->as_number
);
1421 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1422 stream_putl(s
, node
->srgb
.lower_bound
);
1423 stream_putl(s
, node
->srgb
.range_size
);
1424 stream_putc(s
, node
->srgb
.flag
);
1425 stream_put(s
, node
->algo
, 2);
1427 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1428 stream_putl(s
, node
->srlb
.lower_bound
);
1429 stream_putl(s
, node
->srlb
.range_size
);
1431 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1432 stream_putc(s
, node
->msd
);
1437 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
1439 size_t len
, nb_ext_adm_grp
;
1441 /* Push Advertise node information first */
1442 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
1444 /* Push Flags & Origin then LS attributes if there are present */
1445 stream_putl(s
, attr
->flags
);
1446 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1447 len
= strlen(attr
->name
);
1448 stream_putc(s
, len
+ 1);
1449 stream_put(s
, attr
->name
, len
);
1450 stream_putc(s
, '\0');
1452 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1453 stream_putl(s
, attr
->metric
);
1454 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1455 stream_putl(s
, attr
->standard
.te_metric
);
1456 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1457 stream_putl(s
, attr
->standard
.admin_group
);
1458 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
1459 /* Extended Administrative Group */
1460 nb_ext_adm_grp
= admin_group_nb_words(&attr
->ext_admin_group
);
1461 stream_putc(s
, nb_ext_adm_grp
);
1462 for (size_t i
= 0; i
< nb_ext_adm_grp
; i
++)
1463 stream_putl(s
, admin_group_get_offset(
1464 &attr
->ext_admin_group
, i
));
1466 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1467 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
1468 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1469 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
1470 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1471 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
1472 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1473 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
1474 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1475 stream_putl(s
, attr
->standard
.local_id
);
1476 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1477 stream_putl(s
, attr
->standard
.remote_id
);
1478 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1479 stream_putf(s
, attr
->standard
.max_bw
);
1480 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1481 stream_putf(s
, attr
->standard
.max_rsv_bw
);
1482 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1483 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1484 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
1485 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1486 stream_putl(s
, attr
->standard
.remote_as
);
1487 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1488 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
1489 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1490 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
1491 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1492 stream_putl(s
, attr
->extended
.delay
);
1493 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1494 stream_putl(s
, attr
->extended
.min_delay
);
1495 stream_putl(s
, attr
->extended
.max_delay
);
1497 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1498 stream_putl(s
, attr
->extended
.jitter
);
1499 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1500 stream_putl(s
, attr
->extended
.pkt_loss
);
1501 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1502 stream_putf(s
, attr
->extended
.ava_bw
);
1503 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1504 stream_putf(s
, attr
->extended
.rsv_bw
);
1505 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1506 stream_putf(s
, attr
->extended
.used_bw
);
1507 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1508 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1509 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1510 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1512 s
, attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
);
1514 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1515 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1516 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1517 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1519 s
, attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
);
1521 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1522 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1523 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1524 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1525 stream_put(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
,
1528 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1529 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1530 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1531 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1532 stream_put(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
,
1535 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1536 stream_putc(s
, attr
->srlg_len
);
1537 for (len
= 0; len
< attr
->srlg_len
; len
++)
1538 stream_putl(s
, attr
->srlgs
[len
]);
1544 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1548 /* Push Advertise node information first */
1549 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1551 /* Push Flags, Origin & Prefix then information if there are present */
1552 stream_putw(s
, ls_pref
->flags
);
1553 stream_putc(s
, ls_pref
->pref
.family
);
1554 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1555 len
= prefix_blen(&ls_pref
->pref
);
1556 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1557 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1558 stream_putc(s
, ls_pref
->igp_flag
);
1559 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1560 stream_putl(s
, ls_pref
->route_tag
);
1561 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1562 stream_putq(s
, ls_pref
->extended_tag
);
1563 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1564 stream_putl(s
, ls_pref
->metric
);
1565 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1566 stream_putl(s
, ls_pref
->sr
.sid
);
1567 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1568 stream_putc(s
, ls_pref
->sr
.algo
);
1574 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1577 /* Prepare Link State header */
1578 stream_putc(s
, msg
->event
);
1579 stream_putc(s
, msg
->type
);
1581 /* Add Message Payload */
1582 switch (msg
->type
) {
1583 case LS_MSG_TYPE_NODE
:
1584 return ls_format_node(s
, msg
->data
.node
);
1585 case LS_MSG_TYPE_ATTRIBUTES
:
1586 /* Add remote node first */
1587 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1588 return ls_format_attributes(s
, msg
->data
.attr
);
1589 case LS_MSG_TYPE_PREFIX
:
1590 return ls_format_prefix(s
, msg
->data
.prefix
);
1592 zlog_warn("Unsupported Payload");
1599 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1600 struct zapi_opaque_reg_info
*dst
)
1605 /* Check if we have a valid message */
1606 if (msg
->event
== LS_MSG_EVENT_UNDEF
)
1609 /* Check buffer size */
1610 if (STREAM_SIZE(zclient
->obuf
) <
1611 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1617 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1619 /* Set sub-type, flags and destination for unicast message */
1620 stream_putl(s
, LINK_STATE_UPDATE
);
1622 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1623 stream_putw(s
, flags
);
1624 /* Send destination client info */
1625 stream_putc(s
, dst
->proto
);
1626 stream_putw(s
, dst
->instance
);
1627 stream_putl(s
, dst
->session_id
);
1629 stream_putw(s
, flags
);
1632 /* Format Link State message */
1633 if (ls_format_msg(s
, msg
) < 0) {
1638 /* Put length into the header at the start of the stream. */
1639 stream_putw_at(s
, 0, stream_get_endp(s
));
1641 return zclient_send_message(zclient
);
1643 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1644 struct ls_vertex
*vertex
)
1646 /* Allocate space if needed */
1648 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1650 memset(msg
, 0, sizeof(*msg
));
1652 msg
->type
= LS_MSG_TYPE_NODE
;
1653 switch (vertex
->status
) {
1655 msg
->event
= LS_MSG_EVENT_ADD
;
1658 msg
->event
= LS_MSG_EVENT_UPDATE
;
1661 msg
->event
= LS_MSG_EVENT_DELETE
;
1664 msg
->event
= LS_MSG_EVENT_SYNC
;
1668 msg
->event
= LS_MSG_EVENT_UNDEF
;
1671 msg
->data
.node
= vertex
->node
;
1672 msg
->remote_id
.origin
= UNKNOWN
;
1677 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1679 /* Allocate space if needed */
1681 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1683 memset(msg
, 0, sizeof(*msg
));
1685 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1686 switch (edge
->status
) {
1688 msg
->event
= LS_MSG_EVENT_ADD
;
1691 msg
->event
= LS_MSG_EVENT_UPDATE
;
1694 msg
->event
= LS_MSG_EVENT_DELETE
;
1697 msg
->event
= LS_MSG_EVENT_SYNC
;
1701 msg
->event
= LS_MSG_EVENT_UNDEF
;
1704 msg
->data
.attr
= edge
->attributes
;
1705 if (edge
->destination
!= NULL
)
1706 msg
->remote_id
= edge
->destination
->node
->adv
;
1708 msg
->remote_id
.origin
= UNKNOWN
;
1713 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1714 struct ls_subnet
*subnet
)
1716 /* Allocate space if needed */
1718 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1720 memset(msg
, 0, sizeof(*msg
));
1722 msg
->type
= LS_MSG_TYPE_PREFIX
;
1723 switch (subnet
->status
) {
1725 msg
->event
= LS_MSG_EVENT_ADD
;
1728 msg
->event
= LS_MSG_EVENT_UPDATE
;
1731 msg
->event
= LS_MSG_EVENT_DELETE
;
1734 msg
->event
= LS_MSG_EVENT_SYNC
;
1738 msg
->event
= LS_MSG_EVENT_UNDEF
;
1741 msg
->data
.prefix
= subnet
->ls_pref
;
1742 msg
->remote_id
.origin
= UNKNOWN
;
1747 struct ls_vertex
*ls_msg2vertex(struct ls_ted
*ted
, struct ls_message
*msg
,
1750 struct ls_node
*node
= (struct ls_node
*)msg
->data
.node
;
1751 struct ls_vertex
*vertex
= NULL
;
1753 switch (msg
->event
) {
1754 case LS_MSG_EVENT_SYNC
:
1755 vertex
= ls_vertex_add(ted
, node
);
1757 vertex
->status
= SYNC
;
1759 case LS_MSG_EVENT_ADD
:
1760 vertex
= ls_vertex_add(ted
, node
);
1762 vertex
->status
= NEW
;
1764 case LS_MSG_EVENT_UPDATE
:
1765 vertex
= ls_vertex_update(ted
, node
);
1767 vertex
->status
= UPDATE
;
1769 case LS_MSG_EVENT_DELETE
:
1770 vertex
= ls_find_vertex_by_id(ted
, node
->adv
);
1773 ls_vertex_del_all(ted
, vertex
);
1775 vertex
->status
= DELETE
;
1786 struct ls_edge
*ls_msg2edge(struct ls_ted
*ted
, struct ls_message
*msg
,
1789 struct ls_attributes
*attr
= (struct ls_attributes
*)msg
->data
.attr
;
1790 struct ls_edge
*edge
= NULL
;
1792 switch (msg
->event
) {
1793 case LS_MSG_EVENT_SYNC
:
1794 edge
= ls_edge_add(ted
, attr
);
1796 edge
->status
= SYNC
;
1798 case LS_MSG_EVENT_ADD
:
1799 edge
= ls_edge_add(ted
, attr
);
1803 case LS_MSG_EVENT_UPDATE
:
1804 edge
= ls_edge_update(ted
, attr
);
1806 edge
->status
= UPDATE
;
1808 case LS_MSG_EVENT_DELETE
:
1809 edge
= ls_find_edge_by_source(ted
, attr
);
1812 ls_edge_del_all(ted
, edge
);
1815 edge
->status
= DELETE
;
1826 struct ls_subnet
*ls_msg2subnet(struct ls_ted
*ted
, struct ls_message
*msg
,
1829 struct ls_prefix
*pref
= (struct ls_prefix
*)msg
->data
.prefix
;
1830 struct ls_subnet
*subnet
= NULL
;
1832 switch (msg
->event
) {
1833 case LS_MSG_EVENT_SYNC
:
1834 subnet
= ls_subnet_add(ted
, pref
);
1836 subnet
->status
= SYNC
;
1838 case LS_MSG_EVENT_ADD
:
1839 subnet
= ls_subnet_add(ted
, pref
);
1841 subnet
->status
= NEW
;
1843 case LS_MSG_EVENT_UPDATE
:
1844 subnet
= ls_subnet_update(ted
, pref
);
1846 subnet
->status
= UPDATE
;
1848 case LS_MSG_EVENT_DELETE
:
1849 subnet
= ls_find_subnet(ted
, pref
->pref
);
1852 ls_subnet_del_all(ted
, subnet
);
1854 subnet
->status
= DELETE
;
1865 struct ls_element
*ls_msg2ted(struct ls_ted
*ted
, struct ls_message
*msg
,
1868 struct ls_element
*lse
= NULL
;
1870 switch (msg
->type
) {
1871 case LS_MSG_TYPE_NODE
:
1872 lse
= (struct ls_element
*)ls_msg2vertex(ted
, msg
, delete);
1874 case LS_MSG_TYPE_ATTRIBUTES
:
1875 lse
= (struct ls_element
*)ls_msg2edge(ted
, msg
, delete);
1877 case LS_MSG_TYPE_PREFIX
:
1878 lse
= (struct ls_element
*)ls_msg2subnet(ted
, msg
, delete);
1888 struct ls_element
*ls_stream2ted(struct ls_ted
*ted
, struct stream
*s
,
1891 struct ls_message
*msg
;
1892 struct ls_element
*lse
= NULL
;
1894 msg
= ls_parse_msg(s
);
1896 lse
= ls_msg2ted(ted
, msg
, delete);
1903 void ls_delete_msg(struct ls_message
*msg
)
1908 XFREE(MTYPE_LS_DB
, msg
);
1911 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1912 struct zapi_opaque_reg_info
*dst
)
1914 struct ls_vertex
*vertex
;
1915 struct ls_edge
*edge
;
1916 struct ls_subnet
*subnet
;
1917 struct ls_message msg
;
1919 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1920 frr_each(vertices
, &ted
->vertices
, vertex
) {
1921 ls_vertex2msg(&msg
, vertex
);
1922 ls_send_msg(zclient
, &msg
, dst
);
1924 frr_each(edges
, &ted
->edges
, edge
) {
1925 ls_edge2msg(&msg
, edge
);
1926 ls_send_msg(zclient
, &msg
, dst
);
1928 frr_each(subnets
, &ted
->subnets
, subnet
) {
1929 ls_subnet2msg(&msg
, subnet
);
1930 ls_send_msg(zclient
, &msg
, dst
);
1936 * Link State Show functions
1938 static const char *const origin2txt
[] = {
1947 static const char *const type2txt
[] = {
1956 static const char *const status2txt
[] = {
1965 static const char *ls_node_id_to_text(struct ls_node_id lnid
, char *str
,
1968 if (lnid
.origin
== ISIS_L1
|| lnid
.origin
== ISIS_L2
) {
1971 id
= lnid
.id
.iso
.sys_id
;
1972 snprintfrr(str
, size
, "%02x%02x.%02x%02x.%02x%02x", id
[0],
1973 id
[1], id
[2], id
[3], id
[4], id
[5]);
1975 snprintfrr(str
, size
, "%pI4", &lnid
.id
.ip
.addr
);
1980 static void ls_show_vertex_vty(struct ls_vertex
*vertex
, struct vty
*vty
,
1983 struct listnode
*node
;
1984 struct ls_node
*lsn
;
1985 struct ls_edge
*edge
;
1986 struct ls_attributes
*attr
;
1987 struct ls_subnet
*subnet
;
1997 sbuf_init(&sbuf
, NULL
, 0);
1999 sbuf_push(&sbuf
, 2, "Vertex (%" PRIu64
"): %s", vertex
->key
, lsn
->name
);
2000 sbuf_push(&sbuf
, 0, "\tRouter Id: %pI4", &lsn
->router_id
);
2001 sbuf_push(&sbuf
, 0, "\tOrigin: %s", origin2txt
[lsn
->adv
.origin
]);
2002 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[vertex
->status
]);
2006 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
2007 listcount(vertex
->outgoing_edges
),
2008 listcount(vertex
->incoming_edges
),
2009 listcount(vertex
->prefixes
));
2013 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2014 sbuf_push(&sbuf
, 4, "Type: %s\n", type2txt
[lsn
->type
]);
2015 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2016 sbuf_push(&sbuf
, 4, "AS number: %u\n", lsn
->as_number
);
2017 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2018 sbuf_push(&sbuf
, 4, "Segment Routing Capabilities:\n");
2019 upper
= lsn
->srgb
.lower_bound
+ lsn
->srgb
.range_size
- 1;
2020 sbuf_push(&sbuf
, 8, "SRGB: [%d/%d]", lsn
->srgb
.lower_bound
,
2022 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2023 upper
= lsn
->srlb
.lower_bound
+ lsn
->srlb
.range_size
2025 sbuf_push(&sbuf
, 0, "\tSRLB: [%d/%d]",
2026 lsn
->srlb
.lower_bound
, upper
);
2028 sbuf_push(&sbuf
, 0, "\tAlgo: ");
2029 for (int i
= 0; i
< 2; i
++) {
2030 if (lsn
->algo
[i
] == 255)
2034 lsn
->algo
[i
] == 0 ? "SPF " : "S-SPF ");
2036 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2037 sbuf_push(&sbuf
, 0, "\tMSD: %d", lsn
->msd
);
2038 sbuf_push(&sbuf
, 0, "\n");
2041 sbuf_push(&sbuf
, 4, "Outgoing Edges: %d\n",
2042 listcount(vertex
->outgoing_edges
));
2043 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, node
, edge
)) {
2044 if (edge
->destination
) {
2045 lsn
= edge
->destination
->node
;
2046 sbuf_push(&sbuf
, 6, "To:\t%s(%pI4)", lsn
->name
,
2049 sbuf_push(&sbuf
, 6, "To:\t- (0.0.0.0)");
2051 attr
= edge
->attributes
;
2052 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2053 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2054 &attr
->standard
.local
,
2055 &attr
->standard
.remote
);
2056 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2057 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2058 &attr
->standard
.local6
,
2059 &attr
->standard
.remote6
);
2062 sbuf_push(&sbuf
, 4, "Incoming Edges: %d\n",
2063 listcount(vertex
->incoming_edges
));
2064 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, node
, edge
)) {
2066 lsn
= edge
->source
->node
;
2067 sbuf_push(&sbuf
, 6, "From:\t%s(%pI4)", lsn
->name
,
2070 sbuf_push(&sbuf
, 6, "From:\t- (0.0.0.0)");
2072 attr
= edge
->attributes
;
2073 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2074 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2075 &attr
->standard
.local
,
2076 &attr
->standard
.remote
);
2077 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2078 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2079 &attr
->standard
.local6
,
2080 &attr
->standard
.remote6
);
2083 sbuf_push(&sbuf
, 4, "Subnets: %d\n", listcount(vertex
->prefixes
));
2084 for (ALL_LIST_ELEMENTS_RO(vertex
->prefixes
, node
, subnet
))
2085 sbuf_push(&sbuf
, 6, "Prefix:\t%pFX\n", &subnet
->key
);
2088 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2092 static void ls_show_vertex_json(struct ls_vertex
*vertex
,
2093 struct json_object
*json
)
2095 struct ls_node
*lsn
;
2096 json_object
*jsr
, *jalgo
, *jobj
;
2097 char buf
[INET6_BUFSIZ
];
2105 json_object_int_add(json
, "vertex-id", vertex
->key
);
2106 json_object_string_add(json
, "status", status2txt
[vertex
->status
]);
2107 json_object_string_add(json
, "origin", origin2txt
[lsn
->adv
.origin
]);
2108 if (CHECK_FLAG(lsn
->flags
, LS_NODE_NAME
))
2109 json_object_string_add(json
, "name", lsn
->name
);
2110 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID
)) {
2111 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &lsn
->router_id
);
2112 json_object_string_add(json
, "router-id", buf
);
2114 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID6
)) {
2115 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &lsn
->router_id6
);
2116 json_object_string_add(json
, "router-id-v6", buf
);
2118 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2119 json_object_string_add(json
, "vertex-type",
2120 type2txt
[lsn
->type
]);
2121 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2122 json_object_int_add(json
, "asn", lsn
->as_number
);
2123 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2124 jsr
= json_object_new_object();
2125 json_object_object_add(json
, "segment-routing", jsr
);
2126 json_object_int_add(jsr
, "srgb-size", lsn
->srgb
.range_size
);
2127 json_object_int_add(jsr
, "srgb-lower", lsn
->srgb
.lower_bound
);
2128 jalgo
= json_object_new_array();
2129 json_object_object_add(jsr
, "algorithms", jalgo
);
2130 for (int i
= 0; i
< 2; i
++) {
2131 if (lsn
->algo
[i
] == 255)
2133 jobj
= json_object_new_object();
2135 snprintfrr(buf
, 2, "%u", i
);
2136 json_object_string_add(
2137 jobj
, buf
, lsn
->algo
[i
] == 0 ? "SPF" : "S-SPF");
2138 json_object_array_add(jalgo
, jobj
);
2140 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2141 json_object_int_add(jsr
, "srlb-size",
2142 lsn
->srlb
.range_size
);
2143 json_object_int_add(jsr
, "srlb-lower",
2144 lsn
->srlb
.lower_bound
);
2146 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2147 json_object_int_add(jsr
, "msd", lsn
->msd
);
2151 void ls_show_vertex(struct ls_vertex
*vertex
, struct vty
*vty
,
2152 struct json_object
*json
, bool verbose
)
2155 ls_show_vertex_json(vertex
, json
);
2157 ls_show_vertex_vty(vertex
, vty
, verbose
);
2160 void ls_show_vertices(struct ls_ted
*ted
, struct vty
*vty
,
2161 struct json_object
*json
, bool verbose
)
2163 struct ls_vertex
*vertex
;
2164 json_object
*jnodes
, *jnode
;
2167 jnodes
= json_object_new_array();
2168 json_object_object_add(json
, "vertices", jnodes
);
2169 frr_each (vertices
, &ted
->vertices
, vertex
) {
2170 jnode
= json_object_new_object();
2171 ls_show_vertex(vertex
, NULL
, jnode
, verbose
);
2172 json_object_array_add(jnodes
, jnode
);
2175 frr_each (vertices
, &ted
->vertices
, vertex
)
2176 ls_show_vertex(vertex
, vty
, NULL
, verbose
);
2180 static void ls_show_edge_vty(struct ls_edge
*edge
, struct vty
*vty
,
2183 char admin_group_buf
[ADMIN_GROUP_PRINT_MAX_SIZE
];
2184 struct ls_attributes
*attr
;
2186 char buf
[INET6_BUFSIZ
];
2189 attr
= edge
->attributes
;
2190 sbuf_init(&sbuf
, NULL
, 0);
2192 sbuf_push(&sbuf
, 2, "Edge (%" PRIu64
"): ", edge
->key
);
2193 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2194 sbuf_push(&sbuf
, 0, "%pI4", &attr
->standard
.local
);
2195 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2196 sbuf_push(&sbuf
, 0, "%pI6", &attr
->standard
.local6
);
2198 sbuf_push(&sbuf
, 0, "%u/%u", attr
->standard
.local_id
,
2199 attr
->standard
.remote_id
);
2200 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2201 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2202 sbuf_push(&sbuf
, 0, "\tMetric: %u", attr
->metric
);
2203 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[edge
->status
]);
2208 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[attr
->adv
.origin
]);
2209 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2210 sbuf_push(&sbuf
, 4, "Name: %s\n", attr
->name
);
2211 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2212 sbuf_push(&sbuf
, 4, "TE Metric: %u\n",
2213 attr
->standard
.te_metric
);
2214 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2215 sbuf_push(&sbuf
, 4, "Admin Group: 0x%x\n",
2216 attr
->standard
.admin_group
);
2217 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
) &&
2218 admin_group_nb_words(&attr
->ext_admin_group
) != 0) {
2220 sbuf_push(&sbuf
, indent
, "Ext Admin Group: %s\n",
2222 admin_group_buf
, ADMIN_GROUP_PRINT_MAX_SIZE
,
2223 indent
+ strlen("Ext Admin Group: "),
2224 &attr
->ext_admin_group
));
2225 if (admin_group_buf
[0] != '\0' &&
2226 (sbuf
.pos
+ strlen(admin_group_buf
) +
2227 SBUF_DEFAULT_SIZE
/ 2) < sbuf
.size
)
2228 sbuf_push(&sbuf
, indent
+ 2, "Bit positions: %s\n",
2231 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2232 sbuf_push(&sbuf
, 4, "Local IPv4 address: %pI4\n",
2233 &attr
->standard
.local
);
2234 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
2235 sbuf_push(&sbuf
, 4, "Remote IPv4 address: %pI4\n",
2236 &attr
->standard
.remote
);
2237 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2238 sbuf_push(&sbuf
, 4, "Local IPv6 address: %pI6\n",
2239 &attr
->standard
.local6
);
2240 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
2241 sbuf_push(&sbuf
, 4, "Remote IPv6 address: %pI6\n",
2242 &attr
->standard
.remote6
);
2243 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2244 sbuf_push(&sbuf
, 4, "Local Identifier: %u\n",
2245 attr
->standard
.local_id
);
2246 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2247 sbuf_push(&sbuf
, 4, "Remote Identifier: %u\n",
2248 attr
->standard
.remote_id
);
2249 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2250 sbuf_push(&sbuf
, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2251 attr
->standard
.max_bw
);
2252 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2254 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2255 attr
->standard
.max_rsv_bw
);
2256 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2257 sbuf_push(&sbuf
, 4, "Unreserved Bandwidth per Class Type\n");
2258 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2)
2260 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2261 i
, attr
->standard
.unrsv_bw
[i
], i
+ 1,
2262 attr
->standard
.unrsv_bw
[i
+ 1]);
2264 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2265 sbuf_push(&sbuf
, 4, "Remote AS: %u\n",
2266 attr
->standard
.remote_as
);
2267 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
2268 sbuf_push(&sbuf
, 4, "Remote ASBR IPv4 address: %pI4\n",
2269 &attr
->standard
.remote_addr
);
2270 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
2271 sbuf_push(&sbuf
, 4, "Remote ASBR IPv6 address: %pI6\n",
2272 &attr
->standard
.remote_addr6
);
2273 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2274 sbuf_push(&sbuf
, 4, "Average Link Delay: %d (micro-sec)\n",
2275 attr
->extended
.delay
);
2276 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
))
2277 sbuf_push(&sbuf
, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2278 attr
->extended
.min_delay
, attr
->extended
.max_delay
);
2279 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2280 sbuf_push(&sbuf
, 4, "Delay Variation: %d (micro-sec)\n",
2281 attr
->extended
.jitter
);
2282 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2283 sbuf_push(&sbuf
, 4, "Link Loss: %g (%%)\n",
2284 (float)(attr
->extended
.pkt_loss
* LOSS_PRECISION
));
2285 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2286 sbuf_push(&sbuf
, 4, "Available Bandwidth: %g (Bytes/s)\n",
2287 attr
->extended
.ava_bw
);
2288 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2289 sbuf_push(&sbuf
, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2290 attr
->extended
.rsv_bw
);
2291 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2292 sbuf_push(&sbuf
, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2293 attr
->extended
.used_bw
);
2294 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2295 sbuf_push(&sbuf
, 4, "IPv4 Adjacency-SID: %u",
2296 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2297 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2298 attr
->adj_sid
[ADJ_PRI_IPV4
].flags
,
2299 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2301 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2302 sbuf_push(&sbuf
, 4, "IPv4 Bck. Adjacency-SID: %u",
2303 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2304 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2305 attr
->adj_sid
[ADJ_BCK_IPV4
].flags
,
2306 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2308 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2309 sbuf_push(&sbuf
, 4, "IPv6 Adjacency-SID: %u",
2310 attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
2311 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2312 attr
->adj_sid
[ADJ_PRI_IPV6
].flags
,
2313 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2315 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2316 sbuf_push(&sbuf
, 4, "IPv6 Bck. Adjacency-SID: %u",
2317 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2318 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2319 attr
->adj_sid
[ADJ_BCK_IPV6
].flags
,
2320 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2322 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2323 sbuf_push(&sbuf
, 4, "SRLGs: %d", attr
->srlg_len
);
2324 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2326 sbuf_push(&sbuf
, 8, "\n%u", attr
->srlgs
[i
]);
2328 sbuf_push(&sbuf
, 8, ", %u", attr
->srlgs
[i
]);
2330 sbuf_push(&sbuf
, 0, "\n");
2334 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2338 static void ls_show_edge_json(struct ls_edge
*edge
, struct json_object
*json
)
2340 struct ls_attributes
*attr
;
2341 struct json_object
*jte
, *jbw
, *jobj
, *jsr
= NULL
, *jsrlg
, *js_ext_ag
,
2342 *js_ext_ag_arr_word
,
2344 char buf
[INET6_BUFSIZ
];
2345 char buf_ag
[strlen("0xffffffff") + 1];
2349 attr
= edge
->attributes
;
2351 json_object_int_add(json
, "edge-id", edge
->key
);
2352 json_object_string_add(json
, "status", status2txt
[edge
->status
]);
2353 json_object_string_add(json
, "origin", origin2txt
[attr
->adv
.origin
]);
2354 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2355 json_object_string_add(json
, "advertised-router", buf
);
2357 json_object_int_add(json
, "local-vertex-id", edge
->source
->key
);
2358 if (edge
->destination
)
2359 json_object_int_add(json
, "remote-vertex-id",
2360 edge
->destination
->key
);
2361 json_object_int_add(json
, "metric", attr
->metric
);
2362 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2363 json_object_string_add(json
, "name", attr
->name
);
2364 jte
= json_object_new_object();
2365 json_object_object_add(json
, "edge-attributes", jte
);
2366 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2367 json_object_int_add(jte
, "te-metric", attr
->standard
.te_metric
);
2368 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2369 json_object_int_add(jte
, "admin-group",
2370 attr
->standard
.admin_group
);
2371 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
2372 js_ext_ag
= json_object_new_object();
2373 json_object_object_add(jte
, "extAdminGroup", js_ext_ag
);
2374 js_ext_ag_arr_word
= json_object_new_array();
2375 json_object_object_add(js_ext_ag
, "words", js_ext_ag_arr_word
);
2376 js_ext_ag_arr_bit
= json_object_new_array();
2377 json_object_object_add(js_ext_ag
, "bitPositions",
2379 for (i
= 0; i
< admin_group_nb_words(&attr
->ext_admin_group
);
2381 bitmap
= admin_group_get_offset(&attr
->ext_admin_group
,
2383 snprintf(buf_ag
, sizeof(buf_ag
), "0x%08x", bitmap
);
2384 json_object_array_add(js_ext_ag_arr_word
,
2385 json_object_new_string(buf_ag
));
2388 i
< (admin_group_size(&attr
->ext_admin_group
) * WORD_SIZE
);
2390 if (admin_group_get(&attr
->ext_admin_group
, i
))
2391 json_object_array_add(js_ext_ag_arr_bit
,
2392 json_object_new_int(i
));
2395 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
2396 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.local
);
2397 json_object_string_add(jte
, "local-address", buf
);
2399 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
2400 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.remote
);
2401 json_object_string_add(jte
, "remote-address", buf
);
2403 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
2404 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.local6
);
2405 json_object_string_add(jte
, "local-address-v6", buf
);
2407 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
2408 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.remote6
);
2409 json_object_string_add(jte
, "remote-address-v6", buf
);
2411 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2412 json_object_int_add(jte
, "local-identifier",
2413 attr
->standard
.local_id
);
2414 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2415 json_object_int_add(jte
, "remote-identifier",
2416 attr
->standard
.remote_id
);
2417 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2418 json_object_double_add(jte
, "max-link-bandwidth",
2419 attr
->standard
.max_bw
);
2420 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2421 json_object_double_add(jte
, "max-resv-link-bandwidth",
2422 attr
->standard
.max_rsv_bw
);
2423 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2424 jbw
= json_object_new_array();
2425 json_object_object_add(jte
, "unreserved-bandwidth", jbw
);
2426 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
++) {
2427 jobj
= json_object_new_object();
2428 snprintfrr(buf
, 13, "class-type-%u", i
);
2429 json_object_double_add(jobj
, buf
,
2430 attr
->standard
.unrsv_bw
[i
]);
2431 json_object_array_add(jbw
, jobj
);
2434 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2435 json_object_int_add(jte
, "remote-asn",
2436 attr
->standard
.remote_as
);
2437 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
)) {
2438 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4",
2439 &attr
->standard
.remote_addr
);
2440 json_object_string_add(jte
, "remote-as-address", buf
);
2442 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
)) {
2443 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6",
2444 &attr
->standard
.remote_addr6
);
2445 json_object_string_add(jte
, "remote-as-address-v6", buf
);
2447 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2448 json_object_int_add(jte
, "delay", attr
->extended
.delay
);
2449 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
2450 json_object_int_add(jte
, "min-delay", attr
->extended
.min_delay
);
2451 json_object_int_add(jte
, "max-delay", attr
->extended
.max_delay
);
2453 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2454 json_object_int_add(jte
, "jitter", attr
->extended
.jitter
);
2455 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2456 json_object_double_add(
2457 jte
, "loss", attr
->extended
.pkt_loss
* LOSS_PRECISION
);
2458 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2459 json_object_double_add(jte
, "available-bandwidth",
2460 attr
->extended
.ava_bw
);
2461 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2462 json_object_double_add(jte
, "residual-bandwidth",
2463 attr
->extended
.rsv_bw
);
2464 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2465 json_object_double_add(jte
, "utilized-bandwidth",
2466 attr
->extended
.used_bw
);
2467 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2468 jsrlg
= json_object_new_array();
2469 json_object_object_add(jte
, "srlgs", jsrlg
);
2470 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2471 jobj
= json_object_new_object();
2472 json_object_int_add(jobj
, "srlg", attr
->srlgs
[i
]);
2473 json_object_array_add(jsrlg
, jobj
);
2476 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2477 jsr
= json_object_new_array();
2478 json_object_object_add(json
, "segment-routing", jsr
);
2479 jobj
= json_object_new_object();
2480 json_object_int_add(jobj
, "adj-sid",
2481 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2482 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
2483 json_object_string_add(jobj
, "flags", buf
);
2484 json_object_int_add(jobj
, "weight",
2485 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2486 json_object_array_add(jsr
, jobj
);
2488 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2490 jsr
= json_object_new_array();
2491 json_object_object_add(json
, "segment-routing", jsr
);
2493 jobj
= json_object_new_object();
2494 json_object_int_add(jobj
, "adj-sid",
2495 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2496 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
2497 json_object_string_add(jobj
, "flags", buf
);
2498 json_object_int_add(jobj
, "weight",
2499 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2500 json_object_array_add(jsr
, jobj
);
2502 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2503 jsr
= json_object_new_array();
2504 json_object_object_add(json
, "segment-routing", jsr
);
2505 jobj
= json_object_new_object();
2506 json_object_int_add(jobj
, "adj-sid",
2507 attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
2508 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
2509 json_object_string_add(jobj
, "flags", buf
);
2510 json_object_int_add(jobj
, "weight",
2511 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2512 json_object_array_add(jsr
, jobj
);
2514 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2516 jsr
= json_object_new_array();
2517 json_object_object_add(json
, "segment-routing", jsr
);
2519 jobj
= json_object_new_object();
2520 json_object_int_add(jobj
, "adj-sid",
2521 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2522 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
2523 json_object_string_add(jobj
, "flags", buf
);
2524 json_object_int_add(jobj
, "weight",
2525 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2526 json_object_array_add(jsr
, jobj
);
2530 void ls_show_edge(struct ls_edge
*edge
, struct vty
*vty
,
2531 struct json_object
*json
, bool verbose
)
2538 ls_show_edge_json(edge
, json
);
2540 ls_show_edge_vty(edge
, vty
, verbose
);
2543 void ls_show_edges(struct ls_ted
*ted
, struct vty
*vty
,
2544 struct json_object
*json
, bool verbose
)
2546 struct ls_edge
*edge
;
2547 json_object
*jedges
, *jedge
;
2550 jedges
= json_object_new_array();
2551 json_object_object_add(json
, "edges", jedges
);
2552 frr_each (edges
, &ted
->edges
, edge
) {
2553 jedge
= json_object_new_object();
2554 ls_show_edge(edge
, NULL
, jedge
, verbose
);
2555 json_object_array_add(jedges
, jedge
);
2558 frr_each (edges
, &ted
->edges
, edge
)
2559 ls_show_edge(edge
, vty
, NULL
, verbose
);
2563 static void ls_show_subnet_vty(struct ls_subnet
*subnet
, struct vty
*vty
,
2566 struct ls_prefix
*pref
;
2568 char buf
[INET6_BUFSIZ
];
2570 pref
= subnet
->ls_pref
;
2571 sbuf_init(&sbuf
, NULL
, 0);
2573 sbuf_push(&sbuf
, 2, "Subnet: %pFX", &subnet
->key
);
2574 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2575 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2576 sbuf_push(&sbuf
, 0, "\tMetric: %d", pref
->metric
);
2577 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[subnet
->status
]);
2582 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[pref
->adv
.origin
]);
2583 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
))
2584 sbuf_push(&sbuf
, 4, "Flags: %d\n", pref
->igp_flag
);
2586 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2587 sbuf_push(&sbuf
, 4, "Tag: %d\n", pref
->route_tag
);
2589 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2590 sbuf_push(&sbuf
, 4, "Extended Tag: %" PRIu64
"\n",
2591 pref
->extended_tag
);
2593 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
))
2594 sbuf_push(&sbuf
, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2595 pref
->sr
.sid
, pref
->sr
.algo
, pref
->sr
.sid_flag
);
2598 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2602 static void ls_show_subnet_json(struct ls_subnet
*subnet
,
2603 struct json_object
*json
)
2605 struct ls_prefix
*pref
;
2607 char buf
[INET6_BUFSIZ
];
2609 pref
= subnet
->ls_pref
;
2611 snprintfrr(buf
, INET6_BUFSIZ
, "%pFX", &subnet
->key
);
2612 json_object_string_add(json
, "subnet-id", buf
);
2613 json_object_string_add(json
, "status", status2txt
[subnet
->status
]);
2614 json_object_string_add(json
, "origin", origin2txt
[pref
->adv
.origin
]);
2615 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2616 json_object_string_add(json
, "advertised-router", buf
);
2618 json_object_int_add(json
, "vertex-id", subnet
->vertex
->key
);
2619 json_object_int_add(json
, "metric", pref
->metric
);
2620 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
)) {
2621 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->igp_flag
);
2622 json_object_string_add(json
, "flags", buf
);
2624 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2625 json_object_int_add(json
, "tag", pref
->route_tag
);
2626 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2627 json_object_int_add(json
, "extended-tag", pref
->extended_tag
);
2628 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
)) {
2629 jsr
= json_object_new_object();
2630 json_object_object_add(json
, "segment-routing", jsr
);
2631 json_object_int_add(jsr
, "pref-sid", pref
->sr
.sid
);
2632 json_object_int_add(jsr
, "algo", pref
->sr
.algo
);
2633 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->sr
.sid_flag
);
2634 json_object_string_add(jsr
, "flags", buf
);
2638 void ls_show_subnet(struct ls_subnet
*subnet
, struct vty
*vty
,
2639 struct json_object
*json
, bool verbose
)
2646 ls_show_subnet_json(subnet
, json
);
2648 ls_show_subnet_vty(subnet
, vty
, verbose
);
2651 void ls_show_subnets(struct ls_ted
*ted
, struct vty
*vty
,
2652 struct json_object
*json
, bool verbose
)
2654 struct ls_subnet
*subnet
;
2655 json_object
*jsubs
, *jsub
;
2658 jsubs
= json_object_new_array();
2659 json_object_object_add(json
, "subnets", jsubs
);
2660 frr_each (subnets
, &ted
->subnets
, subnet
) {
2661 jsub
= json_object_new_object();
2662 ls_show_subnet(subnet
, NULL
, jsub
, verbose
);
2663 json_object_array_add(jsubs
, jsub
);
2666 frr_each (subnets
, &ted
->subnets
, subnet
)
2667 ls_show_subnet(subnet
, vty
, NULL
, verbose
);
2671 void ls_show_ted(struct ls_ted
*ted
, struct vty
*vty
, struct json_object
*json
,
2677 jted
= json_object_new_object();
2678 json_object_object_add(json
, "ted", jted
);
2679 json_object_string_add(jted
, "name", ted
->name
);
2680 json_object_int_add(jted
, "key", ted
->key
);
2681 json_object_int_add(jted
, "verticesCount",
2682 vertices_count(&ted
->vertices
));
2683 json_object_int_add(jted
, "edgesCount",
2684 edges_count(&ted
->edges
));
2685 json_object_int_add(jted
, "subnetsCount",
2686 subnets_count(&ted
->subnets
));
2687 ls_show_vertices(ted
, NULL
, jted
, verbose
);
2688 ls_show_edges(ted
, NULL
, jted
, verbose
);
2689 ls_show_subnets(ted
, NULL
, jted
, verbose
);
2695 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2696 ted
->name
, ted
->key
);
2697 ls_show_vertices(ted
, vty
, NULL
, verbose
);
2698 ls_show_edges(ted
, vty
, NULL
, verbose
);
2699 ls_show_subnets(ted
, vty
, NULL
, verbose
);
2701 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2702 vertices_count(&ted
->vertices
),
2703 edges_count(&ted
->edges
), subnets_count(&ted
->subnets
));
2707 void ls_dump_ted(struct ls_ted
*ted
)
2709 struct ls_vertex
*vertex
;
2710 struct ls_edge
*edge
;
2711 struct ls_subnet
*subnet
;
2712 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
2714 zlog_debug("(%s) Ted init", __func__
);
2716 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2717 frr_each (vertices
, &ted
->vertices
, vertex
) {
2718 zlog_debug(" Ted node (%s %pI4 %s)",
2719 vertex
->node
->name
[0] ? vertex
->node
->name
2721 &vertex
->node
->router_id
,
2722 origin2txt
[vertex
->node
->adv
.origin
]);
2723 struct listnode
*lst_node
;
2724 struct ls_edge
*vertex_edge
;
2726 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
2729 " inc edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2731 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2732 &vertex_edge
->attributes
->standard
.local
,
2733 &vertex_edge
->attributes
->standard
.remote
);
2735 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
2738 " out edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2740 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2741 &vertex_edge
->attributes
->standard
.local
,
2742 &vertex_edge
->attributes
->standard
.remote
);
2745 frr_each (edges
, &ted
->edges
, edge
) {
2746 zlog_debug(" Ted edge key:%" PRIu64
"src:%pI4 dst:%pI4", edge
->key
,
2747 edge
->source
? &edge
->source
->node
->router_id
2750 ? &edge
->destination
->node
->router_id
2753 frr_each (subnets
, &ted
->subnets
, subnet
) {
2754 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2755 &subnet
->ls_pref
->pref
,
2756 &subnet
->vertex
->node
->adv
.id
.ip
.addr
);
2758 zlog_debug("(%s) Ted end", __func__
);