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
,
946 const struct prefix
*prefix
)
948 struct ls_subnet subnet
= {};
950 subnet
.key
= *prefix
;
951 return subnets_find(&ted
->subnets
, &subnet
);
955 * Link State TED management functions
957 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
962 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
964 /* Set basic information for this ted */
966 new->as_number
= as_number
;
967 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
969 /* Initialize the various RB tree */
970 vertices_init(&new->vertices
);
971 edges_init(&new->edges
);
972 subnets_init(&new->subnets
);
977 void ls_ted_del(struct ls_ted
*ted
)
982 /* Check that TED is empty */
983 if (vertices_count(&ted
->vertices
) || edges_count(&ted
->edges
)
984 || subnets_count(&ted
->subnets
))
987 /* Release RB Tree */
988 vertices_fini(&ted
->vertices
);
989 edges_fini(&ted
->edges
);
990 subnets_fini(&ted
->subnets
);
992 XFREE(MTYPE_LS_DB
, ted
);
995 void ls_ted_del_all(struct ls_ted
**ted
)
997 struct ls_vertex
*vertex
;
998 struct ls_edge
*edge
;
999 struct ls_subnet
*subnet
;
1004 /* First remove Vertices, Edges and Subnets and associated Link State */
1005 frr_each_safe (vertices
, &(*ted
)->vertices
, vertex
)
1006 ls_vertex_del_all(*ted
, vertex
);
1007 frr_each_safe (edges
, &(*ted
)->edges
, edge
)
1008 ls_edge_del_all(*ted
, edge
);
1009 frr_each_safe (subnets
, &(*ted
)->subnets
, subnet
)
1010 ls_subnet_del_all(*ted
, subnet
);
1012 /* then remove TED itself */
1017 void ls_ted_clean(struct ls_ted
*ted
)
1019 struct ls_vertex
*vertex
;
1020 struct ls_edge
*edge
;
1021 struct ls_subnet
*subnet
;
1026 /* First, start with Vertices */
1027 frr_each_safe (vertices
, &ted
->vertices
, vertex
)
1028 if (vertex
->status
== ORPHAN
)
1029 ls_vertex_del_all(ted
, vertex
);
1032 frr_each_safe (edges
, &ted
->edges
, edge
)
1033 if (edge
->status
== ORPHAN
)
1034 ls_edge_del_all(ted
, edge
);
1037 frr_each_safe (subnets
, &ted
->subnets
, subnet
)
1038 if (subnet
->status
== ORPHAN
)
1039 ls_subnet_del_all(ted
, subnet
);
1043 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1045 if (vertex
== NULL
|| edge
== NULL
)
1049 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
1050 edge
->source
= vertex
;
1052 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
1053 edge
->destination
= vertex
;
1057 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1060 if (vertex
== NULL
|| edge
== NULL
)
1064 listnode_delete(vertex
->outgoing_edges
, edge
);
1065 edge
->source
= NULL
;
1067 listnode_delete(vertex
->incoming_edges
, edge
);
1068 edge
->destination
= NULL
;
1072 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
1073 struct ls_edge
*edge
)
1079 edge
->destination
= dst
;
1082 listnode_add_sort_nodup(src
->outgoing_edges
, edge
);
1085 listnode_add_sort_nodup(dst
->incoming_edges
, edge
);
1088 void ls_disconnect_edge(struct ls_edge
*edge
)
1093 ls_disconnect(edge
->source
, edge
, true);
1094 ls_disconnect(edge
->destination
, edge
, false);
1096 /* Mark this Edge as ORPHAN for future cleanup */
1097 edge
->status
= ORPHAN
;
1101 * Link State Message management functions
1104 int ls_register(struct zclient
*zclient
, bool server
)
1109 rc
= zclient_register_opaque(zclient
, LINK_STATE_SYNC
);
1111 rc
= zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
1116 int ls_unregister(struct zclient
*zclient
, bool server
)
1121 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_SYNC
);
1123 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_UPDATE
);
1128 int ls_request_sync(struct zclient
*zclient
)
1133 /* Check buffer size */
1134 if (STREAM_SIZE(zclient
->obuf
)
1135 < (ZEBRA_HEADER_SIZE
+ 3 * sizeof(uint32_t)))
1141 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1143 /* Set type and flags */
1144 stream_putl(s
, LINK_STATE_SYNC
);
1145 stream_putw(s
, flags
);
1146 /* Send destination client info */
1147 stream_putc(s
, zclient
->redist_default
);
1148 stream_putw(s
, zclient
->instance
);
1149 stream_putl(s
, zclient
->session_id
);
1151 /* Put length into the header at the start of the stream. */
1152 stream_putw_at(s
, 0, stream_get_endp(s
));
1154 return zclient_send_message(zclient
);
1157 static struct ls_node
*ls_parse_node(struct stream
*s
)
1159 struct ls_node
*node
;
1162 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
1164 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
1165 STREAM_GETW(s
, node
->flags
);
1166 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1167 STREAM_GETC(s
, len
);
1168 STREAM_GET(node
->name
, s
, len
);
1170 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1171 node
->router_id
.s_addr
= stream_get_ipv4(s
);
1172 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1173 STREAM_GET(&node
->router_id6
, s
, IPV6_MAX_BYTELEN
);
1174 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1175 STREAM_GETC(s
, node
->node_flag
);
1176 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1177 STREAM_GETC(s
, node
->type
);
1178 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1179 STREAM_GETL(s
, node
->as_number
);
1180 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1181 STREAM_GETL(s
, node
->srgb
.lower_bound
);
1182 STREAM_GETL(s
, node
->srgb
.range_size
);
1183 STREAM_GETC(s
, node
->srgb
.flag
);
1184 STREAM_GET(node
->algo
, s
, 2);
1186 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1187 STREAM_GETL(s
, node
->srlb
.lower_bound
);
1188 STREAM_GETL(s
, node
->srlb
.range_size
);
1190 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1191 STREAM_GETC(s
, node
->msd
);
1196 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
1197 XFREE(MTYPE_LS_DB
, node
);
1201 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
1203 struct ls_attributes
*attr
;
1204 uint8_t nb_ext_adm_grp
;
1205 uint32_t bitmap_data
;
1208 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
1209 admin_group_init(&attr
->ext_admin_group
);
1212 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
1213 STREAM_GETL(s
, attr
->flags
);
1214 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1215 STREAM_GETC(s
, len
);
1216 STREAM_GET(attr
->name
, s
, len
);
1218 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1219 STREAM_GETL(s
, attr
->metric
);
1220 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1221 STREAM_GETL(s
, attr
->standard
.te_metric
);
1222 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1223 STREAM_GETL(s
, attr
->standard
.admin_group
);
1224 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
1225 /* Extended Administrative Group */
1226 STREAM_GETC(s
, nb_ext_adm_grp
);
1227 for (size_t i
= 0; i
< nb_ext_adm_grp
; i
++) {
1228 STREAM_GETL(s
, bitmap_data
);
1229 admin_group_bulk_set(&attr
->ext_admin_group
,
1233 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1234 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
1235 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1236 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
1237 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1238 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
1239 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1240 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
1241 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1242 STREAM_GETL(s
, attr
->standard
.local_id
);
1243 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1244 STREAM_GETL(s
, attr
->standard
.remote_id
);
1245 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1246 STREAM_GETF(s
, attr
->standard
.max_bw
);
1247 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1248 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
1249 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1250 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1251 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
1252 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1253 STREAM_GETL(s
, attr
->standard
.remote_as
);
1254 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1255 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
1256 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1257 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
1258 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1259 STREAM_GETL(s
, attr
->extended
.delay
);
1260 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1261 STREAM_GETL(s
, attr
->extended
.min_delay
);
1262 STREAM_GETL(s
, attr
->extended
.max_delay
);
1264 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1265 STREAM_GETL(s
, attr
->extended
.jitter
);
1266 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1267 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
1268 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1269 STREAM_GETF(s
, attr
->extended
.ava_bw
);
1270 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1271 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
1272 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1273 STREAM_GETF(s
, attr
->extended
.used_bw
);
1274 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1275 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1276 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1277 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1278 attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
=
1281 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1282 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1283 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1284 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1285 attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
=
1288 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1289 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1290 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1291 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1292 STREAM_GET(attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
, s
,
1295 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1296 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1297 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1298 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1299 STREAM_GET(attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
, s
,
1302 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1303 STREAM_GETC(s
, len
);
1304 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
1305 attr
->srlg_len
= len
;
1306 for (len
= 0; len
< attr
->srlg_len
; len
++)
1307 STREAM_GETL(s
, attr
->srlgs
[len
]);
1313 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1315 /* Clean memory allocation */
1316 if (attr
->srlgs
!= NULL
)
1317 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
1318 XFREE(MTYPE_LS_DB
, attr
);
1323 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
1325 struct ls_prefix
*ls_pref
;
1328 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
1330 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
1331 STREAM_GETW(s
, ls_pref
->flags
);
1332 STREAM_GETC(s
, ls_pref
->pref
.family
);
1333 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
1334 len
= prefix_blen(&ls_pref
->pref
);
1335 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
1336 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1337 STREAM_GETC(s
, ls_pref
->igp_flag
);
1338 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1339 STREAM_GETL(s
, ls_pref
->route_tag
);
1340 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1341 STREAM_GETQ(s
, ls_pref
->extended_tag
);
1342 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1343 STREAM_GETL(s
, ls_pref
->metric
);
1344 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1345 STREAM_GETL(s
, ls_pref
->sr
.sid
);
1346 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
1347 STREAM_GETC(s
, ls_pref
->sr
.algo
);
1353 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
1354 XFREE(MTYPE_LS_DB
, ls_pref
);
1358 struct ls_message
*ls_parse_msg(struct stream
*s
)
1360 struct ls_message
*msg
;
1362 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1364 /* Read LS Message header */
1365 STREAM_GETC(s
, msg
->event
);
1366 STREAM_GETC(s
, msg
->type
);
1368 /* Read Message Payload */
1369 switch (msg
->type
) {
1370 case LS_MSG_TYPE_NODE
:
1371 msg
->data
.node
= ls_parse_node(s
);
1373 case LS_MSG_TYPE_ATTRIBUTES
:
1374 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
1375 msg
->data
.attr
= ls_parse_attributes(s
);
1377 case LS_MSG_TYPE_PREFIX
:
1378 msg
->data
.prefix
= ls_parse_prefix(s
);
1381 zlog_err("Unsupported Payload");
1382 goto stream_failure
;
1385 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
1386 || msg
->data
.prefix
== NULL
)
1387 goto stream_failure
;
1392 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
1393 XFREE(MTYPE_LS_DB
, msg
);
1397 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
1401 /* Push Advertise node information first */
1402 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
1404 /* Push Flags & Origin then Node information if there are present */
1405 stream_putw(s
, node
->flags
);
1406 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1407 len
= strlen(node
->name
);
1408 stream_putc(s
, len
+ 1);
1409 stream_put(s
, node
->name
, len
);
1410 stream_putc(s
, '\0');
1412 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1413 stream_put_ipv4(s
, node
->router_id
.s_addr
);
1414 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1415 stream_put(s
, &node
->router_id6
, IPV6_MAX_BYTELEN
);
1416 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1417 stream_putc(s
, node
->node_flag
);
1418 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1419 stream_putc(s
, node
->type
);
1420 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1421 stream_putl(s
, node
->as_number
);
1422 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1423 stream_putl(s
, node
->srgb
.lower_bound
);
1424 stream_putl(s
, node
->srgb
.range_size
);
1425 stream_putc(s
, node
->srgb
.flag
);
1426 stream_put(s
, node
->algo
, 2);
1428 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1429 stream_putl(s
, node
->srlb
.lower_bound
);
1430 stream_putl(s
, node
->srlb
.range_size
);
1432 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1433 stream_putc(s
, node
->msd
);
1438 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
1440 size_t len
, nb_ext_adm_grp
;
1442 /* Push Advertise node information first */
1443 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
1445 /* Push Flags & Origin then LS attributes if there are present */
1446 stream_putl(s
, attr
->flags
);
1447 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1448 len
= strlen(attr
->name
);
1449 stream_putc(s
, len
+ 1);
1450 stream_put(s
, attr
->name
, len
);
1451 stream_putc(s
, '\0');
1453 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1454 stream_putl(s
, attr
->metric
);
1455 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1456 stream_putl(s
, attr
->standard
.te_metric
);
1457 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1458 stream_putl(s
, attr
->standard
.admin_group
);
1459 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
1460 /* Extended Administrative Group */
1461 nb_ext_adm_grp
= admin_group_nb_words(&attr
->ext_admin_group
);
1462 stream_putc(s
, nb_ext_adm_grp
);
1463 for (size_t i
= 0; i
< nb_ext_adm_grp
; i
++)
1464 stream_putl(s
, admin_group_get_offset(
1465 &attr
->ext_admin_group
, i
));
1467 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1468 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
1469 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1470 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
1471 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1472 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
1473 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1474 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
1475 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1476 stream_putl(s
, attr
->standard
.local_id
);
1477 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1478 stream_putl(s
, attr
->standard
.remote_id
);
1479 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1480 stream_putf(s
, attr
->standard
.max_bw
);
1481 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1482 stream_putf(s
, attr
->standard
.max_rsv_bw
);
1483 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1484 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1485 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
1486 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1487 stream_putl(s
, attr
->standard
.remote_as
);
1488 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1489 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
1490 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1491 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
1492 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1493 stream_putl(s
, attr
->extended
.delay
);
1494 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1495 stream_putl(s
, attr
->extended
.min_delay
);
1496 stream_putl(s
, attr
->extended
.max_delay
);
1498 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1499 stream_putl(s
, attr
->extended
.jitter
);
1500 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1501 stream_putl(s
, attr
->extended
.pkt_loss
);
1502 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1503 stream_putf(s
, attr
->extended
.ava_bw
);
1504 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1505 stream_putf(s
, attr
->extended
.rsv_bw
);
1506 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1507 stream_putf(s
, attr
->extended
.used_bw
);
1508 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1509 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1510 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1511 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1513 s
, attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
);
1515 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1516 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1517 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1518 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1520 s
, attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
);
1522 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1523 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1524 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1525 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1526 stream_put(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
,
1529 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1530 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1531 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1532 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1533 stream_put(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
,
1536 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1537 stream_putc(s
, attr
->srlg_len
);
1538 for (len
= 0; len
< attr
->srlg_len
; len
++)
1539 stream_putl(s
, attr
->srlgs
[len
]);
1545 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1549 /* Push Advertise node information first */
1550 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1552 /* Push Flags, Origin & Prefix then information if there are present */
1553 stream_putw(s
, ls_pref
->flags
);
1554 stream_putc(s
, ls_pref
->pref
.family
);
1555 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1556 len
= prefix_blen(&ls_pref
->pref
);
1557 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1558 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1559 stream_putc(s
, ls_pref
->igp_flag
);
1560 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1561 stream_putl(s
, ls_pref
->route_tag
);
1562 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1563 stream_putq(s
, ls_pref
->extended_tag
);
1564 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1565 stream_putl(s
, ls_pref
->metric
);
1566 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1567 stream_putl(s
, ls_pref
->sr
.sid
);
1568 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1569 stream_putc(s
, ls_pref
->sr
.algo
);
1575 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1578 /* Prepare Link State header */
1579 stream_putc(s
, msg
->event
);
1580 stream_putc(s
, msg
->type
);
1582 /* Add Message Payload */
1583 switch (msg
->type
) {
1584 case LS_MSG_TYPE_NODE
:
1585 return ls_format_node(s
, msg
->data
.node
);
1586 case LS_MSG_TYPE_ATTRIBUTES
:
1587 /* Add remote node first */
1588 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1589 return ls_format_attributes(s
, msg
->data
.attr
);
1590 case LS_MSG_TYPE_PREFIX
:
1591 return ls_format_prefix(s
, msg
->data
.prefix
);
1593 zlog_warn("Unsupported Payload");
1600 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1601 struct zapi_opaque_reg_info
*dst
)
1606 /* Check if we have a valid message */
1607 if (msg
->event
== LS_MSG_EVENT_UNDEF
)
1610 /* Check buffer size */
1611 if (STREAM_SIZE(zclient
->obuf
) <
1612 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1618 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1620 /* Set sub-type, flags and destination for unicast message */
1621 stream_putl(s
, LINK_STATE_UPDATE
);
1623 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1624 stream_putw(s
, flags
);
1625 /* Send destination client info */
1626 stream_putc(s
, dst
->proto
);
1627 stream_putw(s
, dst
->instance
);
1628 stream_putl(s
, dst
->session_id
);
1630 stream_putw(s
, flags
);
1633 /* Format Link State message */
1634 if (ls_format_msg(s
, msg
) < 0) {
1639 /* Put length into the header at the start of the stream. */
1640 stream_putw_at(s
, 0, stream_get_endp(s
));
1642 return zclient_send_message(zclient
);
1644 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1645 struct ls_vertex
*vertex
)
1647 /* Allocate space if needed */
1649 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1651 memset(msg
, 0, sizeof(*msg
));
1653 msg
->type
= LS_MSG_TYPE_NODE
;
1654 switch (vertex
->status
) {
1656 msg
->event
= LS_MSG_EVENT_ADD
;
1659 msg
->event
= LS_MSG_EVENT_UPDATE
;
1662 msg
->event
= LS_MSG_EVENT_DELETE
;
1665 msg
->event
= LS_MSG_EVENT_SYNC
;
1669 msg
->event
= LS_MSG_EVENT_UNDEF
;
1672 msg
->data
.node
= vertex
->node
;
1673 msg
->remote_id
.origin
= UNKNOWN
;
1678 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1680 /* Allocate space if needed */
1682 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1684 memset(msg
, 0, sizeof(*msg
));
1686 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1687 switch (edge
->status
) {
1689 msg
->event
= LS_MSG_EVENT_ADD
;
1692 msg
->event
= LS_MSG_EVENT_UPDATE
;
1695 msg
->event
= LS_MSG_EVENT_DELETE
;
1698 msg
->event
= LS_MSG_EVENT_SYNC
;
1702 msg
->event
= LS_MSG_EVENT_UNDEF
;
1705 msg
->data
.attr
= edge
->attributes
;
1706 if (edge
->destination
!= NULL
)
1707 msg
->remote_id
= edge
->destination
->node
->adv
;
1709 msg
->remote_id
.origin
= UNKNOWN
;
1714 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1715 struct ls_subnet
*subnet
)
1717 /* Allocate space if needed */
1719 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1721 memset(msg
, 0, sizeof(*msg
));
1723 msg
->type
= LS_MSG_TYPE_PREFIX
;
1724 switch (subnet
->status
) {
1726 msg
->event
= LS_MSG_EVENT_ADD
;
1729 msg
->event
= LS_MSG_EVENT_UPDATE
;
1732 msg
->event
= LS_MSG_EVENT_DELETE
;
1735 msg
->event
= LS_MSG_EVENT_SYNC
;
1739 msg
->event
= LS_MSG_EVENT_UNDEF
;
1742 msg
->data
.prefix
= subnet
->ls_pref
;
1743 msg
->remote_id
.origin
= UNKNOWN
;
1748 struct ls_vertex
*ls_msg2vertex(struct ls_ted
*ted
, struct ls_message
*msg
,
1751 struct ls_node
*node
= (struct ls_node
*)msg
->data
.node
;
1752 struct ls_vertex
*vertex
= NULL
;
1754 switch (msg
->event
) {
1755 case LS_MSG_EVENT_SYNC
:
1756 vertex
= ls_vertex_add(ted
, node
);
1758 vertex
->status
= SYNC
;
1760 case LS_MSG_EVENT_ADD
:
1761 vertex
= ls_vertex_add(ted
, node
);
1763 vertex
->status
= NEW
;
1765 case LS_MSG_EVENT_UPDATE
:
1766 vertex
= ls_vertex_update(ted
, node
);
1768 vertex
->status
= UPDATE
;
1770 case LS_MSG_EVENT_DELETE
:
1771 vertex
= ls_find_vertex_by_id(ted
, node
->adv
);
1774 ls_vertex_del_all(ted
, vertex
);
1776 vertex
->status
= DELETE
;
1787 struct ls_edge
*ls_msg2edge(struct ls_ted
*ted
, struct ls_message
*msg
,
1790 struct ls_attributes
*attr
= (struct ls_attributes
*)msg
->data
.attr
;
1791 struct ls_edge
*edge
= NULL
;
1793 switch (msg
->event
) {
1794 case LS_MSG_EVENT_SYNC
:
1795 edge
= ls_edge_add(ted
, attr
);
1797 edge
->status
= SYNC
;
1799 case LS_MSG_EVENT_ADD
:
1800 edge
= ls_edge_add(ted
, attr
);
1804 case LS_MSG_EVENT_UPDATE
:
1805 edge
= ls_edge_update(ted
, attr
);
1807 edge
->status
= UPDATE
;
1809 case LS_MSG_EVENT_DELETE
:
1810 edge
= ls_find_edge_by_source(ted
, attr
);
1813 ls_edge_del_all(ted
, edge
);
1816 edge
->status
= DELETE
;
1827 struct ls_subnet
*ls_msg2subnet(struct ls_ted
*ted
, struct ls_message
*msg
,
1830 struct ls_prefix
*pref
= (struct ls_prefix
*)msg
->data
.prefix
;
1831 struct ls_subnet
*subnet
= NULL
;
1833 switch (msg
->event
) {
1834 case LS_MSG_EVENT_SYNC
:
1835 subnet
= ls_subnet_add(ted
, pref
);
1837 subnet
->status
= SYNC
;
1839 case LS_MSG_EVENT_ADD
:
1840 subnet
= ls_subnet_add(ted
, pref
);
1842 subnet
->status
= NEW
;
1844 case LS_MSG_EVENT_UPDATE
:
1845 subnet
= ls_subnet_update(ted
, pref
);
1847 subnet
->status
= UPDATE
;
1849 case LS_MSG_EVENT_DELETE
:
1850 subnet
= ls_find_subnet(ted
, &pref
->pref
);
1853 ls_subnet_del_all(ted
, subnet
);
1855 subnet
->status
= DELETE
;
1866 struct ls_element
*ls_msg2ted(struct ls_ted
*ted
, struct ls_message
*msg
,
1869 struct ls_element
*lse
= NULL
;
1871 switch (msg
->type
) {
1872 case LS_MSG_TYPE_NODE
:
1873 lse
= (struct ls_element
*)ls_msg2vertex(ted
, msg
, delete);
1875 case LS_MSG_TYPE_ATTRIBUTES
:
1876 lse
= (struct ls_element
*)ls_msg2edge(ted
, msg
, delete);
1878 case LS_MSG_TYPE_PREFIX
:
1879 lse
= (struct ls_element
*)ls_msg2subnet(ted
, msg
, delete);
1889 struct ls_element
*ls_stream2ted(struct ls_ted
*ted
, struct stream
*s
,
1892 struct ls_message
*msg
;
1893 struct ls_element
*lse
= NULL
;
1895 msg
= ls_parse_msg(s
);
1897 lse
= ls_msg2ted(ted
, msg
, delete);
1904 void ls_delete_msg(struct ls_message
*msg
)
1909 XFREE(MTYPE_LS_DB
, msg
);
1912 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1913 struct zapi_opaque_reg_info
*dst
)
1915 struct ls_vertex
*vertex
;
1916 struct ls_edge
*edge
;
1917 struct ls_subnet
*subnet
;
1918 struct ls_message msg
;
1920 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1921 frr_each(vertices
, &ted
->vertices
, vertex
) {
1922 ls_vertex2msg(&msg
, vertex
);
1923 ls_send_msg(zclient
, &msg
, dst
);
1925 frr_each(edges
, &ted
->edges
, edge
) {
1926 ls_edge2msg(&msg
, edge
);
1927 ls_send_msg(zclient
, &msg
, dst
);
1929 frr_each(subnets
, &ted
->subnets
, subnet
) {
1930 ls_subnet2msg(&msg
, subnet
);
1931 ls_send_msg(zclient
, &msg
, dst
);
1937 * Link State Show functions
1939 static const char *const origin2txt
[] = {
1948 static const char *const type2txt
[] = {
1957 static const char *const status2txt
[] = {
1966 static const char *ls_node_id_to_text(struct ls_node_id lnid
, char *str
,
1969 if (lnid
.origin
== ISIS_L1
|| lnid
.origin
== ISIS_L2
) {
1972 id
= lnid
.id
.iso
.sys_id
;
1973 snprintfrr(str
, size
, "%02x%02x.%02x%02x.%02x%02x", id
[0],
1974 id
[1], id
[2], id
[3], id
[4], id
[5]);
1976 snprintfrr(str
, size
, "%pI4", &lnid
.id
.ip
.addr
);
1981 static void ls_show_vertex_vty(struct ls_vertex
*vertex
, struct vty
*vty
,
1984 struct listnode
*node
;
1985 struct ls_node
*lsn
;
1986 struct ls_edge
*edge
;
1987 struct ls_attributes
*attr
;
1988 struct ls_subnet
*subnet
;
1998 sbuf_init(&sbuf
, NULL
, 0);
2000 sbuf_push(&sbuf
, 2, "Vertex (%" PRIu64
"): %s", vertex
->key
, lsn
->name
);
2001 sbuf_push(&sbuf
, 0, "\tRouter Id: %pI4", &lsn
->router_id
);
2002 sbuf_push(&sbuf
, 0, "\tOrigin: %s", origin2txt
[lsn
->adv
.origin
]);
2003 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[vertex
->status
]);
2007 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
2008 listcount(vertex
->outgoing_edges
),
2009 listcount(vertex
->incoming_edges
),
2010 listcount(vertex
->prefixes
));
2014 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2015 sbuf_push(&sbuf
, 4, "Type: %s\n", type2txt
[lsn
->type
]);
2016 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2017 sbuf_push(&sbuf
, 4, "AS number: %u\n", lsn
->as_number
);
2018 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2019 sbuf_push(&sbuf
, 4, "Segment Routing Capabilities:\n");
2020 upper
= lsn
->srgb
.lower_bound
+ lsn
->srgb
.range_size
- 1;
2021 sbuf_push(&sbuf
, 8, "SRGB: [%d/%d]", lsn
->srgb
.lower_bound
,
2023 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2024 upper
= lsn
->srlb
.lower_bound
+ lsn
->srlb
.range_size
2026 sbuf_push(&sbuf
, 0, "\tSRLB: [%d/%d]",
2027 lsn
->srlb
.lower_bound
, upper
);
2029 sbuf_push(&sbuf
, 0, "\tAlgo: ");
2030 for (int i
= 0; i
< 2; i
++) {
2031 if (lsn
->algo
[i
] == 255)
2035 lsn
->algo
[i
] == 0 ? "SPF " : "S-SPF ");
2037 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2038 sbuf_push(&sbuf
, 0, "\tMSD: %d", lsn
->msd
);
2039 sbuf_push(&sbuf
, 0, "\n");
2042 sbuf_push(&sbuf
, 4, "Outgoing Edges: %d\n",
2043 listcount(vertex
->outgoing_edges
));
2044 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, node
, edge
)) {
2045 if (edge
->destination
) {
2046 lsn
= edge
->destination
->node
;
2047 sbuf_push(&sbuf
, 6, "To:\t%s(%pI4)", lsn
->name
,
2050 sbuf_push(&sbuf
, 6, "To:\t- (0.0.0.0)");
2052 attr
= edge
->attributes
;
2053 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2054 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2055 &attr
->standard
.local
,
2056 &attr
->standard
.remote
);
2057 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2058 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2059 &attr
->standard
.local6
,
2060 &attr
->standard
.remote6
);
2063 sbuf_push(&sbuf
, 4, "Incoming Edges: %d\n",
2064 listcount(vertex
->incoming_edges
));
2065 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, node
, edge
)) {
2067 lsn
= edge
->source
->node
;
2068 sbuf_push(&sbuf
, 6, "From:\t%s(%pI4)", lsn
->name
,
2071 sbuf_push(&sbuf
, 6, "From:\t- (0.0.0.0)");
2073 attr
= edge
->attributes
;
2074 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2075 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2076 &attr
->standard
.local
,
2077 &attr
->standard
.remote
);
2078 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2079 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2080 &attr
->standard
.local6
,
2081 &attr
->standard
.remote6
);
2084 sbuf_push(&sbuf
, 4, "Subnets: %d\n", listcount(vertex
->prefixes
));
2085 for (ALL_LIST_ELEMENTS_RO(vertex
->prefixes
, node
, subnet
))
2086 sbuf_push(&sbuf
, 6, "Prefix:\t%pFX\n", &subnet
->key
);
2089 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2093 static void ls_show_vertex_json(struct ls_vertex
*vertex
,
2094 struct json_object
*json
)
2096 struct ls_node
*lsn
;
2097 json_object
*jsr
, *jalgo
, *jobj
;
2098 char buf
[INET6_BUFSIZ
];
2106 json_object_int_add(json
, "vertex-id", vertex
->key
);
2107 json_object_string_add(json
, "status", status2txt
[vertex
->status
]);
2108 json_object_string_add(json
, "origin", origin2txt
[lsn
->adv
.origin
]);
2109 if (CHECK_FLAG(lsn
->flags
, LS_NODE_NAME
))
2110 json_object_string_add(json
, "name", lsn
->name
);
2111 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID
)) {
2112 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &lsn
->router_id
);
2113 json_object_string_add(json
, "router-id", buf
);
2115 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID6
)) {
2116 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &lsn
->router_id6
);
2117 json_object_string_add(json
, "router-id-v6", buf
);
2119 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2120 json_object_string_add(json
, "vertex-type",
2121 type2txt
[lsn
->type
]);
2122 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2123 json_object_int_add(json
, "asn", lsn
->as_number
);
2124 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2125 jsr
= json_object_new_object();
2126 json_object_object_add(json
, "segment-routing", jsr
);
2127 json_object_int_add(jsr
, "srgb-size", lsn
->srgb
.range_size
);
2128 json_object_int_add(jsr
, "srgb-lower", lsn
->srgb
.lower_bound
);
2129 jalgo
= json_object_new_array();
2130 json_object_object_add(jsr
, "algorithms", jalgo
);
2131 for (int i
= 0; i
< 2; i
++) {
2132 if (lsn
->algo
[i
] == 255)
2134 jobj
= json_object_new_object();
2136 snprintfrr(buf
, 2, "%u", i
);
2137 json_object_string_add(
2138 jobj
, buf
, lsn
->algo
[i
] == 0 ? "SPF" : "S-SPF");
2139 json_object_array_add(jalgo
, jobj
);
2141 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2142 json_object_int_add(jsr
, "srlb-size",
2143 lsn
->srlb
.range_size
);
2144 json_object_int_add(jsr
, "srlb-lower",
2145 lsn
->srlb
.lower_bound
);
2147 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2148 json_object_int_add(jsr
, "msd", lsn
->msd
);
2152 void ls_show_vertex(struct ls_vertex
*vertex
, struct vty
*vty
,
2153 struct json_object
*json
, bool verbose
)
2156 ls_show_vertex_json(vertex
, json
);
2158 ls_show_vertex_vty(vertex
, vty
, verbose
);
2161 void ls_show_vertices(struct ls_ted
*ted
, struct vty
*vty
,
2162 struct json_object
*json
, bool verbose
)
2164 struct ls_vertex
*vertex
;
2165 json_object
*jnodes
, *jnode
;
2168 jnodes
= json_object_new_array();
2169 json_object_object_add(json
, "vertices", jnodes
);
2170 frr_each (vertices
, &ted
->vertices
, vertex
) {
2171 jnode
= json_object_new_object();
2172 ls_show_vertex(vertex
, NULL
, jnode
, verbose
);
2173 json_object_array_add(jnodes
, jnode
);
2176 frr_each (vertices
, &ted
->vertices
, vertex
)
2177 ls_show_vertex(vertex
, vty
, NULL
, verbose
);
2181 static void ls_show_edge_vty(struct ls_edge
*edge
, struct vty
*vty
,
2184 char admin_group_buf
[ADMIN_GROUP_PRINT_MAX_SIZE
];
2185 struct ls_attributes
*attr
;
2187 char buf
[INET6_BUFSIZ
];
2190 attr
= edge
->attributes
;
2191 sbuf_init(&sbuf
, NULL
, 0);
2193 sbuf_push(&sbuf
, 2, "Edge (%" PRIu64
"): ", edge
->key
);
2194 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2195 sbuf_push(&sbuf
, 0, "%pI4", &attr
->standard
.local
);
2196 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2197 sbuf_push(&sbuf
, 0, "%pI6", &attr
->standard
.local6
);
2199 sbuf_push(&sbuf
, 0, "%u/%u", attr
->standard
.local_id
,
2200 attr
->standard
.remote_id
);
2201 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2202 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2203 sbuf_push(&sbuf
, 0, "\tMetric: %u", attr
->metric
);
2204 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[edge
->status
]);
2209 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[attr
->adv
.origin
]);
2210 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2211 sbuf_push(&sbuf
, 4, "Name: %s\n", attr
->name
);
2212 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2213 sbuf_push(&sbuf
, 4, "TE Metric: %u\n",
2214 attr
->standard
.te_metric
);
2215 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2216 sbuf_push(&sbuf
, 4, "Admin Group: 0x%x\n",
2217 attr
->standard
.admin_group
);
2218 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
) &&
2219 admin_group_nb_words(&attr
->ext_admin_group
) != 0) {
2221 sbuf_push(&sbuf
, indent
, "Ext Admin Group: %s\n",
2223 admin_group_buf
, ADMIN_GROUP_PRINT_MAX_SIZE
,
2224 indent
+ strlen("Ext Admin Group: "),
2225 &attr
->ext_admin_group
));
2226 if (admin_group_buf
[0] != '\0' &&
2227 (sbuf
.pos
+ strlen(admin_group_buf
) +
2228 SBUF_DEFAULT_SIZE
/ 2) < sbuf
.size
)
2229 sbuf_push(&sbuf
, indent
+ 2, "Bit positions: %s\n",
2232 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2233 sbuf_push(&sbuf
, 4, "Local IPv4 address: %pI4\n",
2234 &attr
->standard
.local
);
2235 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
2236 sbuf_push(&sbuf
, 4, "Remote IPv4 address: %pI4\n",
2237 &attr
->standard
.remote
);
2238 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2239 sbuf_push(&sbuf
, 4, "Local IPv6 address: %pI6\n",
2240 &attr
->standard
.local6
);
2241 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
2242 sbuf_push(&sbuf
, 4, "Remote IPv6 address: %pI6\n",
2243 &attr
->standard
.remote6
);
2244 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2245 sbuf_push(&sbuf
, 4, "Local Identifier: %u\n",
2246 attr
->standard
.local_id
);
2247 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2248 sbuf_push(&sbuf
, 4, "Remote Identifier: %u\n",
2249 attr
->standard
.remote_id
);
2250 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2251 sbuf_push(&sbuf
, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2252 attr
->standard
.max_bw
);
2253 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2255 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2256 attr
->standard
.max_rsv_bw
);
2257 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2258 sbuf_push(&sbuf
, 4, "Unreserved Bandwidth per Class Type\n");
2259 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2)
2261 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2262 i
, attr
->standard
.unrsv_bw
[i
], i
+ 1,
2263 attr
->standard
.unrsv_bw
[i
+ 1]);
2265 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2266 sbuf_push(&sbuf
, 4, "Remote AS: %u\n",
2267 attr
->standard
.remote_as
);
2268 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
2269 sbuf_push(&sbuf
, 4, "Remote ASBR IPv4 address: %pI4\n",
2270 &attr
->standard
.remote_addr
);
2271 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
2272 sbuf_push(&sbuf
, 4, "Remote ASBR IPv6 address: %pI6\n",
2273 &attr
->standard
.remote_addr6
);
2274 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2275 sbuf_push(&sbuf
, 4, "Average Link Delay: %d (micro-sec)\n",
2276 attr
->extended
.delay
);
2277 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
))
2278 sbuf_push(&sbuf
, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2279 attr
->extended
.min_delay
, attr
->extended
.max_delay
);
2280 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2281 sbuf_push(&sbuf
, 4, "Delay Variation: %d (micro-sec)\n",
2282 attr
->extended
.jitter
);
2283 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2284 sbuf_push(&sbuf
, 4, "Link Loss: %g (%%)\n",
2285 (float)(attr
->extended
.pkt_loss
* LOSS_PRECISION
));
2286 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2287 sbuf_push(&sbuf
, 4, "Available Bandwidth: %g (Bytes/s)\n",
2288 attr
->extended
.ava_bw
);
2289 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2290 sbuf_push(&sbuf
, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2291 attr
->extended
.rsv_bw
);
2292 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2293 sbuf_push(&sbuf
, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2294 attr
->extended
.used_bw
);
2295 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2296 sbuf_push(&sbuf
, 4, "IPv4 Adjacency-SID: %u",
2297 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2298 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2299 attr
->adj_sid
[ADJ_PRI_IPV4
].flags
,
2300 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2302 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2303 sbuf_push(&sbuf
, 4, "IPv4 Bck. Adjacency-SID: %u",
2304 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2305 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2306 attr
->adj_sid
[ADJ_BCK_IPV4
].flags
,
2307 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2309 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2310 sbuf_push(&sbuf
, 4, "IPv6 Adjacency-SID: %u",
2311 attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
2312 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2313 attr
->adj_sid
[ADJ_PRI_IPV6
].flags
,
2314 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2316 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2317 sbuf_push(&sbuf
, 4, "IPv6 Bck. Adjacency-SID: %u",
2318 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2319 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2320 attr
->adj_sid
[ADJ_BCK_IPV6
].flags
,
2321 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2323 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2324 sbuf_push(&sbuf
, 4, "SRLGs: %d", attr
->srlg_len
);
2325 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2327 sbuf_push(&sbuf
, 8, "\n%u", attr
->srlgs
[i
]);
2329 sbuf_push(&sbuf
, 8, ", %u", attr
->srlgs
[i
]);
2331 sbuf_push(&sbuf
, 0, "\n");
2335 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2339 static void ls_show_edge_json(struct ls_edge
*edge
, struct json_object
*json
)
2341 struct ls_attributes
*attr
;
2342 struct json_object
*jte
, *jbw
, *jobj
, *jsr
= NULL
, *jsrlg
, *js_ext_ag
,
2343 *js_ext_ag_arr_word
,
2345 char buf
[INET6_BUFSIZ
];
2346 char buf_ag
[strlen("0xffffffff") + 1];
2350 attr
= edge
->attributes
;
2352 json_object_int_add(json
, "edge-id", edge
->key
);
2353 json_object_string_add(json
, "status", status2txt
[edge
->status
]);
2354 json_object_string_add(json
, "origin", origin2txt
[attr
->adv
.origin
]);
2355 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2356 json_object_string_add(json
, "advertised-router", buf
);
2358 json_object_int_add(json
, "local-vertex-id", edge
->source
->key
);
2359 if (edge
->destination
)
2360 json_object_int_add(json
, "remote-vertex-id",
2361 edge
->destination
->key
);
2362 json_object_int_add(json
, "metric", attr
->metric
);
2363 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2364 json_object_string_add(json
, "name", attr
->name
);
2365 jte
= json_object_new_object();
2366 json_object_object_add(json
, "edge-attributes", jte
);
2367 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2368 json_object_int_add(jte
, "te-metric", attr
->standard
.te_metric
);
2369 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2370 json_object_int_add(jte
, "admin-group",
2371 attr
->standard
.admin_group
);
2372 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
2373 js_ext_ag
= json_object_new_object();
2374 json_object_object_add(jte
, "extAdminGroup", js_ext_ag
);
2375 js_ext_ag_arr_word
= json_object_new_array();
2376 json_object_object_add(js_ext_ag
, "words", js_ext_ag_arr_word
);
2377 js_ext_ag_arr_bit
= json_object_new_array();
2378 json_object_object_add(js_ext_ag
, "bitPositions",
2380 for (i
= 0; i
< admin_group_nb_words(&attr
->ext_admin_group
);
2382 bitmap
= admin_group_get_offset(&attr
->ext_admin_group
,
2384 snprintf(buf_ag
, sizeof(buf_ag
), "0x%08x", bitmap
);
2385 json_object_array_add(js_ext_ag_arr_word
,
2386 json_object_new_string(buf_ag
));
2389 i
< (admin_group_size(&attr
->ext_admin_group
) * WORD_SIZE
);
2391 if (admin_group_get(&attr
->ext_admin_group
, i
))
2392 json_object_array_add(js_ext_ag_arr_bit
,
2393 json_object_new_int(i
));
2396 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
2397 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.local
);
2398 json_object_string_add(jte
, "local-address", buf
);
2400 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
2401 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.remote
);
2402 json_object_string_add(jte
, "remote-address", buf
);
2404 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
2405 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.local6
);
2406 json_object_string_add(jte
, "local-address-v6", buf
);
2408 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
2409 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.remote6
);
2410 json_object_string_add(jte
, "remote-address-v6", buf
);
2412 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2413 json_object_int_add(jte
, "local-identifier",
2414 attr
->standard
.local_id
);
2415 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2416 json_object_int_add(jte
, "remote-identifier",
2417 attr
->standard
.remote_id
);
2418 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2419 json_object_double_add(jte
, "max-link-bandwidth",
2420 attr
->standard
.max_bw
);
2421 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2422 json_object_double_add(jte
, "max-resv-link-bandwidth",
2423 attr
->standard
.max_rsv_bw
);
2424 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2425 jbw
= json_object_new_array();
2426 json_object_object_add(jte
, "unreserved-bandwidth", jbw
);
2427 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
++) {
2428 jobj
= json_object_new_object();
2429 snprintfrr(buf
, 13, "class-type-%u", i
);
2430 json_object_double_add(jobj
, buf
,
2431 attr
->standard
.unrsv_bw
[i
]);
2432 json_object_array_add(jbw
, jobj
);
2435 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2436 json_object_int_add(jte
, "remote-asn",
2437 attr
->standard
.remote_as
);
2438 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
)) {
2439 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4",
2440 &attr
->standard
.remote_addr
);
2441 json_object_string_add(jte
, "remote-as-address", buf
);
2443 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
)) {
2444 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6",
2445 &attr
->standard
.remote_addr6
);
2446 json_object_string_add(jte
, "remote-as-address-v6", buf
);
2448 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2449 json_object_int_add(jte
, "delay", attr
->extended
.delay
);
2450 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
2451 json_object_int_add(jte
, "min-delay", attr
->extended
.min_delay
);
2452 json_object_int_add(jte
, "max-delay", attr
->extended
.max_delay
);
2454 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2455 json_object_int_add(jte
, "jitter", attr
->extended
.jitter
);
2456 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2457 json_object_double_add(
2458 jte
, "loss", attr
->extended
.pkt_loss
* LOSS_PRECISION
);
2459 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2460 json_object_double_add(jte
, "available-bandwidth",
2461 attr
->extended
.ava_bw
);
2462 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2463 json_object_double_add(jte
, "residual-bandwidth",
2464 attr
->extended
.rsv_bw
);
2465 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2466 json_object_double_add(jte
, "utilized-bandwidth",
2467 attr
->extended
.used_bw
);
2468 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2469 jsrlg
= json_object_new_array();
2470 json_object_object_add(jte
, "srlgs", jsrlg
);
2471 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2472 jobj
= json_object_new_object();
2473 json_object_int_add(jobj
, "srlg", attr
->srlgs
[i
]);
2474 json_object_array_add(jsrlg
, jobj
);
2477 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2478 jsr
= json_object_new_array();
2479 json_object_object_add(json
, "segment-routing", jsr
);
2480 jobj
= json_object_new_object();
2481 json_object_int_add(jobj
, "adj-sid",
2482 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2483 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
2484 json_object_string_add(jobj
, "flags", buf
);
2485 json_object_int_add(jobj
, "weight",
2486 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2487 json_object_array_add(jsr
, jobj
);
2489 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2491 jsr
= json_object_new_array();
2492 json_object_object_add(json
, "segment-routing", jsr
);
2494 jobj
= json_object_new_object();
2495 json_object_int_add(jobj
, "adj-sid",
2496 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2497 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
2498 json_object_string_add(jobj
, "flags", buf
);
2499 json_object_int_add(jobj
, "weight",
2500 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2501 json_object_array_add(jsr
, jobj
);
2503 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2504 jsr
= json_object_new_array();
2505 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_PRI_IPV6
].sid
);
2509 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
2510 json_object_string_add(jobj
, "flags", buf
);
2511 json_object_int_add(jobj
, "weight",
2512 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2513 json_object_array_add(jsr
, jobj
);
2515 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2517 jsr
= json_object_new_array();
2518 json_object_object_add(json
, "segment-routing", jsr
);
2520 jobj
= json_object_new_object();
2521 json_object_int_add(jobj
, "adj-sid",
2522 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2523 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
2524 json_object_string_add(jobj
, "flags", buf
);
2525 json_object_int_add(jobj
, "weight",
2526 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2527 json_object_array_add(jsr
, jobj
);
2531 void ls_show_edge(struct ls_edge
*edge
, struct vty
*vty
,
2532 struct json_object
*json
, bool verbose
)
2539 ls_show_edge_json(edge
, json
);
2541 ls_show_edge_vty(edge
, vty
, verbose
);
2544 void ls_show_edges(struct ls_ted
*ted
, struct vty
*vty
,
2545 struct json_object
*json
, bool verbose
)
2547 struct ls_edge
*edge
;
2548 json_object
*jedges
, *jedge
;
2551 jedges
= json_object_new_array();
2552 json_object_object_add(json
, "edges", jedges
);
2553 frr_each (edges
, &ted
->edges
, edge
) {
2554 jedge
= json_object_new_object();
2555 ls_show_edge(edge
, NULL
, jedge
, verbose
);
2556 json_object_array_add(jedges
, jedge
);
2559 frr_each (edges
, &ted
->edges
, edge
)
2560 ls_show_edge(edge
, vty
, NULL
, verbose
);
2564 static void ls_show_subnet_vty(struct ls_subnet
*subnet
, struct vty
*vty
,
2567 struct ls_prefix
*pref
;
2569 char buf
[INET6_BUFSIZ
];
2571 pref
= subnet
->ls_pref
;
2572 sbuf_init(&sbuf
, NULL
, 0);
2574 sbuf_push(&sbuf
, 2, "Subnet: %pFX", &subnet
->key
);
2575 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2576 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2577 sbuf_push(&sbuf
, 0, "\tMetric: %d", pref
->metric
);
2578 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[subnet
->status
]);
2583 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[pref
->adv
.origin
]);
2584 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
))
2585 sbuf_push(&sbuf
, 4, "Flags: %d\n", pref
->igp_flag
);
2587 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2588 sbuf_push(&sbuf
, 4, "Tag: %d\n", pref
->route_tag
);
2590 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2591 sbuf_push(&sbuf
, 4, "Extended Tag: %" PRIu64
"\n",
2592 pref
->extended_tag
);
2594 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
))
2595 sbuf_push(&sbuf
, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2596 pref
->sr
.sid
, pref
->sr
.algo
, pref
->sr
.sid_flag
);
2599 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2603 static void ls_show_subnet_json(struct ls_subnet
*subnet
,
2604 struct json_object
*json
)
2606 struct ls_prefix
*pref
;
2608 char buf
[INET6_BUFSIZ
];
2610 pref
= subnet
->ls_pref
;
2612 snprintfrr(buf
, INET6_BUFSIZ
, "%pFX", &subnet
->key
);
2613 json_object_string_add(json
, "subnet-id", buf
);
2614 json_object_string_add(json
, "status", status2txt
[subnet
->status
]);
2615 json_object_string_add(json
, "origin", origin2txt
[pref
->adv
.origin
]);
2616 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2617 json_object_string_add(json
, "advertised-router", buf
);
2619 json_object_int_add(json
, "vertex-id", subnet
->vertex
->key
);
2620 json_object_int_add(json
, "metric", pref
->metric
);
2621 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
)) {
2622 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->igp_flag
);
2623 json_object_string_add(json
, "flags", buf
);
2625 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2626 json_object_int_add(json
, "tag", pref
->route_tag
);
2627 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2628 json_object_int_add(json
, "extended-tag", pref
->extended_tag
);
2629 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
)) {
2630 jsr
= json_object_new_object();
2631 json_object_object_add(json
, "segment-routing", jsr
);
2632 json_object_int_add(jsr
, "pref-sid", pref
->sr
.sid
);
2633 json_object_int_add(jsr
, "algo", pref
->sr
.algo
);
2634 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->sr
.sid_flag
);
2635 json_object_string_add(jsr
, "flags", buf
);
2639 void ls_show_subnet(struct ls_subnet
*subnet
, struct vty
*vty
,
2640 struct json_object
*json
, bool verbose
)
2647 ls_show_subnet_json(subnet
, json
);
2649 ls_show_subnet_vty(subnet
, vty
, verbose
);
2652 void ls_show_subnets(struct ls_ted
*ted
, struct vty
*vty
,
2653 struct json_object
*json
, bool verbose
)
2655 struct ls_subnet
*subnet
;
2656 json_object
*jsubs
, *jsub
;
2659 jsubs
= json_object_new_array();
2660 json_object_object_add(json
, "subnets", jsubs
);
2661 frr_each (subnets
, &ted
->subnets
, subnet
) {
2662 jsub
= json_object_new_object();
2663 ls_show_subnet(subnet
, NULL
, jsub
, verbose
);
2664 json_object_array_add(jsubs
, jsub
);
2667 frr_each (subnets
, &ted
->subnets
, subnet
)
2668 ls_show_subnet(subnet
, vty
, NULL
, verbose
);
2672 void ls_show_ted(struct ls_ted
*ted
, struct vty
*vty
, struct json_object
*json
,
2678 jted
= json_object_new_object();
2679 json_object_object_add(json
, "ted", jted
);
2680 json_object_string_add(jted
, "name", ted
->name
);
2681 json_object_int_add(jted
, "key", ted
->key
);
2682 json_object_int_add(jted
, "verticesCount",
2683 vertices_count(&ted
->vertices
));
2684 json_object_int_add(jted
, "edgesCount",
2685 edges_count(&ted
->edges
));
2686 json_object_int_add(jted
, "subnetsCount",
2687 subnets_count(&ted
->subnets
));
2688 ls_show_vertices(ted
, NULL
, jted
, verbose
);
2689 ls_show_edges(ted
, NULL
, jted
, verbose
);
2690 ls_show_subnets(ted
, NULL
, jted
, verbose
);
2696 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2697 ted
->name
, ted
->key
);
2698 ls_show_vertices(ted
, vty
, NULL
, verbose
);
2699 ls_show_edges(ted
, vty
, NULL
, verbose
);
2700 ls_show_subnets(ted
, vty
, NULL
, verbose
);
2702 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2703 vertices_count(&ted
->vertices
),
2704 edges_count(&ted
->edges
), subnets_count(&ted
->subnets
));
2708 void ls_dump_ted(struct ls_ted
*ted
)
2710 struct ls_vertex
*vertex
;
2711 struct ls_edge
*edge
;
2712 struct ls_subnet
*subnet
;
2713 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
2715 zlog_debug("(%s) Ted init", __func__
);
2717 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2718 frr_each (vertices
, &ted
->vertices
, vertex
) {
2719 zlog_debug(" Ted node (%s %pI4 %s)",
2720 vertex
->node
->name
[0] ? vertex
->node
->name
2722 &vertex
->node
->router_id
,
2723 origin2txt
[vertex
->node
->adv
.origin
]);
2724 struct listnode
*lst_node
;
2725 struct ls_edge
*vertex_edge
;
2727 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
2730 " inc edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2732 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2733 &vertex_edge
->attributes
->standard
.local
,
2734 &vertex_edge
->attributes
->standard
.remote
);
2736 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
2739 " out edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2741 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2742 &vertex_edge
->attributes
->standard
.local
,
2743 &vertex_edge
->attributes
->standard
.remote
);
2746 frr_each (edges
, &ted
->edges
, edge
) {
2747 zlog_debug(" Ted edge key:%" PRIu64
"src:%pI4 dst:%pI4", edge
->key
,
2748 edge
->source
? &edge
->source
->node
->router_id
2751 ? &edge
->destination
->node
->router_id
2754 frr_each (subnets
, &ted
->subnets
, subnet
) {
2755 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2756 &subnet
->ls_pref
->pref
,
2757 &subnet
->vertex
->node
->adv
.id
.ip
.addr
);
2759 zlog_debug("(%s) Ted end", __func__
);